diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 | 
| commit | 06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 (patch) | |
| tree | 3eb853da77d46cc77c4b017525a422f9ddb1385b /tools | |
| parent | 30d791273d07fac9c0c1641a0731191bca6e8606 (diff) | |
Diffstat (limited to 'tools')
59 files changed, 1253 insertions, 962 deletions
diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp index a59a869c225c..7be4ed6e2a21 100644 --- a/tools/arcmt-test/arcmt-test.cpp +++ b/tools/arcmt-test/arcmt-test.cpp @@ -269,14 +269,11 @@ static bool verifyTransformedFiles(ArrayRef<std::string> resultFiles) {        return true;      } -    bool exists = false; -    sys::fs::exists(It->second, exists); -    if (!exists) { +    if (!sys::fs::exists(It->second)) {        errs() << "error: '" << It->second << "' does not exist\n";        return true;      } -    sys::fs::exists(inputResultFname, exists); -    if (!exists) { +    if (!sys::fs::exists(inputResultFname)) {        errs() << "error: '" << inputResultFname << "' does not exist\n";        return true;      } diff --git a/tools/c-arcmt-test/CMakeLists.txt b/tools/c-arcmt-test/CMakeLists.txt index 9014ccc309f2..8914607358fc 100644 --- a/tools/c-arcmt-test/CMakeLists.txt +++ b/tools/c-arcmt-test/CMakeLists.txt @@ -2,9 +2,15 @@ add_clang_executable(c-arcmt-test    c-arcmt-test.c    ) -target_link_libraries(c-arcmt-test -  libclang -  ) +if (LLVM_BUILD_STATIC) +  target_link_libraries(c-arcmt-test +    libclang_static +    ) +else() +  target_link_libraries(c-arcmt-test +    libclang +    ) +endif()  set_target_properties(c-arcmt-test    PROPERTIES diff --git a/tools/c-arcmt-test/Makefile b/tools/c-arcmt-test/Makefile index e7d5be7658b8..fff05f828254 100644 --- a/tools/c-arcmt-test/Makefile +++ b/tools/c-arcmt-test/Makefile @@ -30,6 +30,7 @@ USEDLIBS = clang.a \  	   clangIndex.a \  	   clangFormat.a \  	   clangTooling.a \ +	   clangToolingCore.a \  	   clangRewriteFrontend.a \  	   clangRewrite.a \  	   clangFrontend.a clangDriver.a \ diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt index 113172ad157c..d0872fd2eff3 100644 --- a/tools/c-index-test/CMakeLists.txt +++ b/tools/c-index-test/CMakeLists.txt @@ -9,9 +9,15 @@ if(NOT MSVC)      )  endif() -target_link_libraries(c-index-test -  libclang +if (LLVM_BUILD_STATIC) +  target_link_libraries(c-index-test +    libclang_static    ) +else() +  target_link_libraries(c-index-test +    libclang +  ) +endif()  set_target_properties(c-index-test    PROPERTIES diff --git a/tools/c-index-test/Makefile b/tools/c-index-test/Makefile index 42bfbb05839c..62bc9348dbf5 100644 --- a/tools/c-index-test/Makefile +++ b/tools/c-index-test/Makefile @@ -30,6 +30,7 @@ USEDLIBS = clang.a \  	   clangIndex.a clangFormat.a clangRewrite.a \  	   clangFrontend.a clangDriver.a \  	   clangTooling.a \ +	   clangToolingCore.a \  	   clangSerialization.a clangParse.a clangSema.a \  	   clangAnalysis.a clangEdit.a clangAST.a clangLex.a \  	   clangBasic.a diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 07be22a5e940..56e4101399a5 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -796,15 +796,42 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {        printf(" [access=%s isVirtual=%s]", accessStr,               isVirtual ? "true" : "false");      } -     +      SpecializationOf = clang_getSpecializedCursorTemplate(Cursor);      if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {        CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);        CXString Name = clang_getCursorSpelling(SpecializationOf);        clang_getSpellingLocation(Loc, 0, &line, &column, 0); -      printf(" [Specialization of %s:%d:%d]",  +      printf(" [Specialization of %s:%d:%d]",               clang_getCString(Name), line, column);        clang_disposeString(Name); + +      if (Cursor.kind == CXCursor_FunctionDecl) { +        /* Collect the template parameter kinds from the base template. */ +        unsigned NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor); +        unsigned I; +        for (I = 0; I < NumTemplateArgs; I++) { +          enum CXTemplateArgumentKind TAK = +              clang_Cursor_getTemplateArgumentKind(Cursor, I); +          switch(TAK) { +            case CXTemplateArgumentKind_Type: +              { +                CXType T = clang_Cursor_getTemplateArgumentType(Cursor, I); +                CXString S = clang_getTypeSpelling(T); +                printf(" [Template arg %d: kind: %d, type: %s]", +                       I, TAK, clang_getCString(S)); +                clang_disposeString(S); +              } +              break; +            case CXTemplateArgumentKind_Integral: +              printf(" [Template arg %d: kind: %d, intval: %lld]", +                     I, TAK, clang_Cursor_getTemplateArgumentValue(Cursor, I)); +              break; +            default: +              printf(" [Template arg %d: kind: %d]\n", I, TAK); +          } +        } +      }      }      clang_getOverriddenCursors(Cursor, &overridden, &num_overridden); @@ -1363,6 +1390,20 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p,  }  /******************************************************************************/ +/* Mangling testing.                                                          */ +/******************************************************************************/ + +static enum CXChildVisitResult PrintMangledName(CXCursor cursor, CXCursor p, +                                                CXClientData d) { +  CXString MangledName; +  PrintCursor(cursor, NULL); +  MangledName = clang_Cursor_getMangling(cursor); +  printf(" [mangled=%s]\n", clang_getCString(MangledName)); +  clang_disposeString(MangledName); +  return CXChildVisit_Continue; +} + +/******************************************************************************/  /* Bitwidth testing.                                                          */  /******************************************************************************/ @@ -1629,6 +1670,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,    if ((fp = fopen(source_file, "r")) == NULL) {      fprintf(stderr, "Could not open '%s'\n", source_file); +    clang_disposeTranslationUnit(TU);      return 1;    } @@ -4081,6 +4123,8 @@ int cindextest_main(int argc, const char **argv) {    else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0)      return perform_test_load_source(argc - 2, argv + 2, "all",                                      PrintBitWidth, 0); +  else if (argc > 2 && strcmp(argv[1], "-test-print-mangle") == 0) +    return perform_test_load_tu(argv[2], "all", NULL, PrintMangledName, NULL);    else if (argc > 1 && strcmp(argv[1], "-print-usr") == 0) {      if (argc > 2)        return print_usrs(argv + 2, argv + argc); diff --git a/tools/clang-check/ClangCheck.cpp b/tools/clang-check/ClangCheck.cpp index cc8d43cec221..7992026a7ccf 100644 --- a/tools/clang-check/ClangCheck.cpp +++ b/tools/clang-check/ClangCheck.cpp @@ -25,6 +25,7 @@  #include "clang/StaticAnalyzer/Frontend/FrontendActions.h"  #include "clang/Tooling/CommonOptionsParser.h"  #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/Option/OptTable.h"  #include "llvm/Support/Path.h"  #include "llvm/Support/Signals.h" @@ -77,15 +78,6 @@ static cl::opt<bool> FixWhatYouCan(      cl::desc(Options->getOptionHelpText(options::OPT_fix_what_you_can)),      cl::cat(ClangCheckCategory)); -static cl::list<std::string> ArgsAfter( -    "extra-arg", -    cl::desc("Additional argument to append to the compiler command line"), -    cl::cat(ClangCheckCategory)); -static cl::list<std::string> ArgsBefore( -    "extra-arg-before", -    cl::desc("Additional argument to prepend to the compiler command line"), -    cl::cat(ClangCheckCategory)); -  namespace {  // FIXME: Move FixItRewriteInPlace from lib/Rewrite/Frontend/FrontendActions.cpp @@ -139,57 +131,21 @@ public:    }  }; -class InsertAdjuster: public clang::tooling::ArgumentsAdjuster { -public: -  enum Position { BEGIN, END }; - -  InsertAdjuster(const CommandLineArguments &Extra, Position Pos) -    : Extra(Extra), Pos(Pos) { -  } - -  InsertAdjuster(const char *Extra, Position Pos) -    : Extra(1, std::string(Extra)), Pos(Pos) { -  } - -  virtual CommandLineArguments -  Adjust(const CommandLineArguments &Args) override { -    CommandLineArguments Return(Args); - -    CommandLineArguments::iterator I; -    if (Pos == END) { -      I = Return.end(); -    } else { -      I = Return.begin(); -      ++I; // To leave the program name in place -    } - -    Return.insert(I, Extra.begin(), Extra.end()); -    return Return; -  } - -private: -  const CommandLineArguments Extra; -  const Position Pos; -}; - -} // namespace - -// Anonymous namespace here causes problems with gcc <= 4.4 on MacOS 10.6. -// "Non-global symbol: ... can't be a weak_definition" -namespace clang_check {  class ClangCheckActionFactory {  public: -  clang::ASTConsumer *newASTConsumer() { +  std::unique_ptr<clang::ASTConsumer> newASTConsumer() {      if (ASTList)        return clang::CreateASTDeclNodeLister();      if (ASTDump) -      return clang::CreateASTDumper(ASTDumpFilter); +      return clang::CreateASTDumper(ASTDumpFilter, /*DumpDecls=*/true, +                                    /*DumpLookups=*/false);      if (ASTPrint)        return clang::CreateASTPrinter(&llvm::outs(), ASTDumpFilter); -    return new clang::ASTConsumer(); +    return llvm::make_unique<clang::ASTConsumer>();    }  }; -} + +} // namespace  int main(int argc, const char **argv) {    llvm::sys::PrintStackTraceOnErrorSignal(); @@ -199,22 +155,14 @@ int main(int argc, const char **argv) {    // Clear adjusters because -fsyntax-only is inserted by the default chain.    Tool.clearArgumentsAdjusters(); -  Tool.appendArgumentsAdjuster(new ClangStripOutputAdjuster()); -  if (ArgsAfter.size() > 0) { -    Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsAfter, -          InsertAdjuster::END)); -  } -  if (ArgsBefore.size() > 0) { -    Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsBefore, -          InsertAdjuster::BEGIN)); -  } +  Tool.appendArgumentsAdjuster(getClangStripOutputAdjuster());    // Running the analyzer requires --analyze. Other modes can work with the    // -fsyntax-only option. -  Tool.appendArgumentsAdjuster(new InsertAdjuster( -        Analyze ? "--analyze" : "-fsyntax-only", InsertAdjuster::BEGIN)); +  Tool.appendArgumentsAdjuster(getInsertArgumentAdjuster( +      Analyze ? "--analyze" : "-fsyntax-only", ArgumentInsertPosition::BEGIN)); -  clang_check::ClangCheckActionFactory CheckFactory; +  ClangCheckActionFactory CheckFactory;    std::unique_ptr<FrontendActionFactory> FrontendFactory;    // Choose the correct factory based on the selected mode. diff --git a/tools/clang-format-vs/CMakeLists.txt b/tools/clang-format-vs/CMakeLists.txt index b1101928aa51..0a50a6a8c426 100644 --- a/tools/clang-format-vs/CMakeLists.txt +++ b/tools/clang-format-vs/CMakeLists.txt @@ -6,6 +6,11 @@ if (BUILD_CLANG_FORMAT_VS_PLUGIN)        "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/clang-format.exe"        DEPENDS clang-format) +  add_custom_target(clang_format_license +      ${CMAKE_COMMAND} -E copy_if_different +      "${CLANG_SOURCE_DIR}/LICENSE.TXT" +      "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/license.txt") +    if (NOT CLANG_FORMAT_VS_VERSION)      set(CLANG_FORMAT_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")    endif() @@ -19,5 +24,5 @@ if (BUILD_CLANG_FORMAT_VS_PLUGIN)        COMMAND ${CMAKE_COMMAND} -E copy_if_different        "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/bin/Release/ClangFormat.vsix"        "${LLVM_TOOLS_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ClangFormat.vsix" -      DEPENDS clang_format_exe_for_vsix) +      DEPENDS clang_format_exe_for_vsix clang_format_license)  endif() diff --git a/tools/clang-format-vs/ClangFormat/ClangFormat.csproj b/tools/clang-format-vs/ClangFormat/ClangFormat.csproj index 2f49221d14b3..709b33d6fa22 100644 --- a/tools/clang-format-vs/ClangFormat/ClangFormat.csproj +++ b/tools/clang-format-vs/ClangFormat/ClangFormat.csproj @@ -181,6 +181,9 @@      <Content Include="clang-format.exe">
        <IncludeInVSIX>true</IncludeInVSIX>
      </Content>
 +    <Content Include="license.txt">
 +      <IncludeInVSIX>true</IncludeInVSIX>
 +    </Content>
      <Content Include="Resources\Package.ico" />
    </ItemGroup>
    <ItemGroup>
 @@ -227,4 +230,4 @@    <Target Name="AfterBuild">
    </Target>
    -->
 -</Project>
\ No newline at end of file +</Project>
 diff --git a/tools/clang-format-vs/README.txt b/tools/clang-format-vs/README.txt index b87df6e92379..636b89f3c673 100644 --- a/tools/clang-format-vs/README.txt +++ b/tools/clang-format-vs/README.txt @@ -6,8 +6,11 @@ Build prerequisites are:  - Visual Studio 2010 Professional
  - Visual Studio 2010 SDK.
 -clang-format.exe must be copied into the ClangFormat/ directory before building.
 -It will be bundled into the .vsix file.
 +The extension is built using CMake by setting BUILD_CLANG_FORMAT_VS_PLUGIN=ON
 +when configuring a Clang build, and building the clang_format_vsix target.
 -The extension can be built manually from ClangFormat.sln (e.g. by opening it in
 -Visual Studio), or with cmake by setting the BUILD_CLANG_FORMAT_VS_PLUGIN flag.
 +The CMake build will copy clang-format.exe and LICENSE.TXT into the ClangFormat/
 +directory so they can be bundled with the plug-in, as well as creating
 +ClangFormat/source.extension.vsixmanifest. Once the plug-in has been built with
 +CMake once, it can be built manually from the ClangFormat.sln solution in Visual
 +Studio.
 diff --git a/tools/clang-format-vs/source.extension.vsixmanifest.in b/tools/clang-format-vs/source.extension.vsixmanifest.in index ed0e72e35512..496fa40063b7 100644 --- a/tools/clang-format-vs/source.extension.vsixmanifest.in +++ b/tools/clang-format-vs/source.extension.vsixmanifest.in @@ -6,6 +6,8 @@      <Version>@CLANG_FORMAT_VS_VERSION@</Version>
      <Description xml:space="preserve">A tool to format C/C++/Obj-C code.</Description>
      <Locale>1033</Locale>
 +    <MoreInfoUrl>http://clang.llvm.org/docs/ClangFormat.html</MoreInfoUrl>
 +    <License>license.txt</License>
      <InstalledByMsi>false</InstalledByMsi>
      <SupportedProducts>
        <VisualStudio Version="10.0">
 @@ -17,6 +19,9 @@        <VisualStudio Version="12.0">
          <Edition>Pro</Edition>
        </VisualStudio>
 +      <VisualStudio Version="14.0">
 +        <Edition>Pro</Edition>
 +      </VisualStudio>
      </SupportedProducts>
      <SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />
    </Identifier>
 diff --git a/tools/clang-format/CMakeLists.txt b/tools/clang-format/CMakeLists.txt index f80a3ec9c91f..6a24e138efcf 100644 --- a/tools/clang-format/CMakeLists.txt +++ b/tools/clang-format/CMakeLists.txt @@ -7,9 +7,8 @@ add_clang_executable(clang-format  target_link_libraries(clang-format    clangBasic    clangFormat -  clangLex    clangRewrite -  clangTooling +  clangToolingCore    )  install(TARGETS clang-format RUNTIME DESTINATION bin) diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp index cebb2757d4da..d44d407aa86c 100644 --- a/tools/clang-format/ClangFormat.cpp +++ b/tools/clang-format/ClangFormat.cpp @@ -19,9 +19,9 @@  #include "clang/Basic/SourceManager.h"  #include "clang/Basic/Version.h"  #include "clang/Format/Format.h" -#include "clang/Lex/Lexer.h"  #include "clang/Rewrite/Core/Rewriter.h"  #include "llvm/ADT/StringMap.h" +#include "llvm/Support/CommandLine.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/Signals.h" @@ -76,7 +76,7 @@ static cl::opt<std::string>  AssumeFilename("assume-filename",                 cl::desc("When reading from stdin, clang-format assumes this\n"                          "filename to look for a style config file (with\n" -                        "-style=file)."), +                        "-style=file) and to determine the language."),                 cl::cat(ClangFormatCategory));  static cl::opt<bool> Inplace("i", @@ -225,12 +225,14 @@ static bool format(StringRef FileName) {    FormatStyle FormatStyle = getStyle(        Style, (FileName == "-") ? AssumeFilename : FileName, FallbackStyle); -  Lexer Lex(ID, Sources.getBuffer(ID), Sources, -            getFormattingLangOpts(FormatStyle.Standard)); -  tooling::Replacements Replaces = reformat(FormatStyle, Lex, Sources, Ranges); +  tooling::Replacements Replaces = reformat(FormatStyle, Sources, ID, Ranges);    if (OutputXML) {      llvm::outs()          << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n"; +    if (Cursor.getNumOccurrences() != 0) +      llvm::outs() << "<cursor>" +                   << tooling::shiftedCodePosition(Replaces, Cursor) +                   << "</cursor>\n";      for (tooling::Replacements::const_iterator I = Replaces.begin(),                                                 E = Replaces.end();           I != E; ++I) { diff --git a/tools/clang-format/Makefile b/tools/clang-format/Makefile index a26ef59822be..76e31cc1a072 100644 --- a/tools/clang-format/Makefile +++ b/tools/clang-format/Makefile @@ -16,9 +16,7 @@ TOOL_NO_EXPORTS = 1  include $(CLANG_LEVEL)/../../Makefile.config  LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option -USEDLIBS = clangFormat.a clangTooling.a clangFrontend.a clangSerialization.a \ -	   clangDriver.a clangParse.a clangSema.a clangAnalysis.a \ -           clangRewriteFrontend.a clangRewrite.a clangEdit.a clangAST.a \ +USEDLIBS = clangFormat.a clangToolingCore.a clangDriver.a clangRewrite.a \             clangLex.a clangBasic.a   include $(CLANG_LEVEL)/Makefile diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py index d6d0d44a06bb..23adb077c953 100755 --- a/tools/clang-format/clang-format-diff.py +++ b/tools/clang-format/clang-format-diff.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python  #  #===- clang-format-diff.py - ClangFormat Diff Reformatter ----*- python -*--===#  # @@ -49,9 +49,11 @@ def main():                        '(case sensitive, overrides -iregex)')    parser.add_argument('-iregex', metavar='PATTERN', default=                        r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc|js|proto' -                      r'|protodevel)', +                      r'|protodevel|java)',                        help='custom pattern selecting file paths to reformat '                        '(case insensitive, overridden by -regex)') +  parser.add_argument('-v', '--verbose', action='store_true', +                      help='be more verbose, ineffective without -i')    parser.add_argument(        '-style',        help= @@ -89,6 +91,8 @@ def main():    # Reformat files containing changes in place.    for filename, lines in lines_by_file.iteritems(): +    if args.i and args.verbose: +      print 'Formatting', filename      command = [binary, filename]      if args.i:        command.append('-i') diff --git a/tools/clang-format/clang-format.el b/tools/clang-format/clang-format.el index 520a3e250cf5..ab0991b2df1c 100644 --- a/tools/clang-format/clang-format.el +++ b/tools/clang-format/clang-format.el @@ -1,56 +1,167 @@ -;;; Clang-format emacs integration for use with C/Objective-C/C++. +;;; clang-format.el --- Format code using clang-format -;; This defines a function clang-format-region that you can bind to a key. -;; A minimal .emacs would contain: +;; Keywords: tools, c +;; Package-Requires: ((cl-lib "0.3")) + +;;; Commentary: + +;; This package allows to filter code through clang-format to fix its formatting. +;; clang-format is a tool that formats C/C++/Obj-C code according to a set of +;; style options, see <http://clang.llvm.org/docs/ClangFormatStyleOptions.html>. +;; Note that clang-format 3.4 or newer is required. + +;; clang-format.el is available via MELPA and can be installed via  ;; -;;   (load "<path-to-clang>/tools/clang-format/clang-format.el") -;;   (global-set-key [C-M-tab] 'clang-format-region) +;;   M-x package-install clang-format +;; +;; when ("melpa" . "http://melpa.org/packages/") is included in +;; `package-archives'. Alternatively, ensure the directory of this +;; file is in your `load-path' and add +;; +;;   (require 'clang-format) +;; +;; to your .emacs configuration. + +;; You may also want to bind `clang-format-region' to a key:  ;; -;; Depending on your configuration and coding style, you might need to modify -;; 'style' in clang-format, below. +;;   (global-set-key [C-M-tab] 'clang-format-region) -(require 'json) +;;; Code: -;; *Location of the clang-format binary. If it is on your PATH, a full path name -;; need not be specified. -(defvar clang-format-binary "clang-format") +(require 'cl-lib) +(require 'xml) -(defun clang-format-region () -  "Use clang-format to format the currently active region." -  (interactive) -  (let ((beg (if mark-active -                 (region-beginning) -               (min (line-beginning-position) (1- (point-max))))) -        (end (if mark-active -                 (region-end) -               (line-end-position)))) -    (clang-format beg end))) - -(defun clang-format-buffer () -  "Use clang-format to format the current buffer." -  (interactive) -  (clang-format (point-min) (point-max))) - -(defun clang-format (begin end) -  "Use clang-format to format the code between BEGIN and END." -  (let* ((orig-windows (get-buffer-window-list (current-buffer))) -         (orig-window-starts (mapcar #'window-start orig-windows)) -         (orig-point (point)) -         (style "file")) +(defgroup clang-format nil +  "Format code using clang-format." +  :group 'tools) + +(defcustom clang-format-executable +  (or (executable-find "clang-format") +      "clang-format") +  "Location of the clang-format executable. + +A string containing the name or the full path of the executable." +  :group 'clang-format +  :type 'string +  :risky t) + +(defcustom clang-format-style "file" +  "Style argument to pass to clang-format. + +By default clang-format will load the style configuration from +a file named .clang-format located in one of the parent directories +of the buffer." +  :group 'clang-format +  :type 'string +  :safe #'stringp) +(make-variable-buffer-local 'clang-format-style) + +(defun clang-format--extract (xml-node) +  "Extract replacements and cursor information from XML-NODE." +  (unless (and (listp xml-node) (eq (xml-node-name xml-node) 'replacements)) +    (error "Expected <replacements> node")) +  (let ((nodes (xml-node-children xml-node)) +        replacements +        cursor) +    (dolist (node nodes) +      (when (listp node) +        (let* ((children (xml-node-children node)) +               (text (car children))) +          (cl-case (xml-node-name node) +            ('replacement +             (let* ((offset (xml-get-attribute-or-nil node 'offset)) +                    (length (xml-get-attribute-or-nil node 'length))) +               (when (or (null offset) (null length)) +                 (error "<replacement> node does not have offset and length attributes")) +               (when (cdr children) +                 (error "More than one child node in <replacement> node")) + +               (setq offset (1+ (string-to-number offset))) +               (setq length (string-to-number length)) +               (push (list offset length text) replacements))) +            ('cursor +             (setq cursor (1+ (string-to-number text)))))))) + +    ;; Sort by decreasing offset, length. +    (setq replacements (sort (delq nil replacements) +                             (lambda (a b) +                               (or (> (car a) (car b)) +                                   (and (= (car a) (car b)) +                                        (> (cadr a) (cadr b))))))) + +    (cons replacements cursor))) + +(defun clang-format--replace (offset length &optional text) +  (goto-char offset) +  (delete-char length) +  (when text +    (insert text))) + +;;;###autoload +(defun clang-format-region (start end &optional style) +  "Use clang-format to format the code between START and END according to STYLE. +If called interactively uses the region or the current statement if there +is no active region.  If no style is given uses `clang-format-style'." +  (interactive +   (if (use-region-p) +       (list (region-beginning) (region-end)) +     (list (point) (point)))) + +  (unless style +    (setq style clang-format-style)) + +  (let ((temp-buffer (generate-new-buffer " *clang-format-temp*")) +        (temp-file (make-temp-file "clang-format")))      (unwind-protect -        (call-process-region (point-min) (point-max) clang-format-binary -                             t (list t nil) nil -                             "-offset" (number-to-string (1- begin)) -                             "-length" (number-to-string (- end begin)) -                             "-cursor" (number-to-string (1- (point))) -                             "-assume-filename" (buffer-file-name) -                             "-style" style) -      (goto-char (point-min)) -      (let ((json-output (json-read-from-string -                           (buffer-substring-no-properties -                             (point-min) (line-beginning-position 2))))) -        (delete-region (point-min) (line-beginning-position 2)) -        (goto-char (1+ (cdr (assoc 'Cursor json-output)))) -        (dotimes (index (length orig-windows)) -          (set-window-start (nth index orig-windows) -                            (nth index orig-window-starts))))))) +        (let (status stderr operations) +          (setq status +                (call-process-region +                 (point-min) (point-max) clang-format-executable +                 nil `(,temp-buffer ,temp-file) nil + +                 "-output-replacements-xml" +                 "-assume-filename" (or (buffer-file-name) "") +                 "-style" style +                 "-offset" (number-to-string (1- start)) +                 "-length" (number-to-string (- end start)) +                 "-cursor" (number-to-string (1- (point))))) +          (setq stderr +                (with-temp-buffer +                  (insert-file-contents temp-file) +                  (when (> (point-max) (point-min)) +                    (insert ": ")) +                  (buffer-substring-no-properties +                   (point-min) (line-end-position)))) + +          (cond +           ((stringp status) +            (error "(clang-format killed by signal %s%s)" status stderr)) +           ((not (equal 0 status)) +            (error "(clang-format failed with code %d%s)" status stderr)) +           (t (message "(clang-format succeeded%s)" stderr))) + +          (with-current-buffer temp-buffer +            (setq operations (clang-format--extract (car (xml-parse-region))))) + +          (let ((replacements (car operations)) +                (cursor (cdr operations))) +            (save-excursion +              (mapc (lambda (rpl) +                      (apply #'clang-format--replace rpl)) +                    replacements)) +            (when cursor +              (goto-char cursor)))) +      (delete-file temp-file) +      (when (buffer-name temp-buffer) (kill-buffer temp-buffer))))) + +;;;###autoload +(defun clang-format-buffer (&optional style) +  "Use clang-format to format the current buffer according to STYLE." +  (interactive) +  (clang-format-region (point-min) (point-max) style)) + +;;;###autoload +(defalias 'clang-format 'clang-format-region) + +(provide 'clang-format) +;;; clang-format.el ends here diff --git a/tools/clang-format/clang-format.py b/tools/clang-format/clang-format.py index 16a187910832..a79205a6dfe8 100644 --- a/tools/clang-format/clang-format.py +++ b/tools/clang-format/clang-format.py @@ -2,8 +2,8 @@  # - Change 'binary' if clang-format is not on the path (see below).  # - Add to your .vimrc:  # -#   map <C-I> :pyf <path-to-this-file>/clang-format.py<CR> -#   imap <C-I> <ESC>:pyf <path-to-this-file>/clang-format.py<CR>i +#   map <C-I> :pyf <path-to-this-file>/clang-format.py<cr> +#   imap <C-I> <c-o>:pyf <path-to-this-file>/clang-format.py<cr>  #  # The first line enables clang-format for NORMAL and VISUAL mode, the second  # line adds support for INSERT mode. Change "C-I" to another binding if you @@ -23,8 +23,11 @@ import subprocess  import sys  import vim +# set g:clang_format_path to the path to clang-format if it is not on the path  # Change this to the full path if clang-format is not on the path.  binary = 'clang-format' +if vim.eval('exists("g:clang_format_path")') == "1": +  binary = vim.eval('g:clang_format_path')  # Change this to format according to other formatting styles. See the output of  # 'clang-format --help' for a list of supported styles. The default looks for diff --git a/tools/clang-format/git-clang-format b/tools/clang-format/git-clang-format index c40b74dae4ba..6a0db27fa9f6 100755 --- a/tools/clang-format/git-clang-format +++ b/tools/clang-format/git-clang-format @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python  #  #===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===#  # diff --git a/tools/diagtool/DiagTool.cpp b/tools/diagtool/DiagTool.cpp index 44bc83e5455f..0e4d8088c6c2 100644 --- a/tools/diagtool/DiagTool.cpp +++ b/tools/diagtool/DiagTool.cpp @@ -36,7 +36,7 @@ DiagTool *DiagTools::getTool(llvm::StringRef toolCmd) {  }  void DiagTools::registerTool(DiagTool *tool) { -  getTools(tools)->GetOrCreateValue(tool->getName(), tool);   +  (*getTools(tools))[tool->getName()] = tool;  }  void DiagTools::printCommands(llvm::raw_ostream &out) { diff --git a/tools/diagtool/DiagTool.h b/tools/diagtool/DiagTool.h index b1e69f38c323..04b926df3b60 100644 --- a/tools/diagtool/DiagTool.h +++ b/tools/diagtool/DiagTool.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef DIAGTOOL_DIAGTOOL_H -#define DIAGTOOL_DIAGTOOL_H +#ifndef LLVM_CLANG_TOOLS_DIAGTOOL_DIAGTOOL_H +#define LLVM_CLANG_TOOLS_DIAGTOOL_DIAGTOOL_H  #include "llvm/ADT/StringRef.h"  #include "llvm/Support/ManagedStatic.h" diff --git a/tools/diagtool/DiagnosticNames.h b/tools/diagtool/DiagnosticNames.h index 2571b1996918..ac1a09857952 100644 --- a/tools/diagtool/DiagnosticNames.h +++ b/tools/diagtool/DiagnosticNames.h @@ -7,6 +7,9 @@  //  //===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_TOOLS_DIAGTOOL_DIAGNOSTICNAMES_H +#define LLVM_CLANG_TOOLS_DIAGTOOL_DIAGNOSTICNAMES_H +  #include "llvm/ADT/ArrayRef.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/Support/DataTypes.h" @@ -112,3 +115,4 @@ namespace diagtool {    }  } // end namespace diagtool +#endif diff --git a/tools/diagtool/ListWarnings.cpp b/tools/diagtool/ListWarnings.cpp index 16837a158495..3e6e88306e24 100644 --- a/tools/diagtool/ListWarnings.cpp +++ b/tools/diagtool/ListWarnings.cpp @@ -73,7 +73,7 @@ int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {        Unflagged.push_back(entry);      else {        Flagged.push_back(entry); -      flagHistogram.GetOrCreateValue(entry.Flag).getValue().push_back(diagID); +      flagHistogram[entry.Flag].push_back(diagID);      }    } @@ -97,11 +97,10 @@ int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {    double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size();    out << "  Average number of diagnostics per flag: "        << llvm::format("%.4g", avgDiagsPerFlag) << '\n'; -     +    out << "  Number in -Wpedantic (not covered by other -W flags): " -      << flagHistogram.GetOrCreateValue("pedantic").getValue().size() -      << '\n'; -   +      << flagHistogram["pedantic"].size() << '\n'; +    out << '\n';    return 0; diff --git a/tools/diagtool/ShowEnabledWarnings.cpp b/tools/diagtool/ShowEnabledWarnings.cpp index 903d1f16f992..06f74320b7fc 100644 --- a/tools/diagtool/ShowEnabledWarnings.cpp +++ b/tools/diagtool/ShowEnabledWarnings.cpp @@ -65,7 +65,7 @@ createDiagnostics(unsigned int argc, char **argv) {    // Try to build a CompilerInvocation.    std::unique_ptr<CompilerInvocation> Invocation( -      createInvocationFromCommandLine(ArrayRef<const char *>(argv, argc), +      createInvocationFromCommandLine(llvm::makeArrayRef(argv, argc),                                        InterimDiags));    if (!Invocation)      return nullptr; diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 990c4fc3c84e..fa1a10e96356 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -63,8 +63,7 @@ void initializePollyPasses(llvm::PassRegistry &Registry);  }  #endif -int cc1_main(const char **ArgBegin, const char **ArgEnd, -             const char *Argv0, void *MainAddr) { +int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {    std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); @@ -84,9 +83,8 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,    IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();    TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;    DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); -  bool Success; -  Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(), -                                               ArgBegin, ArgEnd, Diags); +  bool Success = CompilerInvocation::CreateFromArgs( +      Clang->getInvocation(), Argv.begin(), Argv.end(), Diags);    // Infer the builtin include path if unspecified.    if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && @@ -124,7 +122,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,    if (Clang->getFrontendOpts().DisableFree) {      if (llvm::AreStatisticsEnabled() || Clang->getFrontendOpts().ShowStats)        llvm::PrintStatistics(); -    BuryPointer(Clang.release()); +    BuryPointer(std::move(Clang));      return !Success;    } diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp index e41bc9f824e8..55c9fe602fa3 100644 --- a/tools/driver/cc1as_main.cpp +++ b/tools/driver/cc1as_main.cpp @@ -123,6 +123,7 @@ struct AssemblerInvocation {    unsigned RelaxAll : 1;    unsigned NoExecStack : 1; +  unsigned FatalWarnings : 1;    /// @} @@ -138,18 +139,19 @@ public:      ShowEncoding = 0;      RelaxAll = 0;      NoExecStack = 0; +    FatalWarnings = 0;      DwarfVersion = 3;    } -  static bool CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin, -                             const char **ArgEnd, DiagnosticsEngine &Diags); +  static bool CreateFromArgs(AssemblerInvocation &Res, +                             ArrayRef<const char *> Argv, +                             DiagnosticsEngine &Diags);  };  }  bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, -                                         const char **ArgBegin, -                                         const char **ArgEnd, +                                         ArrayRef<const char *> Argv,                                           DiagnosticsEngine &Diags) {    bool Success = true; @@ -159,7 +161,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,    const unsigned IncludedFlagsBitmask = options::CC1AsOption;    unsigned MissingArgIndex, MissingArgCount;    std::unique_ptr<InputArgList> Args( -      OptTbl->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount, +      OptTbl->ParseArgs(Argv.begin(), Argv.end(), MissingArgIndex, MissingArgCount,                          IncludedFlagsBitmask));    // Check for missing argument error. @@ -246,7 +248,8 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,    // Assemble Options    Opts.RelaxAll = Args->hasArg(OPT_mrelax_all); -  Opts.NoExecStack =  Args->hasArg(OPT_mno_exec_stack); +  Opts.NoExecStack = Args->hasArg(OPT_mno_exec_stack); +  Opts.FatalWarnings =  Args->hasArg(OPT_massembler_fatal_warnings);    return Success;  } @@ -262,13 +265,12 @@ static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,    if (Opts.OutputPath != "-")      sys::RemoveFileOnSignal(Opts.OutputPath); -  std::string Error; -  raw_fd_ostream *Out = -      new raw_fd_ostream(Opts.OutputPath.c_str(), Error, -                         (Binary ? sys::fs::F_None : sys::fs::F_Text)); -  if (!Error.empty()) { -    Diags.Report(diag::err_fe_unable_to_open_output) -      << Opts.OutputPath << Error; +  std::error_code EC; +  raw_fd_ostream *Out = new raw_fd_ostream( +      Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text)); +  if (EC) { +    Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath +                                                     << EC.message();      delete Out;      return nullptr;    } @@ -295,7 +297,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,    SourceMgr SrcMgr;    // Tell SrcMgr about this buffer, which is what the parser will pick up. -  SrcMgr.AddNewSourceBuffer(Buffer->release(), SMLoc()); +  SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());    // Record the location of the include directories so that the lexer can find    // it later. @@ -378,9 +380,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,      MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,                                                        Opts.CPU);      Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, -                                                CE, *STI, Opts.RelaxAll, -                                                Opts.NoExecStack)); -    Str.get()->InitSections(); +                                                CE, *STI, Opts.RelaxAll)); +    Str.get()->InitSections(Opts.NoExecStack);    }    bool Failed = false; @@ -420,11 +421,10 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,    exit(1);  } -int cc1as_main(const char **ArgBegin, const char **ArgEnd, -               const char *Argv0, void *MainAddr) { +int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {    // Print a stack trace if we signal out.    sys::PrintStackTraceOnErrorSignal(); -  PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin); +  PrettyStackTraceProgram X(Argv.size(), Argv.data());    llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.    // Initialize targets and assembly printers/parsers. @@ -447,7 +447,7 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd,    // Parse the arguments.    AssemblerInvocation Asm; -  if (!AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags)) +  if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))      return 1;    if (Asm.ShowHelp) { diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index 9f93837c2c75..e1f9367b0f5c 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -18,7 +18,9 @@  #include "clang/Driver/Driver.h"  #include "clang/Driver/DriverDiagnostic.h"  #include "clang/Driver/Options.h" +#include "clang/Frontend/ChainedDiagnosticConsumer.h"  #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/SerializedDiagnosticPrinter.h"  #include "clang/Frontend/TextDiagnosticPrinter.h"  #include "clang/Frontend/Utils.h"  #include "llvm/ADT/ArrayRef.h" @@ -61,8 +63,8 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {    return llvm::sys::fs::getMainExecutable(Argv0, P);  } -static const char *SaveStringInSet(std::set<std::string> &SavedStrings, -                                   StringRef S) { +static const char *GetStableCStr(std::set<std::string> &SavedStrings, +                                 StringRef S) {    return SavedStrings.insert(S).first->c_str();  } @@ -101,12 +103,12 @@ static void ApplyOneQAOverride(raw_ostream &OS,    if (Edit[0] == '^') {      const char *Str = -      SaveStringInSet(SavedStrings, Edit.substr(1)); +      GetStableCStr(SavedStrings, Edit.substr(1));      OS << "### Adding argument " << Str << " at beginning\n";      Args.insert(Args.begin() + 1, Str);    } else if (Edit[0] == '+') {      const char *Str = -      SaveStringInSet(SavedStrings, Edit.substr(1)); +      GetStableCStr(SavedStrings, Edit.substr(1));      OS << "### Adding argument " << Str << " at end\n";      Args.push_back(Str);    } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && @@ -116,11 +118,14 @@ static void ApplyOneQAOverride(raw_ostream &OS,      ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);      for (unsigned i = 1, e = Args.size(); i != e; ++i) { +      // Ignore end-of-line response file markers +      if (Args[i] == nullptr) +        continue;        std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);        if (Repl != Args[i]) {          OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; -        Args[i] = SaveStringInSet(SavedStrings, Repl); +        Args[i] = GetStableCStr(SavedStrings, Repl);        }      }    } else if (Edit[0] == 'x' || Edit[0] == 'X') { @@ -142,6 +147,9 @@ static void ApplyOneQAOverride(raw_ostream &OS,    } else if (Edit[0] == 'O') {      for (unsigned i = 1; i < Args.size();) {        const char *A = Args[i]; +      // Ignore end-of-line response file markers +      if (A == nullptr) +        continue;        if (A[0] == '-' && A[1] == 'O' &&            (A[2] == '\0' ||             (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || @@ -152,7 +160,7 @@ static void ApplyOneQAOverride(raw_ostream &OS,          ++i;      }      OS << "### Adding argument " << Edit << " at end\n"; -    Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str())); +    Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));    } else {      OS << "### Unrecognized edit: " << Edit << "\n";    } @@ -187,97 +195,98 @@ static void ApplyQAOverride(SmallVectorImpl<const char*> &Args,    }  } -extern int cc1_main(const char **ArgBegin, const char **ArgEnd, -                    const char *Argv0, void *MainAddr); -extern int cc1as_main(const char **ArgBegin, const char **ArgEnd, -                      const char *Argv0, void *MainAddr); +extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, +                    void *MainAddr); +extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, +                      void *MainAddr); + +struct DriverSuffix { +  const char *Suffix; +  const char *ModeFlag; +}; + +static const DriverSuffix *FindDriverSuffix(StringRef ProgName) { +  // A list of known driver suffixes. Suffixes are compared against the +  // program name in order. If there is a match, the frontend type if updated as +  // necessary by applying the ModeFlag. +  static const DriverSuffix DriverSuffixes[] = { +      {"clang", nullptr}, +      {"clang++", "--driver-mode=g++"}, +      {"clang-c++", "--driver-mode=g++"}, +      {"clang-cc", nullptr}, +      {"clang-cpp", "--driver-mode=cpp"}, +      {"clang-g++", "--driver-mode=g++"}, +      {"clang-gcc", nullptr}, +      {"clang-cl", "--driver-mode=cl"}, +      {"cc", nullptr}, +      {"cpp", "--driver-mode=cpp"}, +      {"cl", "--driver-mode=cl"}, +      {"++", "--driver-mode=g++"}, +  }; + +  for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) +    if (ProgName.endswith(DriverSuffixes[i].Suffix)) +      return &DriverSuffixes[i]; +  return nullptr; +}  static void ParseProgName(SmallVectorImpl<const char *> &ArgVector, -                          std::set<std::string> &SavedStrings, -                          Driver &TheDriver) -{ -  // Try to infer frontend type and default target from the program name. - -  // suffixes[] contains the list of known driver suffixes. -  // Suffixes are compared against the program name in order. -  // If there is a match, the frontend type is updated as necessary (CPP/C++). -  // If there is no match, a second round is done after stripping the last -  // hyphen and everything following it. This allows using something like -  // "clang++-2.9". - -  // If there is a match in either the first or second round, -  // the function tries to identify a target as prefix. E.g. -  // "x86_64-linux-clang" as interpreted as suffix "clang" with -  // target prefix "x86_64-linux". If such a target prefix is found, -  // is gets added via -target as implicit first argument. -  static const struct { -    const char *Suffix; -    const char *ModeFlag; -  } suffixes [] = { -    { "clang",     nullptr }, -    { "clang++",   "--driver-mode=g++" }, -    { "clang-c++", "--driver-mode=g++" }, -    { "clang-cc",  nullptr }, -    { "clang-cpp", "--driver-mode=cpp" }, -    { "clang-g++", "--driver-mode=g++" }, -    { "clang-gcc", nullptr }, -    { "clang-cl",  "--driver-mode=cl"  }, -    { "cc",        nullptr }, -    { "cpp",       "--driver-mode=cpp" }, -    { "cl" ,       "--driver-mode=cl"  }, -    { "++",        "--driver-mode=g++" }, -  }; -  std::string ProgName(llvm::sys::path::stem(ArgVector[0])); +                          std::set<std::string> &SavedStrings) { +  // Try to infer frontend type and default target from the program name by +  // comparing it against DriverSuffixes in order. + +  // If there is a match, the function tries to identify a target as prefix. +  // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target +  // prefix "x86_64-linux". If such a target prefix is found, is gets added via +  // -target as implicit first argument. + +  std::string ProgName =llvm::sys::path::stem(ArgVector[0]);  #ifdef LLVM_ON_WIN32    // Transform to lowercase for case insensitive file systems. -  std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), -                 toLowercase); +  ProgName = StringRef(ProgName).lower();  #endif -  StringRef ProgNameRef(ProgName); -  StringRef Prefix; - -  for (int Components = 2; Components; --Components) { -    bool FoundMatch = false; -    size_t i; - -    for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { -      if (ProgNameRef.endswith(suffixes[i].Suffix)) { -        FoundMatch = true; -        SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); -        if (it != ArgVector.end()) -          ++it; -        if (suffixes[i].ModeFlag) -          ArgVector.insert(it, suffixes[i].ModeFlag); -        break; -      } -    } -    if (FoundMatch) { -      StringRef::size_type LastComponent = ProgNameRef.rfind('-', -        ProgNameRef.size() - strlen(suffixes[i].Suffix)); -      if (LastComponent != StringRef::npos) -        Prefix = ProgNameRef.slice(0, LastComponent); -      break; -    } +  StringRef ProgNameRef = ProgName; +  const DriverSuffix *DS = FindDriverSuffix(ProgNameRef); -    StringRef::size_type LastComponent = ProgNameRef.rfind('-'); -    if (LastComponent == StringRef::npos) -      break; -    ProgNameRef = ProgNameRef.slice(0, LastComponent); +  if (!DS) { +    // Try again after stripping any trailing version number: +    // clang++3.5 -> clang++ +    ProgNameRef = ProgNameRef.rtrim("0123456789."); +    DS = FindDriverSuffix(ProgNameRef);    } -  if (Prefix.empty()) -    return; - -  std::string IgnoredError; -  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { -    SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); -    if (it != ArgVector.end()) -      ++it; -    const char* Strings[] = -      { SaveStringInSet(SavedStrings, std::string("-target")), -        SaveStringInSet(SavedStrings, Prefix) }; -    ArgVector.insert(it, Strings, Strings + llvm::array_lengthof(Strings)); +  if (!DS) { +    // Try again after stripping trailing -component. +    // clang++-tot -> clang++ +    ProgNameRef = ProgNameRef.slice(0, ProgNameRef.rfind('-')); +    DS = FindDriverSuffix(ProgNameRef); +  } + +  if (DS) { +    if (const char *Flag = DS->ModeFlag) { +      // Add Flag to the arguments. +      auto it = ArgVector.begin(); +      if (it != ArgVector.end()) +        ++it; +      ArgVector.insert(it, Flag); +    } + +    StringRef::size_type LastComponent = ProgNameRef.rfind( +        '-', ProgNameRef.size() - strlen(DS->Suffix)); +    if (LastComponent == StringRef::npos) +      return; + +    // Infer target from the prefix. +    StringRef Prefix = ProgNameRef.slice(0, LastComponent); +    std::string IgnoredError; +    if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { +      auto it = ArgVector.begin(); +      if (it != ArgVector.end()) +        ++it; +      const char *arr[] = { "-target", GetStableCStr(SavedStrings, Prefix) }; +      ArgVector.insert(it, std::begin(arr), std::end(arr)); +    }    }  } @@ -286,21 +295,97 @@ namespace {    public:      StringSetSaver(std::set<std::string> &Storage) : Storage(Storage) {}      const char *SaveString(const char *Str) override { -      return SaveStringInSet(Storage, Str); +      return GetStableCStr(Storage, Str);      }    private:      std::set<std::string> &Storage;    };  } +static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { +  // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. +  TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); +  if (TheDriver.CCPrintOptions) +    TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE"); + +  // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE. +  TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS"); +  if (TheDriver.CCPrintHeaders) +    TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE"); + +  // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE. +  TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); +  if (TheDriver.CCLogDiagnostics) +    TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE"); +} + +static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, +                                   const std::string &Path) { +  // If the clang binary happens to be named cl.exe for compatibility reasons, +  // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC. +  StringRef ExeBasename(llvm::sys::path::filename(Path)); +  if (ExeBasename.equals_lower("cl.exe")) +    ExeBasename = "clang-cl.exe"; +  DiagClient->setPrefix(ExeBasename); +} + +// This lets us create the DiagnosticsEngine with a properly-filled-out +// DiagnosticOptions instance. +static DiagnosticOptions * +CreateAndPopulateDiagOpts(SmallVectorImpl<const char *> &argv) { +  auto *DiagOpts = new DiagnosticOptions; +  std::unique_ptr<OptTable> Opts(createDriverOptTable()); +  unsigned MissingArgIndex, MissingArgCount; +  std::unique_ptr<InputArgList> Args(Opts->ParseArgs( +      argv.begin() + 1, argv.end(), MissingArgIndex, MissingArgCount)); +  // We ignore MissingArgCount and the return value of ParseDiagnosticArgs. +  // Any errors that would be diagnosed here will also be diagnosed later, +  // when the DiagnosticsEngine actually exists. +  (void) ParseDiagnosticArgs(*DiagOpts, *Args); +  return DiagOpts; +} + +static void SetInstallDir(SmallVectorImpl<const char *> &argv, +                          Driver &TheDriver) { +  // Attempt to find the original path used to invoke the driver, to determine +  // the installed path. We do this manually, because we want to support that +  // path being a symlink. +  SmallString<128> InstalledPath(argv[0]); + +  // Do a PATH lookup, if there are no directory components. +  if (llvm::sys::path::filename(InstalledPath) == InstalledPath) +    if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName( +            llvm::sys::path::filename(InstalledPath.str()))) +      InstalledPath = *Tmp; +  llvm::sys::fs::make_absolute(InstalledPath); +  InstalledPath = llvm::sys::path::parent_path(InstalledPath); +  if (llvm::sys::fs::exists(InstalledPath.c_str())) +    TheDriver.setInstalledDir(InstalledPath); +} + +static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) { +  void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; +  if (Tool == "") +    return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP); +  if (Tool == "as") +    return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP); + +  // Reject unknown tools. +  llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n"; +  return 1; +} +  int main(int argc_, const char **argv_) {    llvm::sys::PrintStackTraceOnErrorSignal();    llvm::PrettyStackTraceProgram X(argc_, argv_); +  if (llvm::sys::Process::FixupStandardFileDescriptors()) +    return 1; +    SmallVector<const char *, 256> argv;    llvm::SpecificBumpPtrAllocator<char> ArgAllocator;    std::error_code EC = llvm::sys::Process::GetArgumentVector( -      argv, ArrayRef<const char *>(argv_, argc_), ArgAllocator); +      argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);    if (EC) {      llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';      return 1; @@ -308,26 +393,33 @@ int main(int argc_, const char **argv_) {    std::set<std::string> SavedStrings;    StringSetSaver Saver(SavedStrings); -  llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, argv); - -  // Handle -cc1 integrated tools. -  if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) { -    StringRef Tool = argv[1] + 4; - -    if (Tool == "") -      return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0], -                      (void*) (intptr_t) GetExecutablePath); -    if (Tool == "as") -      return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0], -                      (void*) (intptr_t) GetExecutablePath); -    // Reject unknown tools. -    llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n"; -    return 1; +  // Determines whether we want nullptr markers in argv to indicate response +  // files end-of-lines. We only use this for the /LINK driver argument. +  bool MarkEOLs = true; +  if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) +    MarkEOLs = false; +  llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, argv, +                                MarkEOLs); + +  // Handle -cc1 integrated tools, even if -cc1 was expanded from a response +  // file. +  auto FirstArg = std::find_if(argv.begin() + 1, argv.end(), +                               [](const char *A) { return A != nullptr; }); +  if (FirstArg != argv.end() && StringRef(*FirstArg).startswith("-cc1")) { +    // If -cc1 came from a response file, remove the EOL sentinels. +    if (MarkEOLs) { +      auto newEnd = std::remove(argv.begin(), argv.end(), nullptr); +      argv.resize(newEnd - argv.begin()); +    } +    return ExecuteCC1Tool(argv, argv[1] + 4);    }    bool CanonicalPrefixes = true;    for (int i = 1, size = argv.size(); i < size; ++i) { +    // Skip end-of-line response file markers +    if (argv[i] == nullptr) +      continue;      if (StringRef(argv[i]) == "-no-canonical-prefixes") {        CanonicalPrefixes = false;        break; @@ -343,73 +435,34 @@ int main(int argc_, const char **argv_) {    std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes); -  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions; -  { -    std::unique_ptr<OptTable> Opts(createDriverOptTable()); -    unsigned MissingArgIndex, MissingArgCount; -    std::unique_ptr<InputArgList> Args(Opts->ParseArgs( -        argv.begin() + 1, argv.end(), MissingArgIndex, MissingArgCount)); -    // We ignore MissingArgCount and the return value of ParseDiagnosticArgs. -    // Any errors that would be diagnosed here will also be diagnosed later, -    // when the DiagnosticsEngine actually exists. -    (void) ParseDiagnosticArgs(*DiagOpts, *Args); -  } -  // Now we can create the DiagnosticsEngine with a properly-filled-out -  // DiagnosticOptions instance. +  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = +      CreateAndPopulateDiagOpts(argv); +    TextDiagnosticPrinter *DiagClient      = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); - -  // If the clang binary happens to be named cl.exe for compatibility reasons, -  // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC. -  StringRef ExeBasename(llvm::sys::path::filename(Path)); -  if (ExeBasename.equals_lower("cl.exe")) -    ExeBasename = "clang-cl.exe"; -  DiagClient->setPrefix(ExeBasename); +  FixupDiagPrefixExeName(DiagClient, Path);    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());    DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); -  ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); - -  Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); -  // Attempt to find the original path used to invoke the driver, to determine -  // the installed path. We do this manually, because we want to support that -  // path being a symlink. -  { -    SmallString<128> InstalledPath(argv[0]); - -    // Do a PATH lookup, if there are no directory components. -    if (llvm::sys::path::filename(InstalledPath) == InstalledPath) { -      std::string Tmp = llvm::sys::FindProgramByName( -        llvm::sys::path::filename(InstalledPath.str())); -      if (!Tmp.empty()) -        InstalledPath = Tmp; -    } -    llvm::sys::fs::make_absolute(InstalledPath); -    InstalledPath = llvm::sys::path::parent_path(InstalledPath); -    bool exists; -    if (!llvm::sys::fs::exists(InstalledPath.str(), exists) && exists) -      TheDriver.setInstalledDir(InstalledPath); +  if (!DiagOpts->DiagnosticSerializationFile.empty()) { +    auto SerializedConsumer = +        clang::serialized_diags::create(DiagOpts->DiagnosticSerializationFile, +                                        &*DiagOpts, /*MergeChildRecords=*/true); +    Diags.setClient(new ChainedDiagnosticConsumer( +        Diags.takeClient(), std::move(SerializedConsumer)));    } -  llvm::InitializeAllTargets(); -  ParseProgName(argv, SavedStrings, TheDriver); +  ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); -  // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. -  TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); -  if (TheDriver.CCPrintOptions) -    TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE"); +  Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); +  SetInstallDir(argv, TheDriver); -  // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE. -  TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS"); -  if (TheDriver.CCPrintHeaders) -    TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE"); +  llvm::InitializeAllTargets(); +  ParseProgName(argv, SavedStrings); -  // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE. -  TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); -  if (TheDriver.CCLogDiagnostics) -    TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE"); +  SetBackdoorDriverOutputsFromEnvVars(TheDriver);    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));    int Res = 0; @@ -420,14 +473,17 @@ int main(int argc_, const char **argv_) {    // Force a crash to test the diagnostics.    if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) {      Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH"; -    const Command *FailingCommand = nullptr; -    FailingCommands.push_back(std::make_pair(-1, FailingCommand)); + +    // Pretend that every command failed. +    FailingCommands.clear(); +    for (const auto &J : C->getJobs()) +      if (const Command *C = dyn_cast<Command>(&J)) +        FailingCommands.push_back(std::make_pair(-1, C));    } -  for (SmallVectorImpl< std::pair<int, const Command *> >::iterator it = -         FailingCommands.begin(), ie = FailingCommands.end(); it != ie; ++it) { -    int CommandRes = it->first; -    const Command *FailingCommand = it->second; +  for (const auto &P : FailingCommands) { +    int CommandRes = P.first; +    const Command *FailingCommand = P.second;      if (!Res)        Res = CommandRes; @@ -440,15 +496,17 @@ int main(int argc_, const char **argv_) {      DiagnoseCrash |= CommandRes == 3;  #endif      if (DiagnoseCrash) { -      TheDriver.generateCompilationDiagnostics(*C, FailingCommand); +      TheDriver.generateCompilationDiagnostics(*C, *FailingCommand);        break;      }    } +  Diags.getClient()->finish(); +    // If any timers were active but haven't been destroyed yet, print their    // results now.  This happens in -disable-free mode.    llvm::TimerGroup::printAll(llvm::errs()); -   +    llvm::llvm_shutdown();  #ifdef LLVM_ON_WIN32 diff --git a/tools/libclang/ARCMigrate.cpp b/tools/libclang/ARCMigrate.cpp index 375c5f40c21b..b0b869ba900b 100644 --- a/tools/libclang/ARCMigrate.cpp +++ b/tools/libclang/ARCMigrate.cpp @@ -47,9 +47,7 @@ CXRemapping clang_getRemappings(const char *migrate_dir_path) {      return nullptr;    } -  bool exists = false; -  llvm::sys::fs::exists(migrate_dir_path, exists); -  if (!exists) { +  if (!llvm::sys::fs::exists(migrate_dir_path)) {      if (Logging) {        llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path                     << "\")\n"; diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index fc8703aface1..00ef8c0bf424 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -22,10 +22,12 @@  #include "CXType.h"  #include "CursorVisitor.h"  #include "clang/AST/Attr.h" +#include "clang/AST/Mangle.h"  #include "clang/AST/StmtVisitor.h"  #include "clang/Basic/Diagnostic.h"  #include "clang/Basic/DiagnosticCategories.h"  #include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/TargetInfo.h"  #include "clang/Basic/Version.h"  #include "clang/Frontend/ASTUnit.h"  #include "clang/Frontend/CompilerInstance.h" @@ -40,6 +42,8 @@  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/StringSwitch.h"  #include "llvm/Config/llvm-config.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/CrashRecoveryContext.h"  #include "llvm/Support/Format.h" @@ -1256,6 +1260,7 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,    case NestedNameSpecifier::TypeSpecWithTemplate:    case NestedNameSpecifier::Global:    case NestedNameSpecifier::Identifier: +  case NestedNameSpecifier::Super:      break;          } @@ -1297,6 +1302,7 @@ CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {      case NestedNameSpecifier::Global:      case NestedNameSpecifier::Identifier: +    case NestedNameSpecifier::Super:        break;                    }    } @@ -1828,6 +1834,7 @@ public:    void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *E);    void VisitCXXUuidofExpr(const CXXUuidofExpr *E);    void VisitCXXCatchStmt(const CXXCatchStmt *S); +  void VisitCXXForRangeStmt(const CXXForRangeStmt *S);    void VisitDeclRefExpr(const DeclRefExpr *D);    void VisitDeclStmt(const DeclStmt *S);    void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E); @@ -1856,21 +1863,28 @@ public:    void VisitOpaqueValueExpr(const OpaqueValueExpr *E);    void VisitLambdaExpr(const LambdaExpr *E);    void VisitOMPExecutableDirective(const OMPExecutableDirective *D); +  void VisitOMPLoopDirective(const OMPLoopDirective *D);    void VisitOMPParallelDirective(const OMPParallelDirective *D);    void VisitOMPSimdDirective(const OMPSimdDirective *D);    void VisitOMPForDirective(const OMPForDirective *D); +  void VisitOMPForSimdDirective(const OMPForSimdDirective *D);    void VisitOMPSectionsDirective(const OMPSectionsDirective *D);    void VisitOMPSectionDirective(const OMPSectionDirective *D);    void VisitOMPSingleDirective(const OMPSingleDirective *D);    void VisitOMPMasterDirective(const OMPMasterDirective *D);    void VisitOMPCriticalDirective(const OMPCriticalDirective *D);    void VisitOMPParallelForDirective(const OMPParallelForDirective *D); +  void VisitOMPParallelForSimdDirective(const OMPParallelForSimdDirective *D);    void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);    void VisitOMPTaskDirective(const OMPTaskDirective *D);    void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);    void VisitOMPBarrierDirective(const OMPBarrierDirective *D);    void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D);    void VisitOMPFlushDirective(const OMPFlushDirective *D); +  void VisitOMPOrderedDirective(const OMPOrderedDirective *D); +  void VisitOMPAtomicDirective(const OMPAtomicDirective *D); +  void VisitOMPTargetDirective(const OMPTargetDirective *D); +  void VisitOMPTeamsDirective(const OMPTeamsDirective *D);  private:    void AddDeclarationNameInfo(const Stmt *S); @@ -1979,14 +1993,28 @@ void OMPClauseEnqueue::VisitOMPUntiedClause(const OMPUntiedClause *) {}  void OMPClauseEnqueue::VisitOMPMergeableClause(const OMPMergeableClause *) {} +void OMPClauseEnqueue::VisitOMPReadClause(const OMPReadClause *) {} + +void OMPClauseEnqueue::VisitOMPWriteClause(const OMPWriteClause *) {} + +void OMPClauseEnqueue::VisitOMPUpdateClause(const OMPUpdateClause *) {} + +void OMPClauseEnqueue::VisitOMPCaptureClause(const OMPCaptureClause *) {} + +void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {} +  template<typename T>  void OMPClauseEnqueue::VisitOMPClauseList(T *Node) { -  for (const auto *I : Node->varlists()) +  for (const auto *I : Node->varlists()) {      Visitor->AddStmt(I); +  }  }  void OMPClauseEnqueue::VisitOMPPrivateClause(const OMPPrivateClause *C) {    VisitOMPClauseList(C); +  for (const auto *E : C->private_copies()) { +    Visitor->AddStmt(E); +  }  }  void OMPClauseEnqueue::VisitOMPFirstprivateClause(                                          const OMPFirstprivateClause *C) { @@ -2127,6 +2155,12 @@ void EnqueueVisitor::VisitCXXCatchStmt(const CXXCatchStmt *S) {    AddDecl(S->getExceptionDecl());  } +void EnqueueVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt *S) { +  AddStmt(S->getBody()); +  AddStmt(S->getRangeInit()); +  AddDecl(S->getLoopVariable()); +} +  void EnqueueVisitor::VisitDeclRefExpr(const DeclRefExpr *DR) {    if (DR->hasExplicitTemplateArgs()) {      AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs()); @@ -2309,16 +2343,24 @@ void EnqueueVisitor::VisitOMPExecutableDirective(      EnqueueChildren(*I);  } +void EnqueueVisitor::VisitOMPLoopDirective(const OMPLoopDirective *D) { +  VisitOMPExecutableDirective(D); +} +  void EnqueueVisitor::VisitOMPParallelDirective(const OMPParallelDirective *D) {    VisitOMPExecutableDirective(D);  }  void EnqueueVisitor::VisitOMPSimdDirective(const OMPSimdDirective *D) { -  VisitOMPExecutableDirective(D); +  VisitOMPLoopDirective(D);  }  void EnqueueVisitor::VisitOMPForDirective(const OMPForDirective *D) { -  VisitOMPExecutableDirective(D); +  VisitOMPLoopDirective(D); +} + +void EnqueueVisitor::VisitOMPForSimdDirective(const OMPForSimdDirective *D) { +  VisitOMPLoopDirective(D);  }  void EnqueueVisitor::VisitOMPSectionsDirective(const OMPSectionsDirective *D) { @@ -2344,7 +2386,12 @@ void EnqueueVisitor::VisitOMPCriticalDirective(const OMPCriticalDirective *D) {  void  EnqueueVisitor::VisitOMPParallelForDirective(const OMPParallelForDirective *D) { -  VisitOMPExecutableDirective(D); +  VisitOMPLoopDirective(D); +} + +void EnqueueVisitor::VisitOMPParallelForSimdDirective( +    const OMPParallelForSimdDirective *D) { +  VisitOMPLoopDirective(D);  }  void EnqueueVisitor::VisitOMPParallelSectionsDirective( @@ -2373,6 +2420,22 @@ void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) {    VisitOMPExecutableDirective(D);  } +void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) { +  VisitOMPExecutableDirective(D); +} + +void EnqueueVisitor::VisitOMPAtomicDirective(const OMPAtomicDirective *D) { +  VisitOMPExecutableDirective(D); +} + +void EnqueueVisitor::VisitOMPTargetDirective(const OMPTargetDirective *D) { +  VisitOMPExecutableDirective(D); +} + +void EnqueueVisitor::VisitOMPTeamsDirective(const OMPTeamsDirective *D) { +  VisitOMPExecutableDirective(D); +} +  void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {    EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);  } @@ -2755,13 +2818,14 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,    CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);    FileSystemOptions FileSystemOpts; -  IntrusiveRefCntPtr<DiagnosticsEngine> Diags; -  ASTUnit *AU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts, -                                         CXXIdx->getOnlyLocalDecls(), None, -                                         /*CaptureDiagnostics=*/true, -                                         /*AllowPCHWithCompilerErrors=*/true, -                                         /*UserFilesAreVolatile=*/true); -  *out_TU = MakeCXTranslationUnit(CXXIdx, AU); +  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = +      CompilerInstance::createDiagnostics(new DiagnosticOptions()); +  std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile( +      ast_filename, Diags, FileSystemOpts, CXXIdx->getOnlyLocalDecls(), None, +      /*CaptureDiagnostics=*/true, +      /*AllowPCHWithCompilerErrors=*/true, +      /*UserFilesAreVolatile=*/true); +  *out_TU = MakeCXTranslationUnit(CXXIdx, AU.release());    return *out_TU ? CXError_Success : CXError_Failure;  } @@ -2847,9 +2911,9 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {      std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());    for (auto &UF : PTUI->unsaved_files) { -    llvm::MemoryBuffer *MB = +    std::unique_ptr<llvm::MemoryBuffer> MB =          llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); -    RemappedFiles->push_back(std::make_pair(UF.Filename, MB)); +    RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));    }    std::unique_ptr<std::vector<const char *>> Args( @@ -3131,9 +3195,9 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) {      std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());    for (auto &UF : RTUI->unsaved_files) { -    llvm::MemoryBuffer *MB = +    std::unique_ptr<llvm::MemoryBuffer> MB =          llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); -    RemappedFiles->push_back(std::make_pair(UF.Filename, MB)); +    RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));    }    if (!CXXUnit->Reparse(*RemappedFiles.get())) @@ -3259,6 +3323,18 @@ int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID) {    return 0;  } +int clang_File_isEqual(CXFile file1, CXFile file2) { +  if (file1 == file2) +    return true; + +  if (!file1 || !file2) +    return false; + +  FileEntry *FEnt1 = static_cast<FileEntry *>(file1); +  FileEntry *FEnt2 = static_cast<FileEntry *>(file2); +  return FEnt1->getUniqueID() == FEnt2->getUniqueID(); +} +  } // end: extern "C"  //===----------------------------------------------------------------------===// @@ -3628,6 +3704,18 @@ CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C,      return clang_getNullRange();    } +  if (C.kind == CXCursor_CXXMethod || C.kind == CXCursor_Destructor || +      C.kind == CXCursor_ConversionFunction) { +    if (pieceIndex > 0) +      return clang_getNullRange(); +    if (const FunctionDecl *FD = +            dyn_cast_or_null<FunctionDecl>(getCursorDecl(C))) { +      DeclarationNameInfo FunctionName = FD->getNameInfo(); +      return cxloc::translateSourceRange(Ctx, FunctionName.getSourceRange()); +    } +    return clang_getNullRange(); +  } +    // FIXME: A CXCursor_InclusionDirective should give the location of the    // filename, but we don't keep track of this. @@ -3647,6 +3735,37 @@ CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C,    return cxloc::translateSourceRange(Ctx, Loc);  } +CXString clang_Cursor_getMangling(CXCursor C) { +  if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind)) +    return cxstring::createEmpty(); + +  // Mangling only works for functions and variables. +  const Decl *D = getCursorDecl(C); +  if (!D || !(isa<FunctionDecl>(D) || isa<VarDecl>(D))) +    return cxstring::createEmpty(); + +  // First apply frontend mangling. +  const NamedDecl *ND = cast<NamedDecl>(D); +  ASTContext &Ctx = ND->getASTContext(); +  std::unique_ptr<MangleContext> MC(Ctx.createMangleContext()); + +  std::string FrontendBuf; +  llvm::raw_string_ostream FrontendBufOS(FrontendBuf); +  MC->mangleName(ND, FrontendBufOS); + +  // Now apply backend mangling. +  std::unique_ptr<llvm::DataLayout> DL( +      new llvm::DataLayout(Ctx.getTargetInfo().getTargetDescription())); +  llvm::Mangler BackendMangler(DL.get()); + +  std::string FinalBuf; +  llvm::raw_string_ostream FinalBufOS(FinalBuf); +  BackendMangler.getNameWithPrefix(FinalBufOS, +                                   llvm::Twine(FrontendBufOS.str())); + +  return cxstring::createDup(FinalBufOS.str()); +} +  CXString clang_getCursorDisplayName(CXCursor C) {    if (!clang_isDeclaration(C.kind))      return clang_getCursorSpelling(C); @@ -3997,6 +4116,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {      return cxstring::createRef("attribute(global)");    case CXCursor_CUDAHostAttr:      return cxstring::createRef("attribute(host)"); +  case CXCursor_CUDASharedAttr: +    return cxstring::createRef("attribute(shared)");    case CXCursor_PreprocessingDirective:      return cxstring::createRef("preprocessing directive");    case CXCursor_MacroDefinition: @@ -4051,6 +4172,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {      return cxstring::createRef("OMPSimdDirective");    case CXCursor_OMPForDirective:      return cxstring::createRef("OMPForDirective"); +  case CXCursor_OMPForSimdDirective: +    return cxstring::createRef("OMPForSimdDirective");    case CXCursor_OMPSectionsDirective:      return cxstring::createRef("OMPSectionsDirective");    case CXCursor_OMPSectionDirective: @@ -4063,6 +4186,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {      return cxstring::createRef("OMPCriticalDirective");    case CXCursor_OMPParallelForDirective:      return cxstring::createRef("OMPParallelForDirective"); +  case CXCursor_OMPParallelForSimdDirective: +    return cxstring::createRef("OMPParallelForSimdDirective");    case CXCursor_OMPParallelSectionsDirective:      return cxstring::createRef("OMPParallelSectionsDirective");    case CXCursor_OMPTaskDirective: @@ -4075,6 +4200,14 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {      return cxstring::createRef("OMPTaskwaitDirective");    case CXCursor_OMPFlushDirective:      return cxstring::createRef("OMPFlushDirective"); +  case CXCursor_OMPOrderedDirective: +    return cxstring::createRef("OMPOrderedDirective"); +  case CXCursor_OMPAtomicDirective: +    return cxstring::createRef("OMPAtomicDirective"); +  case CXCursor_OMPTargetDirective: +    return cxstring::createRef("OMPTargetDirective"); +  case CXCursor_OMPTeamsDirective: +    return cxstring::createRef("OMPTeamsDirective");    }    llvm_unreachable("Unhandled CXCursorKind"); @@ -6296,6 +6429,40 @@ static const Decl *maybeGetTemplateCursor(const Decl *D) {    return D;  } + +enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor C) { +  StorageClass sc = SC_None; +  const Decl *D = getCursorDecl(C); +  if (D) { +    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +      sc = FD->getStorageClass(); +    } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { +      sc = VD->getStorageClass(); +    } else { +      return CX_SC_Invalid; +    } +  } else { +    return CX_SC_Invalid; +  } +  switch (sc) { +  case SC_None: +    return CX_SC_None; +  case SC_Extern: +    return CX_SC_Extern; +  case SC_Static: +    return CX_SC_Static; +  case SC_PrivateExtern: +    return CX_SC_PrivateExtern; +  case SC_OpenCLWorkGroupLocal: +    return CX_SC_OpenCLWorkGroupLocal; +  case SC_Auto: +    return CX_SC_Auto; +  case SC_Register: +    return CX_SC_Register; +  } +  llvm_unreachable("Unhandled storage class!"); +} +  CXCursor clang_getCursorSemanticParent(CXCursor cursor) {    if (clang_isDeclaration(cursor.kind)) {      if (const Decl *D = getCursorDecl(cursor)) { @@ -6490,11 +6657,7 @@ CXModule clang_getModuleForFile(CXTranslationUnit TU, CXFile File) {    HeaderSearch &HS = Unit.getPreprocessor().getHeaderSearchInfo();    ModuleMap::KnownHeader Header = HS.findModuleForHeader(FE); -  if (Module *Mod = Header.getModule()) { -    if (Header.getRole() != ModuleMap::ExcludedHeader) -      return Mod; -  } -  return nullptr; +  return Header.getModule();  }  CXFile clang_Module_getASTFile(CXModule CXMod) { diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index 0d88003a1f6c..b6f71d20de2b 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -692,9 +692,9 @@ void clang_codeCompleteAt_Impl(void *UserData) {    SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;    for (auto &UF : CCAI->unsaved_files) { -    llvm::MemoryBuffer *MB = +    std::unique_ptr<llvm::MemoryBuffer> MB =          llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); -    RemappedFiles.push_back(std::make_pair(UF.Filename, MB)); +    RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));    }    if (EnableLogging) { diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp index 0d97ebd9335b..4d646f0cf828 100644 --- a/tools/libclang/CIndexDiagnostic.cpp +++ b/tools/libclang/CIndexDiagnostic.cpp @@ -30,13 +30,11 @@ using namespace clang::cxloc;  using namespace clang::cxdiag;  using namespace llvm; +CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {} -CXDiagnosticSetImpl::~CXDiagnosticSetImpl() { -  for (std::vector<CXDiagnosticImpl *>::iterator it = Diagnostics.begin(), -       et = Diagnostics.end(); -       it != et; ++it) { -    delete *it; -  } +void +CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) { +  Diagnostics.push_back(std::move(D));  }  CXDiagnosticImpl::~CXDiagnosticImpl() {} @@ -105,12 +103,13 @@ public:      if (Level != DiagnosticsEngine::Note)        CurrentSet = MainSet; -     -    CXStoredDiagnostic *CD = new CXStoredDiagnostic(*SD, LangOpts); -    CurrentSet->appendDiagnostic(CD); -     + +    auto Owner = llvm::make_unique<CXStoredDiagnostic>(*SD, LangOpts); +    CXStoredDiagnostic &CD = *Owner; +    CurrentSet->appendDiagnostic(std::move(Owner)); +      if (Level != DiagnosticsEngine::Note) -      CurrentSet = &CD->getChildDiagnostics(); +      CurrentSet = &CD.getChildDiagnostics();    }    void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, @@ -127,8 +126,8 @@ public:        L = translateSourceLocation(*SM, LangOpts, Loc);      else        L = clang_getNullLocation(); -    CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L); -    CurrentSet->appendDiagnostic(CD); +    CurrentSet->appendDiagnostic( +        llvm::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));    }    void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, @@ -149,8 +148,8 @@ public:        L = translateSourceLocation(*SM, LangOpts, Loc);      else        L = clang_getNullLocation(); -    CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message, -                                                                L)); +    CurrentSet->appendDiagnostic( +        llvm::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));    }    CXDiagnosticSetImpl *CurrentSet; diff --git a/tools/libclang/CIndexDiagnostic.h b/tools/libclang/CIndexDiagnostic.h index 31ae902eac4e..4347fb75f4a5 100644 --- a/tools/libclang/CIndexDiagnostic.h +++ b/tools/libclang/CIndexDiagnostic.h @@ -10,10 +10,11 @@  |* Implements the diagnostic functions of the Clang C interface.              *|  |*                                                                            *|  \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_CLANG_CINDEX_DIAGNOSTIC_H -#define LLVM_CLANG_CINDEX_DIAGNOSTIC_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CINDEXDIAGNOSTIC_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXDIAGNOSTIC_H  #include "clang-c/Index.h" +#include <memory>  #include <vector>  #include <assert.h> @@ -24,27 +25,25 @@ class StoredDiagnostic;  class CXDiagnosticImpl;  class CXDiagnosticSetImpl { -  std::vector<CXDiagnosticImpl *> Diagnostics; +  std::vector<std::unique_ptr<CXDiagnosticImpl>> Diagnostics;    const bool IsExternallyManaged;  public:    CXDiagnosticSetImpl(bool isManaged = false)      : IsExternallyManaged(isManaged) {}    virtual ~CXDiagnosticSetImpl(); -   +    size_t getNumDiagnostics() const {      return Diagnostics.size();    }    CXDiagnosticImpl *getDiagnostic(unsigned i) const {      assert(i < getNumDiagnostics()); -    return Diagnostics[i]; +    return Diagnostics[i].get();    } -   -  void appendDiagnostic(CXDiagnosticImpl *D) { -    Diagnostics.push_back(D); -  } -   + +  void appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D); +    bool empty() const {      return Diagnostics.empty();    } @@ -99,9 +98,9 @@ public:  protected:    CXDiagnosticImpl(Kind k) : K(k) {}    CXDiagnosticSetImpl ChildDiags; -   -  void append(CXDiagnosticImpl *D) { -    ChildDiags.appendDiagnostic(D); + +  void append(std::unique_ptr<CXDiagnosticImpl> D) { +    ChildDiags.appendDiagnostic(std::move(D));    }  private: @@ -163,4 +162,4 @@ CXDiagnosticSetImpl *lazyCreateDiags(CXTranslationUnit TU,  } // end namespace clang -#endif // LLVM_CLANG_CINDEX_DIAGNOSTIC_H +#endif diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index 25881c3ef062..d7b65852844e 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -15,9 +15,9 @@  #include "CXCursor.h"  #include "CXString.h"  #include "CXTranslationUnit.h" +#include "clang/Frontend/ASTUnit.h"  #include "clang/Index/USRGeneration.h"  #include "clang/Lex/PreprocessingRecord.h" -#include "clang/Frontend/ASTUnit.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/Support/raw_ostream.h" diff --git a/tools/libclang/CIndexer.h b/tools/libclang/CIndexer.h index 95d8115a2eee..7a8dbd37d022 100644 --- a/tools/libclang/CIndexer.h +++ b/tools/libclang/CIndexer.h @@ -12,8 +12,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CINDEXER_H -#define LLVM_CLANG_CINDEXER_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CINDEXER_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXER_H  #include "clang-c/Index.h"  #include "llvm/ADT/StringRef.h" diff --git a/tools/libclang/CLog.h b/tools/libclang/CLog.h index e7419b71f83f..b9309ed19239 100644 --- a/tools/libclang/CLog.h +++ b/tools/libclang/CLog.h @@ -7,8 +7,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBCLANG_CLOG_H -#define LLVM_LIBCLANG_CLOG_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CLOG_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CLOG_H  #include "clang-c/Index.h"  #include "clang/Basic/LLVM.h" diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt index e7ab63f7b99d..f1c3f4ca8b23 100644 --- a/tools/libclang/CMakeLists.txt +++ b/tools/libclang/CMakeLists.txt @@ -86,7 +86,7 @@ add_clang_library(libclang ${ENABLE_SHARED} ${ENABLE_STATIC}    ${LIBS}    LINK_COMPONENTS -  BitReader +  Core    Support    ) diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp index 454703149c9d..9cc05ed4e127 100644 --- a/tools/libclang/CXComment.cpp +++ b/tools/libclang/CXComment.cpp @@ -12,10 +12,10 @@  //===----------------------------------------------------------------------===//  #include "clang-c/Index.h" -#include "clang-c/Documentation.h"  #include "CXComment.h"  #include "CXCursor.h"  #include "CXString.h" +#include "clang-c/Documentation.h"  #include "clang/AST/Decl.h"  #include "clang/Index/CommentToXML.h"  #include "llvm/ADT/StringExtras.h" diff --git a/tools/libclang/CXComment.h b/tools/libclang/CXComment.h index d9d2bdef4127..a937a8034636 100644 --- a/tools/libclang/CXComment.h +++ b/tools/libclang/CXComment.h @@ -11,12 +11,12 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CXCOMMENT_H -#define LLVM_CLANG_CXCOMMENT_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXCOMMENT_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXCOMMENT_H  #include "CXTranslationUnit.h" -#include "clang-c/Index.h"  #include "clang-c/Documentation.h" +#include "clang-c/Index.h"  #include "clang/AST/ASTContext.h"  #include "clang/AST/Comment.h"  #include "clang/Frontend/ASTUnit.h" diff --git a/tools/libclang/CXCompilationDatabase.cpp b/tools/libclang/CXCompilationDatabase.cpp index 51677e721035..1e4a2cd44aab 100644 --- a/tools/libclang/CXCompilationDatabase.cpp +++ b/tools/libclang/CXCompilationDatabase.cpp @@ -16,8 +16,8 @@ clang_CompilationDatabase_fromDirectory(const char *BuildDir,    std::string ErrorMsg;    CXCompilationDatabase_Error Err = CXCompilationDatabase_NoError; -  CompilationDatabase *db = CompilationDatabase::loadFromDirectory(BuildDir, -                                                                   ErrorMsg); +  std::unique_ptr<CompilationDatabase> db = +      CompilationDatabase::loadFromDirectory(BuildDir, ErrorMsg);    if (!db) {      fprintf(stderr, "LIBCLANG TOOLING ERROR: %s\n", ErrorMsg.c_str()); @@ -27,7 +27,7 @@ clang_CompilationDatabase_fromDirectory(const char *BuildDir,    if (ErrorCode)      *ErrorCode = Err; -  return db; +  return db.release();  }  void diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 432190390b7f..7834181d4781 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -57,6 +57,7 @@ static CXCursorKind GetCursorKind(const Attr *A) {      case attr::CUDADevice: return CXCursor_CUDADeviceAttr;      case attr::CUDAGlobal: return CXCursor_CUDAGlobalAttr;      case attr::CUDAHost: return CXCursor_CUDAHostAttr; +    case attr::CUDAShared: return CXCursor_CUDASharedAttr;    }    return CXCursor_UnexposedAttr; @@ -228,6 +229,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,    case Stmt::CXXBindTemporaryExprClass:    case Stmt::CXXDefaultArgExprClass:    case Stmt::CXXDefaultInitExprClass: +  case Stmt::CXXFoldExprClass:    case Stmt::CXXStdInitializerListExprClass:    case Stmt::CXXScalarValueInitExprClass:    case Stmt::CXXUuidofExprClass: @@ -468,6 +470,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,    case Stmt::SubstNonTypeTemplateParmPackExprClass:    case Stmt::FunctionParmPackExprClass:    case Stmt::UnresolvedLookupExprClass: +  case Stmt::TypoExprClass: // A typo could actually be a DeclRef or a MemberRef      K = CXCursor_DeclRefExpr;      break; @@ -526,6 +529,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,    case Stmt::OMPForDirectiveClass:      K = CXCursor_OMPForDirective;      break; +  case Stmt::OMPForSimdDirectiveClass: +    K = CXCursor_OMPForSimdDirective; +    break;    case Stmt::OMPSectionsDirectiveClass:      K = CXCursor_OMPSectionsDirective;      break; @@ -544,6 +550,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,    case Stmt::OMPParallelForDirectiveClass:      K = CXCursor_OMPParallelForDirective;      break; +  case Stmt::OMPParallelForSimdDirectiveClass: +    K = CXCursor_OMPParallelForSimdDirective; +    break;    case Stmt::OMPParallelSectionsDirectiveClass:      K = CXCursor_OMPParallelSectionsDirective;      break; @@ -562,6 +571,18 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,    case Stmt::OMPFlushDirectiveClass:      K = CXCursor_OMPFlushDirective;      break; +  case Stmt::OMPOrderedDirectiveClass: +    K = CXCursor_OMPOrderedDirective; +    break; +  case Stmt::OMPAtomicDirectiveClass: +    K = CXCursor_OMPAtomicDirective; +    break; +  case Stmt::OMPTargetDirectiveClass: +    K = CXCursor_OMPTargetDirective; +    break; +  case Stmt::OMPTeamsDirectiveClass: +    K = CXCursor_OMPTeamsDirective; +    break;    }    CXCursor C = { K, 0, { Parent, S, TU } }; @@ -1055,6 +1076,140 @@ CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) {    return clang_getNullCursor();  } +int clang_Cursor_getNumTemplateArguments(CXCursor C) { +  if (clang_getCursorKind(C) != CXCursor_FunctionDecl) { +    return -1; +  } + +  const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>( +      getCursorDecl(C)); +  if (!FD) { +    return -1; +  } + +  const FunctionTemplateSpecializationInfo* SpecInfo = +      FD->getTemplateSpecializationInfo(); +  if (!SpecInfo) { +    return -1; +  } + +  return SpecInfo->TemplateArguments->size(); +} + +enum CXGetTemplateArgumentStatus { +  /** \brief The operation completed successfully */ +  CXGetTemplateArgumentStatus_Success = 0, + +  /** \brief The specified cursor did not represent a FunctionDecl. */ +  CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1, + +  /** \brief The specified cursor was not castable to a FunctionDecl. */ +  CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2, + +  /** \brief A NULL FunctionTemplateSpecializationInfo was retrieved. */ +  CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3, + +  /** \brief An invalid (OOB) argument index was specified */ +  CXGetTemplateArgumentStatus_InvalidIndex = -4 +}; + +static int clang_Cursor_getTemplateArgument( +    CXCursor C, unsigned I, TemplateArgument *TA) { +  if (clang_getCursorKind(C) != CXCursor_FunctionDecl) { +    return CXGetTemplateArgumentStatus_CursorNotFunctionDecl; +  } + +  const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>( +      getCursorDecl(C)); +  if (!FD) { +    return CXGetTemplateArgumentStatus_BadFunctionDeclCast; +  } + +  const FunctionTemplateSpecializationInfo* SpecInfo = +      FD->getTemplateSpecializationInfo(); +  if (!SpecInfo) { +    return CXGetTemplateArgumentStatus_NullTemplSpecInfo; +  } + +  if (I >= SpecInfo->TemplateArguments->size()) { +    return CXGetTemplateArgumentStatus_InvalidIndex; +  } + +  *TA = SpecInfo->TemplateArguments->get(I); +  return 0; +} + +enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C, +                                                                 unsigned I) { +  TemplateArgument TA; +  if (clang_Cursor_getTemplateArgument(C, I, &TA)) { +    return CXTemplateArgumentKind_Invalid; +  } + +  switch (TA.getKind()) { +    case TemplateArgument::Null: return CXTemplateArgumentKind_Null; +    case TemplateArgument::Type: return CXTemplateArgumentKind_Type; +    case TemplateArgument::Declaration: +      return CXTemplateArgumentKind_Declaration; +    case TemplateArgument::NullPtr: return CXTemplateArgumentKind_NullPtr; +    case TemplateArgument::Integral: return CXTemplateArgumentKind_Integral; +    case TemplateArgument::Template: return CXTemplateArgumentKind_Template; +    case TemplateArgument::TemplateExpansion: +      return CXTemplateArgumentKind_TemplateExpansion; +    case TemplateArgument::Expression: return CXTemplateArgumentKind_Expression; +    case TemplateArgument::Pack: return CXTemplateArgumentKind_Pack; +  } + +  return CXTemplateArgumentKind_Invalid; +} + +CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) { +  TemplateArgument TA; +  if (clang_Cursor_getTemplateArgument(C, I, &TA) != +      CXGetTemplateArgumentStatus_Success) { +    return cxtype::MakeCXType(QualType(), getCursorTU(C)); +  } + +  if (TA.getKind() != TemplateArgument::Type) { +    return cxtype::MakeCXType(QualType(), getCursorTU(C)); +  } + +  return cxtype::MakeCXType(TA.getAsType(), getCursorTU(C)); +} + +long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) { +  TemplateArgument TA; +  if (clang_Cursor_getTemplateArgument(C, I, &TA) != +      CXGetTemplateArgumentStatus_Success) { +    assert(0 && "Unable to retrieve TemplateArgument"); +    return 0; +  } + +  if (TA.getKind() != TemplateArgument::Integral) { +    assert(0 && "Passed template argument is not Integral"); +    return 0; +  } + +  return TA.getAsIntegral().getSExtValue(); +} + +unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C, +                                                                 unsigned I) { +  TemplateArgument TA; +  if (clang_Cursor_getTemplateArgument(C, I, &TA) != +      CXGetTemplateArgumentStatus_Success) { +    assert(0 && "Unable to retrieve TemplateArgument"); +    return 0; +  } + +  if (TA.getKind() != TemplateArgument::Integral) { +    assert(0 && "Passed template argument is not Integral"); +    return 0; +  } + +  return TA.getAsIntegral().getZExtValue(); +} +  } // end: extern "C"  //===----------------------------------------------------------------------===// @@ -1262,8 +1417,16 @@ int clang_Cursor_isDynamicCall(CXCursor C) {    if (!E)      return 0; -  if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) -    return MsgE->getReceiverKind() == ObjCMessageExpr::Instance; +  if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) { +    if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) +      return false; +    if (auto *RecE = dyn_cast<ObjCMessageExpr>( +            MsgE->getInstanceReceiver()->IgnoreParenCasts())) { +      if (RecE->getMethodFamily() == OMF_alloc) +        return false; +    } +    return true; +  }    const MemberExpr *ME = nullptr;    if (isa<MemberExpr>(E)) diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h index fee3bac95379..931d112766ed 100644 --- a/tools/libclang/CXCursor.h +++ b/tools/libclang/CXCursor.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CXCURSOR_H -#define LLVM_CLANG_CXCURSOR_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXCURSOR_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXCURSOR_H  #include "clang-c/Index.h"  #include "clang/Basic/SourceLocation.h" diff --git a/tools/libclang/CXLoadedDiagnostic.cpp b/tools/libclang/CXLoadedDiagnostic.cpp index ddf374903a93..fe5599a3abc9 100644 --- a/tools/libclang/CXLoadedDiagnostic.cpp +++ b/tools/libclang/CXLoadedDiagnostic.cpp @@ -16,7 +16,8 @@  #include "clang/Basic/Diagnostic.h"  #include "clang/Basic/FileManager.h"  #include "clang/Basic/LLVM.h" -#include "clang/Frontend/SerializedDiagnosticPrinter.h" +#include "clang/Frontend/SerializedDiagnosticReader.h" +#include "clang/Frontend/SerializedDiagnostics.h"  #include "llvm/ADT/Optional.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/ADT/Twine.h" @@ -183,475 +184,207 @@ void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,  // Deserialize diagnostics.  //===----------------------------------------------------------------------===// -enum { MaxSupportedVersion = 2 }; -typedef SmallVector<uint64_t, 64> RecordData; -enum LoadResult { Failure = 1, Success = 0 }; -enum StreamResult { Read_EndOfStream, -                    Read_BlockBegin, -                    Read_Failure, -                    Read_Record, -                    Read_BlockEnd }; -  namespace { -class DiagLoader { +class DiagLoader : serialized_diags::SerializedDiagnosticReader {    enum CXLoadDiag_Error *error;    CXString *errorString; -   -  void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) { +  std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags; +  SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags; + +  std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {      if (error)        *error = code;      if (errorString)        *errorString = cxstring::createDup(err); +    return serialized_diags::SDError::HandlerFailed;    } -  void reportInvalidFile(llvm::StringRef err) { +  std::error_code reportInvalidFile(llvm::StringRef err) {      return reportBad(CXLoadDiag_InvalidFile, err);    } -  LoadResult readMetaBlock(llvm::BitstreamCursor &Stream); -   -  LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream, -                                 CXDiagnosticSetImpl &Diags, -                                 CXLoadedDiagnosticSetImpl &TopDiags); - -  StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream, -                                       llvm::StringRef errorContext, -                                       unsigned &BlockOrRecordID, -                                       bool atTopLevel = false); -   -   -  LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags, -                        Strings &strings, llvm::StringRef errorContext, -                        RecordData &Record, -                        StringRef Blob, -                        bool allowEmptyString = false); - -  LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags, -                        const char *&RetStr, -                        llvm::StringRef errorContext, -                        RecordData &Record, -                        StringRef Blob, -                        bool allowEmptyString = false); - -  LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags, -                       RecordData &Record, unsigned RecStartIdx, -                       CXSourceRange &SR); -   -  LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags, -                          RecordData &Record, unsigned &offset, -                          CXLoadedDiagnostic::Location &Loc); -                        -public: -  DiagLoader(enum CXLoadDiag_Error *e, CXString *es) -    : error(e), errorString(es) { -      if (error) -        *error = CXLoadDiag_None; -      if (errorString) -        *errorString = cxstring::createEmpty(); -    } +  std::error_code readRange(const serialized_diags::Location &SDStart, +                            const serialized_diags::Location &SDEnd, +                            CXSourceRange &SR); -  CXDiagnosticSet load(const char *file); -}; -} +  std::error_code readLocation(const serialized_diags::Location &SDLoc, +                               CXLoadedDiagnostic::Location &LoadedLoc); -CXDiagnosticSet DiagLoader::load(const char *file) { -  // Open the diagnostics file. -  std::string ErrStr; -  FileSystemOptions FO; -  FileManager FileMgr(FO); +protected: +  std::error_code visitStartOfDiagnostic() override; +  std::error_code visitEndOfDiagnostic() override; -  std::unique_ptr<llvm::MemoryBuffer> Buffer; -  Buffer.reset(FileMgr.getBufferForFile(file)); +  std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override; -  if (!Buffer) { -    reportBad(CXLoadDiag_CannotLoad, ErrStr); -    return nullptr; -  } +  std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override; -  llvm::BitstreamReader StreamFile; -  StreamFile.init((const unsigned char *)Buffer->getBufferStart(), -                  (const unsigned char *)Buffer->getBufferEnd()); - -  llvm::BitstreamCursor Stream; -  Stream.init(StreamFile); - -  // Sniff for the signature. -  if (Stream.Read(8) != 'D' || -      Stream.Read(8) != 'I' || -      Stream.Read(8) != 'A' || -      Stream.Read(8) != 'G') { -    reportBad(CXLoadDiag_InvalidFile, -              "Bad header in diagnostics file"); -    return nullptr; -  } +  std::error_code visitDiagnosticRecord( +      unsigned Severity, const serialized_diags::Location &Location, +      unsigned Category, unsigned Flag, StringRef Message) override; -  std::unique_ptr<CXLoadedDiagnosticSetImpl> Diags( -      new CXLoadedDiagnosticSetImpl()); - -  while (true) { -    unsigned BlockID = 0; -    StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",  -                                               BlockID, true); -    switch (Res) { -      case Read_EndOfStream: -        return (CXDiagnosticSet)Diags.release(); -      case Read_Failure: -        return nullptr; -      case Read_Record: -        llvm_unreachable("Top-level does not have records"); -      case Read_BlockEnd: -        continue; -      case Read_BlockBegin: -        break; -    } -     -    switch (BlockID) { -      case serialized_diags::BLOCK_META: -        if (readMetaBlock(Stream)) -          return nullptr; -        break; -      case serialized_diags::BLOCK_DIAG: -        if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get())) -          return nullptr; -        break; -      default: -        if (!Stream.SkipBlock()) { -          reportInvalidFile("Malformed block at top-level of diagnostics file"); -          return nullptr; -        } -        break; -    } +  std::error_code visitFilenameRecord(unsigned ID, unsigned Size, +                                      unsigned Timestamp, +                                      StringRef Name) override; + +  std::error_code visitFixitRecord(const serialized_diags::Location &Start, +                                   const serialized_diags::Location &End, +                                   StringRef CodeToInsert) override; + +  std::error_code +  visitSourceRangeRecord(const serialized_diags::Location &Start, +                         const serialized_diags::Location &End) override; + +public: +  DiagLoader(enum CXLoadDiag_Error *e, CXString *es) +      : SerializedDiagnosticReader(), error(e), errorString(es) { +    if (error) +      *error = CXLoadDiag_None; +    if (errorString) +      *errorString = cxstring::createEmpty();    } + +  CXDiagnosticSet load(const char *file); +};  } -StreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream, -                                                 llvm::StringRef errorContext, -                                                 unsigned &blockOrRecordID, -                                                 bool atTopLevel) { -   -  blockOrRecordID = 0; - -  while (!Stream.AtEndOfStream()) { -    unsigned Code = Stream.ReadCode(); - -    // Handle the top-level specially. -    if (atTopLevel) { -      if (Code == llvm::bitc::ENTER_SUBBLOCK) { -        unsigned BlockID = Stream.ReadSubBlockID(); -        if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) { -          if (Stream.ReadBlockInfoBlock()) { -            reportInvalidFile("Malformed BlockInfoBlock in diagnostics file"); -            return Read_Failure; -          } -          continue; -        } -        blockOrRecordID = BlockID; -        return Read_BlockBegin; -      } -      reportInvalidFile("Only blocks can appear at the top of a " -                        "diagnostic file"); -      return Read_Failure; -    } -     -    switch ((llvm::bitc::FixedAbbrevIDs)Code) { -      case llvm::bitc::ENTER_SUBBLOCK: -        blockOrRecordID = Stream.ReadSubBlockID(); -        return Read_BlockBegin; -       -      case llvm::bitc::END_BLOCK: -        if (Stream.ReadBlockEnd()) { -          reportInvalidFile("Cannot read end of block"); -          return Read_Failure; -        } -        return Read_BlockEnd; -         -      case llvm::bitc::DEFINE_ABBREV: -        Stream.ReadAbbrevRecord(); -        continue; -         -      case llvm::bitc::UNABBREV_RECORD: -        reportInvalidFile("Diagnostics file should have no unabbreviated " -                          "records"); -        return Read_Failure; -       -      default: -        // We found a record. -        blockOrRecordID = Code; -        return Read_Record; +CXDiagnosticSet DiagLoader::load(const char *file) { +  TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>(); + +  std::error_code EC = readDiagnostics(file); +  if (EC) { +    switch (EC.value()) { +    case static_cast<int>(serialized_diags::SDError::HandlerFailed): +      // We've already reported the problem. +      break; +    case static_cast<int>(serialized_diags::SDError::CouldNotLoad): +      reportBad(CXLoadDiag_CannotLoad, EC.message()); +      break; +    default: +      reportInvalidFile(EC.message()); +      break;      } +    return 0;    } -   -  if (atTopLevel) -    return Read_EndOfStream; -   -  reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +  -                    errorContext.str()); -  return Read_Failure; + +  return (CXDiagnosticSet)TopDiags.release();  } -LoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) { -  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) { -    reportInvalidFile("Malformed metadata block"); -    return Failure; -  } - -  bool versionChecked = false; -   -  while (true) { -    unsigned blockOrCode = 0; -    StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block", -                                               blockOrCode); -     -    switch(Res) { -      case Read_EndOfStream: -        llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock"); -      case Read_Failure: -        return Failure; -      case Read_Record: -        break; -      case Read_BlockBegin: -        if (Stream.SkipBlock()) { -          reportInvalidFile("Malformed metadata block"); -          return Failure; -        } -      case Read_BlockEnd: -        if (!versionChecked) { -          reportInvalidFile("Diagnostics file does not contain version" -                            " information"); -          return Failure; -        } -        return Success; -    } -     -    RecordData Record; -    unsigned recordID = Stream.readRecord(blockOrCode, Record); -     -    if (recordID == serialized_diags::RECORD_VERSION) { -      if (Record.size() < 1) { -        reportInvalidFile("malformed VERSION identifier in diagnostics file"); -        return Failure; -      } -      if (Record[0] > MaxSupportedVersion) { -        reportInvalidFile("diagnostics file is a newer version than the one " -                          "supported"); -        return Failure; -      } -      versionChecked = true; -    } +std::error_code +DiagLoader::readLocation(const serialized_diags::Location &SDLoc, +                         CXLoadedDiagnostic::Location &LoadedLoc) { +  unsigned FileID = SDLoc.FileID; +  if (FileID == 0) +    LoadedLoc.file = nullptr; +  else { +    LoadedLoc.file = const_cast<FileEntry *>(TopDiags->Files[FileID]); +    if (!LoadedLoc.file) +      return reportInvalidFile("Corrupted file entry in source location");    } +  LoadedLoc.line = SDLoc.Line; +  LoadedLoc.column = SDLoc.Col; +  LoadedLoc.offset = SDLoc.Offset; +  return std::error_code();  } -LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags, -                                  const char *&RetStr, -                                  llvm::StringRef errorContext, -                                  RecordData &Record, -                                  StringRef Blob, -                                  bool allowEmptyString) { +std::error_code +DiagLoader::readRange(const serialized_diags::Location &SDStart, +                      const serialized_diags::Location &SDEnd, +                      CXSourceRange &SR) { +  CXLoadedDiagnostic::Location *Start, *End; +  Start = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>(); +  End = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>(); + +  std::error_code EC; +  if ((EC = readLocation(SDStart, *Start))) +    return EC; +  if ((EC = readLocation(SDEnd, *End))) +    return EC; -  // Basic buffer overflow check. -  if (Blob.size() > 65536) { -    reportInvalidFile(std::string("Out-of-bounds string in ") + -                      std::string(errorContext)); -    return Failure; -  } +  CXSourceLocation startLoc = makeLocation(Start); +  CXSourceLocation endLoc = makeLocation(End); +  SR = clang_getRange(startLoc, endLoc); +  return std::error_code(); +} -  if (allowEmptyString && Record.size() >= 1 && Blob.size() == 0) { -    RetStr = ""; -    return Success; -  } -   -  if (Record.size() < 1 || Blob.size() == 0) { -    reportInvalidFile(std::string("Corrupted ") + std::string(errorContext) -                      + std::string(" entry")); -    return Failure; -  } -   -  RetStr = TopDiags.copyString(Blob); -  return Success; +std::error_code DiagLoader::visitStartOfDiagnostic() { +  CurrentDiags.push_back(llvm::make_unique<CXLoadedDiagnostic>()); +  return std::error_code();  } -LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags, -                                  Strings &strings, -                                  llvm::StringRef errorContext, -                                  RecordData &Record, -                                  StringRef Blob, -                                  bool allowEmptyString) { -  const char *RetStr; -  if (readString(TopDiags, RetStr, errorContext, Record, Blob, -                 allowEmptyString)) -    return Failure; -  strings[Record[0]] = RetStr; -  return Success; +std::error_code DiagLoader::visitEndOfDiagnostic() { +  auto D = CurrentDiags.pop_back_val(); +  if (CurrentDiags.empty()) +    TopDiags->appendDiagnostic(std::move(D)); +  else +    CurrentDiags.back()->getChildDiagnostics().appendDiagnostic(std::move(D)); +  return std::error_code();  } -LoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags, -                                    RecordData &Record, unsigned &offset, -                                    CXLoadedDiagnostic::Location &Loc) { -  if (Record.size() < offset + 3) { -    reportInvalidFile("Corrupted source location"); -    return Failure; -  } -   -  unsigned fileID = Record[offset++]; -  if (fileID == 0) { -    // Sentinel value. -    Loc.file = nullptr; -    Loc.line = 0; -    Loc.column = 0; -    Loc.offset = 0; -    return Success; -  } +std::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) { +  // FIXME: Why do we care about long strings? +  if (Name.size() > 65536) +    return reportInvalidFile("Out-of-bounds string in category"); +  TopDiags->Categories[ID] = TopDiags->copyString(Name); +  return std::error_code(); +} -  const FileEntry *FE = TopDiags.Files[fileID]; -  if (!FE) { -    reportInvalidFile("Corrupted file entry in source location"); -    return Failure; -  } -  Loc.file = const_cast<FileEntry *>(FE); -  Loc.line = Record[offset++]; -  Loc.column = Record[offset++]; -  Loc.offset = Record[offset++]; -  return Success; +std::error_code DiagLoader::visitDiagFlagRecord(unsigned ID, StringRef Name) { +  // FIXME: Why do we care about long strings? +  if (Name.size() > 65536) +    return reportInvalidFile("Out-of-bounds string in warning flag"); +  TopDiags->WarningFlags[ID] = TopDiags->copyString(Name); +  return std::error_code();  } -LoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags, -                                 RecordData &Record, -                                 unsigned int RecStartIdx, -                                 CXSourceRange &SR) { -  CXLoadedDiagnostic::Location *Start, *End; -  Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>(); -  End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>(); -   -  if (readLocation(TopDiags, Record, RecStartIdx, *Start)) -    return Failure; -  if (readLocation(TopDiags, Record, RecStartIdx, *End)) -    return Failure; -   -  CXSourceLocation startLoc = makeLocation(Start); -  CXSourceLocation endLoc = makeLocation(End); -  SR = clang_getRange(startLoc, endLoc); -  return Success;   +std::error_code DiagLoader::visitFilenameRecord(unsigned ID, unsigned Size, +                                                unsigned Timestamp, +                                                StringRef Name) { +  // FIXME: Why do we care about long strings? +  if (Name.size() > 65536) +    return reportInvalidFile("Out-of-bounds string in filename"); +  TopDiags->FileNames[ID] = TopDiags->copyString(Name); +  TopDiags->Files[ID] = +      TopDiags->FakeFiles.getVirtualFile(Name, Size, Timestamp); +  return std::error_code();  } -LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream, -                                           CXDiagnosticSetImpl &Diags, -                                           CXLoadedDiagnosticSetImpl &TopDiags){ +std::error_code +DiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start, +                                   const serialized_diags::Location &End) { +  CXSourceRange SR; +  if (std::error_code EC = readRange(Start, End, SR)) +    return EC; +  CurrentDiags.back()->Ranges.push_back(SR); +  return std::error_code(); +} -  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) { -    reportInvalidFile("malformed diagnostic block"); -    return Failure; -  } +std::error_code +DiagLoader::visitFixitRecord(const serialized_diags::Location &Start, +                             const serialized_diags::Location &End, +                             StringRef CodeToInsert) { +  CXSourceRange SR; +  if (std::error_code EC = readRange(Start, End, SR)) +    return EC; +  // FIXME: Why do we care about long strings? +  if (CodeToInsert.size() > 65536) +    return reportInvalidFile("Out-of-bounds string in FIXIT"); +  CurrentDiags.back()->FixIts.push_back( +      std::make_pair(SR, TopDiags->copyString(CodeToInsert))); +  return std::error_code(); +} -  std::unique_ptr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic()); -  RecordData Record; -   -  while (true) { -    unsigned blockOrCode = 0; -    StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block", -                                               blockOrCode); -    switch (Res) { -      case Read_EndOfStream: -        llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock"); -      case Read_Failure: -        return Failure; -      case Read_BlockBegin: { -        // The only blocks we care about are subdiagnostics. -        if (blockOrCode != serialized_diags::BLOCK_DIAG) { -          if (!Stream.SkipBlock()) { -            reportInvalidFile("Invalid subblock in Diagnostics block"); -            return Failure; -          } -        } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(), -                                       TopDiags)) { -          return Failure; -        } - -        continue; -      } -      case Read_BlockEnd: -        Diags.appendDiagnostic(D.release()); -        return Success; -      case Read_Record: -        break; -    } -     -    // Read the record. -    Record.clear(); -    StringRef Blob; -    unsigned recID = Stream.readRecord(blockOrCode, Record, &Blob); -     -    if (recID < serialized_diags::RECORD_FIRST || -        recID > serialized_diags::RECORD_LAST) -      continue; -     -    switch ((serialized_diags::RecordIDs)recID) {   -      case serialized_diags::RECORD_VERSION: -        continue; -      case serialized_diags::RECORD_CATEGORY: -        if (readString(TopDiags, TopDiags.Categories, "category", Record, -                       Blob, /* allowEmptyString */ true)) -          return Failure; -        continue; -       -      case serialized_diags::RECORD_DIAG_FLAG: -        if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record, -                       Blob)) -          return Failure; -        continue; -         -      case serialized_diags::RECORD_FILENAME: { -        if (readString(TopDiags, TopDiags.FileNames, "filename", Record, -                       Blob)) -          return Failure; - -        if (Record.size() < 3) { -          reportInvalidFile("Invalid file entry"); -          return Failure; -        } -         -        const FileEntry *FE = -          TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]], -                                            /* size */ Record[1], -                                            /* time */ Record[2]); -         -        TopDiags.Files[Record[0]] = FE; -        continue; -      } - -      case serialized_diags::RECORD_SOURCE_RANGE: { -        CXSourceRange SR; -        if (readRange(TopDiags, Record, 0, SR)) -          return Failure; -        D->Ranges.push_back(SR); -        continue; -      } -       -      case serialized_diags::RECORD_FIXIT: { -        CXSourceRange SR; -        if (readRange(TopDiags, Record, 0, SR)) -          return Failure; -        const char *RetStr; -        if (readString(TopDiags, RetStr, "FIXIT", Record, Blob, -                       /* allowEmptyString */ true)) -          return Failure; -        D->FixIts.push_back(std::make_pair(SR, RetStr)); -        continue; -      } -         -      case serialized_diags::RECORD_DIAG: { -        D->severity = Record[0]; -        unsigned offset = 1; -        if (readLocation(TopDiags, Record, offset, D->DiagLoc)) -          return Failure; -        D->category = Record[offset++]; -        unsigned diagFlag = Record[offset++]; -        D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : ""; -        D->CategoryText = D->category ? TopDiags.Categories[D->category] : ""; -        D->Spelling = TopDiags.copyString(Blob); -        continue; -      } -    } -  } +std::error_code DiagLoader::visitDiagnosticRecord( +    unsigned Severity, const serialized_diags::Location &Location, +    unsigned Category, unsigned Flag, StringRef Message) { +  CXLoadedDiagnostic &D = *CurrentDiags.back(); +  D.severity = Severity; +  if (std::error_code EC = readLocation(Location, D.DiagLoc)) +    return EC; +  D.category = Category; +  D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : ""; +  D.CategoryText = Category ? TopDiags->Categories[Category] : ""; +  D.Spelling = TopDiags->copyString(Message); +  return std::error_code();  }  extern "C" { diff --git a/tools/libclang/CXLoadedDiagnostic.h b/tools/libclang/CXLoadedDiagnostic.h index c281f9be3e87..54261be6cf46 100644 --- a/tools/libclang/CXLoadedDiagnostic.h +++ b/tools/libclang/CXLoadedDiagnostic.h @@ -11,8 +11,8 @@  |*                                                                            *|  \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_CLANG_CINDEX_LOADED_DIAGNOSTIC_H -#define LLVM_CLANG_CINDEX_LOADED_DIAGNOSTIC_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXLOADEDDIAGNOSTIC_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXLOADEDDIAGNOSTIC_H  #include "CIndexDiagnostic.h"  #include "llvm/ADT/StringRef.h" diff --git a/tools/libclang/CXSourceLocation.h b/tools/libclang/CXSourceLocation.h index f97ac1f3aff8..f0b3f4954919 100644 --- a/tools/libclang/CXSourceLocation.h +++ b/tools/libclang/CXSourceLocation.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CXSOURCELOCATION_H -#define LLVM_CLANG_CXSOURCELOCATION_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXSOURCELOCATION_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXSOURCELOCATION_H  #include "clang-c/Index.h"  #include "clang/AST/ASTContext.h" diff --git a/tools/libclang/CXString.h b/tools/libclang/CXString.h index ed3ed4ad2d52..f6b46f76a443 100644 --- a/tools/libclang/CXString.h +++ b/tools/libclang/CXString.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CXSTRING_H -#define LLVM_CLANG_CXSTRING_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXSTRING_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXSTRING_H  #include "clang-c/Index.h"  #include "clang/Basic/LLVM.h" diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h index d86ed2b8d342..6022c9dab1b5 100644 --- a/tools/libclang/CXTranslationUnit.h +++ b/tools/libclang/CXTranslationUnit.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CXTRANSLATIONUNIT_H -#define LLVM_CLANG_CXTRANSLATIONUNIT_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXTRANSLATIONUNIT_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXTRANSLATIONUNIT_H  #include "CLog.h"  #include "CXString.h" diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index fe45899ad548..81cff5abb4f5 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -520,6 +520,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {        TCALLINGCONV(X86FastCall);        TCALLINGCONV(X86ThisCall);        TCALLINGCONV(X86Pascal); +      TCALLINGCONV(X86VectorCall);        TCALLINGCONV(X86_64Win64);        TCALLINGCONV(X86_64SysV);        TCALLINGCONV(AAPCS); diff --git a/tools/libclang/CXType.h b/tools/libclang/CXType.h index 7660bebf041b..941cc0a9fd7e 100644 --- a/tools/libclang/CXType.h +++ b/tools/libclang/CXType.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CXTYPES_H -#define LLVM_CLANG_CXTYPES_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXTYPE_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXTYPE_H  #include "clang-c/Index.h"  #include "clang/AST/Type.h" diff --git a/tools/libclang/CursorVisitor.h b/tools/libclang/CursorVisitor.h index c4ec7b693766..1b2a922204f8 100644 --- a/tools/libclang/CursorVisitor.h +++ b/tools/libclang/CursorVisitor.h @@ -7,8 +7,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIBCLANG_CURSORVISITOR_H -#define LLVM_CLANG_LIBCLANG_CURSORVISITOR_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H  #include "CXCursor.h"  #include "CXTranslationUnit.h" diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp index 7dc53a627533..5539971f04a7 100644 --- a/tools/libclang/IndexBody.cpp +++ b/tools/libclang/IndexBody.cpp @@ -150,7 +150,7 @@ public:    }    bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) { -    if (C->capturesThis()) +    if (C->capturesThis() || C->capturesVLAType())        return true;      if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/tools/libclang/IndexTypeSourceInfo.cpp index f13c0aff0da3..706870e514b8 100644 --- a/tools/libclang/IndexTypeSourceInfo.cpp +++ b/tools/libclang/IndexTypeSourceInfo.cpp @@ -129,6 +129,7 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,    switch (NNS.getNestedNameSpecifier()->getKind()) {    case NestedNameSpecifier::Identifier:    case NestedNameSpecifier::Global: +  case NestedNameSpecifier::Super:      break;    case NestedNameSpecifier::Namespace: diff --git a/tools/libclang/Index_Internal.h b/tools/libclang/Index_Internal.h index 2d42cb83c970..98f069c88738 100644 --- a/tools/libclang/Index_Internal.h +++ b/tools/libclang/Index_Internal.h @@ -11,8 +11,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBCLANG_INDEX_INTERNAL_H -#define LLVM_LIBCLANG_INDEX_INTERNAL_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEX_INTERNAL_H +#define LLVM_CLANG_TOOLS_LIBCLANG_INDEX_INTERNAL_H  #include "clang-c/Index.h" diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 58af61811bf5..20f4474a1ee8 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -414,8 +414,8 @@ public:      : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU),        CXTU(cxTU), SKData(skData) { } -  ASTConsumer *CreateASTConsumer(CompilerInstance &CI, -                                 StringRef InFile) override { +  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, +                                                 StringRef InFile) override {      PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();      if (!PPOpts.ImplicitPCHInclude.empty()) { @@ -425,17 +425,16 @@ public:      IndexCtx.setASTContext(CI.getASTContext());      Preprocessor &PP = CI.getPreprocessor(); -    PP.addPPCallbacks(new IndexPPCallbacks(PP, IndexCtx)); +    PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, IndexCtx));      IndexCtx.setPreprocessor(PP);      if (SKData) { -      PPConditionalDirectiveRecord * -        PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager()); -      PP.addPPCallbacks(PPRec); -      SKCtrl.reset(new TUSkipBodyControl(*SKData, *PPRec, PP)); +      auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager()); +      PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); +      SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);      } -    return new IndexingConsumer(IndexCtx, SKCtrl.get()); +    return llvm::make_unique<IndexingConsumer>(IndexCtx, SKCtrl.get());    }    void EndSourceFileAction() override { @@ -576,10 +575,10 @@ static void clang_indexSourceFile_Impl(void *UserData) {        BufOwner.get());    for (auto &UF : ITUI->unsaved_files) { -    llvm::MemoryBuffer *MB = +    std::unique_ptr<llvm::MemoryBuffer> MB =          llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); -    BufOwner->push_back(std::unique_ptr<llvm::MemoryBuffer>(MB)); -    CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB); +    CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get()); +    BufOwner->push_back(std::move(MB));    }    // Since libclang is primarily used by batch tools dealing with diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index c3851cd7e95e..31fddfb09cd4 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -7,6 +7,9 @@  //  //===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H +#define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H +  #include "CXCursor.h"  #include "Index_Internal.h"  #include "clang/AST/DeclGroup.h" @@ -517,3 +520,5 @@ inline T *ScratchAlloc::allocate() {  }  }} // end clang::cxindex + +#endif diff --git a/tools/libclang/Makefile b/tools/libclang/Makefile index db3d4f86244a..97f663cde478 100644 --- a/tools/libclang/Makefile +++ b/tools/libclang/Makefile @@ -16,11 +16,11 @@ LINK_LIBS_IN_SHARED = 1  SHARED_LIBRARY = 1  include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := AsmParser BitReader Core MC MCParser Option Support  USEDLIBS = clangIndex.a clangARCMigrate.a \  	   clangRewriteFrontend.a \  	   clangFormat.a \ -	   clangTooling.a \ +	   clangTooling.a clangToolingCore.a \  	   clangFrontend.a clangDriver.a \  	   clangSerialization.a \  	   clangParse.a clangSema.a \ diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 48eec2576743..fa2c0e70bf32 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -7,8 +7,14 @@ clang_CXXMethod_isPureVirtual  clang_CXXMethod_isStatic  clang_CXXMethod_isVirtual  clang_Cursor_getArgument +clang_Cursor_getNumTemplateArguments +clang_Cursor_getTemplateArgumentKind +clang_Cursor_getTemplateArgumentType +clang_Cursor_getTemplateArgumentValue +clang_Cursor_getTemplateArgumentUnsignedValue  clang_Cursor_getBriefCommentText  clang_Cursor_getCommentRange +clang_Cursor_getMangling  clang_Cursor_getParsedComment  clang_Cursor_getRawCommentText  clang_Cursor_getNumArguments @@ -24,6 +30,8 @@ clang_Cursor_isNull  clang_Cursor_isObjCOptional  clang_Cursor_isVariadic  clang_Cursor_getModule +clang_Cursor_getStorageClass +clang_File_isEqual  clang_Module_getASTFile  clang_Module_getParent  clang_Module_getName diff --git a/tools/scan-build/c++-analyzer.bat b/tools/scan-build/c++-analyzer.bat new file mode 100644 index 000000000000..69f048a91671 --- /dev/null +++ b/tools/scan-build/c++-analyzer.bat @@ -0,0 +1 @@ +perl -S c++-analyzer %*
 diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer index 4c8f6482a153..9de38d42aafa 100755 --- a/tools/scan-build/ccc-analyzer +++ b/tools/scan-build/ccc-analyzer @@ -42,9 +42,17 @@ my $DefaultCCompiler;  my $DefaultCXXCompiler;  my $IsCXX; +# If on OSX, use xcrun to determine the SDK root. +my $UseXCRUN = 0; +  if (`uname -a` =~ m/Darwin/) {    $DefaultCCompiler = 'clang';    $DefaultCXXCompiler = 'clang++'; +  # Older versions of OSX do not have xcrun to +  # query the SDK location. +  if (-x "/usr/bin/xcrun") { +    $UseXCRUN = 1; +  }  } else {    $DefaultCCompiler = 'gcc';    $DefaultCXXCompiler = 'g++'; @@ -478,6 +486,7 @@ my $HtmlDir = $ENV{'CCC_ANALYZER_HTML'};  my %DisabledArchs = ('ppc' => 1, 'ppc64' => 1);  my %ArchsSeen;  my $HadArch = 0; +my $HasSDK = 0;  # Process the arguments.  foreach (my $i = 0; $i < scalar(@ARGV); ++$i) { @@ -500,6 +509,12 @@ foreach (my $i = 0; $i < scalar(@ARGV); ++$i) {      next;    } +  # On OSX/iOS, record if an SDK path was specified.  This +  # is innocuous for other platforms, so the check just happens. +  if ($Arg =~ /^-isysroot/) { +    $HasSDK = 1; +  } +    # Options with possible arguments that should pass through to compiler.    if (defined $CompileOptionMap{$ArgKey}) {      my $Cnt = $CompileOptionMap{$ArgKey}; @@ -644,6 +659,15 @@ foreach (my $i = 0; $i < scalar(@ARGV); ++$i) {    }  } +# If we are on OSX and have an installation where the +# default SDK is inferred by xcrun use xcrun to infer +# the SDK. +if (not $HasSDK and $UseXCRUN) { +  my $sdk = `/usr/bin/xcrun --show-sdk-path -sdk macosx`; +  chomp $sdk; +  push @CompileOpts, "-isysroot", $sdk; +} +  if ($Action eq 'compile' or $Action eq 'link') {    my @Archs = keys %ArchsSeen;    # Skip the file if we don't support the architectures specified. diff --git a/tools/scan-build/ccc-analyzer.bat b/tools/scan-build/ccc-analyzer.bat new file mode 100644 index 000000000000..2a85376eb82b --- /dev/null +++ b/tools/scan-build/ccc-analyzer.bat @@ -0,0 +1 @@ +perl -S ccc-analyzer %*
 diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index 153be2dca1c9..d52d8f5f655c 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -1056,7 +1056,7 @@ sub RunBuildCommand {      shift @$Args;      unshift @$Args, $CXXAnalyzer;    } -  elsif ($Cmd eq "make" or $Cmd eq "gmake") { +  elsif ($Cmd eq "make" or $Cmd eq "gmake" or $Cmd eq "mingw32-make") {      AddIfNotPresent($Args, "CC=$CCAnalyzer");      AddIfNotPresent($Args, "CXX=$CXXAnalyzer");      if ($IgnoreErrors) { @@ -1221,104 +1221,104 @@ LOADING CHECKERS:   -load-plugin [plugin library]  ENDTEXT -# Query clang for list of checkers that are enabled. - -# create a list to load the plugins via the 'Xclang' command line -# argument -my @PluginLoadCommandline_xclang; -foreach my $param ( @PluginsToLoad ) { -  push ( @PluginLoadCommandline_xclang, "-Xclang" ); -  push ( @PluginLoadCommandline_xclang, $param ); -} -my %EnabledCheckers; -foreach my $lang ("c", "objective-c", "objective-c++", "c++") { -  pipe(FROM_CHILD, TO_PARENT); -  my $pid = fork(); -  if ($pid == 0) { -    close FROM_CHILD; -    open(STDOUT,">&", \*TO_PARENT); -    open(STDERR,">&", \*TO_PARENT); -    exec $Clang, ( @PluginLoadCommandline_xclang, '--analyze', '-x', $lang, '-', '-###'); -  } -  close(TO_PARENT); -  while(<FROM_CHILD>) { -    foreach my $val (split /\s+/) { -      $val =~ s/\"//g; -      if ($val =~ /-analyzer-checker\=([^\s]+)/) { -        $EnabledCheckers{$1} = 1; +  # Query clang for list of checkers that are enabled. + +  # create a list to load the plugins via the 'Xclang' command line +  # argument +  my @PluginLoadCommandline_xclang; +  foreach my $param ( @PluginsToLoad ) { +    push ( @PluginLoadCommandline_xclang, "-Xclang" ); +    push ( @PluginLoadCommandline_xclang, $param ); +  } +  my %EnabledCheckers; +  foreach my $lang ("c", "objective-c", "objective-c++", "c++") { +    pipe(FROM_CHILD, TO_PARENT); +    my $pid = fork(); +    if ($pid == 0) { +      close FROM_CHILD; +      open(STDOUT,">&", \*TO_PARENT); +      open(STDERR,">&", \*TO_PARENT); +      exec $Clang, ( @PluginLoadCommandline_xclang, '--analyze', '-x', $lang, '-', '-###'); +    } +    close(TO_PARENT); +    while(<FROM_CHILD>) { +      foreach my $val (split /\s+/) { +        $val =~ s/\"//g; +        if ($val =~ /-analyzer-checker\=([^\s]+)/) { +          $EnabledCheckers{$1} = 1; +        }        }      } -  } -  waitpid($pid,0); -  close(FROM_CHILD); -} - -# Query clang for complete list of checkers. -if (defined $Clang && -x $Clang) { -  pipe(FROM_CHILD, TO_PARENT); -  my $pid = fork(); -  if ($pid == 0) { -    close FROM_CHILD; -    open(STDOUT,">&", \*TO_PARENT); -    open(STDERR,">&", \*TO_PARENT); -    exec $Clang, ('-cc1', @PluginsToLoad , '-analyzer-checker-help'); -  } -  close(TO_PARENT); -  my $foundCheckers = 0; -  while(<FROM_CHILD>) { -    if (/CHECKERS:/) { -      $foundCheckers = 1; -      last; +    waitpid($pid,0); +    close(FROM_CHILD); +  } + +  # Query clang for complete list of checkers. +  if (defined $Clang && -x $Clang) { +    pipe(FROM_CHILD, TO_PARENT); +    my $pid = fork(); +    if ($pid == 0) { +      close FROM_CHILD; +      open(STDOUT,">&", \*TO_PARENT); +      open(STDERR,">&", \*TO_PARENT); +      exec $Clang, ('-cc1', @PluginsToLoad , '-analyzer-checker-help');      } -  } -  if (!$foundCheckers) { -    print "  *** Could not query Clang for the list of available checkers."; -  } -  else { -    print("\nAVAILABLE CHECKERS:\n\n"); -    my $skip = 0; +    close(TO_PARENT); +    my $foundCheckers = 0;      while(<FROM_CHILD>) { -      if (/experimental/) { -        $skip = 1; -        next; -      } -      if ($skip) { -        next if (!/^\s\s[^\s]/); -        $skip = 0; +      if (/CHECKERS:/) { +        $foundCheckers = 1; +        last;        } -      s/^\s\s//; -      if (/^([^\s]+)/) { -        # Is the checker enabled? -        my $checker = $1; -        my $enabled = 0; -        my $aggregate = ""; -        foreach my $domain (split /\./, $checker) { -          $aggregate .= $domain; -          if ($EnabledCheckers{$aggregate}) { -            $enabled =1; -            last; -          } -          # append a dot, if an additional domain is added in the next iteration -          $aggregate .= "."; +    } +    if (!$foundCheckers) { +      print "  *** Could not query Clang for the list of available checkers."; +    } +    else { +      print("\nAVAILABLE CHECKERS:\n\n"); +      my $skip = 0; +      while(<FROM_CHILD>) { +        if (/experimental/) { +          $skip = 1; +          next; +        } +        if ($skip) { +          next if (!/^\s\s[^\s]/); +          $skip = 0;          } +        s/^\s\s//; +        if (/^([^\s]+)/) { +          # Is the checker enabled? +          my $checker = $1; +          my $enabled = 0; +          my $aggregate = ""; +          foreach my $domain (split /\./, $checker) { +            $aggregate .= $domain; +            if ($EnabledCheckers{$aggregate}) { +              $enabled =1; +              last; +            } +            # append a dot, if an additional domain is added in the next iteration +            $aggregate .= "."; +          } -        if ($enabled) { -          print " + "; +          if ($enabled) { +            print " + "; +          } +          else { +            print "   "; +          }          }          else {            print "   ";          } +        print $_;        } -      else { -        print "   "; -      } -      print $_; +      print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n"      } -    print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n" +    waitpid($pid,0); +    close(FROM_CHILD);    } -  waitpid($pid,0); -  close(FROM_CHILD); -}  print <<ENDTEXT @@ -1533,6 +1533,7 @@ while (@ARGV) {    }    if ($arg eq "-no-failure-reports") { +    shift @ARGV;      $ENV{"CCC_REPORT_FAILURES"} = 0;      next;    }  | 
