r182544 - Fix bitcode desynchronization when loading a PCH containing a class template

Richard Smith richard-llvm at metafoo.co.uk
Wed May 22 18:49:11 PDT 2013


Author: rsmith
Date: Wed May 22 20:49:11 2013
New Revision: 182544

URL: http://llvm.org/viewvc/llvm-project?rev=182544&view=rev
Log:
Fix bitcode desynchronization when loading a PCH containing a class template
specialization with modules enabled. Just don't merge them at all for now;
we'll revisit this when support for template merging is added.

In passing, make Decl::dump() a little safer to use with PCH/modules, by making
it not deserialize any additional declarations. From a debugger you can call
decls_begin() or similar first if you want to dump all child decls.

Modified:
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/PCH/chain-cxx.cpp
    cfe/trunk/test/PCH/chain-friend-instantiation.cpp

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=182544&r1=182543&r2=182544&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Wed May 22 20:49:11 2013
@@ -62,6 +62,9 @@ namespace  {
   // Null statements
   static const TerminalColor NullColor = { raw_ostream::BLUE, false };
 
+  // Undeserialized entities
+  static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true };
+
   // CastKind from CastExpr's
   static const TerminalColor CastColor = { raw_ostream::RED, false };
 
@@ -477,20 +480,28 @@ bool ASTDumper::hasNodes(const DeclConte
   if (!DC)
     return false;
 
-  return DC->decls_begin() != DC->decls_end();
+  return DC->hasExternalLexicalStorage() ||
+         DC->noload_decls_begin() != DC->noload_decls_end();
 }
 
 void ASTDumper::dumpDeclContext(const DeclContext *DC) {
   if (!DC)
     return;
-  for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+  bool HasUndeserializedDecls = DC->hasExternalLexicalStorage();
+  for (DeclContext::decl_iterator I = DC->noload_decls_begin(), E = DC->noload_decls_end();
        I != E; ++I) {
     DeclContext::decl_iterator Next = I;
     ++Next;
-    if (Next == E)
+    if (Next == E && !HasUndeserializedDecls)
       lastChild();
     dumpDecl(*I);
   }
+  if (HasUndeserializedDecls) {
+    lastChild();
+    IndentScope Indent(*this);
+    ColorScope Color(*this, UndeserializedColor);
+    OS << "<undeserialized declarations>";
+  }
 }
 
 void ASTDumper::dumpAttr(const Attr *A) {

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=182544&r1=182543&r2=182544&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed May 22 20:49:11 2013
@@ -223,12 +223,18 @@ namespace clang {
     void VisitTypedefDecl(TypedefDecl *TD);
     void VisitTypeAliasDecl(TypeAliasDecl *TD);
     void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-    void VisitTagDecl(TagDecl *TD);
+    RedeclarableResult VisitTagDecl(TagDecl *TD);
     void VisitEnumDecl(EnumDecl *ED);
-    void VisitRecordDecl(RecordDecl *RD);
-    void VisitCXXRecordDecl(CXXRecordDecl *D);
-    void VisitClassTemplateSpecializationDecl(
+    RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
+    void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); }
+    RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D);
+    void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
+    RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
                                             ClassTemplateSpecializationDecl *D);
+    void VisitClassTemplateSpecializationDecl(
+        ClassTemplateSpecializationDecl *D) {
+      VisitClassTemplateSpecializationDeclImpl(D);
+    }
     void VisitClassTemplatePartialSpecializationDecl(
                                      ClassTemplatePartialSpecializationDecl *D);
     void VisitClassScopeFunctionSpecializationDecl(
@@ -424,7 +430,7 @@ void ASTDeclReader::VisitTypeAliasDecl(T
   VisitTypedefNameDecl(TD);
 }
 
-void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
+ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
   RedeclarableResult Redecl = VisitRedeclarable(TD);
   VisitTypeDecl(TD);
   
@@ -442,7 +448,8 @@ void ASTDeclReader::VisitTagDecl(TagDecl
   } else
     TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx));
 
-  mergeRedeclarable(TD, Redecl);  
+  mergeRedeclarable(TD, Redecl);
+  return Redecl;
 }
 
 void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
@@ -466,12 +473,14 @@ void ASTDeclReader::VisitEnumDecl(EnumDe
   }
 }
 
