1//===--- ExecuteCompilerInvocation.cpp ------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file holds ExecuteCompilerInvocation(). It is split into its own file to
11// minimize the impact of pulling in essentially everything else in Clang.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/FrontendTool/Utils.h"
16#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
17#include "clang/ARCMigrate/ARCMTActions.h"
18#include "clang/CodeGen/CodeGenAction.h"
19#include "clang/Driver/CC1Options.h"
20#include "clang/Driver/OptTable.h"
21#include "clang/Frontend/CompilerInvocation.h"
22#include "clang/Frontend/CompilerInstance.h"
23#include "clang/Frontend/FrontendActions.h"
24#include "clang/Frontend/FrontendDiagnostic.h"
25#include "clang/Frontend/FrontendPluginRegistry.h"
26#include "clang/Rewrite/FrontendActions.h"
27#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/DynamicLibrary.h"
29using namespace clang;
30
31static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
32  using namespace clang::frontend;
33
34  switch (CI.getFrontendOpts().ProgramAction) {
35  default:
36    llvm_unreachable("Invalid program action!");
37
38  case ASTDump:                return new ASTDumpAction();
39  case ASTDumpXML:             return new ASTDumpXMLAction();
40  case ASTPrint:               return new ASTPrintAction();
41  case ASTView:                return new ASTViewAction();
42  case DumpRawTokens:          return new DumpRawTokensAction();
43  case DumpTokens:             return new DumpTokensAction();
44  case EmitAssembly:           return new EmitAssemblyAction();
45  case EmitBC:                 return new EmitBCAction();
46  case EmitHTML:               return new HTMLPrintAction();
47  case EmitLLVM:               return new EmitLLVMAction();
48  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
49  case EmitCodeGenOnly:        return new EmitCodeGenOnlyAction();
50  case EmitObj:                return new EmitObjAction();
51  case FixIt:                  return new FixItAction();
52  case GenerateModule:         return new GeneratePCHAction(true);
53  case GeneratePCH:            return new GeneratePCHAction(false);
54  case GeneratePTH:            return new GeneratePTHAction();
55  case InitOnly:               return new InitOnlyAction();
56  case ParseSyntaxOnly:        return new SyntaxOnlyAction();
57
58  case PluginAction: {
59    for (FrontendPluginRegistry::iterator it =
60           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
61         it != ie; ++it) {
62      if (it->getName() == CI.getFrontendOpts().ActionName) {
63        llvm::OwningPtr<PluginASTAction> P(it->instantiate());
64        if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
65          return 0;
66        return P.take();
67      }
68    }
69
70    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
71      << CI.getFrontendOpts().ActionName;
72    return 0;
73  }
74
75  case PrintDeclContext:       return new DeclContextPrintAction();
76  case PrintPreamble:          return new PrintPreambleAction();
77  case PrintPreprocessedInput: return new PrintPreprocessedAction();
78  case RewriteMacros:          return new RewriteMacrosAction();
79  case RewriteObjC:            return new RewriteObjCAction();
80  case RewriteTest:            return new RewriteTestAction();
81  case RunAnalysis:            return new ento::AnalysisAction();
82  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
83  }
84}
85
86static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
87  // Create the underlying action.
88  FrontendAction *Act = CreateFrontendBaseAction(CI);
89  if (!Act)
90    return 0;
91
92  // Potentially wrap the base FE action in an ARC Migrate Tool action.
93  switch (CI.getFrontendOpts().ARCMTAction) {
94  case FrontendOptions::ARCMT_None:
95    break;
96  case FrontendOptions::ARCMT_Check:
97    Act = new arcmt::CheckAction(Act);
98    break;
99  case FrontendOptions::ARCMT_Modify:
100    Act = new arcmt::ModifyAction(Act);
101    break;
102  case FrontendOptions::ARCMT_Migrate:
103    Act = new arcmt::MigrateAction(Act,
104                                   CI.getFrontendOpts().ARCMTMigrateDir,
105                                   CI.getFrontendOpts().ARCMTMigrateReportOut,
106                                CI.getFrontendOpts().ARCMTMigrateEmitARCErrors);
107    break;
108  }
109
110  // If there are any AST files to merge, create a frontend action
111  // adaptor to perform the merge.
112  if (!CI.getFrontendOpts().ASTMergeFiles.empty())
113    Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
114                             CI.getFrontendOpts().ASTMergeFiles.size());
115
116  return Act;
117}
118
119bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
120  // Honor -help.
121  if (Clang->getFrontendOpts().ShowHelp) {
122    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
123    Opts->PrintHelp(llvm::outs(), "clang -cc1",
124                    "LLVM 'Clang' Compiler: http://clang.llvm.org");
125    return 0;
126  }
127
128  // Honor -version.
129  //
130  // FIXME: Use a better -version message?
131  if (Clang->getFrontendOpts().ShowVersion) {
132    llvm::cl::PrintVersionMessage();
133    return 0;
134  }
135
136  // Load any requested plugins.
137  for (unsigned i = 0,
138         e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) {
139    const std::string &Path = Clang->getFrontendOpts().Plugins[i];
140    std::string Error;
141    if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
142      Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin)
143        << Path << Error;
144  }
145
146  // Honor -mllvm.
147  //
148  // FIXME: Remove this, one day.
149  // This should happen AFTER plugins have been loaded!
150  if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
151    unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
152    const char **Args = new const char*[NumArgs + 2];
153    Args[0] = "clang (LLVM option parsing)";
154    for (unsigned i = 0; i != NumArgs; ++i)
155      Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
156    Args[NumArgs + 1] = 0;
157    llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
158  }
159
160  // Honor -analyzer-checker-help.
161  // This should happen AFTER plugins have been loaded!
162  if (Clang->getAnalyzerOpts().ShowCheckerHelp) {
163    ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins);
164    return 0;
165  }
166
167  // If there were errors in processing arguments, don't do anything else.
168  bool Success = false;
169  if (!Clang->getDiagnostics().hasErrorOccurred()) {
170    // Create and execute the frontend action.
171    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(*Clang));
172    if (Act) {
173      Success = Clang->ExecuteAction(*Act);
174      if (Clang->getFrontendOpts().DisableFree)
175        Act.take();
176    }
177  }
178
179  return Success;
180}
181