summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-05-02 19:39:53 +0000
committerdim <dim@FreeBSD.org>2011-05-02 19:39:53 +0000
commit110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab (patch)
tree64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /tools
parenta0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff)
downloadFreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.zip
FreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.tar.gz
Vendor import of clang trunk r130700:
http://llvm.org/svn/llvm-project/cfe/trunk@130700
Diffstat (limited to 'tools')
-rw-r--r--tools/c-index-test/Makefile3
-rw-r--r--tools/c-index-test/c-index-test.c39
-rw-r--r--tools/driver/CMakeLists.txt1
-rw-r--r--tools/driver/Makefile2
-rw-r--r--tools/driver/cc1_main.cpp2
-rw-r--r--tools/driver/cc1as_main.cpp9
-rw-r--r--tools/driver/driver.cpp105
-rw-r--r--tools/libclang/CIndex.cpp807
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp21
-rw-r--r--tools/libclang/CIndexInclusionStack.cpp10
-rw-r--r--tools/libclang/CIndexUSRs.cpp10
-rw-r--r--tools/libclang/CIndexer.cpp5
-rw-r--r--tools/libclang/CMakeLists.txt64
-rw-r--r--tools/libclang/CXCursor.cpp9
-rw-r--r--tools/libclang/libclang.darwin.exports6
-rw-r--r--tools/libclang/libclang.exports4
-rwxr-xr-xtools/scan-build/ccc-analyzer66
-rwxr-xr-xtools/scan-build/scan-build30
18 files changed, 903 insertions, 290 deletions
diff --git a/tools/c-index-test/Makefile b/tools/c-index-test/Makefile
index 3d9849a..6806404 100644
--- a/tools/c-index-test/Makefile
+++ b/tools/c-index-test/Makefile
@@ -13,6 +13,9 @@ TOOLNAME = c-index-test
# No plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
+# Don't install this. It is used for tests.
+NO_INSTALL = 1
+
LINK_COMPONENTS := support mc
USEDLIBS = clang.a clangIndex.a clangFrontend.a clangDriver.a \
clangSerialization.a clangParse.a clangSema.a clangAnalysis.a \
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index d4e567d..f7b7a36 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -370,6 +370,23 @@ void PrintDiagnostics(CXTranslationUnit TU) {
}
}
+void PrintMemoryUsage(CXTranslationUnit TU) {
+ unsigned long total = 0.0;
+ unsigned i = 0;
+ CXTUResourceUsage usage = clang_getCXTUResourceUsage(TU);
+ fprintf(stderr, "Memory usage:\n");
+ for (i = 0 ; i != usage.numEntries; ++i) {
+ const char *name = clang_getTUResourceUsageName(usage.entries[i].kind);
+ unsigned long amount = usage.entries[i].amount;
+ total += amount;
+ fprintf(stderr, " %s : %ld bytes (%f MBytes)\n", name, amount,
+ ((double) amount)/(1024*1024));
+ }
+ fprintf(stderr, " TOTAL = %ld bytes (%f MBytes)\n", total,
+ ((double) total)/(1024*1024));
+ clang_disposeCXTUResourceUsage(usage);
+}
+
/******************************************************************************/
/* Logic for testing traversal. */
/******************************************************************************/
@@ -990,7 +1007,7 @@ void print_completion_result(CXCompletionResult *completion_result,
int my_stricmp(const char *s1, const char *s2) {
while (*s1 && *s2) {
- int c1 = tolower(*s1), c2 = tolower(*s2);
+ int c1 = tolower((unsigned char)*s1), c2 = tolower((unsigned char)*s2);
if (c1 < c2)
return -1;
else if (c1 > c2)
@@ -1503,6 +1520,8 @@ static CXCursorVisitor GetVisitor(const char *s) {
return FilteredPrintingVisitor;
if (strcmp(s, "-usrs") == 0)
return USRVisitor;
+ if (strncmp(s, "-memory-usage", 13) == 0)
+ return GetVisitor(s + 13);
return NULL;
}
@@ -1519,16 +1538,20 @@ static void print_usage(void) {
"[FileCheck prefix]\n"
" c-index-test -test-load-source <symbol filter> {<args>}*\n");
fprintf(stderr,
+ " c-index-test -test-load-source-memory-usage "
+ "<symbol filter> {<args>}*\n"
" c-index-test -test-load-source-reparse <trials> <symbol filter> "
" {<args>}*\n"
" c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
+ " c-index-test -test-load-source-usrs-memory-usage "
+ "<symbol filter> {<args>}*\n"
" c-index-test -test-annotate-tokens=<range> {<args>}*\n"
" c-index-test -test-inclusion-stack-source {<args>}*\n"
- " c-index-test -test-inclusion-stack-tu <AST file>\n"
+ " 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-typekind {<args>}*\n"
- " c-index-test -print-usr [<CursorKind> {<args>}]*\n");
- fprintf(stderr,
+ " c-index-test -print-usr [<CursorKind> {<args>}]*\n"
" c-index-test -print-usr-file <file>\n"
" c-index-test -write-pch <file> <compiler arguments>\n\n");
fprintf(stderr,
@@ -1569,8 +1592,14 @@ int cindextest_main(int argc, const char **argv) {
}
else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
CXCursorVisitor I = GetVisitor(argv[1] + 17);
+
+ PostVisitTU postVisit = 0;
+ if (strstr(argv[1], "-memory-usage"))
+ postVisit = PrintMemoryUsage;
+
if (I)
- return perform_test_load_source(argc - 3, argv + 3, argv[2], I, NULL);
+ return perform_test_load_source(argc - 3, argv + 3, argv[2], I,
+ postVisit);
}
else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
return perform_file_scan(argv[2], argv[3],
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 552e7a5..0c41490 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -23,6 +23,7 @@ set( LLVM_LINK_COMPONENTS
bitreader
bitwriter
codegen
+ instrumentation
ipo
selectiondag
)
diff --git a/tools/driver/Makefile b/tools/driver/Makefile
index d96f950..abe7098 100644
--- a/tools/driver/Makefile
+++ b/tools/driver/Makefile
@@ -36,7 +36,7 @@ TOOL_INFO_PLIST := Info.plist
include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
- ipo selectiondag
+ instrumentation ipo selectiondag
USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \
clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \
clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index 7fb394f..535eaa9 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -168,7 +168,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// When running with -disable-free, don't do any destruction or shutdown.
if (Clang->getFrontendOpts().DisableFree) {
- if (Clang->getFrontendOpts().ShowStats)
+ if (llvm::AreStatisticsEnabled() || Clang->getFrontendOpts().ShowStats)
llvm::PrintStatistics();
Clang.take();
return !Success;
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 1d544f3..ec6ce65 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -71,6 +71,7 @@ struct AssemblerInvocation {
std::vector<std::string> IncludePaths;
unsigned NoInitialTextSection : 1;
+ unsigned SaveTemporaryLabels : 1;
/// @}
/// @name Frontend Options
@@ -156,6 +157,7 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Language Options
Opts.IncludePaths = Args->getAllArgValues(OPT_I);
Opts.NoInitialTextSection = Args->hasArg(OPT_n);
+ Opts.SaveTemporaryLabels = Args->hasArg(OPT_L);
// Frontend Options
if (Args->hasArg(OPT_INPUT)) {
@@ -265,6 +267,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
const TargetAsmInfo *tai = new TargetAsmInfo(*TM);
MCContext Ctx(*MAI, tai);
+ if (Opts.SaveTemporaryLabels)
+ Ctx.setAllowTemporaryLabels(false);
OwningPtr<MCStreamer> Str;
@@ -275,7 +279,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
MCInstPrinter *IP =
- TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI);
+ TheTarget->createMCInstPrinter(*TM, Opts.OutputAsmVariant, *MAI);
MCCodeEmitter *CE = 0;
TargetAsmBackend *TAB = 0;
if (Opts.ShowEncoding) {
@@ -283,7 +287,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
TAB = TheTarget->createAsmBackend(Opts.Triple);
}
Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true,
- /*useLoc*/ true, IP, CE, TAB,
+ /*useLoc*/ true,
+ /*useCFI*/ true, IP, CE, TAB,
Opts.ShowInst));
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
Str.reset(createNullStreamer(Ctx));
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 0b5d2c9..db72da4 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -18,6 +18,7 @@
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/OwningPtr.h"
@@ -35,6 +36,8 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/system_error.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
#include <cctype>
using namespace clang;
using namespace clang::driver;
@@ -252,6 +255,85 @@ static void ExpandArgv(int argc, const char **argv,
}
}
+static void ParseProgName(llvm::SmallVectorImpl<const char *> &ArgVector,
+ std::set<std::string> &SavedStrings,
+ Driver &TheDriver)
+{
+ // Try to infer frontend type and default target from the program name.
+
+ // suffixes[] contains the list of known driver suffixes.
+ // Suffixes are compared against the program name in order.
+ // If there is a match, the frontend type is updated as necessary (CPP/C++).
+ // If there is no match, a second round is done after stripping the last
+ // hyphen and everything following it. This allows using something like
+ // "clang++-2.9".
+
+ // If there is a match in either the first or second round,
+ // the function tries to identify a target as prefix. E.g.
+ // "x86_64-linux-clang" as interpreted as suffix "clang" with
+ // target prefix "x86_64-linux". If such a target prefix is found,
+ // is gets added via -ccc-host-triple as implicit first argument.
+ static const struct {
+ const char *Suffix;
+ bool IsCXX;
+ bool IsCPP;
+ } suffixes [] = {
+ { "clang", false, false },
+ { "clang++", true, false },
+ { "clang-c++", true, false },
+ { "clang-cc", false, false },
+ { "clang-cpp", false, true },
+ { "clang-g++", true, false },
+ { "clang-gcc", false, false },
+ { "cc", false, false },
+ { "cpp", false, true },
+ { "++", true, false },
+ };
+ std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
+ llvm::StringRef ProgNameRef(ProgName);
+ llvm::StringRef Prefix;
+
+ for (int Components = 2; Components; --Components) {
+ bool FoundMatch = false;
+ size_t i;
+
+ for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+ if (ProgNameRef.endswith(suffixes[i].Suffix)) {
+ FoundMatch = true;
+ if (suffixes[i].IsCXX)
+ TheDriver.CCCIsCXX = true;
+ if (suffixes[i].IsCPP)
+ TheDriver.CCCIsCPP = true;
+ break;
+ }
+ }
+
+ if (FoundMatch) {
+ llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-',
+ ProgNameRef.size() - strlen(suffixes[i].Suffix));
+ if (LastComponent != llvm::StringRef::npos)
+ Prefix = ProgNameRef.slice(0, LastComponent);
+ break;
+ }
+
+ llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-');
+ if (LastComponent == llvm::StringRef::npos)
+ break;
+ ProgNameRef = ProgNameRef.slice(0, LastComponent);
+ }
+
+ if (Prefix.empty())
+ return;
+
+ std::string IgnoredError;
+ if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
+ ArgVector.insert(&ArgVector[1],
+ SaveStringInSet(SavedStrings, Prefix));
+ ArgVector.insert(&ArgVector[1],
+ SaveStringInSet(SavedStrings, std::string("-ccc-host-triple")));
+ }
+}
+
int main(int argc_, const char **argv_) {
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc_, argv_);
@@ -328,19 +410,8 @@ int main(int argc_, const char **argv_) {
TheDriver.setInstalledDir(InstalledPath);
}
- // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
- // compiler. This matches things like "c++", "clang++", and "clang++-1.1".
- //
- // Note that we intentionally want to use argv[0] here, to support "clang++"
- // being a symlink.
- //
- // We use *argv instead of argv[0] to work around a bogus g++ warning.
- const char *progname = argv_[0];
- std::string ProgName(llvm::sys::path::stem(progname));
- if (llvm::StringRef(ProgName).endswith("++") ||
- llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
- TheDriver.CCCIsCXX = true;
- }
+ llvm::InitializeAllTargets();
+ ParseProgName(argv, SavedStrings, TheDriver);
// Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
@@ -352,6 +423,11 @@ int main(int argc_, const char **argv_) {
if (TheDriver.CCPrintHeaders)
TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
+ // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE.
+ TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
+ if (TheDriver.CCLogDiagnostics)
+ TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
+
// Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
// command line behind the scenes.
if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
@@ -378,8 +454,7 @@ int main(int argc_, const char **argv_) {
argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end());
}
- llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(),
- &argv[0]));
+ llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv));
int Res = 0;
if (C.get())
Res = TheDriver.ExecuteCompilation(*C);
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index cd1b8d6..28f1506 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -34,6 +34,7 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
#include "clang/Analysis/Support/SaveAndRestore.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -115,7 +116,7 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
// location accordingly.
SourceLocation EndLoc = R.getEnd();
if (EndLoc.isValid() && EndLoc.isMacroID())
- EndLoc = SM.getSpellingLoc(EndLoc);
+ EndLoc = SM.getInstantiationRange(EndLoc).second;
if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) {
unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
EndLoc = EndLoc.getFileLocWithOffset(Length);
@@ -187,6 +188,10 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
// be suppressed.
unsigned MaxPCHLevel;
+ /// \brief Whether we should visit the preprocessing record entries last,
+ /// after visiting other declarations.
+ bool VisitPreprocessorLast;
+
/// \brief When valid, a source range to which the cursor should restrict
/// its search.
SourceRange RegionOfInterest;
@@ -234,11 +239,12 @@ public:
CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
CXClientData ClientData,
unsigned MaxPCHLevel,
+ bool VisitPreprocessorLast,
SourceRange RegionOfInterest = SourceRange())
: TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
Visitor(Visitor), ClientData(ClientData),
- MaxPCHLevel(MaxPCHLevel), RegionOfInterest(RegionOfInterest),
- DI_current(0)
+ MaxPCHLevel(MaxPCHLevel), VisitPreprocessorLast(VisitPreprocessorLast),
+ RegionOfInterest(RegionOfInterest), DI_current(0)
{
Parent.kind = CXCursor_NoDeclFound;
Parent.data[0] = 0;
@@ -266,6 +272,7 @@ public:
bool VisitChildren(CXCursor Parent);
// Declaration visitors
+ bool VisitTypeAliasDecl(TypeAliasDecl *D);
bool VisitAttributes(Decl *D);
bool VisitBlockDecl(BlockDecl *B);
bool VisitCXXRecordDecl(CXXRecordDecl *D);
@@ -342,7 +349,11 @@ public:
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL);
bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
-
+ bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL);
+ bool VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL);
+ bool VisitElaboratedTypeLoc(ElaboratedTypeLoc TL);
+
// Data-recursive visitor functions.
bool IsInRegionOfInterest(CXCursor C);
bool RunVisitorWorkList(VisitorWorkList &WL);
@@ -472,7 +483,8 @@ CursorVisitor::getPreprocessedEntities() {
/// \returns true if the visitation should be aborted, false if it
/// should continue.
bool CursorVisitor::VisitChildren(CXCursor Cursor) {
- if (clang_isReference(Cursor.kind)) {
+ if (clang_isReference(Cursor.kind) &&
+ Cursor.kind != CXCursor_CXXBaseSpecifier) {
// By definition, references have no children.
return false;
}
@@ -483,68 +495,96 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
if (clang_isDeclaration(Cursor.kind)) {
Decl *D = getCursorDecl(Cursor);
- assert(D && "Invalid declaration cursor");
+ if (!D)
+ return false;
+
return VisitAttributes(D) || Visit(D);
}
- if (clang_isStatement(Cursor.kind))
- return Visit(getCursorStmt(Cursor));
- if (clang_isExpression(Cursor.kind))
- return Visit(getCursorExpr(Cursor));
+ if (clang_isStatement(Cursor.kind)) {
+ if (Stmt *S = getCursorStmt(Cursor))
+ return Visit(S);
+
+ return false;
+ }
+
+ if (clang_isExpression(Cursor.kind)) {
+ if (Expr *E = getCursorExpr(Cursor))
+ return Visit(E);
+
+ return false;
+ }
if (clang_isTranslationUnit(Cursor.kind)) {
CXTranslationUnit tu = getCursorTU(Cursor);
ASTUnit *CXXUnit = static_cast<ASTUnit*>(tu->TUData);
- if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
- RegionOfInterest.isInvalid()) {
- for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
- TLEnd = CXXUnit->top_level_end();
- TL != TLEnd; ++TL) {
- if (Visit(MakeCXCursor(*TL, tu), true))
+
+ int VisitOrder[2] = { VisitPreprocessorLast, !VisitPreprocessorLast };
+ for (unsigned I = 0; I != 2; ++I) {
+ if (VisitOrder[I]) {
+ if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
+ RegionOfInterest.isInvalid()) {
+ for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
+ TLEnd = CXXUnit->top_level_end();
+ TL != TLEnd; ++TL) {
+ if (Visit(MakeCXCursor(*TL, tu), true))
+ return true;
+ }
+ } else if (VisitDeclContext(
+ CXXUnit->getASTContext().getTranslationUnitDecl()))
return true;
+ continue;
}
- } else if (VisitDeclContext(
- CXXUnit->getASTContext().getTranslationUnitDecl()))
- return true;
- // Walk the preprocessing record.
- if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
- // FIXME: Once we have the ability to deserialize a preprocessing record,
- // do so.
- PreprocessingRecord::iterator E, EEnd;
- for (llvm::tie(E, EEnd) = getPreprocessedEntities(); E != EEnd; ++E) {
- if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
- if (Visit(MakeMacroInstantiationCursor(MI, tu)))
- return true;
-
- continue;
- }
-
- if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
- if (Visit(MakeMacroDefinitionCursor(MD, tu)))
- return true;
+ // Walk the preprocessing record.
+ if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
+ // FIXME: Once we have the ability to deserialize a preprocessing record,
+ // do so.
+ PreprocessingRecord::iterator E, EEnd;
+ for (llvm::tie(E, EEnd) = getPreprocessedEntities(); E != EEnd; ++E) {
+ if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
+ if (Visit(MakeMacroInstantiationCursor(MI, tu)))
+ return true;
+
+ continue;
+ }
- continue;
- }
-
- if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
- if (Visit(MakeInclusionDirectiveCursor(ID, tu)))
- return true;
+ if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
+ if (Visit(MakeMacroDefinitionCursor(MD, tu)))
+ return true;
+
+ continue;
+ }
- continue;
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
+ if (Visit(MakeInclusionDirectiveCursor(ID, tu)))
+ return true;
+
+ continue;
+ }
}
}
}
+
return false;
}
+ if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
+ if (CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {
+ if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {
+ return Visit(BaseTSInfo->getTypeLoc());
+ }
+ }
+ }
+
// Nothing to visit at the moment.
return false;
}
bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
- if (Visit(B->getSignatureAsWritten()->getTypeLoc()))
- return true;
+ if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
if (Stmt *Body = B->getBody())
return Visit(MakeCXCursor(Body, StmtParent, TU));
@@ -604,6 +644,13 @@ bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
return false;
}
+bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
return Visit(TSInfo->getTypeLoc());
@@ -742,7 +789,7 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
// FIXME: Attributes?
}
- if (ND->isThisDeclarationADefinition()) {
+ if (ND->isThisDeclarationADefinition() && !ND->isLateTemplateParsed()) {
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
// Find the initializers that were written in the source.
llvm::SmallVector<CXXCtorInitializer *, 4> WrittenInits;
@@ -1315,6 +1362,9 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
+ if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
+ return true;
+
return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
TAL.getTemplateNameLoc());
}
@@ -1362,7 +1412,9 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
case BuiltinType::LongDouble:
case BuiltinType::NullPtr:
case BuiltinType::Overload:
+ case BuiltinType::BoundMember:
case BuiltinType::Dependent:
+ case BuiltinType::UnknownAny:
break;
case BuiltinType::ObjCId:
@@ -1388,7 +1440,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
}
bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- return Visit(MakeCursorTypeRef(TL.getTypedefDecl(), TL.getNameLoc(), TU));
+ return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
@@ -1400,10 +1452,7 @@ bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
}
bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
- // FIXME: We can't visit the template type parameter, because there's
- // no context information with which we can match up the depth/index in the
- // type to the appropriate
- return false;
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
@@ -1503,6 +1552,35 @@ bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
return false;
}
+bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ // Visit the nested-name-specifier, if there is one.
+ if (TL.getQualifierLoc() &&
+ VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return Visit(TL.getNamedTypeLoc());
+}
+
bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
return Visit(TL.getPatternLoc());
}
@@ -1703,12 +1781,14 @@ public:
void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
void VisitObjCMessageExpr(ObjCMessageExpr *M);
void VisitOverloadExpr(OverloadExpr *E);
- void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
void VisitStmt(Stmt *S);
void VisitSwitchStmt(SwitchStmt *S);
void VisitWhileStmt(WhileStmt *W);
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+ void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
+ void VisitExpressionTraitExpr(ExpressionTraitExpr *E);
void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
void VisitVAArgExpr(VAArgExpr *E);
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
@@ -1797,8 +1877,8 @@ void EnqueueVisitor::
VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
AddDeclarationNameInfo(E);
- if (NestedNameSpecifier *Qualifier = E->getQualifier())
- AddNestedNameSpecifier(Qualifier, E->getQualifierRange());
+ if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
if (!E->isImplicitAccess())
AddStmt(E->getBase());
}
@@ -1934,12 +2014,8 @@ void EnqueueVisitor::VisitMemberExpr(MemberExpr *M) {
// visit it.
// FIXME: If we ever want to show these implicit accesses, this will be
// unfortunate. However, clang_getCursor() relies on this behavior.
- if (CXXThisExpr *This
- = llvm::dyn_cast<CXXThisExpr>(M->getBase()->IgnoreParenImpCasts()))
- if (This->isImplicit())
- return;
-
- AddStmt(M->getBase());
+ if (!M->isImplicitAccess())
+ AddStmt(M->getBase());
}
void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
AddTypeLoc(E->getEncodedTypeSourceInfo());
@@ -1958,7 +2034,7 @@ void EnqueueVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) {
AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));
break;
case OffsetOfNode::Field:
- AddMemberRef(Node.getField(), Node.getRange().getEnd());
+ AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());
break;
case OffsetOfNode::Identifier:
case OffsetOfNode::Base:
@@ -1972,7 +2048,8 @@ void EnqueueVisitor::VisitOverloadExpr(OverloadExpr *E) {
AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
WL.push_back(OverloadExprParts(E, Parent));
}
-void EnqueueVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *E) {
EnqueueChildren(E);
if (E->isArgumentType())
AddTypeLoc(E->getArgumentTypeInfo());
@@ -1991,6 +2068,7 @@ void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) {
AddStmt(W->getCond());
AddDecl(W->getConditionVariable());
}
+
void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
AddTypeLoc(E->getQueriedTypeSourceInfo());
}
@@ -2000,6 +2078,14 @@ void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
AddTypeLoc(E->getLhsTypeSourceInfo());
}
+void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ AddTypeLoc(E->getQueriedTypeSourceInfo());
+}
+
+void EnqueueVisitor::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ EnqueueChildren(E);
+}
+
void EnqueueVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U) {
VisitOverloadExpr(U);
if (!U->isImplicitAccess())
@@ -2124,8 +2210,8 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
MemberExpr *M = cast<MemberExprParts>(&LI)->get();
// Visit the nested-name-specifier
- if (NestedNameSpecifier *Qualifier = M->getQualifier())
- if (VisitNestedNameSpecifier(Qualifier, M->getQualifierRange()))
+ if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
return true;
// Visit the declaration name.
@@ -2146,8 +2232,8 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
case VisitorJob::DeclRefExprPartsKind: {
DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();
// Visit nested-name-specifier, if present.
- if (NestedNameSpecifier *Qualifier = DR->getQualifier())
- if (VisitNestedNameSpecifier(Qualifier, DR->getQualifierRange()))
+ if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
return true;
// Visit declaration name.
if (VisitDeclarationNameInfo(DR->getNameInfo()))
@@ -2157,8 +2243,8 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
case VisitorJob::OverloadExprPartsKind: {
OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();
// Visit the nested-name-specifier.
- if (NestedNameSpecifier *Qualifier = O->getQualifier())
- if (VisitNestedNameSpecifier(Qualifier, O->getQualifierRange()))
+ if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
return true;
// Visit the declaration name.
if (VisitDeclarationNameInfo(O->getNameInfo()))
@@ -2253,6 +2339,13 @@ void clang_disposeIndex(CXIndex CIdx) {
delete static_cast<CIndexer *>(CIdx);
}
+void clang_toggleCrashRecovery(unsigned isEnabled) {
+ if (isEnabled)
+ llvm::CrashRecoveryContext::Enable();
+ else
+ llvm::CrashRecoveryContext::Disable();
+}
+
CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
const char *ast_filename) {
if (!CIdx)
@@ -2327,27 +2420,37 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
// Configure the diagnostics.
DiagnosticOptions DiagOpts;
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
- Diags = CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args,
- command_line_args);
+ llvm::IntrusiveRefCntPtr<Diagnostic>
+ Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args,
+ command_line_args));
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
+ llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
+ DiagCleanup(Diags.getPtr());
+
+ llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> >
+ RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<
+ std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
- llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
for (unsigned I = 0; I != num_unsaved_files; ++I) {
llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
const llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
- RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
- Buffer));
+ RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
}
- llvm::SmallVector<const char *, 16> Args;
+ llvm::OwningPtr<std::vector<const char *> >
+ Args(new std::vector<const char*>());
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
+ ArgsCleanup(Args.get());
- // The 'source_filename' argument is optional. If the caller does not
- // specify it then it is assumed that the source file is specified
- // in the actual argument list.
- if (source_filename)
- Args.push_back(source_filename);
-
// Since the Clang C library is primarily used by batch tools dealing with
// (often very broken) source code, where spell-checking can have a
// significant negative impact on performance (particularly when
@@ -2362,26 +2465,37 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
}
}
if (!FoundSpellCheckingArgument)
- Args.push_back("-fno-spell-checking");
+ Args->push_back("-fno-spell-checking");
- Args.insert(Args.end(), command_line_args,
- command_line_args + num_command_line_args);
+ Args->insert(Args->end(), command_line_args,
+ command_line_args + num_command_line_args);
+
+ // The 'source_filename' argument is optional. If the caller does not
+ // specify it then it is assumed that the source file is specified
+ // in the actual argument list.
+ // Put the source file after command_line_args otherwise if '-x' flag is
+ // present it will be unused.
+ if (source_filename)
+ Args->push_back(source_filename);
// Do we need the detailed preprocessing record?
if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
- Args.push_back("-Xclang");
- Args.push_back("-detailed-preprocessing-record");
+ Args->push_back("-Xclang");
+ Args->push_back("-detailed-preprocessing-record");
}
unsigned NumErrors = Diags->getClient()->getNumErrors();
llvm::OwningPtr<ASTUnit> Unit(
- ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(),
+ ASTUnit::LoadFromCommandLine(Args->size() ? &(*Args)[0] : 0
+ /* vector::data() not portable */,
+ Args->size() ? (&(*Args)[0] + Args->size()) :0,
Diags,
CXXIdx->getClangResourcesPath(),
CXXIdx->getOnlyLocalDecls(),
/*CaptureDiagnostics=*/true,
- RemappedFiles.data(),
- RemappedFiles.size(),
+ RemappedFiles->size() ? &(*RemappedFiles)[0]:0,
+ RemappedFiles->size(),
+ /*RemappedFilesKeepOriginalName=*/true,
PrecompilePreamble,
CompleteTranslationUnit,
CacheCodeCompetionResults,
@@ -2503,16 +2617,23 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) {
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
- llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> >
+ RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<
+ std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
+
for (unsigned I = 0; I != num_unsaved_files; ++I) {
llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
const llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
- RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
- Buffer));
+ RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
}
- if (!CXXUnit->Reparse(RemappedFiles.data(), RemappedFiles.size()))
+ if (!CXXUnit->Reparse(RemappedFiles->size() ? &(*RemappedFiles)[0] : 0,
+ RemappedFiles->size()))
RTUI->result = 0;
}
@@ -2627,7 +2748,22 @@ CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
begin.int_data, end.int_data };
return Result;
}
+} // end: extern "C"
+
+static void createNullLocation(CXFile *file, unsigned *line,
+ unsigned *column, unsigned *offset) {
+ if (file)
+ *file = 0;
+ if (line)
+ *line = 0;
+ if (column)
+ *column = 0;
+ if (offset)
+ *offset = 0;
+ return;
+}
+extern "C" {
void clang_getInstantiationLocation(CXSourceLocation location,
CXFile *file,
unsigned *line,
@@ -2636,14 +2772,7 @@ void clang_getInstantiationLocation(CXSourceLocation location,
SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
if (!location.ptr_data[0] || Loc.isInvalid()) {
- if (file)
- *file = 0;
- if (line)
- *line = 0;
- if (column)
- *column = 0;
- if (offset)
- *offset = 0;
+ createNullLocation(file, line, column, offset);
return;
}
@@ -2651,8 +2780,18 @@ void clang_getInstantiationLocation(CXSourceLocation location,
*static_cast<const SourceManager*>(location.ptr_data[0]);
SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
+ // Check that the FileID is invalid on the instantiation location.
+ // This can manifest in invalid code.
+ FileID fileID = SM.getFileID(InstLoc);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
+ if (!sloc.isFile() || Invalid) {
+ createNullLocation(file, line, column, offset);
+ return;
+ }
+
if (file)
- *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc));
+ *file = (void *)SM.getFileEntryForSLocEntry(sloc);
if (line)
*line = SM.getInstantiationLineNumber(InstLoc);
if (column)
@@ -2816,7 +2955,8 @@ unsigned clang_visitChildren(CXCursor parent,
CXCursorVisitor visitor,
CXClientData client_data) {
CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,
- getCursorASTUnit(parent)->getMaxPCHLevel());
+ getCursorASTUnit(parent)->getMaxPCHLevel(),
+ false);
return CursorVis.VisitChildren(parent);
}
@@ -3216,6 +3356,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("UsingDirective");
case CXCursor_UsingDeclaration:
return createCXString("UsingDeclaration");
+ case CXCursor_TypeAliasDecl:
+ return createCXString("TypeAliasDecl");
}
llvm_unreachable("Unhandled CXCursorKind");
@@ -3272,7 +3414,7 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
// the region of interest, rather than starting from the translation unit.
CXCursor Parent = clang_getTranslationUnitCursor(TU);
CursorVisitor CursorVis(TU, GetCursorVisitor, &Result,
- Decl::MaxPCHLevel, SourceLocation(SLoc));
+ Decl::MaxPCHLevel, true, SourceLocation(SLoc));
CursorVis.VisitChildren(Parent);
}
@@ -3587,25 +3729,30 @@ static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) {
Decl *D = cxcursor::getCursorDecl(C);
SourceRange R = D->getSourceRange();
-
+
+ // Adjust the start of the location for declarations preceded by
+ // declaration specifiers.
+ SourceLocation StartLoc;
if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- if (TypeSourceInfo *TI = DD->getTypeSourceInfo()) {
- TypeLoc TL = TI->getTypeLoc();
- SourceLocation TLoc = TL.getSourceRange().getBegin();
- if (TLoc.isValid() && R.getBegin().isValid() &&
- SrcMgr.isBeforeInTranslationUnit(TLoc, R.getBegin()))
- R.setBegin(TLoc);
- }
+ if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
+ } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
+ if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
+ }
- // FIXME: Multiple variables declared in a single declaration
- // currently lack the information needed to correctly determine their
- // ranges when accounting for the type-specifier. We use context
- // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
- // and if so, whether it is the first decl.
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (!cxcursor::isFirstInDeclGroup(C))
- R.setBegin(VD->getLocation());
- }
+ if (StartLoc.isValid() && R.getBegin().isValid() &&
+ SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))
+ R.setBegin(StartLoc);
+
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ R.setBegin(VD->getLocation());
}
return R;
@@ -3660,7 +3807,9 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
if (clang_isStatement(C.kind)) {
Stmt *S = getCursorStmt(C);
if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
- return MakeCXCursor(Goto->getLabel()->getStmt(), getCursorDecl(C), tu);
+ if (LabelDecl *label = Goto->getLabel())
+ if (LabelStmt *labelS = label->getStmt())
+ return MakeCXCursor(labelS, getCursorDecl(C), tu);
return clang_getNullCursor();
}
@@ -3749,6 +3898,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
// declaration and definition.
case Decl::Namespace:
case Decl::Typedef:
+ case Decl::TypeAlias:
case Decl::TemplateTypeParm:
case Decl::EnumConstant:
case Decl::Field:
@@ -4215,7 +4365,8 @@ class AnnotateTokensWorker {
unsigned PreprocessingTokIdx;
CursorVisitor AnnotateVis;
SourceManager &SrcMgr;
-
+ bool HasContextSensitiveKeywords;
+
bool MoreTokens() const { return TokIdx < NumTokens; }
unsigned NextToken() const { return TokIdx; }
void AdvanceToken() { ++TokIdx; }
@@ -4231,8 +4382,9 @@ public:
NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0),
AnnotateVis(tu,
AnnotateTokensVisitor, this,
- Decl::MaxPCHLevel, RegionOfInterest),
- SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()) {}
+ Decl::MaxPCHLevel, true, RegionOfInterest),
+ SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()),
+ HasContextSensitiveKeywords(false) { }
void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
@@ -4240,6 +4392,12 @@ public:
void AnnotateTokens() {
AnnotateTokens(clang_getTranslationUnitCursor(AnnotateVis.getTU()));
}
+
+ /// \brief Determine whether the annotator saw any cursors that have
+ /// context-sensitive keywords.
+ bool hasContextSensitiveKeywords() const {
+ return HasContextSensitiveKeywords;
+ }
};
}
@@ -4273,7 +4431,52 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
SourceRange cursorRange = getRawCursorExtent(cursor);
if (cursorRange.isInvalid())
return CXChildVisit_Recurse;
-
+
+ if (!HasContextSensitiveKeywords) {
+ // Objective-C properties can have context-sensitive keywords.
+ if (cursor.kind == CXCursor_ObjCPropertyDecl) {
+ if (ObjCPropertyDecl *Property
+ = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
+ HasContextSensitiveKeywords = Property->getPropertyAttributesAsWritten() != 0;
+ }
+ // Objective-C methods can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
+ cursor.kind == CXCursor_ObjCClassMethodDecl) {
+ if (ObjCMethodDecl *Method
+ = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
+ if (Method->getObjCDeclQualifier())
+ HasContextSensitiveKeywords = true;
+ else {
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; ++P) {
+ if ((*P)->getObjCDeclQualifier()) {
+ HasContextSensitiveKeywords = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // C++ methods can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_CXXMethod) {
+ if (CXXMethodDecl *Method
+ = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
+ if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
+ HasContextSensitiveKeywords = true;
+ }
+ }
+ // C++ classes can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_StructDecl ||
+ cursor.kind == CXCursor_ClassDecl ||
+ cursor.kind == CXCursor_ClassTemplate ||
+ cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
+ if (Decl *D = getCursorDecl(cursor))
+ if (D->hasAttr<FinalAttr>())
+ HasContextSensitiveKeywords = true;
+ }
+ }
+
if (clang_isPreprocessing(cursor.kind)) {
// For macro instantiations, just note where the beginning of the macro
// instantiation occurs.
@@ -4342,15 +4545,19 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
if (MD->isSynthesized())
return CXChildVisit_Continue;
}
+
+ SourceLocation StartLoc;
if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- if (TypeSourceInfo *TI = DD->getTypeSourceInfo()) {
- TypeLoc TL = TI->getTypeLoc();
- SourceLocation TLoc = TL.getSourceRange().getBegin();
- if (TLoc.isValid() && L.isValid() &&
- SrcMgr.isBeforeInTranslationUnit(TLoc, L))
- cursorRange.setBegin(TLoc);
- }
+ if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
+ } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
+ if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getSourceRange().getBegin();
}
+
+ if (StartLoc.isValid() && L.isValid() &&
+ SrcMgr.isBeforeInTranslationUnit(StartLoc, L))
+ cursorRange.setBegin(StartLoc);
}
// If the location of the cursor occurs within a macro instantiation, record
@@ -4444,43 +4651,36 @@ static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
return static_cast<AnnotateTokensWorker*>(client_data)->Visit(cursor, parent);
}
-// This gets run a separate thread to avoid stack blowout.
-static void runAnnotateTokensWorker(void *UserData) {
- ((AnnotateTokensWorker*)UserData)->AnnotateTokens();
+namespace {
+ struct clang_annotateTokens_Data {
+ CXTranslationUnit TU;
+ ASTUnit *CXXUnit;
+ CXToken *Tokens;
+ unsigned NumTokens;
+ CXCursor *Cursors;
+ };
}
-extern "C" {
-
-void clang_annotateTokens(CXTranslationUnit TU,
- CXToken *Tokens, unsigned NumTokens,
- CXCursor *Cursors) {
-
- if (NumTokens == 0 || !Tokens || !Cursors)
- return;
-
- // Any token we don't specifically annotate will have a NULL cursor.
- CXCursor C = clang_getNullCursor();
- for (unsigned I = 0; I != NumTokens; ++I)
- Cursors[I] = C;
-
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
- if (!CXXUnit)
- return;
-
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+// 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;
// Determine the region of interest, which contains all of the tokens.
SourceRange RegionOfInterest;
- RegionOfInterest.setBegin(cxloc::translateSourceLocation(
- clang_getTokenLocation(TU, Tokens[0])));
- RegionOfInterest.setEnd(cxloc::translateSourceLocation(
- clang_getTokenLocation(TU,
- Tokens[NumTokens - 1])));
+ RegionOfInterest.setBegin(
+ cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
+ RegionOfInterest.setEnd(
+ cxloc::translateSourceLocation(clang_getTokenLocation(TU,
+ Tokens[NumTokens-1])));
// A mapping from the source locations found when re-lexing or traversing the
// region of interest to the corresponding cursors.
AnnotateTokensData Annotated;
-
+
// Relex the tokens within the source range to look for preprocessing
// directives.
SourceManager &SourceMgr = CXXUnit->getSourceManager();
@@ -4488,7 +4688,7 @@ void clang_annotateTokens(CXTranslationUnit TU,
= SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());
std::pair<FileID, unsigned> EndLocInfo
= SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());
-
+
llvm::StringRef Buffer;
bool Invalid = false;
if (BeginLocInfo.first == EndLocInfo.first &&
@@ -4499,13 +4699,13 @@ void clang_annotateTokens(CXTranslationUnit TU,
Buffer.begin(), Buffer.data() + BeginLocInfo.second,
Buffer.end());
Lex.SetCommentRetentionState(true);
-
+
// Lex tokens in raw mode until we hit the end of the range, to avoid
// entering #includes or expanding macros.
while (true) {
Token Tok;
Lex.LexFromRawLexer(Tok);
-
+
reprocess:
if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
// We have found a preprocessing directive. Gobble it up so that we
@@ -4515,49 +4715,158 @@ void clang_annotateTokens(CXTranslationUnit TU,
//
// FIXME: Some simple tests here could identify macro definitions and
// #undefs, to provide specific cursor kinds for those.
- std::vector<SourceLocation> Locations;
+ llvm::SmallVector<SourceLocation, 32> Locations;
do {
Locations.push_back(Tok.getLocation());
Lex.LexFromRawLexer(Tok);
} while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof));
-
+
using namespace cxcursor;
CXCursor Cursor
- = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
- Locations.back()),
+ = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
+ Locations.back()),
TU);
for (unsigned I = 0, N = Locations.size(); I != N; ++I) {
Annotated[Locations[I].getRawEncoding()] = Cursor;
}
-
+
if (Tok.isAtStartOfLine())
goto reprocess;
-
+
continue;
}
-
+
if (Tok.is(tok::eof))
break;
}
}
-
+
// Annotate all of the source locations in the region of interest that map to
// a specific cursor.
AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens,
TU, RegionOfInterest);
-
- // Run the worker within a CrashRecoveryContext.
+
// FIXME: We use a ridiculous stack size here because the data-recursion
// algorithm uses a large stack frame than the non-data recursive version,
// and AnnotationTokensWorker currently transforms the data-recursion
// algorithm back into a traditional recursion by explicitly calling
// VisitChildren(). We will need to remove this explicit recursive call.
+ W.AnnotateTokens();
+
+ // If we ran into any entities that involve context-sensitive keywords,
+ // take another pass through the tokens to mark them as such.
+ if (W.hasContextSensitiveKeywords()) {
+ for (unsigned I = 0; I != NumTokens; ++I) {
+ if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
+ continue;
+
+ if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (ObjCPropertyDecl *Property
+ = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
+ if (Property->getPropertyAttributesAsWritten() != 0 &&
+ llvm::StringSwitch<bool>(II->getName())
+ .Case("readonly", true)
+ .Case("assign", true)
+ .Case("readwrite", true)
+ .Case("retain", true)
+ .Case("copy", true)
+ .Case("nonatomic", true)
+ .Case("atomic", true)
+ .Case("getter", true)
+ .Case("setter", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ }
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
+ Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (llvm::StringSwitch<bool>(II->getName())
+ .Case("in", true)
+ .Case("out", true)
+ .Case("inout", true)
+ .Case("oneway", true)
+ .Case("bycopy", true)
+ .Case("byref", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_CXXMethod) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (CXXMethodDecl *Method
+ = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) {
+ if ((Method->hasAttr<FinalAttr>() ||
+ Method->hasAttr<OverrideAttr>()) &&
+ Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] &&
+ llvm::StringSwitch<bool>(II->getName())
+ .Case("final", true)
+ .Case("override", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ }
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_ClassDecl ||
+ Cursors[I].kind == CXCursor_StructDecl ||
+ Cursors[I].kind == CXCursor_ClassTemplate) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (II->getName() == "final") {
+ // We have to be careful with 'final', since it could be the name
+ // of a member class rather than the context-sensitive keyword.
+ // So, check whether the cursor associated with this
+ Decl *D = getCursorDecl(Cursors[I]);
+ if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(D)) {
+ if ((Record->hasAttr<FinalAttr>()) &&
+ Record->getIdentifier() != II)
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ } else if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast_or_null<ClassTemplateDecl>(D)) {
+ CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl();
+ if ((Record->hasAttr<FinalAttr>()) &&
+ Record->getIdentifier() != II)
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ }
+ }
+ continue;
+ }
+ }
+ }
+}
+
+extern "C" {
+
+void clang_annotateTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors) {
+
+ if (NumTokens == 0 || !Tokens || !Cursors)
+ return;
+
+ // Any token we don't specifically annotate will have a NULL cursor.
+ CXCursor C = clang_getNullCursor();
+ for (unsigned I = 0; I != NumTokens; ++I)
+ Cursors[I] = C;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ if (!CXXUnit)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, runAnnotateTokensWorker, &W,
+ if (!RunSafely(CRC, clang_annotateTokensImpl, &data,
GetSafetyThreadStackSize() * 2)) {
fprintf(stderr, "libclang: crash detected while annotating tokens\n");
}
}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
@@ -4639,14 +4948,22 @@ extern "C" {
enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
if (clang_isDeclaration(cursor.kind))
if (Decl *D = cxcursor::getCursorDecl(cursor)) {
- if (D->hasAttr<UnavailableAttr>() ||
- (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()))
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
return CXAvailability_Available;
- if (D->hasAttr<DeprecatedAttr>())
+ switch (D->getAvailability()) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ return CXAvailability_Available;
+
+ case AR_Deprecated:
return CXAvailability_Deprecated;
+
+ case AR_Unavailable:
+ return CXAvailability_NotAvailable;
+ }
}
-
+
return CXAvailability_Available;
}
@@ -4866,11 +5183,142 @@ CXType clang_getIBOutletCollectionType(CXCursor C) {
IBOutletCollectionAttr *A =
cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
- return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C));
+ return cxtype::MakeCXType(A->getInterFace(), cxcursor::getCursorTU(C));
}
} // end: extern "C"
//===----------------------------------------------------------------------===//
+// Inspecting memory usage.
+//===----------------------------------------------------------------------===//
+
+typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;
+
+static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
+ enum CXTUResourceUsageKind k,
+ unsigned long amount) {
+ CXTUResourceUsageEntry entry = { k, amount };
+ entries.push_back(entry);
+}
+
+extern "C" {
+
+const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
+ const char *str = "";
+ switch (kind) {
+ case CXTUResourceUsage_AST:
+ str = "ASTContext: expressions, declarations, and types";
+ break;
+ case CXTUResourceUsage_Identifiers:
+ str = "ASTContext: identifiers";
+ break;
+ case CXTUResourceUsage_Selectors:
+ str = "ASTContext: selectors";
+ break;
+ case CXTUResourceUsage_GlobalCompletionResults:
+ str = "Code completion: cached global results";
+ break;
+ case CXTUResourceUsage_SourceManagerContentCache:
+ str = "SourceManager: content cache allocator";
+ break;
+ case CXTUResourceUsage_AST_SideTables:
+ str = "ASTContext: side tables";
+ break;
+ case CXTUResourceUsage_SourceManager_Membuffer_Malloc:
+ str = "SourceManager: malloc'ed memory buffers";
+ break;
+ case CXTUResourceUsage_SourceManager_Membuffer_MMap:
+ str = "SourceManager: mmap'ed memory buffers";
+ break;
+ case CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:
+ str = "ExternalASTSource: malloc'ed memory buffers";
+ break;
+ case CXTUResourceUsage_ExternalASTSource_Membuffer_MMap:
+ str = "ExternalASTSource: mmap'ed memory buffers";
+ break;
+ }
+ return str;
+}
+
+CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
+ if (!TU) {
+ CXTUResourceUsage usage = { (void*) 0, 0, 0 };
+ return usage;
+ }
+
+ ASTUnit *astUnit = static_cast<ASTUnit*>(TU->TUData);
+ llvm::OwningPtr<MemUsageEntries> entries(new MemUsageEntries());
+ ASTContext &astContext = astUnit->getASTContext();
+
+ // How much memory is used by AST nodes and types?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST,
+ (unsigned long) astContext.getASTAllocatedMemory());
+
+ // How much memory is used by identifiers?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Identifiers,
+ (unsigned long) astContext.Idents.getAllocator().getTotalMemory());
+
+ // How much memory is used for selectors?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Selectors,
+ (unsigned long) astContext.Selectors.getTotalMemory());
+
+ // How much memory is used by ASTContext's side tables?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST_SideTables,
+ (unsigned long) astContext.getSideTableAllocatedMemory());
+
+ // How much memory is used for caching global code completion results?
+ unsigned long completionBytes = 0;
+ if (GlobalCodeCompletionAllocator *completionAllocator =
+ astUnit->getCachedCompletionAllocator().getPtr()) {
+ completionBytes = completionAllocator-> getTotalMemory();
+ }
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_GlobalCompletionResults,
+ completionBytes);
+
+ // How much memory is being used by SourceManager's content cache?
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManagerContentCache,
+ (unsigned long) astContext.getSourceManager().getContentCacheSize());
+
+ // How much memory is being used by the MemoryBuffer's in SourceManager?
+ const SourceManager::MemoryBufferSizes &srcBufs =
+ astUnit->getSourceManager().getMemoryBufferSizes();
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_Membuffer_Malloc,
+ (unsigned long) srcBufs.malloc_bytes);
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_Membuffer_MMap,
+ (unsigned long) srcBufs.mmap_bytes);
+
+ // How much memory is being used by the ExternalASTSource?
+ if (ExternalASTSource *esrc = astContext.getExternalSource()) {
+ const ExternalASTSource::MemoryBufferSizes &sizes =
+ esrc->getMemoryBufferSizes();
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc,
+ (unsigned long) sizes.malloc_bytes);
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,
+ (unsigned long) sizes.mmap_bytes);
+ }
+
+ CXTUResourceUsage usage = { (void*) entries.get(),
+ (unsigned) entries->size(),
+ entries->size() ? &(*entries)[0] : 0 };
+ entries.take();
+ return usage;
+}
+
+void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
+ if (usage.data)
+ delete (MemUsageEntries*) usage.data;
+}
+
+} // end extern "C"
+
+//===----------------------------------------------------------------------===//
// Misc. utility functions.
//===----------------------------------------------------------------------===//
@@ -4906,3 +5354,4 @@ CXString clang_getClangVersion() {
}
} // end: extern "C"
+
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 292719b..e85e802 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -201,7 +201,7 @@ clang_getCompletionAvailability(CXCompletionString completion_string) {
/// \brief The CXCodeCompleteResults structure we allocate internally;
/// the client only sees the initial CXCodeCompleteResults structure.
struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
- AllocatedCXCodeCompleteResults();
+ AllocatedCXCodeCompleteResults(const FileSystemOptions& FileSystemOpts);
~AllocatedCXCodeCompleteResults();
/// \brief Diagnostics produced while performing code completion.
@@ -216,10 +216,10 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
FileSystemOptions FileSystemOpts;
/// \brief File manager, used for diagnostics.
- FileManager FileMgr;
+ llvm::IntrusiveRefCntPtr<FileManager> FileMgr;
/// \brief Source manager, used for diagnostics.
- SourceManager SourceMgr;
+ llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr;
/// \brief Temporary files that should be removed once we have finished
/// with the code-completion results.
@@ -243,12 +243,14 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// Used for debugging purposes only.
static llvm::sys::cas_flag CodeCompletionResultObjects;
-AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
+AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
+ const FileSystemOptions& FileSystemOpts)
: CXCodeCompleteResults(),
Diag(new Diagnostic(
llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs))),
- FileMgr(FileSystemOpts),
- SourceMgr(*Diag, FileMgr) {
+ FileSystemOpts(FileSystemOpts),
+ FileMgr(new FileManager(FileSystemOpts)),
+ SourceMgr(new SourceManager(*Diag, *FileMgr)) {
if (getenv("LIBCLANG_OBJTRACKING")) {
llvm::sys::AtomicIncrement(&CodeCompletionResultObjects);
fprintf(stderr, "+++ %d completion results\n", CodeCompletionResultObjects);
@@ -380,7 +382,8 @@ void clang_codeCompleteAt_Impl(void *UserData) {
}
// Parse the resulting source file to find code-completion results.
- AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
+ AllocatedCXCodeCompleteResults *Results =
+ new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts());
Results->Results = 0;
Results->NumResults = 0;
@@ -393,8 +396,8 @@ void clang_codeCompleteAt_Impl(void *UserData) {
(options & CXCodeComplete_IncludeMacros),
(options & CXCodeComplete_IncludeCodePatterns),
Capture,
- *Results->Diag, Results->LangOpts, Results->SourceMgr,
- Results->FileMgr, Results->Diagnostics,
+ *Results->Diag, Results->LangOpts, *Results->SourceMgr,
+ *Results->FileMgr, Results->Diagnostics,
Results->TemporaryBuffers);
// Keep a reference to the allocator used for cached global completions, so
diff --git a/tools/libclang/CIndexInclusionStack.cpp b/tools/libclang/CIndexInclusionStack.cpp
index e0f4d42..6bc4f2e 100644
--- a/tools/libclang/CIndexInclusionStack.cpp
+++ b/tools/libclang/CIndexInclusionStack.cpp
@@ -40,14 +40,14 @@ void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
i = 0;
for ( ; i < n ; ++i) {
-
- const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i, &Invalid);
- if (!SL.isFile())
+ if (!SL.isFile() || Invalid)
continue;
const SrcMgr::FileInfo &FI = SL.getFile();
- if (!FI.getContentCache()->Entry)
+ if (!FI.getContentCache()->OrigEntry)
continue;
// Build the inclusion stack.
@@ -61,7 +61,7 @@ void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
// Callback to the client.
// FIXME: We should have a function to construct CXFiles.
- CB((CXFile) FI.getContentCache()->Entry,
+ CB((CXFile) FI.getContentCache()->OrigEntry,
InclusionStack.data(), InclusionStack.size(), clientData);
}
}
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index e74d1d4..9917d2a 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -431,7 +431,7 @@ void USRGenerator::VisitTagDecl(TagDecl *D) {
const unsigned off = Buf.size() - 1;
if (EmitDeclName(D)) {
- if (const TypedefDecl *TD = D->getTypedefForAnonDecl()) {
+ if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
Buf[off] = 'A';
Out << '@' << TD;
}
@@ -470,6 +470,12 @@ bool USRGenerator::GenLoc(const Decl *D) {
if (generatedLoc)
return IgnoreResults;
generatedLoc = true;
+
+ // Guard against null declarations in invalid code.
+ if (!D) {
+ IgnoreResults = true;
+ return true;
+ }
const SourceManager &SM = AU->getSourceManager();
SourceLocation L = D->getLocStart();
@@ -570,7 +576,9 @@ void USRGenerator::VisitType(QualType T) {
case BuiltinType::NullPtr:
c = 'n'; break;
case BuiltinType::Overload:
+ case BuiltinType::BoundMember:
case BuiltinType::Dependent:
+ case BuiltinType::UnknownAny:
IgnoreResults = true;
return;
case BuiltinType::ObjCId:
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp
index 992d76a..56974b9 100644
--- a/tools/libclang/CIndexer.cpp
+++ b/tools/libclang/CIndexer.cpp
@@ -32,6 +32,7 @@
#include <sstream>
#ifdef __CYGWIN__
+#include <cygwin/version.h>
#include <sys/cygwin.h>
#define LLVM_ON_WIN32 1
#endif
@@ -60,8 +61,12 @@ std::string CIndexer::getClangResourcesPath() {
#ifdef __CYGWIN__
char w32path[MAX_PATH];
strcpy(w32path, path);
+#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181
+ cygwin_conv_path(CCP_WIN_A_TO_POSIX, w32path, path, MAX_PATH);
+#else
cygwin_conv_to_full_posix_path(w32path, path);
#endif
+#endif
llvm::sys::Path LibClangPath(path);
LibClangPath.eraseComponent();
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index 11759ee..7a6270d 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -1,5 +1,3 @@
-set(SHARED_LIBRARY TRUE)
-
set(LLVM_USED_LIBS
clangFrontend
clangDriver
@@ -15,7 +13,7 @@ set( LLVM_LINK_COMPONENTS
mc
)
-add_clang_library(libclang
+set(SOURCES
CIndex.cpp
CIndexCXX.cpp
CIndexCodeCompletion.cpp
@@ -27,34 +25,44 @@ add_clang_library(libclang
CXString.cpp
CXType.cpp
../../include/clang-c/Index.h
-)
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- # Darwin-specific linker flags
+ )
- set(LIBCLANG_LINK_FLAGS "-Wl,-compatibility_version -Wl,1")
-
- set(LIBCLANG_LINK_FLAGS
- "${LIBCLANG_LINK_FLAGS} -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000")
+if( LLVM_ENABLE_PIC )
+ set(SHARED_LIBRARY TRUE)
+ add_clang_library(libclang ${SOURCES})
set_target_properties(libclang
PROPERTIES
- LINK_FLAGS "${LIBCLANG_LINK_FLAGS}"
- INSTALL_NAME_DIR "@executable_path/../lib")
+ OUTPUT_NAME "libclang"
+ VERSION ${LIBCLANG_LIBRARY_VERSION}
+ DEFINE_SYMBOL _CINDEX_LIB_)
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(LIBCLANG_LINK_FLAGS
+ "-Wl,-compatibility_version -Wl,1 -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000")
+ set_target_properties(libclang
+ PROPERTIES
+ LINK_FLAGS "${LIBCLANG_LINK_FLAGS}"
+ INSTALL_NAME_DIR "@executable_path/../lib")
+ endif()
+
+ if(MSVC)
+ # windows.h doesn't compile with /Za
+ get_target_property(NON_ANSI_COMPILE_FLAGS libclang COMPILE_FLAGS)
+ string(REPLACE "/Za" "" NON_ANSI_COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+ set_target_properties(libclang PROPERTIES
+ COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+ endif()
+
+ set(LIBCLANG_STATIC_TARGET_NAME libclang_static)
+else()
+ set(LIBCLANG_STATIC_TARGET_NAME libclang)
endif()
-# Versioning information
-set_target_properties(libclang PROPERTIES VERSION ${LIBCLANG_LIBRARY_VERSION})
-
-if(MSVC)
- # windows.h doesn't compile with /Za
- get_target_property(NON_ANSI_COMPILE_FLAGS libclang COMPILE_FLAGS)
- string(REPLACE /Za "" NON_ANSI_COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
- set_target_properties(libclang PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
-endif(MSVC)
-
-set_target_properties(libclang
- PROPERTIES
- PREFIX "" # Otherwise we get liblibclang.so
- LINKER_LANGUAGE CXX
- DEFINE_SYMBOL _CINDEX_LIB_)
+if( NOT BUILD_SHARED_LIBS AND NOT WIN32 )
+ add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES})
+
+ set_target_properties(${LIBCLANG_STATIC_TARGET_NAME}
+ PROPERTIES
+ OUTPUT_NAME "libclang")
+endif()
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index dd22a97..2a78012 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -95,6 +95,10 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
case Stmt::ObjCForCollectionStmtClass:
case Stmt::CXXCatchStmtClass:
case Stmt::CXXTryStmtClass:
+ case Stmt::CXXForRangeStmtClass:
+ case Stmt::SEHTryStmtClass:
+ case Stmt::SEHExceptStmtClass:
+ case Stmt::SEHFinallyStmtClass:
K = CXCursor_UnexposedStmt;
break;
@@ -111,7 +115,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
case Stmt::ParenExprClass:
case Stmt::UnaryOperatorClass:
case Stmt::OffsetOfExprClass:
- case Stmt::SizeOfAlignOfExprClass:
+ case Stmt::UnaryExprOrTypeTraitExprClass:
case Stmt::ArraySubscriptExprClass:
case Stmt::BinaryOperatorClass:
case Stmt::CompoundAssignOperatorClass:
@@ -129,6 +133,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
case Stmt::AddrLabelExprClass:
case Stmt::StmtExprClass:
case Stmt::ChooseExprClass:
+ case Stmt::GenericSelectionExprClass:
case Stmt::GNUNullExprClass:
case Stmt::CXXStaticCastExprClass:
case Stmt::CXXDynamicCastExprClass:
@@ -149,6 +154,8 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
case Stmt::UnresolvedLookupExprClass:
case Stmt::UnaryTypeTraitExprClass:
case Stmt::BinaryTypeTraitExprClass:
+ case Stmt::ArrayTypeTraitExprClass:
+ case Stmt::ExpressionTraitExprClass:
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::CXXBindTemporaryExprClass:
case Stmt::ExprWithCleanupsClass:
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index 7614544..30c3fd1 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -21,6 +21,7 @@ _clang_defaultEditingTranslationUnitOptions
_clang_defaultReparseOptions
_clang_defaultSaveOptions
_clang_disposeCXCursorSet
+_clang_disposeCXTUResourceUsage
_clang_disposeCodeCompleteResults
_clang_disposeDiagnostic
_clang_disposeIndex
@@ -35,6 +36,7 @@ _clang_equalTypes
_clang_executeOnThread
_clang_formatDiagnostic
_clang_getCString
+_clang_getCXTUResourceUsage
_clang_getCXXAccessSpecifier
_clang_getCanonicalCursor
_clang_getCanonicalType
@@ -98,6 +100,7 @@ _clang_getRangeStart
_clang_getResultType
_clang_getSpecializedCursorTemplate
_clang_getSpellingLocation
+_clang_getTUResourceUsageName
_clang_getTemplateCursorKind
_clang_getTokenExtent
_clang_getTokenKind
@@ -108,8 +111,8 @@ _clang_getTranslationUnitSpelling
_clang_getTypeDeclaration
_clang_getTypeKindSpelling
_clang_hashCursor
-_clang_isCursorDefinition
_clang_isConstQualifiedType
+_clang_isCursorDefinition
_clang_isDeclaration
_clang_isExpression
_clang_isInvalid
@@ -126,6 +129,7 @@ _clang_parseTranslationUnit
_clang_reparseTranslationUnit
_clang_saveTranslationUnit
_clang_sortCodeCompletionResults
+_clang_toggleCrashRecovery
_clang_tokenize
_clang_visitChildren
_clang_visitChildrenWithBlock
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index c2f0587..4e96e8a 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -21,6 +21,7 @@ clang_defaultEditingTranslationUnitOptions
clang_defaultReparseOptions
clang_defaultSaveOptions
clang_disposeCXCursorSet
+clang_disposeCXTUResourceUsage
clang_disposeCodeCompleteResults
clang_disposeDiagnostic
clang_disposeIndex
@@ -35,6 +36,7 @@ clang_equalTypes
clang_executeOnThread
clang_formatDiagnostic
clang_getCString
+clang_getCXTUResourceUsage
clang_getCXXAccessSpecifier
clang_getCanonicalCursor
clang_getCanonicalType
@@ -98,6 +100,7 @@ clang_getRangeStart
clang_getResultType
clang_getSpecializedCursorTemplate
clang_getSpellingLocation
+clang_getTUResourceUsageName
clang_getTemplateCursorKind
clang_getTokenExtent
clang_getTokenKind
@@ -126,6 +129,7 @@ clang_parseTranslationUnit
clang_reparseTranslationUnit
clang_saveTranslationUnit
clang_sortCodeCompletionResults
+clang_toggleCrashRecovery
clang_tokenize
clang_visitChildren
clang_visitChildrenWithBlock
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer
index 5601387..7793a8d 100755
--- a/tools/scan-build/ccc-analyzer
+++ b/tools/scan-build/ccc-analyzer
@@ -147,9 +147,10 @@ sub GetCCArgs {
}
sub Analyze {
- my ($Clang, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir,
+ my ($Clang, $OriginalArgs, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir,
$file) = @_;
+ my @Args = @$OriginalArgs;
my $Cmd;
my @CmdArgs;
my @CmdArgsSansAnalyses;
@@ -166,41 +167,37 @@ sub Analyze {
else {
$Cmd = $Clang;
if ($Lang eq "objective-c" || $Lang eq "objective-c++") {
- push @$Args,'-DIBOutlet=__attribute__((iboutlet))';
- push @$Args,'-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection)))';
- push @$Args,'-DIBAction=void)__attribute__((ibaction)';
+ push @Args,'-DIBOutlet=__attribute__((iboutlet))';
+ push @Args,'-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection)))';
+ push @Args,'-DIBAction=void)__attribute__((ibaction)';
}
# Create arguments for doing regular parsing.
- my $SyntaxArgs = GetCCArgs("-fsyntax-only", $Args);
- @CmdArgsSansAnalyses = @CmdArgs;
- push @CmdArgsSansAnalyses, @$SyntaxArgs;
-
+ my $SyntaxArgs = GetCCArgs("-fsyntax-only", \@Args);
+ @CmdArgsSansAnalyses = @$SyntaxArgs;
+
# Create arguments for doing static analysis.
if (defined $ResultFile) {
- push @$Args,'-o';
- push @$Args, $ResultFile;
+ push @Args, '-o', $ResultFile;
}
elsif (defined $HtmlDir) {
- push @$Args,'-o';
- push @$Args, $HtmlDir;
+ push @Args, '-o', $HtmlDir;
+ }
+ if ($Verbose) {
+ push @Args, "-Xclang", "-analyzer-display-progress";
}
- push @$Args,"-Xclang";
- push @$Args,"-analyzer-display-progress";
foreach my $arg (@$AnalyzeArgs) {
- push @$Args, "-Xclang";
- push @$Args, $arg;
+ push @Args, "-Xclang", $arg;
}
-
+
# Display Ubiviz graph?
if (defined $ENV{'CCC_UBI'}) {
- push @$Args, "-Xclang";
- push @$Args,"-analyzer-viz-egraph-ubigraph";
+ push @Args, "-Xclang", "-analyzer-viz-egraph-ubigraph";
}
- my $AnalysisArgs = GetCCArgs("--analyze", $Args);
- push @CmdArgs, @$AnalysisArgs;
+ my $AnalysisArgs = GetCCArgs("--analyze", \@Args);
+ @CmdArgs = @$AnalysisArgs;
}
my @PrintArgs;
@@ -217,7 +214,7 @@ sub Analyze {
if ($Verbose == 1) {
# We MUST print to stderr. Some clients use the stdout output of
# gcc for various purposes.
- print STDERR join(' ',@PrintArgs);
+ print STDERR join(' ', @PrintArgs);
print STDERR "\n";
}
elsif ($Verbose == 2) {
@@ -368,9 +365,11 @@ my %LangMap = (
'cp' => 'c++',
'cpp' => 'c++',
'cc' => 'c++',
+ 'ii' => 'c++',
'i' => 'c-cpp-output',
'm' => 'objective-c',
- 'mi' => 'objective-c-cpp-output'
+ 'mi' => 'objective-c-cpp-output',
+ 'mm' => 'objective-c++'
);
my %UniqueOptions = (
@@ -383,14 +382,11 @@ my %UniqueOptions = (
my %LangsAccepted = (
"objective-c" => 1,
- "c" => 1
+ "c" => 1,
+ "c++" => 1,
+ "objective-c++" => 1
);
-if (defined $ENV{'CCC_ANALYZER_CPLUSPLUS'}) {
- $LangsAccepted{"c++"} = 1;
- $LangsAccepted{"objective-c++"} = 1;
-}
-
##----------------------------------------------------------------------------##
# Main Logic.
##----------------------------------------------------------------------------##
@@ -613,8 +609,7 @@ if ($Action eq 'compile' or $Action eq 'link') {
my @AnalyzeArgs;
if ($FileLang ne 'unknown') {
- push @CmdArgs,'-x';
- push @CmdArgs,$FileLang;
+ push @CmdArgs, '-x', $FileLang;
}
if (defined $StoreModel) {
@@ -625,9 +620,9 @@ if ($Action eq 'compile' or $Action eq 'link') {
push @AnalyzeArgs, "-analyzer-constraints=$ConstraintsModel";
}
-# if (defined $Analyses) {
-# push @AnalyzeArgs, split '\s+', $Analyses;
-# }
+ if (defined $Analyses) {
+ push @AnalyzeArgs, split '\s+', $Analyses;
+ }
if (defined $OutputFormat) {
push @AnalyzeArgs, "-analyzer-output=" . $OutputFormat;
@@ -646,8 +641,7 @@ if ($Action eq 'compile' or $Action eq 'link') {
if (scalar @Archs) {
foreach my $arch (@Archs) {
my @NewArgs;
- push @NewArgs, '-arch';
- push @NewArgs, $arch;
+ push @NewArgs, '-arch', $arch;
push @NewArgs, @CmdArgs;
Analyze($Clang, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output,
$Verbose, $HtmlDir, $file);
diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build
index f7e521f..f835ca3 100755
--- a/tools/scan-build/scan-build
+++ b/tools/scan-build/scan-build
@@ -201,8 +201,8 @@ sub SetHtmlEnv {
die "No build command." if (scalar(@$Args) == 0);
my $Cmd = $$Args[0];
-
- if ($Cmd =~ /configure/) {
+
+ if ($Cmd =~ /configure/ || $Cmd =~ /autogen/) {
return;
}
@@ -290,7 +290,7 @@ sub AddStatLine {
print $Line . "\n";
my $Regex = qr/(.*?)\ :\ (.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable
- \ CFGBlocks:\ (\d+)\ \|\ Aborted\ Block:\ (yes|no)\ \|\ Empty\ WorkList:
+ \ CFGBlocks:\ (\d+)\ \|\ Exhausted\ Block:\ (yes|no)\ \|\ Empty\ WorkList:
\ (yes|no)/x;
if ($Line !~ $Regex) {
@@ -1001,8 +1001,16 @@ ADVANCED OPTIONS:
-stats - Generates visitation statistics for the project being analyzed.
-maxloop N - specifiy the number of times a block can be visited before giving
- up. Default is 3. Increase for more comprehensive coverage at a
+ up. Default is 4. Increase for more comprehensive coverage at a
cost of speed.
+
+CONTROLLING CHECKERS:
+
+ A default group of checkers are always run unless explicitly disabled.
+ Checkers may be enabled/disabled using the following options:
+
+ -enable-checker [checker name]
+ -disable-checker [checker name]
ENDTEXT
# Query clang for list of checkers that are enabled.
@@ -1053,7 +1061,7 @@ else {
print("\nAVAILABLE CHECKERS:\n\n");
my $skip = 0;
while(<FROM_CHILD>) {
- if (/core\.experimental/ or /debug\./ or /unix.experimental/ or /cocoa.experimental/) {
+ if (/experimental/) {
$skip = 1;
next;
}
@@ -1305,6 +1313,16 @@ while (@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;
+ }
DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
@@ -1365,7 +1383,7 @@ if ($AnalyzeHeaders) {
push @AnalysesToRun,"-analyzer-opt-analyze-headers";
}
if ($AnalyzerStats) {
- push @AnalysesToRun, '-analyzer-stats';
+ push @AnalysesToRun, '-analyzer-checker', 'debug.Stats';
}
if ($MaxLoop > 0) {
push @AnalysesToRun, '-analyzer-max-loop ' . $MaxLoop;
OpenPOWER on IntegriCloud