]> granicus.if.org Git - clang/commitdiff
Read/write in PCH Sema's StdNamespace and StdBadAlloc and use a LazyDeclPtr for them...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 2 Aug 2010 07:14:54 +0000 (07:14 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 2 Aug 2010 07:14:54 +0000 (07:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110031 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/AST/ExternalASTSource.h
include/clang/Frontend/PCHBitCodes.h
include/clang/Frontend/PCHReader.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
test/PCH/cxx-typeid.cpp [new file with mode: 0644]
test/PCH/cxx-typeid.h [new file with mode: 0644]

index 4a6377eaa95b4ca03e39ce8d633ad531370b1626..d23e75dd3810d2a74819f72692af5d361d7cfb57 100644 (file)
@@ -172,7 +172,7 @@ protected:
 /// The AST node is identified within the external AST source by a
 /// 63-bit offset, and can be retrieved via an operation on the
 /// external AST source itself.
-template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)>
+template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
 struct LazyOffsetPtr {
   /// \brief Either a pointer to an AST node or the offset within the
   /// external AST source where the AST node can be found.
@@ -230,9 +230,13 @@ public:
 };
 
 /// \brief A lazy pointer to a statement.
-typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt>
+typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
   LazyDeclStmtPtr;
 
+/// \brief A lazy pointer to a declaration.
+typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
+  LazyDeclPtr;
+
 } // end namespace clang
 
 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
index 774a96becb98a85d77b17e96238010637b1123bc..109a78bd8849e822117b5e5fc2ac0713dceee0f8 100644 (file)
@@ -243,7 +243,10 @@ namespace clang {
 
       /// \brief Record code for an update to the TU's lexically contained
       /// declarations.
-      TU_UPDATE_LEXICAL = 28
+      TU_UPDATE_LEXICAL = 28,
+
+      /// \brief Record code for declarations that Sema keeps references of.
+      SEMA_DECL_REFS = 29
     };
 
     /// \brief Record types used within a source manager block.
index 57af01033a5d89f48d8bb74d0428f4571bb04a12..87c7624be09ea5e8782de02aafc4a0ffb59bfe12 100644 (file)
@@ -391,6 +391,9 @@ private:
   /// \brief The set of dynamic CXXRecord declarations stored in the PCH file.
   llvm::SmallVector<uint64_t, 16> DynamicClasses;
 
+  /// \brief The set of Sema declaration references, stored in PCH.
+  llvm::SmallVector<uint64_t, 4> SemaDeclRefs;
+
   /// \brief The set of Objective-C category definitions stored in the
   /// the PCH file.
   llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
index 5a239e4f045b12ee0d7b4cd9050be74cd08cc6ab..0502e674a9d9fc1a850a1add3d11b7a80f61079c 100644 (file)
@@ -1728,6 +1728,14 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
       DynamicClasses.swap(Record);
       break;
 
+    case pch::SEMA_DECL_REFS:
+      if (!SemaDeclRefs.empty()) {
+        Error("duplicate SEMA_DECL_REFS record in PCH file");
+        return Failure;
+      }
+      SemaDeclRefs.swap(Record);
+      break;
+
     case pch::ORIGINAL_FILE_NAME:
       // The primary PCH will be the last to get here, so it will be the one
       // that's used.
@@ -3152,6 +3160,14 @@ void PCHReader::InitializeSema(Sema &S) {
     SemaObj->DynamicClasses.push_back(
                                cast<CXXRecordDecl>(GetDecl(DynamicClasses[I])));
 
+  // Load the offsets of the declarations that Sema references.
+  // They will be lazily deserialized when needed.
+  if (!SemaDeclRefs.empty()) {
+    assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
+    SemaObj->StdNamespace = SemaDeclRefs[0];
+    SemaObj->StdBadAlloc = SemaDeclRefs[1];
+  }
+
   // If there are @selector references added them to its pool. This is for
   // implementation of -Wselector.
   PerFileData &F = *Chain[0];
index a72f7cfea8950808844534d1478e7dd1c1323798..8bf85efd62b47b1d4585a5b6b0f4f8117f1ea62c 100644 (file)
@@ -2243,6 +2243,13 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
     AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
 
+  // Build a record containing some declaration references.
+  RecordData SemaDeclRefs;
+  if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
+    AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
+    AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
+  }
+
   // Write the remaining PCH contents.
   RecordData Record;
   Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5);
@@ -2323,6 +2330,10 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   if (!DynamicClasses.empty())
     Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses);
 
+  // Write the record containing declaration references of Sema.
+  if (!SemaDeclRefs.empty())
+    Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs);
+
   // Some simple statistics
   Record.clear();
   Record.push_back(NumStatements);
index a9a4f5290cf9330f48a7be646b18e683888ca857..a42c6e804cf880dd1b7855d47a9636c85866fed8 100644 (file)
@@ -127,8 +127,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
     PackContext(0), TopFunctionScope(0), ParsingDeclDepth(0),
-    IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
-    GlobalNewDeleteDeclared(false), 
+    IdResolver(pp.getLangOptions()), GlobalNewDeleteDeclared(false), 
     CompleteTranslationUnit(CompleteTranslationUnit),
     NumSFINAEErrors(0), SuppressAccessChecking(false),
     NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0),
index 336dfa3763ee17b54144ede845a50102c471c8dd..85627b02b9d352628aa21914fa04af266a1e6434 100644 (file)
@@ -523,11 +523,11 @@ public:
   Scope *TUScope;
 
   /// \brief The C++ "std" namespace, where the standard library resides.
