[cfe-commits] r89034 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/AST/DeclPrinter.cpp lib/CodeGen/CGCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/destructors.cpp

Anders Carlsson andersca at mac.com
Mon Nov 16 20:44:20 PST 2009


Author: andersca
Date: Mon Nov 16 22:44:12 2009
New Revision: 89034

URL: http://llvm.org/viewvc/llvm-project?rev=89034&view=rev
Log:
Unify the way destructor epilogues are generated for synthesized and regular destructors. Also fix PR5529.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/destructors.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Nov 16 22:44:12 2009
@@ -1269,13 +1269,6 @@
 /// };
 /// @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
@@ -1284,27 +1277,15 @@
   /// @c !Implicit && ImplicitlyDefined.
   bool ImplicitlyDefined : 1;
 
-  /// Support for base and member destruction.
-  /// BaseOrMemberDestructions - The arguments used to destruct the base
-  /// or member. Each uintptr_t value represents one of base classes (either
-  /// virtual or direct non-virtual base), or non-static data member
-  /// to be destroyed. The low two bits encode the kind of object
-  /// being destroyed.
-  uintptr_t *BaseOrMemberDestructions;
-  unsigned NumBaseOrMemberDestructions;
-
   FunctionDecl *OperatorDelete;
   
   CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
                     DeclarationName N, QualType T,
                     bool isInline, bool isImplicitlyDeclared)
     : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline),
-      ImplicitlyDefined(false),
-      BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0),
-      OperatorDelete(0) {
+      ImplicitlyDefined(false), OperatorDelete(0) {
     setImplicit(isImplicitlyDeclared);
   }
-  virtual void Destroy(ASTContext& C);
 
 public:
   static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
@@ -1333,96 +1314,6 @@
   void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
   const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
 
-  /// destr_iterator - Iterates through the member/base destruction list.
-
-  /// destr_const_iterator - Iterates through the member/base destruction list.
-  typedef uintptr_t const destr_const_iterator;
-
-  /// destr_begin() - Retrieve an iterator to the first destructed member/base.
-  uintptr_t* destr_begin() {
-    return BaseOrMemberDestructions;
-  }
-  /// destr_begin() - Retrieve an iterator to the first destructed member/base.
-  uintptr_t* destr_begin() const {
-    return BaseOrMemberDestructions;
-  }
-
-  /// destr_end() - Retrieve an iterator past the last destructed member/base.
-  uintptr_t* destr_end() {
-    return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
-  }
-  /// destr_end() - Retrieve an iterator past the last destructed member/base.
-  uintptr_t* destr_end() const {
-    return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
-  }
-
-  /// getNumBaseOrMemberDestructions - Number of base and non-static members
-  /// to destroy.
-  unsigned getNumBaseOrMemberDestructions() const {
-    return NumBaseOrMemberDestructions;
-  }
-
-  /// 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;
-  }
-  /// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual
-  /// base.
-  bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const {
-    return (DrctNonVbase & DRCTNONVBASE) != 0;
-  }
-  /// isAnyBaseToDestroy - returns true, if object is any base (virtual or
-  /// direct non-virtual)
-  bool isAnyBaseToDestroy(uintptr_t AnyBase) const {
-    return (AnyBase & ANYBASE) != 0;
-  }
-  /// isMemberToDestroy - returns true if object is a non-static data member.
-  bool isMemberToDestroy(uintptr_t Member) const {
-    return (Member & ANYBASE)  == 0;
-  }
-  /// getAnyBaseClassToDestroy - Get the type for the given base class object.
-  Type *getAnyBaseClassToDestroy(uintptr_t Base) const {
-    if (isAnyBaseToDestroy(Base))
-      return reinterpret_cast<Type*>(Base  & ~0x03);
-    return 0;
-  }
-  /// getMemberToDestroy - Get the member for the given object.
-  FieldDecl *getMemberToDestroy(uintptr_t Member) const {
-    if (isMemberToDestroy(Member))
-      return reinterpret_cast<FieldDecl *>(Member);
-    return 0;
-  }
-  /// getVbaseClassToDestroy - Get the virtual base.
-  Type *getVbaseClassToDestroy(uintptr_t Vbase) const {
-    if (isVbaseToDestroy(Vbase))
-      return reinterpret_cast<Type*>(Vbase  & ~0x01);
-    return 0;
-  }
-  /// getDirectNonVBaseClassToDestroy - Get the virtual base.
-  Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const {
-    if (isDirectNonVBaseToDestroy(Base))
-      return reinterpret_cast<Type*>(Base  & ~0x02);
-    return 0;
-  }
-
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() == CXXDestructor;

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Nov 16 22:44:12 2009
@@ -791,12 +791,6 @@
 }
 
 void
