aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
commit45b533945f0851ec234ca846e1af5ee1e4df0b6e (patch)
tree0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /tools
parent7e86edd64bfae4e324224452e4ea879b3371a4bd (diff)
Notes
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt24
-rw-r--r--tools/Makefile2
-rw-r--r--tools/c-index-test/CMakeLists.txt20
-rw-r--r--tools/c-index-test/c-index-test.c59
-rw-r--r--tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs145
-rw-r--r--tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs4
-rw-r--r--tools/clang-format-vs/README.txt7
-rw-r--r--tools/clang-format/ClangFormat.cpp168
-rwxr-xr-xtools/clang-format/clang-format-diff.py4
-rw-r--r--tools/clang-format/fuzzer/ClangFormatFuzzer.cpp3
-rw-r--r--tools/clang-fuzzer/ClangFuzzer.cpp5
-rw-r--r--tools/diagtool/ShowEnabledWarnings.cpp6
-rw-r--r--tools/driver/CMakeLists.txt53
-rw-r--r--tools/driver/cc1as_main.cpp43
-rw-r--r--tools/driver/clang_symlink.cmake43
-rw-r--r--tools/driver/driver.cpp171
-rw-r--r--tools/libclang/CIndex.cpp586
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp50
-rw-r--r--tools/libclang/CIndexer.h4
-rw-r--r--tools/libclang/CMakeLists.txt17
-rw-r--r--tools/libclang/CXCompilationDatabase.cpp10
-rw-r--r--tools/libclang/CXCursor.cpp24
-rw-r--r--tools/libclang/CXLoadedDiagnostic.cpp7
-rw-r--r--tools/libclang/CXString.cpp17
-rw-r--r--tools/libclang/CXString.h2
-rw-r--r--tools/libclang/CXType.cpp39
-rw-r--r--tools/libclang/CursorVisitor.h1
-rw-r--r--tools/libclang/IndexBody.cpp11
-rw-r--r--tools/libclang/IndexTypeSourceInfo.cpp4
-rw-r--r--tools/libclang/Indexing.cpp180
-rw-r--r--tools/libclang/IndexingContext.cpp5
-rw-r--r--tools/libclang/libclang.exports9
-rw-r--r--tools/scan-build/CMakeLists.txt82
-rw-r--r--tools/scan-build/Makefile53
-rwxr-xr-xtools/scan-build/bin/scan-build (renamed from tools/scan-build/scan-build)739
-rw-r--r--tools/scan-build/bin/scan-build.bat (renamed from tools/scan-build/scan-build.bat)0
-rwxr-xr-xtools/scan-build/bin/set-xcode-analyzer (renamed from tools/scan-build/set-xcode-analyzer)0
-rwxr-xr-xtools/scan-build/libexec/c++-analyzer (renamed from tools/scan-build/c++-analyzer)0
-rw-r--r--tools/scan-build/libexec/c++-analyzer.bat (renamed from tools/scan-build/c++-analyzer.bat)0
-rwxr-xr-xtools/scan-build/libexec/ccc-analyzer (renamed from tools/scan-build/ccc-analyzer)20
-rw-r--r--tools/scan-build/libexec/ccc-analyzer.bat (renamed from tools/scan-build/ccc-analyzer.bat)0
-rw-r--r--tools/scan-build/man/scan-build.1 (renamed from tools/scan-build/scan-build.1)2
-rw-r--r--tools/scan-build/share/scan-build/scanview.css (renamed from tools/scan-build/scanview.css)0
-rw-r--r--tools/scan-build/share/scan-build/sorttable.js (renamed from tools/scan-build/sorttable.js)0
-rw-r--r--tools/scan-view/CMakeLists.txt41
-rw-r--r--tools/scan-view/Makefile37
-rwxr-xr-xtools/scan-view/bin/scan-view143
-rwxr-xr-xtools/scan-view/scan-view131
-rw-r--r--tools/scan-view/share/FileRadar.scpt (renamed from tools/scan-view/Resources/FileRadar.scpt)bin18418 -> 18418 bytes
-rw-r--r--tools/scan-view/share/GetRadarVersion.scpt (renamed from tools/scan-view/Resources/GetRadarVersion.scpt)0
-rw-r--r--tools/scan-view/share/Reporter.py (renamed from tools/scan-view/Reporter.py)4
-rw-r--r--tools/scan-view/share/ScanView.py (renamed from tools/scan-view/ScanView.py)4
-rw-r--r--tools/scan-view/share/bugcatcher.ico (renamed from tools/scan-view/Resources/bugcatcher.ico)bin318 -> 318 bytes
-rw-r--r--tools/scan-view/share/startfile.py (renamed from tools/scan-view/startfile.py)0
54 files changed, 1868 insertions, 1111 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index b2b2f6aa954c7..dba676a1f7561 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,19 +1,23 @@
-add_subdirectory(diagtool)
-add_subdirectory(driver)
-add_subdirectory(clang-format)
-add_subdirectory(clang-format-vs)
-add_subdirectory(clang-fuzzer)
+create_subdirectory_options(CLANG TOOL)
-add_subdirectory(c-index-test)
-add_subdirectory(libclang)
+add_clang_subdirectory(diagtool)
+add_clang_subdirectory(driver)
+add_clang_subdirectory(clang-format)
+add_clang_subdirectory(clang-format-vs)
+add_clang_subdirectory(clang-fuzzer)
+add_clang_subdirectory(scan-build)
+add_clang_subdirectory(scan-view)
+
+add_clang_subdirectory(c-index-test)
+add_clang_subdirectory(libclang)
if(CLANG_ENABLE_ARCMT)
- add_subdirectory(arcmt-test)
- add_subdirectory(c-arcmt-test)
+ add_clang_subdirectory(arcmt-test)
+ add_clang_subdirectory(c-arcmt-test)
endif()
if(CLANG_ENABLE_STATIC_ANALYZER)
- add_subdirectory(clang-check)
+ add_clang_subdirectory(clang-check)
endif()
# We support checking out the clang-tools-extra repository into the 'extra'
diff --git a/tools/Makefile b/tools/Makefile
index 2ee12992f23ff..5c362bfc9aade 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -15,7 +15,7 @@ DIRS :=
PARALLEL_DIRS := clang-format driver diagtool
ifeq ($(ENABLE_CLANG_STATIC_ANALYZER), 1)
- PARALLEL_DIRS += clang-check
+ PARALLEL_DIRS += clang-check scan-build scan-view
endif
ifeq ($(ENABLE_CLANG_ARCMT), 1)
diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt
index d0872fd2eff38..c78a42ffe8eb6 100644
--- a/tools/c-index-test/CMakeLists.txt
+++ b/tools/c-index-test/CMakeLists.txt
@@ -28,3 +28,23 @@ if (CLANG_HAVE_LIBXML)
include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
target_link_libraries(c-index-test ${LIBXML2_LIBRARIES})
endif()
+
+if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
+ if(INTERNAL_INSTALL_PREFIX)
+ set(INSTALL_DESTINATION "${INTERNAL_INSTALL_PREFIX}/bin")
+ else()
+ set(INSTALL_DESTINATION bin)
+ endif()
+
+ install(TARGETS c-index-test
+ RUNTIME DESTINATION "${INSTALL_DESTINATION}"
+ COMPONENT c-index-test)
+
+ if (NOT CMAKE_CONFIGURATION_TYPES) # don't add this for IDE's.
+ add_custom_target(install-c-index-test
+ DEPENDS c-index-test
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=c-index-test
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ endif()
+endif()
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index eeeb832cd8738..48f22eb4bbf65 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -76,7 +76,9 @@ static unsigned getDefaultParsingOptions() {
options |= CXTranslationUnit_SkipFunctionBodies;
if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
-
+ if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE"))
+ options |= CXTranslationUnit_CreatePreambleOnFirstParse;
+
return options;
}
@@ -767,6 +769,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
clang_disposeString(DeprecatedMessage);
clang_disposeString(UnavailableMessage);
+ if (clang_CXXField_isMutable(Cursor))
+ printf(" (mutable)");
if (clang_CXXMethod_isStatic(Cursor))
printf(" (static)");
if (clang_CXXMethod_isVirtual(Cursor))
@@ -1246,6 +1250,32 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
}
/******************************************************************************/
+/* Visibility testing. */
+/******************************************************************************/
+
+static enum CXChildVisitResult PrintVisibility(CXCursor cursor, CXCursor p,
+ CXClientData d) {
+ const char *visibility = 0;
+
+ if (clang_isInvalid(clang_getCursorKind(cursor)))
+ return CXChildVisit_Recurse;
+
+ switch (clang_getCursorVisibility(cursor)) {
+ case CXVisibility_Invalid: break;
+ case CXVisibility_Hidden: visibility = "Hidden"; break;
+ case CXVisibility_Protected: visibility = "Protected"; break;
+ case CXVisibility_Default: visibility = "Default"; break;
+ }
+
+ if (visibility) {
+ PrintCursor(cursor, NULL);
+ printf("visibility=%s\n", visibility);
+ }
+
+ return CXChildVisit_Recurse;
+}
+
+/******************************************************************************/
/* Typekind testing. */
/******************************************************************************/
@@ -1430,6 +1460,8 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p,
static enum CXChildVisitResult PrintMangledName(CXCursor cursor, CXCursor p,
CXClientData d) {
CXString MangledName;
+ if (clang_isUnexposed(clang_getCursorKind(cursor)))
+ return CXChildVisit_Recurse;
PrintCursor(cursor, NULL);
MangledName = clang_Cursor_getMangling(cursor);
printf(" [mangled=%s]\n", clang_getCString(MangledName));
@@ -1437,6 +1469,25 @@ static enum CXChildVisitResult PrintMangledName(CXCursor cursor, CXCursor p,
return CXChildVisit_Continue;
}
+static enum CXChildVisitResult PrintManglings(CXCursor cursor, CXCursor p,
+ CXClientData d) {
+ unsigned I, E;
+ CXStringSet *Manglings = NULL;
+ if (clang_isUnexposed(clang_getCursorKind(cursor)))
+ return CXChildVisit_Recurse;
+ if (!clang_isDeclaration(clang_getCursorKind(cursor)))
+ return CXChildVisit_Recurse;
+ if (clang_getCursorKind(cursor) == CXCursor_ParmDecl)
+ return CXChildVisit_Continue;
+ PrintCursor(cursor, NULL);
+ Manglings = clang_Cursor_getCXXManglings(cursor);
+ for (I = 0, E = Manglings->Count; I < E; ++I)
+ printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I]));
+ clang_disposeStringSet(Manglings);
+ printf("\n");
+ return CXChildVisit_Recurse;
+}
+
/******************************************************************************/
/* Bitwidth testing. */
/******************************************************************************/
@@ -4061,6 +4112,7 @@ static void print_usage(void) {
" c-index-test -test-inclusion-stack-tu <AST file>\n");
fprintf(stderr,
" c-index-test -test-print-linkage-source {<args>}*\n"
+ " c-index-test -test-print-visibility {<args>}*\n"
" c-index-test -test-print-type {<args>}*\n"
" c-index-test -test-print-type-size {<args>}*\n"
" c-index-test -test-print-bitwidth {<args>}*\n"
@@ -4148,6 +4200,9 @@ int cindextest_main(int argc, const char **argv) {
else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage,
NULL);
+ else if (argc > 2 && strcmp(argv[1], "-test-print-visibility") == 0)
+ return perform_test_load_source(argc - 2, argv + 2, "all", PrintVisibility,
+ NULL);
else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintType, 0);
@@ -4159,6 +4214,8 @@ int cindextest_main(int argc, const char **argv) {
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 > 2 && strcmp(argv[1], "-test-print-manglings") == 0)
+ return perform_test_load_tu(argv[2], "all", NULL, PrintManglings, 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-format-vs/ClangFormat/ClangFormatPackage.cs b/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
index c3aa8fecded58..df872b2e21982 100644
--- a/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
+++ b/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
@@ -19,10 +19,10 @@ using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using System;
+using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.IO;
-using System.Reflection;
using System.Runtime.InteropServices;
using System.Xml.Linq;
@@ -32,13 +32,53 @@ namespace LLVM.ClangFormat
[CLSCompliant(false), ComVisible(true)]
public class OptionPageGrid : DialogPage
{
- private string style = "File";
+ private string assumeFilename = "";
+ private string fallbackStyle = "LLVM";
+ private bool sortIncludes = false;
+ private string style = "file";
+
+ public class StyleConverter : TypeConverter
+ {
+ protected ArrayList values;
+ public StyleConverter()
+ {
+ // Initializes the standard values list with defaults.
+ values = new ArrayList(new string[] { "file", "Chromium", "Google", "LLVM", "Mozilla", "WebKit" });
+ }
+
+ public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+ {
+ return true;
+ }
+
+ public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+ {
+ return new StandardValuesCollection(values);
+ }
+
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ if (sourceType == typeof(string))
+ return true;
+
+ return base.CanConvertFrom(context, sourceType);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
+ {
+ string s = value as string;
+ if (s == null)
+ return base.ConvertFrom(context, culture, value);
+
+ return value;
+ }
+ }
[Category("LLVM/Clang")]
[DisplayName("Style")]
[Description("Coding style, currently supports:\n" +
- " - Predefined styles ('LLVM', 'Google', 'Chromium', 'Mozilla').\n" +
- " - 'File' to search for a YAML .clang-format or _clang-format\n" +
+ " - Predefined styles ('LLVM', 'Google', 'Chromium', 'Mozilla', 'WebKit').\n" +
+ " - 'file' to search for a YAML .clang-format or _clang-format\n" +
" configuration file.\n" +
" - A YAML configuration snippet.\n\n" +
"'File':\n" +
@@ -48,11 +88,81 @@ namespace LLVM.ClangFormat
" The content of a .clang-format configuration file, as string.\n" +
" Example: '{BasedOnStyle: \"LLVM\", IndentWidth: 8}'\n\n" +
"See also: http://clang.llvm.org/docs/ClangFormatStyleOptions.html.")]
+ [TypeConverter(typeof(StyleConverter))]
public string Style
{
get { return style; }
set { style = value; }
}
+
+ public sealed class FilenameConverter : TypeConverter
+ {
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ if (sourceType == typeof(string))
+ return true;
+
+ return base.CanConvertFrom(context, sourceType);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
+ {
+ string s = value as string;
+ if (s == null)
+ return base.ConvertFrom(context, culture, value);
+
+ // Check if string contains quotes. On Windows, file names cannot contain quotes.
+ // We do not accept them however to avoid hard-to-debug problems.
+ // A quote in user input would end the parameter quote and so break the command invocation.
+ if (s.IndexOf('\"') != -1)
+ throw new NotSupportedException("Filename cannot contain quotes");
+
+ return value;
+ }
+ }
+
+ [Category("LLVM/Clang")]
+ [DisplayName("Assume Filename")]
+ [Description("When reading from stdin, clang-format assumes this " +
+ "filename to look for a style config file (with 'file' style) " +
+ "and to determine the language.")]
+ [TypeConverter(typeof(FilenameConverter))]
+ public string AssumeFilename
+ {
+ get { return assumeFilename; }
+ set { assumeFilename = value; }
+ }
+
+ public sealed class FallbackStyleConverter : StyleConverter
+ {
+ public FallbackStyleConverter()
+ {
+ // Add "none" to the list of styles.
+ values.Insert(0, "none");
+ }
+ }
+
+ [Category("LLVM/Clang")]
+ [DisplayName("Fallback Style")]
+ [Description("The name of the predefined style used as a fallback in case clang-format " +
+ "is invoked with 'file' style, but can not find the configuration file.\n" +
+ "Use 'none' fallback style to skip formatting.")]
+ [TypeConverter(typeof(FallbackStyleConverter))]
+ public string FallbackStyle
+ {
+ get { return fallbackStyle; }
+ set { fallbackStyle = value; }
+ }
+
+ [Category("LLVM/Clang")]
+ [DisplayName("Sort includes")]
+ [Description("Sort touched include lines.\n\n" +
+ "See also: http://clang.llvm.org/docs/ClangFormat.html.")]
+ public bool SortIncludes
+ {
+ get { return sortIncludes; }
+ set { sortIncludes = value; }
+ }
}
[PackageRegistration(UseManagedResourcesOnly = true)]
@@ -138,10 +248,17 @@ namespace LLVM.ClangFormat
// Poor man's escaping - this will not work when quotes are already escaped
// in the input (but we don't need more).
string style = GetStyle().Replace("\"", "\\\"");
+ string fallbackStyle = GetFallbackStyle().Replace("\"", "\\\"");
process.StartInfo.Arguments = " -offset " + offset +
" -length " + length +
" -output-replacements-xml " +
- " -style \"" + style + "\"";
+ " -style \"" + style + "\"" +
+ " -fallback-style \"" + fallbackStyle + "\"";
+ if (GetSortIncludes())
+ process.StartInfo.Arguments += " -sort-includes ";
+ string assumeFilename = GetAssumeFilename();
+ if (!string.IsNullOrEmpty(assumeFilename))
+ process.StartInfo.Arguments += " -assume-filename \"" + assumeFilename + "\"";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
@@ -211,6 +328,24 @@ namespace LLVM.ClangFormat
return page.Style;
}
+ private string GetAssumeFilename()
+ {
+ var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
+ return page.AssumeFilename;
+ }
+
+ private string GetFallbackStyle()
+ {
+ var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
+ return page.FallbackStyle;
+ }
+
+ private bool GetSortIncludes()
+ {
+ var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
+ return page.SortIncludes;
+ }
+
private string GetDocumentParent(IWpfTextView view)
{
ITextDocument document;
diff --git a/tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs b/tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs
index e6e4de488012a..b1cef49414b5e 100644
--- a/tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs
+++ b/tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.1.0.0")]
+[assembly: AssemblyFileVersion("1.1.0.0")]
diff --git a/tools/clang-format-vs/README.txt b/tools/clang-format-vs/README.txt
index 636b89f3c6736..b23355d0cebcc 100644
--- a/tools/clang-format-vs/README.txt
+++ b/tools/clang-format-vs/README.txt
@@ -2,9 +2,10 @@ This directory contains a VSPackage project to generate a Visual Studio extensio
for clang-format.
Build prerequisites are:
-- Visual Studio 2012 Professional
-- Visual Studio 2010 Professional
-- Visual Studio 2010 SDK.
+- Visual Studio 2013 Professional
+- Visual Studio 2013 SDK
+- Visual Studio 2010 Professional (?)
+- Visual Studio 2010 SDK (?)
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.
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index 5037e901f3b41..36f237fc750c9 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Signals.h"
using namespace llvm;
+using clang::tooling::Replacements;
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
@@ -73,11 +74,11 @@ FallbackStyle("fallback-style",
cl::init("LLVM"), cl::cat(ClangFormatCategory));
static cl::opt<std::string>
-AssumeFilename("assume-filename",
+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) and to determine the language."),
- cl::cat(ClangFormatCategory));
+ cl::init("<stdin>"), cl::cat(ClangFormatCategory));
static cl::opt<bool> Inplace("i",
cl::desc("Inplace edit <file>s, if specified."),
@@ -97,6 +98,12 @@ static cl::opt<unsigned>
"clang-format from an editor integration"),
cl::init(0), cl::cat(ClangFormatCategory));
+static cl::opt<bool> SortIncludes(
+ "sort-includes",
+ cl::desc("If set, overrides the include sorting behavior determined by the "
+ "SortIncludes style flag"),
+ cl::cat(ClangFormatCategory));
+
static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
cl::cat(ClangFormatCategory));
@@ -104,12 +111,11 @@ namespace clang {
namespace format {
static FileID createInMemoryFile(StringRef FileName, MemoryBuffer *Source,
- SourceManager &Sources, FileManager &Files) {
- const FileEntry *Entry = Files.getVirtualFile(FileName == "-" ? "<stdin>" :
- FileName,
- Source->getBufferSize(), 0);
- Sources.overrideFileContents(Entry, Source, true);
- return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
+ SourceManager &Sources, FileManager &Files,
+ vfs::InMemoryFileSystem *MemFS) {
+ MemFS->addFileNoOwn(FileName, 0, Source);
+ return Sources.createFileID(Files.getFile(FileName), SourceLocation(),
+ SrcMgr::C_User);
}
// Parses <start line>:<end line> input to a pair of line numbers.
@@ -121,30 +127,40 @@ static bool parseLineRange(StringRef Input, unsigned &FromLine,
LineRange.second.getAsInteger(0, ToLine);
}
-static bool fillRanges(SourceManager &Sources, FileID ID,
- const MemoryBuffer *Code,
- std::vector<CharSourceRange> &Ranges) {
+static bool fillRanges(MemoryBuffer *Code,
+ std::vector<tooling::Range> &Ranges) {
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ FileManager Files(FileSystemOptions(), InMemoryFileSystem);
+ DiagnosticsEngine Diagnostics(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+ new DiagnosticOptions);
+ SourceManager Sources(Diagnostics, Files);
+ FileID ID = createInMemoryFile("<irrelevant>", Code, Sources, Files,
+ InMemoryFileSystem.get());
if (!LineRanges.empty()) {
if (!Offsets.empty() || !Lengths.empty()) {
- llvm::errs() << "error: cannot use -lines with -offset/-length\n";
+ errs() << "error: cannot use -lines with -offset/-length\n";
return true;
}
for (unsigned i = 0, e = LineRanges.size(); i < e; ++i) {
unsigned FromLine, ToLine;
if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
- llvm::errs() << "error: invalid <start line>:<end line> pair\n";
+ errs() << "error: invalid <start line>:<end line> pair\n";
return true;
}
if (FromLine > ToLine) {
- llvm::errs() << "error: start line should be less than end line\n";
+ errs() << "error: start line should be less than end line\n";
return true;
}
SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
SourceLocation End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
if (Start.isInvalid() || End.isInvalid())
return true;
- Ranges.push_back(CharSourceRange::getCharRange(Start, End));
+ unsigned Offset = Sources.getFileOffset(Start);
+ unsigned Length = Sources.getFileOffset(End) - Offset;
+ Ranges.push_back(tooling::Range(Offset, Length));
}
return false;
}
@@ -153,14 +169,12 @@ static bool fillRanges(SourceManager &Sources, FileID ID,
Offsets.push_back(0);
if (Offsets.size() != Lengths.size() &&
!(Offsets.size() == 1 && Lengths.empty())) {
- llvm::errs()
- << "error: number of -offset and -length arguments must match.\n";
+ errs() << "error: number of -offset and -length arguments must match.\n";
return true;
}
for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
if (Offsets[i] >= Code->getBufferSize()) {
- llvm::errs() << "error: offset " << Offsets[i]
- << " is outside the file\n";
+ errs() << "error: offset " << Offsets[i] << " is outside the file\n";
return true;
}
SourceLocation Start =
@@ -168,97 +182,122 @@ static bool fillRanges(SourceManager &Sources, FileID ID,
SourceLocation End;
if (i < Lengths.size()) {
if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
- llvm::errs() << "error: invalid length " << Lengths[i]
- << ", offset + length (" << Offsets[i] + Lengths[i]
- << ") is outside the file.\n";
+ errs() << "error: invalid length " << Lengths[i]
+ << ", offset + length (" << Offsets[i] + Lengths[i]
+ << ") is outside the file.\n";
return true;
}
End = Start.getLocWithOffset(Lengths[i]);
} else {
End = Sources.getLocForEndOfFile(ID);
}
- Ranges.push_back(CharSourceRange::getCharRange(Start, End));
+ unsigned Offset = Sources.getFileOffset(Start);
+ unsigned Length = Sources.getFileOffset(End) - Offset;
+ Ranges.push_back(tooling::Range(Offset, Length));
}
return false;
}
static void outputReplacementXML(StringRef Text) {
+ // FIXME: When we sort includes, we need to make sure the stream is correct
+ // utf-8.
size_t From = 0;
size_t Index;
- while ((Index = Text.find_first_of("\n\r", From)) != StringRef::npos) {
- llvm::outs() << Text.substr(From, Index - From);
+ while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) {
+ outs() << Text.substr(From, Index - From);
switch (Text[Index]) {
case '\n':
- llvm::outs() << "&#10;";
+ outs() << "&#10;";
break;
case '\r':
- llvm::outs() << "&#13;";
+ outs() << "&#13;";
+ break;
+ case '<':
+ outs() << "&lt;";
+ break;
+ case '&':
+ outs() << "&amp;";
break;
default:
llvm_unreachable("Unexpected character encountered!");
}
From = Index + 1;
}
- llvm::outs() << Text.substr(From);
+ outs() << Text.substr(From);
+}
+
+static void outputReplacementsXML(const Replacements &Replaces) {
+ for (const auto &R : Replaces) {
+ outs() << "<replacement "
+ << "offset='" << R.getOffset() << "' "
+ << "length='" << R.getLength() << "'>";
+ outputReplacementXML(R.getReplacementText());
+ outs() << "</replacement>\n";
+ }
}
// Returns true on error.
static bool format(StringRef FileName) {
- FileManager Files((FileSystemOptions()));
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
- new DiagnosticOptions);
- SourceManager Sources(Diagnostics, Files);
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
MemoryBuffer::getFileOrSTDIN(FileName);
if (std::error_code EC = CodeOrErr.getError()) {
- llvm::errs() << EC.message() << "\n";
+ errs() << EC.message() << "\n";
return true;
}
std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
if (Code->getBufferSize() == 0)
return false; // Empty files are formatted correctly.
- FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
- std::vector<CharSourceRange> Ranges;
- if (fillRanges(Sources, ID, Code.get(), Ranges))
+ std::vector<tooling::Range> Ranges;
+ if (fillRanges(Code.get(), Ranges))
return true;
+ StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName;
+ FormatStyle FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle);
+ if (SortIncludes.getNumOccurrences() != 0)
+ FormatStyle.SortIncludes = SortIncludes;
+ unsigned CursorPosition = Cursor;
+ Replacements Replaces = sortIncludes(FormatStyle, Code->getBuffer(), Ranges,
+ AssumedFileName, &CursorPosition);
+ std::string ChangedCode =
+ tooling::applyAllReplacements(Code->getBuffer(), Replaces);
+ for (const auto &R : Replaces)
+ Ranges.push_back({R.getOffset(), R.getLength()});
- FormatStyle FormatStyle = getStyle(
- Style, (FileName == "-") ? AssumeFilename : FileName, FallbackStyle);
bool IncompleteFormat = false;
- tooling::Replacements Replaces =
- reformat(FormatStyle, Sources, ID, Ranges, &IncompleteFormat);
+ Replacements FormatChanges = reformat(FormatStyle, ChangedCode, Ranges,
+ AssumedFileName, &IncompleteFormat);
+ Replaces = tooling::mergeReplacements(Replaces, FormatChanges);
if (OutputXML) {
- llvm::outs() << "<?xml version='1.0'?>\n<replacements "
- "xml:space='preserve' incomplete_format='"
- << (IncompleteFormat ? "true" : "false") << "'>\n";
+ outs() << "<?xml version='1.0'?>\n<replacements "
+ "xml:space='preserve' incomplete_format='"
+ << (IncompleteFormat ? "true" : "false") << "'>\n";
if (Cursor.getNumOccurrences() != 0)
- llvm::outs() << "<cursor>"
- << tooling::shiftedCodePosition(Replaces, Cursor)
- << "</cursor>\n";
+ outs() << "<cursor>"
+ << tooling::shiftedCodePosition(FormatChanges, CursorPosition)
+ << "</cursor>\n";
- for (tooling::Replacements::const_iterator I = Replaces.begin(),
- E = Replaces.end();
- I != E; ++I) {
- llvm::outs() << "<replacement "
- << "offset='" << I->getOffset() << "' "
- << "length='" << I->getLength() << "'>";
- outputReplacementXML(I->getReplacementText());
- llvm::outs() << "</replacement>\n";
- }
- llvm::outs() << "</replacements>\n";
+ outputReplacementsXML(Replaces);
+ outs() << "</replacements>\n";
} else {
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ FileManager Files(FileSystemOptions(), InMemoryFileSystem);
+ DiagnosticsEngine Diagnostics(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+ new DiagnosticOptions);
+ SourceManager Sources(Diagnostics, Files);
+ FileID ID = createInMemoryFile(AssumedFileName, Code.get(), Sources, Files,
+ InMemoryFileSystem.get());
Rewriter Rewrite(Sources, LangOptions());
tooling::applyAllReplacements(Replaces, Rewrite);
if (Inplace) {
if (FileName == "-")
- llvm::errs() << "error: cannot use -i when reading from stdin.\n";
+ errs() << "error: cannot use -i when reading from stdin.\n";
else if (Rewrite.overwriteChangedFiles())
return true;
} else {
if (Cursor.getNumOccurrences() != 0)
outs() << "{ \"Cursor\": "
- << tooling::shiftedCodePosition(Replaces, Cursor)
+ << tooling::shiftedCodePosition(FormatChanges, CursorPosition)
<< ", \"IncompleteFormat\": "
<< (IncompleteFormat ? "true" : "false") << " }\n";
Rewrite.getEditBuffer(ID).write(outs());
@@ -283,7 +322,7 @@ int main(int argc, const char **argv) {
cl::SetVersionPrinter(PrintVersion);
cl::ParseCommandLineOptions(
argc, argv,
- "A tool to format C/C++/Obj-C code.\n\n"
+ "A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf code.\n\n"
"If no arguments are specified, it formats the code from standard input\n"
"and writes the result to the standard output.\n"
"If <file>s are given, it reformats the files. If -i is specified\n"
@@ -296,9 +335,9 @@ int main(int argc, const char **argv) {
if (DumpConfig) {
std::string Config =
clang::format::configurationAsText(clang::format::getStyle(
- Style, FileNames.empty() ? AssumeFilename : FileNames[0],
+ Style, FileNames.empty() ? AssumeFileName : FileNames[0],
FallbackStyle));
- llvm::outs() << Config << "\n";
+ outs() << Config << "\n";
return 0;
}
@@ -312,8 +351,8 @@ int main(int argc, const char **argv) {
break;
default:
if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) {
- llvm::errs() << "error: -offset, -length and -lines can only be used for "
- "single file.\n";
+ errs() << "error: -offset, -length and -lines can only be used for "
+ "single file.\n";
return 1;
}
for (unsigned i = 0; i < FileNames.size(); ++i)
@@ -322,3 +361,4 @@ int main(int argc, const char **argv) {
}
return Error ? 1 : 0;
}
+
diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py
index 64efb83a8c19e..9e02bb09387f8 100755
--- a/tools/clang-format/clang-format-diff.py
+++ b/tools/clang-format/clang-format-diff.py
@@ -52,6 +52,8 @@ def main():
r'|protodevel|java)',
help='custom pattern selecting file paths to reformat '
'(case insensitive, overridden by -regex)')
+ parser.add_argument('-sort-includes', action='store_true', default=False,
+ help='let clang-format sort include blocks')
parser.add_argument('-v', '--verbose', action='store_true',
help='be more verbose, ineffective without -i')
parser.add_argument(
@@ -96,6 +98,8 @@ def main():
command = [binary, filename]
if args.i:
command.append('-i')
+ if args.sort_includes:
+ command.append('-sort-includes')
command.extend(lines)
if args.style:
command.extend(['-style', args.style])
diff --git a/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp b/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp
index fe4941a5ba1a0..5334ce873eca4 100644
--- a/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp
+++ b/tools/clang-format/fuzzer/ClangFormatFuzzer.cpp
@@ -15,11 +15,12 @@
#include "clang/Format/Format.h"
-extern "C" void LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
// FIXME: fuzz more things: different styles, different style features.
std::string s((const char *)data, size);
auto Style = getGoogleStyle(clang::format::FormatStyle::LK_Cpp);
Style.ColumnLimit = 60;
applyAllReplacements(s, clang::format::reformat(
Style, s, {clang::tooling::Range(0, s.size())}));
+ return 0;
}
diff --git a/tools/clang-fuzzer/ClangFuzzer.cpp b/tools/clang-fuzzer/ClangFuzzer.cpp
index 124911cd4a54d..d07cf5027b2a5 100644
--- a/tools/clang-fuzzer/ClangFuzzer.cpp
+++ b/tools/clang-fuzzer/ClangFuzzer.cpp
@@ -20,7 +20,7 @@
using namespace clang;
-extern "C" void LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
std::string s((const char *)data, size);
llvm::opt::ArgStringList CC1Args;
CC1Args.push_back("-cc1");
@@ -40,7 +40,8 @@ extern "C" void LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
std::unique_ptr<tooling::ToolAction> action(
tooling::newFrontendActionFactory<clang::SyntaxOnlyAction>());
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
- std::make_shared<RawPCHContainerOperations>();
+ std::make_shared<PCHContainerOperations>();
action->runInvocation(Invocation.release(), Files.get(), PCHContainerOps,
&Diags);
+ return 0;
}
diff --git a/tools/diagtool/ShowEnabledWarnings.cpp b/tools/diagtool/ShowEnabledWarnings.cpp
index 06f74320b7fc5..abbd3afbd58c6 100644
--- a/tools/diagtool/ShowEnabledWarnings.cpp
+++ b/tools/diagtool/ShowEnabledWarnings.cpp
@@ -64,9 +64,11 @@ createDiagnostics(unsigned int argc, char **argv) {
new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
// Try to build a CompilerInvocation.
+ SmallVector<const char *, 4> Args;
+ Args.push_back("diagtool");
+ Args.append(argv, argv + argc);
std::unique_ptr<CompilerInvocation> Invocation(
- createInvocationFromCommandLine(llvm::makeArrayRef(argv, argc),
- InterimDiags));
+ createInvocationFromCommandLine(Args, InterimDiags));
if (!Invocation)
return nullptr;
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 3f1ed40abe4d7..fca9b616751ba 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -3,7 +3,6 @@ set( LLVM_LINK_COMPONENTS
Analysis
CodeGen
Core
- IPA
IPO
InstCombine
Instrumentation
@@ -52,38 +51,29 @@ endif()
add_dependencies(clang clang-headers)
-if(UNIX)
- set(CLANGXX_LINK_OR_COPY create_symlink)
-# Create a relative symlink
- set(clang_binary "clang${CMAKE_EXECUTABLE_SUFFIX}")
-else()
- set(CLANGXX_LINK_OR_COPY copy)
- set(clang_binary "${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX}")
-endif()
-
-# Create the clang++ symlink in the build directory.
-set(clang_pp "${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}")
-add_custom_command(TARGET clang POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E ${CLANGXX_LINK_OR_COPY} "${clang_binary}" "${clang_pp}"
- WORKING_DIRECTORY "${LLVM_RUNTIME_OUTPUT_INTDIR}")
-
-set_property(DIRECTORY APPEND
- PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${clang_pp})
+install(TARGETS clang
+ RUNTIME DESTINATION bin
+ COMPONENT clang)
-# Create the clang-cl symlink in the build directory.
-set(clang_cl "${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}")
-add_custom_command(TARGET clang POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E ${CLANGXX_LINK_OR_COPY} "${clang_binary}" "${clang_cl}"
- WORKING_DIRECTORY "${LLVM_RUNTIME_OUTPUT_INTDIR}")
+if(NOT CMAKE_CONFIGURATION_TYPES)
+ add_custom_target(install-clang
+ DEPENDS clang
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=clang
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+endif()
-set_property(DIRECTORY APPEND
- PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${clang_cl})
+if(NOT CLANG_LINKS_TO_CREATE)
+ set(CLANG_LINKS_TO_CREATE clang++ clang-cl)
-install(TARGETS clang
- RUNTIME DESTINATION bin)
+ if (WIN32)
+ list(APPEND CLANG_LINKS_TO_CREATE ../msbuild-bin/cl)
+ endif()
+endif()
-# Create the clang++ and clang-cl symlinks at installation time.
-install(SCRIPT clang_symlink.cmake -DCMAKE_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\")
+foreach(link ${CLANG_LINKS_TO_CREATE})
+ add_clang_symlink(${link} clang)
+endforeach()
# Configure plist creation for OS X.
set (TOOL_INFO_PLIST "Info.plist" CACHE STRING "Plist name")
@@ -96,10 +86,7 @@ if (APPLE)
set(TOOL_INFO_UTI "${CLANG_VENDOR_UTI}")
set(TOOL_INFO_VERSION "${CLANG_VERSION}")
- if (LLVM_SUBMIT_VERSION)
- set(TOOL_INFO_BUILD_VERSION
- "${LLVM_SUBMIT_VERSION}.${LLVM_SUBMIT_SUBVERSION}")
- endif()
+ set(TOOL_INFO_BUILD_VERSION "${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}")
set(TOOL_INFO_PLIST_OUT "${CMAKE_CURRENT_BINARY_DIR}/${TOOL_INFO_PLIST}")
target_link_libraries(clang
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index fd0fbb4c5a26b..59b7af521743b 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -125,6 +125,10 @@ struct AssemblerInvocation {
unsigned RelaxAll : 1;
unsigned NoExecStack : 1;
unsigned FatalWarnings : 1;
+ unsigned IncrementalLinkerCompatible : 1;
+
+ /// The name of the relocation model to use.
+ std::string RelocationModel;
/// @}
@@ -141,7 +145,8 @@ public:
RelaxAll = 0;
NoExecStack = 0;
FatalWarnings = 0;
- DwarfVersion = 3;
+ IncrementalLinkerCompatible = 0;
+ DwarfVersion = 0;
}
static bool CreateFromArgs(AssemblerInvocation &Res,
@@ -192,14 +197,10 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.IncludePaths = Args.getAllArgValues(OPT_I);
Opts.NoInitialTextSection = Args.hasArg(OPT_n);
Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
- Opts.GenDwarfForAssembly = Args.hasArg(OPT_g_Flag);
+ // Any DebugInfoKind implies GenDwarfForAssembly.
+ Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
- if (Args.hasArg(OPT_gdwarf_2))
- Opts.DwarfVersion = 2;
- if (Args.hasArg(OPT_gdwarf_3))
- Opts.DwarfVersion = 3;
- if (Args.hasArg(OPT_gdwarf_4))
- Opts.DwarfVersion = 4;
+ Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
@@ -248,6 +249,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
+ Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
+ Opts.IncrementalLinkerCompatible =
+ Args.hasArg(OPT_mincremental_linker_compatible);
return Success;
}
@@ -321,8 +325,19 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
- // FIXME: Assembler behavior can change with -static.
- MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), Reloc::Default,
+
+ llvm::Reloc::Model RM = llvm::Reloc::Default;
+ if (Opts.RelocationModel == "static") {
+ RM = llvm::Reloc::Static;
+ } else if (Opts.RelocationModel == "pic") {
+ RM = llvm::Reloc::PIC_;
+ } else {
+ assert(Opts.RelocationModel == "dynamic-no-pic" &&
+ "Invalid PIC model!");
+ RM = llvm::Reloc::DynamicNoPIC;
+ }
+
+ MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), RM,
CodeModel::Default, Ctx);
if (Opts.SaveTemporaryLabels)
Ctx.setAllowTemporaryLabels(false);
@@ -383,9 +398,10 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
Opts.CPU);
Triple T(Opts.Triple);
- Str.reset(TheTarget->createMCObjectStreamer(T, Ctx, *MAB, *Out, CE, *STI,
- Opts.RelaxAll,
- /*DWARFMustBeAtTheEnd*/ true));
+ Str.reset(TheTarget->createMCObjectStreamer(
+ T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll,
+ Opts.IncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
}
@@ -496,4 +512,3 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
return !!Failed;
}
-
diff --git a/tools/driver/clang_symlink.cmake b/tools/driver/clang_symlink.cmake
deleted file mode 100644
index c01259543c90a..0000000000000
--- a/tools/driver/clang_symlink.cmake
+++ /dev/null
@@ -1,43 +0,0 @@
-# We need to execute this script at installation time because the
-# DESTDIR environment variable may be unset at configuration time.
-# See PR8397.
-
-if(UNIX)
- set(CLANGXX_LINK_OR_COPY create_symlink)
- set(CLANGXX_DESTDIR $ENV{DESTDIR})
-else()
- set(CLANGXX_LINK_OR_COPY copy)
-endif()
-
-# CMAKE_EXECUTABLE_SUFFIX is undefined on cmake scripts. See PR9286.
-if( WIN32 )
- set(EXECUTABLE_SUFFIX ".exe")
-else()
- set(EXECUTABLE_SUFFIX "")
-endif()
-
-set(bindir "${CLANGXX_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/")
-set(clang "clang${EXECUTABLE_SUFFIX}")
-set(clangxx "clang++${EXECUTABLE_SUFFIX}")
-set(clang_cl "clang-cl${EXECUTABLE_SUFFIX}")
-set(cl "cl${EXECUTABLE_SUFFIX}")
-
-message("Creating clang++ executable based on ${clang}")
-
-execute_process(
- COMMAND "${CMAKE_COMMAND}" -E ${CLANGXX_LINK_OR_COPY} "${clang}" "${clangxx}"
- WORKING_DIRECTORY "${bindir}")
-
-message("Creating clang-cl executable based on ${clang}")
-
-execute_process(
- COMMAND "${CMAKE_COMMAND}" -E ${CLANGXX_LINK_OR_COPY} "${clang}" "${clang_cl}"
- WORKING_DIRECTORY "${bindir}")
-
-if (WIN32)
- message("Creating cl executable based on ${clang}")
-
- execute_process(
- COMMAND "${CMAKE_COMMAND}" -E ${CLANGXX_LINK_OR_COPY} "${clang}" "../msbuild-bin/${cl}"
- WORKING_DIRECTORY "${bindir}")
-endif()
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 5925447841fc2..ea218d5403d83 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -18,6 +18,7 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ChainedDiagnosticConsumer.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
@@ -44,7 +45,6 @@
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
@@ -201,94 +201,33 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
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) {
- // 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.
- ProgName = StringRef(ProgName).lower();
-#endif
-
- StringRef ProgNameRef = ProgName;
- const DriverSuffix *DS = FindDriverSuffix(ProgNameRef);
-
- if (!DS) {
- // Try again after stripping any trailing version number:
- // clang++3.5 -> clang++
- ProgNameRef = ProgNameRef.rtrim("0123456789.");
- DS = FindDriverSuffix(ProgNameRef);
+static void insertTargetAndModeArgs(StringRef Target, StringRef Mode,
+ SmallVectorImpl<const char *> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ if (!Mode.empty()) {
+ // Add the mode flag to the arguments.
+ auto it = ArgVector.begin();
+ if (it != ArgVector.end())
+ ++it;
+ ArgVector.insert(it, GetStableCStr(SavedStrings, Mode));
}
- if (!DS) {
- // Try again after stripping trailing -component.
- // clang++-tot -> clang++
- ProgNameRef = ProgNameRef.slice(0, ProgNameRef.rfind('-'));
- DS = FindDriverSuffix(ProgNameRef);
+ if (!Target.empty()) {
+ auto it = ArgVector.begin();
+ if (it != ArgVector.end())
+ ++it;
+ const char *arr[] = {"-target", GetStableCStr(SavedStrings, Target)};
+ ArgVector.insert(it, std::begin(arr), std::end(arr));
}
+}
- 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));
- }
- }
+static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
+ SmallVectorImpl<const char *> &Opts) {
+ llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts);
+ // The first instance of '#' should be replaced with '=' in each option.
+ for (const char *Opt : Opts)
+ if (char *NumberSignPtr = const_cast<char *>(::strchr(Opt, '#')))
+ *NumberSignPtr = '=';
}
static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
@@ -335,7 +274,7 @@ CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) {
}
static void SetInstallDir(SmallVectorImpl<const char *> &argv,
- Driver &TheDriver) {
+ Driver &TheDriver, bool CanonicalPrefixes) {
// 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.
@@ -346,7 +285,11 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv,
if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName(
llvm::sys::path::filename(InstalledPath.str())))
InstalledPath = *Tmp;
- llvm::sys::fs::make_absolute(InstalledPath);
+
+ // FIXME: We don't actually canonicalize this, we just make it absolute.
+ if (CanonicalPrefixes)
+ llvm::sys::fs::make_absolute(InstalledPath);
+
InstalledPath = llvm::sys::path::parent_path(InstalledPath);
if (llvm::sys::fs::exists(InstalledPath.c_str()))
TheDriver.setInstalledDir(InstalledPath);
@@ -380,16 +323,35 @@ int main(int argc_, const char **argv_) {
return 1;
}
+ llvm::InitializeAllTargets();
+ std::string ProgName = argv[0];
+ std::pair<std::string, std::string> TargetAndMode =
+ ToolChain::getTargetAndModeFromProgramName(ProgName);
+
llvm::BumpPtrAllocator A;
- llvm::BumpPtrStringSaver Saver(A);
+ llvm::StringSaver Saver(A);
+
+ // Parse response files using the GNU syntax, unless we're in CL mode. There
+ // are two ways to put clang in CL compatibility mode: argv[0] is either
+ // clang-cl or cl, or --driver-mode=cl is on the command line. The normal
+ // command line parsing can't happen until after response file parsing, so we
+ // have to manually search for a --driver-mode=cl argument the hard way.
+ // Finally, our -cc1 tools don't care which tokenization mode we use because
+ // response files written by clang will tokenize the same way in either mode.
+ llvm::cl::TokenizerCallback Tokenizer = &llvm::cl::TokenizeGNUCommandLine;
+ if (TargetAndMode.second == "--driver-mode=cl" ||
+ std::find_if(argv.begin(), argv.end(), [](const char *F) {
+ return F && strcmp(F, "--driver-mode=cl") == 0;
+ }) != argv.end()) {
+ Tokenizer = &llvm::cl::TokenizeWindowsCommandLine;
+ }
// 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);
+ llvm::cl::ExpandResponseFiles(Saver, Tokenizer, argv, MarkEOLs);
// Handle -cc1 integrated tools, even if -cc1 was expanded from a response
// file.
@@ -415,6 +377,29 @@ int main(int argc_, const char **argv_) {
}
}
+ // Handle CL and _CL_ which permits additional command line options to be
+ // prepended or appended.
+ if (Tokenizer == &llvm::cl::TokenizeWindowsCommandLine) {
+ // Arguments in "CL" are prepended.
+ llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
+ if (OptCL.hasValue()) {
+ SmallVector<const char *, 8> PrependedOpts;
+ getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts);
+
+ // Insert right after the program name to prepend to the argument list.
+ argv.insert(argv.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());
+ }
+ // Arguments in "_CL_" are appended.
+ llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");
+ if (Opt_CL_.hasValue()) {
+ SmallVector<const char *, 8> AppendedOpts;
+ getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts);
+
+ // Insert at the end of the argument list to append.
+ argv.append(AppendedOpts.begin(), AppendedOpts.end());
+ }
+ }
+
std::set<std::string> SavedStrings;
// Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the
// scenes.
@@ -447,10 +432,10 @@ int main(int argc_, const char **argv_) {
ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
- SetInstallDir(argv, TheDriver);
+ SetInstallDir(argv, TheDriver, CanonicalPrefixes);
- llvm::InitializeAllTargets();
- ParseProgName(argv, SavedStrings);
+ insertTargetAndModeArgs(TargetAndMode.first, TargetAndMode.second, argv,
+ SavedStrings);
SetBackdoorDriverOutputsFromEnvVars(TheDriver);
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 8225a6c44293e..dbda13c23532d 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -29,7 +29,6 @@
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
-#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
@@ -148,7 +147,7 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
SourceLocation EndLoc = R.getEnd();
if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc))
EndLoc = SM.getExpansionRange(EndLoc).second;
- if (R.isTokenRange() && !EndLoc.isInvalid()) {
+ if (R.isTokenRange() && EndLoc.isValid()) {
unsigned Length = Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc),
SM, LangOpts);
EndLoc = EndLoc.getLocWithOffset(Length);
@@ -665,6 +664,13 @@ bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
llvm_unreachable("Translation units are visited directly by Visit()");
}
+bool CursorVisitor::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return Visit(MakeCXCursor(D->getTemplatedDecl(), TU, RegionOfInterest));
+}
+
bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
return Visit(TSInfo->getTypeLoc());
@@ -711,11 +717,8 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl(
return true;
}
}
-
- if (ShouldVisitBody && VisitCXXRecordDecl(D))
- return true;
-
- return false;
+
+ return ShouldVisitBody && VisitCXXRecordDecl(D);
}
bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
@@ -940,11 +943,8 @@ bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
return true;
}
- if (ND->isThisDeclarationADefinition() &&
- Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
- return true;
-
- return false;
+ return ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest));
}
template <typename DeclIt>
@@ -1461,9 +1461,19 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
#define BUILTIN_TYPE(Id, SingletonId)
#define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
#define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
@@ -1514,10 +1524,7 @@ bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
}
bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
- return true;
-
- return false;
+ return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
@@ -1635,10 +1642,7 @@ bool CursorVisitor::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
}
bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
- if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
- return true;
-
- return false;
+ return VisitNestedNameSpecifierLoc(TL.getQualifierLoc());
}
bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
@@ -1745,13 +1749,27 @@ DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
-DEF_JOB(ExplicitTemplateArgsVisit, ASTTemplateArgumentListInfo,
- ExplicitTemplateArgsVisitKind)
DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind)
DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind)
#undef DEF_JOB
+class ExplicitTemplateArgsVisit : public VisitorJob {
+public:
+ ExplicitTemplateArgsVisit(const TemplateArgumentLoc *Begin,
+ const TemplateArgumentLoc *End, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::ExplicitTemplateArgsVisitKind, Begin,
+ End) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == ExplicitTemplateArgsVisitKind;
+ }
+ const TemplateArgumentLoc *begin() const {
+ return static_cast<const TemplateArgumentLoc *>(data[0]);
+ }
+ const TemplateArgumentLoc *end() {
+ return static_cast<const TemplateArgumentLoc *>(data[1]);
+ }
+};
class DeclVisit : public VisitorJob {
public:
DeclVisit(const Decl *D, CXCursor parent, bool isFirst) :
@@ -1930,12 +1948,17 @@ public:
void VisitOMPOrderedDirective(const OMPOrderedDirective *D);
void VisitOMPAtomicDirective(const OMPAtomicDirective *D);
void VisitOMPTargetDirective(const OMPTargetDirective *D);
+ void VisitOMPTargetDataDirective(const OMPTargetDataDirective *D);
void VisitOMPTeamsDirective(const OMPTeamsDirective *D);
+ void VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D);
+ void VisitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective *D);
+ void VisitOMPDistributeDirective(const OMPDistributeDirective *D);
private:
void AddDeclarationNameInfo(const Stmt *S);
void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
- void AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A);
+ void AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
+ unsigned NumTemplateArgs);
void AddMemberRef(const FieldDecl *D, SourceLocation L);
void AddStmt(const Stmt *S);
void AddDecl(const Decl *D, bool isFirst = true);
@@ -1965,10 +1988,9 @@ void EnqueueVisitor::AddDecl(const Decl *D, bool isFirst) {
if (D)
WL.push_back(DeclVisit(D, Parent, isFirst));
}
-void EnqueueVisitor::
- AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A) {
- if (A)
- WL.push_back(ExplicitTemplateArgsVisit(A, Parent));
+void EnqueueVisitor::AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
+ unsigned NumTemplateArgs) {
+ WL.push_back(ExplicitTemplateArgsVisit(A, A + NumTemplateArgs, Parent));
}
void EnqueueVisitor::AddMemberRef(const FieldDecl *D, SourceLocation L) {
if (D)
@@ -2019,6 +2041,10 @@ void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
Visitor->AddStmt(C->getSafelen());
}
+void OMPClauseEnqueue::VisitOMPSimdlenClause(const OMPSimdlenClause *C) {
+ Visitor->AddStmt(C->getSimdlen());
+}
+
void OMPClauseEnqueue::VisitOMPCollapseClause(const OMPCollapseClause *C) {
Visitor->AddStmt(C->getNumForLoops());
}
@@ -2032,7 +2058,9 @@ void OMPClauseEnqueue::VisitOMPScheduleClause(const OMPScheduleClause *C) {
Visitor->AddStmt(C->getHelperChunkSize());
}
-void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *) {}
+void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *C) {
+ Visitor->AddStmt(C->getNumForLoops());
+}
void OMPClauseEnqueue::VisitOMPNowaitClause(const OMPNowaitClause *) {}
@@ -2050,6 +2078,40 @@ void OMPClauseEnqueue::VisitOMPCaptureClause(const OMPCaptureClause *) {}
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {}
+
+void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}
+
+void OMPClauseEnqueue::VisitOMPNogroupClause(const OMPNogroupClause *) {}
+
+void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
+ Visitor->AddStmt(C->getDevice());
+}
+
+void OMPClauseEnqueue::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) {
+ Visitor->AddStmt(C->getNumTeams());
+}
+
+void OMPClauseEnqueue::VisitOMPThreadLimitClause(const OMPThreadLimitClause *C) {
+ Visitor->AddStmt(C->getThreadLimit());
+}
+
+void OMPClauseEnqueue::VisitOMPPriorityClause(const OMPPriorityClause *C) {
+ Visitor->AddStmt(C->getPriority());
+}
+
+void OMPClauseEnqueue::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
+ Visitor->AddStmt(C->getGrainsize());
+}
+
+void OMPClauseEnqueue::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
+ Visitor->AddStmt(C->getNumTasks());
+}
+
+void OMPClauseEnqueue::VisitOMPHintClause(const OMPHintClause *C) {
+ Visitor->AddStmt(C->getHint());
+}
+
template<typename T>
void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
for (const auto *I : Node->varlists()) {
@@ -2088,6 +2150,9 @@ void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
}
void OMPClauseEnqueue::VisitOMPReductionClause(const OMPReductionClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->privates()) {
+ Visitor->AddStmt(E);
+ }
for (auto *E : C->lhs_exprs()) {
Visitor->AddStmt(E);
}
@@ -2100,6 +2165,9 @@ void OMPClauseEnqueue::VisitOMPReductionClause(const OMPReductionClause *C) {
}
void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
+ for (const auto *E : C->privates()) {
+ Visitor->AddStmt(E);
+ }
for (const auto *E : C->inits()) {
Visitor->AddStmt(E);
}
@@ -2147,6 +2215,9 @@ void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) {
void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseEnqueue::VisitOMPMapClause(const OMPMapClause *C) {
+ VisitOMPClauseList(C);
+}
}
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
@@ -2171,10 +2242,8 @@ void EnqueueVisitor::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
AddTypeLoc(E->getTypeSourceInfo());
}
void EnqueueVisitor::VisitCompoundStmt(const CompoundStmt *S) {
- for (CompoundStmt::const_reverse_body_iterator I = S->body_rbegin(),
- E = S->body_rend(); I != E; ++I) {
- AddStmt(*I);
- }
+ for (auto &I : llvm::reverse(S->body()))
+ AddStmt(I);
}
void EnqueueVisitor::
VisitMSDependentExistsStmt(const MSDependentExistsStmt *S) {
@@ -2186,7 +2255,8 @@ VisitMSDependentExistsStmt(const MSDependentExistsStmt *S) {
void EnqueueVisitor::
VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) {
- AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
AddDeclarationNameInfo(E);
if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
AddNestedNameSpecifierLoc(QualifierLoc);
@@ -2261,14 +2331,14 @@ void EnqueueVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
}
void EnqueueVisitor::VisitDeclRefExpr(const DeclRefExpr *DR) {
- if (DR->hasExplicitTemplateArgs()) {
- AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs());
- }
+ if (DR->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(DR->getTemplateArgs(), DR->getNumTemplateArgs());
WL.push_back(DeclRefExprParts(DR, Parent));
}
void EnqueueVisitor::VisitDependentScopeDeclRefExpr(
const DependentScopeDeclRefExpr *E) {
- AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
AddDeclarationNameInfo(E);
AddNestedNameSpecifierLoc(E->getQualifierLoc());
}
@@ -2364,7 +2434,6 @@ void EnqueueVisitor::VisitObjCMessageExpr(const ObjCMessageExpr *M) {
void EnqueueVisitor::VisitOffsetOfExpr(const OffsetOfExpr *E) {
// Visit the components of the offsetof expression.
for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
- typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
const OffsetOfNode &Node = E->getComponent(I-1);
switch (Node.getKind()) {
case OffsetOfNode::Array:
@@ -2382,7 +2451,8 @@ void EnqueueVisitor::VisitOffsetOfExpr(const OffsetOfExpr *E) {
AddTypeLoc(E->getTypeSourceInfo());
}
void EnqueueVisitor::VisitOverloadExpr(const OverloadExpr *E) {
- AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
WL.push_back(OverloadExprParts(E, Parent));
}
void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
@@ -2549,6 +2619,11 @@ void EnqueueVisitor::VisitOMPTargetDirective(const OMPTargetDirective *D) {
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPTargetDataDirective(const
+ OMPTargetDataDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
void EnqueueVisitor::VisitOMPTeamsDirective(const OMPTeamsDirective *D) {
VisitOMPExecutableDirective(D);
}
@@ -2562,6 +2637,20 @@ void EnqueueVisitor::VisitOMPCancelDirective(const OMPCancelDirective *D) {
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskLoopSimdDirective(
+ const OMPTaskLoopSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPDistributeDirective(
+ const OMPDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
}
@@ -2597,12 +2686,9 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
continue;
}
case VisitorJob::ExplicitTemplateArgsVisitKind: {
- const ASTTemplateArgumentListInfo *ArgList =
- cast<ExplicitTemplateArgsVisit>(&LI)->get();
- for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
- *ArgEnd = Arg + ArgList->NumTemplateArgs;
- Arg != ArgEnd; ++Arg) {
- if (VisitTemplateArgumentLoc(*Arg))
+ for (const TemplateArgumentLoc &Arg :
+ *cast<ExplicitTemplateArgsVisit>(&LI)) {
+ if (VisitTemplateArgumentLoc(Arg))
return true;
}
continue;
@@ -2804,10 +2890,9 @@ bool CursorVisitor::Visit(const Stmt *S) {
namespace {
typedef SmallVector<SourceRange, 4> RefNamePieces;
-RefNamePieces
-buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
- const DeclarationNameInfo &NI, const SourceRange &QLoc,
- const ASTTemplateArgumentListInfo *TemplateArgs = nullptr) {
+RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
+ const DeclarationNameInfo &NI, SourceRange QLoc,
+ const SourceRange *TemplateArgsLoc = nullptr) {
const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;
const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;
const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;
@@ -2821,11 +2906,10 @@ buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)
Pieces.push_back(NI.getLoc());
-
- if (WantTemplateArgs && TemplateArgs)
- Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc,
- TemplateArgs->RAngleLoc));
-
+
+ if (WantTemplateArgs && TemplateArgsLoc && TemplateArgsLoc->isValid())
+ Pieces.push_back(*TemplateArgsLoc);
+
if (Kind == DeclarationName::CXXOperatorName) {
Pieces.push_back(SourceLocation::getFromRawEncoding(
NI.getInfo().CXXOperatorName.BeginOpNameLoc));
@@ -2955,7 +3039,8 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,
CompilerInstance::createDiagnostics(new DiagnosticOptions());
std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(), Diags,
- FileSystemOpts, CXXIdx->getOnlyLocalDecls(), None,
+ FileSystemOpts, /*UseDebugInfo=*/false,
+ CXXIdx->getOnlyLocalDecls(), None,
/*CaptureDiagnostics=*/true,
/*AllowPCHWithCompilerErrors=*/true,
/*UserFilesAreVolatile=*/true);
@@ -2982,35 +3067,19 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
Options);
}
-struct ParseTranslationUnitInfo {
- CXIndex CIdx;
- const char *source_filename;
- const char *const *command_line_args;
- int num_command_line_args;
- ArrayRef<CXUnsavedFile> unsaved_files;
- unsigned options;
- CXTranslationUnit *out_TU;
- CXErrorCode &result;
-};
-static void clang_parseTranslationUnit_Impl(void *UserData) {
- const ParseTranslationUnitInfo *PTUI =
- static_cast<ParseTranslationUnitInfo *>(UserData);
- CXIndex CIdx = PTUI->CIdx;
- const char *source_filename = PTUI->source_filename;
- const char * const *command_line_args = PTUI->command_line_args;
- int num_command_line_args = PTUI->num_command_line_args;
- unsigned options = PTUI->options;
- CXTranslationUnit *out_TU = PTUI->out_TU;
-
+static CXErrorCode
+clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
+ const char *const *command_line_args,
+ int num_command_line_args,
+ ArrayRef<CXUnsavedFile> unsaved_files,
+ unsigned options, CXTranslationUnit *out_TU) {
// Set up the initial return values.
if (out_TU)
*out_TU = nullptr;
// Check arguments.
- if (!CIdx || !out_TU) {
- PTUI->result = CXError_InvalidArguments;
- return;
- }
+ if (!CIdx || !out_TU)
+ return CXError_InvalidArguments;
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
@@ -3018,6 +3087,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
setThreadBackgroundPriority();
bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
+ bool CreatePreambleOnFirstParse =
+ options & CXTranslationUnit_CreatePreambleOnFirstParse;
// FIXME: Add a flag for modules.
TranslationUnitKind TUKind
= (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete;
@@ -3044,7 +3115,7 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
llvm::CrashRecoveryContextCleanupRegistrar<
std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
- for (auto &UF : PTUI->unsaved_files) {
+ for (auto &UF : unsaved_files) {
std::unique_ptr<llvm::MemoryBuffer> MB =
llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
@@ -3070,12 +3141,12 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
break;
}
}
- if (!FoundSpellCheckingArgument)
- Args->push_back("-fno-spell-checking");
-
Args->insert(Args->end(), command_line_args,
command_line_args + num_command_line_args);
+ if (!FoundSpellCheckingArgument)
+ Args->insert(Args->begin() + 1, "-fno-spell-checking");
+
// The 'source_filename' argument is optional. If the caller does not
// specify it then it is assumed that the source file is specified
// in the actual argument list.
@@ -3092,21 +3163,26 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
unsigned NumErrors = Diags->getClient()->getNumErrors();
std::unique_ptr<ASTUnit> ErrUnit;
+ // Unless the user specified that they want the preamble on the first parse
+ // set it up to be created on the first reparse. This makes the first parse
+ // faster, trading for a slower (first) reparse.
+ unsigned PrecompilePreambleAfterNParses =
+ !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCommandLine(
Args->data(), Args->data() + Args->size(),
CXXIdx->getPCHContainerOperations(), Diags,
CXXIdx->getClangResourcesPath(), CXXIdx->getOnlyLocalDecls(),
/*CaptureDiagnostics=*/true, *RemappedFiles.get(),
- /*RemappedFilesKeepOriginalName=*/true, PrecompilePreamble, TUKind,
- CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion,
+ /*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses,
+ TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion,
/*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies,
- /*UserFilesAreVolatile=*/true, ForSerialization, &ErrUnit));
+ /*UserFilesAreVolatile=*/true, ForSerialization,
+ CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(),
+ &ErrUnit));
// Early failures in LoadFromCommandLine may return with ErrUnit unset.
- if (!Unit && !ErrUnit) {
- PTUI->result = CXError_ASTReadError;
- return;
- }
+ if (!Unit && !ErrUnit)
+ return CXError_ASTReadError;
if (NumErrors != Diags->getClient()->getNumErrors()) {
// Make sure to check that 'Unit' is non-NULL.
@@ -3114,12 +3190,11 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());
}
- if (isASTReadError(Unit ? Unit.get() : ErrUnit.get())) {
- PTUI->result = CXError_ASTReadError;
- } else {
- *PTUI->out_TU = MakeCXTranslationUnit(CXXIdx, Unit.release());
- PTUI->result = *PTUI->out_TU ? CXError_Success : CXError_Failure;
- }
+ if (isASTReadError(Unit ? Unit.get() : ErrUnit.get()))
+ return CXError_ASTReadError;
+
+ *out_TU = MakeCXTranslationUnit(CXXIdx, Unit.release());
+ return *out_TU ? CXError_Success : CXError_Failure;
}
CXTranslationUnit
@@ -3141,14 +3216,23 @@ clang_parseTranslationUnit(CXIndex CIdx,
}
enum CXErrorCode clang_parseTranslationUnit2(
- CXIndex CIdx,
- const char *source_filename,
- const char *const *command_line_args,
- int num_command_line_args,
- struct CXUnsavedFile *unsaved_files,
- unsigned num_unsaved_files,
- unsigned options,
- CXTranslationUnit *out_TU) {
+ CXIndex CIdx, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
+ unsigned options, CXTranslationUnit *out_TU) {
+ SmallVector<const char *, 4> Args;
+ Args.push_back("clang");
+ Args.append(command_line_args, command_line_args + num_command_line_args);
+ return clang_parseTranslationUnit2FullArgv(
+ CIdx, source_filename, Args.data(), Args.size(), unsaved_files,
+ num_unsaved_files, options, out_TU);
+}
+
+enum CXErrorCode clang_parseTranslationUnit2FullArgv(
+ CXIndex CIdx, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
+ unsigned options, CXTranslationUnit *out_TU) {
LOG_FUNC_SECTION {
*Log << source_filename << ": ";
for (int i = 0; i != num_command_line_args; ++i)
@@ -3159,18 +3243,14 @@ enum CXErrorCode clang_parseTranslationUnit2(
return CXError_InvalidArguments;
CXErrorCode result = CXError_Failure;
- ParseTranslationUnitInfo PTUI = {
- CIdx,
- source_filename,
- command_line_args,
- num_command_line_args,
- llvm::makeArrayRef(unsaved_files, num_unsaved_files),
- options,
- out_TU,
- result};
+ auto ParseTranslationUnitImpl = [=, &result] {
+ result = clang_parseTranslationUnit_Impl(
+ CIdx, source_filename, command_line_args, num_command_line_args,
+ llvm::makeArrayRef(unsaved_files, num_unsaved_files), options, out_TU);
+ };
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {
+ if (!RunSafely(CRC, ParseTranslationUnitImpl)) {
fprintf(stderr, "libclang: crash detected during parsing: {\n");
fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
fprintf(stderr, " 'command_line_args' : [");
@@ -3193,7 +3273,7 @@ enum CXErrorCode clang_parseTranslationUnit2(
return CXError_Crashed;
} else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
- if (CXTranslationUnit *TU = PTUI.out_TU)
+ if (CXTranslationUnit *TU = out_TU)
PrintLibclangResourceUsage(*TU);
}
@@ -3204,27 +3284,15 @@ unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
return CXSaveTranslationUnit_None;
}
-namespace {
-
-struct SaveTranslationUnitInfo {
- CXTranslationUnit TU;
- const char *FileName;
- unsigned options;
- CXSaveError result;
-};
-
-}
-
-static void clang_saveTranslationUnit_Impl(void *UserData) {
- SaveTranslationUnitInfo *STUI =
- static_cast<SaveTranslationUnitInfo*>(UserData);
-
- CIndexer *CXXIdx = STUI->TU->CIdx;
+static CXSaveError clang_saveTranslationUnit_Impl(CXTranslationUnit TU,
+ const char *FileName,
+ unsigned options) {
+ CIndexer *CXXIdx = TU->CIdx;
if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
setThreadBackgroundPriority();
- bool hadError = cxtu::getASTUnit(STUI->TU)->Save(STUI->FileName);
- STUI->result = hadError ? CXSaveError_Unknown : CXSaveError_None;
+ bool hadError = cxtu::getASTUnit(TU)->Save(FileName);
+ return hadError ? CXSaveError_Unknown : CXSaveError_None;
}
int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
@@ -3243,16 +3311,19 @@ int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
if (!CXXUnit->hasSema())
return CXSaveError_InvalidTU;
- SaveTranslationUnitInfo STUI = { TU, FileName, options, CXSaveError_None };
+ CXSaveError result;
+ auto SaveTranslationUnitImpl = [=, &result]() {
+ result = clang_saveTranslationUnit_Impl(TU, FileName, options);
+ };
if (!CXXUnit->getDiagnostics().hasUnrecoverableErrorOccurred() ||
getenv("LIBCLANG_NOTHREADS")) {
- clang_saveTranslationUnit_Impl(&STUI);
+ SaveTranslationUnitImpl();
if (getenv("LIBCLANG_RESOURCE_USAGE"))
PrintLibclangResourceUsage(TU);
- return STUI.result;
+ return result;
}
// We have an AST that has invalid nodes due to compiler errors.
@@ -3260,7 +3331,7 @@ int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_saveTranslationUnit_Impl, &STUI)) {
+ if (!RunSafely(CRC, SaveTranslationUnitImpl)) {
fprintf(stderr, "libclang: crash detected during AST saving: {\n");
fprintf(stderr, " 'filename' : '%s'\n", FileName);
fprintf(stderr, " 'options' : %d,\n", options);
@@ -3272,7 +3343,7 @@ int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
PrintLibclangResourceUsage(TU);
}
- return STUI.result;
+ return result;
}
void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
@@ -3296,25 +3367,14 @@ unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
return CXReparse_None;
}
-struct ReparseTranslationUnitInfo {
- CXTranslationUnit TU;
- ArrayRef<CXUnsavedFile> unsaved_files;
- unsigned options;
- CXErrorCode &result;
-};
-
-static void clang_reparseTranslationUnit_Impl(void *UserData) {
- const ReparseTranslationUnitInfo *RTUI =
- static_cast<ReparseTranslationUnitInfo *>(UserData);
- CXTranslationUnit TU = RTUI->TU;
- unsigned options = RTUI->options;
- (void) options;
-
+static CXErrorCode
+clang_reparseTranslationUnit_Impl(CXTranslationUnit TU,
+ ArrayRef<CXUnsavedFile> unsaved_files,
+ unsigned options) {
// Check arguments.
if (isNotUsableTU(TU)) {
LOG_BAD_TU(TU);
- RTUI->result = CXError_InvalidArguments;
- return;
+ return CXError_InvalidArguments;
}
// Reset the associated diagnostics.
@@ -3335,7 +3395,7 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) {
llvm::CrashRecoveryContextCleanupRegistrar<
std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
- for (auto &UF : RTUI->unsaved_files) {
+ for (auto &UF : unsaved_files) {
std::unique_ptr<llvm::MemoryBuffer> MB =
llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
@@ -3343,9 +3403,10 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) {
if (!CXXUnit->Reparse(CXXIdx->getPCHContainerOperations(),
*RemappedFiles.get()))
- RTUI->result = CXError_Success;
- else if (isASTReadError(CXXUnit))
- RTUI->result = CXError_ASTReadError;
+ return CXError_Success;
+ if (isASTReadError(CXXUnit))
+ return CXError_ASTReadError;
+ return CXError_Failure;
}
int clang_reparseTranslationUnit(CXTranslationUnit TU,
@@ -3359,19 +3420,20 @@ int clang_reparseTranslationUnit(CXTranslationUnit TU,
if (num_unsaved_files && !unsaved_files)
return CXError_InvalidArguments;
- CXErrorCode result = CXError_Failure;
- ReparseTranslationUnitInfo RTUI = {
- TU, llvm::makeArrayRef(unsaved_files, num_unsaved_files), options,
- result};
+ CXErrorCode result;
+ auto ReparseTranslationUnitImpl = [=, &result]() {
+ result = clang_reparseTranslationUnit_Impl(
+ TU, llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
+ };
if (getenv("LIBCLANG_NOTHREADS")) {
- clang_reparseTranslationUnit_Impl(&RTUI);
+ ReparseTranslationUnitImpl();
return result;
}
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {
+ if (!RunSafely(CRC, ReparseTranslationUnitImpl)) {
fprintf(stderr, "libclang: crash detected during reparsing\n");
cxtu::getASTUnit(TU)->setUnsafeToFree(true);
return CXError_Crashed;
@@ -3551,6 +3613,26 @@ static SourceLocation getLocationFromExpr(const Expr *E) {
return E->getLocStart();
}
+static std::string getMangledStructor(std::unique_ptr<MangleContext> &M,
+ std::unique_ptr<llvm::DataLayout> &DL,
+ const NamedDecl *ND,
+ unsigned StructorType) {
+ std::string FrontendBuf;
+ llvm::raw_string_ostream FOS(FrontendBuf);
+
+ if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
+ M->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
+ else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
+ M->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
+
+ std::string BackendBuf;
+ llvm::raw_string_ostream BOS(BackendBuf);
+
+ llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
+
+ return BOS.str();
+}
+
extern "C" {
unsigned clang_visitChildren(CXCursor parent,
@@ -3780,6 +3862,19 @@ CXString clang_getCursorSpelling(CXCursor C) {
return cxstring::createRef("packed");
}
+ if (C.kind == CXCursor_VisibilityAttr) {
+ const VisibilityAttr *AA = cast<VisibilityAttr>(cxcursor::getCursorAttr(C));
+ switch (AA->getVisibility()) {
+ case VisibilityAttr::VisibilityType::Default:
+ return cxstring::createRef("default");
+ case VisibilityAttr::VisibilityType::Hidden:
+ return cxstring::createRef("hidden");
+ case VisibilityAttr::VisibilityType::Protected:
+ return cxstring::createRef("protected");
+ }
+ llvm_unreachable("unknown visibility type");
+ }
+
return cxstring::createEmpty();
}
@@ -3893,11 +3988,15 @@ CXString clang_Cursor_getMangling(CXCursor C) {
std::string FrontendBuf;
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
- MC->mangleName(ND, FrontendBufOS);
+ if (MC->shouldMangleDeclName(ND)) {
+ MC->mangleName(ND, FrontendBufOS);
+ } else {
+ ND->printName(FrontendBufOS);
+ }
// Now apply backend mangling.
std::unique_ptr<llvm::DataLayout> DL(
- new llvm::DataLayout(Ctx.getTargetInfo().getTargetDescription()));
+ new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
std::string FinalBuf;
llvm::raw_string_ostream FinalBufOS(FinalBuf);
@@ -3907,6 +4006,54 @@ CXString clang_Cursor_getMangling(CXCursor C) {
return cxstring::createDup(FinalBufOS.str());
}
+CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
+ if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
+ return nullptr;
+
+ const Decl *D = getCursorDecl(C);
+ if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
+ return nullptr;
+
+ const NamedDecl *ND = cast<NamedDecl>(D);
+
+ ASTContext &Ctx = ND->getASTContext();
+ std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
+ std::unique_ptr<llvm::DataLayout> DL(
+ new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
+
+ std::vector<std::string> Manglings;
+
+ auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
+ auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
+ /*IsCSSMethod=*/true);
+ auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
+ return CC == DefaultCC;
+ };
+
+ if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
+ Manglings.emplace_back(getMangledStructor(M, DL, CD, Ctor_Base));
+
+ if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
+ if (!CD->getParent()->isAbstract())
+ Manglings.emplace_back(getMangledStructor(M, DL, CD, Ctor_Complete));
+
+ if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
+ if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
+ if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
+ Manglings.emplace_back(getMangledStructor(M, DL, CD,
+ Ctor_DefaultClosure));
+ } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
+ Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Base));
+ if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
+ Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Complete));
+ if (DD->isVirtual())
+ Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Deleting));
+ }
+ }
+
+ return cxstring::createSet(Manglings);
+}
+
CXString clang_getCursorDisplayName(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return clang_getCursorSpelling(C);
@@ -4071,6 +4218,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("UnaryOperator");
case CXCursor_ArraySubscriptExpr:
return cxstring::createRef("ArraySubscriptExpr");
+ case CXCursor_OMPArraySectionExpr:
+ return cxstring::createRef("OMPArraySectionExpr");
case CXCursor_BinaryOperator:
return cxstring::createRef("BinaryOperator");
case CXCursor_CompoundAssignOperator:
@@ -4259,6 +4408,12 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("attribute(host)");
case CXCursor_CUDASharedAttr:
return cxstring::createRef("attribute(shared)");
+ case CXCursor_VisibilityAttr:
+ return cxstring::createRef("attribute(visibility)");
+ case CXCursor_DLLExport:
+ return cxstring::createRef("attribute(dllexport)");
+ case CXCursor_DLLImport:
+ return cxstring::createRef("attribute(dllimport)");
case CXCursor_PreprocessingDirective:
return cxstring::createRef("preprocessing directive");
case CXCursor_MacroDefinition:
@@ -4349,14 +4504,24 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPAtomicDirective");
case CXCursor_OMPTargetDirective:
return cxstring::createRef("OMPTargetDirective");
+ case CXCursor_OMPTargetDataDirective:
+ return cxstring::createRef("OMPTargetDataDirective");
case CXCursor_OMPTeamsDirective:
return cxstring::createRef("OMPTeamsDirective");
case CXCursor_OMPCancellationPointDirective:
return cxstring::createRef("OMPCancellationPointDirective");
case CXCursor_OMPCancelDirective:
return cxstring::createRef("OMPCancelDirective");
+ case CXCursor_OMPTaskLoopDirective:
+ return cxstring::createRef("OMPTaskLoopDirective");
+ case CXCursor_OMPTaskLoopSimdDirective:
+ return cxstring::createRef("OMPTaskLoopSimdDirective");
+ case CXCursor_OMPDistributeDirective:
+ return cxstring::createRef("OMPDistributeDirective");
case CXCursor_OverloadCandidate:
return cxstring::createRef("OverloadCandidate");
+ case CXCursor_TypeAliasTemplateDecl:
+ return cxstring::createRef("TypeAliasTemplateDecl");
}
llvm_unreachable("Unhandled CXCursorKind");
@@ -5100,6 +5265,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::ObjCTypeParam:
+ case Decl::BuiltinTemplate:
return C;
// Declaration kinds that don't make any sense here, but are
@@ -5362,10 +5528,12 @@ CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,
break;
case CXCursor_DeclRefExpr:
- if (const DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C)))
- Pieces = buildPieces(NameFlags, false, E->getNameInfo(),
- E->getQualifierLoc().getSourceRange(),
- E->getOptionalExplicitTemplateArgs());
+ if (const DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C))) {
+ SourceRange TemplateArgLoc(E->getLAngleLoc(), E->getRAngleLoc());
+ Pieces =
+ buildPieces(NameFlags, false, E->getNameInfo(),
+ E->getQualifierLoc().getSourceRange(), &TemplateArgLoc);
+ }
break;
case CXCursor_CallExpr:
@@ -6055,16 +6223,6 @@ MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent,
parent);
}
-namespace {
- struct clang_annotateTokens_Data {
- CXTranslationUnit TU;
- ASTUnit *CXXUnit;
- CXToken *Tokens;
- unsigned NumTokens;
- CXCursor *Cursors;
- };
-}
-
/// \brief Used by \c annotatePreprocessorTokens.
/// \returns true if lexing was finished, false otherwise.
static bool lexNext(Lexer &Lex, Token &Tok,
@@ -6074,10 +6232,7 @@ static bool lexNext(Lexer &Lex, Token &Tok,
++NextIdx;
Lex.LexFromRawLexer(Tok);
- if (Tok.is(tok::eof))
- return true;
-
- return false;
+ return Tok.is(tok::eof);
}
static void annotatePreprocessorTokens(CXTranslationUnit TU,
@@ -6184,13 +6339,9 @@ static void annotatePreprocessorTokens(CXTranslationUnit TU,
}
// This gets run a separate thread to avoid stack blowout.
-static void clang_annotateTokensImpl(void *UserData) {
- CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU;
- ASTUnit *CXXUnit = ((clang_annotateTokens_Data*)UserData)->CXXUnit;
- CXToken *Tokens = ((clang_annotateTokens_Data*)UserData)->Tokens;
- const unsigned NumTokens = ((clang_annotateTokens_Data*)UserData)->NumTokens;
- CXCursor *Cursors = ((clang_annotateTokens_Data*)UserData)->Cursors;
-
+static void clang_annotateTokensImpl(CXTranslationUnit TU, ASTUnit *CXXUnit,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors) {
CIndexer *CXXIdx = TU->CIdx;
if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
setThreadBackgroundPriority();
@@ -6326,11 +6477,12 @@ void clang_annotateTokens(CXTranslationUnit TU,
return;
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
-
- clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };
+
+ auto AnnotateTokensImpl = [=]() {
+ clang_annotateTokensImpl(TU, CXXUnit, Tokens, NumTokens, Cursors);
+ };
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_annotateTokensImpl, &data,
- GetSafetyThreadStackSize() * 2)) {
+ if (!RunSafely(CRC, AnnotateTokensImpl, GetSafetyThreadStackSize() * 2)) {
fprintf(stderr, "libclang: crash detected while annotating tokens\n");
}
}
@@ -6361,6 +6513,27 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
} // end: extern "C"
//===----------------------------------------------------------------------===//
+// Operations for querying visibility of a cursor.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
+ if (!clang_isDeclaration(cursor.kind))
+ return CXVisibility_Invalid;
+
+ const Decl *D = cxcursor::getCursorDecl(cursor);
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ switch (ND->getVisibility()) {
+ case HiddenVisibility: return CXVisibility_Hidden;
+ case ProtectedVisibility: return CXVisibility_Protected;
+ case DefaultVisibility: return CXVisibility_Default;
+ };
+
+ return CXVisibility_Invalid;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
// Operations for querying language of a cursor.
//===----------------------------------------------------------------------===//
@@ -6418,7 +6591,7 @@ extern "C" {
static CXAvailabilityKind getCursorAvailabilityForDecl(const Decl *D) {
if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
- return CXAvailability_Available;
+ return CXAvailability_NotAvailable;
switch (D->getAvailability()) {
case AR_Available:
@@ -6612,8 +6785,6 @@ enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor C) {
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:
@@ -6893,6 +7064,16 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit TU,
//===----------------------------------------------------------------------===//
extern "C" {
+unsigned clang_CXXField_isMutable(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ if (const auto D = cxcursor::getCursorDecl(C))
+ if (const auto FD = dyn_cast_or_null<FieldDecl>(D))
+ return FD->isMutable() ? 1 : 0;
+ return 0;
+}
+
unsigned clang_CXXMethod_isPureVirtual(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return 0;
@@ -7179,14 +7360,13 @@ static unsigned SafetyStackThreadSize = 8 << 20;
namespace clang {
-bool RunSafely(llvm::CrashRecoveryContext &CRC,
- void (*Fn)(void*), void *UserData,
+bool RunSafely(llvm::CrashRecoveryContext &CRC, llvm::function_ref<void()> Fn,
unsigned Size) {
if (!Size)
Size = GetSafetyThreadStackSize();
if (Size)
- return CRC.RunSafelyOnThread(Fn, UserData, Size);
- return CRC.RunSafely(Fn, UserData);
+ return CRC.RunSafelyOnThread(Fn, Size);
+ return CRC.RunSafely(Fn);
}
unsigned GetSafetyThreadStackSize() {
@@ -7408,8 +7588,6 @@ Logger &cxindex::Logger::operator<<(const llvm::format_object_base &Fmt) {
static llvm::ManagedStatic<llvm::sys::Mutex> LoggingMutex;
cxindex::Logger::~Logger() {
- LogOS.flush();
-
llvm::sys::ScopedLock L(*LoggingMutex);
static llvm::TimeRecord sBeginTR = llvm::TimeRecord::getCurrentTime();
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 9609a693abdf9..344ed27021a16 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -646,25 +646,12 @@ namespace {
};
}
-extern "C" {
-struct CodeCompleteAtInfo {
- CXTranslationUnit TU;
- const char *complete_filename;
- unsigned complete_line;
- unsigned complete_column;
- ArrayRef<CXUnsavedFile> unsaved_files;
- unsigned options;
- CXCodeCompleteResults *result;
-};
-static void clang_codeCompleteAt_Impl(void *UserData) {
- CodeCompleteAtInfo *CCAI = static_cast<CodeCompleteAtInfo*>(UserData);
- CXTranslationUnit TU = CCAI->TU;
- const char *complete_filename = CCAI->complete_filename;
- unsigned complete_line = CCAI->complete_line;
- unsigned complete_column = CCAI->complete_column;
- unsigned options = CCAI->options;
+static CXCodeCompleteResults *
+clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
+ unsigned complete_line, unsigned complete_column,
+ ArrayRef<CXUnsavedFile> unsaved_files,
+ unsigned options) {
bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
- CCAI->result = nullptr;
#ifdef UDP_CODE_COMPLETION_LOGGER
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
@@ -676,12 +663,12 @@ static void clang_codeCompleteAt_Impl(void *UserData) {
if (cxtu::isNotUsableTU(TU)) {
LOG_BAD_TU(TU);
- return;
+ return nullptr;
}
ASTUnit *AST = cxtu::getASTUnit(TU);
if (!AST)
- return;
+ return nullptr;
CIndexer *CXXIdx = TU->CIdx;
if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
@@ -692,7 +679,7 @@ static void clang_codeCompleteAt_Impl(void *UserData) {
// Perform the remapping of source files.
SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
- for (auto &UF : CCAI->unsaved_files) {
+ for (auto &UF : unsaved_files) {
std::unique_ptr<llvm::MemoryBuffer> MB =
llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));
@@ -804,8 +791,10 @@ static void clang_codeCompleteAt_Impl(void *UserData) {
}
#endif
#endif
- CCAI->result = Results;
+ return Results;
}
+
+extern "C" {
CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
const char *complete_filename,
unsigned complete_line,
@@ -821,25 +810,28 @@ CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
if (num_unsaved_files && !unsaved_files)
return nullptr;
- CodeCompleteAtInfo CCAI = {TU, complete_filename, complete_line,
- complete_column, llvm::makeArrayRef(unsaved_files, num_unsaved_files),
- options, nullptr};
+ CXCodeCompleteResults *result;
+ auto CodeCompleteAtImpl = [=, &result]() {
+ result = clang_codeCompleteAt_Impl(
+ TU, complete_filename, complete_line, complete_column,
+ llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
+ };
if (getenv("LIBCLANG_NOTHREADS")) {
- clang_codeCompleteAt_Impl(&CCAI);
- return CCAI.result;
+ CodeCompleteAtImpl();
+ return result;
}
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_codeCompleteAt_Impl, &CCAI)) {
+ if (!RunSafely(CRC, CodeCompleteAtImpl)) {
fprintf(stderr, "libclang: crash detected in code completion\n");
cxtu::getASTUnit(TU)->setUnsafeToFree(true);
return nullptr;
} else if (getenv("LIBCLANG_RESOURCE_USAGE"))
PrintLibclangResourceUsage(TU);
- return CCAI.result;
+ return result;
}
unsigned clang_defaultCodeCompleteOptions(void) {
diff --git a/tools/libclang/CIndexer.h b/tools/libclang/CIndexer.h
index bf55301d618e6..94c27a05600fd 100644
--- a/tools/libclang/CIndexer.h
+++ b/tools/libclang/CIndexer.h
@@ -85,8 +85,8 @@ public:
/// threads when possible.
///
/// \return False if a crash was detected.
- bool RunSafely(llvm::CrashRecoveryContext &CRC,
- void (*Fn)(void*), void *UserData, unsigned Size = 0);
+ bool RunSafely(llvm::CrashRecoveryContext &CRC, llvm::function_ref<void()> Fn,
+ unsigned Size = 0);
/// \brief Set the thread priority to background.
/// FIXME: Move to llvm/Support.
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index 06db70e61ad5d..5267c02db5f4c 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -102,21 +102,16 @@ if(ENABLE_SHARED)
PROPERTIES
VERSION ${LIBCLANG_LIBRARY_VERSION}
DEFINE_SYMBOL _CINDEX_LIB_)
+ elseif(APPLE)
+ set(LIBCLANG_LINK_FLAGS " -Wl,-compatibility_version -Wl,1")
+ set(LIBCLANG_LINK_FLAGS "${LIBCLANG_LINK_FLAGS} -Wl,-current_version -Wl,${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")
+
+ set_property(TARGET libclang APPEND_STRING PROPERTY
+ LINK_FLAGS ${LIBCLANG_LINK_FLAGS})
else()
set_target_properties(libclang
PROPERTIES
VERSION ${LIBCLANG_LIBRARY_VERSION}
DEFINE_SYMBOL _CINDEX_LIB_)
endif()
-
- if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set(LIBCLANG_LINK_FLAGS " -Wl,-compatibility_version -Wl,1")
- if (DEFINED ${LLVM_SUBMIT_VERSION})
- set(LIBCLANG_LINK_FLAGS
- "${LIBCLANG_LINK_FLAGS} -Wl,-current_version -Wl,${LLVM_SUBMIT_VERSION}.${LLVM_SUBMIT_SUBVERSION}")
- endif()
-
- set_property(TARGET libclang APPEND_STRING PROPERTY
- LINK_FLAGS ${LIBCLANG_LINK_FLAGS})
- endif()
endif()
diff --git a/tools/libclang/CXCompilationDatabase.cpp b/tools/libclang/CXCompilationDatabase.cpp
index 1e4a2cd44aabb..82498bf54c749 100644
--- a/tools/libclang/CXCompilationDatabase.cpp
+++ b/tools/libclang/CXCompilationDatabase.cpp
@@ -111,6 +111,16 @@ clang_CompileCommand_getDirectory(CXCompileCommand CCmd)
return cxstring::createRef(cmd->Directory.c_str());
}
+CXString
+clang_CompileCommand_getFilename(CXCompileCommand CCmd)
+{
+ if (!CCmd)
+ return cxstring::createNull();
+
+ CompileCommand *cmd = static_cast<CompileCommand *>(CCmd);
+ return cxstring::createRef(cmd->Filename.c_str());
+}
+
unsigned
clang_CompileCommand_getNumArgs(CXCompileCommand CCmd)
{
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 099edcf14fed3..c766d2d69fa95 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -58,6 +58,9 @@ static CXCursorKind GetCursorKind(const Attr *A) {
case attr::CUDAGlobal: return CXCursor_CUDAGlobalAttr;
case attr::CUDAHost: return CXCursor_CUDAHostAttr;
case attr::CUDAShared: return CXCursor_CUDASharedAttr;
+ case attr::Visibility: return CXCursor_VisibilityAttr;
+ case attr::DLLExport: return CXCursor_DLLExport;
+ case attr::DLLImport: return CXCursor_DLLImport;
}
return CXCursor_UnexposedAttr;
@@ -226,6 +229,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::AtomicExprClass:
case Stmt::BinaryConditionalOperatorClass:
case Stmt::TypeTraitExprClass:
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoawaitExprClass:
+ case Stmt::CoreturnStmtClass:
+ case Stmt::CoyieldExprClass:
case Stmt::CXXBindTemporaryExprClass:
case Stmt::CXXDefaultArgExprClass:
case Stmt::CXXDefaultInitExprClass:
@@ -324,10 +331,15 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_UnaryExpr;
break;
+ case Stmt::MSPropertySubscriptExprClass:
case Stmt::ArraySubscriptExprClass:
K = CXCursor_ArraySubscriptExpr;
break;
+ case Stmt::OMPArraySectionExprClass:
+ K = CXCursor_OMPArraySectionExpr;
+ break;
+
case Stmt::BinaryOperatorClass:
K = CXCursor_BinaryOperator;
break;
@@ -585,6 +597,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPTargetDirectiveClass:
K = CXCursor_OMPTargetDirective;
break;
+ case Stmt::OMPTargetDataDirectiveClass:
+ K = CXCursor_OMPTargetDataDirective;
+ break;
case Stmt::OMPTeamsDirectiveClass:
K = CXCursor_OMPTeamsDirective;
break;
@@ -594,6 +609,15 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPCancelDirectiveClass:
K = CXCursor_OMPCancelDirective;
break;
+ case Stmt::OMPTaskLoopDirectiveClass:
+ K = CXCursor_OMPTaskLoopDirective;
+ break;
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ K = CXCursor_OMPTaskLoopSimdDirective;
+ break;
+ case Stmt::OMPDistributeDirectiveClass:
+ K = CXCursor_OMPDistributeDirective;
+ break;
}
CXCursor C = { K, 0, { Parent, S, TU } };
diff --git a/tools/libclang/CXLoadedDiagnostic.cpp b/tools/libclang/CXLoadedDiagnostic.cpp
index 754ad55a66040..2c10d34844b75 100644
--- a/tools/libclang/CXLoadedDiagnostic.cpp
+++ b/tools/libclang/CXLoadedDiagnostic.cpp
@@ -25,6 +25,7 @@
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -56,7 +57,7 @@ public:
return mem;
}
};
-}
+} // end anonymous namespace
//===----------------------------------------------------------------------===//
// Cleanup.
@@ -246,7 +247,7 @@ public:
CXDiagnosticSet load(const char *file);
};
-}
+} // end anonymous namespace
CXDiagnosticSet DiagLoader::load(const char *file) {
TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>();
@@ -264,7 +265,7 @@ CXDiagnosticSet DiagLoader::load(const char *file) {
reportInvalidFile(EC.message());
break;
}
- return 0;
+ return nullptr;
}
return (CXDiagnosticSet)TopDiags.release();
diff --git a/tools/libclang/CXString.cpp b/tools/libclang/CXString.cpp
index dec8ebcd98e14..1ccbed3b5c243 100644
--- a/tools/libclang/CXString.cpp
+++ b/tools/libclang/CXString.cpp
@@ -112,6 +112,15 @@ CXString createCXString(CXStringBuf *buf) {
return Str;
}
+CXStringSet *createSet(const std::vector<std::string> &Strings) {
+ CXStringSet *Set = new CXStringSet;
+ Set->Count = Strings.size();
+ Set->Strings = new CXString[Set->Count];
+ for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
+ Set->Strings[SI] = createDup(Strings[SI]);
+ return Set;
+}
+
//===----------------------------------------------------------------------===//
// String pools.
@@ -175,5 +184,13 @@ void clang_disposeString(CXString string) {
break;
}
}
+
+void clang_disposeStringSet(CXStringSet *set) {
+ for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)
+ clang_disposeString(set->Strings[SI]);
+ delete[] set->Strings;
+ delete set;
+}
+
} // end: extern "C"
diff --git a/tools/libclang/CXString.h b/tools/libclang/CXString.h
index 72ac0cf46914a..6473eb2d7103d 100644
--- a/tools/libclang/CXString.h
+++ b/tools/libclang/CXString.h
@@ -68,6 +68,8 @@ CXString createRef(std::string String) = delete;
/// \brief Create a CXString object that is backed by a string buffer.
CXString createCXString(CXStringBuf *buf);
+CXStringSet *createSet(const std::vector<std::string> &Strings);
+
/// \brief A string pool used for fast allocation/deallocation of strings.
class CXStringPool {
public:
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index 1318e86b55539..72c12cd16b978 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -90,6 +90,7 @@ static CXTypeKind GetTypeKind(QualType T) {
TKCASE(DependentSizedArray);
TKCASE(Vector);
TKCASE(MemberPointer);
+ TKCASE(Auto);
default:
return CXType_Unexposed;
}
@@ -101,6 +102,11 @@ CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
CXTypeKind TK = CXType_Invalid;
if (TU && !T.isNull()) {
+ // Handle attributed types as the original type
+ if (auto *ATT = T->getAs<AttributedType>()) {
+ return MakeCXType(ATT->getModifiedType(), TU);
+ }
+
ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
if (Ctx.getLangOpts().ObjC1) {
QualType UnqualT = T.getUnqualifiedType();
@@ -139,7 +145,7 @@ extern "C" {
CXType clang_getCursorType(CXCursor C) {
using namespace cxcursor;
-
+
CXTranslationUnit TU = cxcursor::getCursorTU(C);
if (!TU)
return MakeCXType(QualType(), TU);
@@ -159,23 +165,17 @@ CXType clang_getCursorType(CXCursor C) {
return MakeCXType(Context.getTypeDeclType(TD), TU);
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
return MakeCXType(Context.getObjCInterfaceType(ID), TU);
- if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
- return MakeCXType(TSInfo->getType(), TU);
- return MakeCXType(DD->getType(), TU);
- }
+ if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
+ return MakeCXType(DD->getType(), TU);
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
return MakeCXType(VD->getType(), TU);
if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
return MakeCXType(PD->getType(), TU);
- if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
- if (TypeSourceInfo *TSInfo = FTD->getTemplatedDecl()->getTypeSourceInfo())
- return MakeCXType(TSInfo->getType(), TU);
+ if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
return MakeCXType(FTD->getTemplatedDecl()->getType(), TU);
- }
return MakeCXType(QualType(), TU);
}
-
+
if (clang_isReference(C.kind)) {
switch (C.kind) {
case CXCursor_ObjCSuperClassRef: {
@@ -183,18 +183,18 @@ CXType clang_getCursorType(CXCursor C) {
= Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
return MakeCXType(T, TU);
}
-
+
case CXCursor_ObjCClassRef: {
QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
return MakeCXType(T, TU);
}
-
+
case CXCursor_TypeRef: {
QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
return MakeCXType(T, TU);
}
-
+
case CXCursor_CXXBaseSpecifier:
return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
@@ -211,7 +211,7 @@ CXType clang_getCursorType(CXCursor C) {
default:
break;
}
-
+
return MakeCXType(QualType(), TU);
}
@@ -349,10 +349,10 @@ unsigned clang_isRestrictQualifiedType(CXType CT) {
CXType clang_getPointeeType(CXType CT) {
QualType T = GetQualType(CT);
const Type *TP = T.getTypePtrOrNull();
-
+
if (!TP)
return MakeCXType(QualType(), GetTU(CT));
-
+
switch (TP->getTypeClass()) {
case Type::Pointer:
T = cast<PointerType>(TP)->getPointeeType();
@@ -411,7 +411,7 @@ try_again:
D = cast<TemplateSpecializationType>(TP)->getTemplateName()
.getAsTemplateDecl();
break;
-
+
case Type::InjectedClassName:
D = cast<InjectedClassNameType>(TP)->getDecl();
break;
@@ -421,7 +421,7 @@ try_again:
case Type::Elaborated:
TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
goto try_again;
-
+
default:
break;
}
@@ -484,6 +484,7 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
TKIND(DependentSizedArray);
TKIND(Vector);
TKIND(MemberPointer);
+ TKIND(Auto);
}
#undef TKIND
return cxstring::createRef(s);
diff --git a/tools/libclang/CursorVisitor.h b/tools/libclang/CursorVisitor.h
index 91f63b40f6a59..3e5b0c9120c54 100644
--- a/tools/libclang/CursorVisitor.h
+++ b/tools/libclang/CursorVisitor.h
@@ -195,6 +195,7 @@ public:
bool VisitChildren(CXCursor Parent);
// Declaration visitors
+ bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
bool VisitTypeAliasDecl(TypeAliasDecl *D);
bool VisitAttributes(Decl *D);
bool VisitBlockDecl(BlockDecl *B);
diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp
index 5539971f04a78..64df4b85beac7 100644
--- a/tools/libclang/IndexBody.cpp
+++ b/tools/libclang/IndexBody.cpp
@@ -8,19 +8,19 @@
//===----------------------------------------------------------------------===//
#include "IndexingContext.h"
-#include "clang/AST/DataRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
using namespace clang;
using namespace cxindex;
namespace {
-class BodyIndexer : public DataRecursiveASTVisitor<BodyIndexer> {
+class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
IndexingContext &IndexCtx;
const NamedDecl *Parent;
const DeclContext *ParentDC;
- typedef DataRecursiveASTVisitor<BodyIndexer> base;
+ typedef RecursiveASTVisitor<BodyIndexer> base;
public:
BodyIndexer(IndexingContext &indexCtx,
const NamedDecl *Parent, const DeclContext *DC)
@@ -125,10 +125,11 @@ public:
return true;
}
- bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
+ DataRecursionQueue *Q = nullptr) {
if (E->getOperatorLoc().isInvalid())
return true; // implicit.
- return base::TraverseCXXOperatorCallExpr(E);
+ return base::TraverseCXXOperatorCallExpr(E, Q);
}
bool VisitDeclStmt(DeclStmt *S) {
diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/tools/libclang/IndexTypeSourceInfo.cpp
index 706870e514b8e..9666052ed1818 100644
--- a/tools/libclang/IndexTypeSourceInfo.cpp
+++ b/tools/libclang/IndexTypeSourceInfo.cpp
@@ -8,14 +8,14 @@
//===----------------------------------------------------------------------===//
#include "IndexingContext.h"
-#include "clang/AST/DataRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
using namespace clang;
using namespace cxindex;
namespace {
-class TypeIndexer : public DataRecursiveASTVisitor<TypeIndexer> {
+class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
IndexingContext &IndexCtx;
const NamedDecl *Parent;
const DeclContext *ParentDC;
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index e35640029e62c..d6e35b0019c9c 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -462,48 +462,24 @@ struct IndexSessionData {
: CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {}
};
-struct IndexSourceFileInfo {
- CXIndexAction idxAction;
- CXClientData client_data;
- IndexerCallbacks *index_callbacks;
- unsigned index_callbacks_size;
- unsigned index_options;
- const char *source_filename;
- const char *const *command_line_args;
- int num_command_line_args;
- ArrayRef<CXUnsavedFile> unsaved_files;
- CXTranslationUnit *out_TU;
- unsigned TU_options;
- CXErrorCode &result;
-};
-
} // anonymous namespace
-static void clang_indexSourceFile_Impl(void *UserData) {
- const IndexSourceFileInfo *ITUI =
- static_cast<IndexSourceFileInfo *>(UserData);
- CXIndexAction cxIdxAction = ITUI->idxAction;
- CXClientData client_data = ITUI->client_data;
- IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
- unsigned index_callbacks_size = ITUI->index_callbacks_size;
- unsigned index_options = ITUI->index_options;
- const char *source_filename = ITUI->source_filename;
- const char * const *command_line_args = ITUI->command_line_args;
- int num_command_line_args = ITUI->num_command_line_args;
- CXTranslationUnit *out_TU = ITUI->out_TU;
- unsigned TU_options = ITUI->TU_options;
-
+static CXErrorCode clang_indexSourceFile_Impl(
+ CXIndexAction cxIdxAction, CXClientData client_data,
+ IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
+ unsigned index_options, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU,
+ unsigned TU_options) {
if (out_TU)
*out_TU = nullptr;
bool requestedToGetTU = (out_TU != nullptr);
if (!cxIdxAction) {
- ITUI->result = CXError_InvalidArguments;
- return;
+ return CXError_InvalidArguments;
}
if (!client_index_callbacks || index_callbacks_size == 0) {
- ITUI->result = CXError_InvalidArguments;
- return;
+ return CXError_InvalidArguments;
}
IndexerCallbacks CB;
@@ -557,7 +533,7 @@ static void clang_indexSourceFile_Impl(void *UserData) {
CInvok(createInvocationFromCommandLine(*Args, Diags));
if (!CInvok)
- return;
+ return CXError_Failure;
// Recover resources if we crash before exiting this function.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation,
@@ -565,7 +541,7 @@ static void clang_indexSourceFile_Impl(void *UserData) {
CInvokCleanup(CInvok.get());
if (CInvok->getFrontendOpts().Inputs.empty())
- return;
+ return CXError_Failure;
typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
@@ -574,7 +550,7 @@ static void clang_indexSourceFile_Impl(void *UserData) {
llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
BufOwner.get());
- for (auto &UF : ITUI->unsaved_files) {
+ for (auto &UF : unsaved_files) {
std::unique_ptr<llvm::MemoryBuffer> MB =
llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get());
@@ -590,12 +566,14 @@ static void clang_indexSourceFile_Impl(void *UserData) {
if (index_options & CXIndexOpt_SuppressWarnings)
CInvok->getDiagnosticOpts().IgnoreWarnings = true;
+ // Make sure to use the raw module format.
+ CInvok->getHeaderSearchOpts().ModuleFormat =
+ CXXIdx->getPCHContainerOperations()->getRawReader().getFormat();
+
ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags, CaptureDiagnostics,
/*UserFilesAreVolatile=*/true);
- if (!Unit) {
- ITUI->result = CXError_InvalidArguments;
- return;
- }
+ if (!Unit)
+ return CXError_InvalidArguments;
std::unique_ptr<CXTUOwner> CXTU(
new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit)));
@@ -623,6 +601,7 @@ static void clang_indexSourceFile_Impl(void *UserData) {
bool Persistent = requestedToGetTU;
bool OnlyLocalDecls = false;
bool PrecompilePreamble = false;
+ bool CreatePreambleOnFirstParse = false;
bool CacheCodeCompletionResults = false;
PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
PPOpts.AllowPCHWithCompilerErrors = true;
@@ -630,6 +609,8 @@ static void clang_indexSourceFile_Impl(void *UserData) {
if (requestedToGetTU) {
OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
+ CreatePreambleOnFirstParse =
+ TU_options & CXTranslationUnit_CreatePreambleOnFirstParse;
// FIXME: Add a flag for modules.
CacheCodeCompletionResults
= TU_options & CXTranslationUnit_CacheCompletionResults;
@@ -642,49 +623,38 @@ static void clang_indexSourceFile_Impl(void *UserData) {
if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
PPOpts.DetailedRecord = false;
+ // Unless the user specified that they want the preamble on the first parse
+ // set it up to be created on the first reparse. This makes the first parse
+ // faster, trading for a slower (first) reparse.
+ unsigned PrecompilePreambleAfterNParses =
+ !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
DiagnosticErrorTrap DiagTrap(*Diags);
bool Success = ASTUnit::LoadFromCompilerInvocationAction(
CInvok.get(), CXXIdx->getPCHContainerOperations(), Diags,
IndexAction.get(), Unit, Persistent, CXXIdx->getClangResourcesPath(),
- OnlyLocalDecls, CaptureDiagnostics, PrecompilePreamble,
+ OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses,
CacheCodeCompletionResults,
/*IncludeBriefCommentsInCodeCompletion=*/false,
/*UserFilesAreVolatile=*/true);
if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
printDiagsToStderr(Unit);
- if (isASTReadError(Unit)) {
- ITUI->result = CXError_ASTReadError;
- return;
- }
+ if (isASTReadError(Unit))
+ return CXError_ASTReadError;
if (!Success)
- return;
+ return CXError_Failure;
if (out_TU)
*out_TU = CXTU->takeTU();
- ITUI->result = CXError_Success;
+ return CXError_Success;
}
//===----------------------------------------------------------------------===//
// clang_indexTranslationUnit Implementation
//===----------------------------------------------------------------------===//
-namespace {
-
-struct IndexTranslationUnitInfo {
- CXIndexAction idxAction;
- CXClientData client_data;
- IndexerCallbacks *index_callbacks;
- unsigned index_callbacks_size;
- unsigned index_options;
- CXTranslationUnit TU;
- int result;
-};
-
-} // anonymous namespace
-
static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
Preprocessor &PP = Unit.getPreprocessor();
if (!PP.getPreprocessingRecord())
@@ -711,9 +681,7 @@ static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
static bool topLevelDeclVisitor(void *context, const Decl *D) {
IndexingContext &IdxCtx = *static_cast<IndexingContext*>(context);
IdxCtx.indexTopLevelDecl(D);
- if (IdxCtx.shouldAbort())
- return false;
- return true;
+ return !IdxCtx.shouldAbort();
}
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
@@ -728,27 +696,17 @@ static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {
IdxCtx.handleDiagnosticSet(DiagSet);
}
-static void clang_indexTranslationUnit_Impl(void *UserData) {
- IndexTranslationUnitInfo *ITUI =
- static_cast<IndexTranslationUnitInfo*>(UserData);
- CXTranslationUnit TU = ITUI->TU;
- CXClientData client_data = ITUI->client_data;
- IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
- unsigned index_callbacks_size = ITUI->index_callbacks_size;
- unsigned index_options = ITUI->index_options;
-
- // Set up the initial return value.
- ITUI->result = CXError_Failure;
-
+static CXErrorCode clang_indexTranslationUnit_Impl(
+ CXIndexAction idxAction, CXClientData client_data,
+ IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
+ unsigned index_options, CXTranslationUnit TU) {
// Check arguments.
if (isNotUsableTU(TU)) {
LOG_BAD_TU(TU);
- ITUI->result = CXError_InvalidArguments;
- return;
+ return CXError_InvalidArguments;
}
if (!client_index_callbacks || index_callbacks_size == 0) {
- ITUI->result = CXError_InvalidArguments;
- return;
+ return CXError_InvalidArguments;
}
CIndexer *CXXIdx = TU->CIdx;
@@ -777,7 +735,7 @@ static void clang_indexTranslationUnit_Impl(void *UserData) {
ASTUnit *Unit = cxtu::getASTUnit(TU);
if (!Unit)
- return;
+ return CXError_Failure;
ASTUnit::ConcurrencyCheck Check(*Unit);
@@ -797,7 +755,7 @@ static void clang_indexTranslationUnit_Impl(void *UserData) {
indexTranslationUnit(*Unit, *IndexCtx);
indexDiagnostics(TU, *IndexCtx);
- ITUI->result = CXError_Success;
+ return CXError_Success;
}
//===----------------------------------------------------------------------===//
@@ -959,6 +917,22 @@ int clang_indexSourceFile(CXIndexAction idxAction,
unsigned num_unsaved_files,
CXTranslationUnit *out_TU,
unsigned TU_options) {
+ SmallVector<const char *, 4> Args;
+ Args.push_back("clang");
+ Args.append(command_line_args, command_line_args + num_command_line_args);
+ return clang_indexSourceFileFullArgv(
+ idxAction, client_data, index_callbacks, index_callbacks_size,
+ index_options, source_filename, Args.data(), Args.size(), unsaved_files,
+ num_unsaved_files, out_TU, TU_options);
+}
+
+int clang_indexSourceFileFullArgv(
+ CXIndexAction idxAction, CXClientData client_data,
+ IndexerCallbacks *index_callbacks, unsigned index_callbacks_size,
+ unsigned index_options, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
+ CXTranslationUnit *out_TU, unsigned TU_options) {
LOG_FUNC_SECTION {
*Log << source_filename << ": ";
for (int i = 0; i != num_command_line_args; ++i)
@@ -969,28 +943,23 @@ int clang_indexSourceFile(CXIndexAction idxAction,
return CXError_InvalidArguments;
CXErrorCode result = CXError_Failure;
- IndexSourceFileInfo ITUI = {
- idxAction,
- client_data,
- index_callbacks,
- index_callbacks_size,
- index_options,
- source_filename,
- command_line_args,
- num_command_line_args,
- llvm::makeArrayRef(unsaved_files, num_unsaved_files),
- out_TU,
- TU_options,
- result};
+ auto IndexSourceFileImpl = [=, &result]() {
+ result = clang_indexSourceFile_Impl(
+ idxAction, client_data, index_callbacks, index_callbacks_size,
+ index_options, source_filename, command_line_args,
+ num_command_line_args,
+ llvm::makeArrayRef(unsaved_files, num_unsaved_files), out_TU,
+ TU_options);
+ };
if (getenv("LIBCLANG_NOTHREADS")) {
- clang_indexSourceFile_Impl(&ITUI);
+ IndexSourceFileImpl();
return result;
}
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) {
+ if (!RunSafely(CRC, IndexSourceFileImpl)) {
fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
fprintf(stderr, " 'command_line_args' : [");
@@ -1030,24 +999,27 @@ int clang_indexTranslationUnit(CXIndexAction idxAction,
*Log << TU;
}
- IndexTranslationUnitInfo ITUI = { idxAction, client_data, index_callbacks,
- index_callbacks_size, index_options, TU,
- 0 };
+ CXErrorCode result;
+ auto IndexTranslationUnitImpl = [=, &result]() {
+ result = clang_indexTranslationUnit_Impl(
+ idxAction, client_data, index_callbacks, index_callbacks_size,
+ index_options, TU);
+ };
if (getenv("LIBCLANG_NOTHREADS")) {
- clang_indexTranslationUnit_Impl(&ITUI);
- return ITUI.result;
+ IndexTranslationUnitImpl();
+ return result;
}
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) {
+ if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
fprintf(stderr, "libclang: crash detected during indexing TU\n");
return 1;
}
- return ITUI.result;
+ return result;
}
void clang_indexLoc_getFileLocation(CXIdxLoc location,
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index bf6e172fc074b..f7640c63e05c1 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -804,10 +804,7 @@ bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
RefFileOccurrence RefOccur(FE, D);
std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
res = RefFileOccurrences.insert(RefOccur);
- if (!res.second)
- return true; // already in map.
-
- return false;
+ return !res.second; // already in map
}
const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index f6a7175579aa3..993644d02fc15 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -2,6 +2,7 @@ clang_CXCursorSet_contains
clang_CXCursorSet_insert
clang_CXIndex_getGlobalOptions
clang_CXIndex_setGlobalOptions
+clang_CXXField_isMutable
clang_CXXMethod_isConst
clang_CXXMethod_isPureVirtual
clang_CXXMethod_isStatic
@@ -14,6 +15,7 @@ clang_Cursor_getTemplateArgumentValue
clang_Cursor_getTemplateArgumentUnsignedValue
clang_Cursor_getBriefCommentText
clang_Cursor_getCommentRange
+clang_Cursor_getCXXManglings
clang_Cursor_getMangling
clang_Cursor_getParsedComment
clang_Cursor_getRawCommentText
@@ -119,6 +121,7 @@ clang_disposeOverriddenCursors
clang_disposeCXPlatformAvailability
clang_disposeSourceRangeList
clang_disposeString
+clang_disposeStringSet
clang_disposeTokens
clang_disposeTranslationUnit
clang_enableStackTraces
@@ -173,6 +176,7 @@ clang_getCursorSemanticParent
clang_getCursorSpelling
clang_getCursorType
clang_getCursorUSR
+clang_getCursorVisibility
clang_getDeclObjCTypeEncoding
clang_getDefinitionSpellingAndExtent
clang_getDiagnostic
@@ -246,6 +250,7 @@ clang_hashCursor
clang_indexLoc_getCXSourceLocation
clang_indexLoc_getFileLocation
clang_indexSourceFile
+clang_indexSourceFileFullArgv
clang_indexTranslationUnit
clang_index_getCXXClassDeclInfo
clang_index_getClientContainer
@@ -281,6 +286,7 @@ clang_Location_isInSystemHeader
clang_Location_isFromMainFile
clang_parseTranslationUnit
clang_parseTranslationUnit2
+clang_parseTranslationUnit2FullArgv
clang_remap_dispose
clang_remap_getFilenames
clang_remap_getNumFiles
@@ -297,6 +303,9 @@ clang_CompileCommands_dispose
clang_CompileCommands_getSize
clang_CompileCommands_getCommand
clang_CompileCommand_getDirectory
+clang_CompileCommand_getFilename
+clang_CompileCommand_getMappedSourceContent
+clang_CompileCommand_getMappedSourcePath
clang_CompileCommand_getNumArgs
clang_CompileCommand_getArg
clang_visitChildren
diff --git a/tools/scan-build/CMakeLists.txt b/tools/scan-build/CMakeLists.txt
new file mode 100644
index 0000000000000..78c243d8e0d65
--- /dev/null
+++ b/tools/scan-build/CMakeLists.txt
@@ -0,0 +1,82 @@
+option(CLANG_INSTALL_SCANBUILD "Install the scan-build tool" ON)
+
+include(GNUInstallDirs)
+
+if (WIN32 AND NOT CYGWIN)
+ set(BinFiles
+ scan-build.bat)
+ set(LibexecFiles
+ ccc-analyzer.bat
+ c++-analyzer.bat)
+else()
+ set(BinFiles
+ scan-build)
+ set(LibexecFiles
+ ccc-analyzer
+ c++-analyzer)
+ if (APPLE)
+ list(APPEND BinFiles
+ set-xcode-analyzer)
+ endif()
+endif()
+
+set(ManPages
+ scan-build.1)
+
+set(ShareFiles
+ scanview.css
+ sorttable.js)
+
+
+if(CLANG_INSTALL_SCANBUILD)
+ foreach(BinFile ${BinFiles})
+ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${BinFile}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/bin
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile}
+ ${CMAKE_BINARY_DIR}/bin/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile})
+ list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${BinFile})
+ install(PROGRAMS bin/${BinFile} DESTINATION bin)
+ endforeach()
+
+ foreach(LibexecFile ${LibexecFiles})
+ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/libexec/${LibexecFile}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/libexec
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${LibexecFile}
+ ${CMAKE_BINARY_DIR}/libexec/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${LibexecFile})
+ list(APPEND Depends ${CMAKE_BINARY_DIR}/libexec/${LibexecFile})
+ install(PROGRAMS libexec/${LibexecFile} DESTINATION libexec)
+ endforeach()
+
+ foreach(ManPage ${ManPages})
+ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1/${ManPage}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/man/${ManPage}
+ ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/man/${ManPage})
+ list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1/${ManPage})
+ install(PROGRAMS man/${ManPage} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+ endforeach()
+
+ foreach(ShareFile ${ShareFiles})
+ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/share/scan-build/${ShareFile}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/share/scan-build
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/share/scan-build/${ShareFile}
+ ${CMAKE_BINARY_DIR}/share/scan-build/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/share/scan-build/${ShareFile})
+ list(APPEND Depends ${CMAKE_BINARY_DIR}/share/scan-build/${ShareFile})
+ install(FILES share/scan-build/${ShareFile} DESTINATION share/scan-build)
+ endforeach()
+
+ add_custom_target(scan-build ALL DEPENDS ${Depends})
+ set_target_properties(scan-build PROPERTIES FOLDER "Misc")
+endif()
diff --git a/tools/scan-build/Makefile b/tools/scan-build/Makefile
new file mode 100644
index 0000000000000..23aa19882a527
--- /dev/null
+++ b/tools/scan-build/Makefile
@@ -0,0 +1,53 @@
+##===- tools/scan-build/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+
+include $(CLANG_LEVEL)/../../Makefile.config
+include $(CLANG_LEVEL)/Makefile
+
+ifeq ($(HOST_OS),MingW)
+ Suffix := .bat
+endif
+
+CLANG_INSTALL_SCANBUILD ?= 1
+
+ifeq ($(CLANG_INSTALL_SCANBUILD), 1)
+ InstallTargets := $(ToolDir)/scan-build$(Suffix) \
+ $(LibexecDir)/c++-analyzer$(Suffix) \
+ $(LibexecDir)/ccc-analyzer$(Suffix) \
+ $(ShareDir)/scan-build/scanview.css \
+ $(ShareDir)/scan-build/sorttable.js \
+ $(ShareDir)/man/man1/scan-build.1
+
+ ifeq ($(HOST_OS),Darwin)
+ InstallTargets := $(InstallTargets) $(ToolDir)/set-xcode-analyzer
+ endif
+endif
+
+all:: $(InstallTargets)
+
+$(ToolDir)/%: bin/% Makefile $(ToolDir)/.dir
+ $(Echo) "Copying $(notdir $<) to the 'bin' directory..."
+ $(Verb)cp $< $@
+ $(Verb)chmod +x $@
+
+$(LibexecDir)/%: libexec/% Makefile $(LibexecDir)/.dir
+ $(Echo) "Copying $(notdir $<) to the 'libexec' directory..."
+ $(Verb)cp $< $@
+ $(Verb)chmod +x $@
+
+$(ShareDir)/man/man1/%: man/% Makefile $(ShareDir)/man/man1/.dir
+ $(Echo) "Copying $(notdir $<) to the 'man' directory..."
+ $(Verb)cp $< $@
+
+$(ShareDir)/scan-build/%: share/scan-build/% Makefile $(ShareDir)/scan-build/.dir
+ $(Echo) "Copying $(notdir $<) to the 'share' directory..."
+ $(Verb)cp $< $@
+
diff --git a/tools/scan-build/scan-build b/tools/scan-build/bin/scan-build
index d7cadc3e59e12..6a14484970a27 100755
--- a/tools/scan-build/scan-build
+++ b/tools/scan-build/bin/scan-build
@@ -24,8 +24,8 @@ use Term::ANSIColor;
use Term::ANSIColor qw(:constants);
use Cwd qw/ getcwd abs_path /;
use Sys::Hostname;
+use Hash::Util qw(lock_keys);
-my $Verbose = 0; # Verbose output from this script.
my $Prog = "scan-build";
my $BuildName;
my $BuildDate;
@@ -39,15 +39,40 @@ my $UseColor = (defined $TERM and $TERM =~ 'xterm-.*color' and -t STDOUT
my $UserName = HtmlEscape(getlogin() || getpwuid($<) || 'unknown');
my $HostName = HtmlEscape(hostname() || 'unknown');
my $CurrentDir = HtmlEscape(getcwd());
-my $CurrentDirSuffix = basename($CurrentDir);
-my @PluginsToLoad;
my $CmdArgs;
-my $HtmlTitle;
-
my $Date = localtime();
+# Command-line/config arguments.
+my %Options = (
+ Verbose => 0, # Verbose output from this script.
+ AnalyzeHeaders => 0,
+ OutputDir => undef, # Parent directory to store HTML files.
+ HtmlTitle => basename($CurrentDir)." - scan-build results",
+ IgnoreErrors => 0, # Ignore build errors.
+ ViewResults => 0, # View results when the build terminates.
+ ExitStatusFoundBugs => 0, # Exit status reflects whether bugs were found
+ KeepEmpty => 0, # Don't remove output directory even with 0 results.
+ EnableCheckers => {},
+ DisableCheckers => {},
+ UseCC => undef, # C compiler to use for compilation.
+ UseCXX => undef, # C++ compiler to use for compilation.
+ AnalyzerTarget => undef,
+ StoreModel => undef,
+ ConstraintsModel => undef,
+ InternalStats => undef,
+ OutputFormat => "html",
+ ConfigOptions => [], # Options to pass through to the analyzer's -analyzer-config flag.
+ ReportFailures => undef,
+ AnalyzerStats => 0,
+ MaxLoop => 0,
+ PluginsToLoad => [],
+ AnalyzerDiscoveryMethod => undef,
+ OverrideCompiler => 0 # The flag corresponding to the --override-compiler command line option.
+);
+lock_keys(%Options);
+
##----------------------------------------------------------------------------##
# Diagnostics
##----------------------------------------------------------------------------##
@@ -231,7 +256,7 @@ sub SetHtmlEnv {
return;
}
- if ($Verbose) {
+ if ($Options{Verbose}) {
Diag("Emitting reports for this run to '$Dir'.\n");
}
@@ -437,7 +462,7 @@ sub CopyFiles {
my $Dir = shift;
- my $JS = Cwd::realpath("$RealBin/sorttable.js");
+ my $JS = Cwd::realpath("$RealBin/../share/scan-build/sorttable.js");
DieDiag("Cannot find 'sorttable.js'.\n")
if (! -r $JS);
@@ -447,7 +472,7 @@ sub CopyFiles {
DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
if (! -r "$Dir/sorttable.js");
- my $CSS = Cwd::realpath("$RealBin/scanview.css");
+ my $CSS = Cwd::realpath("$RealBin/../share/scan-build/scanview.css");
DieDiag("Cannot find 'scanview.css'.\n")
if (! -r $CSS);
@@ -582,7 +607,7 @@ sub Postprocess {
print OUT <<ENDTEXT;
<html>
<head>
-<title>${HtmlTitle}</title>
+<title>${Options{HtmlTitle}}</title>
<link type="text/css" rel="stylesheet" href="scanview.css"/>
<script src="sorttable.js"></script>
<script language='javascript' type="text/javascript">
@@ -637,7 +662,7 @@ function ToggleDisplay(CheckButton, ClassName) {
<!-- SUMMARYENDHEAD -->
</head>
<body>
-<h1>${HtmlTitle}</h1>
+<h1>${Options{HtmlTitle}}</h1>
<table>
<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
@@ -912,21 +937,25 @@ sub AddIfNotPresent {
}
sub SetEnv {
- my $Options = shift @_;
- foreach my $opt ('CC', 'CXX', 'CLANG', 'CLANG_CXX',
- 'CCC_ANALYZER_ANALYSIS', 'CCC_ANALYZER_PLUGINS',
- 'CCC_ANALYZER_CONFIG') {
- die "$opt is undefined\n" if (!defined $opt);
- $ENV{$opt} = $Options->{$opt};
+ my $EnvVars = shift @_;
+ foreach my $var ('CC', 'CXX', 'CLANG', 'CLANG_CXX',
+ 'CCC_ANALYZER_ANALYSIS', 'CCC_ANALYZER_PLUGINS',
+ 'CCC_ANALYZER_CONFIG') {
+ die "$var is undefined\n" if (!defined $var);
+ $ENV{$var} = $EnvVars->{$var};
}
- foreach my $opt ('CCC_ANALYZER_STORE_MODEL',
- 'CCC_ANALYZER_PLUGINS',
- 'CCC_ANALYZER_INTERNAL_STATS',
- 'CCC_ANALYZER_OUTPUT_FORMAT') {
- my $x = $Options->{$opt};
- if (defined $x) { $ENV{$opt} = $x }
+ foreach my $var ('CCC_ANALYZER_STORE_MODEL',
+ 'CCC_ANALYZER_CONSTRAINTS_MODEL',
+ 'CCC_ANALYZER_INTERNAL_STATS',
+ 'CCC_ANALYZER_OUTPUT_FORMAT',
+ 'CCC_CC',
+ 'CCC_CXX',
+ 'CCC_REPORT_FAILURES',
+ 'CLANG_ANALYZER_TARGET') {
+ my $x = $EnvVars->{$var};
+ if (defined $x) { $ENV{$var} = $x }
}
- my $Verbose = $Options->{'VERBOSE'};
+ my $Verbose = $EnvVars->{'VERBOSE'};
if ($Verbose >= 2) {
$ENV{'CCC_ANALYZER_VERBOSE'} = 1;
}
@@ -935,15 +964,12 @@ sub SetEnv {
}
}
-# The flag corresponding to the --override-compiler command line option.
-my $OverrideCompiler = 0;
-
sub RunXcodebuild {
my $Args = shift;
my $IgnoreErrors = shift;
my $CCAnalyzer = shift;
my $CXXAnalyzer = shift;
- my $Options = shift;
+ my $EnvVars = shift;
if ($IgnoreErrors) {
AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
@@ -972,14 +998,14 @@ sub RunXcodebuild {
# If --override-compiler is explicitely requested, resort to the old
# behavior regardless of Xcode version.
- if ($OverrideCompiler) {
+ if ($Options{OverrideCompiler}) {
$oldBehavior = 1;
}
if ($oldBehavior == 0) {
- my $OutputDir = $Options->{"OUTPUT_DIR"};
- my $CLANG = $Options->{"CLANG"};
- my $OtherFlags = $Options->{"CCC_ANALYZER_ANALYSIS"};
+ my $OutputDir = $EnvVars->{"OUTPUT_DIR"};
+ my $CLANG = $EnvVars->{"CLANG"};
+ my $OtherFlags = $EnvVars->{"CCC_ANALYZER_ANALYSIS"};
push @$Args,
"RUN_CLANG_STATIC_ANALYZER=YES",
"CLANG_ANALYZER_OUTPUT=plist-html",
@@ -991,7 +1017,7 @@ sub RunXcodebuild {
}
# Default to old behavior where we insert a bogus compiler.
- SetEnv($Options);
+ SetEnv($EnvVars);
# Check if using iPhone SDK 3.0 (simulator). If so the compiler being
# used should be gcc-4.2.
@@ -1023,14 +1049,14 @@ sub RunBuildCommand {
my $Cmd = $Args->[0];
my $CCAnalyzer = shift;
my $CXXAnalyzer = shift;
- my $Options = shift;
+ my $EnvVars = shift;
if ($Cmd =~ /\bxcodebuild$/) {
- return RunXcodebuild($Args, $IgnoreErrors, $CCAnalyzer, $CXXAnalyzer, $Options);
+ return RunXcodebuild($Args, $IgnoreErrors, $CCAnalyzer, $CXXAnalyzer, $EnvVars);
}
# Setup the environment.
- SetEnv($Options);
+ SetEnv($EnvVars);
if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or
$Cmd =~ /(.*\/?cc[^\/]*$)/ or
@@ -1074,6 +1100,7 @@ sub RunBuildCommand {
sub DisplayHelp {
+ my $ArgClangNotFoundErrMsg = shift;
print <<ENDTEXT;
USAGE: $Prog [options] <build command> [build options]
@@ -1145,10 +1172,21 @@ OPTIONS:
scan-build to use a specific compiler for *compilation* then you can use
this option to specify a path to that compiler.
+ If the given compiler is a cross compiler, you may also need to provide
+ --analyzer-target option to properly analyze the source code because static
+ analyzer runs as if the code is compiled for the host machine by default.
+
--use-c++ [compiler path]
--use-c++=[compiler path]
- This is the same as "-use-cc" but for C++ code.
+ This is the same as "--use-cc" but for C++ code.
+
+ --analyzer-target [target triple name for analysis]
+ --analyzer-target=[target triple name for analysis]
+
+ This provides target triple information to clang static analyzer.
+ It only changes the target for analysis but doesn't change the target of a
+ real compiler given by --use-cc and --use-c++ options.
-v
@@ -1221,32 +1259,41 @@ LOADING CHECKERS:
-load-plugin [plugin library]
ENDTEXT
- # Query clang for list of checkers that are enabled.
+ if (defined $Clang && -x $Clang) {
+ # 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++") {
- my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|");
- open(PS, $ExecLine);
- while (<PS>) {
- foreach my $val (split /\s+/) {
- $val =~ s/\"//g;
- if ($val =~ /-analyzer-checker\=([^\s]+)/) {
- $EnabledCheckers{$1} = 1;
+ # create a list to load the plugins via the 'Xclang' command line
+ # argument
+ my @PluginLoadCommandline_xclang;
+ foreach my $param ( @{$Options{PluginsToLoad}} ) {
+ push ( @PluginLoadCommandline_xclang, "-Xclang" );
+ push ( @PluginLoadCommandline_xclang, "-load" );
+ push ( @PluginLoadCommandline_xclang, "-Xclang" );
+ push ( @PluginLoadCommandline_xclang, $param );
+ }
+
+ my %EnabledCheckers;
+ foreach my $lang ("c", "objective-c", "objective-c++", "c++") {
+ my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|");
+ open(PS, $ExecLine);
+ while (<PS>) {
+ foreach my $val (split /\s+/) {
+ $val =~ s/\"//g;
+ if ($val =~ /-analyzer-checker\=([^\s]+)/) {
+ $EnabledCheckers{$1} = 1;
+ }
}
}
}
- }
- # Query clang for complete list of checkers.
- if (defined $Clang && -x $Clang) {
- my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginsToLoad, "-analyzer-checker-help", "2>&1", "|");
+ # Query clang for complete list of checkers.
+ my @PluginLoadCommandline;
+ foreach my $param ( @{$Options{PluginsToLoad}} ) {
+ push ( @PluginLoadCommandline, "-load" );
+ push ( @PluginLoadCommandline, $param );
+ }
+
+ my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginLoadCommandline, "-analyzer-checker-help", "2>&1", "|");
open(PS, $ExecLine);
my $foundCheckers = 0;
while (<PS>) {
@@ -1302,6 +1349,12 @@ ENDTEXT
}
close PS;
}
+ else {
+ print " *** Could not query Clang for the list of available checkers.\n";
+ if (defined $ArgClangNotFoundErrMsg) {
+ print " *** Reason: $ArgClangNotFoundErrMsg\n";
+ }
+ }
print <<ENDTEXT
@@ -1347,284 +1400,331 @@ sub ShellEscape {
}
##----------------------------------------------------------------------------##
+# FindClang - searches for 'clang' executable.
+##----------------------------------------------------------------------------##
+
+sub FindClang {
+ if (!defined $Options{AnalyzerDiscoveryMethod}) {
+ $Clang = Cwd::realpath("$RealBin/bin/clang") if (-f "$RealBin/bin/clang");
+ if (!defined $Clang || ! -x $Clang) {
+ $Clang = Cwd::realpath("$RealBin/clang") if (-f "$RealBin/clang");
+ }
+ if (!defined $Clang || ! -x $Clang) {
+ return "error: Cannot find an executable 'clang' relative to" .
+ " scan-build. Consider using --use-analyzer to pick a version of" .
+ " 'clang' to use for static analysis.\n";
+ }
+ }
+ else {
+ if ($Options{AnalyzerDiscoveryMethod} =~ /^[Xx]code$/) {
+ my $xcrun = `which xcrun`;
+ chomp $xcrun;
+ if ($xcrun eq "") {
+ return "Cannot find 'xcrun' to find 'clang' for analysis.\n";
+ }
+ $Clang = `$xcrun -toolchain XcodeDefault -find clang`;
+ chomp $Clang;
+ if ($Clang eq "") {
+ return "No 'clang' executable found by 'xcrun'\n";
+ }
+ }
+ else {
+ $Clang = $Options{AnalyzerDiscoveryMethod};
+ if (!defined $Clang or not -x $Clang) {
+ return "Cannot find an executable clang at '$Options{AnalyzerDiscoveryMethod}'\n";
+ }
+ }
+ }
+ return undef;
+}
+
+##----------------------------------------------------------------------------##
# Process command-line arguments.
##----------------------------------------------------------------------------##
-my $AnalyzeHeaders = 0;
-my $HtmlDir; # Parent directory to store HTML files.
-my $IgnoreErrors = 0; # Ignore build errors.
-my $ViewResults = 0; # View results when the build terminates.
-my $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found
-my $KeepEmpty = 0; # Don't remove output directory even with 0 results.
-my @AnalysesToRun;
-my $StoreModel;
-my $ConstraintsModel;
-my $InternalStats;
-my @ConfigOptions;
-my $OutputFormat = "html";
-my $AnalyzerStats = 0;
-my $MaxLoop = 0;
my $RequestDisplayHelp = 0;
my $ForceDisplayHelp = 0;
-my $AnalyzerDiscoveryMethod;
-if (!@ARGV) {
- $ForceDisplayHelp = 1
-}
+sub ProcessArgs {
+ my $Args = shift;
+ my $NumArgs = 0;
-while (@ARGV) {
+ while (@$Args) {
- # Scan for options we recognize.
+ $NumArgs++;
- my $arg = $ARGV[0];
+ # Scan for options we recognize.
- if ($arg eq "-h" or $arg eq "--help") {
- $RequestDisplayHelp = 1;
- shift @ARGV;
- next;
- }
+ my $arg = $Args->[0];
- if ($arg eq '-analyze-headers') {
- shift @ARGV;
- $AnalyzeHeaders = 1;
- next;
- }
+ if ($arg eq "-h" or $arg eq "--help") {
+ $RequestDisplayHelp = 1;
+ shift @$Args;
+ next;
+ }
+
+ if ($arg eq '-analyze-headers') {
+ shift @$Args;
+ $Options{AnalyzeHeaders} = 1;
+ next;
+ }
- if ($arg eq "-o") {
- shift @ARGV;
+ if ($arg eq "-o") {
+ shift @$Args;
- if (!@ARGV) {
- DieDiag("'-o' option requires a target directory name.\n");
+ if (!@$Args) {
+ DieDiag("'-o' option requires a target directory name.\n");
+ }
+
+ # Construct an absolute path. Uses the current working directory
+ # as a base if the original path was not absolute.
+ my $OutDir = shift @$Args;
+ mkpath($OutDir) unless (-e $OutDir); # abs_path wants existing dir
+ $Options{OutputDir} = abs_path($OutDir);
+
+ next;
}
- # Construct an absolute path. Uses the current working directory
- # as a base if the original path was not absolute.
- $HtmlDir = abs_path(shift @ARGV);
+ if ($arg =~ /^--html-title(=(.+))?$/) {
+ shift @$Args;
- next;
- }
+ if (!defined $2 || $2 eq '') {
+ if (!@$Args) {
+ DieDiag("'--html-title' option requires a string.\n");
+ }
+
+ $Options{HtmlTitle} = shift @$Args;
+ } else {
+ $Options{HtmlTitle} = $2;
+ }
+
+ next;
+ }
- if ($arg =~ /^--html-title(=(.+))?$/) {
- shift @ARGV;
+ if ($arg eq "-k" or $arg eq "--keep-going") {
+ shift @$Args;
+ $Options{IgnoreErrors} = 1;
+ next;
+ }
+
+ if ($arg =~ /^--use-cc(=(.+))?$/) {
+ shift @$Args;
+ my $cc;
- if (!defined $2 || $2 eq '') {
- if (!@ARGV) {
- DieDiag("'--html-title' option requires a string.\n");
+ if (!defined $2 || $2 eq "") {
+ if (!@$Args) {
+ DieDiag("'--use-cc' option requires a compiler executable name.\n");
+ }
+ $cc = shift @$Args;
+ }
+ else {
+ $cc = $2;
}
- $HtmlTitle = shift @ARGV;
- } else {
- $HtmlTitle = $2;
+ $Options{UseCC} = $cc;
+ next;
}
- next;
- }
+ if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
+ shift @$Args;
+ my $cxx;
- if ($arg eq "-k" or $arg eq "--keep-going") {
- shift @ARGV;
- $IgnoreErrors = 1;
- next;
- }
+ if (!defined $2 || $2 eq "") {
+ if (!@$Args) {
+ DieDiag("'--use-c++' option requires a compiler executable name.\n");
+ }
+ $cxx = shift @$Args;
+ }
+ else {
+ $cxx = $2;
+ }
+
+ $Options{UseCXX} = $cxx;
+ next;
+ }
- if ($arg =~ /^--use-cc(=(.+))?$/) {
- shift @ARGV;
- my $cc;
+ if ($arg =~ /^--analyzer-target(=(.+))?$/) {
+ shift @ARGV;
+ my $AnalyzerTarget;
- if (!defined $2 || $2 eq "") {
- if (!@ARGV) {
- DieDiag("'--use-cc' option requires a compiler executable name.\n");
+ if (!defined $2 || $2 eq "") {
+ if (!@ARGV) {
+ DieDiag("'--analyzer-target' option requires a target triple name.\n");
+ }
+ $AnalyzerTarget = shift @ARGV;
}
- $cc = shift @ARGV;
+ else {
+ $AnalyzerTarget = $2;
+ }
+
+ $Options{AnalyzerTarget} = $AnalyzerTarget;
+ next;
}
- else {
- $cc = $2;
+
+ if ($arg eq "-v") {
+ shift @$Args;
+ $Options{Verbose}++;
+ next;
}
- $ENV{"CCC_CC"} = $cc;
- next;
- }
+ if ($arg eq "-V" or $arg eq "--view") {
+ shift @$Args;
+ $Options{ViewResults} = 1;
+ next;
+ }
- if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
- shift @ARGV;
- my $cxx;
+ if ($arg eq "--status-bugs") {
+ shift @$Args;
+ $Options{ExitStatusFoundBugs} = 1;
+ next;
+ }
- if (!defined $2 || $2 eq "") {
- if (!@ARGV) {
- DieDiag("'--use-c++' option requires a compiler executable name.\n");
- }
- $cxx = shift @ARGV;
+ if ($arg eq "-store") {
+ shift @$Args;
+ $Options{StoreModel} = shift @$Args;
+ next;
}
- else {
- $cxx = $2;
+
+ if ($arg eq "-constraints") {
+ shift @$Args;
+ $Options{ConstraintsModel} = shift @$Args;
+ next;
}
- $ENV{"CCC_CXX"} = $cxx;
- next;
- }
+ if ($arg eq "-internal-stats") {
+ shift @$Args;
+ $Options{InternalStats} = 1;
+ next;
+ }
- if ($arg eq "-v") {
- shift @ARGV;
- $Verbose++;
- next;
- }
+ if ($arg eq "-plist") {
+ shift @$Args;
+ $Options{OutputFormat} = "plist";
+ next;
+ }
- if ($arg eq "-V" or $arg eq "--view") {
- shift @ARGV;
- $ViewResults = 1;
- next;
- }
+ if ($arg eq "-plist-html") {
+ shift @$Args;
+ $Options{OutputFormat} = "plist-html";
+ next;
+ }
- if ($arg eq "--status-bugs") {
- shift @ARGV;
- $ExitStatusFoundBugs = 1;
- next;
- }
+ if ($arg eq "-analyzer-config") {
+ shift @$Args;
+ push @{$Options{ConfigOptions}}, shift @$Args;
+ next;
+ }
- if ($arg eq "-store") {
- shift @ARGV;
- $StoreModel = shift @ARGV;
- next;
- }
+ if ($arg eq "-no-failure-reports") {
+ shift @$Args;
+ $Options{ReportFailures} = 0;
+ next;
+ }
- if ($arg eq "-constraints") {
- shift @ARGV;
- $ConstraintsModel = shift @ARGV;
- next;
- }
+ if ($arg eq "-stats") {
+ shift @$Args;
+ $Options{AnalyzerStats} = 1;
+ next;
+ }
- if ($arg eq "-internal-stats") {
- shift @ARGV;
- $InternalStats = 1;
- next;
- }
+ if ($arg eq "-maxloop") {
+ shift @$Args;
+ $Options{MaxLoop} = shift @$Args;
+ next;
+ }
- if ($arg eq "-plist") {
- shift @ARGV;
- $OutputFormat = "plist";
- next;
- }
- if ($arg eq "-plist-html") {
- shift @ARGV;
- $OutputFormat = "plist-html";
- next;
- }
+ if ($arg eq "-enable-checker") {
+ shift @$Args;
+ my $Checker = shift @$Args;
+ # Store $NumArgs to preserve the order the checkers were enabled.
+ $Options{EnableCheckers}{$Checker} = $NumArgs;
+ delete $Options{DisableCheckers}{$Checker};
+ next;
+ }
- if ($arg eq "-analyzer-config") {
- shift @ARGV;
- push @ConfigOptions, "-analyzer-config", shift @ARGV;
- next;
- }
+ if ($arg eq "-disable-checker") {
+ shift @$Args;
+ my $Checker = shift @$Args;
+ # Store $NumArgs to preserve the order the checkers were disabled.
+ $Options{DisableCheckers}{$Checker} = $NumArgs;
+ delete $Options{EnableCheckers}{$Checker};
+ next;
+ }
- if ($arg eq "-no-failure-reports") {
- shift @ARGV;
- $ENV{"CCC_REPORT_FAILURES"} = 0;
- next;
- }
- if ($arg eq "-stats") {
- shift @ARGV;
- $AnalyzerStats = 1;
- next;
- }
- if ($arg eq "-maxloop") {
- shift @ARGV;
- $MaxLoop = shift @ARGV;
- next;
- }
- if ($arg eq "-enable-checker") {
- shift @ARGV;
- push @AnalysesToRun, "-analyzer-checker", shift @ARGV;
- next;
- }
- if ($arg eq "-disable-checker") {
- shift @ARGV;
- push @AnalysesToRun, "-analyzer-disable-checker", shift @ARGV;
- next;
- }
- if ($arg eq "-load-plugin") {
- shift @ARGV;
- push @PluginsToLoad, "-load", shift @ARGV;
- next;
- }
- if ($arg eq "--use-analyzer") {
- shift @ARGV;
- $AnalyzerDiscoveryMethod = shift @ARGV;
- next;
- }
- if ($arg =~ /^--use-analyzer=(.+)$/) {
- shift @ARGV;
- $AnalyzerDiscoveryMethod = $1;
- next;
- }
- if ($arg eq "--keep-empty") {
- shift @ARGV;
- $KeepEmpty = 1;
- next;
- }
+ if ($arg eq "-load-plugin") {
+ shift @$Args;
+ push @{$Options{PluginsToLoad}}, shift @$Args;
+ next;
+ }
- if ($arg eq "--override-compiler") {
- shift @ARGV;
- $OverrideCompiler = 1;
- next;
- }
+ if ($arg eq "--use-analyzer") {
+ shift @$Args;
+ $Options{AnalyzerDiscoveryMethod} = shift @$Args;
+ next;
+ }
+
+ if ($arg =~ /^--use-analyzer=(.+)$/) {
+ shift @$Args;
+ $Options{AnalyzerDiscoveryMethod} = $1;
+ next;
+ }
+
+ if ($arg eq "--keep-empty") {
+ shift @$Args;
+ $Options{KeepEmpty} = 1;
+ next;
+ }
+
+ if ($arg eq "--override-compiler") {
+ shift @$Args;
+ $Options{OverrideCompiler} = 1;
+ next;
+ }
- DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
+ DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
- last;
+ $NumArgs--;
+ last;
+ }
+ return $NumArgs;
+}
+
+if (!@ARGV) {
+ $ForceDisplayHelp = 1
}
+ProcessArgs(\@ARGV);
+# All arguments are now shifted from @ARGV. The rest is a build command, if any.
+
if (!@ARGV and !$RequestDisplayHelp) {
ErrorDiag("No build command specified.\n\n");
$ForceDisplayHelp = 1;
}
-# Find 'clang'
-if (!defined $AnalyzerDiscoveryMethod) {
- $Clang = Cwd::realpath("$RealBin/bin/clang");
- if (!defined $Clang || ! -x $Clang) {
- $Clang = Cwd::realpath("$RealBin/clang");
- }
- if (!defined $Clang || ! -x $Clang) {
- if (!$RequestDisplayHelp && !$ForceDisplayHelp) {
- DieDiag("error: Cannot find an executable 'clang' relative to scan-build." .
- " Consider using --use-analyzer to pick a version of 'clang' to use for static analysis.\n");
- }
- }
-}
-else {
- if ($AnalyzerDiscoveryMethod =~ /^[Xx]code$/) {
- my $xcrun = `which xcrun`;
- chomp $xcrun;
- if ($xcrun eq "") {
- DieDiag("Cannot find 'xcrun' to find 'clang' for analysis.\n");
- }
- $Clang = `$xcrun -toolchain XcodeDefault -find clang`;
- chomp $Clang;
- if ($Clang eq "") {
- DieDiag("No 'clang' executable found by 'xcrun'\n");
- }
- }
- else {
- $Clang = $AnalyzerDiscoveryMethod;
- if (!defined $Clang or not -x $Clang) {
- DieDiag("Cannot find an executable clang at '$AnalyzerDiscoveryMethod'\n");
- }
- }
-}
+my $ClangNotFoundErrMsg = FindClang();
if ($ForceDisplayHelp || $RequestDisplayHelp) {
- DisplayHelp();
+ DisplayHelp($ClangNotFoundErrMsg);
exit $ForceDisplayHelp;
}
+DieDiag($ClangNotFoundErrMsg) if (defined $ClangNotFoundErrMsg);
+
$ClangCXX = $Clang;
-# Determine operating system under which this copy of Perl was built.
-my $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/);
-if($IsWinBuild) {
- $ClangCXX =~ s/.exe$/++.exe/;
-}
-else {
- $ClangCXX =~ s/\-\d+\.\d+$//;
- $ClangCXX .= "++";
+if ($Clang !~ /\+\+(\.exe)?$/) {
+ # If $Clang holds the name of the clang++ executable then we leave
+ # $ClangCXX and $Clang equal, otherwise construct the name of the clang++
+ # executable from the clang executable name.
+
+ # Determine operating system under which this copy of Perl was built.
+ my $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/);
+ if($IsWinBuild) {
+ $ClangCXX =~ s/.exe$/++.exe/;
+ }
+ else {
+ $ClangCXX =~ s/\-\d+\.\d+$//;
+ $ClangCXX .= "++";
+ }
}
# Make sure to use "" to handle paths with spaces.
@@ -1632,17 +1732,15 @@ $ClangVersion = HtmlEscape(`"$Clang" --version`);
# Determine where results go.
$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV)));
-$HtmlTitle = "${CurrentDirSuffix} - scan-build results"
- unless (defined($HtmlTitle));
# Determine the output directory for the HTML reports.
-my $BaseDir = $HtmlDir;
-$HtmlDir = GetHTMLRunDir($HtmlDir);
+my $BaseDir = $Options{OutputDir};
+$Options{OutputDir} = GetHTMLRunDir($Options{OutputDir});
# Determine the location of ccc-analyzer.
my $AbsRealBin = Cwd::realpath($RealBin);
-my $Cmd = "$AbsRealBin/libexec/ccc-analyzer";
-my $CmdCXX = "$AbsRealBin/libexec/c++-analyzer";
+my $Cmd = "$AbsRealBin/../libexec/ccc-analyzer";
+my $CmdCXX = "$AbsRealBin/../libexec/c++-analyzer";
# Portability: use less strict but portable check -e (file exists) instead of
# non-portable -x (file is executable). On some windows ports -x just checks
@@ -1659,63 +1757,72 @@ if (!defined $CmdCXX || ! -e $CmdCXX) {
Diag("Using '$Clang' for static analysis\n");
-SetHtmlEnv(\@ARGV, $HtmlDir);
-if ($AnalyzeHeaders) { push @AnalysesToRun,"-analyzer-opt-analyze-headers"; }
-if ($AnalyzerStats) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; }
-if ($MaxLoop > 0) { push @AnalysesToRun, "-analyzer-max-loop $MaxLoop"; }
+SetHtmlEnv(\@ARGV, $Options{OutputDir});
+
+my @AnalysesToRun;
+foreach (sort { $Options{EnableCheckers}{$a} <=> $Options{EnableCheckers}{$b} }
+ keys %{$Options{EnableCheckers}}) {
+ # Push checkers in order they were enabled.
+ push @AnalysesToRun, "-analyzer-checker", $_;
+}
+foreach (sort { $Options{DisableCheckers}{$a} <=> $Options{DisableCheckers}{$b} }
+ keys %{$Options{DisableCheckers}}) {
+ # Push checkers in order they were disabled.
+ push @AnalysesToRun, "-analyzer-disable-checker", $_;
+}
+if ($Options{AnalyzeHeaders}) { push @AnalysesToRun, "-analyzer-opt-analyze-headers"; }
+if ($Options{AnalyzerStats}) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; }
+if ($Options{MaxLoop} > 0) { push @AnalysesToRun, "-analyzer-max-loop $Options{MaxLoop}"; }
# Delay setting up other environment variables in case we can do true
# interposition.
-my $CCC_ANALYZER_ANALYSIS = join ' ',@AnalysesToRun;
-my $CCC_ANALYZER_PLUGINS = join ' ',@PluginsToLoad;
-my $CCC_ANALYZER_CONFIG = join ' ',@ConfigOptions;
-my %Options = (
+my $CCC_ANALYZER_ANALYSIS = join ' ', @AnalysesToRun;
+my $CCC_ANALYZER_PLUGINS = join ' ', map { "-load ".$_ } @{$Options{PluginsToLoad}};
+my $CCC_ANALYZER_CONFIG = join ' ', map { "-analyzer-config ".$_ } @{$Options{ConfigOptions}};
+my %EnvVars = (
'CC' => $Cmd,
'CXX' => $CmdCXX,
'CLANG' => $Clang,
'CLANG_CXX' => $ClangCXX,
- 'VERBOSE' => $Verbose,
+ 'VERBOSE' => $Options{Verbose},
'CCC_ANALYZER_ANALYSIS' => $CCC_ANALYZER_ANALYSIS,
'CCC_ANALYZER_PLUGINS' => $CCC_ANALYZER_PLUGINS,
'CCC_ANALYZER_CONFIG' => $CCC_ANALYZER_CONFIG,
- 'OUTPUT_DIR' => $HtmlDir
+ 'OUTPUT_DIR' => $Options{OutputDir},
+ 'CCC_CC' => $Options{UseCC},
+ 'CCC_CXX' => $Options{UseCXX},
+ 'CCC_REPORT_FAILURES' => $Options{ReportFailures},
+ 'CCC_ANALYZER_STORE_MODEL' => $Options{StoreModel},
+ 'CCC_ANALYZER_CONSTRAINTS_MODEL' => $Options{ConstraintsModel},
+ 'CCC_ANALYZER_INTERNAL_STATS' => $Options{InternalStats},
+ 'CCC_ANALYZER_OUTPUT_FORMAT' => $Options{OutputFormat},
+ 'CLANG_ANALYZER_TARGET' => $Options{AnalyzerTarget}
);
-if (defined $StoreModel) {
- $Options{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel;
-}
-if (defined $ConstraintsModel) {
- $Options{'CCC_ANALYZER_CONSTRAINTS_MODEL'} = $ConstraintsModel;
-}
-if (defined $InternalStats) {
- $Options{'CCC_ANALYZER_INTERNAL_STATS'} = 1;
-}
-if (defined $OutputFormat) {
- $Options{'CCC_ANALYZER_OUTPUT_FORMAT'} = $OutputFormat;
-}
-
# Run the build.
-my $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd, $CmdCXX,
- \%Options);
+my $ExitStatus = RunBuildCommand(\@ARGV, $Options{IgnoreErrors}, $Cmd, $CmdCXX,
+ \%EnvVars);
-if (defined $OutputFormat) {
- if ($OutputFormat =~ /plist/) {
+if (defined $Options{OutputFormat}) {
+ if ($Options{OutputFormat} =~ /plist/) {
Diag "Analysis run complete.\n";
- Diag "Analysis results (plist files) deposited in '$HtmlDir'\n";
+ Diag "Analysis results (plist files) deposited in '$Options{OutputDir}'\n";
}
- if ($OutputFormat =~ /html/) {
+ if ($Options{OutputFormat} =~ /html/) {
# Postprocess the HTML directory.
- my $NumBugs = Postprocess($HtmlDir, $BaseDir, $AnalyzerStats, $KeepEmpty);
+ my $NumBugs = Postprocess($Options{OutputDir}, $BaseDir,
+ $Options{AnalyzerStats}, $Options{KeepEmpty});
- if ($ViewResults and -r "$HtmlDir/index.html") {
+ if ($Options{ViewResults} and -r "$Options{OutputDir}/index.html") {
Diag "Analysis run complete.\n";
- Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n";
+ Diag "Viewing analysis results in '$Options{OutputDir}' using scan-view.\n";
my $ScanView = Cwd::realpath("$RealBin/scan-view");
if (! -x $ScanView) { $ScanView = "scan-view"; }
- exec $ScanView, "$HtmlDir";
+ if (! -x $ScanView) { $ScanView = Cwd::realpath("$RealBin/../../scan-view/bin/scan-view"); }
+ exec $ScanView, "$Options{OutputDir}";
}
- if ($ExitStatusFoundBugs) {
+ if ($Options{ExitStatusFoundBugs}) {
exit 1 if ($NumBugs > 0);
exit 0;
}
diff --git a/tools/scan-build/scan-build.bat b/tools/scan-build/bin/scan-build.bat
index 77be6746318f1..77be6746318f1 100644
--- a/tools/scan-build/scan-build.bat
+++ b/tools/scan-build/bin/scan-build.bat
diff --git a/tools/scan-build/set-xcode-analyzer b/tools/scan-build/bin/set-xcode-analyzer
index 8e674823ba66c..8e674823ba66c 100755
--- a/tools/scan-build/set-xcode-analyzer
+++ b/tools/scan-build/bin/set-xcode-analyzer
diff --git a/tools/scan-build/c++-analyzer b/tools/scan-build/libexec/c++-analyzer
index dda5db9c7d925..dda5db9c7d925 100755
--- a/tools/scan-build/c++-analyzer
+++ b/tools/scan-build/libexec/c++-analyzer
diff --git a/tools/scan-build/c++-analyzer.bat b/tools/scan-build/libexec/c++-analyzer.bat
index 69f048a91671f..69f048a91671f 100644
--- a/tools/scan-build/c++-analyzer.bat
+++ b/tools/scan-build/libexec/c++-analyzer.bat
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/libexec/ccc-analyzer
index 14591aef57c87..831dd42e9c9c0 100755
--- a/tools/scan-build/ccc-analyzer
+++ b/tools/scan-build/libexec/ccc-analyzer
@@ -68,6 +68,7 @@ my $Clang;
my $DefaultCCompiler;
my $DefaultCXXCompiler;
my $IsCXX;
+my $AnalyzerTarget;
# If on OSX, use xcrun to determine the SDK root.
my $UseXCRUN = 0;
@@ -104,6 +105,8 @@ else {
$IsCXX = 0
}
+$AnalyzerTarget = $ENV{'CLANG_ANALYZER_TARGET'};
+
##===----------------------------------------------------------------------===##
# Cleanup.
##===----------------------------------------------------------------------===##
@@ -245,6 +248,10 @@ sub Analyze {
push @Args, "-Xclang", "-analyzer-viz-egraph-ubigraph";
}
+ if (defined $AnalyzerTarget) {
+ push @Args, "-target", $AnalyzerTarget;
+ }
+
my $AnalysisArgs = GetCCArgs($HtmlDir, "--analyze", \@Args);
@CmdArgs = @$AnalysisArgs;
}
@@ -275,7 +282,7 @@ sub Analyze {
# We save the output file in the 'crashes' directory if clang encounters
# any problems with the file.
my ($ofh, $ofile) = tempfile("clang_output_XXXXXX", DIR => $HtmlDir);
-
+
my $OutputStream = silent_system($HtmlDir, $Cmd, @CmdArgs);
while ( <$OutputStream> ) {
print $ofh $_;
@@ -579,7 +586,7 @@ foreach (my $i = 0; $i < scalar(@ARGV); ++$i) {
}
# Compile mode flags.
- if ($Arg =~ /^-[D,I,U,isystem](.*)$/) {
+ if ($Arg =~ /^-(?:[DIU]|isystem)(.*)$/) {
my $Tmp = $Arg;
if ($1 eq '') {
# FIXME: Check if we are going off the end.
@@ -660,6 +667,15 @@ foreach (my $i = 0; $i < scalar(@ARGV); ++$i) {
next;
}
+ # Handle -Xclang some-arg. Add both arguments to the compiler options.
+ if ($Arg =~ /^-Xclang$/) {
+ # FIXME: Check if we are going off the end.
+ ++$i;
+ push @CompileOpts, $Arg;
+ push @CompileOpts, $ARGV[$i];
+ next;
+ }
+
if (!($Arg =~ /^-/)) {
push @Files, $Arg;
next;
diff --git a/tools/scan-build/ccc-analyzer.bat b/tools/scan-build/libexec/ccc-analyzer.bat
index 2a85376eb82b1..2a85376eb82b1 100644
--- a/tools/scan-build/ccc-analyzer.bat
+++ b/tools/scan-build/libexec/ccc-analyzer.bat
diff --git a/tools/scan-build/scan-build.1 b/tools/scan-build/man/scan-build.1
index 57333642ce168..fd18d1f5c70a2 100644
--- a/tools/scan-build/scan-build.1
+++ b/tools/scan-build/man/scan-build.1
@@ -1,6 +1,6 @@
.\" This file is distributed under the University of Illinois Open Source
.\" License. See LICENSE.TXT for details.
-.\" $Id: scan-build.1 201182 2014-02-11 21:37:27Z sylvestre $
+.\" $Id: scan-build.1 253074 2015-11-13 20:34:15Z jroelofs $
.Dd May 25, 2012
.Dt SCAN-BUILD 1
.Os "clang" "3.5"
diff --git a/tools/scan-build/scanview.css b/tools/scan-build/share/scan-build/scanview.css
index cf8a5a6ad470c..cf8a5a6ad470c 100644
--- a/tools/scan-build/scanview.css
+++ b/tools/scan-build/share/scan-build/scanview.css
diff --git a/tools/scan-build/sorttable.js b/tools/scan-build/share/scan-build/sorttable.js
index 32faa078d8993..32faa078d8993 100644
--- a/tools/scan-build/sorttable.js
+++ b/tools/scan-build/share/scan-build/sorttable.js
diff --git a/tools/scan-view/CMakeLists.txt b/tools/scan-view/CMakeLists.txt
new file mode 100644
index 0000000000000..b305ca562a72b
--- /dev/null
+++ b/tools/scan-view/CMakeLists.txt
@@ -0,0 +1,41 @@
+option(CLANG_INSTALL_SCANVIEW "Install the scan-view tool" ON)
+
+set(BinFiles
+ scan-view)
+
+set(ShareFiles
+ ScanView.py
+ Reporter.py
+ startfile.py
+ FileRadar.scpt
+ GetRadarVersion.scpt
+ bugcatcher.ico)
+
+if(CLANG_INSTALL_SCANVIEW)
+ foreach(BinFile ${BinFiles})
+ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${BinFile}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/bin
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile}
+ ${CMAKE_BINARY_DIR}/bin/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile})
+ list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${BinFile})
+ install(PROGRAMS bin/${BinFile} DESTINATION bin)
+ endforeach()
+
+ foreach(ShareFile ${ShareFiles})
+ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/share/scan-view/${ShareFile}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${CMAKE_BINARY_DIR}/share/scan-view
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/share/${ShareFile}
+ ${CMAKE_BINARY_DIR}/share/scan-view/
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/share/${ShareFile})
+ list(APPEND Depends ${CMAKE_BINARY_DIR}/share/scan-view/${ShareFile})
+ install(FILES share/${ShareFile} DESTINATION share/scan-view)
+ endforeach()
+
+ add_custom_target(scan-view ALL DEPENDS ${Depends})
+ set_target_properties(scan-view PROPERTIES FOLDER "Misc")
+endif()
diff --git a/tools/scan-view/Makefile b/tools/scan-view/Makefile
new file mode 100644
index 0000000000000..37e4404d6f833
--- /dev/null
+++ b/tools/scan-view/Makefile
@@ -0,0 +1,37 @@
+##===- tools/scan-view/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+
+include $(CLANG_LEVEL)/../../Makefile.config
+include $(CLANG_LEVEL)/Makefile
+
+CLANG_INSTALL_SCANVIEW ?= 1
+
+ifeq ($(CLANG_INSTALL_SCANVIEW), 1)
+ InstallTargets := $(ToolDir)/scan-view \
+ $(ShareDir)/scan-view/Reporter.py \
+ $(ShareDir)/scan-view/ScanView.py \
+ $(ShareDir)/scan-view/startfile.py \
+ $(ShareDir)/scan-view/FileRadar.scpt \
+ $(ShareDir)/scan-view/GetRadarVersion.scpt \
+ $(ShareDir)/scan-view/bugcatcher.ico
+endif
+
+all:: $(InstallTargets)
+
+$(ToolDir)/%: bin/% Makefile $(ToolDir)/.dir
+ $(Echo) "Copying $(notdir $<) to the 'bin' directory..."
+ $(Verb)cp $< $@
+ $(Verb)chmod +x $@
+
+$(ShareDir)/scan-view/%: share/% Makefile $(ShareDir)/scan-view/.dir
+ $(Echo) "Copying $(notdir $<) to the 'share' directory..."
+ $(Verb)cp $< $@
+
diff --git a/tools/scan-view/bin/scan-view b/tools/scan-view/bin/scan-view
new file mode 100755
index 0000000000000..1b6e8ba90dfac
--- /dev/null
+++ b/tools/scan-view/bin/scan-view
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+
+"""The clang static analyzer results viewer.
+"""
+
+import sys
+import imp
+import os
+import posixpath
+import thread
+import time
+import urllib
+import webbrowser
+
+# How long to wait for server to start.
+kSleepTimeout = .05
+kMaxSleeps = int(60 / kSleepTimeout)
+
+# Default server parameters
+
+kDefaultHost = '127.0.0.1'
+kDefaultPort = 8181
+kMaxPortsToTry = 100
+
+###
+
+
+def url_is_up(url):
+ try:
+ o = urllib.urlopen(url)
+ except IOError:
+ return False
+ o.close()
+ return True
+
+
+def start_browser(port, options):
+ import urllib
+ import webbrowser
+
+ url = 'http://%s:%d' % (options.host, port)
+
+ # Wait for server to start...
+ if options.debug:
+ sys.stderr.write('%s: Waiting for server.' % sys.argv[0])
+ sys.stderr.flush()
+ for i in range(kMaxSleeps):
+ if url_is_up(url):
+ break
+ if options.debug:
+ sys.stderr.write('.')
+ sys.stderr.flush()
+ time.sleep(kSleepTimeout)
+ else:
+ print >> sys.stderr, 'WARNING: Unable to detect that server started.'
+
+ if options.debug:
+ print >> sys.stderr, '%s: Starting webbrowser...' % sys.argv[0]
+ webbrowser.open(url)
+
+
+def run(port, options, root):
+ # Prefer to look relative to the installed binary
+ share = os.path.dirname(__file__) + "/../share/scan-view"
+ if not os.path.isdir(share):
+ # Otherwise look relative to the source
+ share = os.path.dirname(__file__) + "/../../scan-view/share"
+ sys.path.append(share)
+
+ import ScanView
+ try:
+ print 'Starting scan-view at: http://%s:%d' % (options.host,
+ port)
+ print ' Use Ctrl-C to exit.'
+ httpd = ScanView.create_server((options.host, port),
+ options, root)
+ httpd.serve_forever()
+ except KeyboardInterrupt:
+ pass
+
+
+def port_is_open(port):
+ import SocketServer
+ try:
+ t = SocketServer.TCPServer((kDefaultHost, port), None)
+ except:
+ return False
+ t.server_close()
+ return True
+
+
+def main():
+ import argparse
+ parser = argparse.ArgumentParser(description="The clang static analyzer "
+ "results viewer.")
+ parser.add_argument("root", metavar="<results directory>", type=str)
+ parser.add_argument(
+ '--host', dest="host", default=kDefaultHost, type=str,
+ help="Host interface to listen on. (default=%s)" % kDefaultHost)
+ parser.add_argument('--port', dest="port", default=None, type=int,
+ help="Port to listen on. (default=%s)" % kDefaultPort)
+ parser.add_argument("--debug", dest="debug", default=0,
+ action="count",
+ help="Print additional debugging information.")
+ parser.add_argument("--auto-reload", dest="autoReload", default=False,
+ action="store_true",
+ help="Automatically update module for each request.")
+ parser.add_argument("--no-browser", dest="startBrowser", default=True,
+ action="store_false",
+ help="Don't open a webbrowser on startup.")
+ parser.add_argument("--allow-all-hosts", dest="onlyServeLocal",
+ default=True, action="store_false",
+ help='Allow connections from any host (access '
+ 'restricted to "127.0.0.1" by default)')
+ args = parser.parse_args()
+
+ # Make sure this directory is in a reasonable state to view.
+ if not posixpath.exists(posixpath.join(args.root, 'index.html')):
+ parser.error('Invalid directory, analysis results not found!')
+
+ # Find an open port. We aren't particularly worried about race
+ # conditions here. Note that if the user specified a port we only
+ # use that one.
+ if args.port is not None:
+ port = args.port
+ else:
+ for i in range(kMaxPortsToTry):
+ if port_is_open(kDefaultPort + i):
+ port = kDefaultPort + i
+ break
+ else:
+ parser.error('Unable to find usable port in [%d,%d)' %
+ (kDefaultPort, kDefaultPort+kMaxPortsToTry))
+
+ # Kick off thread to wait for server and start web browser, if
+ # requested.
+ if args.startBrowser:
+ t = thread.start_new_thread(start_browser, (port, args))
+
+ run(port, args, args.root)
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/scan-view/scan-view b/tools/scan-view/scan-view
deleted file mode 100755
index fb27da698882e..0000000000000
--- a/tools/scan-view/scan-view
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/env python
-
-"""The clang static analyzer results viewer.
-"""
-
-import sys
-import posixpath
-import thread
-import time
-import urllib
-import webbrowser
-
-# How long to wait for server to start.
-kSleepTimeout = .05
-kMaxSleeps = int(60 / kSleepTimeout)
-
-# Default server parameters
-
-kDefaultHost = '127.0.0.1'
-kDefaultPort = 8181
-kMaxPortsToTry = 100
-
-###
-
-def url_is_up(url):
- try:
- o = urllib.urlopen(url)
- except IOError:
- return False
- o.close()
- return True
-
-def start_browser(port, options):
- import urllib, webbrowser
-
- url = 'http://%s:%d'%(options.host, port)
-
- # Wait for server to start...
- if options.debug:
- sys.stderr.write('%s: Waiting for server.' % sys.argv[0])
- sys.stderr.flush()
- for i in range(kMaxSleeps):
- if url_is_up(url):
- break
- if options.debug:
- sys.stderr.write('.')
- sys.stderr.flush()
- time.sleep(kSleepTimeout)
- else:
- print >>sys.stderr,'WARNING: Unable to detect that server started.'
-
- if options.debug:
- print >>sys.stderr,'%s: Starting webbrowser...' % sys.argv[0]
- webbrowser.open(url)
-
-def run(port, options, root):
- import ScanView
- try:
- print 'Starting scan-view at: http://%s:%d'%(options.host,
- port)
- print ' Use Ctrl-C to exit.'
- httpd = ScanView.create_server((options.host, port),
- options, root)
- httpd.serve_forever()
- except KeyboardInterrupt:
- pass
-
-def port_is_open(port):
- import SocketServer
- try:
- t = SocketServer.TCPServer((kDefaultHost,port),None)
- except:
- return False
- t.server_close()
- return True
-
-def main():
- from optparse import OptionParser
- parser = OptionParser('usage: %prog [options] <results directory>')
- parser.set_description(__doc__)
- parser.add_option(
- '--host', dest="host", default=kDefaultHost, type="string",
- help="Host interface to listen on. (default=%s)" % kDefaultHost)
- parser.add_option(
- '--port', dest="port", default=None, type="int",
- help="Port to listen on. (default=%s)" % kDefaultPort)
- parser.add_option("--debug", dest="debug", default=0,
- action="count",
- help="Print additional debugging information.")
- parser.add_option("--auto-reload", dest="autoReload", default=False,
- action="store_true",
- help="Automatically update module for each request.")
- parser.add_option("--no-browser", dest="startBrowser", default=True,
- action="store_false",
- help="Don't open a webbrowser on startup.")
- parser.add_option("--allow-all-hosts", dest="onlyServeLocal", default=True,
- action="store_false",
- help='Allow connections from any host (access restricted to "127.0.0.1" by default)')
- (options, args) = parser.parse_args()
-
- if len(args) != 1:
- parser.error('No results directory specified.')
- root, = args
-
- # Make sure this directory is in a reasonable state to view.
- if not posixpath.exists(posixpath.join(root,'index.html')):
- parser.error('Invalid directory, analysis results not found!')
-
- # Find an open port. We aren't particularly worried about race
- # conditions here. Note that if the user specified a port we only
- # use that one.
- if options.port is not None:
- port = options.port
- else:
- for i in range(kMaxPortsToTry):
- if port_is_open(kDefaultPort + i):
- port = kDefaultPort + i
- break
- else:
- parser.error('Unable to find usable port in [%d,%d)'%(kDefaultPort,
- kDefaultPort+kMaxPortsToTry))
-
- # Kick off thread to wait for server and start web browser, if
- # requested.
- if options.startBrowser:
- t = thread.start_new_thread(start_browser, (port,options))
-
- run(port, options, root)
-
-if __name__ == '__main__':
- main()
diff --git a/tools/scan-view/Resources/FileRadar.scpt b/tools/scan-view/share/FileRadar.scpt
index 1c7455285ccb0..1c7455285ccb0 100644
--- a/tools/scan-view/Resources/FileRadar.scpt
+++ b/tools/scan-view/share/FileRadar.scpt
Binary files differ
diff --git a/tools/scan-view/Resources/GetRadarVersion.scpt b/tools/scan-view/share/GetRadarVersion.scpt
index e69de29bb2d1d..e69de29bb2d1d 100644
--- a/tools/scan-view/Resources/GetRadarVersion.scpt
+++ b/tools/scan-view/share/GetRadarVersion.scpt
diff --git a/tools/scan-view/Reporter.py b/tools/scan-view/share/Reporter.py
index 9560fc1aabbb3..294e05b44c251 100644
--- a/tools/scan-view/Reporter.py
+++ b/tools/scan-view/share/Reporter.py
@@ -175,7 +175,7 @@ class RadarReporter:
@staticmethod
def isAvailable():
# FIXME: Find this .scpt better
- path = os.path.join(os.path.dirname(__file__),'Resources/GetRadarVersion.scpt')
+ path = os.path.join(os.path.dirname(__file__),'../share/scan-view/GetRadarVersion.scpt')
try:
p = subprocess.Popen(['osascript',path],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -206,7 +206,7 @@ class RadarReporter:
if not componentVersion.strip():
componentVersion = 'X'
- script = os.path.join(os.path.dirname(__file__),'Resources/FileRadar.scpt')
+ script = os.path.join(os.path.dirname(__file__),'../share/scan-view/FileRadar.scpt')
args = ['osascript', script, component, componentVersion, classification, personID, report.title,
report.description, diagnosis, config] + map(os.path.abspath, report.files)
# print >>sys.stderr, args
diff --git a/tools/scan-view/ScanView.py b/tools/scan-view/share/ScanView.py
index ee08baa8bad05..7dc0351ebe7f5 100644
--- a/tools/scan-view/ScanView.py
+++ b/tools/scan-view/share/ScanView.py
@@ -73,7 +73,7 @@ kReportReplacements.append((re.compile('<!-- REPORTSUMMARYEXTRA -->'),
###
# Other simple parameters
-kResources = posixpath.join(posixpath.dirname(__file__), 'Resources')
+kShare = posixpath.join(posixpath.dirname(__file__), '../share/scan-view')
kConfigPath = os.path.expanduser('~/.scanview.cfg')
###
@@ -680,7 +680,7 @@ File Bug</h3>
overrides['Radar']['Component Version'] = 'X'
return self.send_report(None, overrides)
elif name=='favicon.ico':
- return self.send_path(posixpath.join(kResources,'bugcatcher.ico'))
+ return self.send_path(posixpath.join(kShare,'bugcatcher.ico'))
# Match directory entries.
if components[-1] == '':
diff --git a/tools/scan-view/Resources/bugcatcher.ico b/tools/scan-view/share/bugcatcher.ico
index 22d39b592036d..22d39b592036d 100644
--- a/tools/scan-view/Resources/bugcatcher.ico
+++ b/tools/scan-view/share/bugcatcher.ico
Binary files differ
diff --git a/tools/scan-view/startfile.py b/tools/scan-view/share/startfile.py
index e8fbe2d5a84ee..e8fbe2d5a84ee 100644
--- a/tools/scan-view/startfile.py
+++ b/tools/scan-view/share/startfile.py