From 83297dfc7e5a311af23eb686e29bc41d31322a79 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 1 Sep 2011 23:39:15 +0000 Subject: [PATCH] Allow the preprocessor to be constructed without performing target- and language-specific initialization. Use this to allow ASTUnit to create a preprocessor object *before* loading the AST file. No actual functionality change. llvm-svn: 138983 --- clang/include/clang/Basic/Builtins.h | 5 +- clang/include/clang/Lex/Preprocessor.h | 15 ++- clang/lib/Basic/Builtins.cpp | 8 +- clang/lib/Frontend/ASTUnit.cpp | 63 ++++++----- clang/lib/Frontend/CompilerInstance.cpp | 2 +- clang/lib/Lex/Preprocessor.cpp | 136 +++++++++++++----------- 6 files changed, 137 insertions(+), 92 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index 1e16a0030adc..fbf4ef417fff 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -62,8 +62,11 @@ class Context { const Info *TSRecords; unsigned NumTSRecords; public: - Context(const TargetInfo &Target); + Context(); + /// \brief Perform target-specific initialization + void InitializeTarget(const TargetInfo &Target); + /// InitializeBuiltins - Mark the identifiers for all the builtins with their /// appropriate builtin ID # and mark any non-portable builtin identifiers as /// such. diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 7044e34cd34a..b23a2156b023 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -59,7 +59,7 @@ class ModuleLoader; class Preprocessor : public llvm::RefCountedBase { Diagnostic *Diags; LangOptions &Features; - const TargetInfo &Target; + const TargetInfo *Target; FileManager &FileMgr; SourceManager &SourceMgr; ScratchBuffer *ScratchBuf; @@ -295,19 +295,26 @@ private: // Cached tokens state. public: Preprocessor(Diagnostic &diags, LangOptions &opts, - const TargetInfo &target, + const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup = 0, - bool OwnsHeaderSearch = false); + bool OwnsHeaderSearch = false, + bool DelayInitialization = false); ~Preprocessor(); + /// \brief Initialize the preprocessor, if the constructor did not already + /// perform the initialization. + /// + /// \param Target Information about the target. + void Initialize(const TargetInfo &Target); + Diagnostic &getDiagnostics() const { return *Diags; } void setDiagnostics(Diagnostic &D) { Diags = &D; } const LangOptions &getLangOptions() const { return Features; } - const TargetInfo &getTargetInfo() const { return Target; } + const TargetInfo &getTargetInfo() const { return *Target; } FileManager &getFileManager() const { return FileMgr; } SourceManager &getSourceManager() const { return SourceMgr; } HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; } diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index 57b771ab5bc5..7bdcdc688552 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -32,11 +32,15 @@ const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const { return TSRecords[ID - Builtin::FirstTSBuiltin]; } -Builtin::Context::Context(const TargetInfo &Target) { +Builtin::Context::Context() { // Get the target specific builtins from the target. TSRecords = 0; NumTSRecords = 0; - Target.getTargetBuiltins(TSRecords, NumTSRecords); +} + +void Builtin::Context::InitializeTarget(const TargetInfo &Target) { + assert(NumTSRecords == 0 && "Already initialized target?"); + Target.getTargetBuiltins(TSRecords, NumTSRecords); } /// InitializeBuiltins - Mark the identifiers for all the builtins with their diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index b09c435c8a06..370e1a9b140d 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -376,28 +376,51 @@ namespace { /// \brief Gathers information from ASTReader that will be used to initialize /// a Preprocessor. class ASTInfoCollector : public ASTReaderListener { + Preprocessor &PP; LangOptions &LangOpt; HeaderSearch &HSI; - std::string &TargetTriple; + llvm::IntrusiveRefCntPtr &Target; std::string &Predefines; unsigned &Counter; unsigned NumHeaderInfos; + bool InitializedPreprocessor; public: - ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI, - std::string &TargetTriple, std::string &Predefines, + ASTInfoCollector(Preprocessor &PP, + LangOptions &LangOpt, HeaderSearch &HSI, + llvm::IntrusiveRefCntPtr &Target, + std::string &Predefines, unsigned &Counter) - : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple), - Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {} + : PP(PP), LangOpt(LangOpt), HSI(HSI), Target(Target), + Predefines(Predefines), Counter(Counter), NumHeaderInfos(0), + InitializedPreprocessor(false) {} virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { + if (InitializedPreprocessor) + return false; + LangOpt = LangOpts; + + // Initialize the preprocessor. + PP.Initialize(*Target); + InitializedPreprocessor = true; return false; } virtual bool ReadTargetTriple(StringRef Triple) { - TargetTriple = Triple; + // If we've already initialized the target, don't do it again. + if (Target) + return false; + + // FIXME: This is broken, we should store the TargetOptions in the AST file. + TargetOptions TargetOpts; + TargetOpts.ABI = ""; + TargetOpts.CXXABI = ""; + TargetOpts.CPU = ""; + TargetOpts.Features.clear(); + TargetOpts.Triple = Triple; + Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts); return false; } @@ -573,12 +596,18 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, // Gather Info for preprocessor construction later on. HeaderSearch &HeaderInfo = *AST->HeaderInfo.get(); - std::string TargetTriple; std::string Predefines; unsigned Counter; llvm::OwningPtr Reader; + AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts, + /*Target=*/0, AST->getSourceManager(), HeaderInfo, + *AST, + /*IILookup=*/0, + /*OwnsHeaderSearch=*/false, + /*DelayInitialization=*/true); + Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(), AST->getDiagnostics())); @@ -586,8 +615,9 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, llvm::CrashRecoveryContextCleanupRegistrar ReaderCleanup(Reader.get()); - Reader->setListener(new ASTInfoCollector(AST->ASTFileLangOpts, HeaderInfo, - TargetTriple, Predefines, Counter)); + Reader->setListener(new ASTInfoCollector(*AST->PP, + AST->ASTFileLangOpts, HeaderInfo, + AST->Target, Predefines, Counter)); switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) { case ASTReader::Success: @@ -602,21 +632,6 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, AST->OriginalSourceFile = Reader->getOriginalSourceFile(); // AST file loaded successfully. Now create the preprocessor. - - // Get information about the target being compiled for. - // - // FIXME: This is broken, we should store the TargetOptions in the AST file. - TargetOptions TargetOpts; - TargetOpts.ABI = ""; - TargetOpts.CXXABI = ""; - TargetOpts.CPU = ""; - TargetOpts.Features.clear(); - TargetOpts.Triple = TargetTriple; - AST->Target = TargetInfo::CreateTargetInfo(AST->getDiagnostics(), - TargetOpts); - AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts, - *AST->Target, AST->getSourceManager(), HeaderInfo, - *AST); Preprocessor &PP = *AST->PP; PP.setPredefines(Reader->getSuggestedPredefines()); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 344e77b63b2e..de950da45c13 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -200,7 +200,7 @@ void CompilerInstance::createPreprocessor() { // Create the Preprocessor. HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager()); - PP = new Preprocessor(getDiagnostics(), getLangOpts(), getTarget(), + PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(), getSourceManager(), *HeaderInfo, *this, PTHMgr, /*OwnsHeaderSearch=*/true); diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index f00349081cd3..e189a9da818e 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -50,75 +50,25 @@ using namespace clang; ExternalPreprocessorSource::~ExternalPreprocessorSource() { } Preprocessor::Preprocessor(Diagnostic &diags, LangOptions &opts, - const TargetInfo &target, SourceManager &SM, + const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup* IILookup, - bool OwnsHeaders) + bool OwnsHeaders, + bool DelayInitialization) : Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()), SourceMgr(SM), HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), ExternalSource(0), - Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0), + Identifiers(opts, IILookup), CodeComplete(0), CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0), CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0), - MICache(0) { - ScratchBuf = new ScratchBuffer(SourceMgr); - CounterValue = 0; // __COUNTER__ starts at 0. + MICache(0) +{ OwnsHeaderSearch = OwnsHeaders; - - // Clear stats. - NumDirectives = NumDefined = NumUndefined = NumPragma = 0; - NumIf = NumElse = NumEndif = 0; - NumEnteredSourceFiles = 0; - NumMacroExpanded = NumFnMacroExpanded = NumBuiltinMacroExpanded = 0; - NumFastMacroExpanded = NumTokenPaste = NumFastTokenPaste = 0; - MaxIncludeStackDepth = 0; - NumSkipped = 0; - - // Default to discarding comments. - KeepComments = false; - KeepMacroComments = false; - SuppressIncludeNotFoundError = false; - - // Macro expansion is enabled. - DisableMacroExpansion = false; - InMacroArgs = false; - NumCachedTokenLexers = 0; - - CachedLexPos = 0; - - // We haven't read anything from the external source. - ReadMacrosFromExternalSource = false; - - LexDepth = 0; - - // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. - // This gets unpoisoned where it is allowed. - (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); - SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); - - // Initialize the pragma handlers. - PragmaHandlers = new PragmaNamespace(StringRef()); - RegisterBuiltinPragmas(); - - // Initialize builtin macros like __LINE__ and friends. - RegisterBuiltinMacros(); - - if(Features.Borland) { - Ident__exception_info = getIdentifierInfo("_exception_info"); - Ident___exception_info = getIdentifierInfo("__exception_info"); - Ident_GetExceptionInfo = getIdentifierInfo("GetExceptionInformation"); - Ident__exception_code = getIdentifierInfo("_exception_code"); - Ident___exception_code = getIdentifierInfo("__exception_code"); - Ident_GetExceptionCode = getIdentifierInfo("GetExceptionCode"); - Ident__abnormal_termination = getIdentifierInfo("_abnormal_termination"); - Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination"); - Ident_AbnormalTermination = getIdentifierInfo("AbnormalTermination"); - } else { - Ident__exception_info = Ident__exception_code = Ident__abnormal_termination = 0; - Ident___exception_info = Ident___exception_code = Ident___abnormal_termination = 0; - Ident_GetExceptionInfo = Ident_GetExceptionCode = Ident_AbnormalTermination = 0; + + if (!DelayInitialization) { + assert(Target && "Must provide target information for PP initialization"); + Initialize(*Target); } - } Preprocessor::~Preprocessor() { @@ -157,6 +107,72 @@ Preprocessor::~Preprocessor() { delete Callbacks; } +void Preprocessor::Initialize(const TargetInfo &Target) { + assert((!this->Target || this->Target == &Target) && + "Invalid override of target information"); + this->Target = &Target; + + // Initialize information about built-ins. + BuiltinInfo.InitializeTarget(Target); + + ScratchBuf = new ScratchBuffer(SourceMgr); + CounterValue = 0; // __COUNTER__ starts at 0. + + // Clear stats. + NumDirectives = NumDefined = NumUndefined = NumPragma = 0; + NumIf = NumElse = NumEndif = 0; + NumEnteredSourceFiles = 0; + NumMacroExpanded = NumFnMacroExpanded = NumBuiltinMacroExpanded = 0; + NumFastMacroExpanded = NumTokenPaste = NumFastTokenPaste = 0; + MaxIncludeStackDepth = 0; + NumSkipped = 0; + + // Default to discarding comments. + KeepComments = false; + KeepMacroComments = false; + SuppressIncludeNotFoundError = false; + + // Macro expansion is enabled. + DisableMacroExpansion = false; + InMacroArgs = false; + NumCachedTokenLexers = 0; + + CachedLexPos = 0; + + // We haven't read anything from the external source. + ReadMacrosFromExternalSource = false; + + LexDepth = 0; + + // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. + // This gets unpoisoned where it is allowed. + (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); + + // Initialize the pragma handlers. + PragmaHandlers = new PragmaNamespace(StringRef()); + RegisterBuiltinPragmas(); + + // Initialize builtin macros like __LINE__ and friends. + RegisterBuiltinMacros(); + + if(Features.Borland) { + Ident__exception_info = getIdentifierInfo("_exception_info"); + Ident___exception_info = getIdentifierInfo("__exception_info"); + Ident_GetExceptionInfo = getIdentifierInfo("GetExceptionInformation"); + Ident__exception_code = getIdentifierInfo("_exception_code"); + Ident___exception_code = getIdentifierInfo("__exception_code"); + Ident_GetExceptionCode = getIdentifierInfo("GetExceptionCode"); + Ident__abnormal_termination = getIdentifierInfo("_abnormal_termination"); + Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination"); + Ident_AbnormalTermination = getIdentifierInfo("AbnormalTermination"); + } else { + Ident__exception_info = Ident__exception_code = Ident__abnormal_termination = 0; + Ident___exception_info = Ident___exception_code = Ident___abnormal_termination = 0; + Ident_GetExceptionInfo = Ident_GetExceptionCode = Ident_AbnormalTermination = 0; + } +} + void Preprocessor::setPTHManager(PTHManager* pm) { PTH.reset(pm); FileMgr.addStatCache(PTH->createStatCache());