[cfe-commits] r80967 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp test/CodeGenCXX/constructor-template.cpp

Fariborz Jahanian fjahanian at apple.com
Thu Sep 3 16:18:17 PDT 2009


Author: fjahanian
Date: Thu Sep  3 18:18:17 2009
New Revision: 80967

URL: http://llvm.org/viewvc/llvm-project?rev=80967&view=rev
Log:
Patch to instantiate destructors used to destruct
base and data members when they are needed.


Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/constructor-template.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Sep  3 18:18:17 2009
@@ -1095,12 +1095,13 @@
 /// };
 /// @endcode
 class CXXDestructorDecl : public CXXMethodDecl {
+public:
   enum KindOfObjectToDestroy {
     VBASE = 0x1,
     DRCTNONVBASE = 0x2,
     ANYBASE = 0x3
   };
-
+private:
   /// ImplicitlyDefined - Whether this destructor was implicitly
   /// defined by the compiler. When false, the destructor was defined
   /// by the user. In C++03, this flag will have the same value as
@@ -1181,12 +1182,24 @@
     return NumBaseOrMemberDestructions; 
   }
   
-  /// getBaseOrMember - get the generic 'member' representing either the field
-  /// or a base class.
+  /// setNumBaseOrMemberDestructions - Set number of base and non-static members
+  /// to destroy.
+  void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) {
+    NumBaseOrMemberDestructions = numBaseOrMemberDestructions;
+  }
+  
+  /// getBaseOrMemberToDestroy - get the generic 'member' representing either 
+  /// the field or a base class.
   uintptr_t* getBaseOrMemberToDestroy() const {
     return BaseOrMemberDestructions; 
   }
   
+  /// setBaseOrMemberToDestroy - set the generic 'member' representing either 
+  /// the field or a base class.
+  void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) {
+    BaseOrMemberDestructions = baseOrMemberDestructions;
+  }
+  
   /// isVbaseToDestroy - returns true, if object is virtual base.
   bool isVbaseToDestroy(uintptr_t Vbase) const {
     return (Vbase & VBASE) != 0;
@@ -1229,12 +1242,6 @@
       return reinterpret_cast<Type*>(Base  & ~0x02);
     return 0;
   }
-  
-  /// computeBaseOrMembersToDestroy - Compute information in current 
-  /// destructor decl's AST of bases and non-static data members which will be 
-  /// implicitly destroyed. We are storing the destruction in the order that
-  /// they should occur (which is the reverse of construction order).
-  void computeBaseOrMembersToDestroy(ASTContext &C);
                         
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { 

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Sep  3 18:18:17 2009
@@ -523,67 +523,6 @@
 }
 
 void
-CXXDestructorDecl::computeBaseOrMembersToDestroy(ASTContext &C) {
-  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext());
-  llvm::SmallVector<uintptr_t, 32> AllToDestruct;
-  
-  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
-       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
-    if (VBase->getType()->isDependentType())
-      continue;
-    // Skip over virtual bases which have trivial destructors.
-    CXXRecordDecl *BaseClassDecl
-      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
-    if (BaseClassDecl->hasTrivialDestructor())
-      continue;
-    uintptr_t Member = 
-      reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) | VBASE;
-    AllToDestruct.push_back(Member);
-  }
-  for (CXXRecordDecl::base_class_iterator Base =
-       ClassDecl->bases_begin(),
-       E = ClassDecl->bases_end(); Base != E; ++Base) {
-    if (Base->isVirtual())
-      continue;
-    if (Base->getType()->isDependentType())
-      continue;
-    // Skip over virtual bases which have trivial destructors.
-    CXXRecordDecl *BaseClassDecl
-      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-    if (BaseClassDecl->hasTrivialDestructor())
-      continue;
-    
-    uintptr_t Member = 
-      reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) | DRCTNONVBASE;
-    AllToDestruct.push_back(Member);
-  }
-  
-  // non-static data members.
-  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
-       E = ClassDecl->field_end(); Field != E; ++Field) {
-    QualType FieldType = C.getBaseElementType((*Field)->getType());
-    
-    if (const RecordType* RT = FieldType->getAs<RecordType>()) {
-      // Skip over virtual bases which have trivial destructors.
-      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-      if (BaseClassDecl->hasTrivialDestructor())
-        continue;
-      uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
-      AllToDestruct.push_back(Member);
-    }
-  }
-  
-  unsigned NumDestructions = AllToDestruct.size();
-  if (NumDestructions > 0) {
-    NumBaseOrMemberDestructions = NumDestructions;
-    BaseOrMemberDestructions = new (C) uintptr_t [NumDestructions];
-    // Insert in reverse order.
-    for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx)
-      BaseOrMemberDestructions[i++] = AllToDestruct[Idx];
-  }
-}
-
-void
 CXXConstructorDecl::Destroy(ASTContext& C) {
   C.Deallocate(BaseOrMemberInitializers);
   CXXMethodDecl::Destroy(C);

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Sep  3 18:18:17 2009
@@ -2191,6 +2191,12 @@
                               llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
                               llvm::SmallVectorImpl<FieldDecl *>&Members);
   
