[cfe-commits] r79269 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/default-destructor-synthesis.cpp

Fariborz Jahanian fjahanian at apple.com
Mon Aug 17 12:04:51 PDT 2009


Author: fjahanian
Date: Mon Aug 17 14:04:50 2009
New Revision: 79269

URL: http://llvm.org/viewvc/llvm-project?rev=79269&view=rev
Log:
Patch to 1) synthesizing non-trivial default destructor when
one is not provided by user. 2) More complete
emission of ctor prologue when it has no initializer
list or when it is synthesized.


Added:
    cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=79269&r1=79268&r2=79269&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Mon Aug 17 14:04:50 2009
@@ -1193,9 +1193,30 @@
     }
   }
 
-  if (!CD->isTrivial() && CD->getNumBaseOrMemberInitializers() == 0)
+  if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) {
     // Nontrivial default constructor with no initializer list. It may still
-    // contain non-static data members which require construction.
+    // have bases classes and/or contain non-static data members which require 
+    // construction.
+    for (CXXRecordDecl::base_class_const_iterator Base = 
+          ClassDecl->bases_begin();
+          Base != ClassDecl->bases_end(); ++Base) {
+      // FIXME. copy assignment of virtual base NYI
+      if (Base->isVirtual())
+        continue;
+    
+      CXXRecordDecl *BaseClassDecl
+        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+      if (BaseClassDecl->hasTrivialConstructor())
+        continue;
+      if (CXXConstructorDecl *BaseCX = 
+            BaseClassDecl->getDefaultConstructor(getContext())) {
+        LoadOfThis = LoadCXXThis();
+        llvm::Value *V = AddressCXXOfBaseClass(LoadOfThis, ClassDecl,
+                                               BaseClassDecl);
+        EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0);
+      }
+    }
+  
     for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
          FieldEnd = ClassDecl->field_end();
          Field != FieldEnd; ++Field) {
@@ -1203,19 +1224,19 @@
       if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion())
         continue;
       const RecordType *ClassRec = FieldType->getAs<RecordType>();
-      if (CXXRecordDecl *MemberClassDecl = 
-            dyn_cast<CXXRecordDecl>(ClassRec->getDecl())) {
-        if (MemberClassDecl->hasTrivialConstructor())
-          continue;
-        if (CXXConstructorDecl *MamberCX = 
-              MemberClassDecl->getDefaultConstructor(getContext())) {
-          LoadOfThis = LoadCXXThis();
-          LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
-          EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 0, 0);
-        }
+      CXXRecordDecl *MemberClassDecl = 
+        dyn_cast<CXXRecordDecl>(ClassRec->getDecl());
+      if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor())
+        continue;
+      if (CXXConstructorDecl *MamberCX = 
+            MemberClassDecl->getDefaultConstructor(getContext())) {
+        LoadOfThis = LoadCXXThis();
+        LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
+        EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 0, 0);
       }
     }
-
+  }
+  
   // Initialize the vtable pointer
   if (ClassDecl->isDynamicClass()) {
     if (!LoadOfThis)
@@ -1267,4 +1288,72 @@
                             Dtor_Complete, V);
     }
   }
+  if (DD->getNumBaseOrMemberDestructions() || DD->isTrivial())
+    return;
+  // Case of destructor synthesis with fields and base classes
+  // which have non-trivial destructors. They must be destructed in 
+  // reverse order of their construction.
+  llvm::SmallVector<FieldDecl *, 16> DestructedFields;
+  
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    QualType FieldType = getContext().getCanonicalType((*Field)->getType());
+    // FIXME. Assert on arrays for now.
+    if (const RecordType *RT = FieldType->getAs<RecordType>()) {
+      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+      if (FieldClassDecl->hasTrivialDestructor())
+        continue;
+      DestructedFields.push_back(*Field);
+    }
+  }
+  if (!DestructedFields.empty())
+    for (int i = DestructedFields.size() -1; i >= 0; --i) {
+      FieldDecl *Field = DestructedFields[i];
+      QualType FieldType = Field->getType();
+      const RecordType *RT = FieldType->getAs<RecordType>();
+      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+      llvm::Value *LoadOfThis = LoadCXXThis();
+      LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
+      EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
+                            Dtor_Complete, LHS.getAddress());
+    }
+  
+  llvm::SmallVector<CXXRecordDecl*, 4> DestructedBases;
+  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
+       Base != ClassDecl->bases_end(); ++Base) {
+    // FIXME. copy assignment of virtual base NYI
+    if (Base->isVirtual())
+      continue;
+    
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    DestructedBases.push_back(BaseClassDecl);
+  }
+  if (DestructedBases.empty())
+    return;
+  for (int i = DestructedBases.size() -1; i >= 0; --i) {
+    CXXRecordDecl *BaseClassDecl = DestructedBases[i];
+    llvm::Value *V = AddressCXXOfBaseClass(LoadCXXThis(), 
+                                           ClassDecl,BaseClassDecl);
+    EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
+                          Dtor_Complete, V);
+  }
 }
