diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 58 |
4 files changed, 64 insertions, 2 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 84f00dbaa2..932cb18a93 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6853,7 +6853,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleNoCfCheckAttr(S, D, AL); break; case ParsedAttr::AT_NoThrow: - handleSimpleAttribute<NoThrowAttr>(S, D, AL); + if (!AL.isUsedAsTypeAttr()) + handleSimpleAttribute<NoThrowAttr>(S, D, AL); break; case ParsedAttr::AT_CUDAShared: handleSharedAttr(S, D, AL); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b3920ff01b..35863a3266 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -192,6 +192,7 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, // If this function has a basic noexcept, it doesn't affect the outcome. case EST_BasicNoexcept: case EST_NoexceptTrue: + case EST_NoThrow: return; // If we're still at noexcept(true) and there's a throw() callee, // change to that specification. @@ -15457,6 +15458,7 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { case EST_Uninstantiated: case EST_Unevaluated: case EST_BasicNoexcept: + case EST_NoThrow: case EST_DynamicNone: case EST_MSAny: case EST_None: diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 00b158debc..6e67968929 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -6045,6 +6045,8 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1, if (EST2 == EST_NoexceptFalse) return ESI2; // If either of them is non-throwing, the result is the other. + if (EST1 == EST_NoThrow) return ESI2; + if (EST2 == EST_NoThrow) return ESI1; if (EST1 == EST_DynamicNone) return ESI2; if (EST2 == EST_DynamicNone) return ESI1; if (EST1 == EST_BasicNoexcept) return ESI2; @@ -6073,6 +6075,7 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1, case EST_DependentNoexcept: case EST_NoexceptFalse: case EST_NoexceptTrue: + case EST_NoThrow: llvm_unreachable("handled above"); case EST_Dynamic: { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 91743bb59f..e0d43a780e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -130,6 +130,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_Regparm: \ case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: \ case ParsedAttr::AT_AnyX86NoCfCheck: \ + case ParsedAttr::AT_NoThrow: \ CALLING_CONV_ATTRS_CASELIST // Microsoft-specific type qualifiers. @@ -4516,7 +4517,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If the function declarator has a prototype (i.e. it is not () and // does not have a K&R-style identifier list), then the arguments are part // of the type, otherwise the argument list is (). - const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; IsQualifiedFunction = FTI.hasMethodTypeQualifiers() || FTI.hasRefQualifier(); @@ -6945,6 +6946,61 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, return true; } + if (attr.getKind() == ParsedAttr::AT_NoThrow) { + if (S.CheckAttrNoArgs(attr)) + return true; + + // Delay if this is not a function type. + if (!unwrapped.isFunctionType()) + return false; + + // Otherwise we can process right away. + auto *Proto = unwrapped.get()->getAs<FunctionProtoType>(); + + // In the case where this is a FunctionNoProtoType instead of a + // FunctionProtoType, let the existing NoThrowAttr implementation do its + // thing. + if (!Proto) + return false; + + attr.setUsedAsTypeAttr(); + + // MSVC ignores nothrow if it is in conflict with an explicit exception + // specification. + if (Proto->hasExceptionSpec()) { + switch (Proto->getExceptionSpecType()) { + case EST_None: + llvm_unreachable("This doesn't have an exception spec!"); + LLVM_FALLTHROUGH; + case EST_DynamicNone: + case EST_BasicNoexcept: + case EST_NoexceptTrue: + case EST_NoThrow: + // Exception spec doesn't conflict with nothrow, so don't warn. + break; + + case EST_Dynamic: + case EST_MSAny: + case EST_NoexceptFalse: + case EST_DependentNoexcept: + case EST_Unevaluated: + case EST_Uninstantiated: + case EST_Unparsed: + S.Diag(attr.getLoc(), diag::warn_nothrow_attribute_ignored); + break; + } + return true; + } + + type = unwrapped.wrap( + S, S.Context + .getFunctionTypeWithExceptionSpec( + QualType{Proto, 0}, + FunctionProtoType::ExceptionSpecInfo{EST_NoThrow}) + ->getAs<FunctionType>()); + return true; + } + // Delay if the type didn't work out to a function. if (!unwrapped.isFunctionType()) return false; |