diff options
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; } |