[cfe-commits] r90327 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/AST/RecordLayoutBuilder.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/implicit-virtual-member-functions.cpp

Anders Carlsson andersca at mac.com
Wed Dec 2 09:15:43 PST 2009


Author: andersca
Date: Wed Dec  2 11:15:43 2009
New Revision: 90327

URL: http://llvm.org/viewvc/llvm-project?rev=90327&view=rev
Log:
In Sema, whenever we think that a function is going to cause a vtable to be generated, we mark any virtual implicit member functions as referenced.

Added:
    cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.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

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Dec  2 11:15:43 2009
@@ -660,7 +660,7 @@
   CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
 
   /// getDestructor - Returns the destructor decl for this class.
-  const CXXDestructorDecl *getDestructor(ASTContext &Context);
+  CXXDestructorDecl *getDestructor(ASTContext &Context);
 
   /// isLocalClass - If the class is a local class [class.local], returns
   /// the enclosing function declaration.

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Dec  2 11:15:43 2009
@@ -507,8 +507,7 @@
   return 0;
 }
 
-const CXXDestructorDecl *
-CXXRecordDecl::getDestructor(ASTContext &Context) {
+CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) {
   QualType ClassType = Context.getTypeDeclType(this);
 
   DeclarationName Name
@@ -519,7 +518,7 @@
   llvm::tie(I, E) = lookup(Name);
   assert(I != E && "Did not find a destructor!");
 
-  const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
+  CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
   assert(++I == E && "Found more than one destructor!");
 
   return Dtor;

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

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Wed Dec  2 11:15:43 2009
@@ -677,6 +677,11 @@
     if (MD->isPure())
       continue;
     
+    // Ignore implicit member functions, they are always marked as inline, but
+    // they don't have a body until they're defined.
+    if (MD->isImplicit())
+      continue;
+    
     const FunctionDecl *fn;
     if (MD->getBody(fn) && !fn->isOutOfLine())
       continue;

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Dec  2 11:15:43 2009
@@ -1932,8 +1932,7 @@
                                        QualType Argument);
 
   bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, 
-                                DeclarationName Name, FunctionDecl* &Operator,
-                                bool Diagnose=true);
+                                DeclarationName Name, FunctionDecl* &Operator);
 
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression
   virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
@@ -2128,6 +2127,12 @@
   /// as referenced.
   void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor);
 
+  /// MaybeMarkVirtualImplicitMembersReferenced - If the passed in method is the
+  /// key function of the record decl, will mark virtual member functions as 
+  /// referenced.
+  void MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, 
+                                                 CXXMethodDecl *MD);
+  
   void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
 
   virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
@@ -2160,7 +2165,7 @@
   void CheckConstructor(CXXConstructorDecl *Constructor);
   QualType CheckDestructorDeclarator(Declarator &D,
                                      FunctionDecl::StorageClass& SC);
-  bool CheckDestructor(CXXDestructorDecl *Destructor, bool Diagnose=true);
+  bool CheckDestructor(CXXDestructorDecl *Destructor);
   void CheckConversionDeclarator(Declarator &D, QualType &R,
                                  FunctionDecl::StorageClass& SC);
   DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Dec  2 11:15:43 2009
@@ -4085,12 +4085,14 @@
     if (!FD->isInvalidDecl())
       DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
 
-    // C++ [basic.def.odr]p2:
-    //   [...] A virtual member function is used if it is not pure. [...]
-    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) {
+      // C++ [basic.def.odr]p2:
+      //   [...] A virtual member function is used if it is not pure. [...]
       if (Method->isVirtual() && !Method->isPure())
         MarkDeclarationReferenced(Method->getLocation(), Method);
 
+      MaybeMarkVirtualImplicitMembersReferenced(Method->getLocation(), Method);
+    }
     assert(FD == getCurFunctionDecl() && "Function parsing confused");
   } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
     assert(MD == getCurMethodDecl() && "Method parsing confused");

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Dec  2 11:15:43 2009
@@ -15,6 +15,7 @@
 #include "Lookup.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/TypeOrdering.h"
