aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h14
-rw-r--r--include/clang/AST/Builtins.h5
-rw-r--r--include/clang/Frontend/PCHWriter.h4
-rw-r--r--lib/AST/ASTContext.cpp12
-rw-r--r--lib/AST/Builtins.cpp18
-rw-r--r--lib/Frontend/PCHReader.cpp31
-rw-r--r--lib/Frontend/PCHWriter.cpp28
-rw-r--r--tools/clang-cc/clang-cc.cpp9
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;
}