diff options
-rw-r--r-- | include/clang/Frontend/CompilerInstance.h | 64 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 52 | ||||
-rw-r--r-- | tools/clang-cc/clang-cc.cpp | 61 |
3 files changed, 119 insertions, 58 deletions
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index fb52383465..dad99e39f6 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -12,6 +12,7 @@ #include "clang/Frontend/CompilerInvocation.h" #include "llvm/ADT/OwningPtr.h" +#include <cassert> namespace llvm { class LLVMContext; @@ -20,6 +21,7 @@ class LLVMContext; namespace clang { class Diagnostic; class DiagnosticClient; +class Preprocessor; class FileManager; class SourceManager; class TargetInfo; @@ -65,6 +67,9 @@ class CompilerInstance { /// The source manager. llvm::OwningPtr<SourceManager> SourceMgr; + /// The preprocessor. + llvm::OwningPtr<Preprocessor> PP; + public: /// Create a new compiler instance with the given LLVM context, optionally /// taking ownership of it. @@ -75,7 +80,10 @@ public: /// @name LLVM Context /// { - llvm::LLVMContext &getLLVMContext() { return *LLVMContext; } + llvm::LLVMContext &getLLVMContext() { + assert(LLVMContext && "Compiler instance has no LLVM context!"); + return *LLVMContext; + } /// setLLVMContext - Replace the current LLVM context and take ownership of /// \arg Value. @@ -163,7 +171,10 @@ public: /// @name Diagnostics Engine /// { - Diagnostic &getDiagnostics() const { return *Diagnostics; } + Diagnostic &getDiagnostics() const { + assert(Diagnostics && "Compiler instance has no diagnostics!"); + return *Diagnostics; + } /// takeDiagnostics - Remove the current diagnostics engine and give ownership /// to the caller. @@ -189,7 +200,10 @@ public: /// @name Target Info /// { - TargetInfo &getTarget() const { return *Target; } + TargetInfo &getTarget() const { + assert(Target && "Compiler instance has no target!"); + return *Target; + } /// takeTarget - Remove the current diagnostics engine and give ownership /// to the caller. @@ -203,7 +217,10 @@ public: /// @name File Manager /// { - FileManager &getFileManager() const { return *FileMgr; } + FileManager &getFileManager() const { + assert(FileMgr && "Compiler instance has no file manager!"); + return *FileMgr; + } /// takeFileManager - Remove the current file manager and give ownership to /// the caller. @@ -217,7 +234,10 @@ public: /// @name Source Manager /// { - SourceManager &getSourceManager() const { return *SourceMgr; } + SourceManager &getSourceManager() const { + assert(SourceMgr && "Compiler instance has no source manager!"); + return *SourceMgr; + } /// takeSourceManager - Remove the current source manager and give ownership /// to the caller. @@ -228,6 +248,23 @@ public: void setSourceManager(SourceManager *Value) { SourceMgr.reset(Value); } /// } + /// @name Preprocessor + /// { + + Preprocessor &getPreprocessor() const { + assert(PP && "Compiler instance has no preprocessor!"); + return *PP; + } + + /// takePreprocessor - Remove the current preprocessor and give ownership to + /// the caller. + Preprocessor *takePreprocessor() { return PP.take(); } + + /// setPreprocessor - Replace the current preprocessor; the compiler instance + /// takes ownership of \arg Value. + void setPreprocessor(Preprocessor *Value) { PP.reset(Value); } + + /// } /// @name Construction Utility Methods /// { @@ -237,6 +274,23 @@ public: /// Create the source manager and replace any existing one with it. void createSourceManager(); + /// Create the preprocessor, using the invocation, file, and source managers, + /// and replace any existing one with it. + void createPreprocessor(); + + /// Create a Preprocessor object. + /// + /// Note that this also creates a new HeaderSearch object which will be owned + /// by the resulting Preprocessor. + /// + /// \return The new object on success, or null on failure. + static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &, + const PreprocessorOptions &, + const HeaderSearchOptions &, + const DependencyOutputOptions &, + const TargetInfo &, + SourceManager &, FileManager &); + /// } }; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 2d1f498e5c..550979777f 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -12,6 +12,10 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PTHManager.h" +#include "clang/Frontend/Utils.h" #include "llvm/LLVMContext.h" using namespace clang; @@ -33,3 +37,51 @@ void CompilerInstance::createFileManager() { void CompilerInstance::createSourceManager() { SourceMgr.reset(new SourceManager()); } + +void CompilerInstance::createPreprocessor() { + PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), + getPreprocessorOpts(), getHeaderSearchOpts(), + getDependencyOutputOpts(), getTarget(), + getSourceManager(), getFileManager())); +} + +Preprocessor * +CompilerInstance::createPreprocessor(Diagnostic &Diags, + const LangOptions &LangInfo, + const PreprocessorOptions &PPOpts, + const HeaderSearchOptions &HSOpts, + const DependencyOutputOptions &DepOpts, + const TargetInfo &Target, + SourceManager &SourceMgr, + FileManager &FileMgr) { + // Create a PTH manager if we are using some form of a token cache. + PTHManager *PTHMgr = 0; + if (!PPOpts.getTokenCache().empty()) + PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags); + + // FIXME: Don't fail like this. + if (Diags.hasErrorOccurred()) + exit(1); + + // Create the Preprocessor. + HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); + Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, + SourceMgr, *HeaderInfo, PTHMgr, + /*OwnsHeaderSearch=*/true); + + // Note that this is different then passing PTHMgr to Preprocessor's ctor. + // That argument is used as the IdentifierInfoLookup argument to + // IdentifierTable's ctor. + if (PTHMgr) { + PTHMgr->setPreprocessor(PP); + PP->setPTHManager(PTHMgr); + } + + InitializePreprocessor(*PP, PPOpts, HSOpts); + + // Handle generating dependencies, if requested. + if (!DepOpts.OutputFile.empty()) + AttachDependencyFileGen(*PP, DepOpts); + + return PP; +} diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 565277ed46..ec9a43fcec 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -219,45 +219,6 @@ std::string GetBuiltinIncludePath(const char *Argv0) { return P.str(); } -static Preprocessor * -CreatePreprocessor(Diagnostic &Diags, const LangOptions &LangInfo, - const PreprocessorOptions &PPOpts, - const HeaderSearchOptions &HSOpts, - const DependencyOutputOptions &DepOpts, - const TargetInfo &Target, SourceManager &SourceMgr, - FileManager &FileMgr) { - // Create a PTH manager if we are using some form of a token cache. - PTHManager *PTHMgr = 0; - if (!PPOpts.getTokenCache().empty()) - PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags); - - // FIXME: Don't fail like this. - if (Diags.hasErrorOccurred()) - exit(1); - - // Create the Preprocessor. - HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); - Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, - SourceMgr, *HeaderInfo, PTHMgr, - /*OwnsHeaderSearch=*/true); - - // Note that this is different then passing PTHMgr to Preprocessor's ctor. - // That argument is used as the IdentifierInfoLookup argument to - // IdentifierTable's ctor. - if (PTHMgr) { - PTHMgr->setPreprocessor(PP); - PP->setPTHManager(PTHMgr); - } - - InitializePreprocessor(*PP, PPOpts, HSOpts); - - // Handle generating dependencies, if requested. - if (!DepOpts.OutputFile.empty()) - AttachDependencyFileGen(*PP, DepOpts); - - return PP; -} - /// \brief Buld a new code-completion consumer that prints the results of /// code completion to standard output. static CodeCompleteConsumer *BuildPrintingCodeCompleter(Sema &S, @@ -499,9 +460,9 @@ static ExternalASTSource *ReadPCHFile(llvm::StringRef Path, } /// ProcessInputFile - Process a single input file with the specified state. -/// -static void ProcessInputFile(CompilerInstance &CI, Preprocessor &PP, - const std::string &InFile, ProgActions PA) { +static void ProcessInputFile(CompilerInstance &CI, const std::string &InFile, + ProgActions PA) { + Preprocessor &PP = CI.getPreprocessor(); const FrontendOptions &FEOpts = CI.getFrontendOpts(); llvm::OwningPtr<llvm::raw_ostream> OS; llvm::OwningPtr<ASTConsumer> Consumer; @@ -759,8 +720,8 @@ static void ProcessInputFile(CompilerInstance &CI, Preprocessor &PP, OutPath.eraseFromDisk(); } -/// ProcessInputFile - Process a single AST input file with the specified state. -/// +/// ProcessASTInputFile - Process a single AST input file with the specified +/// state. static void ProcessASTInputFile(CompilerInstance &CI, const std::string &InFile, ProgActions PA) { std::string Error; @@ -1006,18 +967,12 @@ int main(int argc, char **argv) { if (i) Clang.getSourceManager().clearIDTables(); - // Set up the preprocessor with these options. - llvm::OwningPtr<Preprocessor> - PP(CreatePreprocessor(Clang.getDiagnostics(), Clang.getLangOpts(), - Clang.getPreprocessorOpts(), - Clang.getHeaderSearchOpts(), - Clang.getDependencyOutputOpts(), - Clang.getTarget(), Clang.getSourceManager(), - Clang.getFileManager())); + // Create the preprocessor. + Clang.createPreprocessor(); // Process the source file. Clang.getDiagnostics().getClient()->BeginSourceFile(Clang.getLangOpts()); - ProcessInputFile(Clang, *PP, InFile, ProgAction); + ProcessInputFile(Clang, InFile, ProgAction); Clang.getDiagnostics().getClient()->EndSourceFile(); } |