@@ -2172,7 +2173,6 @@
     ClassDecl->addDecl(Destructor);
     
     AddOverriddenMethods(ClassDecl, Destructor);
-    CheckDestructor(Destructor, false);
   }
 }
 
@@ -2371,7 +2371,7 @@
 
 /// CheckDestructor - Checks a fully-formed destructor for well-formedness, 
 /// issuing any diagnostics required. Returns true on error.
-bool Sema::CheckDestructor(CXXDestructorDecl *Destructor, bool Diagnose) {
+bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
   CXXRecordDecl *RD = Destructor->getParent();
   
   if (Destructor->isVirtual()) {
@@ -2386,7 +2386,7 @@
     FunctionDecl *OperatorDelete = 0;
     DeclarationName Name = 
     Context.DeclarationNames.getCXXOperatorName(OO_Delete);
-    if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete, Diagnose))
+    if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
       return true;
     
     Destructor->setOperatorDelete(OperatorDelete);
@@ -3083,7 +3083,8 @@
   } else {
     Constructor->setUsed();
   }
-  return;
+
+  MaybeMarkVirtualImplicitMembersReferenced(CurrentLocation, Constructor);
 }
 
 void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
@@ -4994,3 +4995,31 @@
   VD->setDeclaredInCondition(true);
   return Dcl;
 }
+
+void Sema::MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc,
+                                                     CXXMethodDecl *MD) {
+  // Ignore dependent types.
+  if (MD->isDependentContext())
+    return;
+  
+  CXXRecordDecl *RD = MD->getParent();
+  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+  const CXXMethodDecl *KeyFunction = Layout.getKeyFunction();
+
+  if (!KeyFunction) {
+    // This record does not have a key function, so we assume that the vtable
+    // will be emitted when it's used by the constructor.
+    if (!isa<CXXConstructorDecl>(MD))
+      return;
+  } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) {
+    // We don't have the right key function.
+    return;
+  }
+  
+  if (CXXDestructorDecl *Dtor = RD->getDestructor(Context)) {
+    if (Dtor->isImplicit() && Dtor->isVirtual())
+      MarkDeclarationReferenced(Loc, Dtor);
+  }
+  
+  // FIXME: Need to handle the virtual assignment operator here too.
+}

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Dec  2 11:15:43 2009
@@ -775,8 +775,7 @@
 
 bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
                                     DeclarationName Name,
-                                    FunctionDecl* &Operator,
-                                    bool Diagnose) {
+                                    FunctionDecl* &Operator) {
   LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
   // Try to find operator delete/operator delete[] in class scope.
   LookupQualifiedName(Found, RD);
@@ -796,8 +795,6 @@
   // We did find operator delete/operator delete[] declarations, but
   // none of them were suitable.
   if (!Found.empty()) {
-    if (!Diagnose)
-      return true;
     Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
       << Name << RD;
         

Added: cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp?rev=90327&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp (added)
+++ cfe/trunk/test/SemaCXX/implicit-virtual-member-functions.cpp Wed Dec  2 11:15:43 2009
@@ -0,0 +1,29 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+struct A {
+  virtual ~A();
+};
+
+struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}}
+  virtual void f();
+
+  void operator delete (void *, int); // expected-note {{'operator delete' declared here}}
+};
+
+void B::f() { // expected-note {{implicit default destructor for 'struct B' first required here}}
+}
+
+struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}}
+  C();
+  void operator delete(void *, int); // expected-note {{'operator delete' declared here}}
+};
+
+C::C() { } // expected-note {{implicit default destructor for 'struct C' first required here}}
+
+struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}}
+  void operator delete(void *, int); // expected-note {{'operator delete' declared here}}
+};
+
+void f() {
+  new D; // expected-note {{implicit default destructor for 'struct D' first required here}}
+}
+





More information about the cfe-commits mailing list