blob: 11a4f242737792c663f7bd473af1ca6b63474438 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- clang.cpp - C-Language Front-end ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This utility may be invoked in the following manner:
Daniel Dunbar4fdba992009-11-14 10:53:49 +000011// clang-cc --help - Output help info.
12// clang-cc [options] - Read from stdin.
13// clang-cc [options] file - Read from "file".
14// clang-cc [options] file1 file2 - Read these files.
Reid Spencer5f016e22007-07-11 17:01:13 +000015//
16//===----------------------------------------------------------------------===//
Reid Spencer5f016e22007-07-11 17:01:13 +000017
Daniel Dunbar9119e7e2009-11-16 22:38:48 +000018#include "clang/Basic/Diagnostic.h"
Daniel Dunbar775bee72009-11-11 10:07:22 +000019#include "clang/Basic/FileManager.h"
20#include "clang/Basic/SourceManager.h"
21#include "clang/Basic/TargetInfo.h"
22#include "clang/Basic/Version.h"
Daniel Dunbarc88aa792009-11-30 07:18:13 +000023#include "clang/Driver/Arg.h"
24#include "clang/Driver/ArgList.h"
25#include "clang/Driver/CC1Options.h"
26#include "clang/Driver/DriverDiagnostic.h"
27#include "clang/Driver/OptTable.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000028#include "clang/Frontend/CompilerInstance.h"
Daniel Dunbare29709f2009-11-09 20:55:08 +000029#include "clang/Frontend/CompilerInvocation.h"
Daniel Dunbar4fdba992009-11-14 10:53:49 +000030#include "clang/Frontend/FrontendActions.h"
Daniel Dunbar50f4f462009-03-12 10:14:16 +000031#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbard10c5b82009-11-15 00:12:04 +000032#include "clang/Frontend/FrontendPluginRegistry.h"
Daniel Dunbar9deb3132009-11-30 08:42:10 +000033#include "clang/Frontend/TextDiagnosticBuffer.h"
Daniel Dunbarc88aa792009-11-30 07:18:13 +000034#include "clang/Frontend/TextDiagnosticPrinter.h"
Daniel Dunbarf79dced2009-11-14 03:24:39 +000035#include "clang/Frontend/VerifyDiagnosticsClient.h"
Daniel Dunbar4fdba992009-11-14 10:53:49 +000036#include "llvm/LLVMContext.h"
Daniel Dunbar9119e7e2009-11-16 22:38:48 +000037#include "llvm/ADT/OwningPtr.h"
Daniel Dunbar70121eb2009-08-10 03:40:28 +000038#include "llvm/Support/ErrorHandling.h"
Daniel Dunbar524b86f2008-10-28 00:38:08 +000039#include "llvm/Support/ManagedStatic.h"
Chris Lattner09e94a32009-03-04 21:41:39 +000040#include "llvm/Support/PrettyStackTrace.h"
Chris Lattner0fa0daa2009-08-24 04:11:30 +000041#include "llvm/Support/raw_ostream.h"
Daniel Dunbarefba2272009-12-03 05:11:05 +000042#include "llvm/System/DynamicLibrary.h"
Daniel Dunbare553a722008-10-02 01:21:33 +000043#include "llvm/System/Host.h"
Chris Lattnerdcaa0962008-03-03 03:16:03 +000044#include "llvm/System/Path.h"
Chris Lattnerba0f25f2008-09-30 20:16:56 +000045#include "llvm/System/Signals.h"
Chris Lattner2fe11942009-06-17 17:25:50 +000046#include "llvm/Target/TargetSelect.h"
Daniel Dunbar1a506282009-11-25 10:53:00 +000047#include <cstdio>
Reid Spencer5f016e22007-07-11 17:01:13 +000048using namespace clang;
49
50//===----------------------------------------------------------------------===//
Daniel Dunbarc363cb12009-11-16 22:38:40 +000051// Main driver
Reid Spencer5f016e22007-07-11 17:01:13 +000052//===----------------------------------------------------------------------===//
53
Daniel Dunbar5e96f9d2009-12-03 07:23:38 +000054void LLVMErrorHandler(void *UserData, const std::string &Message) {
Daniel Dunbarc363cb12009-11-16 22:38:40 +000055 Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
56
57 Diags.Report(diag::err_fe_error_backend) << Message;
58
59 // We cannot recover from llvm errors.
60 exit(1);
61}
Reid Spencer5f016e22007-07-11 17:01:13 +000062
Daniel Dunbard10c5b82009-11-15 00:12:04 +000063static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
Daniel Dunbar9a8a83b2009-11-14 22:32:38 +000064 using namespace clang::frontend;
65
Daniel Dunbard10c5b82009-11-15 00:12:04 +000066 switch (CI.getFrontendOpts().ProgramAction) {
67 default:
68 llvm::llvm_unreachable("Invalid program action!");
69
Daniel Dunbar4fdba992009-11-14 10:53:49 +000070 case ASTDump: return new ASTDumpAction();
71 case ASTPrint: return new ASTPrintAction();
72 case ASTPrintXML: return new ASTPrintXMLAction();
73 case ASTView: return new ASTViewAction();
74 case DumpRawTokens: return new DumpRawTokensAction();
75 case DumpRecordLayouts: return new DumpRecordAction();
76 case DumpTokens: return new DumpTokensAction();
77 case EmitAssembly: return new EmitAssemblyAction();
78 case EmitBC: return new EmitBCAction();
79 case EmitHTML: return new HTMLPrintAction();
80 case EmitLLVM: return new EmitLLVMAction();
81 case EmitLLVMOnly: return new EmitLLVMOnlyAction();
82 case FixIt: return new FixItAction();
83 case GeneratePCH: return new GeneratePCHAction();
84 case GeneratePTH: return new GeneratePTHAction();
85 case InheritanceView: return new InheritanceViewAction();
86 case ParseNoop: return new ParseOnlyAction();
87 case ParsePrintCallbacks: return new PrintParseAction();
88 case ParseSyntaxOnly: return new SyntaxOnlyAction();
Daniel Dunbard10c5b82009-11-15 00:12:04 +000089
90 case PluginAction: {
91 if (CI.getFrontendOpts().ActionName == "help") {
92 llvm::errs() << "clang-cc plugins:\n";
93 for (FrontendPluginRegistry::iterator it =
94 FrontendPluginRegistry::begin(),
95 ie = FrontendPluginRegistry::end();
96 it != ie; ++it)
97 llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n";
Daniel Dunbar36841b32009-12-03 09:13:43 +000098 return 0;
Daniel Dunbard10c5b82009-11-15 00:12:04 +000099 }
100
101 for (FrontendPluginRegistry::iterator it =
102 FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
103 it != ie; ++it) {
104 if (it->getName() == CI.getFrontendOpts().ActionName)
105 return it->instantiate();
106 }
107
108 CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
109 << CI.getFrontendOpts().ActionName;
110 return 0;
111 }
112
Daniel Dunbar4fdba992009-11-14 10:53:49 +0000113 case PrintDeclContext: return new DeclContextPrintAction();
114 case PrintPreprocessedInput: return new PrintPreprocessedAction();
115 case RewriteBlocks: return new RewriteBlocksAction();
116 case RewriteMacros: return new RewriteMacrosAction();
117 case RewriteObjC: return new RewriteObjCAction();
118 case RewriteTest: return new RewriteTestAction();
119 case RunAnalysis: return new AnalysisAction();
120 case RunPreprocessorOnly: return new PreprocessOnlyAction();
Eli Friedman66d6f042009-05-18 22:20:00 +0000121 }
Daniel Dunbaraca2ebd2009-09-17 00:48:13 +0000122}
123
Daniel Dunbarc88aa792009-11-30 07:18:13 +0000124static int cc1_main(Diagnostic &Diags,
125 const char **ArgBegin, const char **ArgEnd,
126 const char *Argv0, void *MainAddr) {
127 using namespace clang::driver;
128
129 llvm::errs() << "cc1 argv:";
130 for (const char **i = ArgBegin; i != ArgEnd; ++i)
131 llvm::errs() << " \"" << *i << '"';
132 llvm::errs() << "\n";
133
134 // Parse the arguments.
135 OptTable *Opts = createCC1OptTable();
136 unsigned MissingArgIndex, MissingArgCount;
137 InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd,
138 MissingArgIndex, MissingArgCount);
139
140 // Check for missing argument error.
141 if (MissingArgCount)
142 Diags.Report(clang::diag::err_drv_missing_argument)
143 << Args->getArgString(MissingArgIndex) << MissingArgCount;
144
145 // Dump the parsed arguments.
146 llvm::errs() << "cc1 parsed options:\n";
147 for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
148 it != ie; ++it)
149 (*it)->dump();
150
151 // Create a compiler invocation.
152 llvm::errs() << "cc1 creating invocation.\n";
153 CompilerInvocation Invocation;
154 CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd,
155 Argv0, MainAddr, Diags);
156
157 // Convert the invocation back to argument strings.
158 std::vector<std::string> InvocationArgs;
159 Invocation.toArgs(InvocationArgs);
160
161 // Dump the converted arguments.
162 llvm::SmallVector<const char*, 32> Invocation2Args;
163 llvm::errs() << "invocation argv :";
164 for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) {
165 Invocation2Args.push_back(InvocationArgs[i].c_str());
166 llvm::errs() << " \"" << InvocationArgs[i] << '"';
167 }
168 llvm::errs() << "\n";
169
170 // Convert those arguments to another invocation, and check that we got the
171 // same thing.
172 CompilerInvocation Invocation2;
173 CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
174 Invocation2Args.end(), Argv0, MainAddr,
175 Diags);
176
177 // FIXME: Implement CompilerInvocation comparison.
178 if (true) {
179 //llvm::errs() << "warning: Invocations differ!\n";
180
181 std::vector<std::string> Invocation2Args;
182 Invocation2.toArgs(Invocation2Args);
183 llvm::errs() << "invocation2 argv:";
184 for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i)
185 llvm::errs() << " \"" << Invocation2Args[i] << '"';
186 llvm::errs() << "\n";
187 }
188
189 return 0;
190}
191
Reid Spencer5f016e22007-07-11 17:01:13 +0000192int main(int argc, char **argv) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000193 llvm::sys::PrintStackTraceOnErrorSignal();
Chris Lattner09e94a32009-03-04 21:41:39 +0000194 llvm::PrettyStackTraceProgram X(argc, argv);
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000195 CompilerInstance Clang(&llvm::getGlobalContext(), false);
Daniel Dunbard6970812009-09-02 23:20:15 +0000196
Daniel Dunbarc88aa792009-11-30 07:18:13 +0000197 // Run clang -cc1 test.
198 if (argc > 1 && llvm::StringRef(argv[1]) == "-cc1") {
199 TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
200 Diagnostic Diags(&DiagClient);
201 return cc1_main(Diags, (const char**) argv + 2, (const char**) argv + argc,
Daniel Dunbar5e96f9d2009-12-03 07:23:38 +0000202 argv[0], (void*) (intptr_t) LLVMErrorHandler);
Daniel Dunbarc88aa792009-11-30 07:18:13 +0000203 }
204
Daniel Dunbar4d861512009-09-03 04:54:12 +0000205 // Initialize targets first, so that --version shows registered targets.
Chris Lattner2fe11942009-06-17 17:25:50 +0000206 llvm::InitializeAllTargets();
207 llvm::InitializeAllAsmPrinters();
Daniel Dunbard6970812009-09-02 23:20:15 +0000208
Daniel Dunbarefba2272009-12-03 05:11:05 +0000209 // Buffer diagnostics from argument parsing so that we can output them using a
210 // well formed diagnostic object.
Daniel Dunbar9deb3132009-11-30 08:42:10 +0000211 TextDiagnosticBuffer DiagsBuffer;
212 Diagnostic Diags(&DiagsBuffer);
Daniel Dunbar9deb3132009-11-30 08:42:10 +0000213 CompilerInvocation::CreateFromArgs(Clang.getInvocation(),
214 (const char**) argv + 1,
215 (const char**) argv + argc, argv[0],
Daniel Dunbar5e96f9d2009-12-03 07:23:38 +0000216 (void*)(intptr_t) LLVMErrorHandler,
Daniel Dunbar9deb3132009-11-30 08:42:10 +0000217 Diags);
218
Daniel Dunbar9b5e9ae2009-12-03 07:01:58 +0000219 // Honor -help.
220 if (Clang.getInvocation().getFrontendOpts().ShowHelp) {
221 llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
222 Opts->PrintHelp(llvm::outs(), "clang-cc",
223 "LLVM 'Clang' Compiler: http://clang.llvm.org");
224 return 0;
225 }
226
227 // Honor -version.
228 //
229 // FIXME: Use a better -version message?
230 if (Clang.getInvocation().getFrontendOpts().ShowVersion) {
231 llvm::cl::PrintVersionMessage();
232 return 0;
233 }
234
Daniel Dunbar9deb3132009-11-30 08:42:10 +0000235 // Create the actual diagnostics engine.
236 Clang.createDiagnostics(argc, argv);
237 if (!Clang.hasDiagnostics())
238 return 1;
Steve Naroffe0c4d892009-12-05 02:14:08 +0000239
Daniel Dunbar9deb3132009-11-30 08:42:10 +0000240 // Set an error handler, so that any LLVM backend diagnostics go through our
241 // error handler.
242 llvm::llvm_install_error_handler(LLVMErrorHandler,
243 static_cast<void*>(&Clang.getDiagnostics()));
244
245 DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics());
246
Daniel Dunbarefba2272009-12-03 05:11:05 +0000247 // Load any requested plugins.
248 for (unsigned i = 0,
249 e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) {
250 const std::string &Path = Clang.getFrontendOpts().Plugins[i];
251 std::string Error;
252 if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
253 Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
254 }
255
Daniel Dunbar9deb3132009-11-30 08:42:10 +0000256 // If there were any errors in processing arguments, exit now.
257 if (Clang.getDiagnostics().getNumErrors())
258 return 1;
Daniel Dunbar33b26ea32009-11-20 16:55:31 +0000259
260 // Create the target instance.
261 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
262 Clang.getTargetOpts()));
Daniel Dunbar704e48a2009-11-13 08:20:57 +0000263 if (!Clang.hasTarget())
Daniel Dunbar21dac5e2009-11-13 01:02:19 +0000264 return 1;
Daniel Dunbar26266882009-11-12 23:52:32 +0000265
Daniel Dunbar33b26ea32009-11-20 16:55:31 +0000266 // Inform the target of the language options
267 //
268 // FIXME: We shouldn't need to do this, the target should be immutable once
269 // created. This complexity should be lifted elsewhere.
270 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
271
Daniel Dunbar21dac5e2009-11-13 01:02:19 +0000272 // Validate/process some options
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000273 if (Clang.getHeaderSearchOpts().Verbose)
Daniel Dunbar1417c742009-11-12 23:52:46 +0000274 llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
275 << " based upon " << PACKAGE_STRING
276 << " hosted on " << llvm::sys::getHostTriple() << "\n";
277
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000278 if (Clang.getFrontendOpts().ShowTimers)
Kovarththanan Rajaratnamf79bafa2009-11-29 09:57:35 +0000279 Clang.createFrontendTimer();
Daniel Dunbar26266882009-11-12 23:52:32 +0000280
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000281 for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
282 const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;
Mike Stump1eb44332009-09-09 15:08:12 +0000283
Daniel Dunbar4fdba992009-11-14 10:53:49 +0000284 // If we aren't using an AST file, setup the file and source managers and
285 // the preprocessor.
Daniel Dunbarae8e17e2009-11-30 07:18:20 +0000286 bool IsAST =
287 Clang.getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
Daniel Dunbar4fdba992009-11-14 10:53:49 +0000288 if (!IsAST) {
289 if (!i) {
290 // Create a file manager object to provide access to and cache the
291 // filesystem.
292 Clang.createFileManager();
293
294 // Create the source manager.
295 Clang.createSourceManager();
296 } else {
297 // Reset the ID tables if we are reusing the SourceManager.
298 Clang.getSourceManager().clearIDTables();
299 }
300
301 // Create the preprocessor.
302 Clang.createPreprocessor();
Daniel Dunbaraca2ebd2009-09-17 00:48:13 +0000303 }
304
Daniel Dunbard10c5b82009-11-15 00:12:04 +0000305 llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
306 if (!Act)
307 break;
308
Daniel Dunbar4fdba992009-11-14 10:53:49 +0000309 if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
310 Act->Execute();
311 Act->EndSourceFile();
312 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000313 }
Chris Lattner11215192008-03-14 06:12:05 +0000314
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000315 if (Clang.getDiagnosticOpts().ShowCarets)
316 if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
Mike Stumpfc0fed32009-04-28 01:19:10 +0000317 fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
318 (NumDiagnostics == 1 ? "" : "s"));
Mike Stump1eb44332009-09-09 15:08:12 +0000319
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000320 if (Clang.getFrontendOpts().ShowStats) {
Daniel Dunbar16b74492009-11-13 04:12:06 +0000321 Clang.getFileManager().PrintStats();
Reid Spencer5f016e22007-07-11 17:01:13 +0000322 fprintf(stderr, "\n");
323 }
Chris Lattner75a97cb2009-04-17 21:05:01 +0000324
Daniel Dunbarf79dced2009-11-14 03:24:39 +0000325 // Return the appropriate status when verifying diagnostics.
326 //
327 // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
328 // this.
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000329 if (Clang.getDiagnosticOpts().VerifyDiagnostics)
Daniel Dunbarf79dced2009-11-14 03:24:39 +0000330 return static_cast<VerifyDiagnosticsClient&>(
331 Clang.getDiagnosticClient()).HadErrors();
Mike Stump1eb44332009-09-09 15:08:12 +0000332
Daniel Dunbar524b86f2008-10-28 00:38:08 +0000333 // Managed static deconstruction. Useful for making things like
334 // -time-passes usable.
335 llvm::llvm_shutdown();
336
Daniel Dunbar2a79e162009-11-13 03:51:44 +0000337 return (Clang.getDiagnostics().getNumErrors() != 0);
Reid Spencer5f016e22007-07-11 17:01:13 +0000338}
Daniel Dunbard10c5b82009-11-15 00:12:04 +0000339