forked from OSchip/llvm-project
Read/write in PCH Sema's StdNamespace and StdBadAlloc and use a LazyDeclPtr for them that will deserialize them when needed.
llvm-svn: 110031
This commit is contained in:
parent
4f8e17379d
commit
2d68810caf
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
// Header for PCH test cxx-typeid.cpp
|
||||
|
||||
#include <typeinfo>
|
Loading…
Reference in New Issue