-CXXDestructorDecl::Destroy(ASTContext& C) {
-  C.Deallocate(BaseOrMemberDestructions);
-  CXXMethodDecl::Destroy(C);
-}
-
-void
 CXXConstructorDecl::Destroy(ASTContext& C) {
   C.Deallocate(BaseOrMemberInitializers);
   CXXMethodDecl::Destroy(C);

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

==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Mon Nov 16 22:44:12 2009
@@ -401,37 +401,6 @@
         }
       }
     }
-    else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(D)) {
-      if (DDecl->getNumBaseOrMemberDestructions() > 0) {
-        // List order of base/member destruction for visualization purposes.
-        assert (D->isThisDeclarationADefinition() && "Destructor with dtor-list");
-        Proto += "/* : ";
-        for (CXXDestructorDecl::destr_const_iterator *B = DDecl->destr_begin(),
-             *E = DDecl->destr_end();
-             B != E; ++B) {
-          uintptr_t BaseOrMember = (*B);
-          if (B != DDecl->destr_begin())
-            Proto += ", ";
-
-          if (DDecl->isMemberToDestroy(BaseOrMember)) {
-            FieldDecl *FD = DDecl->getMemberToDestroy(BaseOrMember);
-            Proto += "~";
-            Proto += FD->getNameAsString();
-          }
-          else // FIXME. skip dependent types for now.
-            if (const RecordType *RT =
-                  DDecl->getAnyBaseClassToDestroy(BaseOrMember)
-                    ->getAs<RecordType>()) {
-              const CXXRecordDecl *BaseDecl =
-                cast<CXXRecordDecl>(RT->getDecl());
-              Proto += "~";
-              Proto += BaseDecl->getNameAsString();
-            }
-          Proto += "()";
-        }
-        Proto += " */";
-      }
-    }
     else
       AFT->getResultType().getAsStringInternal(Proto, Policy);
   } else {

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Mon Nov 16 22:44:12 2009
@@ -1643,119 +1643,97 @@
 /// FIXME: This needs to take a CXXDtorType.
 void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
                                        CXXDtorType DtorType) {
-  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext());
-  assert(!ClassDecl->getNumVBases() &&
-         "FIXME: Destruction of virtual bases not supported");
-  (void)ClassDecl;  // prevent warning.
-
-  for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(),
-       *E = DD->destr_end(); B != E; ++B) {
-    uintptr_t BaseOrMember = (*B);
-    if (DD->isMemberToDestroy(BaseOrMember)) {
-      FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember);
-      QualType FieldType = getContext().getCanonicalType((FD)->getType());
-      const ConstantArrayType *Array =
-        getContext().getAsConstantArrayType(FieldType);
-      if (Array)
-        FieldType = getContext().getBaseElementType(FieldType);
-      const RecordType *RT = FieldType->getAs<RecordType>();
-      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-      if (FieldClassDecl->hasTrivialDestructor())
-        continue;
-      llvm::Value *LoadOfThis = LoadCXXThis();
-      LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0);
-      if (Array) {
-        const llvm::Type *BasePtr = ConvertType(FieldType);
-        BasePtr = llvm::PointerType::getUnqual(BasePtr);
-        llvm::Value *BaseAddrPtr =
-          Builder.CreateBitCast(LHS.getAddress(), BasePtr);
-        EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
-                                  Array, BaseAddrPtr);
-      }
-      else
-        EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
-                              Dtor_Complete, LHS.getAddress());
-    } else {
-      const RecordType *RT =
-        DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>();
-      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-      if (BaseClassDecl->hasTrivialDestructor())
+  assert(!DD->isTrivial() &&
+         "Should not emit dtor epilogue for trivial dtor!");
+
+  const CXXRecordDecl *ClassDecl = DD->getParent();
+
+  // Collect the fields.
+  llvm::SmallVector<const FieldDecl *, 16> FieldDecls;
+  for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); I != E; ++I) {
+    const FieldDecl *Field = *I;
+    
+    QualType FieldType = getContext().getCanonicalType(Field->getType());
+    FieldType = getContext().getBaseElementType(FieldType);
+    
+    const RecordType *RT = FieldType->getAs<RecordType>();
+    if (!RT)
+      continue;
+    
+    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    if (FieldClassDecl->hasTrivialDestructor())
         continue;
-      llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(),
-                                                ClassDecl, BaseClassDecl,
-                                                /*NullCheckValue=*/false);
-      EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
-                            DtorType, V);
-    }
+    
+    FieldDecls.push_back(Field);
   }
