diff options
| -rw-r--r-- | clang/include/clang/AST/Type.h | 8 | ||||
| -rw-r--r-- | clang/include/clang/Basic/Attr.td | 2 | ||||
| -rw-r--r-- | clang/lib/AST/DeclBase.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 2 | ||||
| -rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 2 | ||||
| -rw-r--r-- | clang/test/SemaCXX/nothrow-vs-exception-specs.cpp | 14 |
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; +} |

