diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-11-28 22:52:42 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-11-28 22:52:42 +0000 |
commit | a70c3f8738cc123ded68c183cedd6e93df670c2f (patch) | |
tree | 674b48f01151ea3e22fd62ada9a564529e86a140 | |
parent | 21173b1080abaa2738f9e700a9d4b0d04f928930 (diff) |
Per C++11 [except.spec]p2, rvalue references are not permitted in exception specifications.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168824 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 67 | ||||
-rw-r--r-- | test/SemaCXX/exceptions.cpp | 2 |
3 files changed, 38 insertions, 33 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 8d172ca581..b31fb6b9b7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -892,6 +892,8 @@ def err_distant_exception_spec : Error< def err_incomplete_in_exception_spec : Error< "%select{|pointer to |reference to }0incomplete type %1 is not allowed " "in exception specification">; +def err_rref_in_exception_spec : Error< + "rvalue reference type %0 is not allowed in exception specification">; def err_mismatched_exception_spec : Error< "exception specification in declaration does not match previous declaration">; def warn_mismatched_exception_spec : ExtWarn< diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 8cb2cb4290..e72ebf86d4 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -42,50 +42,51 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T) /// \param[in,out] T The exception type. This will be decayed to a pointer type /// when the input is an array or a function type. bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) { - // This check (and the similar one below) deals with issue 437, that changes - // C++ 9.2p2 this way: - // Within the class member-specification, the class is regarded as complete - // within function bodies, default arguments, exception-specifications, and - // constructor ctor-initializers (including such things in nested classes). - if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) - return false; - - // C++ 15.4p2: A type cv T, "array of T", or "function returning T" denoted + // C++11 [except.spec]p2: + // A type cv T, "array of T", or "function returning T" denoted // in an exception-specification is adjusted to type T, "pointer to T", or // "pointer to function returning T", respectively. - // C++ 15.4p2: A type denoted in an exception-specification shall not denote - // an incomplete type. + // + // We also apply this rule in C++98. if (T->isArrayType()) T = Context.getArrayDecayedType(T); else if (T->isFunctionType()) T = Context.getPointerType(T); - else if (RequireCompleteType(Range.getBegin(), T, - diag::err_incomplete_in_exception_spec, - /*direct*/0, Range)) - return true; - - // C++ 15.4p2: A type denoted in an exception-specification shall not denote - // an incomplete type a pointer or reference to an incomplete type, other - // than (cv) void*. - int kind; + int Kind = 0; QualType PointeeT = T; - if (const PointerType* IT = T->getAs<PointerType>()) { - PointeeT = IT->getPointeeType(); - kind = 1; - } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) { - PointeeT = IT->getPointeeType(); - kind = 2; - } else - return false; + if (const PointerType *PT = T->getAs<PointerType>()) { + PointeeT = PT->getPointeeType(); + Kind = 1; - // Again as before - if (PointeeT->isRecordType() && PointeeT->getAs<RecordType>()->isBeingDefined()) - return false; + // cv void* is explicitly permitted, despite being a pointer to an + // incomplete type. + if (PointeeT->isVoidType()) + return false; + } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { + PointeeT = RT->getPointeeType(); + Kind = 2; + + if (RT->isRValueReferenceType()) { + // C++11 [except.spec]p2: + // A type denoted in an exception-specification shall not denote [...] + // an rvalue reference type. + Diag(Range.getBegin(), diag::err_rref_in_exception_spec) + << T << Range; + return true; + } + } - if (!PointeeT->isVoidType() && + // C++11 [except.spec]p2: + // A type denoted in an exception-specification shall not denote an + // incomplete type other than a class currently being defined [...]. + // A type denoted in an exception-specification shall not denote a + // pointer or reference to an incomplete type, other than (cv) void* or a + // pointer or reference to a class currently being defined. + if (!(PointeeT->isRecordType() && + PointeeT->getAs<RecordType>()->isBeingDefined()) && RequireCompleteType(Range.getBegin(), PointeeT, - diag::err_incomplete_in_exception_spec, kind, Range)) + diag::err_incomplete_in_exception_spec, Kind, Range)) return true; return false; diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp index 8e32494825..c2ca9f952b 100644 --- a/test/SemaCXX/exceptions.cpp +++ b/test/SemaCXX/exceptions.cpp @@ -143,3 +143,5 @@ namespace Decay { struct E; // expected-note {{forward declaration}} C<E[10]> e; // expected-note {{in instantiation of}} } + +void rval_ref() throw (int &&); // expected-error {{rvalue reference type 'int &&' is not allowed in exception specification}} expected-warning {{C++11}} |