From d61c1added2308a5e6b81b06831084bffa743e8e Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 3 Jun 2019 18:36:33 +0000 Subject: [PATCH] Make NoThrow FunctionLike, make FunctionLike include references, fix prettyprint __declspec(nothrow) should work on function pointers as well as function references, so this changes it to FunctionLike. Additionally, FunctionLike needed to be modified to permit function references. Finally, the TypePrinter didn't properly print the NoThrow exception specifier, so make sure we get that right as well. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@362435 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 8 ++++++++ include/clang/Basic/Attr.td | 2 +- lib/AST/DeclBase.cpp | 2 ++ lib/AST/TypePrinter.cpp | 2 ++ ...pragma-attribute-supported-attributes-list.test | 2 +- test/SemaCXX/nothrow-vs-exception-specs.cpp | 14 ++++++++++++++ 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 66c3de72f5..3f71a7ec6f 100644 --- a/include/clang/AST/Type.h +++ b/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()) + return T->getPointeeType()->isFunctionType(); + else + return false; +} + inline bool Type::isMemberPointerType() const { return isa(CanonicalType); } diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index ad179009ea..c20a56532d 100644 --- a/include/clang/Basic/Attr.td +++ b/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/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 511925d1b1..31985486d1 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -957,6 +957,8 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const { if (Ty->isFunctionPointerType()) Ty = Ty->getAs()->getPointeeType(); + else if (Ty->isFunctionReferenceType()) + Ty = Ty->getAs()->getPointeeType(); else if (BlocksToo && Ty->isBlockPointerType()) Ty = Ty->getAs()->getPointeeType(); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 13b105bc57..ca3e346668 100644 --- a/lib/AST/TypePrinter.cpp +++ b/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/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test index f85c89ae01..6e07e8e811 100644 --- a/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/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/test/SemaCXX/nothrow-vs-exception-specs.cpp b/test/SemaCXX/nothrow-vs-exception-specs.cpp index 7a00783b0b..a065dad772 100644 --- a/test/SemaCXX/nothrow-vs-exception-specs.cpp +++ b/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; +} -- 2.50.1