summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Type.h8
-rw-r--r--clang/include/clang/Basic/Attr.td2
-rw-r--r--clang/lib/AST/DeclBase.cpp2
-rw-r--r--clang/lib/AST/TypePrinter.cpp2
-rw-r--r--clang/test/Misc/pragma-attribute-supported-attributes-list.test2
-rw-r--r--clang/test/SemaCXX/nothrow-vs-exception-specs.cpp14
6 files changed, 28 insertions, 2 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 66c3de72f5f..3f71a7ec6ff 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1962,6 +1962,7 @@ public:
bool isLValueReferenceType() const;
bool isRValueReferenceType() const;
bool isFunctionPointerType() const;
+ bool isFunctionReferenceType() const;
bool isMemberPointerType() const;
bool isMemberFunctionPointerType() const;
bool isMemberDataPointerType() const;
@@ -6374,6 +6375,13 @@ inline bool Type::isFunctionPointerType() const {
return false;
}
+inline bool Type::isFunctionReferenceType() const {
+ if (const auto *T = getAs<ReferenceType>())
+ return T->getPointeeType()->isFunctionType();
+ else
+ return false;
+}
+
inline bool Type::isMemberPointerType() const {
return isa<MemberPointerType>(CanonicalType);
}
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index ad179009ea6..c20a56532d5 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1657,7 +1657,7 @@ def NoStackProtector : InheritableAttr {
def NoThrow : InheritableAttr {
let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
- let Subjects = SubjectList<[Function]>;
+ let Subjects = SubjectList<[FunctionLike]>;
let Documentation = [NoThrowDocs];
}
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 511925d1b14..31985486d1d 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -957,6 +957,8 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
if (Ty->isFunctionPointerType())
Ty = Ty->getAs<PointerType>()->getPointeeType();
+ else if (Ty->isFunctionReferenceType())
+ Ty = Ty->getAs<ReferenceType>()->getPointeeType();
else if (BlocksToo && Ty->isBlockPointerType())
Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 13b105bc572..ca3e3466684 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -734,6 +734,8 @@ FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
OS << getExceptionType(I).stream(Policy);
}
OS << ')';
+ } else if (EST_NoThrow == getExceptionSpecType()) {
+ OS << " __attribute__((nothrow))";
} else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
OS << " noexcept";
// FIXME:Is it useful to print out the expression for a non-dependent
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index f85c89ae015..6e07e8e8111 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -86,7 +86,7 @@
// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function)
// CHECK-NEXT: NoStackProtector (SubjectMatchRule_function)
// CHECK-NEXT: NoThreadSafetyAnalysis (SubjectMatchRule_function)
-// CHECK-NEXT: NoThrow (SubjectMatchRule_function)
+// CHECK-NEXT: NoThrow (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: NotTailCalled (SubjectMatchRule_function)
// CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter)
diff --git a/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp b/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp
index 7a00783b0b7..a065dad7724 100644
--- a/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp
+++ b/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp
@@ -88,3 +88,17 @@ public:
void foo() {}
};
}
+
+namespace FuncPointerReferenceConverts
+void FuncToBeRefed();
+
+#ifndef CPP17
+// expected-error@+6{{target exception specification is not superset of source}}
+// expected-error@+6{{target exception specification is not superset of source}}
+#else
+// expected-error@+3{{non-const lvalue reference to type 'void () __attribute__((nothrow))' cannot bind to a value of unrelated type 'void ()'}}
+// expected-error@+3{{cannot initialize a variable of type 'void (*)() __attribute__((nothrow))' with an lvalue of type 'void ()': different exception specifications}}
+#endif
+__declspec(nothrow) void (&FuncRef)() = FuncToBeRefed;
+__declspec(nothrow) void (*FuncPtr)() = FuncToBeRefed;
+}
OpenPOWER on IntegriCloud