[cfe-commits] r130103 - in /cfe/trunk: include/clang/AST/ASTConsumer.h include/clang/AST/ASTMutationListener.h include/clang/Sema/Sema.h include/clang/Serialization/ASTWriter.h lib/Frontend/MultiplexConsumer.cpp lib/Sema/Sema.cpp lib/Sema/SemaDeclCXX.cpp lib/Serialization/ASTWriter.cpp test/PCH/chain-implicit-definition.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Sun Apr 24 09:28:06 PDT 2011


Author: cornedbee
Date: Sun Apr 24 11:28:06 2011
New Revision: 130103

URL: http://llvm.org/viewvc/llvm-project?rev=130103&view=rev
Log:
Synthesizing the definition of an implicit member is an AST modification, so notify any mutation listeners of it. This fixes a crasher in chained PCH, where an implicit destructor in a PCH gets a definition in a chained PCH, which is then lost. However, any further use of the destructor would cause its definition to be regenerated in the final file, hiding the bug.

Added:
    cfe/trunk/test/PCH/chain-implicit-definition.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTConsumer.h
    cfe/trunk/include/clang/AST/ASTMutationListener.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp

Modified: cfe/trunk/include/clang/AST/ASTConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTConsumer.h?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTConsumer.h (original)
+++ cfe/trunk/include/clang/AST/ASTConsumer.h Sun Apr 24 11:28:06 2011
@@ -89,7 +89,7 @@
 
   /// \brief If the consumer is interested in entities getting modified after
   /// their initial creation, it should return a pointer to
-  /// a GetASTMutationListener here.
+  /// an ASTMutationListener here.
   virtual ASTMutationListener *GetASTMutationListener() { return 0; }
 
   /// \brief If the consumer is interested in entities being deserialized from

Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)
+++ cfe/trunk/include/clang/AST/ASTMutationListener.h Sun Apr 24 11:28:06 2011
@@ -48,6 +48,9 @@
   /// template declaration.
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D) {}
+
+  /// \brief An implicit member got a definition.
+  virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
 };
 
 } // end namespace clang

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun Apr 24 11:28:06 2011
@@ -43,6 +43,7 @@
   class ADLResult;
   class ASTConsumer;
   class ASTContext;
+  class ASTMutationListener;
   class ArrayType;
   class AttributeList;
   class BlockDecl;
@@ -657,6 +658,7 @@
   Preprocessor &getPreprocessor() const { return PP; }
   ASTContext &getASTContext() const { return Context; }
   ASTConsumer &getASTConsumer() const { return Consumer; }
+  ASTMutationListener *getASTMutationListener() const;
   
   /// \brief Helper class that creates diagnostics with optional
   /// template instantiation stacks.

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Sun Apr 24 11:28:06 2011
@@ -588,6 +588,7 @@
                                     const ClassTemplateSpecializationDecl *D);
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D);
+  virtual void CompletedImplicitDefinition(const FunctionDecl *D);
 };
 
 /// \brief AST and semantic-analysis consumer that generates a

Modified: cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/MultiplexConsumer.cpp (original)
+++ cfe/trunk/lib/Frontend/MultiplexConsumer.cpp Sun Apr 24 11:28:06 2011
@@ -97,6 +97,7 @@
                                     const ClassTemplateSpecializationDecl *D);
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D);
+  virtual void CompletedImplicitDefinition(const FunctionDecl *D);
 private:
   std::vector<ASTMutationListener*> Listeners;
 };
@@ -132,6 +133,11 @@
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
     Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
 }
+void MultiplexASTMutationListener::CompletedImplicitDefinition(
+                                                        const FunctionDecl *D) {
+  for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+    Listeners[i]->CompletedImplicitDefinition(D);
+}
 
 }  // end namespace clang
 

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Sun Apr 24 11:28:06 2011
@@ -201,6 +201,10 @@
     ExternalSema->ForgetSema();
 }
 
+ASTMutationListener *Sema::getASTMutationListener() const {
+  return getASTConsumer().GetASTMutationListener();
+}
+
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
 /// If there is already an implicit cast, merge into the existing one.
 /// The result is of the given category.

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Apr 24 11:28:06 2011
@@ -18,6 +18,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclVisitor.h"
@@ -4969,6 +4970,10 @@
 
   Constructor->setUsed();
   MarkVTableUsed(CurrentLocation, ClassDecl);
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(Constructor);
+  }
 }
 
 void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
@@ -5254,6 +5259,10 @@
 
   Destructor->setUsed();
   MarkVTableUsed(CurrentLocation, ClassDecl);
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(Destructor);
+  }
 }
 
 /// \brief Builds a statement that copies the given entity from \p From to
@@ -5913,6 +5922,10 @@
                                             /*isStmtExpr=*/false);
   assert(!Body.isInvalid() && "Compound statement creation cannot fail");
   CopyAssignOperator->setBody(Body.takeAs<Stmt>());
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(CopyAssignOperator);
+  }
 }
 
 CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
@@ -6113,6 +6126,10 @@
   }
   
   CopyConstructor->setUsed();
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(CopyConstructor);
+  }
 }
 
 ExprResult

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=130103&r1=130102&r2=130103&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sun Apr 24 11:28:06 2011
@@ -3955,4 +3955,13 @@
   AddDeclRef(D, Record);
 }
 
+void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
+  if (D->getPCHLevel() == 0)
+    return; // Declaration not imported from PCH.
+
+  // Implicit decl from a PCH was defined.
+  // FIXME: Should implicit definition be a separate FunctionDecl?
+  RewriteDecl(D);
+}
+
 ASTSerializationListener::~ASTSerializationListener() { }

Added: cfe/trunk/test/PCH/chain-implicit-definition.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-implicit-definition.cpp?rev=130103&view=auto
==============================================================================
--- cfe/trunk/test/PCH/chain-implicit-definition.cpp (added)
+++ cfe/trunk/test/PCH/chain-implicit-definition.cpp Sun Apr 24 11:28:06 2011
@@ -0,0 +1,39 @@
+// no PCH
+// RUN: %clang_cc1 -emit-llvm -o /dev/null -include %s -include %s %s
+// with PCH
+// RUN: %clang_cc1 -emit-llvm -o /dev/null -chain-include %s -chain-include %s %s
+#if !defined(PASS1)
+#define PASS1
+
+// A base with a virtual dtor.
+struct A {
+  virtual ~A();
+};
+
+// A derived class with an implicit virtual dtor.
+struct B : A {
+  // Key function to suppress vtable definition.
+  virtual void virt();
+};
+
+#elif !defined(PASS2)
+#define PASS2
+
+// Further derived class that requires ~B().
+// Causes definition of ~B(), but it was lost when saving PCH.
+struct C : B {
+  C();
+  ~C() {}
+};
+
+#else
+
+void foo() {
+  // Variable that requires ~C().
+  C c;
+}
+
+// VTable placement would again cause definition of ~B(), hiding the bug,
+// if not for B::virt(), which suppresses the placement.
+
+#endif





More information about the cfe-commits mailing list