summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaExprCXX.cpp3
-rw-r--r--lib/Sema/SemaType.cpp58
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;