+  /// computeBaseOrMembersToDestroy - Compute information in current 
+  /// destructor decl's AST of bases and non-static data members which will be 
+  /// implicitly destroyed. We are storing the destruction in the order that
+  /// they should occur (which is the reverse of construction order).
+  void computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor);
+  
   void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
 
   virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep  3 18:18:17 2009
@@ -3758,7 +3758,7 @@
     DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
   
   if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
-    Destructor->computeBaseOrMembersToDestroy(Context);
+    computeBaseOrMembersToDestroy(Destructor);
   return D;
 }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep  3 18:18:17 2009
@@ -1284,6 +1284,81 @@
   }
 }
 
+void
+Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) {
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
+  llvm::SmallVector<uintptr_t, 32> AllToDestruct;
+  
+  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+    if (VBase->getType()->isDependentType())
+      continue;
+    // Skip over virtual bases which have trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
+      MarkDeclarationReferenced(Destructor->getLocation(), 
+                                const_cast<CXXDestructorDecl*>(Dtor));
+    
+    uintptr_t Member = 
+    reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) 
+      | CXXDestructorDecl::VBASE;
+    AllToDestruct.push_back(Member);
+  }
+  for (CXXRecordDecl::base_class_iterator Base =
+       ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    if (Base->isVirtual())
+      continue;
+    if (Base->getType()->isDependentType())
+      continue;
+    // Skip over virtual bases which have trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+    = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
+      MarkDeclarationReferenced(Destructor->getLocation(), 
+                                const_cast<CXXDestructorDecl*>(Dtor));
+    uintptr_t Member = 
+    reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) 
+      | CXXDestructorDecl::DRCTNONVBASE;
+    AllToDestruct.push_back(Member);
+  }
+  
+  // non-static data members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    
+    if (const RecordType* RT = FieldType->getAs<RecordType>()) {
+      // Skip over virtual bases which have trivial destructors.
+      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+      if (FieldClassDecl->hasTrivialDestructor())
+        continue;
+      if (const CXXDestructorDecl *Dtor = 
+            FieldClassDecl->getDestructor(Context))
+        MarkDeclarationReferenced(Destructor->getLocation(), 
+                                  const_cast<CXXDestructorDecl*>(Dtor));
+      uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
+      AllToDestruct.push_back(Member);
+    }
+  }
+  
+  unsigned NumDestructions = AllToDestruct.size();
+  if (NumDestructions > 0) {
+    Destructor->setNumBaseOrMemberDestructions(NumDestructions);
+    uintptr_t *BaseOrMemberDestructions = 
+      new (Context) uintptr_t [NumDestructions];
+    // Insert in reverse order.
+    for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx)
+      BaseOrMemberDestructions[i++] = AllToDestruct[Idx];
+    Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions);
+  }
+}
+
 void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
   if (!CDtorDecl)
     return;

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Sep  3 18:18:17 2009
@@ -757,6 +757,10 @@
                                  &DeleteArg, 1, Record, /*AllowMissing=*/true,
                                  OperatorDelete))
         return ExprError();
+      if (!Record->hasTrivialDestructor())
+        if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context))
+          MarkDeclarationReferenced(StartLoc, 
+                                    const_cast<CXXDestructorDecl*>(Dtor));
     }
     
     if (!OperatorDelete) {

Modified: cfe/trunk/test/CodeGenCXX/constructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/constructor-template.cpp?rev=80967&r1=80966&r2=80967&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/constructor-template.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/constructor-template.cpp Thu Sep  3 18:18:17 2009
@@ -22,12 +22,14 @@
 template <typename T> class List {
 public:
   List(){ }	// List<BinomialNode<int>*>::List() remains undefined.
+  ~List() {}
 };
 
 template <typename T> class Node {
  int i;
 public:
  Node(){ }      // Node<BinomialNode<int>*>::Node() remains undefined.
+ ~Node() {}
 };
 
 
@@ -40,10 +42,15 @@
 int main() {
   B<int> *n = new B<int>(4);
   BinomialNode<int> *node = new BinomialNode<int>(1);
+  delete node;
 }
 
+// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED1Ev:
+// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED2Ev:
 // CHECK-LP64:	__ZN4NodeIP12BinomialNodeIiEEC1Ev:
 // CHECK-LP64: __ZN4ListIP12BinomialNodeIiEEC1Ev:
 
+// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED1Ev:
+// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED2Ev:
 // CHECK-LP32: __ZN4NodeIP12BinomialNodeIiEEC1Ev:
 // CHECK-LP32: __ZN4ListIP12BinomialNodeIiEEC1Ev:





More information about the cfe-commits mailing list