[cfe-commits] r131528 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/special/class.dtor/p3-0x.cpp test/CodeGenCXX/cxx0x-delegating-ctors.cpp test/CodeGenCXX/eh.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Tue May 17 22:20:57 PDT 2011


Author: cornedbee
Date: Wed May 18 00:20:56 2011
New Revision: 131528

URL: http://llvm.org/viewvc/llvm-project?rev=131528&view=rev
Log:
Implement implicit exception specifications of destructors.

Added:
    cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
    cfe/trunk/test/CodeGenCXX/eh.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=131528&r1=131527&r2=131528&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed May 18 00:20:56 2011
@@ -2644,6 +2644,13 @@
   void DefineImplicitDestructor(SourceLocation CurrentLocation,
                                 CXXDestructorDecl *Destructor);
 
+  /// \brief Build an exception spec for destructors that don't have one.
+  ///
+  /// C++11 says that user-defined destructors with no exception spec get one
+  /// that looks as if the destructor was implicitly declared.
+  void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
+                                     CXXDestructorDecl *Destructor);
+
   /// \brief Declare all inherited constructors for the given class.
   ///
   /// \param ClassDecl The class declaration into which the inherited

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=131528&r1=131527&r2=131528&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 18 00:20:56 2011
@@ -4143,14 +4143,25 @@
       // This is a C++ destructor declaration.
       if (DC->isRecord()) {
         R = CheckDestructorDeclarator(D, R, SC);
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
 
-        NewFD = CXXDestructorDecl::Create(Context,
-                                          cast<CXXRecordDecl>(DC),
+        CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(Context, Record,
                                           D.getSourceRange().getBegin(),
                                           NameInfo, R, TInfo,
                                           isInline,
                                           /*isImplicitlyDeclared=*/false);
+        NewFD = NewDD;
         isVirtualOkay = true;
+
+        // If the class is complete, then we now create the implicit exception
+        // specification. If the class is incomplete or dependent, we can't do
+        // it yet.
+        if (getLangOptions().CPlusPlus0x && !Record->isDependentType() &&
+            Record->getDefinition() && !Record->isBeingDefined() &&
+            R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
+          AdjustDestructorExceptionSpec(Record, NewDD);
+        }
+
       } else {
         Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
 
@@ -8128,6 +8139,11 @@
           Convs->setAccess(I, (*I)->getAccess());
         
         if (!CXXRecord->isDependentType()) {
+          // Adjust user-defined destructor exception spec.
+          if (getLangOptions().CPlusPlus0x &&
+              CXXRecord->hasUserDeclaredDestructor())
+            AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor());
+
           // Add any implicitly-declared members to this class.
           AddImplicitlyDeclaredMembersToClass(CXXRecord);
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=131528&r1=131527&r2=131528&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May 18 00:20:56 2011
@@ -6222,18 +6222,18 @@
     
     if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
       ExceptSpec.CalledDecl(
-                    LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+                   LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
   }
-  
+
   // Virtual base-class destructors.
   for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
                                        BEnd = ClassDecl->vbases_end();
        B != BEnd; ++B) {
     if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
       ExceptSpec.CalledDecl(
-                    LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+                  LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
   }
-  
+
   // Field destructors.
   for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
                                FEnd = ClassDecl->field_end();
@@ -6241,7 +6241,7 @@
     if (const RecordType *RecordTy
         = Context.getBaseElementType(F->getType())->getAs<RecordType>())
       ExceptSpec.CalledDecl(
-                    LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
+                  LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
   }
 
   return ExceptSpec;
@@ -6254,7 +6254,7 @@
   //   inline public member of its class.
   
   ImplicitExceptionSpecification Spec =
-   ComputeDefaultedDtorExceptionSpec(ClassDecl); 
+      ComputeDefaultedDtorExceptionSpec(ClassDecl); 
   FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
 
   // Create the actual destructor declaration.
@@ -6329,6 +6329,35 @@
   }
 }
 
+void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl,
+                                         CXXDestructorDecl *destructor) {
+  // C++11 [class.dtor]p3:
+  //   A declaration of a destructor that does not have an exception-
+  //   specification is implicitly considered to have the same exception-
+  //   specification as an implicit declaration.
+  const FunctionProtoType *dtorType = destructor->getType()->
+                                        getAs<FunctionProtoType>();
+  if (dtorType->hasExceptionSpec())
+    return;
+
+  ImplicitExceptionSpecification exceptSpec =
+      ComputeDefaultedDtorExceptionSpec(classDecl);
+
+  // Replace the destructor's type.
+  FunctionProtoType::ExtProtoInfo epi;
+  epi.ExceptionSpecType = exceptSpec.getExceptionSpecType();
+  epi.NumExceptions = exceptSpec.size();
+  epi.Exceptions = exceptSpec.data();
+  QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi);
+
+  destructor->setType(ty);
+
+  // FIXME: If the destructor has a body that could throw, and the newly created
+  // spec doesn't allow exceptions, we should emit a warning, because this
+  // change in behavior can break conforming C++03 programs at runtime.
+  // However, we don't have a body yet, so it needs to be done somewhere else.
+}
+
 /// \brief Builds a statement that copies the given entity from \p From to
 /// \c To.
 ///