-void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
-  VisitTagDecl(RD);
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
+  RedeclarableResult Redecl = VisitTagDecl(RD);
   RD->setHasFlexibleArrayMember(Record[Idx++]);
   RD->setAnonymousStructOrUnion(Record[Idx++]);
   RD->setHasObjectMember(Record[Idx++]);
   RD->setHasVolatileMember(Record[Idx++]);
+  return Redecl;
 }
 
 void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
@@ -1022,6 +1031,7 @@ void ASTDeclReader::VisitNamespaceDecl(N
   D->setInline(Record[Idx++]);
   D->LocStart = ReadSourceLocation(Record, Idx);
   D->RBraceLoc = ReadSourceLocation(Record, Idx);
+  // FIXME: At the point of this call, D->getCanonicalDecl() returns 0.
   mergeRedeclarable(D, Redecl);
 
   if (Redecl.getFirstID() == ThisDeclID) {
@@ -1180,8 +1190,9 @@ void ASTDeclReader::ReadCXXDefinitionDat
   }
 }
 
-void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
-  VisitRecordDecl(D);
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
+  RedeclarableResult Redecl = VisitRecordDeclImpl(D);
 
   ASTContext &C = Reader.getContext();
   if (Record[Idx++]) {
@@ -1236,6 +1247,8 @@ void ASTDeclReader::VisitCXXRecordDecl(C
     if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx))
       C.KeyFunctions[D] = Key;
   }
+
+  return Redecl;
 }
 
 void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -1391,9 +1404,10 @@ void ASTDeclReader::VisitClassTemplateDe
   }
 }
 
-void ASTDeclReader::VisitClassTemplateSpecializationDecl(
-                                           ClassTemplateSpecializationDecl *D) {
-  VisitCXXRecordDecl(D);
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
+    ClassTemplateSpecializationDecl *D) {
+  RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D);
   
   ASTContext &C = Reader.getContext();
   if (Decl *InstD = ReadDecl(Record, Idx)) {
@@ -1444,11 +1458,13 @@ void ASTDeclReader::VisitClassTemplateSp
       }
     }
   }
+
+  return Redecl;
 }
 
 void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
                                     ClassTemplatePartialSpecializationDecl *D) {
-  VisitClassTemplateSpecializationDecl(D);
+  RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
 
   ASTContext &C = Reader.getContext();
   D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
@@ -1464,7 +1480,7 @@ void ASTDeclReader::VisitClassTemplatePa
   D->SequenceNumber = Record[Idx++];
 
   // These are read/set from/to the first declaration.
-  if (D->getPreviousDecl() == 0) {
+  if (ThisDeclID == Redecl.getFirstID()) {
     D->InstantiatedFromMember.setPointer(
       ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx));
     D->InstantiatedFromMember.setInt(Record[Idx++]);
@@ -1780,6 +1796,13 @@ static bool isSameEntity(NamedDecl *X, N
   // Objective-C classes and protocols with the same name always match.
   if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
     return true;
+
+  if (isa<ClassTemplateSpecializationDecl>(X)) {
+    // FIXME: Deal with merging of template specializations.
+    // For now, don't merge these; we need to check more than just the name to
+    // determine if they refer to the same entity.
+    return false;
+  }
   
   // Compatible tags match.
   if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {

Modified: cfe/trunk/test/PCH/chain-cxx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-cxx.cpp?rev=182544&r1=182543&r2=182544&view=diff
==============================================================================
--- cfe/trunk/test/PCH/chain-cxx.cpp (original)
+++ cfe/trunk/test/PCH/chain-cxx.cpp Wed May 22 20:49:11 2013
@@ -6,6 +6,9 @@
 // With PCH
 // RUN: %clang_cc1 -fsyntax-only -verify %s -chain-include %s -chain-include %s
 
+// With modules
+// RUN: %clang_cc1 -fsyntax-only -verify -fmodules %s -chain-include %s -chain-include %s
+
 // expected-no-diagnostics
 
 #ifndef HEADER1

Modified: cfe/trunk/test/PCH/chain-friend-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-friend-instantiation.cpp?rev=182544&r1=182543&r2=182544&view=diff
==============================================================================
--- cfe/trunk/test/PCH/chain-friend-instantiation.cpp (original)
+++ cfe/trunk/test/PCH/chain-friend-instantiation.cpp Wed May 22 20:49:11 2013
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -ast-print -o - -chain-include %s -chain-include %s
+// RUN: %clang_cc1 %s -ast-print -o - -fmodules -chain-include %s -chain-include %s
 
 #if !defined(PASS1)
 #define PASS1





More information about the cfe-commits mailing list