-  NamespaceDecl *StdNamespace;
+  LazyDeclPtr StdNamespace;
 
   /// \brief The C++ "std::bad_alloc" class, which is defined by the C++
   /// standard library.
-  CXXRecordDecl *StdBadAlloc;
+  LazyDeclPtr StdBadAlloc;
 
   /// A flag to remember whether the implicit forms of operator new and delete
   /// have been declared.
@@ -2167,7 +2167,17 @@ public:
                                            AttributeList *AttrList);
   virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace);
 
+  NamespaceDecl *getStdNamespace() const {
+    return cast_or_null<NamespaceDecl>(
+                                 StdNamespace.get(Context.getExternalSource()));
+  }
   NamespaceDecl *getOrCreateStdNamespace();
+
+  CXXRecordDecl *getStdBadAlloc() const {
+    return cast_or_null<CXXRecordDecl>(
+                                  StdBadAlloc.get(Context.getExternalSource()));
+  }
+
   virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
                                         SourceLocation UsingLoc,
                                         SourceLocation NamespcLoc,
index 71572d89b6cc5e5d9a72d55113f74ac876bc785b..8a656bcf16f353d5564151bbd95dce666513b232 100644 (file)
@@ -5182,7 +5182,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
   }
 
   if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
-      DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) {
+      DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) {
     // This is a declaration of or a reference to "std::bad_alloc".
     isStdBadAlloc = true;
     
@@ -5190,7 +5190,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
       // std::bad_alloc has been implicitly declared (but made invisible to
       // name lookup). Fill in this implicit declaration as the previous 
       // declaration, so that the declarations get chained appropriately.
-      Previous.addDecl(StdBadAlloc);
+      Previous.addDecl(getStdBadAlloc());
     }
   }
 
@@ -5481,7 +5481,7 @@ CreateNewDecl:
       New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
                                   cast_or_null<CXXRecordDecl>(PrevDecl));
       
-      if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit()))
+      if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit()))
         StdBadAlloc = cast<CXXRecordDecl>(New);
     } else
       New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
index cf6e354f3c4d56fd0d72ebc5e431530f57ce06e2..a0bc5840cdb4052936ca5d3f0361d3bcd6028f09 100644 (file)
@@ -3213,12 +3213,12 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
                CurContext->getLookupContext()->isTranslationUnit()) {
       // This is the first "real" definition of the namespace "std", so update
       // our cache of the "std" namespace to point at this definition.
-      if (StdNamespace) {
+      if (NamespaceDecl *StdNS = getStdNamespace()) {
         // We had already defined a dummy namespace "std". Link this new 
         // namespace definition to the dummy namespace "std".
-        StdNamespace->setNextNamespace(Namespc);
-        StdNamespace->setLocation(IdentLoc);
-        Namespc->setOriginalNamespace(StdNamespace->getOriginalNamespace());
+        StdNS->setNextNamespace(Namespc);
+        StdNS->setLocation(IdentLoc);
+        Namespc->setOriginalNamespace(StdNS->getOriginalNamespace());
       }
       
       // Make our StdNamespace cache point at the first real definition of the
@@ -3320,10 +3320,10 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
                                          Context.getTranslationUnitDecl(),
                                          SourceLocation(),
                                          &PP.getIdentifierTable().get("std"));
-    StdNamespace->setImplicit(true);
+    getStdNamespace()->setImplicit(true);
   }
   
-  return StdNamespace;
+  return getStdNamespace();
 }
 
 Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
index d607afac1665ae105870f4258bbbac909a49b2e6..8b2fc7e56a1ede4adb6d8ea9942204e8227add76 100644 (file)
@@ -343,7 +343,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
 
   IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
   LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
-  LookupQualifiedName(R, StdNamespace);
+  LookupQualifiedName(R, getStdNamespace());
   RecordDecl *TypeInfoRecordDecl = R.getAsSingle<RecordDecl>();
   if (!TypeInfoRecordDecl)
     return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
@@ -1203,7 +1203,7 @@ void Sema::DeclareGlobalNewDelete() {
                                         SourceLocation(), 
                                       &PP.getIdentifierTable().get("bad_alloc"), 
                                         SourceLocation(), 0);
-    StdBadAlloc->setImplicit(true);
+    getStdBadAlloc()->setImplicit(true);
   }
   
   GlobalNewDeleteDeclared = true;
@@ -1257,7 +1257,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
        Name.getCXXOverloadedOperator() == OO_Array_New);
   if (HasBadAllocExceptionSpec) {
     assert(StdBadAlloc && "Must have std::bad_alloc declared");
-    BadAllocType = Context.getTypeDeclType(StdBadAlloc);
+    BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
   }
   
   QualType FnType = Context.getFunctionType(Return, &Argument, 1, false, 0,
diff --git a/test/PCH/cxx-typeid.cpp b/test/PCH/cxx-typeid.cpp
new file mode 100644 (file)
index 0000000..164b4ba
--- /dev/null
@@ -0,0 +1,9 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/cxx-typeid.h -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-typeid.h
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s 
+
+void f() {
+    (void)typeid(int);
+}
diff --git a/test/PCH/cxx-typeid.h b/test/PCH/cxx-typeid.h
new file mode 100644 (file)
index 0000000..aa3b16a
--- /dev/null
@@ -0,0 +1,3 @@
+// Header for PCH test cxx-typeid.cpp
+
+#include <typeinfo>