[cfe-commits] r153254 - in /cfe/trunk: include/clang/AST/DeclBase.h include/clang/Serialization/ASTReader.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriterDecl.cpp test/PCH/chain-class-extension.m

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Mar 22 09:08:06 PDT 2012


Author: akirtzidis
Date: Thu Mar 22 11:08:04 2012
New Revision: 153254

URL: http://llvm.org/viewvc/llvm-project?rev=153254&view=rev
Log:
[PCH] When we are replacing a decl in a chained PCH that is also a DeclContext,
make sure to fully load its external lexical and visible declarations before
re-writing it.

rdar://10914192

Added:
    cfe/trunk/test/PCH/chain-class-extension.m
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=153254&r1=153253&r2=153254&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Mar 22 11:08:04 2012
@@ -967,6 +967,7 @@
   mutable Decl *LastDecl;
 
   friend class ExternalASTSource;
+  friend class ASTWriter;
 
   /// \brief Build up a chain of declarations.
   ///

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=153254&r1=153253&r2=153254&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Mar 22 11:08:04 2012
@@ -1466,6 +1466,9 @@
   void LoadMacroDefinition(
                      llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos);
 
+  /// \brief Load all external visible decls in the given DeclContext.
+  void completeVisibleDeclsMap(DeclContext *DC);
+
   /// \brief Retrieve the AST context that this AST reader supplements.
   ASTContext &getContext() { return Context; }
 

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=153254&r1=153253&r2=153254&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Mar 22 11:08:04 2012
@@ -4972,6 +4972,51 @@
   return const_cast<DeclContext*>(DC)->lookup(Name);
 }
 
+namespace {
+  /// \brief ModuleFile visitor used to complete the visible decls map of a
+  /// declaration context.
+  class DeclContextVisibleDeclMapVisitor {
+    ASTReader &Reader;
+    DeclContext *DC;
+
+  public:
+    DeclContextVisibleDeclMapVisitor(ASTReader &Reader, DeclContext *DC)
+      : Reader(Reader), DC(DC) { }
+
+    static bool visit(ModuleFile &M, void *UserData) {
+      return static_cast<DeclContextVisibleDeclMapVisitor*>(UserData)->visit(M);
+    }
+
+    bool visit(ModuleFile &M) {
+      // Check whether we have any visible declaration information for
+      // this context in this module.
+      ModuleFile::DeclContextInfosMap::iterator
+        Info = M.DeclContextInfos.find(DC);
+      if (Info == M.DeclContextInfos.end() || 
+          !Info->second.NameLookupTableData)
+        return false;
+      
+      // Look for this name within this module.
+      ASTDeclContextNameLookupTable *LookupTable =
+        (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData;
+      for (ASTDeclContextNameLookupTable::key_iterator
+             I = LookupTable->key_begin(),
+             E = LookupTable->key_end(); I != E; ++I) {
+        DC->lookup(*I); // Force loading of the visible decls for the decl name.
+      }
+
+      return false;
+    }
+  };
+}
+
+void ASTReader::completeVisibleDeclsMap(DeclContext *DC) {
+  if (!DC->hasExternalVisibleStorage())
+    return;
+  DeclContextVisibleDeclMapVisitor Visitor(*this, DC);
+  ModuleMgr.visit(&DeclContextVisibleDeclMapVisitor::visit, &Visitor);
+}
+
 /// \brief Under non-PCH compilation the consumer receives the objc methods
 /// before receiving the implementation, and codegen depends on this.
 /// We simulate this by deserializing and passing to consumer the methods of the

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=153254&r1=153253&r2=153254&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Mar 22 11:08:04 2012
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ASTReader.h"
 #include "ASTCommon.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/DeclCXX.h"
@@ -1640,6 +1641,20 @@
   RecordData Record;
   ASTDeclWriter W(*this, Context, Record);
 
+  // Determine the ID for this declaration.
+  serialization::DeclID ID;
+  if (D->isFromASTFile())
+    ID = getDeclID(D);
+  else {
+    serialization::DeclID &IDR = DeclIDs[D];
+    if (IDR == 0)
+      IDR = NextDeclID++;
+    
+    ID= IDR;
+  }
+
+  bool isReplacingADecl = ID < FirstDeclID;
+
   // If this declaration is also a DeclContext, write blocks for the
   // declarations that lexically stored inside its context and those
   // declarations that are visible from its context. These blocks
@@ -1649,23 +1664,19 @@
   uint64_t VisibleOffset = 0;
   DeclContext *DC = dyn_cast<DeclContext>(D);
   if (DC) {
+    if (isReplacingADecl) {
+      // It is replacing a decl from a chained PCH; make sure that the
+      // DeclContext is fully loaded.
+      if (DC->hasExternalLexicalStorage())
+        DC->LoadLexicalDeclsFromExternalStorage();
+      if (DC->hasExternalVisibleStorage())
+        Chain->completeVisibleDeclsMap(DC);
+    }
     LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
     VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
   }
-
-  // Determine the ID for this declaration.
-  serialization::DeclID ID;
-  if (D->isFromASTFile())
-    ID = getDeclID(D);
-  else {
-    serialization::DeclID &IDR = DeclIDs[D];
-    if (IDR == 0)
-      IDR = NextDeclID++;
-    
-    ID= IDR;
-  }
   
-  if (ID < FirstDeclID) {
+  if (isReplacingADecl) {
     // We're replacing a decl in a previous file.
     ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(),
                                              D->getLocation()));

Added: cfe/trunk/test/PCH/chain-class-extension.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-class-extension.m?rev=153254&view=auto
==============================================================================
--- cfe/trunk/test/PCH/chain-class-extension.m (added)
+++ cfe/trunk/test/PCH/chain-class-extension.m Thu Mar 22 11:08:04 2012
@@ -0,0 +1,42 @@
+// Without PCH
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin10 -fobjc-arc %s -include %s -include %s
+
+// With PCH
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin10 -fobjc-arc %s -chain-include %s -chain-include %s
+
+#ifndef HEADER1
+#define HEADER1
+//===----------------------------------------------------------------------===//
+// Primary header
+
+ at interface I
++(void)meth;
+ at end
+
+//===----------------------------------------------------------------------===//
+#elif !defined(HEADER2)
+#define HEADER2
+#if !defined(HEADER1)
+#error Header inclusion order messed up
+#endif
+
+//===----------------------------------------------------------------------===//
+// Dependent header
+
+ at interface I()
+ at property (assign) id prop;
++(void)meth2;
+ at end
+
+//===----------------------------------------------------------------------===//
+#else
+//===----------------------------------------------------------------------===//
+
+void foo(I *i) {
+  [I meth];
+  [I meth2];
+  i.prop = 0;
+}
+
+//===----------------------------------------------------------------------===//
+#endif





More information about the cfe-commits mailing list