]> granicus.if.org Git - clang/commitdiff
Make sure that virtual destructors have delete operators.
authorAnders Carlsson <andersca@mac.com>
Sun, 15 Nov 2009 22:49:34 +0000 (22:49 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 15 Nov 2009 22:49:34 +0000 (22:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88877 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp

index eb3205f00f6a4b365f5b6c44ebcf6419d205f133..6ede5dee1e1e6f31f179b265ebe5baa84d543dc2 100644 (file)
@@ -1293,12 +1293,15 @@ private:
   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) {
+      BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0),
+      OperatorDelete(0) {
     setImplicit(isImplicitlyDeclared);
   }
   virtual void Destroy(ASTContext& C);
@@ -1327,6 +1330,9 @@ public:
     ImplicitlyDefined = ID;
   }
 
+  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.
index 0dd106ecafb9695683f223a49e5c9f1e66980db8..011747a1dc08fddb4e263b934bb00507c00c524e 100644 (file)
@@ -2346,6 +2346,7 @@ public:
   void CheckConstructor(CXXConstructorDecl *Constructor);
   QualType CheckDestructorDeclarator(Declarator &D,
                                      FunctionDecl::StorageClass& SC);
+  void CheckDestructor(CXXDestructorDecl *Destructor);
   void CheckConversionDeclarator(Declarator &D, QualType &R,
                                  FunctionDecl::StorageClass& SC);
   DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
index d3257c17a40501fd39f3b5f4656d46be06a43698..c6bbb9a438f3aaecccf11fdbdf755734aa2332ff 100644 (file)
@@ -3105,9 +3105,13 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
     // C++-specific checks.
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
       CheckConstructor(Constructor);
-    } else if (isa<CXXDestructorDecl>(NewFD)) {
-      CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
+    } else if (CXXDestructorDecl *Destructor = 
+                dyn_cast<CXXDestructorDecl>(NewFD)) {
+      CXXRecordDecl *Record = Destructor->getParent();
       QualType ClassType = Context.getTypeDeclType(Record);
+      
+      // FIXME: Shouldn't we be able to perform thisc heck even when the class
+      // type is dependent? Both gcc and edg can handle that.
       if (!ClassType->isDependentType()) {
         DeclarationName Name
           = Context.DeclarationNames.getCXXDestructorName(
@@ -3116,7 +3120,10 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
           Diag(NewFD->getLocation(), diag::err_destructor_name);
           return NewFD->setInvalidDecl();
         }
+      
+        CheckDestructor(Destructor);
       }
+
       Record->setUserDeclaredDestructor(true);
       // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
       // user-defined destructor.
index a45c22e2981d2d786df60b763ea2c95ee03f016c..b0e18d865cffd7ef5fdf0c8a55ba8b78f633df96 100644 (file)
@@ -2368,6 +2368,28 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
   ClassDecl->addedConstructor(Context, Constructor);
 }
 
+/// CheckDestructor - Checks a fully-formed destructor for
+/// well-formedness, issuing any diagnostics required. 
+void Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
+  CXXRecordDecl *RD = Destructor->getParent();
+  
+  if (Destructor->isVirtual()) {
+    SourceLocation Loc;
+    
+    if (!Destructor->isImplicit())
+      Loc = Destructor->getLocation();
+    else
+      Loc = RD->getLocation();
+    
+    // If we have a virtual destructor, look up the deallocation function
+    FunctionDecl *OperatorDelete = 0;
+    DeclarationName Name = 
+    Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+    if (!FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
+      Destructor->setOperatorDelete(OperatorDelete);
+  }
+}
+
 static inline bool
 FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
   return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
@@ -2997,9 +3019,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
                                     CXXDestructorDecl *Destructor) {
   assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
          "DefineImplicitDestructor - call it for implicit default dtor");
-
-  CXXRecordDecl *ClassDecl
-  = cast<CXXRecordDecl>(Destructor->getDeclContext());
+  CXXRecordDecl *ClassDecl = Destructor->getParent();
   assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
   // C++ [class.dtor] p5
   // Before the implicitly-declared default destructor for a class is