blob: 6ff5580f2ca16672cac2d0d3217c28f516eaabb0 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- clang.cpp - C-Language Front-end ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This utility may be invoked in the following manner:
11// clang --help - Output help info.
12// clang [options] - Read from stdin.
13// clang [options] file - Read from "file".
14// clang [options] file1 file2 - Read these files.
15//
16//===----------------------------------------------------------------------===//
17//
18// TODO: Options to support:
19//
20// -ffatal-errors
21// -ftabstop=width
22//
23//===----------------------------------------------------------------------===//
24
25#include "clang.h"
26#include "ASTStreamers.h"
27#include "TextDiagnosticBuffer.h"
28#include "TextDiagnosticPrinter.h"
Chris Lattner556beb72007-09-15 22:56:56 +000029#include "clang/Sema/ASTStreamer.h"
30#include "clang/AST/ASTConsumer.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000031#include "clang/Parse/Parser.h"
32#include "clang/Lex/HeaderSearch.h"
33#include "clang/Basic/FileManager.h"
34#include "clang/Basic/SourceManager.h"
35#include "clang/Basic/TargetInfo.h"
36#include "llvm/Support/CommandLine.h"
37#include "llvm/Support/MemoryBuffer.h"
38#include "llvm/System/Signals.h"
39#include <memory>
40using namespace clang;
41
42//===----------------------------------------------------------------------===//
43// Global options.
44//===----------------------------------------------------------------------===//
45
46static llvm::cl::opt<bool>
47Verbose("v", llvm::cl::desc("Enable verbose output"));
48static llvm::cl::opt<bool>
49Stats("stats", llvm::cl::desc("Print performance metrics and statistics"));
50
51enum ProgActions {
52 EmitLLVM, // Emit a .ll file.
53 ParseASTPrint, // Parse ASTs and print them.
Chris Lattner6000dac2007-08-08 22:51:59 +000054 ParseASTDump, // Parse ASTs and dump them.
Ted Kremenek80de08f2007-09-19 21:29:43 +000055 ParseASTView, // Parse ASTs and view them in Graphviz.
Reid Spencer5f016e22007-07-11 17:01:13 +000056 ParseASTCheck, // Parse ASTs and check diagnostics.
Ted Kremenek80de08f2007-09-19 21:29:43 +000057 BuildAST, // Parse ASTs.
Ted Kremenekfddd5182007-08-21 21:42:03 +000058 ParseCFGDump, // Parse ASTS. Build CFGs. Print CFGs.
Ted Kremenek055c2752007-09-06 23:00:42 +000059 ParseCFGView, // Parse ASTS. Build CFGs. View CFGs.
Ted Kremeneke4e63342007-09-06 00:17:54 +000060 AnalysisLiveVariables, // Print results of live-variable analysis.
Ted Kremenek055c2752007-09-06 23:00:42 +000061 WarnDeadStores, // Run DeadStores checker on parsed ASTs.
Ted Kremenek44579782007-09-25 18:37:20 +000062 WarnDeadStoresCheck, // Check diagnostics for "DeadStores".
Ted Kremenek2bf55142007-09-17 20:49:30 +000063 WarnUninitVals, // Run UnitializedVariables checker.
Reid Spencer5f016e22007-07-11 17:01:13 +000064 ParsePrintCallbacks, // Parse and print each callback.
65 ParseSyntaxOnly, // Parse and perform semantic analysis.
66 ParseNoop, // Parse with noop callbacks.
67 RunPreprocessorOnly, // Just lex, no output.
68 PrintPreprocessedInput, // -E mode.
69 DumpTokens // Token dump mode.
70};
71
72static llvm::cl::opt<ProgActions>
73ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
74 llvm::cl::init(ParseSyntaxOnly),
75 llvm::cl::values(
76 clEnumValN(RunPreprocessorOnly, "Eonly",
77 "Just run preprocessor, no output (for timings)"),
78 clEnumValN(PrintPreprocessedInput, "E",
79 "Run preprocessor, emit preprocessed file"),
80 clEnumValN(DumpTokens, "dumptokens",
81 "Run preprocessor, dump internal rep of tokens"),
82 clEnumValN(ParseNoop, "parse-noop",
83 "Run parser with noop callbacks (for timings)"),
84 clEnumValN(ParseSyntaxOnly, "fsyntax-only",
85 "Run parser and perform semantic analysis"),
86 clEnumValN(ParsePrintCallbacks, "parse-print-callbacks",
87 "Run parser and print each callback invoked"),
Chris Lattner556beb72007-09-15 22:56:56 +000088 clEnumValN(BuildAST, "parse-ast",
Reid Spencer5f016e22007-07-11 17:01:13 +000089 "Run parser and build ASTs"),
90 clEnumValN(ParseASTPrint, "parse-ast-print",
91 "Run parser, build ASTs, then print ASTs"),
Chris Lattner6000dac2007-08-08 22:51:59 +000092 clEnumValN(ParseASTDump, "parse-ast-dump",
93 "Run parser, build ASTs, then dump them"),
Ted Kremenek80de08f2007-09-19 21:29:43 +000094 clEnumValN(ParseASTView, "parse-ast-view",
95 "Run parser, build ASTs, and view them with GraphViz."),
Reid Spencer5f016e22007-07-11 17:01:13 +000096 clEnumValN(ParseASTCheck, "parse-ast-check",
97 "Run parser, build ASTs, then check diagnostics"),
Ted Kremenekfddd5182007-08-21 21:42:03 +000098 clEnumValN(ParseCFGDump, "dump-cfg",
Ted Kremenek7dba8602007-08-29 21:56:09 +000099 "Run parser, then build and print CFGs."),
100 clEnumValN(ParseCFGView, "view-cfg",
Ted Kremeneke4e63342007-09-06 00:17:54 +0000101 "Run parser, then build and view CFGs with Graphviz."),
102 clEnumValN(AnalysisLiveVariables, "dump-live-variables",
Ted Kremenek27b07c52007-09-06 21:26:58 +0000103 "Print results of live variable analysis."),
Ted Kremenek786d3372007-09-25 18:05:45 +0000104 clEnumValN(WarnDeadStores, "warn-dead-stores",
Ted Kremenek055c2752007-09-06 23:00:42 +0000105 "Flag warnings of stores to dead variables."),
Ted Kremenek44579782007-09-25 18:37:20 +0000106 clEnumValN(WarnDeadStoresCheck, "warn-dead-stores-check",
107 "Check diagnostics emitted by --warn-dead-stores."),
Ted Kremenek786d3372007-09-25 18:05:45 +0000108 clEnumValN(WarnUninitVals, "warn-uninit-values",
Ted Kremenek2bf55142007-09-17 20:49:30 +0000109 "Flag warnings of uses of unitialized variables."),
Reid Spencer5f016e22007-07-11 17:01:13 +0000110 clEnumValN(EmitLLVM, "emit-llvm",
Ted Kremenek27b07c52007-09-06 21:26:58 +0000111 "Build ASTs then convert to LLVM, emit .ll file"),
Reid Spencer5f016e22007-07-11 17:01:13 +0000112 clEnumValEnd));
113
114//===----------------------------------------------------------------------===//
115// Language Options
116//===----------------------------------------------------------------------===//
117
118enum LangKind {
119 langkind_unspecified,
120 langkind_c,
121 langkind_c_cpp,
122 langkind_cxx,
123 langkind_cxx_cpp,
124 langkind_objc,
125 langkind_objc_cpp,
126 langkind_objcxx,
127 langkind_objcxx_cpp
128};
129
130/* TODO: GCC also accepts:
131 c-header c++-header objective-c-header objective-c++-header
132 assembler assembler-with-cpp
133 ada, f77*, ratfor (!), f95, java, treelang
134 */
135static llvm::cl::opt<LangKind>
136BaseLang("x", llvm::cl::desc("Base language to compile"),
137 llvm::cl::init(langkind_unspecified),
138 llvm::cl::values(clEnumValN(langkind_c, "c", "C"),
139 clEnumValN(langkind_cxx, "c++", "C++"),
140 clEnumValN(langkind_objc, "objective-c", "Objective C"),
141 clEnumValN(langkind_objcxx,"objective-c++","Objective C++"),
142 clEnumValN(langkind_c_cpp, "c-cpp-output",
143 "Preprocessed C"),
144 clEnumValN(langkind_cxx_cpp, "c++-cpp-output",
145 "Preprocessed C++"),
146 clEnumValN(langkind_objc_cpp, "objective-c-cpp-output",
147 "Preprocessed Objective C"),
148 clEnumValN(langkind_objcxx_cpp,"objective-c++-cpp-output",
149 "Preprocessed Objective C++"),
150 clEnumValEnd));
151
152static llvm::cl::opt<bool>
153LangObjC("ObjC", llvm::cl::desc("Set base language to Objective-C"),
154 llvm::cl::Hidden);
155static llvm::cl::opt<bool>
156LangObjCXX("ObjC++", llvm::cl::desc("Set base language to Objective-C++"),
157 llvm::cl::Hidden);
158
159/// InitializeBaseLanguage - Handle the -x foo options or infer a base language
160/// from the input filename.
161static void InitializeBaseLanguage(LangOptions &Options,
162 const std::string &Filename) {
163 if (BaseLang == langkind_unspecified) {
164 std::string::size_type DotPos = Filename.rfind('.');
165 if (LangObjC) {
166 BaseLang = langkind_objc;
167 } else if (LangObjCXX) {
168 BaseLang = langkind_objcxx;
169 } else if (DotPos == std::string::npos) {
170 BaseLang = langkind_c; // Default to C if no extension.
171 } else {
172 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
173 // C header: .h
174 // C++ header: .hh or .H;
175 // assembler no preprocessing: .s
176 // assembler: .S
177 if (Ext == "c")
178 BaseLang = langkind_c;
179 else if (Ext == "i")
180 BaseLang = langkind_c_cpp;
181 else if (Ext == "ii")
182 BaseLang = langkind_cxx_cpp;
183 else if (Ext == "m")
184 BaseLang = langkind_objc;
185 else if (Ext == "mi")
186 BaseLang = langkind_objc_cpp;
187 else if (Ext == "mm" || Ext == "M")
188 BaseLang = langkind_objcxx;
189 else if (Ext == "mii")
190 BaseLang = langkind_objcxx_cpp;
191 else if (Ext == "C" || Ext == "cc" || Ext == "cpp" || Ext == "CPP" ||
192 Ext == "c++" || Ext == "cp" || Ext == "cxx")
193 BaseLang = langkind_cxx;
194 else
195 BaseLang = langkind_c;
196 }
197 }
198
199 // FIXME: implement -fpreprocessed mode.
200 bool NoPreprocess = false;
201
202 switch (BaseLang) {
203 default: assert(0 && "Unknown language kind!");
204 case langkind_c_cpp:
205 NoPreprocess = true;
206 // FALLTHROUGH
207 case langkind_c:
208 break;
209 case langkind_cxx_cpp:
210 NoPreprocess = true;
211 // FALLTHROUGH
212 case langkind_cxx:
213 Options.CPlusPlus = 1;
214 break;
215 case langkind_objc_cpp:
216 NoPreprocess = true;
217 // FALLTHROUGH
218 case langkind_objc:
219 Options.ObjC1 = Options.ObjC2 = 1;
220 break;
221 case langkind_objcxx_cpp:
222 NoPreprocess = true;
223 // FALLTHROUGH
224 case langkind_objcxx:
225 Options.ObjC1 = Options.ObjC2 = 1;
226 Options.CPlusPlus = 1;
227 break;
228 }
229}
230
231/// LangStds - Language standards we support.
232enum LangStds {
233 lang_unspecified,
234 lang_c89, lang_c94, lang_c99,
235 lang_gnu89, lang_gnu99,
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000236 lang_cxx98, lang_gnucxx98,
237 lang_cxx0x, lang_gnucxx0x
Reid Spencer5f016e22007-07-11 17:01:13 +0000238};
239
240static llvm::cl::opt<LangStds>
241LangStd("std", llvm::cl::desc("Language standard to compile for"),
242 llvm::cl::init(lang_unspecified),
243 llvm::cl::values(clEnumValN(lang_c89, "c89", "ISO C 1990"),
244 clEnumValN(lang_c89, "c90", "ISO C 1990"),
245 clEnumValN(lang_c89, "iso9899:1990", "ISO C 1990"),
246 clEnumValN(lang_c94, "iso9899:199409",
247 "ISO C 1990 with amendment 1"),
248 clEnumValN(lang_c99, "c99", "ISO C 1999"),
249// clEnumValN(lang_c99, "c9x", "ISO C 1999"),
250 clEnumValN(lang_c99, "iso9899:1999", "ISO C 1999"),
251// clEnumValN(lang_c99, "iso9899:199x", "ISO C 1999"),
252 clEnumValN(lang_gnu89, "gnu89",
253 "ISO C 1990 with GNU extensions (default for C)"),
254 clEnumValN(lang_gnu99, "gnu99",
255 "ISO C 1999 with GNU extensions"),
256 clEnumValN(lang_gnu99, "gnu9x",
257 "ISO C 1999 with GNU extensions"),
258 clEnumValN(lang_cxx98, "c++98",
259 "ISO C++ 1998 with amendments"),
260 clEnumValN(lang_gnucxx98, "gnu++98",
261 "ISO C++ 1998 with amendments and GNU "
262 "extensions (default for C++)"),
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000263 clEnumValN(lang_cxx0x, "c++0x",
264 "Upcoming ISO C++ 200x with amendments"),
265 clEnumValN(lang_gnucxx0x, "gnu++0x",
266 "Upcoming ISO C++ 200x with amendments and GNU "
267 "extensions (default for C++)"),
Reid Spencer5f016e22007-07-11 17:01:13 +0000268 clEnumValEnd));
269
270static llvm::cl::opt<bool>
271NoOperatorNames("fno-operator-names",
272 llvm::cl::desc("Do not treat C++ operator name keywords as "
273 "synonyms for operators"));
274
275// FIXME: add:
276// -ansi
277// -trigraphs
278// -fdollars-in-identifiers
279static void InitializeLanguageStandard(LangOptions &Options) {
280 if (LangStd == lang_unspecified) {
281 // Based on the base language, pick one.
282 switch (BaseLang) {
283 default: assert(0 && "Unknown base language");
284 case langkind_c:
285 case langkind_c_cpp:
286 case langkind_objc:
287 case langkind_objc_cpp:
288 LangStd = lang_gnu99;
289 break;
290 case langkind_cxx:
291 case langkind_cxx_cpp:
292 case langkind_objcxx:
293 case langkind_objcxx_cpp:
294 LangStd = lang_gnucxx98;
295 break;
296 }
297 }
298
299 switch (LangStd) {
300 default: assert(0 && "Unknown language standard!");
301
302 // Fall through from newer standards to older ones. This isn't really right.
303 // FIXME: Enable specifically the right features based on the language stds.
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000304 case lang_gnucxx0x:
305 case lang_cxx0x:
306 Options.CPlusPlus0x = 1;
307 // FALL THROUGH
Reid Spencer5f016e22007-07-11 17:01:13 +0000308 case lang_gnucxx98:
309 case lang_cxx98:
310 Options.CPlusPlus = 1;
311 Options.CXXOperatorNames = !NoOperatorNames;
312 // FALL THROUGH.
313 case lang_gnu99:
314 case lang_c99:
315 Options.Digraphs = 1;
316 Options.C99 = 1;
317 Options.HexFloats = 1;
318 // FALL THROUGH.
319 case lang_gnu89:
320 Options.BCPLComment = 1; // Only for C99/C++.
321 // FALL THROUGH.
322 case lang_c94:
323 case lang_c89:
324 break;
325 }
326
327 Options.Trigraphs = 1; // -trigraphs or -ansi
328 Options.DollarIdents = 1; // FIXME: Really a target property.
329}
330
331//===----------------------------------------------------------------------===//
332// Our DiagnosticClient implementation
333//===----------------------------------------------------------------------===//
334
335// FIXME: Werror should take a list of things, -Werror=foo,bar
336static llvm::cl::opt<bool>
337WarningsAsErrors("Werror", llvm::cl::desc("Treat all warnings as errors"));
338
339static llvm::cl::opt<bool>
340WarnOnExtensions("pedantic", llvm::cl::init(false),
341 llvm::cl::desc("Issue a warning on uses of GCC extensions"));
342
343static llvm::cl::opt<bool>
344ErrorOnExtensions("pedantic-errors",
345 llvm::cl::desc("Issue an error on uses of GCC extensions"));
346
347static llvm::cl::opt<bool>
348WarnUnusedMacros("Wunused_macros",
349 llvm::cl::desc("Warn for unused macros in the main translation unit"));
350
351
352/// InitializeDiagnostics - Initialize the diagnostic object, based on the
353/// current command line option settings.
354static void InitializeDiagnostics(Diagnostic &Diags) {
355 Diags.setWarningsAsErrors(WarningsAsErrors);
356 Diags.setWarnOnExtensions(WarnOnExtensions);
357 Diags.setErrorOnExtensions(ErrorOnExtensions);
358
359 // Silence the "macro is not used" warning unless requested.
360 if (!WarnUnusedMacros)
361 Diags.setDiagnosticMapping(diag::pp_macro_not_used, diag::MAP_IGNORE);
362}
363
364//===----------------------------------------------------------------------===//
365// Preprocessor Initialization
366//===----------------------------------------------------------------------===//
367
368// FIXME: Preprocessor builtins to support.
369// -A... - Play with #assertions
370// -undef - Undefine all predefined macros
371
372static llvm::cl::list<std::string>
373D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
374 llvm::cl::desc("Predefine the specified macro"));
375static llvm::cl::list<std::string>
376U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
377 llvm::cl::desc("Undefine the specified macro"));
378
379// Append a #define line to Buf for Macro. Macro should be of the form XXX,
380// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
381// "#define XXX Y z W". To get a #define with no value, use "XXX=".
382static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro,
383 const char *Command = "#define ") {
384 Buf.insert(Buf.end(), Command, Command+strlen(Command));
385 if (const char *Equal = strchr(Macro, '=')) {
386 // Turn the = into ' '.
387 Buf.insert(Buf.end(), Macro, Equal);
388 Buf.push_back(' ');
389 Buf.insert(Buf.end(), Equal+1, Equal+strlen(Equal));
390 } else {
391 // Push "macroname 1".
392 Buf.insert(Buf.end(), Macro, Macro+strlen(Macro));
393 Buf.push_back(' ');
394 Buf.push_back('1');
395 }
396 Buf.push_back('\n');
397}
398
399static void InitializePredefinedMacros(Preprocessor &PP,
400 std::vector<char> &Buf) {
401 // FIXME: Implement magic like cpp_init_builtins for things like __STDC__
402 // and __DATE__ etc.
403#if 0
404 /* __STDC__ has the value 1 under normal circumstances.
405 However, if (a) we are in a system header, (b) the option
406 stdc_0_in_system_headers is true (set by target config), and
407 (c) we are not in strictly conforming mode, then it has the
408 value 0. (b) and (c) are already checked in cpp_init_builtins. */
409 //case BT_STDC:
410 if (cpp_in_system_header (pfile))
411 number = 0;
412 else
413 number = 1;
414 break;
415#endif
416 // These should all be defined in the preprocessor according to the
417 // current language configuration.
418 DefineBuiltinMacro(Buf, "__STDC__=1");
419 //DefineBuiltinMacro(Buf, "__ASSEMBLER__=1");
Chris Lattner94fea5a2007-07-22 22:11:35 +0000420 if (PP.getLangOptions().C99 && !PP.getLangOptions().CPlusPlus)
Reid Spencer5f016e22007-07-11 17:01:13 +0000421 DefineBuiltinMacro(Buf, "__STDC_VERSION__=199901L");
Chris Lattner94fea5a2007-07-22 22:11:35 +0000422 else if (0) // STDC94 ?
Reid Spencer5f016e22007-07-11 17:01:13 +0000423 DefineBuiltinMacro(Buf, "__STDC_VERSION__=199409L");
424
425 DefineBuiltinMacro(Buf, "__STDC_HOSTED__=1");
426 if (PP.getLangOptions().ObjC1)
427 DefineBuiltinMacro(Buf, "__OBJC__=1");
428 if (PP.getLangOptions().ObjC2)
429 DefineBuiltinMacro(Buf, "__OBJC2__=1");
430
431 // Get the target #defines.
432 PP.getTargetInfo().getTargetDefines(Buf);
433
434 // Compiler set macros.
435 DefineBuiltinMacro(Buf, "__APPLE_CC__=5250");
436 DefineBuiltinMacro(Buf, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__=1030");
437 DefineBuiltinMacro(Buf, "__GNUC_MINOR__=0");
438 DefineBuiltinMacro(Buf, "__GNUC_PATCHLEVEL__=1");
439 DefineBuiltinMacro(Buf, "__GNUC__=4");
440 DefineBuiltinMacro(Buf, "__GXX_ABI_VERSION=1002");
441 DefineBuiltinMacro(Buf, "__VERSION__=\"4.0.1 (Apple Computer, Inc. "
442 "build 5250)\"");
443
444 // Build configuration options.
445 DefineBuiltinMacro(Buf, "__DYNAMIC__=1");
446 DefineBuiltinMacro(Buf, "__FINITE_MATH_ONLY__=0");
447 DefineBuiltinMacro(Buf, "__NO_INLINE__=1");
448 DefineBuiltinMacro(Buf, "__PIC__=1");
449
450
451 if (PP.getLangOptions().CPlusPlus) {
452 DefineBuiltinMacro(Buf, "__DEPRECATED=1");
453 DefineBuiltinMacro(Buf, "__EXCEPTIONS=1");
454 DefineBuiltinMacro(Buf, "__GNUG__=4");
455 DefineBuiltinMacro(Buf, "__GXX_WEAK__=1");
456 DefineBuiltinMacro(Buf, "__cplusplus=1");
457 DefineBuiltinMacro(Buf, "__private_extern__=extern");
458 }
459
460 // FIXME: Should emit a #line directive here.
461
462 // Add macros from the command line.
463 // FIXME: Should traverse the #define/#undef lists in parallel.
464 for (unsigned i = 0, e = D_macros.size(); i != e; ++i)
465 DefineBuiltinMacro(Buf, D_macros[i].c_str());
466 for (unsigned i = 0, e = U_macros.size(); i != e; ++i)
467 DefineBuiltinMacro(Buf, U_macros[i].c_str(), "#undef ");
468}
469
470//===----------------------------------------------------------------------===//
471// Preprocessor include path information.
472//===----------------------------------------------------------------------===//
473
474// This tool exports a large number of command line options to control how the
475// preprocessor searches for header files. At root, however, the Preprocessor
476// object takes a very simple interface: a list of directories to search for
477//
478// FIXME: -nostdinc,-nostdinc++
Chris Lattner0c946412007-08-26 17:47:35 +0000479// FIXME: -imultilib
Reid Spencer5f016e22007-07-11 17:01:13 +0000480//
481// FIXME: -include,-imacros
482
483static llvm::cl::opt<bool>
484nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
485
486// Various command line options. These four add directories to each chain.
487static llvm::cl::list<std::string>
488F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
489 llvm::cl::desc("Add directory to framework include search path"));
490static llvm::cl::list<std::string>
491I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
492 llvm::cl::desc("Add directory to include search path"));
493static llvm::cl::list<std::string>
494idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
495 llvm::cl::desc("Add directory to AFTER include search path"));
496static llvm::cl::list<std::string>
497iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
498 llvm::cl::desc("Add directory to QUOTE include search path"));
499static llvm::cl::list<std::string>
500isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
501 llvm::cl::desc("Add directory to SYSTEM include search path"));
502
503// These handle -iprefix/-iwithprefix/-iwithprefixbefore.
504static llvm::cl::list<std::string>
505iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix,
506 llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix"));
507static llvm::cl::list<std::string>
508iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix,
509 llvm::cl::desc("Set directory to SYSTEM include search path with prefix"));
510static llvm::cl::list<std::string>
511iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"),
512 llvm::cl::Prefix,
513 llvm::cl::desc("Set directory to include search path with prefix"));
514
Chris Lattner0c946412007-08-26 17:47:35 +0000515static llvm::cl::opt<std::string>
516isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),
517 llvm::cl::desc("Set the system root directory (usually /)"));
518
Reid Spencer5f016e22007-07-11 17:01:13 +0000519// Finally, implement the code that groks the options above.
520enum IncludeDirGroup {
521 Quoted = 0,
522 Angled,
523 System,
524 After
525};
526
527static std::vector<DirectoryLookup> IncludeGroup[4];
528
529/// AddPath - Add the specified path to the specified group list.
530///
531static void AddPath(const std::string &Path, IncludeDirGroup Group,
532 bool isCXXAware, bool isUserSupplied,
533 bool isFramework, FileManager &FM) {
Chris Lattner0c946412007-08-26 17:47:35 +0000534 const DirectoryEntry *DE;
535 if (Group == System)
536 DE = FM.getDirectory(isysroot + "/" + Path);
537 else
538 DE = FM.getDirectory(Path);
539
Reid Spencer5f016e22007-07-11 17:01:13 +0000540 if (DE == 0) {
541 if (Verbose)
542 fprintf(stderr, "ignoring nonexistent directory \"%s\"\n",
543 Path.c_str());
544 return;
545 }
546
547 DirectoryLookup::DirType Type;
548 if (Group == Quoted || Group == Angled)
549 Type = DirectoryLookup::NormalHeaderDir;
550 else if (isCXXAware)
551 Type = DirectoryLookup::SystemHeaderDir;
552 else
553 Type = DirectoryLookup::ExternCSystemHeaderDir;
554
555 IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
556 isFramework));
557}
558
559/// RemoveDuplicates - If there are duplicate directory entries in the specified
560/// search list, remove the later (dead) ones.
561static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList) {
562 std::set<const DirectoryEntry *> SeenDirs;
563 for (unsigned i = 0; i != SearchList.size(); ++i) {
564 // If this isn't the first time we've seen this dir, remove it.
565 if (!SeenDirs.insert(SearchList[i].getDir()).second) {
566 if (Verbose)
567 fprintf(stderr, "ignoring duplicate directory \"%s\"\n",
568 SearchList[i].getDir()->getName());
569 SearchList.erase(SearchList.begin()+i);
570 --i;
571 }
572 }
573}
574
575/// InitializeIncludePaths - Process the -I options and set them in the
576/// HeaderSearch object.
577static void InitializeIncludePaths(HeaderSearch &Headers, FileManager &FM,
578 Diagnostic &Diags, const LangOptions &Lang) {
579 // Handle -F... options.
580 for (unsigned i = 0, e = F_dirs.size(); i != e; ++i)
581 AddPath(F_dirs[i], Angled, false, true, true, FM);
582
583 // Handle -I... options.
584 for (unsigned i = 0, e = I_dirs.size(); i != e; ++i) {
585 if (I_dirs[i] == "-") {
586 // -I- is a deprecated GCC feature.
587 Diags.Report(SourceLocation(), diag::err_pp_I_dash_not_supported);
588 } else {
589 AddPath(I_dirs[i], Angled, false, true, false, FM);
590 }
591 }
592
593 // Handle -idirafter... options.
594 for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
595 AddPath(idirafter_dirs[i], After, false, true, false, FM);
596
597 // Handle -iquote... options.
598 for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
599 AddPath(iquote_dirs[i], Quoted, false, true, false, FM);
600
601 // Handle -isystem... options.
602 for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
603 AddPath(isystem_dirs[i], System, false, true, false, FM);
604
605 // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
606 // parallel, processing the values in order of occurance to get the right
607 // prefixes.
608 {
609 std::string Prefix = ""; // FIXME: this isn't the correct default prefix.
610 unsigned iprefix_idx = 0;
611 unsigned iwithprefix_idx = 0;
612 unsigned iwithprefixbefore_idx = 0;
613 bool iprefix_done = iprefix_vals.empty();
614 bool iwithprefix_done = iwithprefix_vals.empty();
615 bool iwithprefixbefore_done = iwithprefixbefore_vals.empty();
616 while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) {
617 if (!iprefix_done &&
618 (iwithprefix_done ||
619 iprefix_vals.getPosition(iprefix_idx) <
620 iwithprefix_vals.getPosition(iwithprefix_idx)) &&
621 (iwithprefixbefore_done ||
622 iprefix_vals.getPosition(iprefix_idx) <
623 iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
624 Prefix = iprefix_vals[iprefix_idx];
625 ++iprefix_idx;
626 iprefix_done = iprefix_idx == iprefix_vals.size();
627 } else if (!iwithprefix_done &&
628 (iwithprefixbefore_done ||
629 iwithprefix_vals.getPosition(iwithprefix_idx) <
630 iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
631 AddPath(Prefix+iwithprefix_vals[iwithprefix_idx],
632 System, false, false, false, FM);
633 ++iwithprefix_idx;
634 iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
635 } else {
636 AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx],
637 Angled, false, false, false, FM);
638 ++iwithprefixbefore_idx;
639 iwithprefixbefore_done =
640 iwithprefixbefore_idx == iwithprefixbefore_vals.size();
641 }
642 }
643 }
644
645 // FIXME: Add contents of the CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH,
646 // OBJC_INCLUDE_PATH, OBJCPLUS_INCLUDE_PATH environment variables.
647
648 // FIXME: temporary hack: hard-coded paths.
649 // FIXME: get these from the target?
650 if (!nostdinc) {
651 if (Lang.CPlusPlus) {
652 AddPath("/usr/include/c++/4.0.0", System, true, false, false, FM);
653 AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false,
654 false, FM);
655 AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false,FM);
656 }
657
658 AddPath("/usr/local/include", System, false, false, false, FM);
659 // leopard
660 AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System,
661 false, false, false, FM);
662 AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include",
663 System, false, false, false, FM);
664 AddPath("/usr/lib/gcc/powerpc-apple-darwin9/"
665 "4.0.1/../../../../powerpc-apple-darwin0/include",
666 System, false, false, false, FM);
667
668 // tiger
669 AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System,
670 false, false, false, FM);
671 AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include",
672 System, false, false, false, FM);
673 AddPath("/usr/lib/gcc/powerpc-apple-darwin8/"
674 "4.0.1/../../../../powerpc-apple-darwin8/include",
675 System, false, false, false, FM);
676
677 AddPath("/usr/include", System, false, false, false, FM);
678 AddPath("/System/Library/Frameworks", System, true, false, true, FM);
679 AddPath("/Library/Frameworks", System, true, false, true, FM);
680 }
681
682 // Now that we have collected all of the include paths, merge them all
683 // together and tell the preprocessor about them.
684
685 // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
686 std::vector<DirectoryLookup> SearchList;
687 SearchList = IncludeGroup[Angled];
688 SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
689 IncludeGroup[System].end());
690 SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
691 IncludeGroup[After].end());
692 RemoveDuplicates(SearchList);
693 RemoveDuplicates(IncludeGroup[Quoted]);
694
695 // Prepend QUOTED list on the search list.
696 SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
697 IncludeGroup[Quoted].end());
698
699
700 bool DontSearchCurDir = false; // TODO: set to true if -I- is set?
701 Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
702 DontSearchCurDir);
703
704 // If verbose, print the list of directories that will be searched.
705 if (Verbose) {
706 fprintf(stderr, "#include \"...\" search starts here:\n");
707 unsigned QuotedIdx = IncludeGroup[Quoted].size();
708 for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
709 if (i == QuotedIdx)
710 fprintf(stderr, "#include <...> search starts here:\n");
711 fprintf(stderr, " %s\n", SearchList[i].getDir()->getName());
712 }
713 }
714}
715
716
717// Read any files specified by -imacros or -include.
718static void ReadPrologFiles(Preprocessor &PP, std::vector<char> &Buf) {
719 // FIXME: IMPLEMENT
720}
721
722//===----------------------------------------------------------------------===//
723// Basic Parser driver
724//===----------------------------------------------------------------------===//
725
726static void ParseFile(Preprocessor &PP, MinimalAction *PA, unsigned MainFileID){
727 Parser P(PP, *PA);
728 PP.EnterSourceFile(MainFileID, 0, true);
729
730 // Parsing the specified input file.
731 P.ParseTranslationUnit();
732 delete PA;
733}
734
735//===----------------------------------------------------------------------===//
736// Main driver
737//===----------------------------------------------------------------------===//
738
739/// InitializePreprocessor - Initialize the preprocessor getting it and the
740/// environment ready to process a single file. This returns the file ID for the
741/// input file. If a failure happens, it returns 0.
742///
743static unsigned InitializePreprocessor(Preprocessor &PP,
744 const std::string &InFile,
745 SourceManager &SourceMgr,
746 HeaderSearch &HeaderInfo,
747 const LangOptions &LangInfo,
748 std::vector<char> &PrologMacros) {
749 FileManager &FileMgr = HeaderInfo.getFileMgr();
750
751 // Install things like __POWERPC__, __GNUC__, etc into the macro table.
752 InitializePredefinedMacros(PP, PrologMacros);
753
754 // Read any files specified by -imacros or -include.
755 ReadPrologFiles(PP, PrologMacros);
756
757 // Figure out where to get and map in the main file.
758 unsigned MainFileID = 0;
759 if (InFile != "-") {
760 const FileEntry *File = FileMgr.getFile(InFile);
761 if (File) MainFileID = SourceMgr.createFileID(File, SourceLocation());
762 if (MainFileID == 0) {
763 fprintf(stderr, "Error reading '%s'!\n",InFile.c_str());
764 return 0;
765 }
766 } else {
767 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
768 if (SB) MainFileID = SourceMgr.createFileIDForMemBuffer(SB);
769 if (MainFileID == 0) {
770 fprintf(stderr, "Error reading standard input! Empty?\n");
771 return 0;
772 }
773 }
774
775 // Now that we have emitted the predefined macros, #includes, etc into
776 // PrologMacros, preprocess it to populate the initial preprocessor state.
777
778 // Memory buffer must end with a null byte!
779 PrologMacros.push_back(0);
780
781 llvm::MemoryBuffer *SB =
782 llvm::MemoryBuffer::getMemBuffer(&PrologMacros.front(),&PrologMacros.back(),
783 "<predefines>");
784 assert(SB && "Cannot fail to create predefined source buffer");
785 unsigned FileID = SourceMgr.createFileIDForMemBuffer(SB);
786 assert(FileID && "Could not create FileID for predefines?");
787
788 // Start parsing the predefines.
789 PP.EnterSourceFile(FileID, 0);
790
791 // Lex the file, which will read all the macros.
Chris Lattnerd2177732007-07-20 16:59:19 +0000792 Token Tok;
Reid Spencer5f016e22007-07-11 17:01:13 +0000793 PP.Lex(Tok);
794 assert(Tok.getKind() == tok::eof && "Didn't read entire file!");
795
796 // Once we've read this, we're done.
797 return MainFileID;
798}
799
800/// ProcessInputFile - Process a single input file with the specified state.
801///
802static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
803 const std::string &InFile,
804 SourceManager &SourceMgr,
805 TextDiagnostics &OurDiagnosticClient,
806 HeaderSearch &HeaderInfo,
807 const LangOptions &LangInfo) {
Chris Lattnerbd247762007-07-22 06:05:44 +0000808 bool ClearSourceMgr = false;
Reid Spencer5f016e22007-07-11 17:01:13 +0000809 switch (ProgAction) {
810 default:
811 fprintf(stderr, "Unexpected program action!\n");
812 return;
813 case DumpTokens: { // Token dump mode.
Chris Lattnerd2177732007-07-20 16:59:19 +0000814 Token Tok;
Reid Spencer5f016e22007-07-11 17:01:13 +0000815 // Start parsing the specified input file.
816 PP.EnterSourceFile(MainFileID, 0, true);
817 do {
818 PP.Lex(Tok);
819 PP.DumpToken(Tok, true);
820 fprintf(stderr, "\n");
821 } while (Tok.getKind() != tok::eof);
Chris Lattnerbd247762007-07-22 06:05:44 +0000822 ClearSourceMgr = true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000823 break;
824 }
825 case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
Chris Lattnerd2177732007-07-20 16:59:19 +0000826 Token Tok;
Reid Spencer5f016e22007-07-11 17:01:13 +0000827 // Start parsing the specified input file.
828 PP.EnterSourceFile(MainFileID, 0, true);
829 do {
830 PP.Lex(Tok);
831 } while (Tok.getKind() != tok::eof);
Chris Lattnerbd247762007-07-22 06:05:44 +0000832 ClearSourceMgr = true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000833 break;
834 }
835
836 case PrintPreprocessedInput: // -E mode.
837 DoPrintPreprocessedInput(MainFileID, PP, LangInfo);
Chris Lattnerbd247762007-07-22 06:05:44 +0000838 ClearSourceMgr = true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000839 break;
840
841 case ParseNoop: // -parse-noop
842 ParseFile(PP, new MinimalAction(), MainFileID);
Chris Lattnerbd247762007-07-22 06:05:44 +0000843 ClearSourceMgr = true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000844 break;
845
846 case ParsePrintCallbacks:
847 ParseFile(PP, CreatePrintParserActionsAction(), MainFileID);
Chris Lattnerbd247762007-07-22 06:05:44 +0000848 ClearSourceMgr = true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000849 break;
850 case ParseSyntaxOnly: // -fsyntax-only
Chris Lattner556beb72007-09-15 22:56:56 +0000851 case BuildAST: {
852 ASTConsumer NullConsumer;
853 ParseAST(PP, MainFileID, NullConsumer, Stats);
Reid Spencer5f016e22007-07-11 17:01:13 +0000854 break;
Chris Lattner556beb72007-09-15 22:56:56 +0000855 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000856 case ParseASTPrint: {
857 std::auto_ptr<ASTConsumer> C(CreateASTPrinter());
858 ParseAST(PP, MainFileID, *C.get(), Stats);
Reid Spencer5f016e22007-07-11 17:01:13 +0000859 break;
Chris Lattner3d4997d2007-09-15 23:02:28 +0000860 }
861 case ParseASTDump: {
862 std::auto_ptr<ASTConsumer> C(CreateASTDumper());
863 ParseAST(PP, MainFileID, *C.get(), Stats);
Chris Lattner6000dac2007-08-08 22:51:59 +0000864 break;
Chris Lattner3d4997d2007-09-15 23:02:28 +0000865 }
Ted Kremenek80de08f2007-09-19 21:29:43 +0000866 case ParseASTView: {
867 std::auto_ptr<ASTConsumer> C(CreateASTViewer());
868 ParseAST(PP, MainFileID, *C.get(), Stats);
869 break;
870 }
Ted Kremenekfddd5182007-08-21 21:42:03 +0000871 case ParseCFGDump:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000872 case ParseCFGView: {
873 std::auto_ptr<ASTConsumer> C(CreateCFGDumper(ProgAction == ParseCFGView));
874 ParseAST(PP, MainFileID, *C.get(), Stats);
Ted Kremenekfddd5182007-08-21 21:42:03 +0000875 break;
Chris Lattnerc0508f92007-09-15 23:21:08 +0000876 }
877 case AnalysisLiveVariables: {
878 std::auto_ptr<ASTConsumer> C(CreateLiveVarAnalyzer());
879 ParseAST(PP, MainFileID, *C.get(), Stats);
Ted Kremenek7dba8602007-08-29 21:56:09 +0000880 break;
Chris Lattnerc0508f92007-09-15 23:21:08 +0000881 }
882 case WarnDeadStores: {
883 std::auto_ptr<ASTConsumer> C(CreateDeadStoreChecker(PP.getDiagnostics()));
884 ParseAST(PP, MainFileID, *C.get(), Stats);
Ted Kremenek055c2752007-09-06 23:00:42 +0000885 break;
Chris Lattnerc0508f92007-09-15 23:21:08 +0000886 }
Ted Kremenek44579782007-09-25 18:37:20 +0000887 case WarnDeadStoresCheck: {
888 std::auto_ptr<ASTConsumer> C(CreateDeadStoreChecker(PP.getDiagnostics()));
889 exit (CheckASTConsumer(PP, MainFileID, C));
890 break;
891 }
892
Ted Kremenek2bf55142007-09-17 20:49:30 +0000893 case WarnUninitVals: {
894 std::auto_ptr<ASTConsumer> C(CreateUnitValsChecker(PP.getDiagnostics()));
895 ParseAST(PP, MainFileID, *C.get(), Stats);
896 break;
897 }
Chris Lattner580980b2007-09-16 19:46:59 +0000898 case EmitLLVM: {
899 std::auto_ptr<ASTConsumer> C(CreateLLVMEmitter(PP.getDiagnostics()));
900 ParseAST(PP, MainFileID, *C.get(), Stats);
Reid Spencer5f016e22007-07-11 17:01:13 +0000901 break;
Chris Lattner580980b2007-09-16 19:46:59 +0000902 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000903 case ParseASTCheck:
904 exit(CheckDiagnostics(PP, MainFileID));
905 break;
906 }
907
908 if (Stats) {
909 fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str());
910 PP.PrintStats();
911 PP.getIdentifierTable().PrintStats();
912 HeaderInfo.PrintStats();
Chris Lattnerbd247762007-07-22 06:05:44 +0000913 if (ClearSourceMgr)
914 SourceMgr.PrintStats();
Reid Spencer5f016e22007-07-11 17:01:13 +0000915 fprintf(stderr, "\n");
916 }
Chris Lattnerbd247762007-07-22 06:05:44 +0000917
918 // For a multi-file compilation, some things are ok with nuking the source
919 // manager tables, other require stable fileid/macroid's across multiple
920 // files.
921 if (ClearSourceMgr) {
922 SourceMgr.clearIDTables();
923 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000924}
925
926static llvm::cl::list<std::string>
927InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
928
929
930int main(int argc, char **argv) {
931 llvm::cl::ParseCommandLineOptions(argc, argv, " llvm cfe\n");
932 llvm::sys::PrintStackTraceOnErrorSignal();
933
934 // If no input was specified, read from stdin.
935 if (InputFilenames.empty())
936 InputFilenames.push_back("-");
937
938 /// Create a SourceManager object. This tracks and owns all the file buffers
939 /// allocated to the program.
940 SourceManager SourceMgr;
941
942 // Create a file manager object to provide access to and cache the filesystem.
943 FileManager FileMgr;
944
945 // Initialize language options, inferring file types from input filenames.
946 // FIXME: This infers info from the first file, we should clump by language
947 // to handle 'x.c y.c a.cpp b.cpp'.
948 LangOptions LangInfo;
949 InitializeBaseLanguage(LangInfo, InputFilenames[0]);
950 InitializeLanguageStandard(LangInfo);
951
952 std::auto_ptr<TextDiagnostics> DiagClient;
953 if (ProgAction != ParseASTCheck) {
954 // Print diagnostics to stderr by default.
955 DiagClient.reset(new TextDiagnosticPrinter(SourceMgr));
956 } else {
957 // When checking diagnostics, just buffer them up.
958 DiagClient.reset(new TextDiagnosticBuffer(SourceMgr));
959
960 if (InputFilenames.size() != 1) {
961 fprintf(stderr,
962 "parse-ast-check only works on single input files for now.\n");
963 return 1;
964 }
965 }
966
967 // Configure our handling of diagnostics.
968 Diagnostic Diags(*DiagClient);
969 InitializeDiagnostics(Diags);
970
971 // Get information about the targets being compiled for. Note that this
972 // pointer and the TargetInfoImpl objects are never deleted by this toy
973 // driver.
974 TargetInfo *Target = CreateTargetInfo(Diags);
975 if (Target == 0) {
976 fprintf(stderr,
977 "Sorry, don't know what target this is, please use -arch.\n");
978 exit(1);
979 }
980
981 // Process the -I options and set them in the HeaderInfo.
982 HeaderSearch HeaderInfo(FileMgr);
983 DiagClient->setHeaderSearch(HeaderInfo);
984 InitializeIncludePaths(HeaderInfo, FileMgr, Diags, LangInfo);
985
986 for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
987 // Set up the preprocessor with these options.
988 Preprocessor PP(Diags, LangInfo, *Target, SourceMgr, HeaderInfo);
989 DiagClient->setPreprocessor(PP);
990 const std::string &InFile = InputFilenames[i];
991 std::vector<char> PrologMacros;
992 unsigned MainFileID = InitializePreprocessor(PP, InFile, SourceMgr,
993 HeaderInfo, LangInfo,
994 PrologMacros);
995
996 if (!MainFileID) continue;
997
998 ProcessInputFile(PP, MainFileID, InFile, SourceMgr,
999 *DiagClient, HeaderInfo, LangInfo);
1000 HeaderInfo.ClearFileInfo();
1001 }
1002
1003 unsigned NumDiagnostics = Diags.getNumDiagnostics();
1004
1005 if (NumDiagnostics)
1006 fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
1007 (NumDiagnostics == 1 ? "" : "s"));
1008
1009 if (Stats) {
1010 // Printed from high-to-low level.
1011 SourceMgr.PrintStats();
1012 FileMgr.PrintStats();
1013 fprintf(stderr, "\n");
1014 }
1015
Chris Lattner96f1a642007-07-21 05:40:53 +00001016 return Diags.getNumErrors() != 0;
Reid Spencer5f016e22007-07-11 17:01:13 +00001017}