r179154 - Add support for computing the exception specification for an inheriting

Richard Smith richard-llvm at metafoo.co.uk
Tue Apr 9 23:11:48 PDT 2013


Author: rsmith
Date: Wed Apr 10 01:11:48 2013
New Revision: 179154

URL: http://llvm.org/viewvc/llvm-project?rev=179154&view=rev
Log:
Add support for computing the exception specification for an inheriting
constructor. This isn't quite perfect (as usual, we don't handle default
arguments correctly yet, and we don't deal with copy/move constructors for
arguments correctly either, but this will be fixed when we implement core issue
1351.

This completes our support for inheriting constructors.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/except/except.spec/p14.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=179154&r1=179153&r2=179154&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 10 01:11:48 2013
@@ -3542,7 +3542,7 @@ public:
     const QualType *data() const { return Exceptions.data(); }
 
     /// \brief Integrate another called method into the collected data.
-    void CalledDecl(SourceLocation CallLoc, CXXMethodDecl *Method);
+    void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
 
     /// \brief Integrate an invoked expression into the collected data.
     void CalledExpr(Expr *E);
@@ -3606,7 +3606,7 @@ public:
   /// \brief Determine what sort of exception specification an inheriting
   /// constructor of a class will have.
   ImplicitExceptionSpecification
-  ComputeInheritingCtorExceptionSpec(CXXMethodDecl *MD);
+  ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD);
 
   /// \brief Evaluate the implicit exception specification for a defaulted
   /// special member function.

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=179154&r1=179153&r2=179154&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr 10 01:11:48 2013
@@ -145,8 +145,9 @@ namespace {
   }
 }
 
-void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
-                                                      CXXMethodDecl *Method) {
+void
+Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
+                                                 const CXXMethodDecl *Method) {
   // If we have an MSAny spec already, don't bother.
   if (!Method || ComputedEST == EST_MSAny)
     return;
@@ -7522,9 +7523,73 @@ Sema::ComputeDefaultedDefaultCtorExcepti
 }
 
 Sema::ImplicitExceptionSpecification
-Sema::ComputeInheritingCtorExceptionSpec(CXXMethodDecl *MD) {
+Sema::ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD) {
+  CXXRecordDecl *ClassDecl = CD->getParent();
+
+  // C++ [except.spec]p14:
+  //   An inheriting constructor [...] shall have an exception-specification. [...]
   ImplicitExceptionSpecification ExceptSpec(*this);
-  // FIXME: Compute the exception spec.
+  if (ClassDecl->isInvalidDecl())
+    return ExceptSpec;
+
+  // Inherited constructor.
+  const CXXConstructorDecl *InheritedCD = CD->getInheritedConstructor();
+  const CXXRecordDecl *InheritedDecl = InheritedCD->getParent();
+  // FIXME: Copying or moving the parameters could add extra exceptions to the
+  // set, as could the default arguments for the inherited constructor. This
+  // will be addressed when we implement the resolution of core issue 1351.
+  ExceptSpec.CalledDecl(CD->getLocStart(), InheritedCD);
+
+  // Direct base-class constructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+                                       BEnd = ClassDecl->bases_end();
+       B != BEnd; ++B) {
+    if (B->isVirtual()) // Handled below.
+      continue;
+
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (BaseClassDecl == InheritedDecl)
+        continue;
+      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
+      if (Constructor)
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+    }
+  }
+
+  // Virtual base-class constructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+                                       BEnd = ClassDecl->vbases_end();
+       B != BEnd; ++B) {
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (BaseClassDecl == InheritedDecl)
+        continue;
+      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
+      if (Constructor)
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+    }
+  }
+
+  // Field constructors.
+  for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+                               FEnd = ClassDecl->field_end();
+       F != FEnd; ++F) {
+    if (F->hasInClassInitializer()) {
+      if (Expr *E = F->getInClassInitializer())
+        ExceptSpec.CalledExpr(E);
+      else if (!F->isInvalidDecl())
+        Diag(CD->getLocation(),
+             diag::err_in_class_initializer_references_def_ctor) << CD;
+    } else if (const RecordType *RecordTy
+              = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+      CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
+      if (Constructor)
+        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
+    }
+  }
+
   return ExceptSpec;
 }
 

Modified: cfe/trunk/test/CXX/except/except.spec/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p14.cpp?rev=179154&r1=179153&r2=179154&view=diff
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p14.cpp (original)
+++ cfe/trunk/test/CXX/except/except.spec/p14.cpp Wed Apr 10 01:11:48 2013
@@ -112,3 +112,26 @@ namespace rdar13017229 {
     Typo foo(); // expected-error{{unknown type name 'Typo'}}
   };
 }
+
+namespace InhCtor {
+  template<int> struct X {};
+  struct Base {
+    Base(X<0>) noexcept(true);
+    Base(X<1>) noexcept(false);
+    Base(X<2>) throw(X<2>);
+    template<typename T> Base(T) throw(T);
+  };
+  template<typename T> struct Throw {
+    Throw() throw(T);
+  };
+  struct Derived : Base, Throw<X<3>> {
+    using Base::Base;
+    Throw<X<4>> x;
+  };
+  struct Test {
+    friend Derived::Derived(X<0>) throw(X<3>, X<4>);
+    friend Derived::Derived(X<1>) noexcept(false);
+    friend Derived::Derived(X<2>) throw(X<2>, X<3>, X<4>);
+  };
+  static_assert(!noexcept(Derived{X<5>{}}), "");
+}

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=179154&r1=179153&r2=179154&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Wed Apr 10 01:11:48 2013
@@ -196,7 +196,7 @@ releases prior to version 3.2 in C++11 m
     <tr>
       <td>Inheriting constructors</td>
       <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm">N2540</a></td>
-      <td class="none" align="center">No</td>
+      <td class="svn" align="center">SVN</td>
     </tr>
     <tr>
       <td>Explicit conversion operators</td>





More information about the cfe-commits mailing list