-  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());
-    if (getContext().getAsConstantArrayType(FieldType))
+  
+  // Now destroy the fields.
+  for (size_t i = FieldDecls.size(); i > 0; --i) {
+    const FieldDecl *Field = FieldDecls[i - 1];
+    
+    QualType FieldType = Field->getType();
+    const ConstantArrayType *Array = 
+      getContext().getAsConstantArrayType(FieldType);
+    if (Array)
       FieldType = getContext().getBaseElementType(FieldType);
-    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 ConstantArrayType *Array =
-        getContext().getAsConstantArrayType(FieldType);
-        if (Array)
-          FieldType = getContext().getBaseElementType(FieldType);
-      const RecordType *RT = FieldType->getAs<RecordType>();
-      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-      llvm::Value *LoadOfThis = LoadCXXThis();
-      LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
-      if (Array) {
-        const llvm::Type *BasePtr = ConvertType(FieldType);
-        BasePtr = llvm::PointerType::getUnqual(BasePtr);
-        llvm::Value *BaseAddrPtr =
+    
+    const RecordType *RT = FieldType->getAs<RecordType>();
+    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+
+    llvm::Value *ThisPtr = LoadCXXThis();
+
+    LValue LHS = EmitLValueForField(ThisPtr, Field, 
+                                    /*isUnion=*/false,
+                                    // FIXME: Qualifiers?
+                                    /*CVRQualifiers=*/0);
+    if (Array) {
+      const llvm::Type *BasePtr = ConvertType(FieldType);
+      BasePtr = llvm::PointerType::getUnqual(BasePtr);
+      llvm::Value *BaseAddrPtr =
         Builder.CreateBitCast(LHS.getAddress(), BasePtr);
-        EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
-                                  Array, BaseAddrPtr);
-      }
-      else
-        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;
+      EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()),
+                                Array, BaseAddrPtr);
+    } else
+      EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
+                            Dtor_Complete, LHS.getAddress());
+  }
 
+  // Destroy non-virtual bases.
+  for (CXXRecordDecl::reverse_base_class_const_iterator I = 
+        ClassDecl->bases_rbegin(), E = ClassDecl->bases_rend(); I != E; ++I) {
+    const CXXBaseSpecifier &Base = *I;
+    
+    // Ignore virtual bases.
+    if (Base.isVirtual())
+      continue;
+    
     CXXRecordDecl *BaseClassDecl
-      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+    
+    // Ignore trivial destructors.
     if (BaseClassDecl->hasTrivialDestructor())
       continue;
-    DestructedBases.push_back(BaseClassDecl);
-  }
 
-  for (int i = DestructedBases.size(); i > 0; --i) {
-    CXXRecordDecl *BaseClassDecl = DestructedBases[i - 1];
     llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(),
-                                              ClassDecl,BaseClassDecl, 
+                                              ClassDecl, BaseClassDecl, 
                                               /*NullCheckValue=*/false);
     EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
-                          Dtor_Complete, V);
+                          Dtor_Base, V);
   }
+
+  // If we're emitting a base destructor, we don't want to emit calls to the
+  // virtual bases.
+  if (DtorType == Dtor_Base)
+    return;
   
