diff options
Diffstat (limited to 'clang/Driver/clang.cpp')
-rw-r--r-- | clang/Driver/clang.cpp | 1490 |
1 files changed, 0 insertions, 1490 deletions
diff --git a/clang/Driver/clang.cpp b/clang/Driver/clang.cpp deleted file mode 100644 index 1071659..0000000 --- a/clang/Driver/clang.cpp +++ /dev/null @@ -1,1490 +0,0 @@ -//===--- clang.cpp - C-Language Front-end ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This utility may be invoked in the following manner: -// clang --help - Output help info. -// clang [options] - Read from stdin. -// clang [options] file - Read from "file". -// clang [options] file1 file2 - Read these files. -// -//===----------------------------------------------------------------------===// -// -// TODO: Options to support: -// -// -ffatal-errors -// -ftabstop=width -// -//===----------------------------------------------------------------------===// - -#include "clang.h" -#include "ASTConsumers.h" -#include "TextDiagnosticBuffer.h" -#include "TextDiagnosticPrinter.h" -#include "HTMLDiagnostics.h" -#include "clang/Analysis/PathDiagnostic.h" -#include "clang/AST/TranslationUnit.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Sema/ParseAST.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/Parse/Parser.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/Module.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/System/Signals.h" -#include "llvm/Config/config.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/System/Path.h" -#include <memory> -#include <fstream> -#include <algorithm> -using namespace clang; - -//===----------------------------------------------------------------------===// -// Global options. -//===----------------------------------------------------------------------===// - -static llvm::cl::opt<bool> -Verbose("v", llvm::cl::desc("Enable verbose output")); -static llvm::cl::opt<bool> -Stats("print-stats", - llvm::cl::desc("Print performance metrics and statistics")); - -enum ProgActions { - RewriteObjC, // ObjC->C Rewriter. - RewriteMacros, // Expand macros but not #includes. - HTMLTest, // HTML displayer testing stuff. - EmitLLVM, // Emit a .ll file. - EmitBC, // Emit a .bc file. - SerializeAST, // Emit a .ast file. - EmitHTML, // Translate input source into HTML. - ASTPrint, // Parse ASTs and print them. - ASTDump, // Parse ASTs and dump them. - ASTView, // Parse ASTs and view them in Graphviz. - ParseCFGDump, // Parse ASTS. Build CFGs. Print CFGs. - ParseCFGView, // Parse ASTS. Build CFGs. View CFGs. - AnalysisLiveVariables, // Print results of live-variable analysis. - AnalysisGRSimpleVals, // Perform graph-reachability constant prop. - AnalysisGRSimpleValsView, // Visualize results of path-sens. analysis. - CheckerCFRef, // Run the Core Foundation Ref. Count Checker. - WarnDeadStores, // Run DeadStores checker on parsed ASTs. - WarnDeadStoresCheck, // Check diagnostics for "DeadStores". - WarnUninitVals, // Run UnitializedVariables checker. - TestSerialization, // Run experimental serialization code. - ParsePrintCallbacks, // Parse and print each callback. - ParseSyntaxOnly, // Parse and perform semantic analysis. - ParseNoop, // Parse with noop callbacks. - RunPreprocessorOnly, // Just lex, no output. - PrintPreprocessedInput, // -E mode. - DumpTokens // Token dump mode. -}; - -static llvm::cl::opt<ProgActions> -ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore, - llvm::cl::init(ParseSyntaxOnly), - llvm::cl::values( - clEnumValN(RunPreprocessorOnly, "Eonly", - "Just run preprocessor, no output (for timings)"), - clEnumValN(PrintPreprocessedInput, "E", - "Run preprocessor, emit preprocessed file"), - clEnumValN(DumpTokens, "dumptokens", - "Run preprocessor, dump internal rep of tokens"), - clEnumValN(ParseNoop, "parse-noop", - "Run parser with noop callbacks (for timings)"), - clEnumValN(ParseSyntaxOnly, "fsyntax-only", - "Run parser and perform semantic analysis"), - clEnumValN(ParsePrintCallbacks, "parse-print-callbacks", - "Run parser and print each callback invoked"), - clEnumValN(EmitHTML, "emit-html", - "Output input source as HTML"), - clEnumValN(ASTPrint, "ast-print", - "Build ASTs and then pretty-print them"), - clEnumValN(ASTDump, "ast-dump", - "Build ASTs and then debug dump them"), - clEnumValN(ASTView, "ast-view", - "Build ASTs and view them with GraphViz"), - clEnumValN(ParseCFGDump, "dump-cfg", - "Run parser, then build and print CFGs"), - clEnumValN(ParseCFGView, "view-cfg", - "Run parser, then build and view CFGs with Graphviz"), - clEnumValN(AnalysisLiveVariables, "dump-live-variables", - "Print results of live variable analysis"), - clEnumValN(WarnDeadStores, "warn-dead-stores", - "Flag warnings of stores to dead variables"), - clEnumValN(WarnUninitVals, "warn-uninit-values", - "Flag warnings of uses of unitialized variables"), - clEnumValN(AnalysisGRSimpleVals, "checker-simple", - "Perform path-sensitive constant propagation"), - clEnumValN(CheckerCFRef, "checker-cfref", - "Run the Core Foundation reference count checker"), - clEnumValN(TestSerialization, "test-pickling", - "Run prototype serialization code"), - clEnumValN(EmitLLVM, "emit-llvm", - "Build ASTs then convert to LLVM, emit .ll file"), - clEnumValN(EmitBC, "emit-llvm-bc", - "Build ASTs then convert to LLVM, emit .bc file"), - clEnumValN(SerializeAST, "serialize", - "Build ASTs and emit .ast file"), - clEnumValN(RewriteObjC, "rewrite-objc", - "Rewrite ObjC into C (code rewriter example)"), - clEnumValN(RewriteMacros, "rewrite-macros", - "Expand macros without full preprocessing"), - clEnumValEnd)); - - -static llvm::cl::opt<std::string> -OutputFile("o", - llvm::cl::value_desc("path"), - llvm::cl::desc("Specify output file (for --serialize, this is a directory)")); - -//===----------------------------------------------------------------------===// -// Code Generator Options -//===----------------------------------------------------------------------===// -static llvm::cl::opt<bool> -GenerateDebugInfo("g", - llvm::cl::desc("Generate source level debug information")); - -//===----------------------------------------------------------------------===// -// Diagnostic Options -//===----------------------------------------------------------------------===// - -static llvm::cl::opt<bool> -VerifyDiagnostics("verify", - llvm::cl::desc("Verify emitted diagnostics and warnings")); - -static llvm::cl::opt<std::string> -HTMLDiag("html-diags", - llvm::cl::desc("Generate HTML to report diagnostics"), - llvm::cl::value_desc("HTML directory")); - -//===----------------------------------------------------------------------===// -// Analyzer Options -//===----------------------------------------------------------------------===// - -static llvm::cl::opt<bool> -VisualizeEG("visualize-egraph", - llvm::cl::desc("Display static analysis Exploded Graph")); - -static llvm::cl::opt<bool> -AnalyzeAll("checker-opt-analyze-headers", - llvm::cl::desc("Force the static analyzer to analyze " - "functions defined in header files")); - -//===----------------------------------------------------------------------===// -// Language Options -//===----------------------------------------------------------------------===// - -enum LangKind { - langkind_unspecified, - langkind_c, - langkind_c_cpp, - langkind_cxx, - langkind_cxx_cpp, - langkind_objc, - langkind_objc_cpp, - langkind_objcxx, - langkind_objcxx_cpp -}; - -/* TODO: GCC also accepts: - c-header c++-header objective-c-header objective-c++-header - assembler assembler-with-cpp - ada, f77*, ratfor (!), f95, java, treelang - */ -static llvm::cl::opt<LangKind> -BaseLang("x", llvm::cl::desc("Base language to compile"), - llvm::cl::init(langkind_unspecified), - llvm::cl::values(clEnumValN(langkind_c, "c", "C"), - clEnumValN(langkind_cxx, "c++", "C++"), - clEnumValN(langkind_objc, "objective-c", "Objective C"), - clEnumValN(langkind_objcxx,"objective-c++","Objective C++"), - clEnumValN(langkind_c_cpp, "c-cpp-output", - "Preprocessed C"), - clEnumValN(langkind_cxx_cpp, "c++-cpp-output", - "Preprocessed C++"), - clEnumValN(langkind_objc_cpp, "objective-c-cpp-output", - "Preprocessed Objective C"), - clEnumValN(langkind_objcxx_cpp,"objective-c++-cpp-output", - "Preprocessed Objective C++"), - clEnumValEnd)); - -static llvm::cl::opt<bool> -LangObjC("ObjC", llvm::cl::desc("Set base language to Objective-C"), - llvm::cl::Hidden); -static llvm::cl::opt<bool> -LangObjCXX("ObjC++", llvm::cl::desc("Set base language to Objective-C++"), - llvm::cl::Hidden); - -/// InitializeBaseLanguage - Handle the -x foo options. -static void InitializeBaseLanguage() { - if (LangObjC) - BaseLang = langkind_objc; - else if (LangObjCXX) - BaseLang = langkind_objcxx; -} - -static LangKind GetLanguage(const std::string &Filename) { - if (BaseLang != langkind_unspecified) - return BaseLang; - - std::string::size_type DotPos = Filename.rfind('.'); - - if (DotPos == std::string::npos) { - BaseLang = langkind_c; // Default to C if no extension. - return langkind_c; - } - - std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); - // C header: .h - // C++ header: .hh or .H; - // assembler no preprocessing: .s - // assembler: .S - if (Ext == "c") - return langkind_c; - else if (Ext == "i") - return langkind_c_cpp; - else if (Ext == "ii") - return langkind_cxx_cpp; - else if (Ext == "m") - return langkind_objc; - else if (Ext == "mi") - return langkind_objc_cpp; - else if (Ext == "mm" || Ext == "M") - return langkind_objcxx; - else if (Ext == "mii") - return langkind_objcxx_cpp; - else if (Ext == "C" || Ext == "cc" || Ext == "cpp" || Ext == "CPP" || - Ext == "c++" || Ext == "cp" || Ext == "cxx") - return langkind_cxx; - else - return langkind_c; -} - - -static void InitializeLangOptions(LangOptions &Options, LangKind LK) { - // FIXME: implement -fpreprocessed mode. - bool NoPreprocess = false; - - switch (LK) { - default: assert(0 && "Unknown language kind!"); - case langkind_c_cpp: - NoPreprocess = true; - // FALLTHROUGH - case langkind_c: - break; - case langkind_cxx_cpp: - NoPreprocess = true; - // FALLTHROUGH - case langkind_cxx: - Options.CPlusPlus = 1; - break; - case langkind_objc_cpp: - NoPreprocess = true; - // FALLTHROUGH - case langkind_objc: - Options.ObjC1 = Options.ObjC2 = 1; - break; - case langkind_objcxx_cpp: - NoPreprocess = true; - // FALLTHROUGH - case langkind_objcxx: - Options.ObjC1 = Options.ObjC2 = 1; - Options.CPlusPlus = 1; - break; - } -} - -/// LangStds - Language standards we support. -enum LangStds { - lang_unspecified, - lang_c89, lang_c94, lang_c99, - lang_gnu89, lang_gnu99, - lang_cxx98, lang_gnucxx98, - lang_cxx0x, lang_gnucxx0x -}; - -static llvm::cl::opt<LangStds> -LangStd("std", llvm::cl::desc("Language standard to compile for"), - llvm::cl::init(lang_unspecified), - llvm::cl::values(clEnumValN(lang_c89, "c89", "ISO C 1990"), - clEnumValN(lang_c89, "c90", "ISO C 1990"), - clEnumValN(lang_c89, "iso9899:1990", "ISO C 1990"), - clEnumValN(lang_c94, "iso9899:199409", - "ISO C 1990 with amendment 1"), - clEnumValN(lang_c99, "c99", "ISO C 1999"), -// clEnumValN(lang_c99, "c9x", "ISO C 1999"), - clEnumValN(lang_c99, "iso9899:1999", "ISO C 1999"), -// clEnumValN(lang_c99, "iso9899:199x", "ISO C 1999"), - clEnumValN(lang_gnu89, "gnu89", - "ISO C 1990 with GNU extensions (default for C)"), - clEnumValN(lang_gnu99, "gnu99", - "ISO C 1999 with GNU extensions"), - clEnumValN(lang_gnu99, "gnu9x", - "ISO C 1999 with GNU extensions"), - clEnumValN(lang_cxx98, "c++98", - "ISO C++ 1998 with amendments"), - clEnumValN(lang_gnucxx98, "gnu++98", - "ISO C++ 1998 with amendments and GNU " - "extensions (default for C++)"), - clEnumValN(lang_cxx0x, "c++0x", - "Upcoming ISO C++ 200x with amendments"), - clEnumValN(lang_gnucxx0x, "gnu++0x", - "Upcoming ISO C++ 200x with amendments and GNU " - "extensions (default for C++)"), - clEnumValEnd)); - -static llvm::cl::opt<bool> -NoOperatorNames("fno-operator-names", - llvm::cl::desc("Do not treat C++ operator name keywords as " - "synonyms for operators")); - -static llvm::cl::opt<bool> -PascalStrings("fpascal-strings", - llvm::cl::desc("Recognize and construct Pascal-style " - "string literals")); - -static llvm::cl::opt<bool> -MSExtensions("fms-extensions", - llvm::cl::desc("Accept some non-standard constructs used in " - "Microsoft header files ")); - -static llvm::cl::opt<bool> -WritableStrings("fwritable-strings", - llvm::cl::desc("Store string literals as writable data")); - -static llvm::cl::opt<bool> -LaxVectorConversions("flax-vector-conversions", - llvm::cl::desc("Allow implicit conversions between vectors" - " with a different number of elements or " - "different element types")); - -// FIXME: add: -// -ansi -// -trigraphs -// -fdollars-in-identifiers -// -fpascal-strings -static void InitializeLanguageStandard(LangOptions &Options, LangKind LK) { - if (LangStd == lang_unspecified) { - // Based on the base language, pick one. - switch (LK) { - default: assert(0 && "Unknown base language"); - case langkind_c: - case langkind_c_cpp: - case langkind_objc: - case langkind_objc_cpp: - LangStd = lang_gnu99; - break; - case langkind_cxx: - case langkind_cxx_cpp: - case langkind_objcxx: - case langkind_objcxx_cpp: - LangStd = lang_gnucxx98; - break; - } - } - - switch (LangStd) { - default: assert(0 && "Unknown language standard!"); - - // Fall through from newer standards to older ones. This isn't really right. - // FIXME: Enable specifically the right features based on the language stds. - case lang_gnucxx0x: - case lang_cxx0x: - Options.CPlusPlus0x = 1; - // FALL THROUGH - case lang_gnucxx98: - case lang_cxx98: - Options.CPlusPlus = 1; - Options.CXXOperatorNames = !NoOperatorNames; - Options.Boolean = 1; - // FALL THROUGH. - case lang_gnu99: - case lang_c99: - Options.C99 = 1; - Options.HexFloats = 1; - // FALL THROUGH. - case lang_gnu89: - Options.BCPLComment = 1; // Only for C99/C++. - // FALL THROUGH. - case lang_c94: - Options.Digraphs = 1; // C94, C99, C++. - // FALL THROUGH. - case lang_c89: - break; - } - - if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89) - Options.ImplicitInt = 1; - else - Options.ImplicitInt = 0; - Options.Trigraphs = 1; // -trigraphs or -ansi - Options.DollarIdents = 1; // FIXME: Really a target property. - Options.PascalStrings = PascalStrings; - Options.Microsoft = MSExtensions; - Options.WritableStrings = WritableStrings; - Options.LaxVectorConversions = LaxVectorConversions; -} - -static llvm::cl::opt<bool> -ObjCExclusiveGC("fobjc-gc-only", - llvm::cl::desc("Use GC exclusively for Objective-C related " - "memory management")); - -static llvm::cl::opt<bool> -ObjCEnableGC("fobjc-gc", - llvm::cl::desc("Enable Objective-C garbage collection")); - -void InitializeGCMode(LangOptions &Options) { - if (ObjCExclusiveGC) - Options.setGCMode(LangOptions::GCOnly); - else if (ObjCEnableGC) - Options.setGCMode(LangOptions::HybridGC); -} - - -//===----------------------------------------------------------------------===// -// Our DiagnosticClient implementation -//===----------------------------------------------------------------------===// - -// FIXME: Werror should take a list of things, -Werror=foo,bar -static llvm::cl::opt<bool> -WarningsAsErrors("Werror", llvm::cl::desc("Treat all warnings as errors")); - -static llvm::cl::opt<bool> -WarnOnExtensions("pedantic", llvm::cl::init(false), - llvm::cl::desc("Issue a warning on uses of GCC extensions")); - -static llvm::cl::opt<bool> -ErrorOnExtensions("pedantic-errors", - llvm::cl::desc("Issue an error on uses of GCC extensions")); - -static llvm::cl::opt<bool> -WarnUnusedMacros("Wunused_macros", - llvm::cl::desc("Warn for unused macros in the main translation unit")); - -static llvm::cl::opt<bool> -WarnFloatEqual("Wfloat-equal", - llvm::cl::desc("Warn about equality comparisons of floating point values")); - -static llvm::cl::opt<bool> -WarnNoFormatNonLiteral("Wno-format-nonliteral", - llvm::cl::desc("Do not warn about non-literal format strings")); - -static llvm::cl::opt<bool> -WarnUndefMacros("Wundef", - llvm::cl::desc("Warn on use of undefined macros in #if's")); - -static llvm::cl::opt<bool> -WarnImplicitFunctionDeclaration("Wimplicit-function-declaration" - "Warn about use of implicitly defined functions"); - -/// InitializeDiagnostics - Initialize the diagnostic object, based on the -/// current command line option settings. -static void InitializeDiagnostics(Diagnostic &Diags) { - Diags.setWarningsAsErrors(WarningsAsErrors); - Diags.setWarnOnExtensions(WarnOnExtensions); - Diags.setErrorOnExtensions(ErrorOnExtensions); - - // Silence the "macro is not used" warning unless requested. - if (!WarnUnusedMacros) - Diags.setDiagnosticMapping(diag::pp_macro_not_used, diag::MAP_IGNORE); - - // Silence "floating point comparison" warnings unless requested. - if (!WarnFloatEqual) - Diags.setDiagnosticMapping(diag::warn_floatingpoint_eq, diag::MAP_IGNORE); - - // Silence "format string is not a string literal" warnings if requested - if (WarnNoFormatNonLiteral) - Diags.setDiagnosticMapping(diag::warn_printf_not_string_constant, - diag::MAP_IGNORE); - if (!WarnUndefMacros) - Diags.setDiagnosticMapping(diag::warn_pp_undef_identifier,diag::MAP_IGNORE); - - if (!WarnImplicitFunctionDeclaration) - Diags.setDiagnosticMapping(diag::warn_implicit_function_decl, - diag::MAP_IGNORE); - - if (MSExtensions) // MS allows unnamed struct/union fields. - Diags.setDiagnosticMapping(diag::w_no_declarators, diag::MAP_IGNORE); - - // If -pedantic-errors is set, turn extensions that warn by default into - // errors. - if (ErrorOnExtensions) { - Diags.setDiagnosticMapping(diag::warn_hex_escape_too_large, - diag::MAP_ERROR); - Diags.setDiagnosticMapping(diag::warn_octal_escape_too_large, - diag::MAP_ERROR); - } -} - -//===----------------------------------------------------------------------===// -// Analysis-specific options. -//===----------------------------------------------------------------------===// - -static llvm::cl::opt<std::string> -AnalyzeSpecificFunction("analyze-function", - llvm::cl::desc("Run analysis on specific function")); - -static llvm::cl::opt<bool> -TrimGraph("trim-egraph", - llvm::cl::desc("Only show error-related paths in the analysis graph")); - -//===----------------------------------------------------------------------===// -// Target Triple Processing. -//===----------------------------------------------------------------------===// - -static llvm::cl::opt<std::string> -TargetTriple("triple", - llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)")); - -static llvm::cl::opt<std::string> -Arch("arch", llvm::cl::desc("Specify target architecture (e.g. i686)")); - -static std::string CreateTargetTriple() { - // Initialize base triple. If a -triple option has been specified, use - // that triple. Otherwise, default to the host triple. - std::string Triple = TargetTriple; - if (Triple.empty()) Triple = LLVM_HOSTTRIPLE; - - // If -arch foo was specified, remove the architecture from the triple we have - // so far and replace it with the specified one. - if (Arch.empty()) - return Triple; - - // Decompose the base triple into "arch" and suffix. - std::string::size_type FirstDashIdx = Triple.find("-"); - - if (FirstDashIdx == std::string::npos) { - fprintf(stderr, - "Malformed target triple: \"%s\" ('-' could not be found).\n", - Triple.c_str()); - exit(1); - } - - return Arch + std::string(Triple.begin()+FirstDashIdx, Triple.end()); -} - -//===----------------------------------------------------------------------===// -// Preprocessor Initialization -//===----------------------------------------------------------------------===// - -// FIXME: Preprocessor builtins to support. -// -A... - Play with #assertions -// -undef - Undefine all predefined macros - -static llvm::cl::list<std::string> -D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix, - llvm::cl::desc("Predefine the specified macro")); -static llvm::cl::list<std::string> -U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix, - llvm::cl::desc("Undefine the specified macro")); - -static llvm::cl::list<std::string> -ImplicitIncludes("include", llvm::cl::value_desc("file"), - llvm::cl::desc("Include file before parsing")); - - -// Append a #define line to Buf for Macro. Macro should be of the form XXX, -// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit -// "#define XXX Y z W". To get a #define with no value, use "XXX=". -static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro, - const char *Command = "#define ") { - Buf.insert(Buf.end(), Command, Command+strlen(Command)); - if (const char *Equal = strchr(Macro, '=')) { - // Turn the = into ' '. - Buf.insert(Buf.end(), Macro, Equal); - Buf.push_back(' '); - Buf.insert(Buf.end(), Equal+1, Equal+strlen(Equal)); - } else { - // Push "macroname 1". - Buf.insert(Buf.end(), Macro, Macro+strlen(Macro)); - Buf.push_back(' '); - Buf.push_back('1'); - } - Buf.push_back('\n'); -} - -/// AddImplicitInclude - Add an implicit #include of the specified file to the -/// predefines buffer. -static void AddImplicitInclude(std::vector<char> &Buf, const std::string &File){ - const char *Inc = "#include \""; - Buf.insert(Buf.end(), Inc, Inc+strlen(Inc)); - Buf.insert(Buf.end(), File.begin(), File.end()); - Buf.push_back('"'); - Buf.push_back('\n'); -} - - -/// InitializePreprocessor - Initialize the preprocessor getting it and the -/// environment ready to process a single file. This returns true on error. -/// -static bool InitializePreprocessor(Preprocessor &PP, - bool InitializeSourceMgr, - const std::string &InFile) { - FileManager &FileMgr = PP.getFileManager(); - - // Figure out where to get and map in the main file. - SourceManager &SourceMgr = PP.getSourceManager(); - - if (InitializeSourceMgr) { - if (InFile != "-") { - const FileEntry *File = FileMgr.getFile(InFile); - if (File) SourceMgr.createMainFileID(File, SourceLocation()); - if (SourceMgr.getMainFileID() == 0) { - fprintf(stderr, "Error reading '%s'!\n",InFile.c_str()); - return true; - } - } else { - llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN(); - if (SB) SourceMgr.createMainFileIDForMemBuffer(SB); - if (SourceMgr.getMainFileID() == 0) { - fprintf(stderr, "Error reading standard input! Empty?\n"); - return true; - } - } - } - - std::vector<char> PredefineBuffer; - - // Add macros from the command line. - unsigned d = 0, D = D_macros.size(); - unsigned u = 0, U = U_macros.size(); - while (d < D || u < U) { - if (u == U || (d < D && D_macros.getPosition(d) < U_macros.getPosition(u))) - DefineBuiltinMacro(PredefineBuffer, D_macros[d++].c_str()); - else - DefineBuiltinMacro(PredefineBuffer, U_macros[u++].c_str(), "#undef "); - } - - // FIXME: Read any files specified by -imacros. - - // Add implicit #includes from -include. - for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i) - AddImplicitInclude(PredefineBuffer, ImplicitIncludes[i]); - - // Null terminate PredefinedBuffer and add it. - PredefineBuffer.push_back(0); - PP.setPredefines(&PredefineBuffer[0]); - - // Once we've read this, we're done. - return false; -} - -//===----------------------------------------------------------------------===// -// Preprocessor include path information. -//===----------------------------------------------------------------------===// - -// This tool exports a large number of command line options to control how the -// preprocessor searches for header files. At root, however, the Preprocessor -// object takes a very simple interface: a list of directories to search for -// -// FIXME: -nostdinc,-nostdinc++ -// FIXME: -imultilib -// -// FIXME: -imacros - -static llvm::cl::opt<bool> -nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories")); - -// Various command line options. These four add directories to each chain. -static llvm::cl::list<std::string> -F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix, - llvm::cl::desc("Add directory to framework include search path")); -static llvm::cl::list<std::string> -I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix, - llvm::cl::desc("Add directory to include search path")); -static llvm::cl::list<std::string> -idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix, - llvm::cl::desc("Add directory to AFTER include search path")); -static llvm::cl::list<std::string> -iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix, - llvm::cl::desc("Add directory to QUOTE include search path")); -static llvm::cl::list<std::string> -isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix, - llvm::cl::desc("Add directory to SYSTEM include search path")); - -// These handle -iprefix/-iwithprefix/-iwithprefixbefore. -static llvm::cl::list<std::string> -iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix, - llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix")); -static llvm::cl::list<std::string> -iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix, - llvm::cl::desc("Set directory to SYSTEM include search path with prefix")); -static llvm::cl::list<std::string> -iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"), - llvm::cl::Prefix, - llvm::cl::desc("Set directory to include search path with prefix")); - -static llvm::cl::opt<std::string> -isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"), - llvm::cl::desc("Set the system root directory (usually /)")); - -// Finally, implement the code that groks the options above. -enum IncludeDirGroup { - Quoted = 0, - Angled, - System, - After -}; - -static std::vector<DirectoryLookup> IncludeGroup[4]; - -/// AddPath - Add the specified path to the specified group list. -/// -static void AddPath(const std::string &Path, IncludeDirGroup Group, - bool isCXXAware, bool isUserSupplied, - bool isFramework, HeaderSearch &HS) { - assert(!Path.empty() && "can't handle empty path here"); - FileManager &FM = HS.getFileMgr(); - - // Compute the actual path, taking into consideration -isysroot. - llvm::SmallString<256> MappedPath; - - // Handle isysroot. - if (Group == System) { - // FIXME: Portability. This should be a sys::Path interface, this doesn't - // handle things like C:\ right, nor win32 \\network\device\blah. - if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present. - MappedPath.append(isysroot.begin(), isysroot.end()); - } - - MappedPath.append(Path.begin(), Path.end()); - - // Compute the DirectoryLookup type. - DirectoryLookup::DirType Type; - if (Group == Quoted || Group == Angled) - Type = DirectoryLookup::NormalHeaderDir; - else if (isCXXAware) - Type = DirectoryLookup::SystemHeaderDir; - else - Type = DirectoryLookup::ExternCSystemHeaderDir; - - - // If the directory exists, add it. - if (const DirectoryEntry *DE = FM.getDirectory(&MappedPath[0], - &MappedPath[0]+ - MappedPath.size())) { - IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied, - isFramework)); - return; - } - - // Check to see if this is an apple-style headermap (which are not allowed to - // be frameworks). - if (!isFramework) { - if (const FileEntry *FE = FM.getFile(&MappedPath[0], - &MappedPath[0]+MappedPath.size())) { - if (const HeaderMap *HM = HS.CreateHeaderMap(FE)) { - // It is a headermap, add it to the search path. - IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); - return; - } - } - } - - if (Verbose) - fprintf(stderr, "ignoring nonexistent directory \"%s\"\n", Path.c_str()); -} - -/// RemoveDuplicates - If there are duplicate directory entries in the specified -/// search list, remove the later (dead) ones. -static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList) { - llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs; - llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs; - llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps; - for (unsigned i = 0; i != SearchList.size(); ++i) { - if (SearchList[i].isNormalDir()) { - // If this isn't the first time we've seen this dir, remove it. - if (SeenDirs.insert(SearchList[i].getDir())) - continue; - - if (Verbose) - fprintf(stderr, "ignoring duplicate directory \"%s\"\n", - SearchList[i].getDir()->getName()); - } else if (SearchList[i].isFramework()) { - // If this isn't the first time we've seen this framework dir, remove it. - if (SeenFrameworkDirs.insert(SearchList[i].getFrameworkDir())) - continue; - - if (Verbose) - fprintf(stderr, "ignoring duplicate framework \"%s\"\n", - SearchList[i].getFrameworkDir()->getName()); - - } else { - assert(SearchList[i].isHeaderMap() && "Not a headermap or normal dir?"); - // If this isn't the first time we've seen this headermap, remove it. - if (SeenHeaderMaps.insert(SearchList[i].getHeaderMap())) - continue; - - if (Verbose) - fprintf(stderr, "ignoring duplicate directory \"%s\"\n", - SearchList[i].getDir()->getName()); - } - - // This is reached if the current entry is a duplicate. - SearchList.erase(SearchList.begin()+i); - --i; - } -} - -// AddEnvVarPaths - Add a list of paths from an environment variable to a -// header search list. -// -static void AddEnvVarPaths(const char *Name, HeaderSearch &Headers) { - const char* at = getenv(Name); - if (!at) - return; - - const char* delim = strchr(at, llvm::sys::PathSeparator); - while (delim != 0) { - if (delim-at == 0) - AddPath(".", Angled, false, true, false, Headers); - else - AddPath(std::string(at, std::string::size_type(delim-at)), Angled, false, - true, false, Headers); - at = delim + 1; - delim = strchr(at, llvm::sys::PathSeparator); - } - if (*at == 0) - AddPath(".", Angled, false, true, false, Headers); - else - AddPath(at, Angled, false, true, false, Headers); -} - -/// InitializeIncludePaths - Process the -I options and set them in the -/// HeaderSearch object. -static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers, - FileManager &FM, const LangOptions &Lang) { - // Handle -F... options. - for (unsigned i = 0, e = F_dirs.size(); i != e; ++i) - AddPath(F_dirs[i], Angled, false, true, true, Headers); - - // Handle -I... options. - for (unsigned i = 0, e = I_dirs.size(); i != e; ++i) - AddPath(I_dirs[i], Angled, false, true, false, Headers); - - // Handle -idirafter... options. - for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i) - AddPath(idirafter_dirs[i], After, false, true, false, Headers); - - // Handle -iquote... options. - for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i) - AddPath(iquote_dirs[i], Quoted, false, true, false, Headers); - - // Handle -isystem... options. - for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i) - AddPath(isystem_dirs[i], System, false, true, false, Headers); - - // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in - // parallel, processing the values in order of occurance to get the right - // prefixes. - { - std::string Prefix = ""; // FIXME: this isn't the correct default prefix. - unsigned iprefix_idx = 0; - unsigned iwithprefix_idx = 0; - unsigned iwithprefixbefore_idx = 0; - bool iprefix_done = iprefix_vals.empty(); - bool iwithprefix_done = iwithprefix_vals.empty(); - bool iwithprefixbefore_done = iwithprefixbefore_vals.empty(); - while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) { - if (!iprefix_done && - (iwithprefix_done || - iprefix_vals.getPosition(iprefix_idx) < - iwithprefix_vals.getPosition(iwithprefix_idx)) && - (iwithprefixbefore_done || - iprefix_vals.getPosition(iprefix_idx) < - iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) { - Prefix = iprefix_vals[iprefix_idx]; - ++iprefix_idx; - iprefix_done = iprefix_idx == iprefix_vals.size(); - } else if (!iwithprefix_done && - (iwithprefixbefore_done || - iwithprefix_vals.getPosition(iwithprefix_idx) < - iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) { - AddPath(Prefix+iwithprefix_vals[iwithprefix_idx], - System, false, false, false, Headers); - ++iwithprefix_idx; - iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size(); - } else { - AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx], - Angled, false, false, false, Headers); - ++iwithprefixbefore_idx; - iwithprefixbefore_done = - iwithprefixbefore_idx == iwithprefixbefore_vals.size(); - } - } - } - - AddEnvVarPaths("CPATH", Headers); - if (Lang.CPlusPlus && Lang.ObjC1) - AddEnvVarPaths("OBJCPLUS_INCLUDE_PATH", Headers); - else if (Lang.CPlusPlus) - AddEnvVarPaths("CPLUS_INCLUDE_PATH", Headers); - else if (Lang.ObjC1) - AddEnvVarPaths("OBJC_INCLUDE_PATH", Headers); - else - AddEnvVarPaths("C_INCLUDE_PATH", Headers); - - // Add the clang headers, which are relative to the clang driver. - llvm::sys::Path MainExecutablePath = - llvm::sys::Path::GetMainExecutable(Argv0, - (void*)(intptr_t)InitializeIncludePaths); - if (!MainExecutablePath.isEmpty()) { - MainExecutablePath.eraseComponent(); // Remove /clang from foo/bin/clang - MainExecutablePath.eraseComponent(); // Remove /bin from foo/bin - MainExecutablePath.appendComponent("Headers"); // Get foo/Headers - AddPath(MainExecutablePath.c_str(), System, false, false, false, Headers); - } - - // FIXME: temporary hack: hard-coded paths. - // FIXME: get these from the target? - if (!nostdinc) { - if (Lang.CPlusPlus) { - AddPath("/usr/include/c++/4.0.0", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false, - Headers); - - // Ubuntu 7.10 - Gutsy Gibbon - AddPath("/usr/include/c++/4.1.3", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.1.3/i486-linux-gnu", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false, - Headers); - - // Fedora 8 - AddPath("/usr/include/c++/4.1.2", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.1.2/backward", System, true, false, false, - Headers); - } - - AddPath("/usr/local/include", System, false, false, false, Headers); - // leopard - AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include", - System, false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin9/" - "4.0.1/../../../../powerpc-apple-darwin0/include", - System, false, false, false, Headers); - - // tiger - AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include", - System, false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin8/" - "4.0.1/../../../../powerpc-apple-darwin8/include", - System, false, false, false, Headers); - - // Ubuntu 7.10 - Gutsy Gibbon - AddPath("/usr/lib/gcc/i486-linux-gnu/4.1.3/include", System, - false, false, false, Headers); - - // Fedora 8 - AddPath("/usr/lib/gcc/i386-redhat-linux/4.1.2/include", System, - false, false, false, Headers); - - //Debian testing/lenny x86 - AddPath("/usr/lib/gcc/i486-linux-gnu/4.2.3/include", System, - false, false, false, Headers); - - //Debian testing/lenny amd64 - AddPath("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include", System, - false, false, false, Headers); - - AddPath("/usr/include", System, false, false, false, Headers); - AddPath("/System/Library/Frameworks", System, true, false, true, Headers); - AddPath("/Library/Frameworks", System, true, false, true, Headers); - } - - // Now that we have collected all of the include paths, merge them all - // together and tell the preprocessor about them. - - // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList. - std::vector<DirectoryLookup> SearchList; - SearchList = IncludeGroup[Angled]; - SearchList.insert(SearchList.end(), IncludeGroup[System].begin(), - IncludeGroup[System].end()); - SearchList.insert(SearchList.end(), IncludeGroup[After].begin(), - IncludeGroup[After].end()); - RemoveDuplicates(SearchList); - RemoveDuplicates(IncludeGroup[Quoted]); - - // Prepend QUOTED list on the search list. - SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), - IncludeGroup[Quoted].end()); - - - bool DontSearchCurDir = false; // TODO: set to true if -I- is set? - Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(), - DontSearchCurDir); - - // If verbose, print the list of directories that will be searched. - if (Verbose) { - fprintf(stderr, "#include \"...\" search starts here:\n"); - unsigned QuotedIdx = IncludeGroup[Quoted].size(); - for (unsigned i = 0, e = SearchList.size(); i != e; ++i) { - if (i == QuotedIdx) - fprintf(stderr, "#include <...> search starts here:\n"); - const char *Name = SearchList[i].getName(); - const char *Suffix; - if (SearchList[i].isNormalDir()) - Suffix = ""; - else if (SearchList[i].isFramework()) - Suffix = " (framework directory)"; - else { - assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup"); - Suffix = " (headermap)"; - } - fprintf(stderr, " %s%s\n", Name, Suffix); - } - fprintf(stderr, "End of search list.\n"); - } -} - -//===----------------------------------------------------------------------===// -// Driver PreprocessorFactory - For lazily generating preprocessors ... -//===----------------------------------------------------------------------===// - -namespace { -class VISIBILITY_HIDDEN DriverPreprocessorFactory : public PreprocessorFactory { - const std::string &InFile; - Diagnostic &Diags; - const LangOptions &LangInfo; - TargetInfo &Target; - SourceManager &SourceMgr; - HeaderSearch &HeaderInfo; - bool InitializeSourceMgr; - -public: - DriverPreprocessorFactory(const std::string &infile, - Diagnostic &diags, const LangOptions &opts, - TargetInfo &target, SourceManager &SM, - HeaderSearch &Headers) - : InFile(infile), Diags(diags), LangInfo(opts), Target(target), - SourceMgr(SM), HeaderInfo(Headers), InitializeSourceMgr(true) {} - - - virtual ~DriverPreprocessorFactory() {} - - virtual Preprocessor* CreatePreprocessor() { - Preprocessor* PP = new Preprocessor(Diags, LangInfo, Target, - SourceMgr, HeaderInfo); - - if (InitializePreprocessor(*PP, InitializeSourceMgr, InFile)) { - delete PP; - return NULL; - } - - InitializeSourceMgr = false; - return PP; - } -}; -} - -//===----------------------------------------------------------------------===// -// Basic Parser driver -//===----------------------------------------------------------------------===// - -static void ParseFile(Preprocessor &PP, MinimalAction *PA) { - Parser P(PP, *PA); - PP.EnterMainSourceFile(); - - // Parsing the specified input file. - P.ParseTranslationUnit(); - delete PA; -} - -//===----------------------------------------------------------------------===// -// Main driver -//===----------------------------------------------------------------------===// - -/// CreateASTConsumer - Create the ASTConsumer for the corresponding program -/// action. These consumers can operate on both ASTs that are freshly -/// parsed from source files as well as those deserialized from Bitcode. -static ASTConsumer* CreateASTConsumer(const std::string& InFile, - Diagnostic& Diag, FileManager& FileMgr, - const LangOptions& LangOpts, - Preprocessor *PP, - PreprocessorFactory *PPF, - llvm::Module *&DestModule) { - switch (ProgAction) { - default: - return NULL; - - case ASTPrint: - return CreateASTPrinter(); - - case ASTDump: - return CreateASTDumper(); - - case ASTView: - return CreateASTViewer(); - - case EmitHTML: - return CreateHTMLPrinter(OutputFile, Diag, PP, PPF); - - case ParseCFGDump: - case ParseCFGView: - return CreateCFGDumper(ProgAction == ParseCFGView, - AnalyzeSpecificFunction); - - case AnalysisLiveVariables: - return CreateLiveVarAnalyzer(AnalyzeSpecificFunction); - - case WarnDeadStores: - return CreateDeadStoreChecker(Diag); - - case WarnUninitVals: - return CreateUnitValsChecker(Diag); - - case AnalysisGRSimpleVals: - return CreateGRSimpleVals(Diag, PP, PPF, AnalyzeSpecificFunction, - OutputFile, VisualizeEG, TrimGraph, AnalyzeAll); - - case CheckerCFRef: - return CreateCFRefChecker(Diag, PP, PPF, LangOpts, - AnalyzeSpecificFunction, - OutputFile, VisualizeEG, TrimGraph, AnalyzeAll); - - case TestSerialization: - return CreateSerializationTest(Diag, FileMgr, LangOpts); - - case EmitLLVM: - case EmitBC: - DestModule = new llvm::Module(InFile); - return CreateLLVMCodeGen(Diag, LangOpts, DestModule, GenerateDebugInfo); - - case SerializeAST: - // FIXME: Allow user to tailor where the file is written. - return CreateASTSerializer(InFile, OutputFile, Diag, LangOpts); - - case RewriteObjC: - return CreateCodeRewriterTest(InFile, OutputFile, Diag, LangOpts); - } -} - -/// ProcessInputFile - Process a single input file with the specified state. -/// -static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, - const std::string &InFile) { - - ASTConsumer* Consumer = NULL; - bool ClearSourceMgr = false; - llvm::Module *CodeGenModule = 0; - - switch (ProgAction) { - default: - Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(), - PP.getFileManager(), PP.getLangOptions(), &PP, - &PPF, CodeGenModule); - - if (!Consumer) { - fprintf(stderr, "Unexpected program action!\n"); - return; - } - - break; - - case DumpTokens: { // Token dump mode. - Token Tok; - // Start parsing the specified input file. - PP.EnterMainSourceFile(); - do { - PP.Lex(Tok); - PP.DumpToken(Tok, true); - fprintf(stderr, "\n"); - } while (Tok.isNot(tok::eof)); - ClearSourceMgr = true; - break; - } - case RunPreprocessorOnly: { // Just lex as fast as we can, no output. - Token Tok; - // Start parsing the specified input file. - PP.EnterMainSourceFile(); - do { - PP.Lex(Tok); - } while (Tok.isNot(tok::eof)); - ClearSourceMgr = true; - break; - } - - case PrintPreprocessedInput: // -E mode. - DoPrintPreprocessedInput(PP, OutputFile); - ClearSourceMgr = true; - break; - - case ParseNoop: // -parse-noop - ParseFile(PP, new MinimalAction(PP.getIdentifierTable())); - ClearSourceMgr = true; - break; - - case ParsePrintCallbacks: - ParseFile(PP, CreatePrintParserActionsAction(PP.getIdentifierTable())); - ClearSourceMgr = true; - break; - - case ParseSyntaxOnly: // -fsyntax-only - Consumer = new ASTConsumer(); - break; - - case RewriteMacros: - RewriteMacrosInInput(PP, InFile, OutputFile); - ClearSourceMgr = true; - break; - } - - if (Consumer) { - if (VerifyDiagnostics) - exit(CheckASTConsumer(PP, Consumer)); - - // This deletes Consumer. - ParseAST(PP, Consumer, Stats); - } - - // If running the code generator, finish up now. - if (CodeGenModule) { - std::ostream *Out; - if (OutputFile == "-") { - Out = llvm::cout.stream(); - } else if (!OutputFile.empty()) { - Out = new std::ofstream(OutputFile.c_str(), - std::ios_base::binary|std::ios_base::out); - } else if (InFile == "-") { - Out = llvm::cout.stream(); - } else { - llvm::sys::Path Path(InFile); - Path.eraseSuffix(); - if (ProgAction == EmitLLVM) - Path.appendSuffix("ll"); - else if (ProgAction == EmitBC) - Path.appendSuffix("bc"); - else - assert(0 && "Unknown action"); - Out = new std::ofstream(Path.toString().c_str(), - std::ios_base::binary|std::ios_base::out); - } - - if (ProgAction == EmitLLVM) { - CodeGenModule->print(*Out); - } else { - assert(ProgAction == EmitBC); - llvm::WriteBitcodeToFile(CodeGenModule, *Out); - } - - if (Out != llvm::cout.stream()) - delete Out; - delete CodeGenModule; - } - - if (Stats) { - fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str()); - PP.PrintStats(); - PP.getIdentifierTable().PrintStats(); - PP.getHeaderSearchInfo().PrintStats(); - if (ClearSourceMgr) - PP.getSourceManager().PrintStats(); - fprintf(stderr, "\n"); - } - - // For a multi-file compilation, some things are ok with nuking the source - // manager tables, other require stable fileid/macroid's across multiple - // files. - if (ClearSourceMgr) - PP.getSourceManager().clearIDTables(); -} - -static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag, - FileManager& FileMgr) { - - if (VerifyDiagnostics) { - fprintf(stderr, "-verify does not yet work with serialized ASTs.\n"); - exit (1); - } - - llvm::sys::Path Filename(InFile); - - if (!Filename.isValid()) { - fprintf(stderr, "serialized file '%s' not available.\n",InFile.c_str()); - exit (1); - } - - llvm::OwningPtr<TranslationUnit> TU(ReadASTBitcodeFile(Filename, FileMgr)); - - if (!TU) { - fprintf(stderr, "error: file '%s' could not be deserialized\n", - InFile.c_str()); - exit (1); - } - - // Observe that we use the source file name stored in the deserialized - // translation unit, rather than InFile. - llvm::Module *DestModule; - llvm::OwningPtr<ASTConsumer> - Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts(), 0, 0, - DestModule)); - - if (!Consumer) { - fprintf(stderr, "Unsupported program action with serialized ASTs!\n"); - exit (1); - } - - Consumer->Initialize(TU->getContext()); - - // FIXME: We need to inform Consumer about completed TagDecls as well. - for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I) - Consumer->HandleTopLevelDecl(*I); -} - - -static llvm::cl::list<std::string> -InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>")); - -static bool isSerializedFile(const std::string& InFile) { - if (InFile.size() < 4) - return false; - - const char* s = InFile.c_str()+InFile.size()-4; - - return s[0] == '.' && - s[1] == 'a' && - s[2] == 's' && - s[3] == 't'; -} - - -int main(int argc, char **argv) { - llvm::cl::ParseCommandLineOptions(argc, argv, " llvm clang cfe\n"); - llvm::sys::PrintStackTraceOnErrorSignal(); - - // If no input was specified, read from stdin. - if (InputFilenames.empty()) - InputFilenames.push_back("-"); - - // Create a file manager object to provide access to and cache the filesystem. - FileManager FileMgr; - - // Create the diagnostic client for reporting errors or for - // implementing -verify. - std::auto_ptr<DiagnosticClient> DiagClient; - TextDiagnostics* TextDiagClient = NULL; - - if (!HTMLDiag.empty()) { - - // FIXME: The HTMLDiagnosticClient uses the Preprocessor for - // (optional) syntax highlighting, but we don't have a preprocessor yet. - // Fix this dependency later. - DiagClient.reset(CreateHTMLDiagnosticClient(HTMLDiag, 0, 0)); - } - else { // Use Text diagnostics. - if (!VerifyDiagnostics) { - // Print diagnostics to stderr by default. - TextDiagClient = new TextDiagnosticPrinter(); - } else { - // When checking diagnostics, just buffer them up. - TextDiagClient = new TextDiagnosticBuffer(); - - if (InputFilenames.size() != 1) { - fprintf(stderr, - "-verify only works on single input files for now.\n"); - return 1; - } - } - - assert (TextDiagClient); - DiagClient.reset(TextDiagClient); - } - - // Configure our handling of diagnostics. - Diagnostic Diags(*DiagClient); - InitializeDiagnostics(Diags); - - // -I- is a deprecated GCC feature, scan for it and reject it. - for (unsigned i = 0, e = I_dirs.size(); i != e; ++i) { - if (I_dirs[i] == "-") { - Diags.Report(diag::err_pp_I_dash_not_supported); - I_dirs.erase(I_dirs.begin()+i); - --i; - } - } - - // Get information about the target being compiled for. - std::string Triple = CreateTargetTriple(); - TargetInfo *Target = TargetInfo::CreateTargetInfo(Triple); - if (Target == 0) { - fprintf(stderr, "Sorry, I don't know what target this is: %s\n", - Triple.c_str()); - fprintf(stderr, "Please use -triple or -arch.\n"); - exit(1); - } - - for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { - const std::string &InFile = InputFilenames[i]; - - if (isSerializedFile(InFile)) - ProcessSerializedFile(InFile,Diags,FileMgr); - else { - /// Create a SourceManager object. This tracks and owns all the file - /// buffers allocated to a translation unit. - SourceManager SourceMgr; - - // Initialize language options, inferring file types from input filenames. - LangOptions LangInfo; - InitializeBaseLanguage(); - LangKind LK = GetLanguage(InFile); - InitializeLangOptions(LangInfo, LK); - InitializeLanguageStandard(LangInfo, LK); - InitializeGCMode(LangInfo); - - // Process the -I options and set them in the HeaderInfo. - HeaderSearch HeaderInfo(FileMgr); - if (TextDiagClient) TextDiagClient->setHeaderSearch(HeaderInfo); - InitializeIncludePaths(argv[0], HeaderInfo, FileMgr, LangInfo); - - // Set up the preprocessor with these options. - DriverPreprocessorFactory PPFactory(InFile, Diags, LangInfo, *Target, - SourceMgr, HeaderInfo); - - llvm::OwningPtr<Preprocessor> PP(PPFactory.CreatePreprocessor()); - - if (!PP) - continue; - - ProcessInputFile(*PP, PPFactory, InFile); - HeaderInfo.ClearFileInfo(); - - if (Stats) - SourceMgr.PrintStats(); - } - } - - delete Target; - - unsigned NumDiagnostics = Diags.getNumDiagnostics(); - - if (NumDiagnostics) - fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics, - (NumDiagnostics == 1 ? "" : "s")); - - if (Stats) { - FileMgr.PrintStats(); - fprintf(stderr, "\n"); - } - - return Diags.getNumErrors() != 0; -} |