From 998b3d3e8528ebd9d2c5d78d3a82edd90a8953a4 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138983 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.h | 5 +- include/clang/Lex/Preprocessor.h | 15 +++- lib/Basic/Builtins.cpp | 8 +- lib/Frontend/ASTUnit.cpp | 63 +++++++++------ lib/Frontend/CompilerInstance.cpp | 2 +- lib/Lex/Preprocessor.cpp | 122 +++++++++++++++++------------- 6 files changed, 130 insertions(+), 85 deletions(-) diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 1e16a0030a..fbf4ef417f 100644 --- a/include/clang/Basic/Builtins.h +++ b/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/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 7044e34cd3..b23a2156b0 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/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/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp index 57b771ab5b..7bdcdc6885 100644 --- a/lib/Basic/Builtins.cpp +++ b/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/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index b09c435c8a..370e1a9b14 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/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/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 344e77b63b..de950da45c 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/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/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index f00349081c..e189a9da81 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -50,21 +50,74 @@ 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; + + if (!DelayInitialization) { + assert(Target && "Must provide target information for PP initialization"); + Initialize(*Target); + } +} + +Preprocessor::~Preprocessor() { + assert(BacktrackPositions.empty() && "EnableBacktrack/Backtrack imbalance!"); + assert(MacroExpandingLexersStack.empty() && MacroExpandedTokens.empty() && + "Preprocessor::HandleEndOfTokenLexer should have cleared those"); + + while (!IncludeMacroStack.empty()) { + delete IncludeMacroStack.back().TheLexer; + delete IncludeMacroStack.back().TheTokenLexer; + IncludeMacroStack.pop_back(); + } + + // Free any macro definitions. + for (MacroInfoChain *I = MIChainHead ; I ; I = I->Next) + I->MI.Destroy(); + // Free any cached macro expanders. + for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i) + delete TokenLexerCache[i]; + + // Free any cached MacroArgs. + for (MacroArgs *ArgList = MacroArgCache; ArgList; ) + ArgList = ArgList->deallocate(); + + // Release pragma information. + delete PragmaHandlers; + + // Delete the scratch buffer info. + delete ScratchBuf; + + // Delete the header search info, if we own it. + if (OwnsHeaderSearch) + delete &HeaderInfo; + + 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; @@ -73,36 +126,36 @@ Preprocessor::Preprocessor(Diagnostic &diags, LangOptions &opts, 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"); @@ -117,44 +170,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, LangOptions &opts, 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; - } - -} - -Preprocessor::~Preprocessor() { - assert(BacktrackPositions.empty() && "EnableBacktrack/Backtrack imbalance!"); - assert(MacroExpandingLexersStack.empty() && MacroExpandedTokens.empty() && - "Preprocessor::HandleEndOfTokenLexer should have cleared those"); - - while (!IncludeMacroStack.empty()) { - delete IncludeMacroStack.back().TheLexer; - delete IncludeMacroStack.back().TheTokenLexer; - IncludeMacroStack.pop_back(); - } - - // Free any macro definitions. - for (MacroInfoChain *I = MIChainHead ; I ; I = I->Next) - I->MI.Destroy(); - - // Free any cached macro expanders. - for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i) - delete TokenLexerCache[i]; - - // Free any cached MacroArgs. - for (MacroArgs *ArgList = MacroArgCache; ArgList; ) - ArgList = ArgList->deallocate(); - - // Release pragma information. - delete PragmaHandlers; - - // Delete the scratch buffer info. - delete ScratchBuf; - - // Delete the header search info, if we own it. - if (OwnsHeaderSearch) - delete &HeaderInfo; - - delete Callbacks; + } } void Preprocessor::setPTHManager(PTHManager* pm) { -- 2.40.0