+  // FIXME: Handle virtual bases.
+  for (CXXRecordDecl::reverse_base_class_const_iterator I = 
+       ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) {
+    assert(false && "FIXME: Handle virtual bases.");
+  }
+    
+  // If we have a deleting destructor, emit a call to the delete operator.
   if (DtorType == Dtor_Deleting) {
     const FunctionDecl *DeleteFD = DD->getOperatorDelete();
     assert(DeleteFD && "deleting dtor did not have a delete operator!");
@@ -1782,19 +1760,17 @@
                                                   CXXDtorType DtorType,
                                                   llvm::Function *Fn,
                                                   const FunctionArgList &Args) {
-
-  const CXXRecordDecl *ClassDecl = Dtor->getParent();
-  assert(!ClassDecl->hasUserDeclaredDestructor() &&
+  assert(!Dtor->getParent()->hasUserDeclaredDestructor() &&
          "SynthesizeDefaultDestructor - destructor has user declaration");
-  (void) ClassDecl;
 
   StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args, 
                 SourceLocation());
+
   EmitDtorEpilogue(Dtor, DtorType);
   FinishFunction();
 }
 
-// FIXME: Move this to CGCXXStmt.cpp
+// FIXME: Move this to CGStmtCXX.cpp
 void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
   // FIXME: We need to do more here.
   EmitStmt(S.getTryBlock());

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Nov 16 22:44:12 2009
@@ -2407,11 +2407,10 @@
                               unsigned NumInitializers,
                               bool IsImplicitConstructor);
 
-  /// 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);
+  /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl,
+  /// mark all its non-trivial member and base destructor declarations
+  /// as referenced.
+  void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor);
 
   void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov 16 22:44:12 2009
@@ -4052,7 +4052,7 @@
     DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
 
   if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
-    computeBaseOrMembersToDestroy(Destructor);
+    MarkBaseAndMemberDestructorsReferenced(Destructor);
   
   // If any errors have occurred, clear out any temporaries that may have
   // been leftover. This ensures that these temporaries won't be picked up for

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov 16 22:44:12 2009
@@ -1633,77 +1633,63 @@
 }
 
 void
-Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) {
-  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
-  llvm::SmallVector<uintptr_t, 32> AllToDestruct;
+Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) {
+  // Ignore dependent destructors.
+  if (Destructor->isDependentContext())
+    return;
+  
+  CXXRecordDecl *ClassDecl = Destructor->getParent();
 
-  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
-       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
-    if (VBase->getType()->isDependentType())
+  // Non-static data members.
+  for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); I != E; ++I) {
+    FieldDecl *Field = *I;
+    
+    QualType FieldType = Context.getBaseElementType(Field->getType());
+    
+    const RecordType* RT = FieldType->getAs<RecordType>();
+    if (!RT)
       continue;
-    // Skip over virtual bases which have trivial destructors.
-    CXXRecordDecl *BaseClassDecl
-      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
-    if (BaseClassDecl->hasTrivialDestructor())
+    
+    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    if (FieldClassDecl->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);
+
+    const CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(Destructor->getLocation(),
+                              const_cast<CXXDestructorDecl*>(Dtor));
   }
-  for (CXXRecordDecl::base_class_iterator Base =
-       ClassDecl->bases_begin(),
+
+  // Bases.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
        E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Ignore virtual bases.
     if (Base->isVirtual())
       continue;
-    if (Base->getType()->isDependentType())
-      continue;
-    // Skip over virtual bases which have trivial destructors.
+
+    // Ignore trivial destructors.
     CXXRecordDecl *BaseClassDecl
-    = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+      = 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);
-    }
+    
+    const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(Destructor->getLocation(),
+                              const_cast<CXXDestructorDecl*>(Dtor));
   }
-
-  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);
+  
+  // Virtual bases.
+  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+    // Ignore trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    
+    const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+    MarkDeclarationReferenced(Destructor->getLocation(),
+                              const_cast<CXXDestructorDecl*>(Dtor));
   }
 }
 

Modified: cfe/trunk/test/CodeGenCXX/destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=89034&r1=89033&r2=89034&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/destructors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/destructors.cpp Mon Nov 16 22:44:12 2009
@@ -28,3 +28,17 @@
 };
 
 template<> A1<char>::~A1();
+
+// PR5529
+namespace PR5529 {
+  struct A {
+    ~A();
+  };
+  
+  A::~A() { }
+  struct B : A {
+    virtual ~B();
+  };
+  
+  B::~B()  {}
+}





More information about the cfe-commits mailing list