summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
committerdim <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
commitea266cad53e3d49771fa38103913d3ec7a166694 (patch)
tree8f7776b7310bebaf415ac5b69e46e9f928c37144 /tools
parentc72c57c9e9b69944e3e009cd5e209634839581d3 (diff)
downloadFreeBSD-src-ea266cad53e3d49771fa38103913d3ec7a166694.zip
FreeBSD-src-ea266cad53e3d49771fa38103913d3ec7a166694.tar.gz
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3
release): http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_33/final@183502
Diffstat (limited to 'tools')
-rw-r--r--tools/c-index-test/c-index-test.c133
-rw-r--r--tools/clang-format/ClangFormat.cpp87
-rw-r--r--tools/clang-format/clang-format-bbedit.applescript27
-rwxr-xr-xtools/clang-format/clang-format-diff.py11
-rw-r--r--tools/clang-format/clang-format.el31
-rw-r--r--tools/clang-format/clang-format.py7
-rw-r--r--tools/libclang/CIndex.cpp91
-rw-r--r--tools/libclang/CIndexCXX.cpp2
-rw-r--r--tools/libclang/CXCursor.cpp24
-rw-r--r--tools/libclang/CXSourceLocation.cpp11
-rw-r--r--tools/libclang/CXTranslationUnit.h2
-rw-r--r--tools/libclang/CXType.cpp132
-rw-r--r--tools/libclang/IndexBody.cpp9
-rw-r--r--tools/libclang/IndexDecl.cpp5
-rw-r--r--tools/libclang/Indexing.cpp9
-rw-r--r--tools/libclang/IndexingContext.cpp6
-rw-r--r--tools/libclang/IndexingContext.h3
-rw-r--r--tools/libclang/RecursiveASTVisitor.h28
-rw-r--r--tools/libclang/libclang.exports9
-rwxr-xr-x[l---------]tools/scan-build/c++-analyzer9
-rwxr-xr-xtools/scan-build/ccc-analyzer2
-rwxr-xr-xtools/scan-build/scan-build16
-rw-r--r--tools/scan-build/scan-build.bat1
-rw-r--r--tools/scan-view/ScanView.py16
24 files changed, 600 insertions, 71 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 88b49ed..e575234 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -694,6 +694,9 @@ static void PrintCursor(CXCursor Cursor,
printf(" (static)");
if (clang_CXXMethod_isVirtual(Cursor))
printf(" (virtual)");
+
+ if (clang_Cursor_isVariadic(Cursor))
+ printf(" (variadic)");
if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
CXType T =
@@ -787,6 +790,44 @@ static void PrintCursor(CXCursor Cursor,
}
PrintCursorComments(Cursor, ValidationData);
+
+ {
+ unsigned PropAttrs = clang_Cursor_getObjCPropertyAttributes(Cursor, 0);
+ if (PropAttrs != CXObjCPropertyAttr_noattr) {
+ printf(" [");
+ #define PRINT_PROP_ATTR(A) \
+ if (PropAttrs & CXObjCPropertyAttr_##A) printf(#A ",")
+ PRINT_PROP_ATTR(readonly);
+ PRINT_PROP_ATTR(getter);
+ PRINT_PROP_ATTR(assign);
+ PRINT_PROP_ATTR(readwrite);
+ PRINT_PROP_ATTR(retain);
+ PRINT_PROP_ATTR(copy);
+ PRINT_PROP_ATTR(nonatomic);
+ PRINT_PROP_ATTR(setter);
+ PRINT_PROP_ATTR(atomic);
+ PRINT_PROP_ATTR(weak);
+ PRINT_PROP_ATTR(strong);
+ PRINT_PROP_ATTR(unsafe_unretained);
+ printf("]");
+ }
+ }
+
+ {
+ unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor);
+ if (QT != CXObjCDeclQualifier_None) {
+ printf(" [");
+ #define PRINT_OBJC_QUAL(A) \
+ if (QT & CXObjCDeclQualifier_##A) printf(#A ",")
+ PRINT_OBJC_QUAL(In);
+ PRINT_OBJC_QUAL(Inout);
+ PRINT_OBJC_QUAL(Out);
+ PRINT_OBJC_QUAL(Bycopy);
+ PRINT_OBJC_QUAL(Byref);
+ PRINT_OBJC_QUAL(Oneway);
+ printf("]");
+ }
+ }
}
}
@@ -934,6 +975,23 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
GetCursorSource(Cursor), line, column);
PrintCursor(Cursor, &Data->ValidationData);
PrintCursorExtent(Cursor);
+ if (clang_isDeclaration(Cursor.kind)) {
+ enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
+ const char *accessStr = 0;
+
+ switch (access) {
+ case CX_CXXInvalidAccessSpecifier: break;
+ case CX_CXXPublic:
+ accessStr = "public"; break;
+ case CX_CXXProtected:
+ accessStr = "protected"; break;
+ case CX_CXXPrivate:
+ accessStr = "private"; break;
+ }
+
+ if (accessStr)
+ printf(" [access=%s]", accessStr);
+ }
printf("\n");
return CXChildVisit_Recurse;
}
@@ -1144,6 +1202,61 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
return CXChildVisit_Recurse;
}
+static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p,
+ CXClientData d) {
+ CXType T;
+ enum CXCursorKind K = clang_getCursorKind(cursor);
+ if (clang_isInvalid(K))
+ return CXChildVisit_Recurse;
+ T = clang_getCursorType(cursor);
+ PrintCursor(cursor, NULL);
+ PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
+ /* Print the type sizeof if applicable. */
+ {
+ long long Size = clang_Type_getSizeOf(T);
+ if (Size >= 0 || Size < -1 ) {
+ printf(" [sizeof=%lld]", Size);
+ }
+ }
+ /* Print the type alignof if applicable. */
+ {
+ long long Align = clang_Type_getAlignOf(T);
+ if (Align >= 0 || Align < -1) {
+ printf(" [alignof=%lld]", Align);
+ }
+ }
+ /* Print the record field offset if applicable. */
+ {
+ const char *FieldName = clang_getCString(clang_getCursorSpelling(cursor));
+ /* recurse to get the root anonymous record parent */
+ CXCursor Parent, Root;
+ if (clang_getCursorKind(cursor) == CXCursor_FieldDecl ) {
+ const char *RootParentName;
+ Root = Parent = p;
+ do {
+ Root = Parent;
+ RootParentName = clang_getCString(clang_getCursorSpelling(Root));
+ Parent = clang_getCursorSemanticParent(Root);
+ } while ( clang_getCursorType(Parent).kind == CXType_Record &&
+ !strcmp(RootParentName, "") );
+ /* if RootParentName is "", record is anonymous. */
+ {
+ long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Root),
+ FieldName);
+ printf(" [offsetof=%lld]", Offset);
+ }
+ }
+ }
+ /* Print if its a bitfield */
+ {
+ int IsBitfield = clang_Cursor_isBitField(cursor);
+ if (IsBitfield)
+ printf(" [BitFieldSize=%d]", clang_getFieldDeclBitWidth(cursor));
+ }
+ printf("\n");
+ return CXChildVisit_Recurse;
+}
+
/******************************************************************************/
/* Bitwidth testing. */
/******************************************************************************/
@@ -1256,7 +1369,7 @@ int perform_test_load_source(int argc, const char **argv,
Idx = clang_createIndex(/* excludeDeclsFromPCH */
(!strcmp(filter, "local") ||
!strcmp(filter, "local-display"))? 1 : 0,
- /* displayDiagnostics=*/0);
+ /* displayDiagnostics=*/1);
if ((CommentSchemaFile = parse_comments_schema(argc, argv))) {
argc--;
@@ -1301,7 +1414,7 @@ int perform_test_reparse_source(int argc, const char **argv, int trials,
Idx = clang_createIndex(/* excludeDeclsFromPCH */
!strcmp(filter, "local") ? 1 : 0,
- /* displayDiagnostics=*/0);
+ /* displayDiagnostics=*/1);
if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
clang_disposeIndex(Idx);
@@ -1992,14 +2105,19 @@ static int inspect_cursor_at(int argc, const char **argv) {
{
CXModule mod = clang_Cursor_getModule(Cursor);
- CXString name;
+ CXFile astFile;
+ CXString name, astFilename;
unsigned i, numHeaders;
if (mod) {
+ astFile = clang_Module_getASTFile(mod);
+ astFilename = clang_getFileName(astFile);
name = clang_Module_getFullName(mod);
numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod);
- printf(" ModuleName=%s Headers(%d):",
- clang_getCString(name), numHeaders);
+ printf(" ModuleName=%s (%s) Headers(%d):",
+ clang_getCString(name), clang_getCString(astFilename),
+ numHeaders);
clang_disposeString(name);
+ clang_disposeString(astFilename);
for (i = 0; i < numHeaders; ++i) {
CXFile file = clang_Module_getTopLevelHeader(TU, mod, i);
CXString filename = clang_getFileName(file);
@@ -3395,6 +3513,7 @@ int write_pch_file(const char *filename, int argc, const char *argv[]) {
unsaved_files,
num_unsaved_files,
CXTranslationUnit_Incomplete |
+ CXTranslationUnit_DetailedPreprocessingRecord|
CXTranslationUnit_ForSerialization);
if (!TU) {
fprintf(stderr, "Unable to load translation unit!\n");
@@ -3642,6 +3761,7 @@ static void print_usage(void) {
fprintf(stderr,
" c-index-test -test-print-linkage-source {<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"
" c-index-test -print-usr [<CursorKind> {<args>}]*\n"
" c-index-test -print-usr-file <file>\n"
@@ -3728,6 +3848,9 @@ int cindextest_main(int argc, const char **argv) {
else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintType, 0);
+ else if (argc > 2 && strcmp(argv[1], "-test-print-type-size") == 0)
+ return perform_test_load_source(argc - 2, argv + 2, "all",
+ PrintTypeSize, 0);
else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintBitWidth, 0);
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index c4969b2..57833ed 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -27,22 +27,25 @@ using namespace llvm;
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
-static cl::list<int> Offsets(
- "offset", cl::desc("Format a range starting at this file offset."));
-static cl::list<int> Lengths(
- "length", cl::desc("Format a range of this length, -1 for end of file."));
+static cl::list<unsigned>
+Offsets("offset", cl::desc("Format a range starting at this file offset. Can "
+ "only be used with one input file."));
+static cl::list<unsigned>
+Lengths("length", cl::desc("Format a range of this length. "
+ "When it's not specified, end of file is used. "
+ "Can only be used with one input file."));
static cl::opt<std::string> Style(
"style",
- cl::desc("Coding style, currently supports: LLVM, Google, Chromium."),
+ cl::desc("Coding style, currently supports: LLVM, Google, Chromium, Mozilla."),
cl::init("LLVM"));
static cl::opt<bool> Inplace("i",
- cl::desc("Inplace edit <file>, if specified."));
+ cl::desc("Inplace edit <file>s, if specified."));
static cl::opt<bool> OutputXML(
"output-replacements-xml", cl::desc("Output replacements as XML."));
-static cl::opt<std::string> FileName(cl::Positional, cl::desc("[<file>]"),
- cl::init("-"));
+static cl::list<std::string> FileNames(cl::Positional,
+ cl::desc("[<file> ...]"));
namespace clang {
namespace format {
@@ -60,12 +63,18 @@ static FormatStyle getStyle() {
FormatStyle TheStyle = getGoogleStyle();
if (Style == "LLVM")
TheStyle = getLLVMStyle();
- if (Style == "Chromium")
+ else if (Style == "Chromium")
TheStyle = getChromiumStyle();
+ else if (Style == "Mozilla")
+ TheStyle = getMozillaStyle();
+ else if (Style != "Google")
+ llvm::errs() << "Unknown style " << Style << ", using Google style.\n";
+
return TheStyle;
}
-static void format() {
+// Returns true on error.
+static bool format(std::string FileName) {
FileManager Files((FileSystemOptions()));
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
@@ -74,7 +83,7 @@ static void format() {
OwningPtr<MemoryBuffer> Code;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(FileName, Code)) {
llvm::errs() << ec.message() << "\n";
- return;
+ return true;
}
FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
Lexer Lex(ID, Sources.getBuffer(ID), Sources, getFormattingLangOpts());
@@ -82,15 +91,27 @@ static void format() {
Offsets.push_back(0);
if (Offsets.size() != Lengths.size() &&
!(Offsets.size() == 1 && Lengths.empty())) {
- llvm::errs() << "Number of -offset and -length arguments must match.\n";
- return;
+ llvm::errs()
+ << "error: number of -offset and -length arguments must match.\n";
+ return true;
}
std::vector<CharSourceRange> Ranges;
- for (cl::list<int>::size_type i = 0, e = Offsets.size(); i != e; ++i) {
+ 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";
+ return true;
+ }
SourceLocation Start =
Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
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";
+ return true;
+ }
End = Start.getLocWithOffset(Lengths[i]);
} else {
End = Sources.getLocForEndOfFile(ID);
@@ -99,7 +120,8 @@ static void format() {
}
tooling::Replacements Replaces = reformat(getStyle(), Lex, Sources, Ranges);
if (OutputXML) {
- llvm::outs() << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
+ llvm::outs()
+ << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
for (tooling::Replacements::const_iterator I = Replaces.begin(),
E = Replaces.end();
I != E; ++I) {
@@ -114,14 +136,14 @@ static void format() {
tooling::applyAllReplacements(Replaces, Rewrite);
if (Inplace) {
if (Replaces.size() == 0)
- return; // Nothing changed, don't touch the file.
+ return false; // Nothing changed, don't touch the file.
std::string ErrorInfo;
llvm::raw_fd_ostream FileStream(FileName.c_str(), ErrorInfo,
llvm::raw_fd_ostream::F_Binary);
if (!ErrorInfo.empty()) {
llvm::errs() << "Error while writing file: " << ErrorInfo << "\n";
- return;
+ return true;
}
Rewrite.getEditBuffer(ID).write(FileStream);
FileStream.flush();
@@ -129,6 +151,7 @@ static void format() {
Rewrite.getEditBuffer(ID).write(outs());
}
}
+ return false;
}
} // namespace format
@@ -139,14 +162,32 @@ int main(int argc, const char **argv) {
cl::ParseCommandLineOptions(
argc, argv,
"A tool to format C/C++/Obj-C code.\n\n"
- "Currently supports LLVM and Google style guides.\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> is given, it reformats the file. If -i is specified together\n"
- "with <file>, the file is edited in-place. Otherwise, the result is\n"
- "written to the standard output.\n");
+ "If <file>s are given, it reformats the files. If -i is specified \n"
+ "together with <file>s, the files are edited in-place. Otherwise, the \n"
+ "result is written to the standard output.\n");
+
if (Help)
cl::PrintHelpMessage();
- clang::format::format();
- return 0;
+
+ bool Error = false;
+ switch (FileNames.size()) {
+ case 0:
+ Error = clang::format::format("-");
+ break;
+ case 1:
+ Error = clang::format::format(FileNames[0]);
+ break;
+ default:
+ if (!Offsets.empty() || !Lengths.empty()) {
+ llvm::errs() << "error: \"-offset\" and \"-length\" can only be used for "
+ "single file.\n";
+ return 1;
+ }
+ for (unsigned i = 0; i < FileNames.size(); ++i)
+ Error |= clang::format::format(FileNames[i]);
+ break;
+ }
+ return Error ? 1 : 0;
}
diff --git a/tools/clang-format/clang-format-bbedit.applescript b/tools/clang-format/clang-format-bbedit.applescript
new file mode 100644
index 0000000..fa88fe9
--- /dev/null
+++ b/tools/clang-format/clang-format-bbedit.applescript
@@ -0,0 +1,27 @@
+-- In this file, change "/path/to/" to the path where you installed clang-format
+-- and save it to ~/Library/Application Support/BBEdit/Scripts. You can then
+-- select the script from the Script menu and clang-format will format the
+-- selection. Note that you can rename the menu item by renaming the script, and
+-- can assign the menu item a keyboard shortcut in the BBEdit preferences, under
+-- Menus & Shortcuts.
+on urlToPOSIXPath(theURL)
+ return do shell script "python -c \"import urllib, urlparse, sys; print urllib.unquote(urlparse.urlparse(sys.argv[1])[2])\" " & quoted form of theURL
+end urlToPOSIXPath
+
+tell application "BBEdit"
+ set selectionOffset to characterOffset of selection
+ set selectionLength to length of selection
+ set fileURL to URL of text document 1
+end tell
+
+set filePath to urlToPOSIXPath(fileURL)
+set newContents to do shell script "/path/to/clang-format -offset=" & selectionOffset & " -length=" & selectionLength & " " & quoted form of filePath
+
+tell application "BBEdit"
+ -- "set contents of text document 1 to newContents" scrolls to the bottom while
+ -- replacing a selection flashes a bit but doesn't affect the scroll position.
+ set currentLength to length of contents of text document 1
+ select characters 1 thru currentLength of text document 1
+ set text of selection to newContents
+ select characters selectionOffset thru (selectionOffset + selectionLength - 1) of text document 1
+end tell
diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py
index ab5f1b1..68b5113 100755
--- a/tools/clang-format/clang-format-diff.py
+++ b/tools/clang-format/clang-format-diff.py
@@ -63,9 +63,10 @@ def formatRange(r, style):
offset, length = getOffsetLength(filename, line_number, line_count)
with open(filename, 'r') as f:
text = f.read()
- p = subprocess.Popen([binary, '-offset', str(offset), '-length', str(length),
- '-style', style],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ command = [binary, '-offset', str(offset), '-length', str(length)]
+ if style:
+ command.extend(['-style', style])
+ p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stdout, stderr = p.communicate(input=text)
if stderr:
@@ -84,8 +85,8 @@ def main():
'Reformat changed lines in diff')
parser.add_argument('-p', default=1,
help='strip the smallest prefix containing P slashes')
- parser.add_argument('-style', default='LLVM',
- help='formatting style to apply (LLVM, Google)')
+ parser.add_argument('-style',
+ help='formatting style to apply (LLVM, Google, Chromium)')
args = parser.parse_args()
filename = None
diff --git a/tools/clang-format/clang-format.el b/tools/clang-format/clang-format.el
new file mode 100644
index 0000000..2c5546b
--- /dev/null
+++ b/tools/clang-format/clang-format.el
@@ -0,0 +1,31 @@
+;;; Clang-format emacs integration for use with C/Objective-C/C++.
+
+;; This defines a function clang-format-region that you can bind to a key.
+;; A minimal .emacs would contain:
+;;
+;; (load "<path-to-clang>/tools/clang-format/clang-format.el")
+;; (global-set-key [C-M-tab] 'clang-format-region)
+;;
+;; Depending on your configuration and coding style, you might need to modify
+;; 'style' and 'binary' below.
+(defun clang-format-region ()
+ (interactive)
+
+ (let* ((orig-windows (get-buffer-window-list (current-buffer)))
+ (orig-window-starts (mapcar #'window-start orig-windows))
+ (orig-point (point))
+ (binary "clang-format")
+ (style "LLVM"))
+ (if mark-active
+ (setq beg (region-beginning)
+ end (region-end))
+ (setq beg (min (line-beginning-position) (1- (point-max)))
+ end (min (line-end-position) (1- (point-max)))))
+ (call-process-region (point-min) (point-max) binary t t nil
+ "-offset" (number-to-string (1- beg))
+ "-length" (number-to-string (- end beg))
+ "-style" style)
+ (goto-char orig-point)
+ (dotimes (index (length orig-windows))
+ (set-window-start (nth index orig-windows)
+ (nth index orig-window-starts)))))
diff --git a/tools/clang-format/clang-format.py b/tools/clang-format/clang-format.py
index de92257..d90c62a 100644
--- a/tools/clang-format/clang-format.py
+++ b/tools/clang-format/clang-format.py
@@ -23,6 +23,10 @@ import subprocess
# Change this to the full path if clang-format is not on the path.
binary = 'clang-format'
+# Change this to format according to other formatting styles (see
+# clang-format -help)
+style = 'LLVM'
+
# Get the current text.
buf = vim.current.buffer
text = "\n".join(buf)
@@ -34,7 +38,8 @@ length = int(vim.eval('line2byte(' +
str(vim.current.range.end + 2) + ')')) - offset - 2
# Call formatter.
-p = subprocess.Popen([binary, '-offset', str(offset), '-length', str(length)],
+p = subprocess.Popen([binary, '-offset', str(offset), '-length', str(length),
+ '-style', style],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stdout, stderr = p.communicate(input=text)
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index a81f1e4..a43c1ab 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -723,6 +723,13 @@ bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
}
bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+ unsigned NumParamList = DD->getNumTemplateParameterLists();
+ for (unsigned i = 0; i < NumParamList; i++) {
+ TemplateParameterList* Params = DD->getTemplateParameterList(i);
+ if (VisitTemplateParameters(Params))
+ return true;
+ }
+
if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
if (Visit(TSInfo->getTypeLoc()))
return true;
@@ -751,6 +758,13 @@ static int CompareCXXCtorInitializers(const void* Xp, const void *Yp) {
}
bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
+ unsigned NumParamList = ND->getNumTemplateParameterLists();
+ for (unsigned i = 0; i < NumParamList; i++) {
+ TemplateParameterList* Params = ND->getTemplateParameterList(i);
+ if (VisitTemplateParameters(Params))
+ return true;
+ }
+
if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
// Visit the function declaration's syntactic components in the order
// written. This requires a bit of work.
@@ -3574,6 +3588,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("ObjCStringLiteral");
case CXCursor_ObjCBoolLiteralExpr:
return cxstring::createRef("ObjCBoolLiteralExpr");
+ case CXCursor_ObjCSelfExpr:
+ return cxstring::createRef("ObjCSelfExpr");
case CXCursor_ObjCEncodeExpr:
return cxstring::createRef("ObjCEncodeExpr");
case CXCursor_ObjCSelectorExpr:
@@ -4444,6 +4460,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::TemplateTypeParm:
case Decl::EnumConstant:
case Decl::Field:
+ case Decl::MSProperty:
case Decl::IndirectField:
case Decl::ObjCIvar:
case Decl::ObjCAtDefsField:
@@ -4459,6 +4476,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::FileScopeAsm:
case Decl::StaticAssert:
case Decl::Block:
+ case Decl::Captured:
case Decl::Label: // FIXME: Is this right??
case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
@@ -5903,6 +5921,72 @@ CXFile clang_getIncludedFile(CXCursor cursor) {
return const_cast<FileEntry *>(ID->getFile());
}
+unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved) {
+ if (C.kind != CXCursor_ObjCPropertyDecl)
+ return CXObjCPropertyAttr_noattr;
+
+ unsigned Result = CXObjCPropertyAttr_noattr;
+ const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
+ ObjCPropertyDecl::PropertyAttributeKind Attr =
+ PD->getPropertyAttributesAsWritten();
+
+#define SET_CXOBJCPROP_ATTR(A) \
+ if (Attr & ObjCPropertyDecl::OBJC_PR_##A) \
+ Result |= CXObjCPropertyAttr_##A
+ SET_CXOBJCPROP_ATTR(readonly);
+ SET_CXOBJCPROP_ATTR(getter);
+ SET_CXOBJCPROP_ATTR(assign);
+ SET_CXOBJCPROP_ATTR(readwrite);
+ SET_CXOBJCPROP_ATTR(retain);
+ SET_CXOBJCPROP_ATTR(copy);
+ SET_CXOBJCPROP_ATTR(nonatomic);
+ SET_CXOBJCPROP_ATTR(setter);
+ SET_CXOBJCPROP_ATTR(atomic);
+ SET_CXOBJCPROP_ATTR(weak);
+ SET_CXOBJCPROP_ATTR(strong);
+ SET_CXOBJCPROP_ATTR(unsafe_unretained);
+#undef SET_CXOBJCPROP_ATTR
+
+ return Result;
+}
+
+unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return CXObjCDeclQualifier_None;
+
+ Decl::ObjCDeclQualifier QT = Decl::OBJC_TQ_None;
+ const Decl *D = getCursorDecl(C);
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ QT = MD->getObjCDeclQualifier();
+ else if (const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
+ QT = PD->getObjCDeclQualifier();
+ if (QT == Decl::OBJC_TQ_None)
+ return CXObjCDeclQualifier_None;
+
+ unsigned Result = CXObjCDeclQualifier_None;
+ if (QT & Decl::OBJC_TQ_In) Result |= CXObjCDeclQualifier_In;
+ if (QT & Decl::OBJC_TQ_Inout) Result |= CXObjCDeclQualifier_Inout;
+ if (QT & Decl::OBJC_TQ_Out) Result |= CXObjCDeclQualifier_Out;
+ if (QT & Decl::OBJC_TQ_Bycopy) Result |= CXObjCDeclQualifier_Bycopy;
+ if (QT & Decl::OBJC_TQ_Byref) Result |= CXObjCDeclQualifier_Byref;
+ if (QT & Decl::OBJC_TQ_Oneway) Result |= CXObjCDeclQualifier_Oneway;
+
+ return Result;
+}
+
+unsigned clang_Cursor_isVariadic(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = getCursorDecl(C);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isVariadic();
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->isVariadic();
+
+ return 0;
+}
+
CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return clang_getNullRange();
@@ -5971,6 +6055,13 @@ CXModule clang_Cursor_getModule(CXCursor C) {
return 0;
}
+CXFile clang_Module_getASTFile(CXModule CXMod) {
+ if (!CXMod)
+ return 0;
+ Module *Mod = static_cast<Module*>(CXMod);
+ return const_cast<FileEntry *>(Mod->getASTFile());
+}
+
CXModule clang_Module_getParent(CXModule CXMod) {
if (!CXMod)
return 0;
diff --git a/tools/libclang/CIndexCXX.cpp b/tools/libclang/CIndexCXX.cpp
index c68dde7..a3d2364 100644
--- a/tools/libclang/CIndexCXX.cpp
+++ b/tools/libclang/CIndexCXX.cpp
@@ -33,7 +33,7 @@ unsigned clang_isVirtualBase(CXCursor C) {
enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
AccessSpecifier spec = AS_none;
- if (C.kind == CXCursor_CXXAccessSpecifier)
+ if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
spec = getCursorDecl(C)->getAccess();
else if (C.kind == CXCursor_CXXBaseSpecifier)
spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 7b01ec2..2cdb71b 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -215,6 +215,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::TypeTraitExprClass:
case Stmt::CXXBindTemporaryExprClass:
case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDefaultInitExprClass:
case Stmt::CXXScalarValueInitExprClass:
case Stmt::CXXUuidofExprClass:
case Stmt::ChooseExprClass:
@@ -270,6 +271,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_DeclStmt;
break;
+ case Stmt::CapturedStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
case Stmt::IntegerLiteralClass:
K = CXCursor_IntegerLiteral;
break;
@@ -430,7 +435,21 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_SizeOfPackExpr;
break;
- case Stmt::DeclRefExprClass:
+ case Stmt::DeclRefExprClass:
+ if (const ImplicitParamDecl *IPD =
+ dyn_cast_or_null<ImplicitParamDecl>(cast<DeclRefExpr>(S)->getDecl())) {
+ if (const ObjCMethodDecl *MD =
+ dyn_cast<ObjCMethodDecl>(IPD->getDeclContext())) {
+ if (MD->getSelfDecl() == IPD) {
+ K = CXCursor_ObjCSelfExpr;
+ break;
+ }
+ }
+ }
+
+ K = CXCursor_DeclRefExpr;
+ break;
+
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::SubstNonTypeTemplateParmExprClass:
case Stmt::SubstNonTypeTemplateParmPackExprClass:
@@ -442,6 +461,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::CXXDependentScopeMemberExprClass:
case Stmt::CXXPseudoDestructorExprClass:
case Stmt::MemberExprClass:
+ case Stmt::MSPropertyRefExprClass:
case Stmt::ObjCIsaExprClass:
case Stmt::ObjCIvarRefExprClass:
case Stmt::ObjCPropertyRefExprClass:
@@ -1025,7 +1045,7 @@ unsigned clang_CXCursorSet_contains(CXCursorSet set, CXCursor cursor) {
CXCursorSet_Impl *setImpl = unpackCXCursorSet(set);
if (!setImpl)
return 0;
- return setImpl->find(cursor) == setImpl->end();
+ return setImpl->find(cursor) != setImpl->end();
}
unsigned clang_CXCursorSet_insert(CXCursorSet set, CXCursor cursor) {
diff --git a/tools/libclang/CXSourceLocation.cpp b/tools/libclang/CXSourceLocation.cpp
index bc8d575..b7c7622 100644
--- a/tools/libclang/CXSourceLocation.cpp
+++ b/tools/libclang/CXSourceLocation.cpp
@@ -198,6 +198,17 @@ static void createNullLocation(CXString *filename, unsigned *line,
extern "C" {
+int clang_Location_isInSystemHeader(CXSourceLocation location) {
+ const SourceLocation Loc =
+ SourceLocation::getFromRawEncoding(location.int_data);
+ if (Loc.isInvalid())
+ return 0;
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ return SM.isInSystemHeader(Loc);
+}
+
void clang_getExpansionLocation(CXSourceLocation location,
CXFile *file,
unsigned *line,
diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h
index 699b74a..bdc171c 100644
--- a/tools/libclang/CXTranslationUnit.h
+++ b/tools/libclang/CXTranslationUnit.h
@@ -39,6 +39,8 @@ namespace cxtu {
CXTranslationUnitImpl *MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *AU);
static inline ASTUnit *getASTUnit(CXTranslationUnit TU) {
+ if (!TU)
+ return 0;
return TU->TheASTUnit;
}
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index 6f87fc5..1482415 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -149,14 +149,20 @@ 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 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 FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return MakeCXType(FD->getType(), TU);
- if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
+ if (TypeSourceInfo *TSInfo = FTD->getTemplatedDecl()->getTypeSourceInfo())
+ return MakeCXType(TSInfo->getType(), TU);
return MakeCXType(FTD->getTemplatedDecl()->getType(), TU);
+ }
return MakeCXType(QualType(), TU);
}
@@ -651,6 +657,126 @@ long long clang_getArraySize(CXType CT) {
return result;
}
+long long clang_Type_getAlignOf(CXType T) {
+ if (T.kind == CXType_Invalid)
+ return CXTypeLayoutError_Invalid;
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
+ QualType QT = GetQualType(T);
+ // [expr.alignof] p1: return size_t value for complete object type, reference
+ // or array.
+ // [expr.alignof] p3: if reference type, return size of referenced type
+ if (QT->isReferenceType())
+ QT = QT.getNonReferenceType();
+ if (QT->isIncompleteType())
+ return CXTypeLayoutError_Incomplete;
+ if (QT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
+ // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
+ // if (QT->isVoidType()) return 1;
+ return Ctx.getTypeAlignInChars(QT).getQuantity();
+}
+
+long long clang_Type_getSizeOf(CXType T) {
+ if (T.kind == CXType_Invalid)
+ return CXTypeLayoutError_Invalid;
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
+ QualType QT = GetQualType(T);
+ // [expr.sizeof] p2: if reference type, return size of referenced type
+ if (QT->isReferenceType())
+ QT = QT.getNonReferenceType();
+ // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
+ // enumeration
+ // Note: We get the cxtype, not the cxcursor, so we can't call
+ // FieldDecl->isBitField()
+ // [expr.sizeof] p3: pointer ok, function not ok.
+ // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
+ if (QT->isIncompleteType())
+ return CXTypeLayoutError_Incomplete;
+ if (QT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ if (!QT->isConstantSizeType())
+ return CXTypeLayoutError_NotConstantSize;
+ // [gcc extension] lib/AST/ExprConstant.cpp:1372
+ // HandleSizeof : {voidtype,functype} == 1
+ // not handled by ASTContext.cpp:1313 getTypeInfoImpl
+ if (QT->isVoidType() || QT->isFunctionType())
+ return 1;
+ return Ctx.getTypeSizeInChars(QT).getQuantity();
+}
+
+static long long visitRecordForValidation(const RecordDecl *RD) {
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I){
+ QualType FQT = (*I)->getType();
+ if (FQT->isIncompleteType())
+ return CXTypeLayoutError_Incomplete;
+ if (FQT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ // recurse
+ if (const RecordType *ChildType = (*I)->getType()->getAs<RecordType>()) {
+ if (const RecordDecl *Child = ChildType->getDecl()) {
+ long long ret = visitRecordForValidation(Child);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ // else try next field
+ }
+ return 0;
+}
+
+long long clang_Type_getOffsetOf(CXType PT, const char *S) {
+ // check that PT is not incomplete/dependent
+ CXCursor PC = clang_getTypeDeclaration(PT);
+ if (clang_isInvalid(PC.kind))
+ return CXTypeLayoutError_Invalid;
+ const RecordDecl *RD =
+ dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ if (!RD)
+ return CXTypeLayoutError_Invalid;
+ RD = RD->getDefinition();
+ if (!RD)
+ return CXTypeLayoutError_Incomplete;
+ QualType RT = GetQualType(PT);
+ if (RT->isIncompleteType())
+ return CXTypeLayoutError_Incomplete;
+ if (RT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ // We recurse into all record fields to detect incomplete and dependent types.
+ long long Error = visitRecordForValidation(RD);
+ if (Error < 0)
+ return Error;
+ if (!S)
+ return CXTypeLayoutError_InvalidFieldName;
+ // lookup field
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext();
+ IdentifierInfo *II = &Ctx.Idents.get(S);
+ DeclarationName FieldName(II);
+ RecordDecl::lookup_const_result Res = RD->lookup(FieldName);
+ // If a field of the parent record is incomplete, lookup will fail.
+ // and we would return InvalidFieldName instead of Incomplete.
+ // But this erroneous results does protects again a hidden assertion failure
+ // in the RecordLayoutBuilder
+ if (Res.size() != 1)
+ return CXTypeLayoutError_InvalidFieldName;
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(Res.front()))
+ return Ctx.getFieldOffset(FD);
+ if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Res.front()))
+ return Ctx.getFieldOffset(IFD);
+ // we don't want any other Decl Type.
+ return CXTypeLayoutError_InvalidFieldName;
+}
+
+unsigned clang_Cursor_isBitField(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+ const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(cxcursor::getCursorDecl(C));
+ if (!FD)
+ return 0;
+ return FD->isBitField();
+}
+
CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return cxstring::createEmpty();
diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp
index 95d74ef..02ab885 100644
--- a/tools/libclang/IndexBody.cpp
+++ b/tools/libclang/IndexBody.cpp
@@ -68,9 +68,6 @@ public:
}
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo())
- IndexCtx.indexTypeSourceInfo(Cls, Parent, ParentDC);
-
if (ObjCMethodDecl *MD = E->getMethodDecl())
IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
Parent, ParentDC, E,
@@ -89,6 +86,12 @@ public:
return true;
}
+ bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+ IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
+ ParentDC, E, CXIdxEntityRef_Direct);
+ return true;
+ }
+
bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
Parent, ParentDC, E, CXIdxEntityRef_Direct);
diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp
index d7fb959..756001c 100644
--- a/tools/libclang/IndexDecl.cpp
+++ b/tools/libclang/IndexDecl.cpp
@@ -105,6 +105,11 @@ public:
return true;
}
+ bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
+ handleDeclarator(D);
+ return true;
+ }
+
bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
IndexCtx.handleEnumerator(D);
IndexCtx.indexBody(D->getInitExpr(), D);
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index 2a504db..15786ac 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -292,7 +292,7 @@ public:
/// MacroExpands - This is called by when a macro invocation is found.
virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
- SourceRange Range) {
+ SourceRange Range, const MacroArgs *Args) {
}
/// SourceRangeSkipped - This hook is called when a source range is skipped.
@@ -398,10 +398,6 @@ public:
if (level >= DiagnosticsEngine::Error)
Errors.push_back(StoredDiagnostic(level, Info));
}
-
- DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
- return new IgnoringDiagConsumer();
- }
};
//===----------------------------------------------------------------------===//
@@ -549,8 +545,7 @@ static void clang_indexSourceFile_Impl(void *UserData) {
IntrusiveRefCntPtr<DiagnosticsEngine>
Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
CaptureDiag,
- /*ShouldOwnClient=*/true,
- /*ShouldCloneClient=*/false));
+ /*ShouldOwnClient=*/true));
// Recover resources if we crash before exiting this function.
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index 3368922..14b430c 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -396,6 +396,12 @@ bool IndexingContext::handleField(const FieldDecl *D) {
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
}
+bool IndexingContext::handleMSProperty(const MSPropertyDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
/*isContainer=*/false);
diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h
index c9097c5..62873be 100644
--- a/tools/libclang/IndexingContext.h
+++ b/tools/libclang/IndexingContext.h
@@ -16,6 +16,7 @@
namespace clang {
class FileEntry;
+ class MSPropertyDecl;
class ObjCPropertyDecl;
class ClassTemplateDecl;
class FunctionTemplateDecl;
@@ -404,6 +405,8 @@ public:
bool handleField(const FieldDecl *D);
+ bool handleMSProperty(const MSPropertyDecl *D);
+
bool handleEnumerator(const EnumConstantDecl *D);
bool handleTagDecl(const TagDecl *D);
diff --git a/tools/libclang/RecursiveASTVisitor.h b/tools/libclang/RecursiveASTVisitor.h
index 5862e12..e45545e 100644
--- a/tools/libclang/RecursiveASTVisitor.h
+++ b/tools/libclang/RecursiveASTVisitor.h
@@ -1170,8 +1170,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
for (DeclContext::decl_iterator Child = DC->decls_begin(),
ChildEnd = DC->decls_end();
Child != ChildEnd; ++Child) {
- // BlockDecls are traversed through BlockExprs.
- if (!isa<BlockDecl>(*Child))
+ // BlockDecls and CapturedDecls are traversed through BlockExprs and
+ // CapturedStmts respectively.
+ if (!isa<BlockDecl>(*Child) && !isa<CapturedDecl>(*Child))
TRY_TO(TraverseDecl(*Child));
}
@@ -1200,6 +1201,14 @@ DEF_TRAVERSE_DECL(BlockDecl, {
return true;
})
+DEF_TRAVERSE_DECL(CapturedDecl, {
+ TRY_TO(TraverseStmt(D->getBody()));
+ // This return statement makes sure the traversal of nodes in
+ // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
+ // is skipped - don't remove it.
+ return true;
+ })
+
DEF_TRAVERSE_DECL(EmptyDecl, { })
DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
@@ -1614,6 +1623,10 @@ DEF_TRAVERSE_DECL(FieldDecl, {
TRY_TO(TraverseStmt(D->getInClassInitializer()));
})
+DEF_TRAVERSE_DECL(MSPropertyDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ })
+
DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
TRY_TO(TraverseDeclaratorHelper(D));
if (D->isBitField())
@@ -1836,7 +1849,6 @@ DEF_TRAVERSE_STMT(ReturnStmt, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(WhileStmt, { })
-
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
@@ -2079,6 +2091,7 @@ DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
+DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { })
DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
@@ -2103,7 +2116,10 @@ DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
})
DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
-DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
+DEF_TRAVERSE_STMT(ObjCMessageExpr, {
+ if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
@@ -2133,9 +2149,13 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
}
})
+DEF_TRAVERSE_STMT(MSPropertyRefExpr, {})
DEF_TRAVERSE_STMT(SEHTryStmt, {})
DEF_TRAVERSE_STMT(SEHExceptStmt, {})
DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
+DEF_TRAVERSE_STMT(CapturedStmt, {
+ TRY_TO(TraverseDecl(S->getCapturedDecl()));
+})
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index d99f24e..0c9912e 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -10,13 +10,18 @@ clang_Cursor_getCommentRange
clang_Cursor_getParsedComment
clang_Cursor_getRawCommentText
clang_Cursor_getNumArguments
+clang_Cursor_getObjCDeclQualifiers
+clang_Cursor_getObjCPropertyAttributes
clang_Cursor_getObjCSelectorIndex
clang_Cursor_getSpellingNameRange
clang_Cursor_getTranslationUnit
clang_Cursor_getReceiverType
+clang_Cursor_isBitField
clang_Cursor_isDynamicCall
clang_Cursor_isNull
+clang_Cursor_isVariadic
clang_Cursor_getModule
+clang_Module_getASTFile
clang_Module_getParent
clang_Module_getName
clang_Module_getFullName
@@ -53,6 +58,9 @@ clang_TParamCommandComment_getParamName
clang_TParamCommandComment_isParamPositionValid
clang_TParamCommandComment_getDepth
clang_TParamCommandComment_getIndex
+clang_Type_getAlignOf
+clang_Type_getSizeOf
+clang_Type_getOffsetOf
clang_VerbatimBlockLineComment_getText
clang_VerbatimLineComment_getText
clang_HTMLTagComment_getAsString
@@ -244,6 +252,7 @@ clang_isUnexposed
clang_isVirtualBase
clang_isVolatileQualifiedType
clang_loadDiagnostics
+clang_Location_isInSystemHeader
clang_parseTranslationUnit
clang_remap_dispose
clang_remap_getFilenames
diff --git a/tools/scan-build/c++-analyzer b/tools/scan-build/c++-analyzer
index ca10bf5..dda5db9 120000..100755
--- a/tools/scan-build/c++-analyzer
+++ b/tools/scan-build/c++-analyzer
@@ -1 +1,8 @@
-ccc-analyzer \ No newline at end of file
+#!/usr/bin/env perl
+
+use Cwd qw/ abs_path /;
+use File::Basename qw/ dirname /;
+# Add scan-build dir to the list of places where perl looks for modules.
+use lib dirname(abs_path($0));
+
+do 'ccc-analyzer';
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer
index bb6dd95..60b0185 100755
--- a/tools/scan-build/ccc-analyzer
+++ b/tools/scan-build/ccc-analyzer
@@ -491,7 +491,7 @@ foreach (my $i = 0; $i < scalar(@ARGV); ++$i) {
while ($Cnt > 0) { ++$i; --$Cnt; push @CompileOpts, $ARGV[$i]; }
next;
}
- if ($Arg =~ /-msse.*/) {
+ if ($Arg =~ /-m.*/) {
push @CompileOpts,$Arg;
next;
}
diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build
index 32eecc0..35f852e 100755
--- a/tools/scan-build/scan-build
+++ b/tools/scan-build/scan-build
@@ -931,11 +931,13 @@ sub RunXcodebuild {
if ($oldBehavior == 0) {
my $OutputDir = $Options->{"OUTPUT_DIR"};
my $CLANG = $Options->{"CLANG"};
+ my $OtherFlags = $Options->{"CCC_ANALYZER_ANALYSIS"};
push @$Args,
"RUN_CLANG_STATIC_ANALYZER=YES",
"CLANG_ANALYZER_OUTPUT=plist-html",
"CLANG_ANALYZER_EXEC=$CLANG",
- "CLANG_ANALYZER_OUTPUT_DIR=$OutputDir";
+ "CLANG_ANALYZER_OUTPUT_DIR=$OutputDir",
+ "CLANG_ANALYZER_OTHER_FLAGS=$OtherFlags";
return (system(@$Args) >> 8);
}
@@ -1560,8 +1562,16 @@ if ($ForceDisplayHelp || $RequestDisplayHelp) {
}
$ClangCXX = $Clang;
-$ClangCXX =~ s/\-\d+\.\d+$//;
-$ClangCXX .= "++";
+# 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.
$ClangVersion = HtmlEscape(`"$Clang" --version`);
diff --git a/tools/scan-build/scan-build.bat b/tools/scan-build/scan-build.bat
new file mode 100644
index 0000000..77be674
--- /dev/null
+++ b/tools/scan-build/scan-build.bat
@@ -0,0 +1 @@
+perl -S scan-build %*
diff --git a/tools/scan-view/ScanView.py b/tools/scan-view/ScanView.py
index 32570b9..ee08baa 100644
--- a/tools/scan-view/ScanView.py
+++ b/tools/scan-view/ScanView.py
@@ -686,16 +686,8 @@ File Bug</h3>
if components[-1] == '':
components[-1] = 'index.html'
- suffix = '/'.join(components)
-
- # The summary may reference source files on disk using rooted
- # paths. Make sure these resolve correctly for now.
- # FIXME: This isn't a very good idea... we should probably
- # mark rooted paths somehow.
- if os.path.exists(posixpath.join('/', suffix)):
- path = posixpath.join('/', suffix)
- else:
- path = posixpath.join(self.server.root, suffix)
+ relpath = '/'.join(components)
+ path = posixpath.join(self.server.root, relpath)
if self.server.options.debug > 1:
print >>sys.stderr, '%s: SERVER: sending path "%s"'%(sys.argv[0],
@@ -708,8 +700,8 @@ File Bug</h3>
def send_path(self, path):
# If the requested path is outside the root directory, do not open it
- rel = os.path.abspath(os.path.join(self.server.root, path))
- if not rel.startswith(os.path.abspath(self.server.root) ):
+ rel = os.path.abspath(path)
+ if not rel.startswith(os.path.abspath(self.server.root)):
return self.send_404()
ctype = self.guess_type(path)
OpenPOWER on IntegriCloud