+
+void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *CD,
+                                                  const FunctionDecl *FD,
+                                                  llvm::Function *Fn,
+                                                  const FunctionArgList &Args) {
+  
+  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
+  assert(!ClassDecl->hasUserDeclaredDestructor() &&
+         "SynthesizeDefaultDestructor - destructor has user declaration");
+  (void) ClassDecl;
+  
+  StartFunction(FD, FD->getResultType(), Fn, Args, SourceLocation());
+  EmitDtorEpilogue(CD);
+  FinishFunction();
+}  

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=79269&r1=79268&r2=79269&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Aug 17 14:04:50 2009
@@ -254,6 +254,8 @@
         SynthesizeDefaultConstructor(CD, FD, Fn, Args);
       }
     }
+  else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
+         SynthesizeDefaultDestructor(DD, FD, Fn, Args);
   else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
          if (MD->isCopyAssignment())
            SynthesizeCXXCopyAssignment(MD, FD, Fn, Args);

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=79269&r1=79268&r2=79269&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Aug 17 14:04:50 2009
@@ -403,6 +403,11 @@
                                     llvm::Function *Fn,
                                     const FunctionArgList &Args);
   
+  void SynthesizeDefaultDestructor(const CXXDestructorDecl *CD,
+                                    const FunctionDecl *FD,
+                                    llvm::Function *Fn,
+                                    const FunctionArgList &Args);
+  
   /// EmitDtorEpilogue - Emit all code that comes at the end of class's
   /// destructor. This is to call destructors on members and base classes 
   /// in reverse order of their construction.

Added: cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp?rev=79269&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp Mon Aug 17 14:04:50 2009
@@ -0,0 +1,54 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s &&
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -O0 -S %s -o %t-32.s &&
+// RUN: FileCheck -check-prefix LP32 -input-file=%t-32.s %s &&
+// RUN: true
+
+extern "C" int printf(...);
+
+struct S {
+  S() : iS(1), fS(1.23) {};
+  ~S(){printf("S::~S(%d, %f)\n", iS, fS); };
+  int iS;
+  float fS;
+};
+
+struct Q {
+  Q() : iQ(2), dQ(2.34) {};
+  ~Q(){printf("Q::~Q(%d, %f)\n", iQ, dQ); };
+  int iQ;
+  double dQ;
+};
+
+struct P {
+  P() : fP(3.45) , iP(3) {};
+  ~P(){printf("P::~P(%d, %f)\n", iP, fP); };
+  float fP;
+  int iP;
+};
+
+struct M  : Q, P {
+  S s;
+
+  Q q;
+
+  P p; 
+
+};
+
+M gm;
+
+int main() {M m1;}
+
+// CHECK-LP64:  call	__ZN1MC1Ev
+// CHECK-LP64:  call	__ZN1MD1Ev
+// CHECK-LP64:  .globl	__ZN1MD1Ev
+// CHECK-LP64-NEXT:  .weak_definition __ZN1MD1Ev
+// CHECK-LP64-NEXT:  __ZN1MD1Ev:
+
+
+// CHECK-LP32:  call	L__ZN1MC1Ev
+// CHECK-LP32:  call	L__ZN1MD1Ev
+// CHECK-LP32:  .globl	__ZN1MD1Ev
+// CHECK-LP32-NEXT:  .weak_definition __ZN1MD1Ev
+// CHECK-LP32-NEXT:  __ZN1MD1Ev:





More information about the cfe-commits mailing list