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