diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 14 | ||||
-rw-r--r-- | include/clang/AST/Builtins.h | 5 | ||||
-rw-r--r-- | include/clang/Frontend/PCHWriter.h | 4 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 12 | ||||
-rw-r--r-- | lib/AST/Builtins.cpp | 18 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 31 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 28 | ||||
-rw-r--r-- | tools/clang-cc/clang-cc.cpp | 9 |
8 files changed, 105 insertions, 16 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2be3689bc0..bba9cfb400 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -170,6 +170,8 @@ public: /// This is intentionally not serialized. It is populated by the /// ASTContext ctor, and there are no external pointers/references to /// internal variables of BuiltinInfo. + // FIXME: PCH does serialize this information, so that we don't have to + // construct it again when the PCH is loaded. Builtin::Context BuiltinInfo; // Builtin Types. @@ -188,10 +190,20 @@ public: ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, - bool FreeMemory = true, unsigned size_reserve=0); + bool FreeMemory = true, unsigned size_reserve=0, + bool InitializeBuiltins = true); ~ASTContext(); + /// \brief Initialize builtins. + /// + /// Typically, this routine will be called automatically by the + /// constructor. However, in certain cases (e.g., when there is a + /// PCH file to be loaded), the constructor does not perform + /// initialization for builtins. This routine can be called to + /// perform the initialization. + void InitializeBuiltins(IdentifierTable &idents); + /// \brief Attach an external AST source to the AST context. /// /// The external AST source provides the ability to load parts of diff --git a/include/clang/AST/Builtins.h b/include/clang/AST/Builtins.h index 9216029860..b16d3bf341 100644 --- a/include/clang/AST/Builtins.h +++ b/include/clang/AST/Builtins.h @@ -17,6 +17,7 @@ #include <cstring> #include <string> +#include "llvm/ADT/SmallVector.h" namespace clang { class TargetInfo; @@ -60,6 +61,10 @@ public: /// appropriate builtin ID # and mark any non-portable builtin identifiers as /// such. void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false); + + /// \brief Popular the vector with the names of all of the builtins. + void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, + bool NoBuiltins); /// Builtin::GetName - Return the identifier name for the specified builtin, /// e.g. "__builtin_abs". diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 2db253e7dd..d721f1077f 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -171,6 +171,10 @@ public: /// \brief Emit a reference to an identifier void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record); + /// \brief Get the unique number used to refer to the given + /// identifier. + pch::IdentID getIdentifierRef(const IdentifierInfo *II); + /// \brief Retrieve the offset of the macro definition for the given /// identifier. /// diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7d3c119d57..159110a080 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -34,16 +34,17 @@ enum FloatingRank { ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, - bool FreeMem, unsigned size_reserve) : + bool FreeMem, unsigned size_reserve, + bool InitializeBuiltins) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), ExternalSource(0) { if (size_reserve > 0) Types.reserve(size_reserve); InitBuiltinTypes(); - BuiltinInfo.InitializeTargetBuiltins(Target); - BuiltinInfo.InitializeBuiltins(idents, LangOpts.NoBuiltin); TUDecl = TranslationUnitDecl::Create(*this); + if (InitializeBuiltins) + this->InitializeBuiltins(idents); } ASTContext::~ASTContext() { @@ -94,6 +95,11 @@ ASTContext::~ASTContext() { TUDecl->Destroy(*this); } +void ASTContext::InitializeBuiltins(IdentifierTable &idents) { + BuiltinInfo.InitializeTargetBuiltins(Target); + BuiltinInfo.InitializeBuiltins(idents, LangOpts.NoBuiltin); +} + void ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) { ExternalSource.reset(Source.take()); diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index ece9eeed76..3e1b3dc2a1 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -58,6 +58,24 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); } +void +Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, + bool NoBuiltins) { + // Final all target-independent names + for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) + if (!BuiltinInfo[i].Suppressed && + (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f'))) + Names.push_back(BuiltinInfo[i].Name); + + // Find target-specific names. + for (unsigned i = 0, e = NumTSRecords; i != e; ++i) + if (!TSRecords[i].Suppressed && + (!NoBuiltins || + (TSRecords[i].Attributes && + !strchr(TSRecords[i].Attributes, 'f')))) + Names.push_back(TSRecords[i].Name); +} + bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg) { diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 031b71fbac..976b98dd11 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1110,10 +1110,21 @@ public: unsigned DataLen) { using namespace clang::io; uint32_t Bits = ReadUnalignedLE32(d); // FIXME: use these? - (void)Bits; - bool hasMacroDefinition = (Bits >> 3) & 0x01; - + bool CPlusPlusOperatorKeyword = Bits & 0x01; + Bits >>= 1; + bool Poisoned = Bits & 0x01; + Bits >>= 1; + bool ExtensionToken = Bits & 0x01; + Bits >>= 1; + bool hasMacroDefinition = Bits & 0x01; + Bits >>= 1; + unsigned ObjCOrBuiltinID = Bits & 0x3FF; + Bits >>= 10; + unsigned TokenID = Bits & 0xFF; + Bits >>= 8; + pch::IdentID ID = ReadUnalignedLE32(d); + assert(Bits == 0 && "Extra bits in the identifier?"); DataLen -= 8; // Build the IdentifierInfo itself and link the identifier ID with @@ -1124,6 +1135,20 @@ public: k.first, k.first + k.second); Reader.SetIdentifierInfo(ID, II); + // Set or check the various bits in the IdentifierInfo structure. + // FIXME: Load token IDs lazily, too? + assert((unsigned)II->getTokenID() == TokenID && + "Incorrect token ID loaded"); + (void)TokenID; + II->setObjCOrBuiltinID(ObjCOrBuiltinID); + assert(II->isExtensionToken() == ExtensionToken && + "Incorrect extension token flag"); + (void)ExtensionToken; + II->setIsPoisoned(Poisoned); + assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword && + "Incorrect C++ operator keyword flag"); + (void)CPlusPlusOperatorKeyword; + // If this identifier is a macro, deserialize the macro // definition. if (hasMacroDefinition) { diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index f34323c160..15ee2369dd 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1800,8 +1800,8 @@ public: II->hasMacroDefinition() && !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro(); Bits = Bits | (uint32_t)II->getTokenID(); - Bits = (Bits << 8) | (uint32_t)II->getObjCOrBuiltinID(); - Bits = (Bits << 10) | hasMacroDefinition; + Bits = (Bits << 10) | (uint32_t)II->getObjCOrBuiltinID(); + Bits = (Bits << 1) | hasMacroDefinition; Bits = (Bits << 1) | II->isExtensionToken(); Bits = (Bits << 1) | II->isPoisoned(); Bits = (Bits << 1) | II->isCPlusPlusOperatorKeyword(); @@ -2028,6 +2028,17 @@ void PCHWriter::WritePCH(Sema &SemaRef) { DeclIDs[Context.getTranslationUnitDecl()] = 1; DeclsToEmit.push(Context.getTranslationUnitDecl()); + // Make sure that we emit IdentifierInfos (and any attached + // declarations) for builtins. + { + IdentifierTable &Table = PP.getIdentifierTable(); + llvm::SmallVector<const char *, 32> BuiltinNames; + Context.BuiltinInfo.GetBuiltinNames(BuiltinNames, + Context.getLangOptions().NoBuiltin); + for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) + getIdentifierRef(&Table.get(BuiltinNames[I])); + } + // Write the remaining PCH contents. RecordData Record; Stream.EnterSubblock(pch::PCH_BLOCK_ID, 3); @@ -2079,16 +2090,17 @@ void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) { } void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) { - if (II == 0) { - Record.push_back(0); - return; - } + Record.push_back(getIdentifierRef(II)); +} + +pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) { + if (II == 0) + return 0; pch::IdentID &ID = IdentifierIDs[II]; if (ID == 0) ID = IdentifierIDs.size(); - - Record.push_back(ID); + return ID; } void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 4f2ab2b746..37233134da 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -1760,7 +1760,9 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, PP.getTargetInfo(), PP.getIdentifierTable(), PP.getSelectorTable(), - /* FreeMemory = */ !DisableFree)); + /* FreeMemory = */ !DisableFree, + /* size_reserve = */0, + /* InitializeBuiltins = */ImplicitIncludePCH.empty())); if (!ImplicitIncludePCH.empty()) { // The user has asked us to include a precompiled header. Load @@ -1788,6 +1790,11 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, case PCHReader::IgnorePCH: // No suitable PCH file could be found. Just ignore the // -include-pch option entirely. + + // We delayed the initialization of builtins in the hope of + // loading the PCH file. Since the PCH file could not be + // loaded, initialize builtins now. + ContextOwner->InitializeBuiltins(PP.getIdentifierTable()); break; } |