Added: cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp?rev=131528&view=auto
==============================================================================
--- cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp (added)
+++ cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp Wed May 18 00:20:56 2011
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -std=c++0x -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s
+
+struct A {
+  ~A();
+};
+
+struct B {
+  ~B() throw(int);
+};
+
+struct C {
+  B b;
+  ~C() {}
+};
+
+struct D {
+  ~D() noexcept(false);
+};
+
+struct E {
+  D d;
+  ~E() {}
+};
+
+void foo() {
+  A a;
+  C c;
+  E e;
+  // CHECK: invoke void @_ZN1ED1Ev
+  // CHECK: invoke void @_ZN1CD1Ev
+  // CHECK: call void @_ZN1AD1Ev
+}
+
+struct F {
+  D d;
+  ~F();
+};
+F::~F() noexcept(false) {}
+
+struct G {
+  D d;
+  ~G();
+};
+G::~G() {}
+
+struct H {
+  B b;
+  ~H();
+};
+H::~H() throw(int) {}
+
+struct I {
+  B b;
+  ~I();
+};
+I::~I() {}
+
+// Template variants.
+
+template <typename T>
+struct TA {
+  ~TA();
+};
+
+template <typename T>
+struct TB {
+  ~TB() throw(int);
+};
+
+template <typename T>
+struct TC {
+  TB<T> b;
+  ~TC() {}
+};
+
+template <typename T>
+struct TD {
+  ~TD() noexcept(false);
+};
+
+template <typename T>
+struct TE {
+  TD<T> d;
+  ~TE() {}
+};
+
+void tfoo() {
+  TA<int> a;
+  TC<int> c;
+  TE<int> e;
+  // CHECK: invoke void @_ZN2TEIiED1Ev
+  // CHECK: invoke void @_ZN2TCIiED1Ev
+  // CHECK: call void @_ZN2TAIiED1Ev
+}
+
+template <typename T>
+struct TF {
+  TD<T> d;
+  ~TF();
+};
+template <typename T>
+TF<T>::~TF() noexcept(false) {}
+
+template <typename T>
+struct TG {
+  TD<T> d;
+  ~TG();
+};
+template <typename T>
+TG<T>::~TG() {}
+
+template <typename T>
+struct TH {
+  TB<T> b;
+  ~TH();
+};
+template <typename T>
+TH<T>::~TH() {}
+
+void tinst() {
+  TF<int> f;
+  TG<int> g;
+  TH<int> h;
+}
+// CHECK: define linkonce_odr void @_ZN2THIiED1Ev
+// CHECK: _ZTIi
+// CHECK: __cxa_call_unexpected

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp?rev=131528&r1=131527&r2=131528&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp Wed May 18 00:20:56 2011
@@ -2,10 +2,10 @@
 
 struct non_trivial {
   non_trivial();
-  ~non_trivial();
+  ~non_trivial() noexcept(false);
 };
 non_trivial::non_trivial() {}
-non_trivial::~non_trivial() {}
+non_trivial::~non_trivial() noexcept(false) {}
 
 // We use a virtual base to ensure that the constructor
 // delegation optimization (complete->base) can't be

Modified: cfe/trunk/test/CodeGenCXX/eh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/eh.cpp?rev=131528&r1=131527&r2=131528&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/eh.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/eh.cpp Wed May 18 00:20:56 2011
@@ -159,7 +159,7 @@
       // CHECK-NEXT: bitcast
       // CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_(
       // CHECK:      call i8* @__cxa_begin_catch
-      // CHECK-NEXT: invoke void @_ZN5test81AD1Ev(
+      // CHECK-NEXT: call void @_ZN5test81AD1Ev(
       // CHECK:      call void @__cxa_end_catch()
       // CHECK:      ret void
     }
@@ -272,7 +272,7 @@
 
 // PR7686
 namespace test12 {
-  struct A { ~A(); };
+  struct A { ~A() noexcept(false); };
   bool opaque(const A&);
 
   // CHECK: define void @_ZN6test124testEv()
@@ -392,8 +392,8 @@
 }
 
 namespace test16 {
-  struct A { A(); ~A(); };
-  struct B { int x; B(const A &); ~B(); };
+  struct A { A(); ~A() noexcept(false); };
+  struct B { int x; B(const A &); ~B() noexcept(false); };
   void foo();
   bool cond();
 





More information about the cfe-commits mailing list