FrontendAction.cpp revision 199990
161452Sdfr//===--- FrontendAction.cpp -----------------------------------------------===// 261452Sdfr// 361452Sdfr// The LLVM Compiler Infrastructure 461452Sdfr// 561452Sdfr// This file is distributed under the University of Illinois Open Source 661452Sdfr// License. See LICENSE.TXT for details. 761452Sdfr// 861452Sdfr//===----------------------------------------------------------------------===// 961452Sdfr 1061452Sdfr#include "clang/Frontend/FrontendAction.h" 1161452Sdfr#include "clang/AST/ASTContext.h" 1261452Sdfr#include "clang/Lex/HeaderSearch.h" 1361452Sdfr#include "clang/Lex/Preprocessor.h" 1461452Sdfr#include "clang/Frontend/ASTUnit.h" 1561452Sdfr#include "clang/Frontend/CompilerInstance.h" 1661452Sdfr#include "clang/Frontend/FrontendDiagnostic.h" 1761452Sdfr#include "clang/Sema/ParseAST.h" 1861452Sdfr#include "llvm/Support/MemoryBuffer.h" 1961452Sdfr#include "llvm/Support/Timer.h" 2061452Sdfr#include "llvm/Support/ErrorHandling.h" 2161452Sdfr#include "llvm/Support/raw_ostream.h" 2261452Sdfrusing namespace clang; 2361452Sdfr 2461452SdfrFrontendAction::FrontendAction() : Instance(0) {} 2561452Sdfr 2661452SdfrFrontendAction::~FrontendAction() {} 27116192Sobrien 28116192Sobrienvoid FrontendAction::setCurrentFile(llvm::StringRef Value, ASTUnit *AST) { 29116192Sobrien CurrentFile = Value; 3061452Sdfr CurrentASTUnit.reset(AST); 3161452Sdfr} 3261452Sdfr 3361452Sdfrbool FrontendAction::BeginSourceFile(CompilerInstance &CI, 3461452Sdfr llvm::StringRef Filename, 3561452Sdfr bool IsAST) { 36129878Sphk assert(!Instance && "Already processing a source file!"); 3761452Sdfr assert(!Filename.empty() && "Unexpected empty filename!"); 3861452Sdfr setCurrentFile(Filename); 3976827Salfred setCompilerInstance(&CI); 4079339Sjhb 4161452Sdfr // AST files follow a very different path, since they share objects via the 42173573Sjhb // AST unit. 43173573Sjhb if (IsAST) { 44119288Simp assert(!usesPreprocessorOnly() && 45119288Simp "Attempt to pass AST file to preprocessor only action!"); 4661452Sdfr assert(hasASTSupport() && "This action does not have AST support!"); 4761452Sdfr 4861452Sdfr std::string Error; 4961452Sdfr ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, &Error); 5061452Sdfr if (!AST) { 5161452Sdfr CI.getDiagnostics().Report(diag::err_fe_invalid_ast_file) << Error; 5261452Sdfr goto failure; 5361452Sdfr } 5461452Sdfr 5561452Sdfr setCurrentFile(Filename, AST); 5661452Sdfr 5761452Sdfr // Set the shared objects, these are reset when we finish processing the 5861452Sdfr // file, otherwise the CompilerInstance will happily destroy them. 5961452Sdfr CI.setFileManager(&AST->getFileManager()); 6061452Sdfr CI.setSourceManager(&AST->getSourceManager()); 6161452Sdfr CI.setPreprocessor(&AST->getPreprocessor()); 6261452Sdfr CI.setASTContext(&AST->getASTContext()); 6361452Sdfr 6461452Sdfr // Initialize the action. 6561452Sdfr if (!BeginSourceFileAction(CI, Filename)) 6661452Sdfr goto failure; 6761452Sdfr 68142646Scognet /// Create the AST consumer. 69142646Scognet CI.setASTConsumer(CreateASTConsumer(CI, Filename)); 7061452Sdfr if (!CI.hasASTConsumer()) 7161452Sdfr goto failure; 72139431Sanholt 73139431Sanholt return true; 7461452Sdfr } 7561452Sdfr 7661452Sdfr // Inform the diagnostic client we are processing a source file. 7761452Sdfr CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 7861452Sdfr &CI.getPreprocessor()); 7961452Sdfr 8061452Sdfr // Initialize the action. 8161452Sdfr if (!BeginSourceFileAction(CI, Filename)) 8261452Sdfr goto failure; 8361452Sdfr 84127815Snjl /// Create the AST context and consumer unless this is a preprocessor only 85127815Snjl /// action. 8661452Sdfr if (!usesPreprocessorOnly()) { 8761452Sdfr CI.createASTContext(); 8861452Sdfr CI.setASTConsumer(CreateASTConsumer(CI, Filename)); 89142398Simp if (!CI.hasASTConsumer()) 9061452Sdfr goto failure; 9161452Sdfr 9261452Sdfr /// Use PCH? 9361452Sdfr if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 9461452Sdfr assert(hasPCHSupport() && "This action does not have PCH support!"); 9561452Sdfr CI.createPCHExternalASTSource( 9661452Sdfr CI.getPreprocessorOpts().ImplicitPCHInclude); 9761452Sdfr if (!CI.getASTContext().getExternalSource()) 9861452Sdfr goto failure; 9961452Sdfr } 10061452Sdfr } 101134098Sanholt 10261452Sdfr // Initialize builtin info as long as we aren't using an external AST 10361452Sdfr // source. 10461452Sdfr if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { 10561452Sdfr Preprocessor &PP = CI.getPreprocessor(); 10661452Sdfr PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 10761452Sdfr PP.getLangOptions().NoBuiltin); 108122513Sanholt } 109122513Sanholt 110122513Sanholt return true; 111122513Sanholt 11261452Sdfr // If we failed, reset state since the client will not end up calling the 11361452Sdfr // matching EndSourceFile(). 11461452Sdfr failure: 11561452Sdfr if (isCurrentFileAST()) { 11661452Sdfr CI.takeASTContext(); 11761452Sdfr CI.takePreprocessor(); 11861452Sdfr CI.takeSourceManager(); 11961452Sdfr CI.takeFileManager(); 12061452Sdfr } 12161452Sdfr 12261452Sdfr CI.getDiagnosticClient().EndSourceFile(); 12361452Sdfr setCurrentFile(""); 12461452Sdfr setCompilerInstance(0); 12561452Sdfr return false; 12661452Sdfr} 12761452Sdfr 12861452Sdfrvoid FrontendAction::Execute() { 12961452Sdfr CompilerInstance &CI = getCompilerInstance(); 130134098Sanholt 131134098Sanholt // Initialize the main file entry. This needs to be delayed until after PCH 132134099Sanholt // has loaded. 13361452Sdfr if (isCurrentFileAST()) { 13461452Sdfr // Set the main file ID to an empty file. 13561452Sdfr // 13661452Sdfr // FIXME: We probably shouldn't need this, but for now this is the 13761452Sdfr // simplest way to reuse the logic in ParseAST. 13861452Sdfr const char *EmptyStr = ""; 13961452Sdfr llvm::MemoryBuffer *SB = 14061452Sdfr llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>"); 14161452Sdfr CI.getSourceManager().createMainFileIDForMemBuffer(SB); 14261452Sdfr } else { 14361452Sdfr if (!CI.InitializeSourceManager(getCurrentFile())) 144134098Sanholt return; 14561452Sdfr } 146173203Sjhb 14761452Sdfr if (CI.hasFrontendTimer()) { 14861452Sdfr llvm::TimeRegion Timer(CI.getFrontendTimer()); 14961452Sdfr ExecuteAction(); 15061452Sdfr } 15161452Sdfr else ExecuteAction(); 15261452Sdfr} 153134098Sanholt 154134099Sanholtvoid FrontendAction::EndSourceFile() { 15561452Sdfr CompilerInstance &CI = getCompilerInstance(); 15661452Sdfr 157173203Sjhb // Finalize the action. 15861452Sdfr EndSourceFileAction(); 15961452Sdfr 16061452Sdfr // Release the consumer and the AST, in that order since the consumer may 16161452Sdfr // perform actions in its destructor which require the context. 16261452Sdfr // 16361452Sdfr // FIXME: There is more per-file stuff we could just drop here? 16461452Sdfr if (CI.getFrontendOpts().DisableFree) { 16561452Sdfr CI.takeASTConsumer(); 16661452Sdfr if (!isCurrentFileAST()) 16761452Sdfr CI.takeASTContext(); 16861452Sdfr } else { 16961452Sdfr CI.setASTConsumer(0); 17061452Sdfr if (!isCurrentFileAST()) 17161452Sdfr CI.setASTContext(0); 17261452Sdfr } 17361452Sdfr 17461452Sdfr if (CI.getFrontendOpts().ShowStats) { 17561452Sdfr llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n"; 17661452Sdfr CI.getPreprocessor().PrintStats(); 17761452Sdfr CI.getPreprocessor().getIdentifierTable().PrintStats(); 17861452Sdfr CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); 17961452Sdfr CI.getSourceManager().PrintStats(); 18061452Sdfr llvm::errs() << "\n"; 18161452Sdfr } 18261452Sdfr 18361452Sdfr // Cleanup the output streams, and erase the output files if we encountered 18461452Sdfr // an error. 185134099Sanholt CI.ClearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors()); 18661452Sdfr 18761452Sdfr // Inform the diagnostic client we are done with this source file. 18861452Sdfr CI.getDiagnosticClient().EndSourceFile(); 18961452Sdfr 19061452Sdfr if (isCurrentFileAST()) { 19161452Sdfr CI.takeASTContext(); 19261452Sdfr CI.takePreprocessor(); 19361452Sdfr CI.takeSourceManager(); 19461452Sdfr CI.takeFileManager(); 195134098Sanholt } 19661452Sdfr 19761452Sdfr setCompilerInstance(0); 19861452Sdfr setCurrentFile(""); 19961452Sdfr} 20061452Sdfr 20161452Sdfr//===----------------------------------------------------------------------===// 20261452Sdfr// Utility Actions 203134098Sanholt//===----------------------------------------------------------------------===// 204134099Sanholt 20561452Sdfrvoid ASTFrontendAction::ExecuteAction() { 20661452Sdfr CompilerInstance &CI = getCompilerInstance(); 20761452Sdfr 20861452Sdfr // FIXME: Move the truncation aspect of this into Sema, we delayed this till 209194017Savg // here so the source manager would be initialized. 21061452Sdfr if (hasCodeCompletionSupport() && 21161452Sdfr !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 21261452Sdfr CI.createCodeCompletionConsumer(); 213194017Savg 21461452Sdfr // Use a code completion consumer? 21561452Sdfr CodeCompleteConsumer *CompletionConsumer = 0; 21661452Sdfr if (CI.hasCodeCompletionConsumer()) 21761452Sdfr CompletionConsumer = &CI.getCodeCompletionConsumer(); 21861452Sdfr 21961452Sdfr ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(), 22061452Sdfr CI.getFrontendOpts().ShowStats, 221194017Savg usesCompleteTranslationUnit(), CompletionConsumer); 22261452Sdfr} 22361452Sdfr 22461452SdfrASTConsumer * 225194017SavgPreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, 22661452Sdfr llvm::StringRef InFile) { 22761452Sdfr llvm::llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); 22861452Sdfr} 22961452Sdfr