diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CIndex/CIndex.cpp | 190 | ||||
-rw-r--r-- | tools/CIndex/CIndex.exports | 3 | ||||
-rw-r--r-- | tools/CIndex/CMakeLists.txt | 15 | ||||
-rw-r--r-- | tools/CIndex/Makefile | 5 | ||||
-rw-r--r-- | tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/Makefile | 2 | ||||
-rw-r--r-- | tools/c-index-test/CMakeLists.txt | 3 | ||||
-rw-r--r-- | tools/c-index-test/Makefile | 6 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 101 | ||||
-rw-r--r-- | tools/clang-cc/CMakeLists.txt | 32 | ||||
-rw-r--r-- | tools/clang-cc/Makefile | 32 | ||||
-rw-r--r-- | tools/clang-cc/Options.cpp | 1265 | ||||
-rw-r--r-- | tools/clang-cc/Options.h | 54 | ||||
-rw-r--r-- | tools/clang-cc/clang-cc.cpp | 408 | ||||
-rw-r--r-- | tools/driver/CMakeLists.txt | 19 | ||||
-rw-r--r-- | tools/driver/Makefile | 21 | ||||
-rw-r--r-- | tools/driver/cc1_main.cpp | 319 | ||||
-rw-r--r-- | tools/driver/driver.cpp | 21 | ||||
-rw-r--r-- | tools/index-test/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tools/index-test/Makefile | 6 | ||||
-rw-r--r-- | tools/index-test/index-test.cpp | 46 | ||||
-rwxr-xr-x | tools/scan-build/ccc-analyzer | 77 | ||||
-rwxr-xr-x | tools/scan-build/scan-build | 132 |
23 files changed, 771 insertions, 1991 deletions
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 4681b939..fe3aa37 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -12,24 +12,26 @@ //===----------------------------------------------------------------------===// #include "clang-c/Index.h" -#include "clang/Index/Program.h" -#include "clang/Index/Indexer.h" -#include "clang/Index/ASTLocation.h" -#include "clang/Index/Utils.h" -#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" -#include "clang/AST/Decl.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Version.h" #include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Index/ASTLocation.h" +#include "clang/Index/Indexer.h" +#include "clang/Index/Program.h" +#include "clang/Index/Utils.h" +#include "clang/Sema/CodeCompleteConsumer.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/System/Program.h" -#include "llvm/Support/raw_ostream.h" #include <cstdio> #include <vector> @@ -291,10 +293,25 @@ public: }; class CIndexer : public Indexer { + DiagnosticOptions DiagOpts; + IgnoreDiagnosticsClient IgnoreDiagClient; + llvm::OwningPtr<Diagnostic> TextDiags; + Diagnostic IgnoreDiags; + bool UseExternalASTGeneration; + bool OnlyLocalDecls; + bool DisplayDiagnostics; + + llvm::sys::Path ClangPath; + public: explicit CIndexer(Program *prog) : Indexer(*prog), + IgnoreDiags(&IgnoreDiagClient), + UseExternalASTGeneration(false), OnlyLocalDecls(false), - DisplayDiagnostics(false) {} + DisplayDiagnostics(false) { + TextDiags.reset( + CompilerInstance::createDiagnostics(DiagOpts, 0, 0)); + } virtual ~CIndexer() { delete &getProgram(); } @@ -304,18 +321,25 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; } + bool getDisplayDiagnostics() const { return DisplayDiagnostics; } void setDisplayDiagnostics(bool Display = true) { DisplayDiagnostics = Display; } - bool getDisplayDiagnostics() const { return DisplayDiagnostics; } + + bool getUseExternalASTGeneration() const { return UseExternalASTGeneration; } + void setUseExternalASTGeneration(bool Value) { + UseExternalASTGeneration = Value; + } + + Diagnostic &getDiags() { + return DisplayDiagnostics ? *TextDiags : IgnoreDiags; + } /// \brief Get the path of the clang binary. const llvm::sys::Path& getClangPath(); -private: - bool OnlyLocalDecls; - bool DisplayDiagnostics; - llvm::sys::Path ClangPath; + /// \brief Get the path of the clang resource files. + std::string getClangResourcesPath(); }; const llvm::sys::Path& CIndexer::getClangPath() { @@ -357,6 +381,22 @@ const llvm::sys::Path& CIndexer::getClangPath() { return ClangPath; } +std::string CIndexer::getClangResourcesPath() { + llvm::sys::Path P = getClangPath(); + + if (!P.empty()) { + P.eraseComponent(); // Remove /clang from foo/bin/clang + P.eraseComponent(); // Remove /bin from foo/bin + + // Get foo/lib/clang/<version>/include + P.appendComponent("lib"); + P.appendComponent("clang"); + P.appendComponent(CLANG_VERSION_STRING); + } + + return P.str(); +} + } static SourceLocation getLocationFromCursor(CXCursor C, @@ -452,25 +492,21 @@ void clang_disposeIndex(CXIndex CIdx) { delete static_cast<CIndexer *>(CIdx); } +void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) { + assert(CIdx && "Passed null CXIndex"); + CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); + CXXIdx->setUseExternalASTGeneration(value); +} + // FIXME: need to pass back error info. CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, const char *ast_filename) { assert(CIdx && "Passed null CXIndex"); CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); - std::string astName(ast_filename); - std::string ErrMsg; - - CXTranslationUnit TU = - ASTUnit::LoadFromPCHFile(astName, &ErrMsg, - CXXIdx->getDisplayDiagnostics() ? - NULL : new IgnoreDiagnosticsClient(), - CXXIdx->getOnlyLocalDecls(), - /* UseBumpAllocator = */ true); - if (CXXIdx->getDisplayDiagnostics() && !ErrMsg.empty()) - llvm::errs() << "clang_createTranslationUnit: " << ErrMsg << '\n'; - - return TU; + return ASTUnit::LoadFromPCHFile(ast_filename, CXXIdx->getDiags(), + CXXIdx->getOnlyLocalDecls(), + /* UseBumpAllocator = */ true); } CXTranslationUnit @@ -481,6 +517,33 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, assert(CIdx && "Passed null CXIndex"); CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); + if (!CXXIdx->getUseExternalASTGeneration()) { + llvm::SmallVector<const char *, 16> Args; + + // The 'source_filename' argument is optional. If the caller does not + // specify it then it is assumed that the source file is specified + // in the actual argument list. + if (source_filename) + Args.push_back(source_filename); + Args.insert(Args.end(), command_line_args, + command_line_args + num_command_line_args); + + unsigned NumErrors = CXXIdx->getDiags().getNumErrors(); + llvm::OwningPtr<ASTUnit> Unit( + ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(), + CXXIdx->getDiags(), + CXXIdx->getClangResourcesPath(), + CXXIdx->getOnlyLocalDecls(), + /* UseBumpAllocator = */ true)); + + // FIXME: Until we have broader testing, just drop the entire AST if we + // encountered an error. + if (NumErrors != CXXIdx->getDiags().getNumErrors()) + return 0; + + return Unit.take(); + } + // Build up the arguments for invoking 'clang'. std::vector<const char *> argv; @@ -568,9 +631,29 @@ void clang_loadTranslationUnit(CXTranslationUnit CTUnit, ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit); ASTContext &Ctx = CXXUnit->getASTContext(); - TUVisitor DVisit(CTUnit, callback, CData, - CXXUnit->getOnlyLocalDecls()? 1 : Decl::MaxPCHLevel); - DVisit.Visit(Ctx.getTranslationUnitDecl()); + unsigned PCHLevel = Decl::MaxPCHLevel; + + // Set the PCHLevel to filter out unwanted decls if requested. + if (CXXUnit->getOnlyLocalDecls()) { + PCHLevel = 0; + + // If the main input was an AST, bump the level. + if (CXXUnit->isMainFileAST()) + ++PCHLevel; + } + + TUVisitor DVisit(CTUnit, callback, CData, PCHLevel); + + // If using a non-AST based ASTUnit, iterate over the stored list of top-level + // decls. + if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls()) { + const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls(); + for (std::vector<Decl*>::const_iterator it = TLDs.begin(), + ie = TLDs.end(); it != ie; ++it) { + DVisit.Visit(*it); + } + } else + DVisit.Visit(Ctx.getTranslationUnitDecl()); } void clang_loadDeclaration(CXDecl Dcl, @@ -1082,7 +1165,7 @@ const char *clang_getCompletionChunkText(CXCompletionString completion_string, case CodeCompletionString::CK_Optional: // Note: treated as an empty text block. - return 0; + return ""; } // Should be unreachable, but let's be careful. @@ -1141,6 +1224,8 @@ void clang_codeComplete(CXIndex CIdx, const char *source_filename, int num_command_line_args, const char **command_line_args, + unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files, const char *complete_filename, unsigned complete_line, unsigned complete_column, @@ -1149,6 +1234,9 @@ void clang_codeComplete(CXIndex CIdx, // The indexer, which is mainly used to determine where diagnostics go. CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); + // The set of temporary files that we've built. + std::vector<llvm::sys::Path> TemporaryFiles; + // Build up the arguments for invoking 'clang'. std::vector<const char *> argv; @@ -1163,17 +1251,53 @@ void clang_codeComplete(CXIndex CIdx, // Add the appropriate '-code-completion-at=file:line:column' argument // to perform code completion, with an "-Xclang" preceding it. std::string code_complete_at; - code_complete_at += "-code-completion-at="; code_complete_at += complete_filename; code_complete_at += ":"; code_complete_at += llvm::utostr(complete_line); code_complete_at += ":"; code_complete_at += llvm::utostr(complete_column); argv.push_back("-Xclang"); + argv.push_back("-code-completion-at"); + argv.push_back("-Xclang"); argv.push_back(code_complete_at.c_str()); argv.push_back("-Xclang"); argv.push_back("-no-code-completion-debug-printer"); + std::vector<std::string> RemapArgs; + for (unsigned i = 0; i != num_unsaved_files; ++i) { + char tmpFile[L_tmpnam]; + char *tmpFileName = tmpnam(tmpFile); + + // Write the contents of this unsaved file into the temporary file. + llvm::sys::Path SavedFile(tmpFileName); + std::string ErrorInfo; + llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo); + if (!ErrorInfo.empty()) + continue; + + OS.write(unsaved_files[i].Contents, unsaved_files[i].Length); + OS.close(); + if (OS.has_error()) { + SavedFile.eraseFromDisk(); + continue; + } + + // Remap the file. + std::string RemapArg = unsaved_files[i].Filename; + RemapArg += ';'; + RemapArg += tmpFileName; + RemapArgs.push_back("-Xclang"); + RemapArgs.push_back("-remap-file"); + RemapArgs.push_back("-Xclang"); + RemapArgs.push_back(RemapArg); + TemporaryFiles.push_back(SavedFile); + } + + // The pointers into the elements of RemapArgs are stable because we + // won't be adding anything to RemapArgs after this point. + for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i) + argv.push_back(RemapArgs[i].c_str()); + // Add the source file name (FIXME: later, we'll want to build temporary // file from the buffer, or just feed the source text via standard input). if (source_filename) @@ -1203,6 +1327,7 @@ void clang_codeComplete(CXIndex CIdx, char tmpFile[L_tmpnam]; char *tmpFileName = tmpnam(tmpFile); llvm::sys::Path ResultsFile(tmpFileName); + TemporaryFiles.push_back(ResultsFile); // Invoke 'clang'. llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null @@ -1255,7 +1380,8 @@ void clang_codeComplete(CXIndex CIdx, delete F; } - ResultsFile.eraseFromDisk(); + for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i) + TemporaryFiles[i].eraseFromDisk(); } } // end extern "C" diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index 2892ce50e..458ad10 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -6,6 +6,7 @@ _clang_disposeIndex _clang_disposeString _clang_disposeTranslationUnit _clang_equalCursors +_clang_getCString _clang_getCompletionChunkCompletionString _clang_getCompletionChunkKind _clang_getCompletionChunkText @@ -19,7 +20,6 @@ _clang_getCursorLine _clang_getCursorSource _clang_getCursorSourceFile _clang_getCursorSpelling -_clang_getCString _clang_getDeclColumn _clang_getDeclLine _clang_getDeclSource @@ -41,3 +41,4 @@ _clang_isInvalid _clang_isReference _clang_loadDeclaration _clang_loadTranslationUnit +_clang_setUseExternalASTGeneration diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt index 69de8a1..a3ff3db 100644 --- a/tools/CIndex/CMakeLists.txt +++ b/tools/CIndex/CMakeLists.txt @@ -3,11 +3,20 @@ set(SHARED_LIBRARY TRUE) set(LLVM_NO_RTTI 1) set(LLVM_USED_LIBS - clangFrontend clangIndex clangSema clangAnalysis clangAST clangParse clangLex clangBasic) + clangIndex + clangFrontend + clangDriver + clangSema + clangAnalysis + clangAST + clangParse + clangLex + clangBasic) set( LLVM_LINK_COMPONENTS - MC - support + bitreader + mc + core ) add_clang_library(CIndex CIndex.cpp) diff --git a/tools/CIndex/Makefile b/tools/CIndex/Makefile index a34f68b..94f0467 100644 --- a/tools/CIndex/Makefile +++ b/tools/CIndex/Makefile @@ -21,8 +21,9 @@ include $(LEVEL)/Makefile.config LINK_LIBS_IN_SHARED = 1 SHARED_LIBRARY = 1 -LINK_COMPONENTS := MC support -USEDLIBS = clangFrontend.a clangIndex.a clangSema.a clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a +LINK_COMPONENTS := bitreader mc core +USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \ + clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a include $(LEVEL)/Makefile.common diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 8c666dd..46e4ae9 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(CIndex) add_subdirectory(c-index-test) -add_subdirectory(clang-cc) add_subdirectory(driver) add_subdirectory(index-test) diff --git a/tools/Makefile b/tools/Makefile index 0e98439..a30932b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -8,6 +8,6 @@ ##===----------------------------------------------------------------------===## LEVEL := ../../.. -DIRS := clang-cc driver index-test CIndex c-index-test +DIRS := driver index-test CIndex c-index-test include $(LEVEL)/Makefile.common diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt index 4678461..f0a34a5 100644 --- a/tools/c-index-test/CMakeLists.txt +++ b/tools/c-index-test/CMakeLists.txt @@ -5,8 +5,8 @@ set( LLVM_USED_LIBS clangIndex clangFrontend clangDriver - clangAnalysis clangSema + clangAnalysis clangAST clangParse clangLex @@ -16,6 +16,7 @@ set( LLVM_USED_LIBS set( LLVM_LINK_COMPONENTS bitreader mc + core ) add_clang_executable(c-index-test diff --git a/tools/c-index-test/Makefile b/tools/c-index-test/Makefile index ae49bf4..06e2405 100644 --- a/tools/c-index-test/Makefile +++ b/tools/c-index-test/Makefile @@ -18,8 +18,8 @@ TOOL_NO_EXPORTS = 1 include $(LEVEL)/Makefile.config -LINK_COMPONENTS := bitreader mc -USEDLIBS = CIndex.a clangIndex.a clangFrontend.a clangDriver.a clangAnalysis.a \ - clangSema.a clangAST.a clangParse.a clangLex.a clangBasic.a +LINK_COMPONENTS := bitreader mc core +USEDLIBS = CIndex.a clangIndex.a clangFrontend.a clangDriver.a clangSema.a \ + clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 5364d794..7300585 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -179,12 +179,17 @@ int perform_test_load_tu(const char *file, const char *filter) { } int perform_test_load_source(int argc, const char **argv, const char *filter) { + const char *UseExternalASTs = + getenv("CINDEXTEST_USE_EXTERNAL_AST_GENERATION"); CXIndex Idx; CXTranslationUnit TU; Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(filter, "local") ? 1 : 0, /* displayDiagnostics */ 1); + if (UseExternalASTs && strlen(UseExternalASTs)) + clang_setUseExternalASTGeneration(Idx, 1); + TU = clang_createTranslationUnitFromSourceFile(Idx, 0, argc, argv); if (!TU) { fprintf(stderr, "Unable to load translation unit!\n"); @@ -389,6 +394,91 @@ void print_completion_result(CXCompletionResult *completion_result, fprintf(file, "\n"); } +void free_remapped_files(struct CXUnsavedFile *unsaved_files, + int num_unsaved_files) { + int i; + for (i = 0; i != num_unsaved_files; ++i) { + free((char *)unsaved_files[i].Filename); + free((char *)unsaved_files[i].Contents); + } +} + +int parse_remapped_files(int argc, const char **argv, int start_arg, + struct CXUnsavedFile **unsaved_files, + int *num_unsaved_files) { + int i; + int arg; + int prefix_len = strlen("-remap-file="); + *unsaved_files = 0; + *num_unsaved_files = 0; + + /* Count the number of remapped files. */ + for (arg = start_arg; arg < argc; ++arg) { + if (strncmp(argv[arg], "-remap-file=", prefix_len)) + break; + + ++*num_unsaved_files; + } + + if (*num_unsaved_files == 0) + return 0; + + *unsaved_files + = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * + *num_unsaved_files); + for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) { + struct CXUnsavedFile *unsaved = *unsaved_files + i; + const char *arg_string = argv[arg] + prefix_len; + int filename_len; + char *filename; + char *contents; + FILE *to_file; + const char *semi = strchr(arg_string, ';'); + if (!semi) { + fprintf(stderr, + "error: -remap-file=from;to argument is missing semicolon\n"); + free_remapped_files(*unsaved_files, i); + *unsaved_files = 0; + *num_unsaved_files = 0; + return -1; + } + + /* Open the file that we're remapping to. */ + to_file = fopen(semi + 1, "r"); + if (!to_file) { + fprintf(stderr, "error: cannot open file %s that we are remapping to\n", + semi + 1); + free_remapped_files(*unsaved_files, i); + *unsaved_files = 0; + *num_unsaved_files = 0; + return -1; + } + + /* Determine the length of the file we're remapping to. */ + fseek(to_file, 0, SEEK_END); + unsaved->Length = ftell(to_file); + fseek(to_file, 0, SEEK_SET); + + /* Read the contents of the file we're remapping to. */ + contents = (char *)malloc(unsaved->Length + 1); + fread(contents, 1, unsaved->Length, to_file); + contents[unsaved->Length] = 0; + unsaved->Contents = contents; + + /* Close the file. */ + fclose(to_file); + + /* Copy the file name that we're remapping from. */ + filename_len = semi - arg_string; + filename = (char *)malloc(filename_len + 1); + memcpy(filename, arg_string, filename_len); + filename[filename_len] = 0; + unsaved->Filename = filename; + } + + return 0; +} + int perform_code_completion(int argc, const char **argv) { const char *input = argv[1]; char *filename = 0; @@ -396,17 +486,26 @@ int perform_code_completion(int argc, const char **argv) { unsigned column; CXIndex CIdx; int errorCode; + struct CXUnsavedFile *unsaved_files = 0; + int num_unsaved_files = 0; input += strlen("-code-completion-at="); if ((errorCode = parse_file_line_column(input, &filename, &line, &column))) return errorCode; + if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) + return -1; + CIdx = clang_createIndex(0, 0); - clang_codeComplete(CIdx, argv[argc - 1], argc - 3, argv + 2, + clang_codeComplete(CIdx, argv[argc - 1], argc - num_unsaved_files - 3, + argv + num_unsaved_files + 2, + num_unsaved_files, unsaved_files, filename, line, column, &print_completion_result, stdout); clang_disposeIndex(CIdx); free(filename); + free_remapped_files(unsaved_files, num_unsaved_files); + return 0; } diff --git a/tools/clang-cc/CMakeLists.txt b/tools/clang-cc/CMakeLists.txt deleted file mode 100644 index c96e8b1..0000000 --- a/tools/clang-cc/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -set(LLVM_NO_RTTI 1) - -set( LLVM_USED_LIBS - clangDriver - clangFrontend - clangCodeGen - clangAnalysis - clangRewrite - clangSema - clangAST - clangParse - clangLex - clangBasic - ) - -set( LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} - bitreader - bitwriter - codegen - ipo - selectiondag - ) - -add_clang_executable(clang-cc - clang-cc.cpp - Options.cpp - ) -add_dependencies(clang-cc clang-headers) - -install(TARGETS clang-cc - RUNTIME DESTINATION libexec) diff --git a/tools/clang-cc/Makefile b/tools/clang-cc/Makefile deleted file mode 100644 index ebcc1d5..0000000 --- a/tools/clang-cc/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -##===- tools/clang-cc/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. - -TOOLNAME = clang-cc -CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include -CXXFLAGS = -fno-rtti - -# Clang has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 - -# Include this here so we can get the configuration of the targets -# that have been configured for construction. We have to do this -# early so we can set up LINK_COMPONENTS before including Makefile.rules -include $(LEVEL)/Makefile.config - -LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader bitwriter codegen ipo selectiondag -USEDLIBS = clangDriver.a clangFrontend.a clangCodeGen.a clangAnalysis.a \ - clangRewrite.a clangSema.a clangAST.a clangParse.a \ - clangLex.a clangBasic.a - -# clang-cc lives in a special location; we can get away with this -# because nothing else gets installed from here. -PROJ_bindir := $(DESTDIR)$(PROJ_prefix)/libexec - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/clang-cc/Options.cpp b/tools/clang-cc/Options.cpp deleted file mode 100644 index a18598e..0000000 --- a/tools/clang-cc/Options.cpp +++ /dev/null @@ -1,1265 +0,0 @@ -//===--- Options.cpp - clang-cc Option Handling ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This file contains "pure" option handling, it is only responsible for turning -// the options into internal *Option classes, but shouldn't have any other -// logic. - -#include "Options.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Frontend/AnalysisConsumer.h" -#include "clang/CodeGen/CodeGenOptions.h" -#include "clang/Frontend/DependencyOutputOptions.h" -#include "clang/Frontend/DiagnosticOptions.h" -#include "clang/Frontend/FrontendOptions.h" -#include "clang/Frontend/HeaderSearchOptions.h" -#include "clang/Frontend/LangStandard.h" -#include "clang/Frontend/PCHReader.h" -#include "clang/Frontend/PreprocessorOptions.h" -#include "clang/Frontend/PreprocessorOutputOptions.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/RegistryParser.h" -#include "llvm/System/Host.h" -#include <stdio.h> - -using namespace clang; - -//===----------------------------------------------------------------------===// -// Analyzer Options -//===----------------------------------------------------------------------===// - -namespace analyzeroptions { - -static llvm::cl::list<Analyses> -AnalysisList(llvm::cl::desc("Source Code Analysis - Checks and Analyses"), -llvm::cl::values( -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\ -clEnumValN(NAME, CMDFLAG, DESC), -#include "clang/Frontend/Analyses.def" -clEnumValEnd)); - -static llvm::cl::opt<AnalysisStores> -AnalysisStoreOpt("analyzer-store", - llvm::cl::desc("Source Code Analysis - Abstract Memory Store Models"), - llvm::cl::init(BasicStoreModel), - llvm::cl::values( -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)\ -clEnumValN(NAME##Model, CMDFLAG, DESC), -#include "clang/Frontend/Analyses.def" -clEnumValEnd)); - -static llvm::cl::opt<AnalysisConstraints> -AnalysisConstraintsOpt("analyzer-constraints", - llvm::cl::desc("Source Code Analysis - Symbolic Constraint Engines"), - llvm::cl::init(RangeConstraintsModel), - llvm::cl::values( -#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)\ -clEnumValN(NAME##Model, CMDFLAG, DESC), -#include "clang/Frontend/Analyses.def" -clEnumValEnd)); - -static llvm::cl::opt<AnalysisDiagClients> -AnalysisDiagOpt("analyzer-output", - llvm::cl::desc("Source Code Analysis - Output Options"), - llvm::cl::init(PD_HTML), - llvm::cl::values( -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE)\ -clEnumValN(PD_##NAME, CMDFLAG, DESC), -#include "clang/Frontend/Analyses.def" -clEnumValEnd)); - -static llvm::cl::opt<bool> -AnalyzeAll("analyzer-opt-analyze-headers", - llvm::cl::desc("Force the static analyzer to analyze " - "functions defined in header files")); - -static llvm::cl::opt<bool> -AnalyzerDisplayProgress("analyzer-display-progress", - llvm::cl::desc("Emit verbose output about the analyzer's progress")); - -static llvm::cl::opt<bool> -AnalyzerExperimentalChecks("analyzer-experimental-checks", - llvm::cl::desc("Use experimental path-sensitive checks")); - -static llvm::cl::opt<bool> -AnalyzerExperimentalInternalChecks("analyzer-experimental-internal-checks", - llvm::cl::desc("Use new default path-sensitive checks currently in testing")); - -static llvm::cl::opt<std::string> -AnalyzeSpecificFunction("analyze-function", - llvm::cl::desc("Run analysis on specific function")); - -static llvm::cl::opt<bool> -EagerlyAssume("analyzer-eagerly-assume", - llvm::cl::desc("Eagerly assume the truth/falseness of some " - "symbolic constraints")); - -static llvm::cl::opt<bool> -NoPurgeDead("analyzer-no-purge-dead", - llvm::cl::desc("Don't remove dead symbols, bindings, and constraints before" - " processing a statement")); - -static llvm::cl::opt<bool> -TrimGraph("trim-egraph", - llvm::cl::desc("Only show error-related paths in the analysis graph")); - -static llvm::cl::opt<bool> -VisualizeEGDot("analyzer-viz-egraph-graphviz", - llvm::cl::desc("Display exploded graph using GraphViz")); - -static llvm::cl::opt<bool> -VisualizeEGUbi("analyzer-viz-egraph-ubigraph", - llvm::cl::desc("Display exploded graph using Ubigraph")); - -} - -//===----------------------------------------------------------------------===// -// Code Generation Options -//===----------------------------------------------------------------------===// - -namespace codegenoptions { - -static llvm::cl::opt<bool> -DisableLLVMOptimizations("disable-llvm-optzns", - llvm::cl::desc("Don't run LLVM optimization passes")); - -static llvm::cl::opt<bool> -DisableRedZone("disable-red-zone", - llvm::cl::desc("Do not emit code that uses the red zone.")); - -static llvm::cl::opt<bool> -GenerateDebugInfo("g", - llvm::cl::desc("Generate source level debug information")); - -static llvm::cl::opt<bool> -MAsmVerbose("masm-verbose", llvm::cl::desc("Generate verbose assembly output")); - -static llvm::cl::opt<std::string> -MCodeModel("mcode-model", llvm::cl::desc("The code model to use")); - -static llvm::cl::opt<std::string> -MDebugPass("mdebu-pass", llvm::cl::desc("Output additional debug information")); - -static llvm::cl::opt<bool> -MDisableFPElim("mdisable-fp-elim", - llvm::cl::desc("Disable frame pointer elimination optimization")); - -static llvm::cl::opt<std::string> -MFloatABI("mfloat-abi", llvm::cl::desc("The float ABI to use")); - -static llvm::cl::opt<std::string> -MLimitFloatPrecision("mlimit-float-precision", - llvm::cl::desc("Limit float precision to the given value")); - -static llvm::cl::opt<bool> -MNoZeroInitializedInBSS("mno-zero-initialized-in-bss", - llvm::cl::desc("Do not put zero initialized data in the BSS")); - -static llvm::cl::opt<bool> -MSoftFloat("msoft-float", llvm::cl::desc("Use software floating point")); - -static llvm::cl::opt<std::string> -MRelocationModel("mrelocation-model", - llvm::cl::desc("The relocation model to use"), - llvm::cl::init("pic")); - -static llvm::cl::opt<bool> -MUnwindTables("munwind-tables", - llvm::cl::desc("Generate unwinding tables for all functions")); - -static llvm::cl::opt<std::string> -MainFileName("main-file-name", - llvm::cl::desc("Main file name to use for debug info")); - -static llvm::cl::opt<bool> -NoCommon("fno-common", - llvm::cl::desc("Compile common globals like normal definitions"), - llvm::cl::ValueDisallowed); - -static llvm::cl::opt<bool> -NoImplicitFloat("no-implicit-float", - llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)")); - -static llvm::cl::opt<bool> -NoMergeConstants("fno-merge-all-constants", - llvm::cl::desc("Disallow merging of constants.")); - -// It might be nice to add bounds to the CommandLine library directly. -struct OptLevelParser : public llvm::cl::parser<unsigned> { - bool parse(llvm::cl::Option &O, llvm::StringRef ArgName, - llvm::StringRef Arg, unsigned &Val) { - if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val)) - return true; - if (Val > 3) - return O.error("'" + Arg + "' invalid optimization level!"); - return false; - } -}; -static llvm::cl::opt<unsigned, false, OptLevelParser> -OptLevel("O", llvm::cl::Prefix, - llvm::cl::desc("Optimization level")); - -static llvm::cl::opt<bool> -OptSize("Os", llvm::cl::desc("Optimize for size")); - -} - -//===----------------------------------------------------------------------===// -// Dependency Output Options -//===----------------------------------------------------------------------===// - -namespace dependencyoutputoptions { - -static llvm::cl::opt<std::string> -DependencyFile("dependency-file", - llvm::cl::desc("Filename (or -) to write dependency output to")); - -static llvm::cl::opt<bool> -DependenciesIncludeSystemHeaders("sys-header-deps", - llvm::cl::desc("Include system headers in dependency output")); - -static llvm::cl::list<std::string> -DependencyTargets("MT", - llvm::cl::desc("Specify target for dependency")); - -static llvm::cl::opt<bool> -PhonyDependencyTarget("MP", - llvm::cl::desc("Create phony target for each dependency " - "(other than main file)")); - -} - -//===----------------------------------------------------------------------===// -// Diagnostic Options -//===----------------------------------------------------------------------===// - -namespace diagnosticoptions { - -static llvm::cl::opt<std::string> -DumpBuildInformation("dump-build-information", - llvm::cl::value_desc("filename"), - llvm::cl::desc("output a dump of some build information to a file")); - -static llvm::cl::opt<bool> -NoShowColumn("fno-show-column", - llvm::cl::desc("Do not include column number on diagnostics")); - -static llvm::cl::opt<bool> -NoShowLocation("fno-show-source-location", - llvm::cl::desc("Do not include source location information with" - " diagnostics")); - -static llvm::cl::opt<bool> -NoCaretDiagnostics("fno-caret-diagnostics", - llvm::cl::desc("Do not include source line and caret with" - " diagnostics")); - -static llvm::cl::opt<bool> -NoDiagnosticsFixIt("fno-diagnostics-fixit-info", - llvm::cl::desc("Do not include fixit information in" - " diagnostics")); - -static llvm::cl::opt<bool> OptNoWarnings("w"); - -static llvm::cl::opt<bool> OptPedantic("pedantic"); - -static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors"); - -// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The -// driver has stripped off -Wa,foo etc. The driver has also translated -W to -// -Wextra, so we don't need to worry about it. -static llvm::cl::list<std::string> -OptWarnings("W", llvm::cl::Prefix, llvm::cl::ValueOptional); - -static llvm::cl::opt<bool> -PrintSourceRangeInfo("fdiagnostics-print-source-range-info", - llvm::cl::desc("Print source range spans in numeric form")); - -static llvm::cl::opt<bool> -PrintDiagnosticOption("fdiagnostics-show-option", - llvm::cl::desc("Print diagnostic name with mappable diagnostics")); - -static llvm::cl::opt<unsigned> -MessageLength("fmessage-length", - llvm::cl::desc("Format message diagnostics so that they fit " - "within N columns or fewer, when possible."), - llvm::cl::value_desc("N")); - -static llvm::cl::opt<bool> -PrintColorDiagnostic("fcolor-diagnostics", - llvm::cl::desc("Use colors in diagnostics")); - -static llvm::cl::opt<bool> -SilenceRewriteMacroWarning("Wno-rewrite-macros", - llvm::cl::desc("Silence ObjC rewriting warnings")); - -static llvm::cl::opt<bool> -VerifyDiagnostics("verify", - llvm::cl::desc("Verify emitted diagnostics and warnings")); - -} - -//===----------------------------------------------------------------------===// -// Frontend Options -//===----------------------------------------------------------------------===// - -namespace frontendoptions { - -using namespace clang::frontend; - -static llvm::cl::opt<ParsedSourceLocation> -CodeCompletionAt("code-completion-at", - llvm::cl::value_desc("file:line:column"), - llvm::cl::desc("Dump code-completion information at a location")); - -static llvm::cl::opt<bool> -NoCodeCompletionDebugPrinter("no-code-completion-debug-printer", - llvm::cl::desc("Don't the \"debug\" code-completion print")); - -static llvm::cl::opt<bool> -CodeCompletionWantsMacros("code-completion-macros", - llvm::cl::desc("Include macros in code-completion results")); - -static llvm::cl::opt<bool> -DisableFree("disable-free", - llvm::cl::desc("Disable freeing of memory on exit")); - -static llvm::cl::opt<bool> -EmptyInputOnly("empty-input-only", - llvm::cl::desc("Force running on an empty input file")); - -static llvm::cl::opt<FrontendOptions::InputKind> -InputType("x", llvm::cl::desc("Input language type"), - llvm::cl::init(FrontendOptions::IK_None), - llvm::cl::values(clEnumValN(FrontendOptions::IK_C, "c", "C"), - clEnumValN(FrontendOptions::IK_OpenCL, "cl", "OpenCL C"), - clEnumValN(FrontendOptions::IK_CXX, "c++", "C++"), - clEnumValN(FrontendOptions::IK_ObjC, "objective-c", - "Objective C"), - clEnumValN(FrontendOptions::IK_ObjCXX, "objective-c++", - "Objective C++"), - clEnumValN(FrontendOptions::IK_PreprocessedC, - "cpp-output", - "Preprocessed C"), - clEnumValN(FrontendOptions::IK_Asm, - "assembler-with-cpp", - "Assembly Source Codde"), - clEnumValN(FrontendOptions::IK_PreprocessedCXX, - "c++-cpp-output", - "Preprocessed C++"), - clEnumValN(FrontendOptions::IK_PreprocessedObjC, - "objective-c-cpp-output", - "Preprocessed Objective C"), - clEnumValN(FrontendOptions::IK_PreprocessedObjCXX, - "objective-c++-cpp-output", - "Preprocessed Objective C++"), - clEnumValN(FrontendOptions::IK_C, "c-header", - "C header"), - clEnumValN(FrontendOptions::IK_ObjC, "objective-c-header", - "Objective-C header"), - clEnumValN(FrontendOptions::IK_CXX, "c++-header", - "C++ header"), - clEnumValN(FrontendOptions::IK_ObjCXX, - "objective-c++-header", - "Objective-C++ header"), - clEnumValN(FrontendOptions::IK_AST, "ast", - "Clang AST"), - clEnumValEnd)); - -static llvm::cl::list<std::string> -InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>")); - -static llvm::cl::opt<std::string> -InheritanceViewCls("cxx-inheritance-view", - llvm::cl::value_desc("class name"), - llvm::cl::desc("View C++ inheritance for a specified class")); - -static llvm::cl::list<ParsedSourceLocation> -FixItAtLocations("fixit-at", llvm::cl::value_desc("source-location"), - llvm::cl::desc("Perform Fix-It modifications at the given source location")); - -static llvm::cl::opt<std::string> -OutputFile("o", - llvm::cl::value_desc("path"), - llvm::cl::desc("Specify output file")); - -static llvm::cl::opt<std::string> -PluginActionName("plugin", - llvm::cl::desc("Use the named plugin action " - "(use \"help\" to list available options)")); - -static llvm::cl::opt<ActionKind> -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(DumpRawTokens, "dump-raw-tokens", - "Lex file in raw mode and dump raw tokens"), - clEnumValN(RunAnalysis, "analyze", - "Run static analysis engine"), - clEnumValN(DumpTokens, "dump-tokens", - "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(FixIt, "fixit", - "Apply fix-it advice to the input source"), - 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(ASTPrintXML, "ast-print-xml", - "Build ASTs and then print them in XML format"), - clEnumValN(ASTDump, "ast-dump", - "Build ASTs and then debug dump them"), - clEnumValN(ASTView, "ast-view", - "Build ASTs and view them with GraphViz"), - clEnumValN(PrintDeclContext, "print-decl-contexts", - "Print DeclContexts and their Decls"), - clEnumValN(DumpRecordLayouts, "dump-record-layouts", - "Dump record layout information"), - clEnumValN(GeneratePTH, "emit-pth", - "Generate pre-tokenized header file"), - clEnumValN(GeneratePCH, "emit-pch", - "Generate pre-compiled header file"), - clEnumValN(EmitAssembly, "S", - "Emit native assembly 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(EmitLLVMOnly, "emit-llvm-only", - "Build ASTs and convert to LLVM, discarding output"), - clEnumValN(RewriteTest, "rewrite-test", - "Rewriter playground"), - clEnumValN(RewriteObjC, "rewrite-objc", - "Rewrite ObjC into C (code rewriter example)"), - clEnumValN(RewriteMacros, "rewrite-macros", - "Expand macros without full preprocessing"), - clEnumValN(RewriteBlocks, "rewrite-blocks", - "Rewrite Blocks to C"), - clEnumValEnd)); - -static llvm::cl::opt<bool> -RelocatablePCH("relocatable-pch", - llvm::cl::desc("Whether to build a relocatable precompiled " - "header")); -static llvm::cl::opt<bool> -Stats("print-stats", - llvm::cl::desc("Print performance metrics and statistics")); - -static llvm::cl::opt<bool> -TimeReport("ftime-report", - llvm::cl::desc("Print the amount of time each " - "phase of compilation takes")); - -} - -//===----------------------------------------------------------------------===// -// Language Options -//===----------------------------------------------------------------------===// - -namespace langoptions { - -using namespace clang::frontend; - -static llvm::cl::opt<bool> -NoBuiltin("fno-builtin", - llvm::cl::desc("Disable implicit builtin knowledge of functions")); - -static llvm::cl::opt<bool> -AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax")); - -static llvm::cl::opt<bool> -AccessControl("faccess-control", - llvm::cl::desc("Enable C++ access control")); - -static llvm::cl::opt<bool> -NoSignedChar("fno-signed-char", - llvm::cl::desc("Char is unsigned")); - -static llvm::cl::opt<bool> -DollarsInIdents("fdollars-in-identifiers", - llvm::cl::desc("Allow '$' in identifiers")); - -static llvm::cl::opt<bool> -EmitAllDecls("femit-all-decls", - llvm::cl::desc("Emit all declarations, even if unused")); - -static llvm::cl::opt<bool> -EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature")); - -static llvm::cl::opt<bool> -EnableHeinousExtensions("fheinous-gnu-extensions", - llvm::cl::desc("enable GNU extensions that you really really shouldn't use"), - llvm::cl::ValueDisallowed, llvm::cl::Hidden); - -static llvm::cl::opt<bool> -Exceptions("fexceptions", - llvm::cl::desc("Enable support for exception handling")); - -static llvm::cl::opt<bool> -Freestanding("ffreestanding", - llvm::cl::desc("Assert that the compilation takes place in a " - "freestanding environment")); - -static llvm::cl::opt<bool> -GNURuntime("fgnu-runtime", - llvm::cl::desc("Generate output compatible with the standard GNU " - "Objective-C runtime")); - -static llvm::cl::opt<LangStandard::Kind> -LangStd("std", llvm::cl::desc("Language standard to compile for"), - llvm::cl::init(LangStandard::lang_unspecified), llvm::cl::values( -#define LANGSTANDARD(id, name, desc, features) \ - clEnumValN(LangStandard::lang_##id, name, desc), -#include "clang/Frontend/LangStandards.def" - clEnumValEnd)); - -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> -NoMathErrno("fno-math-errno", - llvm::cl::desc("Don't require math functions to respect errno")); - -static llvm::cl::opt<bool> -NoElideConstructors("fno-elide-constructors", - llvm::cl::desc("Disable C++ copy constructor elision")); - -static llvm::cl::opt<bool> -NoLaxVectorConversions("fno-lax-vector-conversions", - llvm::cl::desc("Disallow implicit conversions between " - "vectors with a different number of " - "elements or different element types")); - - -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<std::string> -ObjCConstantStringClass("fconstant-string-class", - llvm::cl::value_desc("class name"), - llvm::cl::desc("Specify the class to use for constant " - "Objective-C string objects.")); - -static llvm::cl::opt<bool> -ObjCEnableGC("fobjc-gc", - llvm::cl::desc("Enable Objective-C garbage collection")); - -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> -ObjCEnableGCBitmapPrint("print-ivar-layout", - llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace")); - -static llvm::cl::opt<bool> -ObjCNonFragileABI("fobjc-nonfragile-abi", - llvm::cl::desc("enable objective-c's nonfragile abi")); - -static llvm::cl::opt<bool> -OverflowChecking("ftrapv", - llvm::cl::desc("Trap on integer overflow")); - -static llvm::cl::opt<unsigned> -PICLevel("pic-level", llvm::cl::desc("Value for __PIC__")); - -static llvm::cl::opt<bool> -PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code")); - -static llvm::cl::opt<bool> -PascalStrings("fpascal-strings", - llvm::cl::desc("Recognize and construct Pascal-style " - "string literals")); - -static llvm::cl::opt<bool> -NoRtti("fno-rtti", - llvm::cl::desc("Disable generation of rtti information")); - -static llvm::cl::opt<bool> -ShortWChar("fshort-wchar", - llvm::cl::desc("Force wchar_t to be a short unsigned int")); - -static llvm::cl::opt<bool> -StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined")); - -static llvm::cl::opt<int> -StackProtector("stack-protector", - llvm::cl::desc("Enable stack protectors")); - -static llvm::cl::opt<LangOptions::VisibilityMode> -SymbolVisibility("fvisibility", - llvm::cl::desc("Set the default symbol visibility:"), - llvm::cl::init(LangOptions::Default), - llvm::cl::values(clEnumValN(LangOptions::Default, "default", - "Use default symbol visibility"), - clEnumValN(LangOptions::Hidden, "hidden", - "Use hidden symbol visibility"), - clEnumValN(LangOptions::Protected,"protected", - "Use protected symbol visibility"), - clEnumValEnd)); - -static llvm::cl::opt<unsigned> -TemplateDepth("ftemplate-depth", - llvm::cl::desc("Maximum depth of recursive template " - "instantiation")); - -static llvm::cl::opt<bool> -Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences")); - -static llvm::cl::opt<bool> -WritableStrings("fwritable-strings", - llvm::cl::desc("Store string literals as writable data")); - -} - -//===----------------------------------------------------------------------===// -// General Preprocessor Options -//===----------------------------------------------------------------------===// - -namespace preprocessoroptions { - -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> -ImplicitIncludes("include", llvm::cl::value_desc("file"), - llvm::cl::desc("Include file before parsing")); -static llvm::cl::list<std::string> -ImplicitMacroIncludes("imacros", llvm::cl::value_desc("file"), - llvm::cl::desc("Include macros from file before parsing")); - -static llvm::cl::opt<std::string> -ImplicitIncludePCH("include-pch", llvm::cl::value_desc("file"), - llvm::cl::desc("Include precompiled header file")); - -static llvm::cl::opt<std::string> -ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"), - llvm::cl::desc("Include file before parsing")); - -static llvm::cl::opt<std::string> -TokenCache("token-cache", llvm::cl::value_desc("path"), - llvm::cl::desc("Use specified token cache file")); - -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::opt<bool> -UndefMacros("undef", llvm::cl::value_desc("macro"), - llvm::cl::desc("undef all system defines")); - -} - -//===----------------------------------------------------------------------===// -// Header Search Options -//===----------------------------------------------------------------------===// - -namespace headersearchoptions { - -static llvm::cl::opt<bool> -nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories")); - -static llvm::cl::opt<bool> -nobuiltininc("nobuiltininc", - llvm::cl::desc("Disable builtin #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::desc("Set the system root directory (usually /)")); - -static llvm::cl::opt<bool> -Verbose("v", llvm::cl::desc("Enable verbose output")); - -} - -//===----------------------------------------------------------------------===// -// Preprocessed Output Options -//===----------------------------------------------------------------------===// - -namespace preprocessoroutputoptions { - -static llvm::cl::opt<bool> -DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode")); - -static llvm::cl::opt<bool> -EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode")); - -static llvm::cl::opt<bool> -EnableMacroCommentOutput("CC", - llvm::cl::desc("Enable comment output in -E mode, " - "even from macro expansions")); -static llvm::cl::opt<bool> -DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of" - " normal output")); -static llvm::cl::opt<bool> -DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in " - "addition to normal output")); - -} - -//===----------------------------------------------------------------------===// -// Target Options -//===----------------------------------------------------------------------===// - -namespace targetoptions { - -static llvm::cl::opt<std::string> -TargetABI("target-abi", - llvm::cl::desc("Target a particular ABI type")); - -static llvm::cl::opt<std::string> -TargetCPU("mcpu", - llvm::cl::desc("Target a specific cpu type ('-mcpu help' for details)")); - -static llvm::cl::list<std::string> -TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes")); - -static llvm::cl::opt<std::string> -TargetTriple("triple", - llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)")); - -} - -//===----------------------------------------------------------------------===// -// Option Object Construction -//===----------------------------------------------------------------------===// - -void clang::InitializeAnalyzerOptions(AnalyzerOptions &Opts) { - using namespace analyzeroptions; - Opts.AnalysisList = AnalysisList; - Opts.AnalysisStoreOpt = AnalysisStoreOpt; - Opts.AnalysisConstraintsOpt = AnalysisConstraintsOpt; - Opts.AnalysisDiagOpt = AnalysisDiagOpt; - Opts.VisualizeEGDot = VisualizeEGDot; - Opts.VisualizeEGUbi = VisualizeEGUbi; - Opts.AnalyzeAll = AnalyzeAll; - Opts.AnalyzerDisplayProgress = AnalyzerDisplayProgress; - Opts.PurgeDead = !NoPurgeDead; - Opts.EagerlyAssume = EagerlyAssume; - Opts.AnalyzeSpecificFunction = AnalyzeSpecificFunction; - Opts.EnableExperimentalChecks = AnalyzerExperimentalChecks; - Opts.EnableExperimentalInternalChecks = AnalyzerExperimentalInternalChecks; - Opts.TrimGraph = TrimGraph; -} - -void clang::InitializeCodeGenOptions(CodeGenOptions &Opts, - const LangOptions &Lang) { - using namespace codegenoptions; - - // -Os implies -O2 - unsigned Opt = OptLevel.getPosition() ? OptLevel : 0; - Opts.OptimizationLevel = OptSize ? 2 : Opt; - - // We must always run at least the always inlining pass. - Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining - : CodeGenOptions::OnlyAlwaysInlining; - - Opts.DebugInfo = GenerateDebugInfo; - Opts.DisableLLVMOpts = DisableLLVMOptimizations; - Opts.DisableRedZone = DisableRedZone; - Opts.MergeAllConstants = !NoMergeConstants; - Opts.NoCommon = NoCommon; - Opts.NoImplicitFloat = NoImplicitFloat; - Opts.OptimizeSize = OptSize; - Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize); - - // LLVM Code Generator options. - - Opts.AsmVerbose = MAsmVerbose; - Opts.CodeModel = MCodeModel; - Opts.DebugPass = MDebugPass; - Opts.DisableFPElim = MDisableFPElim; - Opts.FloatABI = MFloatABI; - Opts.LimitFloatPrecision = MLimitFloatPrecision; - Opts.NoZeroInitializedInBSS = MNoZeroInitializedInBSS; - Opts.SoftFloat = MSoftFloat; - Opts.RelocationModel = MRelocationModel; - Opts.UnwindTables = MUnwindTables; - -#ifdef NDEBUG - Opts.VerifyModule = 0; -#endif - - if (MainFileName.getPosition()) - Opts.MainFileName = MainFileName; -} - -void clang::InitializeDependencyOutputOptions(DependencyOutputOptions &Opts) { - using namespace dependencyoutputoptions; - - Opts.OutputFile = DependencyFile; - Opts.Targets = DependencyTargets; - Opts.IncludeSystemHeaders = DependenciesIncludeSystemHeaders; - Opts.UsePhonyTargets = PhonyDependencyTarget; -} - -void clang::InitializeDiagnosticOptions(DiagnosticOptions &Opts) { - using namespace diagnosticoptions; - - Opts.Warnings = OptWarnings; - Opts.DumpBuildInformation = DumpBuildInformation; - Opts.IgnoreWarnings = OptNoWarnings; - Opts.MessageLength = MessageLength; - Opts.NoRewriteMacros = SilenceRewriteMacroWarning; - Opts.Pedantic = OptPedantic; - Opts.PedanticErrors = OptPedanticErrors; - Opts.ShowCarets = !NoCaretDiagnostics; - Opts.ShowColors = PrintColorDiagnostic; - Opts.ShowColumn = !NoShowColumn; - Opts.ShowFixits = !NoDiagnosticsFixIt; - Opts.ShowLocation = !NoShowLocation; - Opts.ShowOptionNames = PrintDiagnosticOption; - Opts.ShowSourceRanges = PrintSourceRangeInfo; - Opts.VerifyDiagnostics = VerifyDiagnostics; -} - -void clang::InitializeFrontendOptions(FrontendOptions &Opts) { - using namespace frontendoptions; - - Opts.ProgramAction = ProgAction; - Opts.ActionName = PluginActionName; - Opts.CodeCompletionAt = CodeCompletionAt; - Opts.DebugCodeCompletionPrinter = !NoCodeCompletionDebugPrinter; - Opts.DisableFree = DisableFree; - Opts.EmptyInputOnly = EmptyInputOnly; - Opts.FixItLocations = FixItAtLocations; - Opts.OutputFile = OutputFile; - Opts.RelocatablePCH = RelocatablePCH; - Opts.ShowMacrosInCodeCompletion = CodeCompletionWantsMacros; - Opts.ShowStats = Stats; - Opts.ShowTimers = TimeReport; - Opts.ViewClassInheritance = InheritanceViewCls; - - // Enforce certain program action implications. - if (!Opts.ActionName.empty()) - Opts.ProgramAction = frontend::PluginAction; - if (!Opts.ViewClassInheritance.empty()) - Opts.ProgramAction = frontend::InheritanceView; - if (!Opts.FixItLocations.empty()) - Opts.ProgramAction = frontend::FixIt; - - // '-' is the default input if none is given. - if (InputFilenames.empty()) { - FrontendOptions::InputKind IK = InputType; - if (IK == FrontendOptions::IK_None) IK = FrontendOptions::IK_C; - Opts.Inputs.push_back(std::make_pair(IK, "-")); - } else { - for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { - FrontendOptions::InputKind IK = InputType; - llvm::StringRef Ext = - llvm::StringRef(InputFilenames[i]).rsplit('.').second; - if (IK == FrontendOptions::IK_None) - IK = FrontendOptions::getInputKindForExtension(Ext); - Opts.Inputs.push_back(std::make_pair(IK, InputFilenames[i])); - } - } -} - -void clang::InitializeHeaderSearchOptions(HeaderSearchOptions &Opts, - llvm::StringRef BuiltinIncludePath) { - using namespace headersearchoptions; - - if (isysroot.getPosition()) - Opts.Sysroot = isysroot; - Opts.Verbose = Verbose; - - // Handle -I... and -F... options, walking the lists in parallel. - unsigned Iidx = 0, Fidx = 0; - while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) { - if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) { - Opts.AddPath(I_dirs[Iidx], frontend::Angled, true, false); - ++Iidx; - } else { - Opts.AddPath(F_dirs[Fidx], frontend::Angled, true, true); - ++Fidx; - } - } - - // Consume what's left from whatever list was longer. - for (; Iidx != I_dirs.size(); ++Iidx) - Opts.AddPath(I_dirs[Iidx], frontend::Angled, true, false); - for (; Fidx != F_dirs.size(); ++Fidx) - Opts.AddPath(F_dirs[Fidx], frontend::Angled, true, true); - - // Handle -idirafter... options. - for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i) - Opts.AddPath(idirafter_dirs[i], frontend::After, true, false); - - // Handle -iquote... options. - for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i) - Opts.AddPath(iquote_dirs[i], frontend::Quoted, true, false); - - // Handle -isystem... options. - for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i) - Opts.AddPath(isystem_dirs[i], frontend::System, true, false); - - // 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))) { - Opts.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx], - frontend::System, false, false); - ++iwithprefix_idx; - iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size(); - } else { - Opts.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx], - frontend::Angled, false, false); - ++iwithprefixbefore_idx; - iwithprefixbefore_done = - iwithprefixbefore_idx == iwithprefixbefore_vals.size(); - } - } - } - - // Add CPATH environment paths. - if (const char *Env = getenv("CPATH")) - Opts.EnvIncPath = Env; - - // Add language specific environment paths. - if (const char *Env = getenv("OBJCPLUS_INCLUDE_PATH")) - Opts.ObjCXXEnvIncPath = Env; - if (const char *Env = getenv("CPLUS_INCLUDE_PATH")) - Opts.CXXEnvIncPath = Env; - if (const char *Env = getenv("OBJC_INCLUDE_PATH")) - Opts.CEnvIncPath = Env; - if (const char *Env = getenv("C_INCLUDE_PATH")) - Opts.CEnvIncPath = Env; - - if (!nobuiltininc) - Opts.BuiltinIncludePath = BuiltinIncludePath; - - Opts.UseStandardIncludes = !nostdinc; -} - -void clang::InitializePreprocessorOptions(PreprocessorOptions &Opts) { - using namespace preprocessoroptions; - - Opts.ImplicitPCHInclude = ImplicitIncludePCH; - Opts.ImplicitPTHInclude = ImplicitIncludePTH; - - // Select the token cache file, we don't support more than one currently so we - // can't have both an implicit-pth and a token cache file. - if (TokenCache.getPosition() && ImplicitIncludePTH.getPosition()) { - // FIXME: Don't fail like this. - fprintf(stderr, "error: cannot use both -token-cache and -include-pth " - "options\n"); - exit(1); - } - if (TokenCache.getPosition()) - Opts.TokenCache = TokenCache; - else - Opts.TokenCache = ImplicitIncludePTH; - - // Use predefines? - Opts.UsePredefines = !UndefMacros; - - // 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))) - Opts.addMacroDef(D_macros[d++]); - else - Opts.addMacroUndef(U_macros[u++]); - } - - // If -imacros are specified, include them now. These are processed before - // any -include directives. - for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i) - Opts.MacroIncludes.push_back(ImplicitMacroIncludes[i]); - - // Add the ordered list of -includes, sorting in the implicit include options - // at the appropriate location. - llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths; - std::string OriginalFile; - - if (!ImplicitIncludePTH.empty()) - OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(), - &ImplicitIncludePTH)); - if (!ImplicitIncludePCH.empty()) { - OriginalFile = PCHReader::getOriginalSourceFile(ImplicitIncludePCH); - // FIXME: Don't fail like this. - if (OriginalFile.empty()) - exit(1); - OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(), - &OriginalFile)); - } - for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i) - OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i), - &ImplicitIncludes[i])); - llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end()); - - for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i) - Opts.Includes.push_back(*OrderedPaths[i].second); -} - -void clang::InitializeLangOptions(LangOptions &Options, - FrontendOptions::InputKind IK) { - using namespace langoptions; - - // Set some properties which depend soley on the input kind; it would be nice - // to move these to the language standard, and have the driver resolve the - // input kind + language standard. - if (IK == FrontendOptions::IK_Asm) { - Options.AsmPreprocessor = 1; - } else if (IK == FrontendOptions::IK_ObjC || - IK == FrontendOptions::IK_ObjCXX || - IK == FrontendOptions::IK_PreprocessedObjC || - IK == FrontendOptions::IK_PreprocessedObjCXX) { - Options.ObjC1 = Options.ObjC2 = 1; - } - - if (LangStd == LangStandard::lang_unspecified) { - // Based on the base language, pick one. - switch (IK) { - case FrontendOptions::IK_None: - case FrontendOptions::IK_AST: - assert(0 && "Invalid input kind!"); - case FrontendOptions::IK_OpenCL: - LangStd = LangStandard::lang_opencl; - break; - case FrontendOptions::IK_Asm: - case FrontendOptions::IK_C: - case FrontendOptions::IK_PreprocessedC: - case FrontendOptions::IK_ObjC: - case FrontendOptions::IK_PreprocessedObjC: - LangStd = LangStandard::lang_gnu99; - break; - case FrontendOptions::IK_CXX: - case FrontendOptions::IK_PreprocessedCXX: - case FrontendOptions::IK_ObjCXX: - case FrontendOptions::IK_PreprocessedObjCXX: - LangStd = LangStandard::lang_gnucxx98; - break; - } - } - - const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - Options.BCPLComment = Std.hasBCPLComments(); - Options.C99 = Std.isC99(); - Options.CPlusPlus = Std.isCPlusPlus(); - Options.CPlusPlus0x = Std.isCPlusPlus0x(); - Options.Digraphs = Std.hasDigraphs(); - Options.GNUInline = !Std.isC99(); - Options.GNUMode = Std.isGNUMode(); - Options.HexFloats = Std.hasHexFloats(); - Options.ImplicitInt = Std.hasImplicitInt(); - - // OpenCL has some additional defaults. - if (LangStd == LangStandard::lang_opencl) { - Options.OpenCL = 1; - Options.AltiVec = 1; - Options.CXXOperatorNames = 1; - Options.LaxVectorConversions = 1; - } - - // OpenCL and C++ both have bool, true, false keywords. - Options.Bool = Options.OpenCL || Options.CPlusPlus; - - if (Options.CPlusPlus) - Options.CXXOperatorNames = !NoOperatorNames; - - if (ObjCExclusiveGC) - Options.setGCMode(LangOptions::GCOnly); - else if (ObjCEnableGC) - Options.setGCMode(LangOptions::HybridGC); - - if (ObjCEnableGCBitmapPrint) - Options.ObjCGCBitmapPrint = 1; - - if (AltiVec) - Options.AltiVec = 1; - - if (PThread) - Options.POSIXThreads = 1; - - Options.setVisibilityMode(SymbolVisibility); - Options.OverflowChecking = OverflowChecking; - - // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs - // is specified, or -std is set to a conforming mode. - Options.Trigraphs = !Options.GNUMode; - if (Trigraphs.getPosition()) - Options.Trigraphs = Trigraphs; // Command line option wins if specified. - - // Default to not accepting '$' in identifiers when preprocessing assembler. - Options.DollarIdents = !Options.AsmPreprocessor; - if (DollarsInIdents.getPosition()) // Explicit setting overrides default. - Options.DollarIdents = DollarsInIdents; - - if (PascalStrings.getPosition()) - Options.PascalStrings = PascalStrings; - if (MSExtensions.getPosition()) - Options.Microsoft = MSExtensions; - Options.WritableStrings = WritableStrings; - if (NoLaxVectorConversions.getPosition()) - Options.LaxVectorConversions = 0; - Options.Exceptions = Exceptions; - Options.Rtti = !NoRtti; - Options.Blocks = EnableBlocks; - Options.CharIsSigned = !NoSignedChar; - if (ShortWChar.getPosition()) - Options.ShortWChar = ShortWChar; - - Options.NoBuiltin = NoBuiltin; - if (Freestanding) - Options.Freestanding = Options.NoBuiltin = 1; - - if (EnableHeinousExtensions) - Options.HeinousExtensions = 1; - - if (AccessControl) - Options.AccessControl = 1; - - Options.ElideConstructors = !NoElideConstructors; - - Options.MathErrno = !NoMathErrno; - - if (TemplateDepth.getPosition()) - Options.InstantiationDepth = TemplateDepth; - - // Override the default runtime if the user requested it. - if (GNURuntime) - Options.NeXTRuntime = 0; - - if (!ObjCConstantStringClass.empty()) - Options.ObjCConstantStringClass = ObjCConstantStringClass; - - if (ObjCNonFragileABI) - Options.ObjCNonFragileABI = 1; - - if (EmitAllDecls) - Options.EmitAllDecls = 1; - - // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't support. - unsigned Opt = - codegenoptions::OptLevel.getPosition() ? codegenoptions::OptLevel : 0; - Options.OptimizeSize = 0; - Options.Optimize = codegenoptions::OptSize || Opt; - - assert(PICLevel <= 2 && "Invalid value for -pic-level"); - Options.PICLevel = PICLevel; - - // This is the __NO_INLINE__ define, which just depends on things like the - // optimization level and -fno-inline, not actually whether the backend has - // inlining enabled. - // - // FIXME: This is affected by other options (-fno-inline). - Options.NoInline = !Opt; - - Options.Static = StaticDefine; - - if (StackProtector.getPosition()) { - switch (StackProtector) { - default: - assert(0 && "Invalid value for -stack-protector"); - case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break; - case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break; - case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break; - } - } -} - -void -clang::InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts) { - using namespace preprocessoroutputoptions; - - Opts.ShowCPP = !DumpMacros; - Opts.ShowMacros = DumpMacros || DumpDefines; - Opts.ShowLineMarkers = !DisableLineMarkers; - Opts.ShowComments = EnableCommentOutput; - Opts.ShowMacroComments = EnableMacroCommentOutput; -} - -void clang::InitializeTargetOptions(TargetOptions &Opts) { - using namespace targetoptions; - - Opts.ABI = TargetABI; - Opts.CPU = TargetCPU; - Opts.Triple = TargetTriple; - Opts.Features = TargetFeatures; - - // Use the host triple if unspecified. - if (Opts.Triple.empty()) - Opts.Triple = llvm::sys::getHostTriple(); -} diff --git a/tools/clang-cc/Options.h b/tools/clang-cc/Options.h deleted file mode 100644 index 91e37f2..0000000 --- a/tools/clang-cc/Options.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- Options.h - clang-cc Option Handling --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANGCC_OPTIONS_H -#define LLVM_CLANGCC_OPTIONS_H - -#include "clang/Frontend/FrontendOptions.h" -#include "llvm/ADT/StringRef.h" - -namespace clang { - -class AnalyzerOptions; -class CodeGenOptions; -class DependencyOutputOptions; -class DiagnosticOptions; -class FrontendOptions; -class HeaderSearchOptions; -class LangOptions; -class PreprocessorOptions; -class PreprocessorOutputOptions; -class TargetInfo; -class TargetOptions; - -void InitializeAnalyzerOptions(AnalyzerOptions &Opts); - -void InitializeCodeGenOptions(CodeGenOptions &Opts, - const LangOptions &Lang); - -void InitializeDependencyOutputOptions(DependencyOutputOptions &Opts); - -void InitializeDiagnosticOptions(DiagnosticOptions &Opts); - -void InitializeFrontendOptions(FrontendOptions &Opts); - -void InitializeHeaderSearchOptions(HeaderSearchOptions &Opts, - llvm::StringRef BuiltinIncludePath); - -void InitializeLangOptions(LangOptions &Options, FrontendOptions::InputKind LK); - -void InitializePreprocessorOptions(PreprocessorOptions &Opts); - -void InitializePreprocessorOutputOptions(PreprocessorOutputOptions &Opts); - -void InitializeTargetOptions(TargetOptions &Opts); - -} // end namespace clang - -#endif diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp deleted file mode 100644 index 2899684..0000000 --- a/tools/clang-cc/clang-cc.cpp +++ /dev/null @@ -1,408 +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-cc --help - Output help info. -// clang-cc [options] - Read from stdin. -// clang-cc [options] file - Read from "file". -// clang-cc [options] file1 file2 - Read these files. -// -//===----------------------------------------------------------------------===// - -#include "Options.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "clang/Driver/Arg.h" -#include "clang/Driver/ArgList.h" -#include "clang/Driver/CC1Options.h" -#include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/OptTable.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/FrontendPluginRegistry.h" -#include "clang/Frontend/TextDiagnosticBuffer.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Frontend/VerifyDiagnosticsClient.h" -#include "llvm/LLVMContext.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/PluginLoader.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Host.h" -#include "llvm/System/Path.h" -#include "llvm/System/Signals.h" -#include "llvm/Target/TargetSelect.h" -#include <cstdio> -using namespace clang; - -//===----------------------------------------------------------------------===// -// Main driver -//===----------------------------------------------------------------------===// - -std::string GetBuiltinIncludePath(const char *Argv0) { - llvm::sys::Path P = - llvm::sys::Path::GetMainExecutable(Argv0, - (void*)(intptr_t) GetBuiltinIncludePath); - - if (!P.isEmpty()) { - P.eraseComponent(); // Remove /clang from foo/bin/clang - P.eraseComponent(); // Remove /bin from foo/bin - - // Get foo/lib/clang/<version>/include - P.appendComponent("lib"); - P.appendComponent("clang"); - P.appendComponent(CLANG_VERSION_STRING); - P.appendComponent("include"); - } - - return P.str(); -} - -static void LLVMErrorHandler(void *UserData, const std::string &Message) { - Diagnostic &Diags = *static_cast<Diagnostic*>(UserData); - - Diags.Report(diag::err_fe_error_backend) << Message; - - // We cannot recover from llvm errors. - exit(1); -} - -static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { - using namespace clang::frontend; - - switch (CI.getFrontendOpts().ProgramAction) { - default: - llvm::llvm_unreachable("Invalid program action!"); - - case ASTDump: return new ASTDumpAction(); - case ASTPrint: return new ASTPrintAction(); - case ASTPrintXML: return new ASTPrintXMLAction(); - case ASTView: return new ASTViewAction(); - case DumpRawTokens: return new DumpRawTokensAction(); - case DumpRecordLayouts: return new DumpRecordAction(); - case DumpTokens: return new DumpTokensAction(); - case EmitAssembly: return new EmitAssemblyAction(); - case EmitBC: return new EmitBCAction(); - case EmitHTML: return new HTMLPrintAction(); - case EmitLLVM: return new EmitLLVMAction(); - case EmitLLVMOnly: return new EmitLLVMOnlyAction(); - case FixIt: return new FixItAction(); - case GeneratePCH: return new GeneratePCHAction(); - case GeneratePTH: return new GeneratePTHAction(); - case InheritanceView: return new InheritanceViewAction(); - case ParseNoop: return new ParseOnlyAction(); - case ParsePrintCallbacks: return new PrintParseAction(); - case ParseSyntaxOnly: return new SyntaxOnlyAction(); - - case PluginAction: { - if (CI.getFrontendOpts().ActionName == "help") { - llvm::errs() << "clang-cc plugins:\n"; - for (FrontendPluginRegistry::iterator it = - FrontendPluginRegistry::begin(), - ie = FrontendPluginRegistry::end(); - it != ie; ++it) - llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n"; - exit(1); - } - - for (FrontendPluginRegistry::iterator it = - FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); - it != ie; ++it) { - if (it->getName() == CI.getFrontendOpts().ActionName) - return it->instantiate(); - } - - CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) - << CI.getFrontendOpts().ActionName; - return 0; - } - - case PrintDeclContext: return new DeclContextPrintAction(); - case PrintPreprocessedInput: return new PrintPreprocessedAction(); - case RewriteBlocks: return new RewriteBlocksAction(); - case RewriteMacros: return new RewriteMacrosAction(); - case RewriteObjC: return new RewriteObjCAction(); - case RewriteTest: return new RewriteTestAction(); - case RunAnalysis: return new AnalysisAction(); - case RunPreprocessorOnly: return new PreprocessOnlyAction(); - } -} - -static bool ConstructCompilerInvocation(CompilerInvocation &Opts, - Diagnostic &Diags, const char *Argv0) { - // Initialize target options. - InitializeTargetOptions(Opts.getTargetOpts()); - - // Initialize frontend options. - InitializeFrontendOptions(Opts.getFrontendOpts()); - - // Determine the input language, we currently require all files to match. - FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first; - for (unsigned i = 1, e = Opts.getFrontendOpts().Inputs.size(); i != e; ++i) { - if (Opts.getFrontendOpts().Inputs[i].first != IK) { - llvm::errs() << "error: cannot have multiple input files of distinct " - << "language kinds without -x\n"; - return false; - } - } - - // Initialize language options. - // - // FIXME: These aren't used during operations on ASTs. Split onto a separate - // code path to make this obvious. - if (IK != FrontendOptions::IK_AST) - InitializeLangOptions(Opts.getLangOpts(), IK); - - // Initialize the static analyzer options. - InitializeAnalyzerOptions(Opts.getAnalyzerOpts()); - - // Initialize the dependency output options (-M...). - InitializeDependencyOutputOptions(Opts.getDependencyOutputOpts()); - - // Initialize the header search options. - InitializeHeaderSearchOptions(Opts.getHeaderSearchOpts(), - GetBuiltinIncludePath(Argv0)); - - // Initialize the other preprocessor options. - InitializePreprocessorOptions(Opts.getPreprocessorOpts()); - - // Initialize the preprocessed output options. - InitializePreprocessorOutputOptions(Opts.getPreprocessorOutputOpts()); - - // Initialize backend options. - InitializeCodeGenOptions(Opts.getCodeGenOpts(), Opts.getLangOpts()); - - return true; -} - -static int cc1_main(Diagnostic &Diags, - const char **ArgBegin, const char **ArgEnd, - const char *Argv0, void *MainAddr) { - using namespace clang::driver; - - llvm::errs() << "cc1 argv:"; - for (const char **i = ArgBegin; i != ArgEnd; ++i) - llvm::errs() << " \"" << *i << '"'; - llvm::errs() << "\n"; - - // Parse the arguments. - OptTable *Opts = createCC1OptTable(); - unsigned MissingArgIndex, MissingArgCount; - InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd, - MissingArgIndex, MissingArgCount); - - // Check for missing argument error. - if (MissingArgCount) - Diags.Report(clang::diag::err_drv_missing_argument) - << Args->getArgString(MissingArgIndex) << MissingArgCount; - - // Dump the parsed arguments. - llvm::errs() << "cc1 parsed options:\n"; - for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); - it != ie; ++it) - (*it)->dump(); - - // Create a compiler invocation. - llvm::errs() << "cc1 creating invocation.\n"; - CompilerInvocation Invocation; - CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, - Argv0, MainAddr, Diags); - - // Convert the invocation back to argument strings. - std::vector<std::string> InvocationArgs; - Invocation.toArgs(InvocationArgs); - - // Dump the converted arguments. - llvm::SmallVector<const char*, 32> Invocation2Args; - llvm::errs() << "invocation argv :"; - for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { - Invocation2Args.push_back(InvocationArgs[i].c_str()); - llvm::errs() << " \"" << InvocationArgs[i] << '"'; - } - llvm::errs() << "\n"; - - // Convert those arguments to another invocation, and check that we got the - // same thing. - CompilerInvocation Invocation2; - CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(), - Invocation2Args.end(), Argv0, MainAddr, - Diags); - - // FIXME: Implement CompilerInvocation comparison. - if (true) { - //llvm::errs() << "warning: Invocations differ!\n"; - - std::vector<std::string> Invocation2Args; - Invocation2.toArgs(Invocation2Args); - llvm::errs() << "invocation2 argv:"; - for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i) - llvm::errs() << " \"" << Invocation2Args[i] << '"'; - llvm::errs() << "\n"; - } - - return 0; -} - -int main(int argc, char **argv) { - llvm::sys::PrintStackTraceOnErrorSignal(); - llvm::PrettyStackTraceProgram X(argc, argv); - CompilerInstance Clang(&llvm::getGlobalContext(), false); - - // Run clang -cc1 test. - if (argc > 1 && llvm::StringRef(argv[1]) == "-cc1") { - TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions()); - Diagnostic Diags(&DiagClient); - return cc1_main(Diags, (const char**) argv + 2, (const char**) argv + argc, - argv[0], (void*) (intptr_t) GetBuiltinIncludePath); - } - - // Initialize targets first, so that --version shows registered targets. - llvm::InitializeAllTargets(); - llvm::InitializeAllAsmPrinters(); - -#if 1 - llvm::cl::ParseCommandLineOptions(argc, argv, - "LLVM 'Clang' Compiler: http://clang.llvm.org\n"); - - // Construct the diagnostic engine first, so that we can build a diagnostic - // client to use for any errors during option handling. - InitializeDiagnosticOptions(Clang.getDiagnosticOpts()); - Clang.createDiagnostics(argc, argv); - if (!Clang.hasDiagnostics()) - return 1; - - // Set an error handler, so that any LLVM backend diagnostics go through our - // error handler. - llvm::llvm_install_error_handler(LLVMErrorHandler, - static_cast<void*>(&Clang.getDiagnostics())); - - // Now that we have initialized the diagnostics engine, create the target and - // the compiler invocation object. - // - // FIXME: We should move .ast inputs to taking a separate path, they are - // really quite different. - if (!ConstructCompilerInvocation(Clang.getInvocation(), - Clang.getDiagnostics(), argv[0])) - return 1; -#else - // Buffer diagnostics from argument parsing. - TextDiagnosticBuffer DiagsBuffer; - Diagnostic Diags(&DiagsBuffer); - - CompilerInvocation::CreateFromArgs(Clang.getInvocation(), - (const char**) argv + 1, - (const char**) argv + argc, argv[0], - (void*)(intptr_t) GetBuiltinIncludePath, - Diags); - - // Create the actual diagnostics engine. - Clang.createDiagnostics(argc, argv); - if (!Clang.hasDiagnostics()) - return 1; - - // Set an error handler, so that any LLVM backend diagnostics go through our - // error handler. - llvm::llvm_install_error_handler(LLVMErrorHandler, - static_cast<void*>(&Clang.getDiagnostics())); - - DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); - - // If there were any errors in processing arguments, exit now. - if (Clang.getDiagnostics().getNumErrors()) - return 1; -#endif - - // Create the target instance. - Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), - Clang.getTargetOpts())); - if (!Clang.hasTarget()) - return 1; - - // Inform the target of the language options - // - // FIXME: We shouldn't need to do this, the target should be immutable once - // created. This complexity should be lifted elsewhere. - Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); - - // Validate/process some options - if (Clang.getHeaderSearchOpts().Verbose) - llvm::errs() << "clang-cc version " CLANG_VERSION_STRING - << " based upon " << PACKAGE_STRING - << " hosted on " << llvm::sys::getHostTriple() << "\n"; - - if (Clang.getFrontendOpts().ShowTimers) - Clang.createFrontendTimer(); - - for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) { - const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second; - - // If we aren't using an AST file, setup the file and source managers and - // the preprocessor. - bool IsAST = - Clang.getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST; - if (!IsAST) { - if (!i) { - // Create a file manager object to provide access to and cache the - // filesystem. - Clang.createFileManager(); - - // Create the source manager. - Clang.createSourceManager(); - } else { - // Reset the ID tables if we are reusing the SourceManager. - Clang.getSourceManager().clearIDTables(); - } - - // Create the preprocessor. - Clang.createPreprocessor(); - } - - llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang)); - if (!Act) - break; - - if (Act->BeginSourceFile(Clang, InFile, IsAST)) { - Act->Execute(); - Act->EndSourceFile(); - } - } - - if (Clang.getDiagnosticOpts().ShowCarets) - if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics()) - fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics, - (NumDiagnostics == 1 ? "" : "s")); - - if (Clang.getFrontendOpts().ShowStats) { - Clang.getFileManager().PrintStats(); - fprintf(stderr, "\n"); - } - - // Return the appropriate status when verifying diagnostics. - // - // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need - // this. - if (Clang.getDiagnosticOpts().VerifyDiagnostics) - return static_cast<VerifyDiagnosticsClient&>( - Clang.getDiagnosticClient()).HadErrors(); - - // Managed static deconstruction. Useful for making things like - // -time-passes usable. - llvm::llvm_shutdown(); - - return (Clang.getDiagnostics().getNumErrors() != 0); -} - diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index 7900211..0815554 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -2,18 +2,31 @@ set(LLVM_NO_RTTI 1) set( LLVM_USED_LIBS clangDriver + clangFrontend + clangCodeGen + clangAnalysis + clangRewrite + clangSema + clangAST + clangParse + clangLex clangBasic ) -set(LLVM_LINK_COMPONENTS system support bitreader bitwriter) +set( LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + bitreader + bitwriter + codegen + ipo + selectiondag + ) add_clang_executable(clang driver.cpp cc1_main.cpp ) -add_dependencies(clang clang-cc) - if(UNIX) set(CLANGXX_LINK_OR_COPY create_symlink) else() diff --git a/tools/driver/Makefile b/tools/driver/Makefile index f250651..7dab2ac 100644 --- a/tools/driver/Makefile +++ b/tools/driver/Makefile @@ -1,10 +1,10 @@ ##===- tools/driver/Makefile -------------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## LEVEL = ../../../.. @@ -13,15 +13,20 @@ TOOLALIAS = clang++ CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include CXXFLAGS = -fno-rtti -# This tool has no plugins, optimize startup time. +# Clang tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 -# FIXME: It is unfortunate we need to pull in the bitcode reader and -# writer just to get the serializer stuff used by clangBasic. -LINK_COMPONENTS := system support bitreader bitwriter -USEDLIBS = clangDriver.a clangBasic.a +# Include this here so we can get the configuration of the targets that have +# been configured for construction. We have to do this early so we can set up +# LINK_COMPONENTS before including Makefile.rules +include $(LEVEL)/Makefile.config + +LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader bitwriter codegen ipo selectiondag +USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangAnalysis.a \ + clangRewrite.a clangSema.a clangAST.a clangParse.a \ + clangLex.a clangBasic.a -include $(LEVEL)/Makefile.common +include $(LLVM_SRC_ROOT)/Makefile.rules # Translate make variable to define when building a "production" clang. ifdef CLANG_IS_PRODUCTION diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index a9d27ef..6e82c51 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -7,18 +7,331 @@ // //===----------------------------------------------------------------------===// // -// This is the entry point to the clang -cc1 functionality. +// This is the entry point to the clang -cc1 functionality, which implements the +// core compiler functionality along with a number of additional tools for +// demonstration and testing purposes. // //===----------------------------------------------------------------------===// +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" +#include "clang/Driver/Arg.h" +#include "clang/Driver/ArgList.h" +#include "clang/Driver/CC1Options.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/OptTable.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Frontend/VerifyDiagnosticsClient.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/System/Host.h" +#include "llvm/System/Path.h" +#include "llvm/System/Signals.h" +#include "llvm/Target/TargetSelect.h" +#include <cstdio> +using namespace clang; + +//===----------------------------------------------------------------------===// +// Main driver +//===----------------------------------------------------------------------===// + +void LLVMErrorHandler(void *UserData, const std::string &Message) { + Diagnostic &Diags = *static_cast<Diagnostic*>(UserData); + + Diags.Report(diag::err_fe_error_backend) << Message; + + // We cannot recover from llvm errors. + exit(1); +} + +static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { + using namespace clang::frontend; + + switch (CI.getFrontendOpts().ProgramAction) { + default: + llvm_unreachable("Invalid program action!"); + + case ASTDump: return new ASTDumpAction(); + case ASTPrint: return new ASTPrintAction(); + case ASTPrintXML: return new ASTPrintXMLAction(); + case ASTView: return new ASTViewAction(); + case DumpRawTokens: return new DumpRawTokensAction(); + case DumpRecordLayouts: return new DumpRecordAction(); + case DumpTokens: return new DumpTokensAction(); + case EmitAssembly: return new EmitAssemblyAction(); + case EmitBC: return new EmitBCAction(); + case EmitHTML: return new HTMLPrintAction(); + case EmitLLVM: return new EmitLLVMAction(); + case EmitLLVMOnly: return new EmitLLVMOnlyAction(); + case FixIt: return new FixItAction(); + case GeneratePCH: return new GeneratePCHAction(); + case GeneratePTH: return new GeneratePTHAction(); + case InheritanceView: return new InheritanceViewAction(); + case ParseNoop: return new ParseOnlyAction(); + case ParsePrintCallbacks: return new PrintParseAction(); + case ParseSyntaxOnly: return new SyntaxOnlyAction(); + + case PluginAction: { + if (CI.getFrontendOpts().ActionName == "help") { + llvm::errs() << "clang -cc1 plugins:\n"; + for (FrontendPluginRegistry::iterator it = + FrontendPluginRegistry::begin(), + ie = FrontendPluginRegistry::end(); + it != ie; ++it) + llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n"; + return 0; + } + + for (FrontendPluginRegistry::iterator it = + FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); + it != ie; ++it) { + if (it->getName() == CI.getFrontendOpts().ActionName) + return it->instantiate(); + } + + CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) + << CI.getFrontendOpts().ActionName; + return 0; + } + + case PrintDeclContext: return new DeclContextPrintAction(); + case PrintPreprocessedInput: return new PrintPreprocessedAction(); + case RewriteBlocks: return new RewriteBlocksAction(); + case RewriteMacros: return new RewriteMacrosAction(); + case RewriteObjC: return new RewriteObjCAction(); + case RewriteTest: return new RewriteTestAction(); + case RunAnalysis: return new AnalysisAction(); + case RunPreprocessorOnly: return new PreprocessOnlyAction(); + } +} + +// FIXME: Define the need for this testing away. +static int cc1_test(Diagnostic &Diags, + const char **ArgBegin, const char **ArgEnd) { + using namespace clang::driver; -int cc1_main(const char **ArgBegin, const char **ArgEnd, - const char *Argv0, void *MainAddr) { llvm::errs() << "cc1 argv:"; for (const char **i = ArgBegin; i != ArgEnd; ++i) llvm::errs() << " \"" << *i << '"'; llvm::errs() << "\n"; + // Parse the arguments. + OptTable *Opts = createCC1OptTable(); + unsigned MissingArgIndex, MissingArgCount; + InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd, + MissingArgIndex, MissingArgCount); + + // Check for missing argument error. + if (MissingArgCount) + Diags.Report(clang::diag::err_drv_missing_argument) + << Args->getArgString(MissingArgIndex) << MissingArgCount; + + // Dump the parsed arguments. + llvm::errs() << "cc1 parsed options:\n"; + for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); + it != ie; ++it) + (*it)->dump(); + + // Create a compiler invocation. + llvm::errs() << "cc1 creating invocation.\n"; + CompilerInvocation Invocation; + CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags); + + // Convert the invocation back to argument strings. + std::vector<std::string> InvocationArgs; + Invocation.toArgs(InvocationArgs); + + // Dump the converted arguments. + llvm::SmallVector<const char*, 32> Invocation2Args; + llvm::errs() << "invocation argv :"; + for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { + Invocation2Args.push_back(InvocationArgs[i].c_str()); + llvm::errs() << " \"" << InvocationArgs[i] << '"'; + } + llvm::errs() << "\n"; + + // Convert those arguments to another invocation, and check that we got the + // same thing. + CompilerInvocation Invocation2; + CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(), + Invocation2Args.end(), Diags); + + // FIXME: Implement CompilerInvocation comparison. + if (true) { + //llvm::errs() << "warning: Invocations differ!\n"; + + std::vector<std::string> Invocation2Args; + Invocation2.toArgs(Invocation2Args); + llvm::errs() << "invocation2 argv:"; + for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i) + llvm::errs() << " \"" << Invocation2Args[i] << '"'; + llvm::errs() << "\n"; + } + return 0; } + +int cc1_main(const char **ArgBegin, const char **ArgEnd, + const char *Argv0, void *MainAddr) { + llvm::sys::PrintStackTraceOnErrorSignal(); + llvm::PrettyStackTraceProgram X(ArgBegin - ArgEnd, ArgBegin); + CompilerInstance Clang(&llvm::getGlobalContext(), false); + + // Run clang -cc1 test. + if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") { + TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions()); + Diagnostic Diags(&DiagClient); + return cc1_test(Diags, ArgBegin + 1, ArgEnd); + } + + // Initialize targets first, so that --version shows registered targets. + llvm::InitializeAllTargets(); + llvm::InitializeAllAsmPrinters(); + + // Buffer diagnostics from argument parsing so that we can output them using a + // well formed diagnostic object. + TextDiagnosticBuffer DiagsBuffer; + Diagnostic Diags(&DiagsBuffer); + CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd, + Diags); + + // Infer the builtin include path if unspecified. + if (Clang.getInvocation().getHeaderSearchOpts().UseBuiltinIncludes && + Clang.getInvocation().getHeaderSearchOpts().ResourceDir.empty()) + Clang.getInvocation().getHeaderSearchOpts().ResourceDir = + CompilerInvocation::GetResourcesPath(Argv0, MainAddr); + + // Honor -help. + if (Clang.getInvocation().getFrontendOpts().ShowHelp) { + llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable()); + Opts->PrintHelp(llvm::outs(), "clang -cc1", + "LLVM 'Clang' Compiler: http://clang.llvm.org"); + return 0; + } + + // Honor -version. + // + // FIXME: Use a better -version message? + if (Clang.getInvocation().getFrontendOpts().ShowVersion) { + llvm::cl::PrintVersionMessage(); + return 0; + } + + // Create the actual diagnostics engine. + Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin)); + if (!Clang.hasDiagnostics()) + return 1; + + // Set an error handler, so that any LLVM backend diagnostics go through our + // error handler. + llvm::llvm_install_error_handler(LLVMErrorHandler, + static_cast<void*>(&Clang.getDiagnostics())); + + DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); + + // Load any requested plugins. + for (unsigned i = 0, + e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) { + const std::string &Path = Clang.getFrontendOpts().Plugins[i]; + std::string Error; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) + Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error; + } + + // If there were any errors in processing arguments, exit now. + if (Clang.getDiagnostics().getNumErrors()) + return 1; + + // Create the target instance. + Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), + Clang.getTargetOpts())); + if (!Clang.hasTarget()) + return 1; + + // Inform the target of the language options + // + // FIXME: We shouldn't need to do this, the target should be immutable once + // created. This complexity should be lifted elsewhere. + Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + + // Validate/process some options + if (Clang.getHeaderSearchOpts().Verbose) + llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING + << " based upon " << PACKAGE_STRING + << " hosted on " << llvm::sys::getHostTriple() << "\n"; + + if (Clang.getFrontendOpts().ShowTimers) + Clang.createFrontendTimer(); + + for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) { + const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second; + + // If we aren't using an AST file, setup the file and source managers and + // the preprocessor. + bool IsAST = + Clang.getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST; + if (!IsAST) { + if (!i) { + // Create a file manager object to provide access to and cache the + // filesystem. + Clang.createFileManager(); + + // Create the source manager. + Clang.createSourceManager(); + } else { + // Reset the ID tables if we are reusing the SourceManager. + Clang.getSourceManager().clearIDTables(); + } + + // Create the preprocessor. + Clang.createPreprocessor(); + } + + llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang)); + if (!Act) + break; + + if (Act->BeginSourceFile(Clang, InFile, IsAST)) { + Act->Execute(); + Act->EndSourceFile(); + } + } + + if (Clang.getDiagnosticOpts().ShowCarets) + if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics()) + fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics, + (NumDiagnostics == 1 ? "" : "s")); + + if (Clang.getFrontendOpts().ShowStats) { + Clang.getFileManager().PrintStats(); + fprintf(stderr, "\n"); + } + + // Return the appropriate status when verifying diagnostics. + // + // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need + // this. + if (Clang.getDiagnosticOpts().VerifyDiagnostics) + return static_cast<VerifyDiagnosticsClient&>( + Clang.getDiagnosticClient()).HadErrors(); + + // Managed static deconstruction. Useful for making things like + // -time-passes usable. + llvm::llvm_shutdown(); + + return (Clang.getDiagnostics().getNumErrors() != 0); +} diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index c61ee72..cfdd9c3 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -60,7 +60,10 @@ void DriverDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, OS << '\n'; } -llvm::sys::Path GetExecutablePath(const char *Argv0) { +llvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { + if (!CanonicalPrefixes) + return llvm::sys::Path(Argv0); + // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. void *P = (void*) (intptr_t) GetExecutablePath; @@ -190,7 +193,16 @@ int main(int argc, const char **argv) { return cc1_main(argv+2, argv+argc, argv[0], (void*) (intptr_t) GetExecutablePath); - llvm::sys::Path Path = GetExecutablePath(argv[0]); + bool CanonicalPrefixes = true; + for (int i = 1; i < argc; ++i) { + if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") { + CanonicalPrefixes = false; + break; + } + } + + llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes); + DriverDiagnosticPrinter DiagClient(Path.getBasename(), llvm::errs()); Diagnostic Diags(&DiagClient); @@ -200,8 +212,8 @@ int main(int argc, const char **argv) { #else bool IsProduction = false; #endif - Driver TheDriver(Path.getBasename().c_str(), Path.getDirname().c_str(), - llvm::sys::getHostTriple().c_str(), + Driver TheDriver(Path.getBasename(), Path.getDirname(), + llvm::sys::getHostTriple(), "a.out", IsProduction, Diags); // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++ @@ -264,4 +276,3 @@ int main(int argc, const char **argv) { return Res; } - diff --git a/tools/index-test/CMakeLists.txt b/tools/index-test/CMakeLists.txt index 163afc4..9472e58 100644 --- a/tools/index-test/CMakeLists.txt +++ b/tools/index-test/CMakeLists.txt @@ -3,8 +3,9 @@ set(LLVM_NO_RTTI 1) set( LLVM_USED_LIBS clangIndex clangFrontend - clangAnalysis + clangDriver clangSema + clangAnalysis clangAST clangParse clangLex @@ -14,6 +15,7 @@ set( LLVM_USED_LIBS set( LLVM_LINK_COMPONENTS bitreader mc + core ) add_clang_executable(index-test diff --git a/tools/index-test/Makefile b/tools/index-test/Makefile index 8e7bfe5..4ee98fc 100644 --- a/tools/index-test/Makefile +++ b/tools/index-test/Makefile @@ -18,8 +18,8 @@ TOOL_NO_EXPORTS = 1 include $(LEVEL)/Makefile.config -LINK_COMPONENTS := bitreader mc -USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangAnalysis.a clangSema.a \ - clangAST.a clangParse.a clangLex.a clangBasic.a +LINK_COMPONENTS := bitreader mc core +USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \ + clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp index dd7cbb2..ff9fd54 100644 --- a/tools/index-test/index-test.cpp +++ b/tools/index-test/index-test.cpp @@ -208,20 +208,26 @@ static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) { static llvm::cl::opt<bool> ASTFromSource("ast-from-source", - llvm::cl::desc("Treat the inputs as source files to parse.")); + llvm::cl::desc("Treat the inputs as source files to parse")); + +static llvm::cl::list<std::string> +CompilerArgs("arg", llvm::cl::desc("Extra arguments to use during parsing")); static llvm::cl::list<std::string> InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input AST files>")); -void CreateCompilerInvocation(const std::string &Filename, - CompilerInvocation &CI, Diagnostic &Diags, - const char *argv0) { +ASTUnit *CreateFromSource(const std::string &Filename, Diagnostic &Diags, + const char *Argv0) { llvm::SmallVector<const char *, 16> Args; Args.push_back(Filename.c_str()); - - void *MainAddr = (void*) (intptr_t) CreateCompilerInvocation; - CompilerInvocation::CreateFromArgs(CI, Args.data(), Args.data() + Args.size(), - argv0, MainAddr, Diags); + for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) + Args.push_back(CompilerArgs[i].c_str()); + + void *MainAddr = (void*) (intptr_t) CreateFromSource; + std::string ResourceDir = + CompilerInvocation::GetResourcesPath(Argv0, MainAddr); + return ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(), + Diags, ResourceDir); } int main(int argc, char **argv) { @@ -234,9 +240,9 @@ int main(int argc, char **argv) { Indexer Idxer(Prog); llvm::SmallVector<TUnit*, 4> TUnits; - TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions(), false); + DiagnosticOptions DiagOpts; llvm::OwningPtr<Diagnostic> Diags( - CompilerInstance::createDiagnostics(DiagnosticOptions(), argc, argv)); + CompilerInstance::createDiagnostics(DiagOpts, argc, argv)); // If no input was specified, read from stdin. if (InputFilenames.empty()) @@ -244,23 +250,13 @@ int main(int argc, char **argv) { for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { const std::string &InFile = InputFilenames[i]; - - std::string ErrMsg; llvm::OwningPtr<ASTUnit> AST; - - if (ASTFromSource) { - CompilerInvocation CI; - CreateCompilerInvocation(InFile, CI, *Diags, argv[0]); - AST.reset(ASTUnit::LoadFromCompilerInvocation(CI, *Diags)); - if (!AST) - ErrMsg = "unable to create AST"; - } else - AST.reset(ASTUnit::LoadFromPCHFile(InFile, &ErrMsg)); - - if (!AST) { - llvm::errs() << "[" << InFile << "] Error: " << ErrMsg << '\n'; + if (ASTFromSource) + AST.reset(CreateFromSource(InFile, *Diags, argv[0])); + else + AST.reset(ASTUnit::LoadFromPCHFile(InFile, *Diags)); + if (!AST) return 1; - } TUnit *TU = new TUnit(AST.take(), InFile); TUnits.push_back(TU); diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer index 25b9800..aca411f 100755 --- a/tools/scan-build/ccc-analyzer +++ b/tools/scan-build/ccc-analyzer @@ -14,14 +14,38 @@ use strict; use warnings; +use FindBin; use Cwd qw/ getcwd abs_path /; use File::Temp qw/ tempfile /; use File::Path qw / mkpath /; use File::Basename; use Text::ParseWords; -my $CC = $ENV{'CCC_CC'}; -if (!defined $CC) { $CC = "gcc"; } +##===----------------------------------------------------------------------===## +# Compiler command setup. +##===----------------------------------------------------------------------===## + +my $Compiler; +my $Clang; + +if ($FindBin::Script =~ /c\+\+-analyzer/) { + $Compiler = $ENV{'CCC_CXX'}; + if (!defined $Compiler) { $Compiler = "g++"; } + + $Clang = $ENV{'CLANG_CXX'}; + if (!defined $Clang) { $Clang = 'clang++'; } +} +else { + $Compiler = $ENV{'CCC_CC'}; + if (!defined $Compiler) { $Compiler = "gcc"; } + + $Clang = $ENV{'CLANG'}; + if (!defined $Clang) { $Clang = 'clang'; } +} + +##===----------------------------------------------------------------------===## +# Cleanup. +##===----------------------------------------------------------------------===## my $ReportFailures = $ENV{'CCC_REPORT_FAILURES'}; if (!defined $ReportFailures) { $ReportFailures = 1; } @@ -53,7 +77,7 @@ my $ParserRejects = "Parser Rejects"; my $AttributeIgnored = "Attribute Ignored"; sub ProcessClangFailure { - my ($ClangCC, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; + my ($Clang, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; my $Dir = "$HtmlDir/failures"; mkpath $Dir; @@ -69,7 +93,7 @@ sub ProcessClangFailure { my ($PPH, $PPFile) = tempfile( $prefix . "_XXXXXX", SUFFIX => GetPPExt($Lang), DIR => $Dir); - system $ClangCC, @$Args, "-E", "-o", $PPFile; + system $Clang, @$Args, "-E", "-o", $PPFile; close ($PPH); # Create the info file. @@ -79,7 +103,7 @@ sub ProcessClangFailure { print OUT "@$Args\n"; close OUT; `uname -a >> $PPFile.info.txt 2>&1`; - `$CC -v >> $PPFile.info.txt 2>&1`; + `$Compiler -v >> $PPFile.info.txt 2>&1`; system 'mv',$ofile,"$PPFile.stderr.txt"; return (basename $PPFile); } @@ -88,10 +112,6 @@ sub ProcessClangFailure { # Running the analyzer. ##----------------------------------------------------------------------------## -# Determine what clang executable to use. -my $Clang = $ENV{'CLANG'}; -if (!defined $Clang) { $Clang = 'clang'; } - sub GetCCArgs { my $Args = shift; @@ -106,14 +126,14 @@ sub GetCCArgs { close(TO_PARENT); my $line; while (<FROM_CHILD>) { - next if (!/clang-cc/); + next if (!/-cc1/); $line = $_; } waitpid($pid,0); close(FROM_CHILD); - die "could not find clang-cc line\n" if (!defined $line); + die "could not find clang line\n" if (!defined $line); # Strip the newline and initial whitspace chomp $line; $line =~ s/^\s+//; @@ -124,19 +144,16 @@ sub GetCCArgs { $items[$i] =~ s/\"$//; } my $cmd = shift @items; - die "cannot find 'clang-cc' in 'clang' command\n" if (!($cmd =~ /clang-cc/)); + die "cannot find 'clang' in 'clang' command\n" if (!($cmd =~ /clang/)); return \@items; } sub Analyze { - my ($ClangCC, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir, + my ($Clang, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir, $file, $Analyses) = @_; $Args = GetCCArgs($Args); - # Skip anything related to C++. - return if ($Lang =~ /c[+][+]/); - my $RunAnalyzer = 0; my $Cmd; my @CmdArgs; @@ -152,13 +169,15 @@ sub Analyze { @CmdArgsSansAnalyses = @CmdArgs; } else { - $Cmd = $ClangCC; + $Cmd = $Clang; + push @CmdArgs, "-cc1"; push @CmdArgs,'-DIBOutlet=__attribute__((iboutlet))'; - push @CmdArgs,@$Args; + push @CmdArgs, @$Args; @CmdArgsSansAnalyses = @CmdArgs; push @CmdArgs,'-analyze'; push @CmdArgs,"-analyzer-display-progress"; push @CmdArgs,"-analyzer-eagerly-assume"; + push @CmdArgs,"-analyzer-opt-analyze-nested-blocks"; push @CmdArgs,(split /\s/,$Analyses); if (defined $ENV{"CCC_EXPERIMENTAL_CHECKS"}) { @@ -236,13 +255,13 @@ sub Analyze { # Did the command die because of a signal? if ($ReportFailures) { - if ($Result & 127 and $Cmd eq $ClangCC and defined $HtmlDir) { - ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, + if ($Result & 127 and $Cmd eq $Clang and defined $HtmlDir) { + ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, "Crash", $ofile); } elsif ($Result) { if ($IncludeParserRejects && !($file =~/conftest/)) { - ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, + ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, $ParserRejects, $ofile); } } @@ -274,7 +293,7 @@ sub Analyze { # Add this file to the list of files that contained this attribute. # Generate a preprocessed file if we haven't already. if (!(defined $ppfile)) { - $ppfile = ProcessClangFailure($ClangCC, $Lang, $file, + $ppfile = ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, $AttributeIgnored, $ofile); } @@ -359,7 +378,9 @@ my %UniqueOptions = ( my %LangsAccepted = ( "objective-c" => 1, - "c" => 1 + "c" => 1, + "c++" => 1, + "objective-c++" => 1 ); ##----------------------------------------------------------------------------## @@ -375,7 +396,7 @@ my $Output; my %Uniqued; # Forward arguments to gcc. -my $Status = system($CC,@ARGV); +my $Status = system($Compiler,@ARGV); if ($Status) { exit($Status >> 8); } # Get the analysis options. @@ -399,10 +420,6 @@ my $Verbose = 0; if (defined $ENV{CCC_ANALYZER_VERBOSE}) { $Verbose = 1; } if (defined $ENV{CCC_ANALYZER_LOG}) { $Verbose = 2; } -# Determine what clang-cc executable to use. -my $ClangCC = $ENV{'CLANG_CC'}; -if (!defined $ClangCC) { $ClangCC = 'clang-cc'; } - # Get the HTML output directory. my $HtmlDir = $ENV{'CCC_ANALYZER_HTML'}; @@ -617,12 +634,12 @@ if ($Action eq 'compile' or $Action eq 'link') { push @NewArgs, '-arch'; push @NewArgs, $arch; push @NewArgs, @CmdArgs; - Analyze($ClangCC, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output, + Analyze($Clang, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output, $Verbose, $HtmlDir, $file, $Analyses); } } else { - Analyze($ClangCC, \@CmdArgs, \@AnalyzeArgs, $FileLang, $Output, + Analyze($Clang, \@CmdArgs, \@AnalyzeArgs, $FileLang, $Output, $Verbose, $HtmlDir, $file, $Analyses); } } diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index 8d99f07..f978a88 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -26,7 +26,6 @@ my $Verbose = 0; # Verbose output from this script. my $Prog = "scan-build"; my $BuildName; my $BuildDate; -my $CXX; # Leave undefined initially. my $TERM = $ENV{'TERM'}; my $UseColor = (defined $TERM and $TERM eq 'xterm-color' and -t STDOUT @@ -81,43 +80,26 @@ sub DieDiag { # Some initial preprocessing of Clang options. ##----------------------------------------------------------------------------## -# First, look for 'clang-cc' in libexec. -my $ClangCCSB = Cwd::realpath("$RealBin/libexec/clang-cc"); -# Second, look for 'clang-cc' in the same directory as scan-build. -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - $ClangCCSB = Cwd::realpath("$RealBin/clang-cc"); -} -# Third, look for 'clang-cc' in ../libexec -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - $ClangCCSB = Cwd::realpath("$RealBin/../libexec/clang-cc"); -} -# Finally, default to looking for 'clang-cc' in the path. -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - $ClangCCSB = "clang-cc"; -} -my $ClangCC = $ClangCCSB; - -# Now find 'clang' +# Find 'clang' my $ClangSB = Cwd::realpath("$RealBin/bin/clang"); +my $ClangCXXSB; if (!defined $ClangSB || ! -x $ClangSB) { $ClangSB = Cwd::realpath("$RealBin/clang"); -} -# Third, look for 'clang' in ../bin -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = Cwd::realpath("$RealBin/../bin/clang"); -} -# Finally, default to looking for 'clang-cc' in the path. -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = "clang"; + if (defined $ClangSB) { $ClangCXXSB = $ClangSB . "++"; } } my $Clang = $ClangSB; - +my $ClangCXX = $ClangCXXSB; +# Default to looking for 'clang' in the path. +if (!defined $Clang || ! -x $Clang) { + $Clang = "clang"; + $ClangCXX = "clang++"; +} my %AvailableAnalyses; # Query clang for analysis options. -open(PIPE, "-|", $ClangCC, "--help") or - DieDiag("Cannot execute '$ClangCC'\n"); +open(PIPE, "-|", $Clang, "-cc1", "--help") or + DieDiag("Cannot execute '$Clang'\n"); my $FoundAnalysis = 0; @@ -128,17 +110,14 @@ while(<PIPE>) { } next; } - if (/^\s\s\s\s([^\s]+)\s(.+)$/) { next if ($1 =~ /-dump/ or $1 =~ /-view/ - or $1 =~ /-warn-uninit/); - + or $1 =~ /-warn-uninit/); $AvailableAnalyses{$1} = $2; next; } last; } - close (PIPE); my %AnalysesDefaultEnabled = ( @@ -156,10 +135,8 @@ my %AnalysesDefaultEnabled = ( ##----------------------------------------------------------------------------## sub GetHTMLRunDir { - die "Not enough arguments." if (@_ == 0); - my $Dir = shift @_; - + my $Dir = shift @_; my $TmpMode = 0; if (!defined $Dir) { if (`uname` =~ /Darwin/) { @@ -168,8 +145,7 @@ sub GetHTMLRunDir { } else { $Dir = "/tmp"; - } - + } $TmpMode = 1; } @@ -177,42 +153,32 @@ sub GetHTMLRunDir { while ($Dir =~ /\/$/) { chop $Dir; } # Get current date and time. - - my @CurrentTime = localtime(); - + my @CurrentTime = localtime(); my $year = $CurrentTime[5] + 1900; my $day = $CurrentTime[3]; my $month = $CurrentTime[4] + 1; - my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); - # Determine the run number. - + # Determine the run number. my $RunNumber; - if (-d $Dir) { - + if (-d $Dir) { if (! -r $Dir) { DieDiag("directory '$Dir' exists but is not readable.\n"); - } - - # Iterate over all files in the specified directory. - - my $max = 0; - + } + # Iterate over all files in the specified directory. + my $max = 0; opendir(DIR, $Dir); my @FILES = grep { -d "$Dir/$_" } readdir(DIR); closedir(DIR); - - foreach my $f (@FILES) { + foreach my $f (@FILES) { # Strip the prefix '$Prog-' if we are dumping files to /tmp. if ($TmpMode) { next if (!($f =~ /^$Prog-(.+)/)); $f = $1; } - my @x = split/-/, $f; next if (scalar(@x) != 4); next if ($x[0] != $year); @@ -836,14 +802,26 @@ sub RunBuildCommand { $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) { if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) { - $ENV{"CCC_CC"} = $1; + $ENV{"CCC_CC"} = $1; } shift @$Args; unshift @$Args, $CCAnalyzer; } + elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or + $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or + $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or + $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) { + if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) { + $ENV{"CCC_CXX"} = $1; + } + shift @$Args; + unshift @$Args, $CCAnalyzer; + } elsif ($IgnoreErrors) { if ($Cmd eq "make" or $Cmd eq "gmake") { + AddIfNotPresent($Args, "CC=$CCAnalyzer"); + AddIfNotPresent($Args, "CXX=$CCAnalyzer"); AddIfNotPresent($Args,"-k"); AddIfNotPresent($Args,"-i"); } @@ -860,6 +838,7 @@ sub RunBuildCommand { if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) { if (@$Args[$i+1] =~ /^iphonesimulator3/) { $ENV{"CCC_CC"} = "gcc-4.2"; + $ENV{"CCC_CXX"} = "g++-4.2"; } } } @@ -874,10 +853,10 @@ sub RunBuildCommand { # When 'CC' is set, xcodebuild uses it to do all linking, even if we are # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' # when linking such files. - die if (!defined $CXX); - my $LDPLUSPLUS = `which $CXX`; - $LDPLUSPLUS =~ s/\015?\012//; # strip newlines - $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS; + if (!defined $ENV{'CCC_CXX'}) { + $ENV{'CCC_CXX'} = 'g++'; + } + $ENV{'LDPLUSPLUS'} = $ENV{'CCC_CXX'}; } return (system(@$Args) >> 8); @@ -1125,16 +1104,19 @@ while (@ARGV) { if ($arg =~ /^--use-c\+\+(=(.+))?$/) { shift @ARGV; + my $cxx; if (!defined $2 || $2 eq "") { if (!@ARGV) { DieDiag("'--use-c++' option requires a compiler executable name.\n"); } - $CXX = shift @ARGV; + $cxx = shift @ARGV; } else { - $CXX = $2; + $cxx = $2; } + + $ENV{"CCC_CXX"} = $cxx; next; } @@ -1206,32 +1188,28 @@ $HtmlDir = GetHTMLRunDir($HtmlDir); # Set the appropriate environment variables. SetHtmlEnv(\@ARGV, $HtmlDir); -my $Cmd = Cwd::realpath("$RealBin/libexec/ccc-analyzer"); +my $AbsRealBin = Cwd::realpath($RealBin); +my $Cmd = "$AbsRealBin/libexec/ccc-analyzer"; +my $CmdCXX = "$AbsRealBin/libexec/c++-analyzer"; + if (!defined $Cmd || ! -x $Cmd) { - $Cmd = Cwd::realpath("$RealBin/ccc-analyzer"); + $Cmd = "$AbsRealBin/ccc-analyzer"; DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd); } - -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - Diag("'clang-cc' executable not found in '$RealBin/libexec'.\n"); - Diag("Using 'clang-cc' from path.\n"); +if (!defined $CmdCXX || ! -x $CmdCXX) { + $CmdCXX = "$AbsRealBin/c++-analyzer"; + DieDiag("Executable 'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -x $CmdCXX); } + if (!defined $ClangSB || ! -x $ClangSB) { Diag("'clang' executable not found in '$RealBin/bin'.\n"); Diag("Using 'clang' from path.\n"); } -if (defined $CXX) { - $ENV{'CXX'} = $CXX; -} -else { - $CXX = 'g++'; # This variable is used by other parts of scan-build - # that need to know a default C++ compiler to fall back to. -} - $ENV{'CC'} = $Cmd; -$ENV{'CLANG_CC'} = $ClangCC; +$ENV{'CXX'} = $CmdCXX; $ENV{'CLANG'} = $Clang; +$ENV{'CLANG_CXX'} = $ClangCXX; if ($Verbose >= 2) { $ENV{'CCC_ANALYZER_VERBOSE'} = 1; |