]> granicus.if.org Git - clang/commitdiff
Per C++11 [except.spec]p2, rvalue references are not permitted in exception specifica...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 28 Nov 2012 22:52:42 +0000 (22:52 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 28 Nov 2012 22:52:42 +0000 (22:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168824 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExceptionSpec.cpp
test/SemaCXX/exceptions.cpp

index 8d172ca58172e75290cd54d72c534e7e3a61ed52..b31fb6b9b78ef9d6253c2b31aaef2be4bcd2854b 100644 (file)
@@ -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<
index 8cb2cb4290e7252eb2606b9b961c0ee01f691350..e72ebf86d49da8fc5ff71afa6c7055aa4dc79324 100644 (file)
@@ -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;
index 8e32494825e3e10716fe353870d7ca969c40371d..c2ca9f952b229723f1f97fa89ea38cb794629500 100644 (file)
@@ -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}}