diff options
author | dim <dim@FreeBSD.org> | 2011-10-20 21:14:49 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-10-20 21:14:49 +0000 |
commit | 3963a48221351c61c17fb3f382341ab04809a3d3 (patch) | |
tree | ee2483e98b09cac943dc93a6969d83ca737ff139 /tools | |
parent | 611ba3ea3300b71eb95dc4e45f20eee5dddd32e1 (diff) | |
download | FreeBSD-src-3963a48221351c61c17fb3f382341ab04809a3d3.zip FreeBSD-src-3963a48221351c61c17fb3f382341ab04809a3d3.tar.gz |
Vendor import of clang release_30 branch r142614:
http://llvm.org/svn/llvm-project/cfe/branches/release_30@142614
Diffstat (limited to 'tools')
36 files changed, 2817 insertions, 1107 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index aff437f..117d10a 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,4 +2,5 @@ add_subdirectory(libclang) add_subdirectory(c-index-test) add_subdirectory(arcmt-test) add_subdirectory(c-arcmt-test) +add_subdirectory(diagtool) add_subdirectory(driver) diff --git a/tools/Makefile b/tools/Makefile index bfd2a64..4ea2cdd 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -8,7 +8,7 @@ ##===----------------------------------------------------------------------===## CLANG_LEVEL := .. -DIRS := driver libclang c-index-test arcmt-test c-arcmt-test +DIRS := driver libclang c-index-test arcmt-test c-arcmt-test diagtool include $(CLANG_LEVEL)/../../Makefile.config diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp index eb0f569..d27483f 100644 --- a/tools/arcmt-test/arcmt-test.cpp +++ b/tools/arcmt-test/arcmt-test.cpp @@ -10,7 +10,7 @@ #include "clang/ARCMigrate/ARCMT.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Frontend/VerifyDiagnosticsClient.h" +#include "clang/Frontend/VerifyDiagnosticConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/Preprocessor.h" #include "llvm/Support/MemoryBuffer.h" @@ -69,24 +69,24 @@ llvm::sys::Path GetExecutablePath(const char *Argv0) { } static void printSourceLocation(SourceLocation loc, ASTContext &Ctx, - llvm::raw_ostream &OS); + raw_ostream &OS); static void printSourceRange(CharSourceRange range, ASTContext &Ctx, - llvm::raw_ostream &OS); + raw_ostream &OS); namespace { class PrintTransforms : public MigrationProcess::RewriteListener { ASTContext *Ctx; - llvm::raw_ostream &OS; + raw_ostream &OS; public: - PrintTransforms(llvm::raw_ostream &OS) + PrintTransforms(raw_ostream &OS) : Ctx(0), OS(OS) { } virtual void start(ASTContext &ctx) { Ctx = &ctx; } virtual void finish() { Ctx = 0; } - virtual void insert(SourceLocation loc, llvm::StringRef text) { + virtual void insert(SourceLocation loc, StringRef text) { assert(Ctx); OS << "Insert: "; printSourceLocation(loc, *Ctx, OS); @@ -103,16 +103,17 @@ public: } // anonymous namespace -static bool checkForMigration(llvm::StringRef resourcesPath, - llvm::ArrayRef<const char *> Args) { - DiagnosticClient *DiagClient = +static bool checkForMigration(StringRef resourcesPath, + ArrayRef<const char *> Args) { + DiagnosticConsumer *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID, DiagClient)); + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags( + new DiagnosticsEngine(DiagID, DiagClient)); // Chain in -verify checker, if requested. - VerifyDiagnosticsClient *verifyDiag = 0; + VerifyDiagnosticConsumer *verifyDiag = 0; if (VerifyDiags) { - verifyDiag = new VerifyDiagnosticsClient(*Diags, Diags->takeClient()); + verifyDiag = new VerifyDiagnosticConsumer(*Diags); Diags->setClient(verifyDiag); } @@ -134,7 +135,7 @@ static bool checkForMigration(llvm::StringRef resourcesPath, return Diags->getClient()->getNumErrors() > 0; } -static void printResult(FileRemapper &remapper, llvm::raw_ostream &OS) { +static void printResult(FileRemapper &remapper, raw_ostream &OS) { CompilerInvocation CI; remapper.applyMappings(CI); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); @@ -145,16 +146,17 @@ static void printResult(FileRemapper &remapper, llvm::raw_ostream &OS) { } } -static bool performTransformations(llvm::StringRef resourcesPath, - llvm::ArrayRef<const char *> Args) { +static bool performTransformations(StringRef resourcesPath, + ArrayRef<const char *> Args) { // Check first. if (checkForMigration(resourcesPath, Args)) return true; - DiagnosticClient *DiagClient = + DiagnosticConsumer *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr<Diagnostic> TopDiags(new Diagnostic(DiagID, DiagClient)); + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> TopDiags( + new DiagnosticsEngine(DiagID, DiagClient)); CompilerInvocation origCI; CompilerInvocation::CreateFromArgs(origCI, Args.begin(), Args.end(), @@ -199,7 +201,7 @@ static bool performTransformations(llvm::StringRef resourcesPath, return false; } -static bool filesCompareEqual(llvm::StringRef fname1, llvm::StringRef fname2) { +static bool filesCompareEqual(StringRef fname1, StringRef fname2) { using namespace llvm; OwningPtr<MemoryBuffer> file1; @@ -215,7 +217,7 @@ static bool filesCompareEqual(llvm::StringRef fname1, llvm::StringRef fname2) { return file1->getBuffer() == file2->getBuffer(); } -static bool verifyTransformedFiles(llvm::ArrayRef<std::string> resultFiles) { +static bool verifyTransformedFiles(ArrayRef<std::string> resultFiles) { using namespace llvm; assert(!resultFiles.empty()); @@ -303,7 +305,7 @@ static bool verifyTransformedFiles(llvm::ArrayRef<std::string> resultFiles) { //===----------------------------------------------------------------------===// static void printSourceLocation(SourceLocation loc, ASTContext &Ctx, - llvm::raw_ostream &OS) { + raw_ostream &OS) { SourceManager &SM = Ctx.getSourceManager(); PresumedLoc PL = SM.getPresumedLoc(loc); @@ -313,7 +315,7 @@ static void printSourceLocation(SourceLocation loc, ASTContext &Ctx, } static void printSourceRange(CharSourceRange range, ASTContext &Ctx, - llvm::raw_ostream &OS) { + raw_ostream &OS) { SourceManager &SM = Ctx.getSourceManager(); const LangOptions &langOpts = Ctx.getLangOptions(); @@ -338,7 +340,6 @@ static void printSourceRange(CharSourceRange range, ASTContext &Ctx, //===----------------------------------------------------------------------===// int main(int argc, const char **argv) { - using llvm::StringRef; void *MainAddr = (void*) (intptr_t) GetExecutablePath; llvm::sys::PrintStackTraceOnErrorSignal(); @@ -365,7 +366,7 @@ int main(int argc, const char **argv) { return 1; } - llvm::ArrayRef<const char*> Args(argv+optargc+1, argc-optargc-1); + ArrayRef<const char*> Args(argv+optargc+1, argc-optargc-1); if (CheckOnly) return checkForMigration(resourcesPath, Args); diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt index 45ad9e3..c44b34b 100644 --- a/tools/c-index-test/CMakeLists.txt +++ b/tools/c-index-test/CMakeLists.txt @@ -13,3 +13,4 @@ set_target_properties(c-index-test PROPERTIES LINKER_LANGUAGE CXX) +install(TARGETS c-index-test RUNTIME DESTINATION bin) diff --git a/tools/c-index-test/Makefile b/tools/c-index-test/Makefile index 5e5b857..c21b327 100644 --- a/tools/c-index-test/Makefile +++ b/tools/c-index-test/Makefile @@ -13,9 +13,6 @@ 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 \ diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 6e0aaac..2a3584b 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -158,9 +158,25 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, /* Pretty-printing. */ /******************************************************************************/ +static void PrintRange(CXSourceRange R, const char *str) { + CXFile begin_file, end_file; + unsigned begin_line, begin_column, end_line, end_column; + + clang_getSpellingLocation(clang_getRangeStart(R), + &begin_file, &begin_line, &begin_column, 0); + clang_getSpellingLocation(clang_getRangeEnd(R), + &end_file, &end_line, &end_column, 0); + if (!begin_file || !end_file) + return; + + printf(" %s=", str); + PrintExtent(stdout, begin_line, begin_column, end_line, end_column); +} + int want_display_name = 0; -static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) { +static void PrintCursor(CXCursor Cursor) { + CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); if (clang_isInvalid(Cursor.kind)) { CXString ks = clang_getCursorKindSpelling(Cursor.kind); printf("Invalid Cursor => %s", clang_getCString(ks)); @@ -173,6 +189,9 @@ static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) { CXCursor SpecializationOf; CXCursor *overridden; unsigned num_overridden; + unsigned RefNameRangeNr; + CXSourceRange CursorExtent; + CXSourceRange RefNameRange; ks = clang_getCursorKindSpelling(Cursor.kind); string = want_display_name? clang_getCursorDisplayName(Cursor) @@ -219,6 +238,10 @@ static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) { case CXAvailability_NotAvailable: printf(" (unavailable)"); break; + + case CXAvailability_NotAccessible: + printf(" (inaccessible)"); + break; } if (clang_CXXMethod_isStatic(Cursor)) @@ -288,6 +311,26 @@ static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) { if (clang_isFileMultipleIncludeGuarded(TU, File)) printf(" [multi-include guarded]"); } + + CursorExtent = clang_getCursorExtent(Cursor); + RefNameRange = clang_getCursorReferenceNameRange(Cursor, + CXNameRange_WantQualifier + | CXNameRange_WantSinglePiece + | CXNameRange_WantTemplateArgs, + 0); + if (!clang_equalRanges(CursorExtent, RefNameRange)) + PrintRange(RefNameRange, "SingleRefName"); + + for (RefNameRangeNr = 0; 1; RefNameRangeNr++) { + RefNameRange = clang_getCursorReferenceNameRange(Cursor, + CXNameRange_WantQualifier + | CXNameRange_WantTemplateArgs, + RefNameRangeNr); + if (clang_equalRanges(clang_getNullRange(), RefNameRange)) + break; + if (!clang_equalRanges(CursorExtent, RefNameRange)) + PrintRange(RefNameRange, "RefName"); + } } } @@ -381,7 +424,7 @@ void PrintDiagnostics(CXTranslationUnit TU) { } void PrintMemoryUsage(CXTranslationUnit TU) { - unsigned long total = 0.0; + unsigned long total = 0; unsigned i = 0; CXTUResourceUsage usage = clang_getCXTUResourceUsage(TU); fprintf(stderr, "Memory usage:\n"); @@ -405,18 +448,7 @@ static const char *FileCheckPrefix = "CHECK"; static void PrintCursorExtent(CXCursor C) { CXSourceRange extent = clang_getCursorExtent(C); - CXFile begin_file, end_file; - unsigned begin_line, begin_column, end_line, end_column; - - clang_getSpellingLocation(clang_getRangeStart(extent), - &begin_file, &begin_line, &begin_column, 0); - clang_getSpellingLocation(clang_getRangeEnd(extent), - &end_file, &end_line, &end_column, 0); - if (!begin_file || !end_file) - return; - - printf(" Extent="); - PrintExtent(stdout, begin_line, begin_column, end_line, end_column); + PrintRange(extent, "Extent"); } /* Data used by all of the visitors. */ @@ -436,7 +468,7 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor, clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Cursor), line, column); - PrintCursor(Data->TU, Cursor); + PrintCursor(Cursor); PrintCursorExtent(Cursor); printf("\n"); return CXChildVisit_Recurse; @@ -489,7 +521,7 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor, } else if (Ref.kind != CXCursor_FunctionDecl) { printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref), curLine, curColumn); - PrintCursor(Data->TU, Ref); + PrintCursor(Ref); printf("\n"); } } @@ -564,8 +596,6 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p, CXClientData d) { const char *linkage = 0; - VisitorData *Data = (VisitorData *)d; - if (clang_isInvalid(clang_getCursorKind(cursor))) return CXChildVisit_Recurse; @@ -578,7 +608,7 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p, } if (linkage) { - PrintCursor(Data->TU, cursor); + PrintCursor(cursor); printf("linkage=%s\n", linkage); } @@ -591,12 +621,10 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p, static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p, CXClientData d) { - VisitorData *Data = (VisitorData *)d; - if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); CXString S = clang_getTypeKindSpelling(T.kind); - PrintCursor(Data->TU, cursor); + PrintCursor(cursor); printf(" typekind=%s", clang_getCString(S)); if (clang_isConstQualifiedType(T)) printf(" const"); @@ -747,6 +775,8 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, int num_unsaved_files = 0; int result; int trial; + int remap_after_trial = 0; + char *endptr = 0; Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(filter, "local") ? 1 : 0, @@ -770,8 +800,15 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, return 1; } + if (getenv("CINDEXTEST_REMAP_AFTER_TRIAL")) { + remap_after_trial = + strtol(getenv("CINDEXTEST_REMAP_AFTER_TRIAL"), &endptr, 10); + } + for (trial = 0; trial < trials; ++trial) { - if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + if (clang_reparseTranslationUnit(TU, + trial >= remap_after_trial ? num_unsaved_files : 0, + trial >= remap_after_trial ? unsaved_files : 0, clang_defaultReparseOptions(TU))) { fprintf(stderr, "Unable to reparse translation unit!\n"); clang_disposeTranslationUnit(TU); @@ -800,7 +837,7 @@ static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor, printf("-%s", prefix); PrintExtent(stdout, start_line, start_col, end_line, end_col); printf(" "); - PrintCursor(TU, cursor); + PrintCursor(cursor); printf("\n"); } @@ -996,6 +1033,7 @@ void print_completion_result(CXCompletionResult *completion_result, CXClientData client_data) { FILE *file = (FILE *)client_data; CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); + unsigned annotationCount; fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); @@ -1014,7 +1052,27 @@ void print_completion_result(CXCompletionResult *completion_result, case CXAvailability_NotAvailable: fprintf(file, " (unavailable)"); break; + + case CXAvailability_NotAccessible: + fprintf(file, " (inaccessible)"); + break; + } + + annotationCount = clang_getCompletionNumAnnotations( + completion_result->CompletionString); + if (annotationCount) { + unsigned i; + fprintf(file, " ("); + for (i = 0; i < annotationCount; ++i) { + if (i != 0) + fprintf(file, ", "); + fprintf(file, "\"%s\"", + clang_getCString(clang_getCompletionAnnotation( + completion_result->CompletionString, i))); + } + fprintf(file, ")"); } + fprintf(file, "\n"); } @@ -1171,8 +1229,11 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { } if (results) { - unsigned i, n = results->NumResults; + unsigned i, n = results->NumResults, containerIsIncomplete = 0; unsigned long long contexts; + enum CXCursorKind containerKind; + CXString objCSelector; + const char *selectorString; if (!timing_only) { /* Sort the code-completion results based on the typed text. */ clang_sortCodeCompletionResults(results->Results, results->NumResults); @@ -1190,6 +1251,35 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { contexts = clang_codeCompleteGetContexts(results); print_completion_contexts(contexts, stdout); + containerKind = clang_codeCompleteGetContainerKind(results, + &containerIsIncomplete); + + if (containerKind != CXCursor_InvalidCode) { + /* We have found a container */ + CXString containerUSR, containerKindSpelling; + containerKindSpelling = clang_getCursorKindSpelling(containerKind); + printf("Container Kind: %s\n", clang_getCString(containerKindSpelling)); + clang_disposeString(containerKindSpelling); + + if (containerIsIncomplete) { + printf("Container is incomplete\n"); + } + else { + printf("Container is complete\n"); + } + + containerUSR = clang_codeCompleteGetContainerUSR(results); + printf("Container USR: %s\n", clang_getCString(containerUSR)); + clang_disposeString(containerUSR); + } + + objCSelector = clang_codeCompleteGetObjCSelector(results); + selectorString = clang_getCString(objCSelector); + if (selectorString && strlen(selectorString) > 0) { + printf("Objective-C selector: %s\n", selectorString); + } + clang_disposeString(objCSelector); + clang_disposeCodeCompleteResults(results); } clang_disposeTranslationUnit(TU); @@ -1207,7 +1297,7 @@ typedef struct { unsigned column; } CursorSourceLocation; -int inspect_cursor_at(int argc, const char **argv) { +static int inspect_cursor_at(int argc, const char **argv) { CXIndex CIdx; int errorCode; struct CXUnsavedFile *unsaved_files = 0; @@ -1274,7 +1364,13 @@ int inspect_cursor_at(int argc, const char **argv) { clang_getLocation(TU, file, Locations[Loc].line, Locations[Loc].column)); if (I + 1 == Repeats) { - PrintCursor(TU, Cursor); + CXCompletionString completionString = clang_getCursorCompletionString( + Cursor); + PrintCursor(Cursor); + if (completionString != NULL) { + printf("\nCompletion string: "); + print_completion_string(completionString, stdout); + } printf("\n"); free(Locations[Loc].filename); } @@ -1289,6 +1385,101 @@ int inspect_cursor_at(int argc, const char **argv) { return 0; } +static enum CXVisitorResult findFileRefsVisit(void *context, + CXCursor cursor, CXSourceRange range) { + if (clang_Range_isNull(range)) + return CXVisit_Continue; + + PrintCursor(cursor); + PrintRange(range, ""); + printf("\n"); + return CXVisit_Continue; +} + +static int find_file_refs_at(int argc, const char **argv) { + CXIndex CIdx; + int errorCode; + struct CXUnsavedFile *unsaved_files = 0; + int num_unsaved_files = 0; + CXTranslationUnit TU; + CXCursor Cursor; + CursorSourceLocation *Locations = 0; + unsigned NumLocations = 0, Loc; + unsigned Repeats = 1; + unsigned I; + + /* Count the number of locations. */ + while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1]) + ++NumLocations; + + /* Parse the locations. */ + assert(NumLocations > 0 && "Unable to count locations?"); + Locations = (CursorSourceLocation *)malloc( + NumLocations * sizeof(CursorSourceLocation)); + for (Loc = 0; Loc < NumLocations; ++Loc) { + const char *input = argv[Loc + 1] + strlen("-file-refs-at="); + if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename, + &Locations[Loc].line, + &Locations[Loc].column, 0, 0))) + return errorCode; + } + + if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files, + &num_unsaved_files)) + return -1; + + if (getenv("CINDEXTEST_EDITING")) + Repeats = 5; + + /* Parse the translation unit. When we're testing clang_getCursor() after + reparsing, don't remap unsaved files until the second parse. */ + CIdx = clang_createIndex(1, 1); + TU = clang_parseTranslationUnit(CIdx, argv[argc - 1], + argv + num_unsaved_files + 1 + NumLocations, + argc - num_unsaved_files - 2 - NumLocations, + unsaved_files, + Repeats > 1? 0 : num_unsaved_files, + getDefaultParsingOptions()); + + if (!TU) { + fprintf(stderr, "unable to parse input\n"); + return -1; + } + + for (I = 0; I != Repeats; ++I) { + if (Repeats > 1 && + clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU))) { + clang_disposeTranslationUnit(TU); + return 1; + } + + for (Loc = 0; Loc < NumLocations; ++Loc) { + CXFile file = clang_getFile(TU, Locations[Loc].filename); + if (!file) + continue; + + Cursor = clang_getCursor(TU, + clang_getLocation(TU, file, Locations[Loc].line, + Locations[Loc].column)); + if (I + 1 == Repeats) { + CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit }; + PrintCursor(Cursor); + printf("\n"); + clang_findReferencesInFile(Cursor, file, visitor); + free(Locations[Loc].filename); + } + } + } + + PrintDiagnostics(TU); + clang_disposeTranslationUnit(TU); + clang_disposeIndex(CIdx); + free(Locations); + free_remapped_files(unsaved_files, num_unsaved_files); + return 0; +} + int perform_token_annotation(int argc, const char **argv) { const char *input = argv[1]; char *filename = 0; @@ -1331,6 +1522,17 @@ int perform_token_annotation(int argc, const char **argv) { } errorCode = 0; + if (getenv("CINDEXTEST_EDITING")) { + for (i = 0; i < 5; ++i) { + if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU))) { + fprintf(stderr, "Unable to reparse translation unit!\n"); + errorCode = -1; + goto teardown; + } + } + } + file = clang_getFile(TU, filename); if (!file) { fprintf(stderr, "file %s is not in this translation unit\n", filename); @@ -1379,7 +1581,7 @@ int perform_token_annotation(int argc, const char **argv) { PrintExtent(stdout, start_line, start_column, end_line, end_column); if (!clang_isInvalid(cursors[i].kind)) { printf(" "); - PrintCursor(TU, cursors[i]); + PrintCursor(cursors[i]); } printf("\n"); } @@ -1645,8 +1847,10 @@ static void print_usage(void) { "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n" " c-index-test -code-completion-timing=<site> <compiler arguments>\n" " c-index-test -cursor-at=<site> <compiler arguments>\n" + " c-index-test -file-refs-at=<site> <compiler arguments>\n" " c-index-test -test-file-scan <AST file> <source file> " - "[FileCheck prefix]\n" + "[FileCheck prefix]\n"); + fprintf(stderr, " c-index-test -test-load-tu <AST file> <symbol filter> " "[FileCheck prefix]\n" " c-index-test -test-load-tu-usrs <AST file> <symbol filter> " @@ -1691,6 +1895,8 @@ int cindextest_main(int argc, const char **argv) { return perform_code_completion(argc, argv, 1); if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1]) return inspect_cursor_at(argc, argv); + if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1]) + return find_file_refs_at(argc, argv); else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) { CXCursorVisitor I = GetVisitor(argv[1] + 13); if (I) diff --git a/tools/diagtool/CMakeLists.txt b/tools/diagtool/CMakeLists.txt new file mode 100644 index 0000000..f1fd9de --- /dev/null +++ b/tools/diagtool/CMakeLists.txt @@ -0,0 +1,24 @@ +set( LLVM_LINK_COMPONENTS + support + ) + +set( LLVM_USED_LIBS + clangBasic + clangLex + clangSema + ) + +add_clang_executable(diagtool + diagtool_main.cpp + DiagTool.cpp + ListWarnings.cpp +) + +if(UNIX) + set(CLANGXX_LINK_OR_COPY create_symlink) +else() + set(CLANGXX_LINK_OR_COPY copy) +endif() + +install(TARGETS diagtool + RUNTIME DESTINATION bin) diff --git a/tools/diagtool/DiagTool.cpp b/tools/diagtool/DiagTool.cpp new file mode 100644 index 0000000..36e72a2 --- /dev/null +++ b/tools/diagtool/DiagTool.cpp @@ -0,0 +1,68 @@ +//===- DiagTool.cpp - Classes for defining diagtool tools -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the boilerplate for defining diagtool tools. +// +//===----------------------------------------------------------------------===// + +#include "DiagTool.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/SmallString.h" +#include <vector> + +using namespace diagtool; + +DiagTool::DiagTool(llvm::StringRef toolCmd, + llvm::StringRef toolDesc) + : cmd(toolCmd), description(toolDesc) {} + +DiagTool::~DiagTool() {} + +typedef llvm::StringMap<DiagTool *> ToolMap; +static inline ToolMap *getTools(void *v) { return static_cast<ToolMap*>(v); } + +DiagTools::DiagTools() : tools(new ToolMap()) {} +DiagTools::~DiagTools() { delete getTools(tools); } + +DiagTool *DiagTools::getTool(llvm::StringRef toolCmd) { + ToolMap::iterator it = getTools(tools)->find(toolCmd); + return (it == getTools(tools)->end()) ? 0 : it->getValue(); +} + +void DiagTools::registerTool(DiagTool *tool) { + getTools(tools)->GetOrCreateValue(tool->getName(), tool); +} + +void DiagTools::printCommands(llvm::raw_ostream &out) { + std::vector<llvm::StringRef> toolNames; + unsigned maxName = 0; + for (ToolMap::iterator it = getTools(tools)->begin(), + ei = getTools(tools)->end(); it != ei; ++it) { + toolNames.push_back(it->getKey()); + unsigned len = it->getKey().size(); + if (len > maxName) + maxName = len; + } + std::sort(toolNames.begin(), toolNames.end()); + + for (std::vector<llvm::StringRef>::iterator it = toolNames.begin(), + ei = toolNames.end(); it != ei; ++it) { + + out << " " << (*it); + unsigned spaces = (maxName + 3) - (it->size()); + for (unsigned i = 0; i < spaces; ++i) + out << ' '; + + out << getTool(*it)->getDescription() << '\n'; + } +} + +namespace diagtool { + llvm::ManagedStatic<DiagTools> diagTools; +} diff --git a/tools/diagtool/DiagTool.h b/tools/diagtool/DiagTool.h new file mode 100644 index 0000000..dcb6ac7 --- /dev/null +++ b/tools/diagtool/DiagTool.h @@ -0,0 +1,70 @@ +//===- DiagTool.h - Classes for defining diagtool tools -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the boilerplate for defining diagtool tools. +// +//===----------------------------------------------------------------------===// + +#ifndef DIAGTOOL_DIAGTOOL_H +#define DIAGTOOL_DIAGTOOL_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ManagedStatic.h" +#include <string> + + +namespace diagtool { + +class DiagTool { + const std::string cmd; + const std::string description; +public: + DiagTool(llvm::StringRef toolCmd, llvm::StringRef toolDesc); + virtual ~DiagTool(); + + llvm::StringRef getName() const { return cmd; } + llvm::StringRef getDescription() const { return description; } + + virtual int run(unsigned argc, char *argv[], llvm::raw_ostream &out) = 0; +}; + +class DiagTools { + void *tools; +public: + DiagTools(); + ~DiagTools(); + + DiagTool *getTool(llvm::StringRef toolCmd); + void registerTool(DiagTool *tool); + void printCommands(llvm::raw_ostream &out); +}; + +extern llvm::ManagedStatic<DiagTools> diagTools; + +template <typename DIAGTOOL> +class RegisterDiagTool { +public: + RegisterDiagTool() { diagTools->registerTool(new DIAGTOOL()); } +}; + +} // end diagtool namespace + +#define DEF_DIAGTOOL(NAME, DESC, CLSNAME)\ +namespace {\ +class CLSNAME : public diagtool::DiagTool {\ +public:\ + CLSNAME() : DiagTool(NAME, DESC) {}\ + virtual ~CLSNAME() {}\ + virtual int run(unsigned argc, char *argv[], llvm::raw_ostream &out);\ +};\ +diagtool::RegisterDiagTool<CLSNAME> Register##CLSNAME;\ +} + +#endif diff --git a/tools/diagtool/ListWarnings.cpp b/tools/diagtool/ListWarnings.cpp new file mode 100644 index 0000000..7f7db8e --- /dev/null +++ b/tools/diagtool/ListWarnings.cpp @@ -0,0 +1,106 @@ +//===- ListWarnings.h - diagtool tool for printing warning flags ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a diagtool tool that displays warning flags for +// diagnostics. +// +//===----------------------------------------------------------------------===// + +#include "DiagTool.h" +#include "clang/Basic/Diagnostic.h" +#include "llvm/Support/Format.h" +#include "llvm/ADT/StringMap.h" + +DEF_DIAGTOOL("list-warnings", + "List warnings and their corresponding flags", + ListWarnings) + +using namespace clang; + + +namespace { +struct Entry { + llvm::StringRef DiagName; + llvm::StringRef Flag; + + Entry(llvm::StringRef diagN, llvm::StringRef flag) + : DiagName(diagN), Flag(flag) {} + + bool operator<(const Entry &x) const { return DiagName < x.DiagName; } +}; +} + +static void printEntries(std::vector<Entry> &entries, llvm::raw_ostream &out) { + for (std::vector<Entry>::iterator it = entries.begin(), ei = entries.end(); + it != ei; ++it) { + out << " " << it->DiagName; + if (!it->Flag.empty()) + out << " [-W" << it->Flag << "]"; + out << '\n'; + } +} + +int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { + llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags(new DiagnosticIDs); + DiagnosticsEngine D(Diags); + + std::vector<Entry> Flagged, Unflagged; + llvm::StringMap<std::vector<unsigned> > flagHistogram; + + for (DiagnosticIDs::diag_iterator di = DiagnosticIDs::diags_begin(), + de = DiagnosticIDs::diags_end(); di != de; ++di) { + + unsigned diagID = di.getDiagID(); + + if (DiagnosticIDs::isBuiltinNote(diagID)) + continue; + + if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID)) + continue; + + Entry entry(di.getDiagName(), + DiagnosticIDs::getWarningOptionForDiag(diagID)); + + if (entry.Flag.empty()) + Unflagged.push_back(entry); + else { + Flagged.push_back(entry); + flagHistogram.GetOrCreateValue(entry.Flag).getValue().push_back(diagID); + } + } + + std::sort(Flagged.begin(), Flagged.end()); + std::sort(Unflagged.begin(), Unflagged.end()); + + out << "Warnings with flags (" << Flagged.size() << "):\n"; + printEntries(Flagged, out); + + out << "Warnings without flags (" << Unflagged.size() << "):\n"; + printEntries(Unflagged, out); + + out << "\nSTATISTICS:\n\n"; + + double percentFlagged = ((double) Flagged.size()) + / (Flagged.size() + Unflagged.size()) * 100.0; + + out << " Percentage of warnings with flags: " + << llvm::format("%.4g",percentFlagged) << "%\n"; + + out << " Number of unique flags: " + << flagHistogram.size() << '\n'; + + double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size(); + out << " Average number of diagnostics per flag: " + << llvm::format("%.4g", avgDiagsPerFlag) << '\n'; + + out << '\n'; + + return 0; +} + diff --git a/tools/diagtool/Makefile b/tools/diagtool/Makefile new file mode 100644 index 0000000..22d7411 --- /dev/null +++ b/tools/diagtool/Makefile @@ -0,0 +1,25 @@ +##===- tools/driver/Makefile -------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +CLANG_LEVEL := ../.. + +TOOLNAME = diagtool + +# No plugins, optimize startup time. +TOOL_NO_EXPORTS := 1 + +# Don't install this. +NO_INSTALL = 1 + +LINK_COMPONENTS := support + +USEDLIBS = clangCodeGen.a clangParse.a clangSema.a \ + clangAST.a clangLex.a clangBasic.a + +include $(CLANG_LEVEL)/Makefile + diff --git a/tools/diagtool/diagtool_main.cpp b/tools/diagtool/diagtool_main.cpp new file mode 100644 index 0000000..e34f0dc --- /dev/null +++ b/tools/diagtool/diagtool_main.cpp @@ -0,0 +1,26 @@ +//===- diagtool_main.h - Entry point for invoking all diagnostic tools ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the main function for diagtool. +// +//===----------------------------------------------------------------------===// + +#include "DiagTool.h" + +using namespace diagtool; + +int main(int argc, char *argv[]) { + if (argc > 1) + if (DiagTool *tool = diagTools->getTool(argv[1])) + return tool->run(argc - 1, &argv[2], llvm::errs()); + + llvm::errs() << "usage: diagtool <command> [<args>]\n\n"; + diagTools->printCommands(llvm::errs()); + return 1; +} diff --git a/tools/driver/Makefile b/tools/driver/Makefile index 1ba8bc2..6b34a99 100644 --- a/tools/driver/Makefile +++ b/tools/driver/Makefile @@ -9,13 +9,7 @@ CLANG_LEVEL := ../.. TOOLNAME = clang -ifndef CLANG_IS_PRODUCTION TOOLALIAS = clang++ -else - ifdef CLANGXX_IS_PRODUCTION - TOOLALIAS = clang++ - endif -endif # We don't currently expect production Clang builds to be interested in # plugins. This is important for startup performance. @@ -73,6 +67,3 @@ endif ifdef CLANG_IS_PRODUCTION CPP.Defines += -DCLANG_IS_PRODUCTION endif -ifdef CLANGXX_IS_PRODUCTION -CPP.Defines += -DCLANGXX_IS_PRODUCTION -endif diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 9ad4af1..27f79b7 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -27,9 +27,9 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetSelect.h" #include <cstdio> using namespace clang; @@ -38,7 +38,7 @@ using namespace clang; //===----------------------------------------------------------------------===// static void LLVMErrorHandler(void *UserData, const std::string &Message) { - Diagnostic &Diags = *static_cast<Diagnostic*>(UserData); + DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); Diags.Report(diag::err_fe_error_backend) << Message; @@ -47,7 +47,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) { } // FIXME: Define the need for this testing away. -static int cc1_test(Diagnostic &Diags, +static int cc1_test(DiagnosticsEngine &Diags, const char **ArgBegin, const char **ArgEnd) { using namespace clang::driver; @@ -83,7 +83,7 @@ static int cc1_test(Diagnostic &Diags, Invocation.toArgs(InvocationArgs); // Dump the converted arguments. - llvm::SmallVector<const char*, 32> Invocation2Args; + SmallVector<const char*, 32> Invocation2Args; llvm::errs() << "invocation argv :"; for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { Invocation2Args.push_back(InvocationArgs[i].c_str()); @@ -118,23 +118,22 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd, llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); // Run clang -cc1 test. - if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") { - Diagnostic Diags(DiagID, new TextDiagnosticPrinter(llvm::errs(), + if (ArgBegin != ArgEnd && StringRef(ArgBegin[0]) == "-cc1test") { + DiagnosticsEngine Diags(DiagID, new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions())); return cc1_test(Diags, ArgBegin + 1, ArgEnd); } // Initialize targets first, so that --version shows registered targets. llvm::InitializeAllTargets(); - llvm::InitializeAllMCAsmInfos(); - llvm::InitializeAllMCSubtargetInfos(); + llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; - Diagnostic Diags(DiagID, DiagsBuffer); + DiagnosticsEngine Diags(DiagID, DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd, Diags); diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp index 358d746..7cc42aa 100644 --- a/tools/driver/cc1as_main.cpp +++ b/tools/driver/cc1as_main.cpp @@ -30,8 +30,12 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ErrorHandling.h" @@ -39,23 +43,15 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" -#include "llvm/Target/TargetAsmBackend.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetSelect.h" -#include "llvm/Target/TargetSubtargetInfo.h" using namespace clang; using namespace clang::driver; using namespace llvm; @@ -125,7 +121,7 @@ public: } static void CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin, - const char **ArgEnd, Diagnostic &Diags); + const char **ArgEnd, DiagnosticsEngine &Diags); }; } @@ -133,7 +129,7 @@ public: void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, const char **ArgBegin, const char **ArgEnd, - Diagnostic &Diags) { + DiagnosticsEngine &Diags) { using namespace clang::driver::cc1asoptions; // Parse the arguments. OwningPtr<OptTable> OptTbl(createCC1AsOptTable()); @@ -207,7 +203,7 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, } static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts, - Diagnostic &Diags, + DiagnosticsEngine &Diags, bool Binary) { if (Opts.OutputPath.empty()) Opts.OutputPath = "-"; @@ -230,7 +226,8 @@ static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts, return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM); } -static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { +static bool ExecuteAssembler(AssemblerInvocation &Opts, + DiagnosticsEngine &Diags) { // Get the target specific parser. std::string Error; const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error)); @@ -259,64 +256,60 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(Opts.Triple)); assert(MAI && "Unable to create target asm info!"); + OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); + assert(MRI && "Unable to create target register info!"); + bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary); if (!Out) return false; - // FIXME: We shouldn't need to do this (and link in codegen). - OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(Opts.Triple, - "", "")); - if (!TM) { - Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; - return false; - } - - const TargetAsmInfo *tai = new TargetAsmInfo(*TM); - MCContext Ctx(*MAI, tai); + // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and + // MCObjectFileInfo needs a MCContext reference in order to initialize itself. + OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); + MCContext Ctx(*MAI, *MRI, MOFI.get()); + // FIXME: Assembler behavior can change with -static. + MOFI->InitMCObjectFileInfo(Opts.Triple, + Reloc::Default, CodeModel::Default, Ctx); if (Opts.SaveTemporaryLabels) Ctx.setAllowTemporaryLabels(false); OwningPtr<MCStreamer> Str; - const TargetLoweringObjectFile &TLOF = - TM->getTargetLowering()->getObjFileLowering(); - const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(Ctx, *TM); - - const MCSubtargetInfo &STI = TM->getSubtarget<MCSubtargetInfo>(); + OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); + OwningPtr<MCSubtargetInfo> + STI(TheTarget->createMCSubtargetInfo(Opts.Triple, "", "")); // 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(Opts.OutputAsmVariant, *MAI, *STI); MCCodeEmitter *CE = 0; - TargetAsmBackend *TAB = 0; + MCAsmBackend *MAB = 0; if (Opts.ShowEncoding) { - CE = TheTarget->createCodeEmitter(*TM->getInstrInfo(), STI, Ctx); - TAB = TheTarget->createAsmBackend(Opts.Triple); + CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx); + MAB = TheTarget->createMCAsmBackend(Opts.Triple); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, /*useLoc*/ true, - /*useCFI*/ true, IP, CE, TAB, + /*useCFI*/ true, IP, CE, MAB, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); - MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM->getInstrInfo(), - STI, Ctx); - TargetAsmBackend *TAB = TheTarget->createAsmBackend(Opts.Triple); - Str.reset(TheTarget->createObjectStreamer(Opts.Triple, Ctx, *TAB, *Out, - CE, Opts.RelaxAll, - Opts.NoExecStack)); + MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx); + MCAsmBackend *MAB = TheTarget->createMCAsmBackend(Opts.Triple); + Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, + CE, Opts.RelaxAll, + Opts.NoExecStack)); Str.get()->InitSections(); } - OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx, + OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); - OwningPtr<TargetAsmParser> - TAP(TheTarget->createAsmParser(const_cast<MCSubtargetInfo&>(STI), *Parser)); + OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser)); if (!TAP) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; @@ -337,7 +330,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { } static void LLVMErrorHandler(void *UserData, const std::string &Message) { - Diagnostic &Diags = *static_cast<Diagnostic*>(UserData); + DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); Diags.Report(diag::err_fe_error_backend) << Message; @@ -354,12 +347,7 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd, // Initialize targets and assembly printers/parsers. InitializeAllTargetInfos(); - // FIXME: We shouldn't need to initialize the Target(Machine)s. - InitializeAllTargets(); - InitializeAllMCAsmInfos(); - InitializeAllMCInstrInfos(); - InitializeAllMCSubtargetInfos(); - InitializeAllAsmPrinters(); + InitializeAllTargetMCs(); InitializeAllAsmParsers(); // Construct our diagnostic client. @@ -367,7 +355,7 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd, = new TextDiagnosticPrinter(errs(), DiagnosticOptions()); DiagClient->setPrefix("clang -cc1as"); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - Diagnostic Diags(DiagID, DiagClient); + DiagnosticsEngine Diags(DiagID, DiagClient); // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index ca89826..bd1d2a2 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -35,9 +35,9 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.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; @@ -53,7 +53,7 @@ llvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { } static const char *SaveStringInSet(std::set<std::string> &SavedStrings, - llvm::StringRef S) { + StringRef S) { return SavedStrings.insert(S).first->c_str(); } @@ -84,9 +84,9 @@ static const char *SaveStringInSet(std::set<std::string> &SavedStrings, /// \param Args - The vector of command line arguments. /// \param Edit - The override command to perform. /// \param SavedStrings - Set to use for storing string representations. -static void ApplyOneQAOverride(llvm::raw_ostream &OS, - llvm::SmallVectorImpl<const char*> &Args, - llvm::StringRef Edit, +static void ApplyOneQAOverride(raw_ostream &OS, + SmallVectorImpl<const char*> &Args, + StringRef Edit, std::set<std::string> &SavedStrings) { // This does not need to be efficient. @@ -101,9 +101,9 @@ static void ApplyOneQAOverride(llvm::raw_ostream &OS, OS << "### Adding argument " << Str << " at end\n"; Args.push_back(Str); } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && - Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) { - llvm::StringRef MatchPattern = Edit.substr(2).split('/').first; - llvm::StringRef ReplPattern = Edit.substr(2).split('/').second; + Edit.slice(2, Edit.size()-1).find('/') != StringRef::npos) { + StringRef MatchPattern = Edit.substr(2).split('/').first; + StringRef ReplPattern = Edit.substr(2).split('/').second; ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); for (unsigned i = 1, e = Args.size(); i != e; ++i) { @@ -151,10 +151,10 @@ static void ApplyOneQAOverride(llvm::raw_ostream &OS, /// ApplyQAOverride - Apply a comma separate list of edits to the /// input argument lists. See ApplyOneQAOverride. -static void ApplyQAOverride(llvm::SmallVectorImpl<const char*> &Args, +static void ApplyQAOverride(SmallVectorImpl<const char*> &Args, const char *OverrideStr, std::set<std::string> &SavedStrings) { - llvm::raw_ostream *OS = &llvm::errs(); + raw_ostream *OS = &llvm::errs(); if (OverrideStr[0] == '#') { ++OverrideStr; @@ -184,7 +184,7 @@ extern int cc1as_main(const char **ArgBegin, const char **ArgEnd, const char *Argv0, void *MainAddr); static void ExpandArgsFromBuf(const char *Arg, - llvm::SmallVectorImpl<const char*> &ArgVector, + SmallVectorImpl<const char*> &ArgVector, std::set<std::string> &SavedStrings) { const char *FName = Arg + 1; llvm::OwningPtr<llvm::MemoryBuffer> MemBuf; @@ -242,7 +242,7 @@ static void ExpandArgsFromBuf(const char *Arg, } static void ExpandArgv(int argc, const char **argv, - llvm::SmallVectorImpl<const char*> &ArgVector, + SmallVectorImpl<const char*> &ArgVector, std::set<std::string> &SavedStrings) { for (int i = 0; i < argc; ++i) { const char *Arg = argv[i]; @@ -255,7 +255,7 @@ static void ExpandArgv(int argc, const char **argv, } } -static void ParseProgName(llvm::SmallVectorImpl<const char *> &ArgVector, +static void ParseProgName(SmallVectorImpl<const char *> &ArgVector, std::set<std::string> &SavedStrings, Driver &TheDriver) { @@ -290,8 +290,8 @@ static void ParseProgName(llvm::SmallVectorImpl<const char *> &ArgVector, { "++", true, false }, }; std::string ProgName(llvm::sys::path::stem(ArgVector[0])); - llvm::StringRef ProgNameRef(ProgName); - llvm::StringRef Prefix; + StringRef ProgNameRef(ProgName); + StringRef Prefix; for (int Components = 2; Components; --Components) { bool FoundMatch = false; @@ -309,15 +309,15 @@ static void ParseProgName(llvm::SmallVectorImpl<const char *> &ArgVector, } if (FoundMatch) { - llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-', + StringRef::size_type LastComponent = ProgNameRef.rfind('-', ProgNameRef.size() - strlen(suffixes[i].Suffix)); - if (LastComponent != llvm::StringRef::npos) + if (LastComponent != StringRef::npos) Prefix = ProgNameRef.slice(0, LastComponent); break; } - llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-'); - if (LastComponent == llvm::StringRef::npos) + StringRef::size_type LastComponent = ProgNameRef.rfind('-'); + if (LastComponent == StringRef::npos) break; ProgNameRef = ProgNameRef.slice(0, LastComponent); } @@ -327,7 +327,7 @@ static void ParseProgName(llvm::SmallVectorImpl<const char *> &ArgVector, std::string IgnoredError; if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { - llvm::SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); + SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); if (it != ArgVector.end()) ++it; ArgVector.insert(it, SaveStringInSet(SavedStrings, Prefix)); @@ -341,13 +341,13 @@ int main(int argc_, const char **argv_) { llvm::PrettyStackTraceProgram X(argc_, argv_); std::set<std::string> SavedStrings; - llvm::SmallVector<const char*, 256> argv; + SmallVector<const char*, 256> argv; ExpandArgv(argc_, argv_, argv, SavedStrings); // Handle -cc1 integrated tools. - if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) { - llvm::StringRef Tool = argv[1] + 4; + if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) { + StringRef Tool = argv[1] + 4; if (Tool == "") return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0], @@ -363,7 +363,7 @@ int main(int argc_, const char **argv_) { bool CanonicalPrefixes = true; for (int i = 1, size = argv.size(); i < size; ++i) { - if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") { + if (StringRef(argv[i]) == "-no-canonical-prefixes") { CanonicalPrefixes = false; break; } @@ -375,22 +375,15 @@ int main(int argc_, const char **argv_) { = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); DiagClient->setPrefix(llvm::sys::path::stem(Path.str())); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - Diagnostic Diags(DiagID, DiagClient); + DiagnosticsEngine Diags(DiagID, DiagClient); #ifdef CLANG_IS_PRODUCTION const bool IsProduction = true; -# ifdef CLANGXX_IS_PRODUCTION - const bool CXXIsProduction = true; -# else - const bool CXXIsProduction = false; -# endif #else const bool IsProduction = false; - const bool CXXIsProduction = false; #endif Driver TheDriver(Path.str(), llvm::sys::getHostTriple(), - "a.out", IsProduction, CXXIsProduction, - Diags); + "a.out", IsProduction, Diags); // Attempt to find the original path used to invoke the driver, to determine // the installed path. We do this manually, because we want to support that @@ -458,9 +451,15 @@ int main(int argc_, const char **argv_) { llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv)); int Res = 0; + const Command *FailingCommand = 0; if (C.get()) - Res = TheDriver.ExecuteCompilation(*C); - + Res = TheDriver.ExecuteCompilation(*C, FailingCommand); + + // If result status is < 0, then the driver command signalled an error. + // In this case, generate additional diagnostic information if possible. + if (Res < 0) + TheDriver.generateCompilationDiagnostics(*C, FailingCommand); + // If any timers were active but haven't been destroyed yet, print their // results now. This happens in -disable-free mode. llvm::TimerGroup::printAll(llvm::errs()); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 50d56fc..46ba3d5 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -51,8 +51,9 @@ using namespace clang; using namespace clang::cxcursor; using namespace clang::cxstring; +using namespace clang::cxtu; -static CXTranslationUnit MakeCXTranslationUnit(ASTUnit *TU) { +CXTranslationUnit cxtu::MakeCXTranslationUnit(ASTUnit *TU) { if (!TU) return 0; CXTranslationUnit D = new CXTranslationUnitImpl(); @@ -117,10 +118,10 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM, // location accordingly. SourceLocation EndLoc = R.getEnd(); if (EndLoc.isValid() && EndLoc.isMacroID()) - EndLoc = SM.getInstantiationRange(EndLoc).second; + EndLoc = SM.getExpansionRange(EndLoc).second; if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) { unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts); - EndLoc = EndLoc.getFileLocWithOffset(Length); + EndLoc = EndLoc.getLocWithOffset(Length); } CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts }, @@ -141,7 +142,6 @@ public: TypeLocVisitKind, OverloadExprPartsKind, DeclRefExprPartsKind, LabelRefVisitKind, ExplicitTemplateArgsVisitKind, - NestedNameSpecifierVisitKind, NestedNameSpecifierLocVisitKind, DeclarationNameInfoVisitKind, MemberRefVisitKind, SizeOfPackExprPartsKind }; @@ -161,7 +161,7 @@ public: static bool classof(VisitorJob *VJ) { return true; } }; -typedef llvm::SmallVector<VisitorJob, 10> VisitorWorkList; +typedef SmallVector<VisitorJob, 10> VisitorWorkList; // Cursor visitor. class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, @@ -184,11 +184,6 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, /// \brief The opaque client data, to be passed along to the visitor. CXClientData ClientData; - // MaxPCHLevel - the maximum PCH level of declarations that we will pass on - // to the visitor. Declarations with a PCH level greater than this value will - // be suppressed. - unsigned MaxPCHLevel; - /// \brief Whether we should visit the preprocessing record entries last, /// after visiting other declarations. bool VisitPreprocessorLast; @@ -203,8 +198,8 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, DeclContext::decl_iterator DE_current; // Cache of pre-allocated worklists for data-recursion walk of Stmts. - llvm::SmallVector<VisitorWorkList*, 5> WorkListFreeList; - llvm::SmallVector<VisitorWorkList*, 5> WorkListCache; + SmallVector<VisitorWorkList*, 5> WorkListFreeList; + SmallVector<VisitorWorkList*, 5> WorkListCache; using DeclVisitor<CursorVisitor, bool>::Visit; using TypeLocVisitor<CursorVisitor, bool>::Visit; @@ -239,12 +234,11 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, 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), VisitPreprocessorLast(VisitPreprocessorLast), + VisitPreprocessorLast(VisitPreprocessorLast), RegionOfInterest(RegionOfInterest), DI_current(0) { Parent.kind = CXCursor_NoDeclFound; @@ -256,7 +250,7 @@ public: ~CursorVisitor() { // Free the pre-allocated worklists for data-recursion. - for (llvm::SmallVectorImpl<VisitorWorkList*>::iterator + for (SmallVectorImpl<VisitorWorkList*>::iterator I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) { delete *I; } @@ -267,8 +261,10 @@ public: bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false); - std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> - getPreprocessedEntities(); + bool visitPreprocessedEntitiesInRegion(); + + template<typename InputIterator> + bool visitPreprocessedEntities(InputIterator First, InputIterator Last); bool VisitChildren(CXCursor Parent); @@ -327,35 +323,15 @@ public: bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL); // Type visitors - bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL); - bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL); - bool VisitTypedefTypeLoc(TypedefTypeLoc TL); - bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL); +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); +#include "clang/AST/TypeLocNodes.def" + bool VisitTagTypeLoc(TagTypeLoc TL); - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL); - bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); - bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL); - bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL); - bool VisitParenTypeLoc(ParenTypeLoc TL); - bool VisitPointerTypeLoc(PointerTypeLoc TL); - bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL); - bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL); - bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL); - bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL); - bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false); bool VisitArrayTypeLoc(ArrayTypeLoc TL); - bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL); - // FIXME: Implement visitors here when the unimplemented TypeLocs get - // implemented - bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL); - bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL); - bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL); - bool VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL); - bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL); - bool VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL); - bool VisitElaboratedTypeLoc(ElaboratedTypeLoc TL); - + bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false); + // Data-recursive visitor functions. bool IsInRegionOfInterest(CXCursor C); bool RunVisitorWorkList(VisitorWorkList &WL); @@ -390,10 +366,9 @@ bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) { if (clang_isDeclaration(Cursor.kind)) { Decl *D = getCursorDecl(Cursor); assert(D && "Invalid declaration cursor"); - if (D->getPCHLevel() > MaxPCHLevel) - return false; - - if (D->isImplicit()) + // Ignore implicit declarations, unless it's an objc method because + // currently we should report implicit methods for properties when indexing. + if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) return false; } @@ -419,65 +394,53 @@ bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) { return false; } -std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> -CursorVisitor::getPreprocessedEntities() { +bool CursorVisitor::visitPreprocessedEntitiesInRegion() { PreprocessingRecord &PPRec = *AU->getPreprocessor().getPreprocessingRecord(); + if (RegionOfInterest.isValid()) { + SourceRange MappedRange = AU->mapRangeToPreamble(RegionOfInterest); + std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> + Entities = PPRec.getPreprocessedEntitiesInRange(MappedRange); + return visitPreprocessedEntities(Entities.first, Entities.second); + } + bool OnlyLocalDecls = !AU->isMainFileAST() && AU->getOnlyLocalDecls(); - if (OnlyLocalDecls && RegionOfInterest.isValid()) { - // If we would only look at local declarations but we have a region of - // interest, check whether that region of interest is in the main file. - // If not, we should traverse all declarations. - // FIXME: My kingdom for a proper binary search approach to finding - // cursors! - std::pair<FileID, unsigned> Location - = AU->getSourceManager().getDecomposedInstantiationLoc( - RegionOfInterest.getBegin()); - if (Location.first != AU->getSourceManager().getMainFileID()) - OnlyLocalDecls = false; - } - - PreprocessingRecord::iterator StartEntity, EndEntity; - if (OnlyLocalDecls) { - StartEntity = AU->pp_entity_begin(); - EndEntity = AU->pp_entity_end(); - } else { - StartEntity = PPRec.begin(); - EndEntity = PPRec.end(); - } - - // There is no region of interest; we have to walk everything. - if (RegionOfInterest.isInvalid()) - return std::make_pair(StartEntity, EndEntity); - - // Find the file in which the region of interest lands. - SourceManager &SM = AU->getSourceManager(); - std::pair<FileID, unsigned> Begin - = SM.getDecomposedInstantiationLoc(RegionOfInterest.getBegin()); - std::pair<FileID, unsigned> End - = SM.getDecomposedInstantiationLoc(RegionOfInterest.getEnd()); - - // The region of interest spans files; we have to walk everything. - if (Begin.first != End.first) - return std::make_pair(StartEntity, EndEntity); + if (OnlyLocalDecls) + return visitPreprocessedEntities(PPRec.local_begin(), PPRec.local_end()); + + return visitPreprocessedEntities(PPRec.begin(), PPRec.end()); +} + +template<typename InputIterator> +bool CursorVisitor::visitPreprocessedEntities(InputIterator First, + InputIterator Last) { + for (; First != Last; ++First) { + if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*First)) { + if (Visit(MakeMacroExpansionCursor(ME, TU))) + return true; + + continue; + } + + if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*First)) { + if (Visit(MakeMacroDefinitionCursor(MD, TU))) + return true; + + continue; + } - ASTUnit::PreprocessedEntitiesByFileMap &ByFileMap - = AU->getPreprocessedEntitiesByFile(); - if (ByFileMap.empty()) { - // Build the mapping from files to sets of preprocessed entities. - for (PreprocessingRecord::iterator E = StartEntity; E != EndEntity; ++E) { - std::pair<FileID, unsigned> P - = SM.getDecomposedInstantiationLoc((*E)->getSourceRange().getBegin()); + if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*First)) { + if (Visit(MakeInclusionDirectiveCursor(ID, TU))) + return true; - ByFileMap[P.first].push_back(*E); + continue; } } - return std::make_pair(ByFileMap[Begin.first].begin(), - ByFileMap[Begin.first].end()); + return false; } /// \brief Visit the children of the given cursor. @@ -529,7 +492,7 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(), TLEnd = CXXUnit->top_level_end(); TL != TLEnd; ++TL) { - if (Visit(MakeCXCursor(*TL, tu), true)) + if (Visit(MakeCXCursor(*TL, tu, RegionOfInterest), true)) return true; } } else if (VisitDeclContext( @@ -539,33 +502,8 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { } // 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 (MacroExpansion *ME = dyn_cast<MacroExpansion>(*E)) { - if (Visit(MakeMacroExpansionCursor(ME, tu))) - return true; - - continue; - } - - if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { - if (Visit(MakeMacroDefinitionCursor(MD, tu))) - return true; - - continue; - } - - if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) { - if (Visit(MakeInclusionDirectiveCursor(ID, tu))) - return true; - - continue; - } - } - } + if (CXXUnit->getPreprocessor().getPreprocessingRecord()) + visitPreprocessedEntitiesInRegion(); } return false; @@ -578,7 +516,15 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { } } } - + + if (Cursor.kind == CXCursor_IBOutletCollectionAttr) { + IBOutletCollectionAttr *A = + cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor)); + if (const ObjCInterfaceType *InterT = A->getInterface()->getAs<ObjCInterfaceType>()) + return Visit(cxcursor::MakeCursorObjCClassRef(InterT->getInterface(), + A->getInterfaceLoc(), TU)); + } + // Nothing to visit at the moment. return false; } @@ -589,7 +535,7 @@ bool CursorVisitor::VisitBlockDecl(BlockDecl *B) { return true; if (Stmt *Body = B->getBody()) - return Visit(MakeCXCursor(Body, StmtParent, TU)); + return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest)); return false; } @@ -629,7 +575,7 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) { Decl *D = *I; if (D->getLexicalDeclContext() != DC) continue; - CXCursor Cursor = MakeCXCursor(D, TU); + CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest); const llvm::Optional<bool> &V = shouldVisitCursor(Cursor); if (!V.hasValue()) continue; @@ -727,7 +673,7 @@ bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) { if (Expr *Init = D->getInitExpr()) - return Visit(MakeCXCursor(Init, StmtParent, TU)); + return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest)); return false; } @@ -794,7 +740,7 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) { // Find the initializers that were written in the source. - llvm::SmallVector<CXXCtorInitializer *, 4> WrittenInits; + SmallVector<CXXCtorInitializer *, 4> WrittenInits; for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(), IEnd = Constructor->init_end(); I != IEnd; ++I) { @@ -822,12 +768,12 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { // Visit the initializer value. if (Expr *Initializer = Init->getInit()) - if (Visit(MakeCXCursor(Initializer, ND, TU))) + if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest))) return true; } } - if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU))) + if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest))) return true; } @@ -839,7 +785,7 @@ bool CursorVisitor::VisitFieldDecl(FieldDecl *D) { return true; if (Expr *BitWidth = D->getBitWidth()) - return Visit(MakeCXCursor(BitWidth, StmtParent, TU)); + return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest)); return false; } @@ -849,7 +795,7 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) { return true; if (Expr *Init = D->getInit()) - return Visit(MakeCXCursor(Init, StmtParent, TU)); + return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest)); return false; } @@ -860,7 +806,7 @@ bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) if (Expr *DefArg = D->getDefaultArgument()) - return Visit(MakeCXCursor(DefArg, StmtParent, TU)); + return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest)); return false; } @@ -902,12 +848,12 @@ bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { for (ObjCMethodDecl::param_iterator P = ND->param_begin(), PEnd = ND->param_end(); P != PEnd; ++P) { - if (Visit(MakeCXCursor(*P, TU))) + if (Visit(MakeCXCursor(*P, TU, RegionOfInterest))) return true; } if (ND->isThisDeclarationADefinition() && - Visit(MakeCXCursor(ND->getBody(), StmtParent, TU))) + Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest))) return true; return false; @@ -938,7 +884,7 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) { // in the current DeclContext. If any fall within the // container's lexical region, stash them into a vector // for later processing. - llvm::SmallVector<Decl *, 24> DeclsInContainer; + SmallVector<Decl *, 24> DeclsInContainer; SourceLocation EndLoc = D->getSourceRange().getEnd(); SourceManager &SM = AU->getSourceManager(); if (EndLoc.isValid()) { @@ -979,9 +925,9 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) { ContainerDeclsSort(SM)); // Now visit the decls. - for (llvm::SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(), + for (SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(), E = DeclsInContainer.end(); I != E; ++I) { - CXCursor Cursor = MakeCXCursor(*I, TU); + CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest); const llvm::Optional<bool> &V = shouldVisitCursor(Cursor); if (!V.hasValue()) continue; @@ -1043,12 +989,12 @@ bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) { // the @interface. if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl()) if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl) - if (Visit(MakeCXCursor(MD, TU))) + if (Visit(MakeCXCursor(MD, TU, RegionOfInterest))) return true; if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl()) if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl) - if (Visit(MakeCXCursor(MD, TU))) + if (Visit(MakeCXCursor(MD, TU, RegionOfInterest))) return true; return false; @@ -1110,10 +1056,9 @@ bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { } bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) { - for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C) - if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU))) + if (Visit(MakeCursorObjCClassRef(D->getForwardInterfaceDecl(), + D->getForwardDecl()->getLocation(), TU))) return true; - return false; } @@ -1254,7 +1199,7 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, bool CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { - llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; + SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; for (; Qualifier; Qualifier = Qualifier.getPrefix()) Qualifiers.push_back(Qualifier); @@ -1302,7 +1247,7 @@ bool CursorVisitor::VisitTemplateParameters( for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { - if (Visit(MakeCXCursor(*P, TU))) + if (Visit(MakeCXCursor(*P, TU, RegionOfInterest))) return true; } @@ -1359,12 +1304,12 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { case TemplateArgument::Declaration: if (Expr *E = TAL.getSourceDeclExpression()) - return Visit(MakeCXCursor(E, StmtParent, TU)); + return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); return false; case TemplateArgument::Expression: if (Expr *E = TAL.getSourceExpression()) - return Visit(MakeCXCursor(E, StmtParent, TU)); + return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); return false; case TemplateArgument::Template: @@ -1414,6 +1359,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { case BuiltinType::Long: case BuiltinType::LongLong: case BuiltinType::Int128: + case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: @@ -1455,6 +1401,9 @@ bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { } bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) { + if (TL.isDefinition()) + return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest)); + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } @@ -1510,6 +1459,10 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { return Visit(TL.getPointeeLoc()); } +bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) { + return Visit(TL.getModifiedLoc()); +} + bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType) { if (!SkipResultType && Visit(TL.getResultLoc())) @@ -1517,7 +1470,7 @@ bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL, for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I) if (Decl *D = TL.getArg(I)) - if (Visit(MakeCXCursor(D, TU))) + if (Visit(MakeCXCursor(D, TU, RegionOfInterest))) return true; return false; @@ -1528,7 +1481,7 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) { return true; if (Expr *Size = TL.getSizeExpr()) - return Visit(MakeCXCursor(Size, StmtParent, TU)); + return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest)); return false; } @@ -1599,13 +1552,49 @@ bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { return Visit(TL.getPatternLoc()); } +bool CursorVisitor::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { + if (Expr *E = TL.getUnderlyingExpr()) + return Visit(MakeCXCursor(E, StmtParent, TU)); + + return false; +} + +bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); +} + +bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) { + return Visit(TL.getValueLoc()); +} + +#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \ +bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + return Visit##PARENT##Loc(TL); \ +} + +DEFAULT_TYPELOC_IMPL(Complex, Type) +DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType) +DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) +DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) +DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) +DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) +DEFAULT_TYPELOC_IMPL(Vector, Type) +DEFAULT_TYPELOC_IMPL(ExtVector, VectorType) +DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType) +DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType) +DEFAULT_TYPELOC_IMPL(Record, TagType) +DEFAULT_TYPELOC_IMPL(Enum, TagType) +DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type) +DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type) +DEFAULT_TYPELOC_IMPL(Auto, Type) + bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) { // Visit the nested-name-specifier, if present. if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; - if (D->isDefinition()) { + if (D->isCompleteDefinition()) { for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU))) @@ -1642,7 +1631,7 @@ DEF_JOB(StmtVisit, Stmt, StmtVisitKind) DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind) DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind) DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind) -DEF_JOB(ExplicitTemplateArgsVisit, ExplicitTemplateArgumentList, +DEF_JOB(ExplicitTemplateArgsVisit, ASTTemplateArgumentListInfo, ExplicitTemplateArgsVisitKind) DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind) #undef DEF_JOB @@ -1687,27 +1676,6 @@ public: SourceLocation getLoc() const { return SourceLocation::getFromPtrEncoding(data[1]); } }; -class NestedNameSpecifierVisit : public VisitorJob { -public: - NestedNameSpecifierVisit(NestedNameSpecifier *NS, SourceRange R, - CXCursor parent) - : VisitorJob(parent, VisitorJob::NestedNameSpecifierVisitKind, - NS, R.getBegin().getPtrEncoding(), - R.getEnd().getPtrEncoding()) {} - static bool classof(const VisitorJob *VJ) { - return VJ->getKind() == VisitorJob::NestedNameSpecifierVisitKind; - } - NestedNameSpecifier *get() const { - return static_cast<NestedNameSpecifier*>(data[0]); - } - SourceRange getSourceRange() const { - SourceLocation A = - SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]); - SourceLocation B = - SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[2]); - return SourceRange(A, B); - } -}; class NestedNameSpecifierLocVisit : public VisitorJob { public: @@ -1809,9 +1777,8 @@ public: private: void AddDeclarationNameInfo(Stmt *S); - void AddNestedNameSpecifier(NestedNameSpecifier *NS, SourceRange R); void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier); - void AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A); + void AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A); void AddMemberRef(FieldDecl *D, SourceLocation L); void AddStmt(Stmt *S); void AddDecl(Decl *D, bool isFirst = true); @@ -1825,11 +1792,6 @@ void EnqueueVisitor::AddDeclarationNameInfo(Stmt *S) { // statement we are visiting. WL.push_back(DeclarationNameInfoVisit(S, Parent)); } -void EnqueueVisitor::AddNestedNameSpecifier(NestedNameSpecifier *N, - SourceRange R) { - if (N) - WL.push_back(NestedNameSpecifierVisit(N, R, Parent)); -} void EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { @@ -1846,10 +1808,10 @@ void EnqueueVisitor::AddDecl(Decl *D, bool isFirst) { WL.push_back(DeclVisit(D, Parent, isFirst)); } void EnqueueVisitor:: - AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A) { + AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A) { if (A) WL.push_back(ExplicitTemplateArgsVisit( - const_cast<ExplicitTemplateArgumentList*>(A), Parent)); + const_cast<ASTTemplateArgumentListInfo*>(A), Parent)); } void EnqueueVisitor::AddMemberRef(FieldDecl *D, SourceLocation L) { if (D) @@ -2114,7 +2076,7 @@ void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) { } void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) { - EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU)).Visit(S); + EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } bool CursorVisitor::IsInRegionOfInterest(CXCursor C) { @@ -2142,13 +2104,14 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { continue; // For now, perform default visitation for Decls. - if (Visit(MakeCXCursor(D, TU, cast<DeclVisit>(&LI)->isFirst()))) + if (Visit(MakeCXCursor(D, TU, RegionOfInterest, + cast<DeclVisit>(&LI)->isFirst()))) return true; continue; } case VisitorJob::ExplicitTemplateArgsVisitKind: { - const ExplicitTemplateArgumentList *ArgList = + const ASTTemplateArgumentListInfo *ArgList = cast<ExplicitTemplateArgsVisit>(&LI)->get(); for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(), *ArgEnd = Arg + ArgList->NumTemplateArgs; @@ -2174,14 +2137,7 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { } continue; } - - case VisitorJob::NestedNameSpecifierVisitKind: { - NestedNameSpecifierVisit *V = cast<NestedNameSpecifierVisit>(&LI); - if (VisitNestedNameSpecifier(V->get(), V->getSourceRange())) - return true; - continue; - } - + case VisitorJob::NestedNameSpecifierLocVisitKind: { NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI); if (VisitNestedNameSpecifierLoc(V->get())) @@ -2207,7 +2163,7 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { continue; // Update the current cursor. - CXCursor Cursor = MakeCXCursor(S, StmtParent, TU); + CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest); if (!IsInRegionOfInterest(Cursor)) continue; switch (Visitor(Cursor, Parent, ClientData)) { @@ -2313,6 +2269,47 @@ bool CursorVisitor::Visit(Stmt *S) { return result; } +namespace { +typedef llvm::SmallVector<SourceRange, 4> RefNamePieces; +RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr, + const DeclarationNameInfo &NI, + const SourceRange &QLoc, + const ASTTemplateArgumentListInfo *TemplateArgs = 0){ + const bool WantQualifier = NameFlags & CXNameRange_WantQualifier; + const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs; + const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece; + + const DeclarationName::NameKind Kind = NI.getName().getNameKind(); + + RefNamePieces Pieces; + + if (WantQualifier && QLoc.isValid()) + Pieces.push_back(QLoc); + + if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr) + Pieces.push_back(NI.getLoc()); + + if (WantTemplateArgs && TemplateArgs) + Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc, + TemplateArgs->RAngleLoc)); + + if (Kind == DeclarationName::CXXOperatorName) { + Pieces.push_back(SourceLocation::getFromRawEncoding( + NI.getInfo().CXXOperatorName.BeginOpNameLoc)); + Pieces.push_back(SourceLocation::getFromRawEncoding( + NI.getInfo().CXXOperatorName.EndOpNameLoc)); + } + + if (WantSinglePiece) { + SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd()); + Pieces.clear(); + Pieces.push_back(R); + } + + return Pieces; +} +} + //===----------------------------------------------------------------------===// // Misc. API hooks. //===----------------------------------------------------------------------===// @@ -2369,7 +2366,7 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, FileSystemOptions FileSystemOpts; FileSystemOpts.WorkingDir = CXXIdx->getWorkingDirectory(); - llvm::IntrusiveRefCntPtr<Diagnostic> Diags; + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags; ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts, CXXIdx->getOnlyLocalDecls(), 0, 0, true); @@ -2378,9 +2375,7 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, unsigned clang_defaultEditingTranslationUnitOptions() { return CXTranslationUnit_PrecompiledPreamble | - CXTranslationUnit_CacheCompletionResults | - CXTranslationUnit_CXXPrecompiledPreamble | - CXTranslationUnit_CXXChainedPCH; + CXTranslationUnit_CacheCompletionResults; } CXTranslationUnit @@ -2426,24 +2421,21 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble; - bool CompleteTranslationUnit - = ((options & CXTranslationUnit_Incomplete) == 0); + // FIXME: Add a flag for modules. + TranslationUnitKind TUKind + = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete; bool CacheCodeCompetionResults = options & CXTranslationUnit_CacheCompletionResults; - bool CXXPrecompilePreamble - = options & CXTranslationUnit_CXXPrecompiledPreamble; - bool CXXChainedPCH - = options & CXTranslationUnit_CXXChainedPCH; // Configure the diagnostics. DiagnosticOptions DiagOpts; - llvm::IntrusiveRefCntPtr<Diagnostic> + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> 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> > + llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.getPtr()); llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> > @@ -2454,7 +2446,7 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { 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); + 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, @@ -2517,10 +2509,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { RemappedFiles->size(), /*RemappedFilesKeepOriginalName=*/true, PrecompilePreamble, - CompleteTranslationUnit, + TUKind, CacheCodeCompetionResults, - CXXPrecompilePreamble, - CXXChainedPCH, NestedMacroExpansions)); if (NumErrors != Diags->getClient()->getNumErrors()) { @@ -2651,7 +2641,7 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) { 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); + 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, @@ -2691,7 +2681,7 @@ CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) { } CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) { - CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } }; + CXCursor Result = { CXCursor_TranslationUnit, 0, { 0, 0, TU } }; return Result; } @@ -2722,9 +2712,9 @@ CXSourceLocation clang_getLocation(CXTranslationUnit tu, bool Logging = ::getenv("LIBCLANG_LOGGING"); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData); + ASTUnit::ConcurrencyCheck Check(*CXXUnit); const FileEntry *File = static_cast<const FileEntry *>(file); - SourceLocation SLoc - = CXXUnit->getSourceManager().getLocation(File, line, column); + SourceLocation SLoc = CXXUnit->getLocation(File, line, column); if (SLoc.isInvalid()) { if (Logging) llvm::errs() << "clang_getLocation(\"" << File->getName() @@ -2747,14 +2737,8 @@ CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu, return clang_getNullLocation(); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData); - SourceLocation Start - = CXXUnit->getSourceManager().getLocation( - static_cast<const FileEntry *>(file), - 1, 1); - if (Start.isInvalid()) return clang_getNullLocation(); - - SourceLocation SLoc = Start.getFileLocWithOffset(offset); - + SourceLocation SLoc + = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset); if (SLoc.isInvalid()) return clang_getNullLocation(); return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); @@ -2774,6 +2758,19 @@ CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) { begin.int_data, end.int_data }; return Result; } + +unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) +{ + return range1.ptr_data[0] == range2.ptr_data[0] + && range1.ptr_data[1] == range2.ptr_data[1] + && range1.begin_int_data == range2.begin_int_data + && range1.end_int_data == range2.end_int_data; +} + +int clang_Range_isNull(CXSourceRange range) { + return clang_equalRanges(range, clang_getNullRange()); +} + } // end: extern "C" static void createNullLocation(CXFile *file, unsigned *line, @@ -2790,11 +2787,11 @@ static void createNullLocation(CXFile *file, unsigned *line, } extern "C" { -void clang_getInstantiationLocation(CXSourceLocation location, - CXFile *file, - unsigned *line, - unsigned *column, - unsigned *offset) { +void clang_getExpansionLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset) { SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); if (!location.ptr_data[0] || Loc.isInvalid()) { @@ -2804,11 +2801,11 @@ void clang_getInstantiationLocation(CXSourceLocation location, const SourceManager &SM = *static_cast<const SourceManager*>(location.ptr_data[0]); - SourceLocation InstLoc = SM.getInstantiationLoc(Loc); + SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc); // Check that the FileID is invalid on the expansion location. // This can manifest in invalid code. - FileID fileID = SM.getFileID(InstLoc); + FileID fileID = SM.getFileID(ExpansionLoc); bool Invalid = false; const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid); if (!sloc.isFile() || Invalid) { @@ -2819,11 +2816,48 @@ void clang_getInstantiationLocation(CXSourceLocation location, if (file) *file = (void *)SM.getFileEntryForSLocEntry(sloc); if (line) - *line = SM.getInstantiationLineNumber(InstLoc); + *line = SM.getExpansionLineNumber(ExpansionLoc); if (column) - *column = SM.getInstantiationColumnNumber(InstLoc); + *column = SM.getExpansionColumnNumber(ExpansionLoc); if (offset) - *offset = SM.getDecomposedLoc(InstLoc).second; + *offset = SM.getDecomposedLoc(ExpansionLoc).second; +} + +void clang_getPresumedLocation(CXSourceLocation location, + CXString *filename, + unsigned *line, + unsigned *column) { + SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); + + if (!location.ptr_data[0] || Loc.isInvalid()) { + if (filename) + *filename = createCXString(""); + if (line) + *line = 0; + if (column) + *column = 0; + } + else { + const SourceManager &SM = + *static_cast<const SourceManager*>(location.ptr_data[0]); + PresumedLoc PreLoc = SM.getPresumedLoc(Loc); + + if (filename) + *filename = createCXString(PreLoc.getFilename()); + if (line) + *line = PreLoc.getLine(); + if (column) + *column = PreLoc.getColumn(); + } +} + +void clang_getInstantiationLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset) { + // Redirect to new API. + clang_getExpansionLocation(location, file, line, column, offset); } void clang_getSpellingLocation(CXSourceLocation location, @@ -2845,7 +2879,7 @@ void clang_getSpellingLocation(CXSourceLocation location, SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first)) SpellLoc = SimpleSpellingLoc; else - SpellLoc = SM.getInstantiationLoc(SpellLoc); + SpellLoc = SM.getExpansionLoc(SpellLoc); } std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc); @@ -2927,7 +2961,7 @@ unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file) { //===----------------------------------------------------------------------===// static Decl *getDeclFromExpr(Stmt *E) { - if (CastExpr *CE = dyn_cast<CastExpr>(E)) + if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) return getDeclFromExpr(CE->getSubExpr()); if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E)) @@ -2943,7 +2977,7 @@ static Decl *getDeclFromExpr(Stmt *E) { if (CallExpr *CE = dyn_cast<CallExpr>(E)) return getDeclFromExpr(CE->getCallee()); - if (CXXConstructExpr *CE = llvm::dyn_cast<CXXConstructExpr>(E)) + if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) if (!CE->isElidable()) return CE->getConstructor(); if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E)) @@ -2963,6 +2997,9 @@ static Decl *getDeclFromExpr(Stmt *E) { } static SourceLocation getLocationFromExpr(Expr *E) { + if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) + return getLocationFromExpr(CE->getSubExpr()); + if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) return /*FIXME:*/Msg->getLeftLoc(); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) @@ -2985,7 +3022,6 @@ unsigned clang_visitChildren(CXCursor parent, CXCursorVisitor visitor, CXClientData client_data) { CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data, - getCursorASTUnit(parent)->getMaxPCHLevel(), false); return CursorVis.VisitChildren(parent); } @@ -3030,7 +3066,7 @@ unsigned clang_visitChildrenWithBlock(CXCursor parent, static CXString getDeclSpelling(Decl *D) { NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D); if (!ND) { - if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D)) + if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D)) if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl()) return createCXString(Property->getIdentifier()->getName()); @@ -3165,6 +3201,11 @@ CXString clang_getCursorSpelling(CXCursor C) { if (clang_isDeclaration(C.kind)) return getDeclSpelling(getCursorDecl(C)); + if (C.kind == CXCursor_AnnotateAttr) { + AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C)); + return createCXString(AA->getAnnotation()); + } + return createCXString(""); } @@ -3176,7 +3217,7 @@ CXString clang_getCursorDisplayName(CXCursor C) { if (!D) return createCXString(""); - PrintingPolicy &Policy = getCursorContext(C).PrintingPolicy; + PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy(); if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) D = FunTmpl->getTemplatedDecl(); @@ -3314,10 +3355,86 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("LabelRef"); case CXCursor_OverloadedDeclRef: return createCXString("OverloadedDeclRef"); - case CXCursor_UnexposedExpr: - return createCXString("UnexposedExpr"); + case CXCursor_IntegerLiteral: + return createCXString("IntegerLiteral"); + case CXCursor_FloatingLiteral: + return createCXString("FloatingLiteral"); + case CXCursor_ImaginaryLiteral: + return createCXString("ImaginaryLiteral"); + case CXCursor_StringLiteral: + return createCXString("StringLiteral"); + case CXCursor_CharacterLiteral: + return createCXString("CharacterLiteral"); + case CXCursor_ParenExpr: + return createCXString("ParenExpr"); + case CXCursor_UnaryOperator: + return createCXString("UnaryOperator"); + case CXCursor_ArraySubscriptExpr: + return createCXString("ArraySubscriptExpr"); + case CXCursor_BinaryOperator: + return createCXString("BinaryOperator"); + case CXCursor_CompoundAssignOperator: + return createCXString("CompoundAssignOperator"); + case CXCursor_ConditionalOperator: + return createCXString("ConditionalOperator"); + case CXCursor_CStyleCastExpr: + return createCXString("CStyleCastExpr"); + case CXCursor_CompoundLiteralExpr: + return createCXString("CompoundLiteralExpr"); + case CXCursor_InitListExpr: + return createCXString("InitListExpr"); + case CXCursor_AddrLabelExpr: + return createCXString("AddrLabelExpr"); + case CXCursor_StmtExpr: + return createCXString("StmtExpr"); + case CXCursor_GenericSelectionExpr: + return createCXString("GenericSelectionExpr"); + case CXCursor_GNUNullExpr: + return createCXString("GNUNullExpr"); + case CXCursor_CXXStaticCastExpr: + return createCXString("CXXStaticCastExpr"); + case CXCursor_CXXDynamicCastExpr: + return createCXString("CXXDynamicCastExpr"); + case CXCursor_CXXReinterpretCastExpr: + return createCXString("CXXReinterpretCastExpr"); + case CXCursor_CXXConstCastExpr: + return createCXString("CXXConstCastExpr"); + case CXCursor_CXXFunctionalCastExpr: + return createCXString("CXXFunctionalCastExpr"); + case CXCursor_CXXTypeidExpr: + return createCXString("CXXTypeidExpr"); + case CXCursor_CXXBoolLiteralExpr: + return createCXString("CXXBoolLiteralExpr"); + case CXCursor_CXXNullPtrLiteralExpr: + return createCXString("CXXNullPtrLiteralExpr"); + case CXCursor_CXXThisExpr: + return createCXString("CXXThisExpr"); + case CXCursor_CXXThrowExpr: + return createCXString("CXXThrowExpr"); + case CXCursor_CXXNewExpr: + return createCXString("CXXNewExpr"); + case CXCursor_CXXDeleteExpr: + return createCXString("CXXDeleteExpr"); + case CXCursor_UnaryExpr: + return createCXString("UnaryExpr"); + case CXCursor_ObjCStringLiteral: + return createCXString("ObjCStringLiteral"); + case CXCursor_ObjCEncodeExpr: + return createCXString("ObjCEncodeExpr"); + case CXCursor_ObjCSelectorExpr: + return createCXString("ObjCSelectorExpr"); + case CXCursor_ObjCProtocolExpr: + return createCXString("ObjCProtocolExpr"); + case CXCursor_ObjCBridgedCastExpr: + return createCXString("ObjCBridgedCastExpr"); case CXCursor_BlockExpr: return createCXString("BlockExpr"); + case CXCursor_PackExpansionExpr: + return createCXString("PackExpansionExpr"); + case CXCursor_SizeOfPackExpr: + return createCXString("SizeOfPackExpr"); + case CXCursor_UnexposedExpr: + return createCXString("UnexposedExpr"); case CXCursor_DeclRefExpr: return createCXString("DeclRefExpr"); case CXCursor_MemberRefExpr: @@ -3328,8 +3445,66 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("ObjCMessageExpr"); case CXCursor_UnexposedStmt: return createCXString("UnexposedStmt"); + case CXCursor_DeclStmt: + return createCXString("DeclStmt"); case CXCursor_LabelStmt: return createCXString("LabelStmt"); + case CXCursor_CompoundStmt: + return createCXString("CompoundStmt"); + case CXCursor_CaseStmt: + return createCXString("CaseStmt"); + case CXCursor_DefaultStmt: + return createCXString("DefaultStmt"); + case CXCursor_IfStmt: + return createCXString("IfStmt"); + case CXCursor_SwitchStmt: + return createCXString("SwitchStmt"); + case CXCursor_WhileStmt: + return createCXString("WhileStmt"); + case CXCursor_DoStmt: + return createCXString("DoStmt"); + case CXCursor_ForStmt: + return createCXString("ForStmt"); + case CXCursor_GotoStmt: + return createCXString("GotoStmt"); + case CXCursor_IndirectGotoStmt: + return createCXString("IndirectGotoStmt"); + case CXCursor_ContinueStmt: + return createCXString("ContinueStmt"); + case CXCursor_BreakStmt: + return createCXString("BreakStmt"); + case CXCursor_ReturnStmt: + return createCXString("ReturnStmt"); + case CXCursor_AsmStmt: + return createCXString("AsmStmt"); + case CXCursor_ObjCAtTryStmt: + return createCXString("ObjCAtTryStmt"); + case CXCursor_ObjCAtCatchStmt: + return createCXString("ObjCAtCatchStmt"); + case CXCursor_ObjCAtFinallyStmt: + return createCXString("ObjCAtFinallyStmt"); + case CXCursor_ObjCAtThrowStmt: + return createCXString("ObjCAtThrowStmt"); + case CXCursor_ObjCAtSynchronizedStmt: + return createCXString("ObjCAtSynchronizedStmt"); + case CXCursor_ObjCAutoreleasePoolStmt: + return createCXString("ObjCAutoreleasePoolStmt"); + case CXCursor_ObjCForCollectionStmt: + return createCXString("ObjCForCollectionStmt"); + case CXCursor_CXXCatchStmt: + return createCXString("CXXCatchStmt"); + case CXCursor_CXXTryStmt: + return createCXString("CXXTryStmt"); + case CXCursor_CXXForRangeStmt: + return createCXString("CXXForRangeStmt"); + case CXCursor_SEHTryStmt: + return createCXString("SEHTryStmt"); + case CXCursor_SEHExceptStmt: + return createCXString("SEHExceptStmt"); + case CXCursor_SEHFinallyStmt: + return createCXString("SEHFinallyStmt"); + case CXCursor_NullStmt: + return createCXString("NullStmt"); case CXCursor_InvalidFile: return createCXString("InvalidFile"); case CXCursor_InvalidCode: @@ -3348,6 +3523,12 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("attribute(iboutlet)"); case CXCursor_IBOutletCollectionAttr: return createCXString("attribute(iboutletcollection)"); + case CXCursor_CXXFinalAttr: + return createCXString("attribute(final)"); + case CXCursor_CXXOverrideAttr: + return createCXString("attribute(override)"); + case CXCursor_AnnotateAttr: + return createCXString("attribute(annotate)"); case CXCursor_PreprocessingDirective: return createCXString("preprocessing directive"); case CXCursor_MacroDefinition: @@ -3392,6 +3573,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("ObjCSynthesizeDecl"); case CXCursor_ObjCDynamicDecl: return createCXString("ObjCDynamicDecl"); + case CXCursor_CXXAccessSpecifier: + return createCXString("CXXAccessSpecifier"); } llvm_unreachable("Unhandled CXCursorKind"); @@ -3400,18 +3583,35 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { struct GetCursorData { SourceLocation TokenBeginLoc; + bool PointsAtMacroArgExpansion; CXCursor &BestCursor; - GetCursorData(SourceLocation tokenBegin, CXCursor &outputCursor) - : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) { } + GetCursorData(SourceManager &SM, + SourceLocation tokenBegin, CXCursor &outputCursor) + : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) { + PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin); + } }; -enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, - CXCursor parent, - CXClientData client_data) { +static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, + CXCursor parent, + CXClientData client_data) { GetCursorData *Data = static_cast<GetCursorData *>(client_data); CXCursor *BestCursor = &Data->BestCursor; + // If we point inside a macro argument we should provide info of what the + // token is so use the actual cursor, don't replace it with a macro expansion + // cursor. + if (cursor.kind == CXCursor_MacroExpansion && Data->PointsAtMacroArgExpansion) + return CXChildVisit_Recurse; + + if (clang_isDeclaration(cursor.kind)) { + // Avoid having the implicit methods override the property decls. + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCursorDecl(cursor))) + if (MD->isImplicit()) + return CXChildVisit_Break; + } + if (clang_isExpression(cursor.kind) && clang_isDeclaration(BestCursor->kind)) { Decl *D = getCursorDecl(*BestCursor); @@ -3431,14 +3631,12 @@ enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, // clang_getCursor() to point at the constructor. if (clang_isExpression(BestCursor->kind) && isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) && - cursor.kind == CXCursor_TypeRef) - return CXChildVisit_Recurse; - - // Don't override a preprocessing cursor with another preprocessing - // cursor; we want the outermost preprocessing cursor. - if (clang_isPreprocessing(cursor.kind) && - clang_isPreprocessing(BestCursor->kind)) + cursor.kind == CXCursor_TypeRef) { + // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it + // as having the actual point on the type reference. + *BestCursor = getTypeRefedCallExprCursor(*BestCursor); return CXChildVisit_Recurse; + } *BestCursor = cursor; return CXChildVisit_Recurse; @@ -3451,31 +3649,10 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); ASTUnit::ConcurrencyCheck Check(*CXXUnit); - // Translate the given source location to make it point at the beginning of - // the token under the cursor. SourceLocation SLoc = cxloc::translateSourceLocation(Loc); - - // Guard against an invalid SourceLocation, or we may assert in one - // of the following calls. - if (SLoc.isInvalid()) - return clang_getNullCursor(); + CXCursor Result = cxcursor::getCursor(TU, SLoc); bool Logging = getenv("LIBCLANG_LOGGING"); - SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(), - CXXUnit->getASTContext().getLangOptions()); - - CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound); - if (SLoc.isValid()) { - // FIXME: Would be great to have a "hint" cursor, then walk from that - // hint cursor upward until we find a cursor whose source range encloses - // the region of interest, rather than starting from the translation unit. - GetCursorData ResultData(SLoc, Result); - CXCursor Parent = clang_getTranslationUnitCursor(TU); - CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData, - Decl::MaxPCHLevel, true, SourceLocation(SLoc)); - CursorVis.VisitChildren(Parent); - } - if (Logging) { CXFile SearchFile; unsigned SearchLine, SearchColumn; @@ -3485,10 +3662,9 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : ""; CXSourceLocation ResultLoc = clang_getCursorLocation(Result); - clang_getInstantiationLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, - 0); - clang_getInstantiationLocation(ResultLoc, &ResultFile, &ResultLine, - &ResultColumn, 0); + clang_getExpansionLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, 0); + clang_getExpansionLocation(ResultLoc, &ResultFile, &ResultLine, + &ResultColumn, 0); SearchFileName = clang_getFileName(SearchFile); ResultFileName = clang_getFileName(ResultFile); KindSpelling = clang_getCursorKindSpelling(Result.kind); @@ -3510,8 +3686,8 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { = clang_getCursorKindSpelling(Definition.kind); CXFile DefinitionFile; unsigned DefinitionLine, DefinitionColumn; - clang_getInstantiationLocation(DefinitionLoc, &DefinitionFile, - &DefinitionLine, &DefinitionColumn, 0); + clang_getExpansionLocation(DefinitionLoc, &DefinitionFile, + &DefinitionLine, &DefinitionColumn, 0); CXString DefinitionFileName = clang_getFileName(DefinitionFile); fprintf(stderr, " -> %s(%s:%d:%d)\n", clang_getCString(DefinitionKindSpelling), @@ -3694,8 +3870,6 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { Decl *D = getCursorDecl(C); SourceLocation Loc = D->getLocation(); - if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) - Loc = Class->getClassLoc(); // 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 @@ -3711,6 +3885,37 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { } // end extern "C" +CXCursor cxcursor::getCursor(CXTranslationUnit TU, SourceLocation SLoc) { + assert(TU); + + // Guard against an invalid SourceLocation, or we may assert in one + // of the following calls. + if (SLoc.isInvalid()) + return clang_getNullCursor(); + + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + + // Translate the given source location to make it point at the beginning of + // the token under the cursor. + SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(), + CXXUnit->getASTContext().getLangOptions()); + + CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound); + if (SLoc.isValid()) { + // FIXME: Would be great to have a "hint" cursor, then walk from that + // hint cursor upward until we find a cursor whose source range encloses + // the region of interest, rather than starting from the translation unit. + GetCursorData ResultData(CXXUnit->getSourceManager(), SLoc, Result); + CXCursor Parent = clang_getTranslationUnitCursor(TU); + CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData, + /*VisitPreprocessorLast=*/true, + SourceLocation(SLoc)); + CursorVis.VisitChildren(Parent); + } + + return Result; +} + static SourceRange getRawCursorExtent(CXCursor C) { if (clang_isReference(C.kind)) { switch (C.kind) { @@ -3756,17 +3961,29 @@ static SourceRange getRawCursorExtent(CXCursor C) { if (clang_isStatement(C.kind)) return getCursorStmt(C)->getSourceRange(); + if (clang_isAttribute(C.kind)) + return getCursorAttr(C)->getRange(); + if (C.kind == CXCursor_PreprocessingDirective) return cxcursor::getCursorPreprocessingDirective(C); - if (C.kind == CXCursor_MacroExpansion) - return cxcursor::getCursorMacroExpansion(C)->getSourceRange(); + if (C.kind == CXCursor_MacroExpansion) { + ASTUnit *TU = getCursorASTUnit(C); + SourceRange Range = cxcursor::getCursorMacroExpansion(C)->getSourceRange(); + return TU->mapRangeFromPreamble(Range); + } - if (C.kind == CXCursor_MacroDefinition) - return cxcursor::getCursorMacroDefinition(C)->getSourceRange(); + if (C.kind == CXCursor_MacroDefinition) { + ASTUnit *TU = getCursorASTUnit(C); + SourceRange Range = cxcursor::getCursorMacroDefinition(C)->getSourceRange(); + return TU->mapRangeFromPreamble(Range); + } - if (C.kind == CXCursor_InclusionDirective) - return cxcursor::getCursorInclusionDirective(C)->getSourceRange(); + if (C.kind == CXCursor_InclusionDirective) { + ASTUnit *TU = getCursorASTUnit(C); + SourceRange Range = cxcursor::getCursorInclusionDirective(C)->getSourceRange(); + return TU->mapRangeFromPreamble(Range); + } if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) { Decl *D = cxcursor::getCursorDecl(C); @@ -3847,7 +4064,7 @@ CXCursor clang_getCursorReferenced(CXCursor C) { if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D)) return MakeCursorOverloadedDeclRef(Protocols, D->getLocation(), tu); - if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D)) + if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D)) if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl()) return MakeCXCursor(Property, tu); @@ -3857,8 +4074,12 @@ CXCursor clang_getCursorReferenced(CXCursor C) { if (clang_isExpression(C.kind)) { Expr *E = getCursorExpr(C); Decl *D = getDeclFromExpr(E); - if (D) - return MakeCXCursor(D, tu); + if (D) { + CXCursor declCursor = MakeCXCursor(D, tu); + declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C), + declCursor); + return declCursor; + } if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E)) return MakeCursorOverloadedDeclRef(Ovl, tu); @@ -3981,6 +4202,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::StaticAssert: case Decl::Block: case Decl::Label: // FIXME: Is this right?? + case Decl::ClassScopeFunctionSpecialization: return C; // Declaration kinds that don't make any sense here, but are @@ -4171,8 +4393,8 @@ unsigned clang_getNumOverloadedDecls(CXCursor C) { Decl *D = Storage.get<Decl*>(); if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) return Using->shadow_size(); - if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) - return Classes->size(); + if (isa<ObjCClassDecl>(D)) + return 1; if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D)) return Protocols->protocol_size(); @@ -4202,10 +4424,8 @@ CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) { std::advance(Pos, index); return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU); } - if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) - return MakeCXCursor(Classes->begin()[index].getInterface(), TU); - + return MakeCXCursor(Classes->getForwardInterfaceDecl(), TU); if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D)) return MakeCXCursor(Protocols->protocol_begin()[index], TU); @@ -4233,6 +4453,54 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C, *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc()); } + +CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags, + unsigned PieceIndex) { + RefNamePieces Pieces; + + switch (C.kind) { + case CXCursor_MemberRefExpr: + if (MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C))) + Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(), + E->getQualifierLoc().getSourceRange()); + break; + + case CXCursor_DeclRefExpr: + if (DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C))) + Pieces = buildPieces(NameFlags, false, E->getNameInfo(), + E->getQualifierLoc().getSourceRange(), + E->getExplicitTemplateArgsOpt()); + break; + + case CXCursor_CallExpr: + if (CXXOperatorCallExpr *OCE = + dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) { + Expr *Callee = OCE->getCallee(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) + Callee = ICE->getSubExpr(); + + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) + Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(), + DRE->getQualifierLoc().getSourceRange()); + } + break; + + default: + break; + } + + if (Pieces.empty()) { + if (PieceIndex == 0) + return clang_getCursorExtent(C); + } else if (PieceIndex < Pieces.size()) { + SourceRange R = Pieces[PieceIndex]; + if (R.isValid()) + return cxloc::translateSourceRange(getCursorContext(C), R); + } + + return clang_getNullRange(); +} + void clang_enableStackTraces(void) { llvm::sys::PrintStackTraceOnErrorSignal(); } @@ -4273,7 +4541,7 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { case CXToken_Literal: { // We have stashed the starting pointer in the ptr_data field. Use it. const char *Text = static_cast<const char *>(CXTok.ptr_data); - return createCXString(llvm::StringRef(Text, CXTok.int_data[2])); + return createCXString(StringRef(Text, CXTok.int_data[2])); } case CXToken_Punctuation: @@ -4289,9 +4557,9 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]); std::pair<FileID, unsigned> LocInfo - = CXXUnit->getSourceManager().getDecomposedLoc(Loc); + = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc); bool Invalid = false; - llvm::StringRef Buffer + StringRef Buffer = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid); if (Invalid) return createCXString(""); @@ -4317,28 +4585,13 @@ CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) { SourceLocation::getFromRawEncoding(CXTok.int_data[1])); } -void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, - CXToken **Tokens, unsigned *NumTokens) { - if (Tokens) - *Tokens = 0; - if (NumTokens) - *NumTokens = 0; - - ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); - if (!CXXUnit || !Tokens || !NumTokens) - return; - - ASTUnit::ConcurrencyCheck Check(*CXXUnit); - - SourceRange R = cxloc::translateCXSourceRange(Range); - if (R.isInvalid()) - return; - +static void getTokens(ASTUnit *CXXUnit, SourceRange Range, + SmallVectorImpl<CXToken> &CXTokens) { SourceManager &SourceMgr = CXXUnit->getSourceManager(); std::pair<FileID, unsigned> BeginLocInfo - = SourceMgr.getDecomposedLoc(R.getBegin()); + = SourceMgr.getDecomposedLoc(Range.getBegin()); std::pair<FileID, unsigned> EndLocInfo - = SourceMgr.getDecomposedLoc(R.getEnd()); + = SourceMgr.getDecomposedLoc(Range.getEnd()); // Cannot tokenize across files. if (BeginLocInfo.first != EndLocInfo.first) @@ -4346,7 +4599,7 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, // Create a lexer bool Invalid = false; - llvm::StringRef Buffer + StringRef Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid); if (Invalid) return; @@ -4358,7 +4611,6 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, // Lex tokens until we hit the end of the range. const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second; - llvm::SmallVector<CXToken, 32> CXTokens; Token Tok; bool previousWasAt = false; do { @@ -4403,6 +4655,27 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXTokens.push_back(CXTok); previousWasAt = Tok.is(tok::at); } while (Lex.getBufferLocation() <= EffectiveBufferEnd); +} + +void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, + CXToken **Tokens, unsigned *NumTokens) { + if (Tokens) + *Tokens = 0; + if (NumTokens) + *NumTokens = 0; + + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + if (!CXXUnit || !Tokens || !NumTokens) + return; + + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + + SourceRange R = cxloc::translateCXSourceRange(Range); + if (R.isInvalid()) + return; + + SmallVector<CXToken, 32> CXTokens; + getTokens(CXXUnit, R, CXTokens); if (CXTokens.empty()) return; @@ -4445,6 +4718,16 @@ class AnnotateTokensWorker { SourceLocation GetTokenLoc(unsigned tokI) { return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]); } + bool isFunctionMacroToken(unsigned tokI) const { + return Tokens[tokI].int_data[3] != 0; + } + SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const { + return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[3]); + } + + void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange); + void annotateAndAdvanceFunctionMacroTokens(CXCursor, RangeComparisonResult, + SourceRange); public: AnnotateTokensWorker(AnnotateTokensData &annotated, @@ -4453,8 +4736,7 @@ public: : Annotated(annotated), Tokens(tokens), Cursors(cursors), NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0), AnnotateVis(tu, - AnnotateTokensVisitor, this, - Decl::MaxPCHLevel, true, RegionOfInterest), + AnnotateTokensVisitor, this, true, RegionOfInterest), SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()), HasContextSensitiveKeywords(false) { } @@ -4497,6 +4779,65 @@ void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) { } } +/// \brief It annotates and advances tokens with a cursor until the comparison +//// between the cursor location and the source range is the same as +/// \arg compResult. +/// +/// Pass RangeBefore to annotate tokens with a cursor until a range is reached. +/// Pass RangeOverlap to annotate tokens inside a range. +void AnnotateTokensWorker::annotateAndAdvanceTokens(CXCursor updateC, + RangeComparisonResult compResult, + SourceRange range) { + while (MoreTokens()) { + const unsigned I = NextToken(); + if (isFunctionMacroToken(I)) + return annotateAndAdvanceFunctionMacroTokens(updateC, compResult, range); + + SourceLocation TokLoc = GetTokenLoc(I); + if (LocationCompare(SrcMgr, TokLoc, range) == compResult) { + Cursors[I] = updateC; + AdvanceToken(); + continue; + } + break; + } +} + +/// \brief Special annotation handling for macro argument tokens. +void AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens( + CXCursor updateC, + RangeComparisonResult compResult, + SourceRange range) { + assert(MoreTokens()); + assert(isFunctionMacroToken(NextToken()) && + "Should be called only for macro arg tokens"); + + // This works differently than annotateAndAdvanceTokens; because expanded + // macro arguments can have arbitrary translation-unit source order, we do not + // advance the token index one by one until a token fails the range test. + // We only advance once past all of the macro arg tokens if all of them + // pass the range test. If one of them fails we keep the token index pointing + // at the start of the macro arg tokens so that the failing token will be + // annotated by a subsequent annotation try. + + bool atLeastOneCompFail = false; + + unsigned I = NextToken(); + for (; I < NumTokens && isFunctionMacroToken(I); ++I) { + SourceLocation TokLoc = getFunctionMacroTokenLoc(I); + if (TokLoc.isFileID()) + continue; // not macro arg token, it's parens or comma. + if (LocationCompare(SrcMgr, TokLoc, range) == compResult) { + if (clang_isInvalid(clang_getCursorKind(Cursors[I]))) + Cursors[I] = updateC; + } else + atLeastOneCompFail = true; + } + + if (!atLeastOneCompFail) + TokIdx = I; // All of the tokens were handled, advance beyond all of them. +} + enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { CXSourceLocation Loc = clang_getCursorLocation(cursor); @@ -4584,7 +4925,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { SourceLocation TokLoc = GetTokenLoc(I); switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { case RangeBefore: - assert(0 && "Infeasible"); + llvm_unreachable("Infeasible"); case RangeAfter: break; case RangeOverlap: @@ -4611,12 +4952,6 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { const enum CXCursorKind cursorK = clang_getCursorKind(cursor); if (cursorK >= CXCursor_FirstDecl && cursorK <= CXCursor_LastDecl) { Decl *D = cxcursor::getCursorDecl(cursor); - // Don't visit synthesized ObjC methods, since they have no syntatic - // representation in the source. - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - if (MD->isSynthesized()) - return CXChildVisit_Continue; - } SourceLocation StartLoc; if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { @@ -4654,20 +4989,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { (clang_isInvalid(K) || K == CXCursor_TranslationUnit) ? clang_getNullCursor() : parent; - while (MoreTokens()) { - const unsigned I = NextToken(); - SourceLocation TokLoc = GetTokenLoc(I); - switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { - case RangeBefore: - Cursors[I] = updateC; - AdvanceToken(); - continue; - case RangeAfter: - case RangeOverlap: - break; - } - break; - } + annotateAndAdvanceTokens(updateC, RangeBefore, cursorRange); // Avoid having the cursor of an expression "overwrite" the annotation of the // variable declaration that it belongs to. @@ -4692,46 +5014,19 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { VisitChildren(cursor); const unsigned AfterChildren = NextToken(); - // Adjust 'Last' to the last token within the extent of the cursor. - while (MoreTokens()) { - const unsigned I = NextToken(); - SourceLocation TokLoc = GetTokenLoc(I); - switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { - case RangeBefore: - assert(0 && "Infeasible"); - case RangeAfter: - break; - case RangeOverlap: - Cursors[I] = updateC; - AdvanceToken(); - continue; - } - break; - } - const unsigned Last = NextToken(); + // Scan the tokens that are at the end of the cursor, but are not captured + // but the child cursors. + annotateAndAdvanceTokens(cursor, RangeOverlap, cursorRange); // Scan the tokens that are at the beginning of the cursor, but are not // capture by the child cursors. - - // For AST elements within macros, rely on a post-annotate pass to - // to correctly annotate the tokens with cursors. Otherwise we can - // get confusing results of having tokens that map to cursors that really - // are expanded by an instantiation. - if (L.isMacroID()) - cursor = clang_getNullCursor(); - for (unsigned I = BeforeChildren; I != AfterChildren; ++I) { if (!clang_isInvalid(clang_getCursorKind(Cursors[I]))) break; Cursors[I] = cursor; } - // Scan the tokens that are at the end of the cursor, but are not captured - // but the child cursors. - for (unsigned I = AfterChildren; I != Last; ++I) - Cursors[I] = cursor; - TokIdx = Last; return CXChildVisit_Continue; } @@ -4742,6 +5037,74 @@ static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor, } namespace { + +/// \brief Uses the macro expansions in the preprocessing record to find +/// and mark tokens that are macro arguments. This info is used by the +/// AnnotateTokensWorker. +class MarkMacroArgTokensVisitor { + SourceManager &SM; + CXToken *Tokens; + unsigned NumTokens; + unsigned CurIdx; + +public: + MarkMacroArgTokensVisitor(SourceManager &SM, + CXToken *tokens, unsigned numTokens) + : SM(SM), Tokens(tokens), NumTokens(numTokens), CurIdx(0) { } + + CXChildVisitResult visit(CXCursor cursor, CXCursor parent) { + if (cursor.kind != CXCursor_MacroExpansion) + return CXChildVisit_Continue; + + SourceRange macroRange = getCursorMacroExpansion(cursor)->getSourceRange(); + if (macroRange.getBegin() == macroRange.getEnd()) + return CXChildVisit_Continue; // it's not a function macro. + + for (; CurIdx < NumTokens; ++CurIdx) { + if (!SM.isBeforeInTranslationUnit(getTokenLoc(CurIdx), + macroRange.getBegin())) + break; + } + + if (CurIdx == NumTokens) + return CXChildVisit_Break; + + for (; CurIdx < NumTokens; ++CurIdx) { + SourceLocation tokLoc = getTokenLoc(CurIdx); + if (!SM.isBeforeInTranslationUnit(tokLoc, macroRange.getEnd())) + break; + + setFunctionMacroTokenLoc(CurIdx, SM.getMacroArgExpandedLocation(tokLoc)); + } + + if (CurIdx == NumTokens) + return CXChildVisit_Break; + + return CXChildVisit_Continue; + } + +private: + SourceLocation getTokenLoc(unsigned tokI) { + return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]); + } + + void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) { + // The third field is reserved and currently not used. Use it here + // to mark macro arg expanded tokens with their expanded locations. + Tokens[tokI].int_data[3] = loc.getRawEncoding(); + } +}; + +} // end anonymous namespace + +static CXChildVisitResult +MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent, + CXClientData client_data) { + return static_cast<MarkMacroArgTokensVisitor*>(client_data)->visit(cursor, + parent); +} + +namespace { struct clang_annotateTokens_Data { CXTranslationUnit TU; ASTUnit *CXXUnit; @@ -4751,6 +5114,73 @@ namespace { }; } +static void annotatePreprocessorTokens(CXTranslationUnit TU, + SourceRange RegionOfInterest, + AnnotateTokensData &Annotated) { + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + + SourceManager &SourceMgr = CXXUnit->getSourceManager(); + std::pair<FileID, unsigned> BeginLocInfo + = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin()); + std::pair<FileID, unsigned> EndLocInfo + = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd()); + + if (BeginLocInfo.first != EndLocInfo.first) + return; + + StringRef Buffer; + bool Invalid = false; + Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid); + if (Buffer.empty() || Invalid) + return; + + Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), + CXXUnit->getASTContext().getLangOptions(), + 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 + // don't see it while preprocessing these tokens later, but keep track + // of all of the token locations inside this preprocessing directive so + // that we can annotate them appropriately. + // + // FIXME: Some simple tests here could identify macro definitions and + // #undefs, to provide specific cursor kinds for those. + 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()), + 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; + } +} + // This gets run a separate thread to avoid stack blowout. static void clang_annotateTokensImpl(void *UserData) { CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU; @@ -4770,65 +5200,19 @@ static void clang_annotateTokensImpl(void *UserData) { // 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(); - std::pair<FileID, unsigned> BeginLocInfo - = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin()); - std::pair<FileID, unsigned> EndLocInfo - = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd()); + annotatePreprocessorTokens(TU, RegionOfInterest, Annotated); - llvm::StringRef Buffer; - bool Invalid = false; - if (BeginLocInfo.first == EndLocInfo.first && - ((Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid)),true) && - !Invalid) { - Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), - CXXUnit->getASTContext().getLangOptions(), - 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 - // don't see it while preprocessing these tokens later, but keep track - // of all of the token locations inside this preprocessing directive so - // that we can annotate them appropriately. - // - // FIXME: Some simple tests here could identify macro definitions and - // #undefs, to provide specific cursor kinds for those. - 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()), - 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; - } + if (CXXUnit->getPreprocessor().getPreprocessingRecord()) { + // Search and mark tokens that are macro argument expansions. + MarkMacroArgTokensVisitor Visitor(CXXUnit->getSourceManager(), + Tokens, NumTokens); + CursorVisitor MacroArgMarker(TU, + MarkMacroArgTokensVisitorDelegate, &Visitor, + true, RegionOfInterest); + MacroArgMarker.visitPreprocessedEntitiesInRegion(); } // Annotate all of the source locations in the region of interest that map to @@ -4888,44 +5272,10 @@ static void clang_annotateTokensImpl(void *UserData) { 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; - } - } + + if (Cursors[I].kind == CXCursor_CXXFinalAttr || + Cursors[I].kind == CXCursor_CXXOverrideAttr) { + Tokens[I].int_data[0] = CXToken_Keyword; continue; } } @@ -5122,62 +5472,6 @@ CXCursor clang_getCursorLexicalParent(CXCursor cursor) { return clang_getNullCursor(); } -static void CollectOverriddenMethods(DeclContext *Ctx, - ObjCMethodDecl *Method, - llvm::SmallVectorImpl<ObjCMethodDecl *> &Methods) { - if (!Ctx) - return; - - // If we have a class or category implementation, jump straight to the - // interface. - if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx)) - return CollectOverriddenMethods(Impl->getClassInterface(), Method, Methods); - - ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx); - if (!Container) - return; - - // Check whether we have a matching method at this level. - if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - if (Method != Overridden) { - // We found an override at this level; there is no need to look - // into other protocols or categories. - Methods.push_back(Overridden); - return; - } - - if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), - PEnd = Protocol->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethods(*P, Method, Methods); - } - - if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { - for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), - PEnd = Category->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethods(*P, Method, Methods); - } - - if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { - for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), - PEnd = Interface->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethods(*P, Method, Methods); - - for (ObjCCategoryDecl *Category = Interface->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethods(Category, Method, Methods); - - // We only look into the superclass if we haven't found anything yet. - if (Methods.empty()) - if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) - return CollectOverriddenMethods(Super, Method, Methods); - } -} - void clang_getOverriddenCursors(CXCursor cursor, CXCursor **overridden, unsigned *num_overridden) { @@ -5188,45 +5482,12 @@ void clang_getOverriddenCursors(CXCursor cursor, if (!overridden || !num_overridden) return; - if (!clang_isDeclaration(cursor.kind)) - return; - - Decl *D = getCursorDecl(cursor); - if (!D) - return; + SmallVector<CXCursor, 8> Overridden; + cxcursor::getOverriddenCursors(cursor, Overridden); - // Handle C++ member functions. - CXTranslationUnit TU = getCursorTU(cursor); - if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { - *num_overridden = CXXMethod->size_overridden_methods(); - if (!*num_overridden) - return; - - *overridden = new CXCursor [*num_overridden]; - unsigned I = 0; - for (CXXMethodDecl::method_iterator - M = CXXMethod->begin_overridden_methods(), - MEnd = CXXMethod->end_overridden_methods(); - M != MEnd; (void)++M, ++I) - (*overridden)[I] = MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU); - return; - } - - ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); - if (!Method) - return; - - // Handle Objective-C methods. - llvm::SmallVector<ObjCMethodDecl *, 4> Methods; - CollectOverriddenMethods(Method->getDeclContext(), Method, Methods); - - if (Methods.empty()) - return; - - *num_overridden = Methods.size(); - *overridden = new CXCursor [Methods.size()]; - for (unsigned I = 0, N = Methods.size(); I != N; ++I) - (*overridden)[I] = MakeCXCursor(Methods[I], TU); + *num_overridden = Overridden.size(); + *overridden = new CXCursor [Overridden.size()]; + std::copy(Overridden.begin(), Overridden.end(), *overridden); } void clang_disposeOverriddenCursors(CXCursor *overridden) { @@ -5274,7 +5535,6 @@ unsigned clang_CXXMethod_isVirtual(CXCursor C) { Method = dyn_cast_or_null<CXXMethodDecl>(D); return (Method && Method->isVirtual()) ? 1 : 0; } - } // end: extern "C" //===----------------------------------------------------------------------===// @@ -5289,7 +5549,7 @@ 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" @@ -5347,6 +5607,12 @@ const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) { case CXTUResourceUsage_PreprocessingRecord: str = "Preprocessor: PreprocessingRecord"; break; + case CXTUResourceUsage_SourceManager_DataStructures: + str = "SourceManager: data structures and tables"; + break; + case CXTUResourceUsage_Preprocessor_HeaderSearch: + str = "Preprocessor: header search tables"; + break; } return str; } @@ -5399,9 +5665,13 @@ CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) { createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_SourceManager_Membuffer_Malloc, (unsigned long) srcBufs.malloc_bytes); - createCXTUResourceUsageEntry(*entries, + createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_SourceManager_Membuffer_MMap, (unsigned long) srcBufs.mmap_bytes); + createCXTUResourceUsageEntry(*entries, + CXTUResourceUsage_SourceManager_DataStructures, + (unsigned long) astContext.getSourceManager() + .getDataStructureSizes()); // How much memory is being used by the ExternalASTSource? if (ExternalASTSource *esrc = astContext.getExternalSource()) { @@ -5428,6 +5698,9 @@ CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) { pRec->getTotalMemory()); } + createCXTUResourceUsageEntry(*entries, + CXTUResourceUsage_Preprocessor_HeaderSearch, + pp.getHeaderSearchInfo().getTotalMemory()); CXTUResourceUsage usage = { (void*) entries.get(), (unsigned) entries->size(), diff --git a/tools/libclang/CIndexCXX.cpp b/tools/libclang/CIndexCXX.cpp index 0f49f65..fb0ccb1 100644 --- a/tools/libclang/CIndexCXX.cpp +++ b/tools/libclang/CIndexCXX.cpp @@ -31,11 +31,16 @@ unsigned clang_isVirtualBase(CXCursor C) { } enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { - if (C.kind != CXCursor_CXXBaseSpecifier) + AccessSpecifier spec = AS_none; + + if (C.kind == CXCursor_CXXAccessSpecifier) + spec = getCursorDecl(C)->getAccess(); + else if (C.kind == CXCursor_CXXBaseSpecifier) + spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier(); + else return CX_CXXInvalidAccessSpecifier; - CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); - switch (B->getAccessSpecifier()) { + switch (spec) { case AS_public: return CX_CXXPublic; case AS_protected: return CX_CXXProtected; case AS_private: return CX_CXXPrivate; diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index 832e2f2..c19b340 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -15,7 +15,12 @@ #include "CIndexer.h" #include "CXTranslationUnit.h" #include "CXString.h" +#include "CXCursor.h" +#include "CXString.h" #include "CIndexDiagnostic.h" +#include "clang/AST/Type.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Frontend/ASTUnit.h" @@ -198,6 +203,20 @@ clang_getCompletionAvailability(CXCompletionString completion_string) { : CXAvailability_Available; } +unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string) +{ + CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; + return CCStr ? CCStr->getAnnotationCount() : 0; +} + +CXString clang_getCompletionAnnotation(CXCompletionString completion_string, + unsigned annotation_number) { + CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; + return CCStr ? createCXString(CCStr->getAnnotation(annotation_number)) + : createCXString((const char *) 0); +} + + /// \brief The CXCodeCompleteResults structure we allocate internally; /// the client only sees the initial CXCodeCompleteResults structure. struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { @@ -205,10 +224,10 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { ~AllocatedCXCodeCompleteResults(); /// \brief Diagnostics produced while performing code completion. - llvm::SmallVector<StoredDiagnostic, 8> Diagnostics; + SmallVector<StoredDiagnostic, 8> Diagnostics; /// \brief Diag object - llvm::IntrusiveRefCntPtr<Diagnostic> Diag; + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diag; /// \brief Language options used to adjust source locations. LangOptions LangOpts; @@ -227,7 +246,7 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// \brief Temporary buffers that will be deleted once we have finished with /// the code-completion results. - llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers; + SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers; /// \brief Allocator used to store globally cached code-completion results. llvm::IntrusiveRefCntPtr<clang::GlobalCodeCompletionAllocator> @@ -242,6 +261,18 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// \brief A bitfield representing the acceptable completions for the /// current context. unsigned long long Contexts; + + /// \brief The kind of the container for the current context for completions. + enum CXCursorKind ContainerKind; + /// \brief The USR of the container for the current context for completions. + CXString ContainerUSR; + /// \brief a boolean value indicating whether there is complete information + /// about the container + unsigned ContainerIsIncomplete; + + /// \brief A string containing the Objective-C selector entered thus far for a + /// message send. + std::string Selector; }; /// \brief Tracks the number of code-completion result objects that are @@ -253,11 +284,16 @@ static llvm::sys::cas_flag CodeCompletionResultObjects; AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( const FileSystemOptions& FileSystemOpts) : CXCodeCompleteResults(), - Diag(new Diagnostic( + Diag(new DiagnosticsEngine( llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs))), FileSystemOpts(FileSystemOpts), FileMgr(new FileManager(FileSystemOpts)), - SourceMgr(new SourceManager(*Diag, *FileMgr)) { + SourceMgr(new SourceManager(*Diag, *FileMgr)), + Contexts(CXCompletionContext_Unknown), + ContainerKind(CXCursor_InvalidCode), + ContainerUSR(createCXString("")), + ContainerIsIncomplete(1) +{ if (getenv("LIBCLANG_OBJTRACKING")) { llvm::sys::AtomicIncrement(&CodeCompletionResultObjects); fprintf(stderr, "+++ %d completion results\n", CodeCompletionResultObjects); @@ -267,6 +303,8 @@ AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { delete [] Results; + clang_disposeString(ContainerUSR); + for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) TemporaryFiles[I].eraseFromDisk(); for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I) @@ -420,7 +458,7 @@ static unsigned long long getContextsForContextKind( contexts = CXCompletionContext_ObjCClassMessage; break; } - case CodeCompletionContext::CCC_ObjCSuperclass: { + case CodeCompletionContext::CCC_ObjCInterfaceName: { contexts = CXCompletionContext_ObjCInterface; break; } @@ -454,11 +492,13 @@ static unsigned long long getContextsForContextKind( namespace { class CaptureCompletionResults : public CodeCompleteConsumer { AllocatedCXCodeCompleteResults &AllocatedResults; - llvm::SmallVector<CXCompletionResult, 16> StoredResults; + SmallVector<CXCompletionResult, 16> StoredResults; + CXTranslationUnit *TU; public: - CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results) + CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results, + CXTranslationUnit *TranslationUnit) : CodeCompleteConsumer(true, false, true, false), - AllocatedResults(Results) { } + AllocatedResults(Results), TU(TranslationUnit) { } ~CaptureCompletionResults() { Finish(); } virtual void ProcessCodeCompleteResults(Sema &S, @@ -477,10 +517,77 @@ namespace { StoredResults.push_back(R); } - enum CodeCompletionContext::Kind kind = Context.getKind(); + enum CodeCompletionContext::Kind contextKind = Context.getKind(); - AllocatedResults.ContextKind = kind; - AllocatedResults.Contexts = getContextsForContextKind(kind, S); + AllocatedResults.ContextKind = contextKind; + AllocatedResults.Contexts = getContextsForContextKind(contextKind, S); + + AllocatedResults.Selector = ""; + if (Context.getNumSelIdents() > 0) { + for (unsigned i = 0; i < Context.getNumSelIdents(); i++) { + IdentifierInfo *selIdent = Context.getSelIdents()[i]; + if (selIdent != NULL) { + StringRef selectorString = Context.getSelIdents()[i]->getName(); + AllocatedResults.Selector += selectorString; + } + AllocatedResults.Selector += ":"; + } + } + + QualType baseType = Context.getBaseType(); + NamedDecl *D = NULL; + + if (!baseType.isNull()) { + // Get the declaration for a class/struct/union/enum type + if (const TagType *Tag = baseType->getAs<TagType>()) + D = Tag->getDecl(); + // Get the @interface declaration for a (possibly-qualified) Objective-C + // object pointer type, e.g., NSString* + else if (const ObjCObjectPointerType *ObjPtr = + baseType->getAs<ObjCObjectPointerType>()) + D = ObjPtr->getInterfaceDecl(); + // Get the @interface declaration for an Objective-C object type + else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>()) + D = Obj->getInterface(); + // Get the class for a C++ injected-class-name + else if (const InjectedClassNameType *Injected = + baseType->getAs<InjectedClassNameType>()) + D = Injected->getDecl(); + } + + if (D != NULL) { + CXCursor cursor = cxcursor::MakeCXCursor(D, *TU); + + CXCursorKind cursorKind = clang_getCursorKind(cursor); + CXString cursorUSR = clang_getCursorUSR(cursor); + + // Normally, clients of CXString shouldn't care whether or not + // a CXString is managed by a pool or by explicitly malloc'ed memory. + // However, there are cases when AllocatedResults outlives the + // CXTranslationUnit. This is a workaround that failure mode. + if (cxstring::isManagedByPool(cursorUSR)) { + CXString heapStr = + cxstring::createCXString(clang_getCString(cursorUSR), true); + clang_disposeString(cursorUSR); + cursorUSR = heapStr; + } + + AllocatedResults.ContainerKind = cursorKind; + AllocatedResults.ContainerUSR = cursorUSR; + + const Type *type = baseType.getTypePtrOrNull(); + if (type != NULL) { + AllocatedResults.ContainerIsIncomplete = type->isIncompleteType(); + } + else { + AllocatedResults.ContainerIsIncomplete = 1; + } + } + else { + AllocatedResults.ContainerKind = CXCursor_InvalidCode; + AllocatedResults.ContainerUSR = createCXString(""); + AllocatedResults.ContainerIsIncomplete = 1; + } } virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, @@ -551,9 +658,9 @@ void clang_codeCompleteAt_Impl(void *UserData) { ASTUnit::ConcurrencyCheck Check(*AST); // Perform the remapping of source files. - llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles; + 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); + 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, @@ -571,7 +678,7 @@ void clang_codeCompleteAt_Impl(void *UserData) { Results->NumResults = 0; // Create a code-completion consumer to capture the results. - CaptureCompletionResults Capture(*Results); + CaptureCompletionResults Capture(*Results, &TU); // Perform completion. AST->CodeComplete(complete_filename, complete_line, complete_column, @@ -621,7 +728,7 @@ void clang_codeCompleteAt_Impl(void *UserData) { } pchName.push_back('\0'); struct stat stat_results; - if (stat(pchName.data(), &stat_results) == 0) + if (stat(pchName.str().c_str(), &stat_results) == 0) usesPCH = true; continue; } @@ -639,7 +746,7 @@ void clang_codeCompleteAt_Impl(void *UserData) { os << ", \"clangVer\": \"" << getClangFullVersion() << '"'; os << " }"; - llvm::StringRef res = os.str(); + StringRef res = os.str(); if (res.size() > 0) { do { // Setup the UDP socket. @@ -731,6 +838,40 @@ clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) { return Results->Contexts; } +enum CXCursorKind clang_codeCompleteGetContainerKind( + CXCodeCompleteResults *ResultsIn, + unsigned *IsIncomplete) { + AllocatedCXCodeCompleteResults *Results = + static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn); + if (!Results) + return CXCursor_InvalidCode; + + if (IsIncomplete != NULL) { + *IsIncomplete = Results->ContainerIsIncomplete; + } + + return Results->ContainerKind; +} + +CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) { + AllocatedCXCodeCompleteResults *Results = + static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn); + if (!Results) + return createCXString(""); + + return createCXString(clang_getCString(Results->ContainerUSR)); +} + + +CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) { + AllocatedCXCodeCompleteResults *Results = + static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn); + if (!Results) + return createCXString(""); + + return createCXString(Results->Selector); +} + } // end extern "C" /// \brief Simple utility function that appends a \p New string to the given @@ -744,7 +885,7 @@ clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) { /// /// \param Buffer A buffer that stores the actual, concatenated string. It will /// be used if the old string is already-non-empty. -static void AppendToString(llvm::StringRef &Old, llvm::StringRef New, +static void AppendToString(StringRef &Old, StringRef New, llvm::SmallString<256> &Buffer) { if (Old.empty()) { Old = New; @@ -764,9 +905,9 @@ static void AppendToString(llvm::StringRef &Old, llvm::StringRef New, /// concatenated. /// /// \param Buffer A buffer used for storage of the completed name. -static llvm::StringRef GetTypedName(CodeCompletionString *String, +static StringRef GetTypedName(CodeCompletionString *String, llvm::SmallString<256> &Buffer) { - llvm::StringRef Result; + StringRef Result; for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end(); C != CEnd; ++C) { if (C->Kind == CodeCompletionString::CK_TypedText) @@ -786,9 +927,9 @@ namespace { = (CodeCompletionString *)YR.CompletionString; llvm::SmallString<256> XBuffer; - llvm::StringRef XText = GetTypedName(X, XBuffer); + StringRef XText = GetTypedName(X, XBuffer); llvm::SmallString<256> YBuffer; - llvm::StringRef YText = GetTypedName(Y, YBuffer); + StringRef YText = GetTypedName(Y, YBuffer); if (XText.empty() || YText.empty()) return !XText.empty(); diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp index 0fcdab7..26f69b0 100644 --- a/tools/libclang/CIndexDiagnostic.cpp +++ b/tools/libclang/CIndexDiagnostic.cpp @@ -106,7 +106,7 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { /* Print warning/error/etc. */ switch (Severity) { - case CXDiagnostic_Ignored: assert(0 && "impossible"); break; + case CXDiagnostic_Ignored: llvm_unreachable("impossible"); case CXDiagnostic_Note: Out << "note: "; break; case CXDiagnostic_Warning: Out << "warning: "; break; case CXDiagnostic_Error: Out << "error: "; break; @@ -182,11 +182,11 @@ enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) { return CXDiagnostic_Ignored; switch (StoredDiag->Diag.getLevel()) { - case Diagnostic::Ignored: return CXDiagnostic_Ignored; - case Diagnostic::Note: return CXDiagnostic_Note; - case Diagnostic::Warning: return CXDiagnostic_Warning; - case Diagnostic::Error: return CXDiagnostic_Error; - case Diagnostic::Fatal: return CXDiagnostic_Fatal; + case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored; + case DiagnosticsEngine::Note: return CXDiagnostic_Note; + case DiagnosticsEngine::Warning: return CXDiagnostic_Warning; + case DiagnosticsEngine::Error: return CXDiagnostic_Error; + case DiagnosticsEngine::Fatal: return CXDiagnostic_Fatal; } llvm_unreachable("Invalid diagnostic level"); @@ -220,11 +220,11 @@ CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) { return createCXString(""); unsigned ID = StoredDiag->Diag.getID(); - llvm::StringRef Option = DiagnosticIDs::getWarningOptionForDiag(ID); + StringRef Option = DiagnosticIDs::getWarningOptionForDiag(ID); if (!Option.empty()) { if (Disable) - *Disable = createCXString((llvm::Twine("-Wno-") + Option).str()); - return createCXString((llvm::Twine("-W") + Option).str()); + *Disable = createCXString((Twine("-Wno-") + Option).str()); + return createCXString((Twine("-W") + Option).str()); } if (ID == diag::fatal_too_many_errors) { diff --git a/tools/libclang/CIndexHigh.cpp b/tools/libclang/CIndexHigh.cpp new file mode 100644 index 0000000..b5a05ea --- /dev/null +++ b/tools/libclang/CIndexHigh.cpp @@ -0,0 +1,315 @@ +//===- CIndexHigh.cpp - Higher level API functions ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Index_Internal.h" +#include "CXCursor.h" +#include "CXSourceLocation.h" +#include "CXTranslationUnit.h" + +#include "clang/Frontend/ASTUnit.h" +#include "clang/AST/DeclObjC.h" + +using namespace clang; + +static void getTopOverriddenMethods(CXTranslationUnit TU, + Decl *D, + SmallVectorImpl<Decl *> &Methods) { + if (!isa<ObjCMethodDecl>(D) && !isa<CXXMethodDecl>(D)) + return; + + SmallVector<CXCursor, 8> Overridden; + cxcursor::getOverriddenCursors(cxcursor::MakeCXCursor(D, TU), Overridden); + + if (Overridden.empty()) { + Methods.push_back(D->getCanonicalDecl()); + return; + } + + for (SmallVector<CXCursor, 8>::iterator + I = Overridden.begin(), E = Overridden.end(); I != E; ++I) + getTopOverriddenMethods(TU, cxcursor::getCursorDecl(*I), Methods); +} + +namespace { + +struct FindFileIdRefVisitData { + CXTranslationUnit TU; + FileID FID; + Decl *Dcl; + int SelectorIdIdx; + CXCursorAndRangeVisitor visitor; + + typedef SmallVector<Decl *, 8> TopMethodsTy; + TopMethodsTy TopMethods; + + FindFileIdRefVisitData(CXTranslationUnit TU, FileID FID, + Decl *D, int selectorIdIdx, + CXCursorAndRangeVisitor visitor) + : TU(TU), FID(FID), SelectorIdIdx(selectorIdIdx), visitor(visitor) { + Dcl = getCanonical(D); + getTopOverriddenMethods(TU, Dcl, TopMethods); + } + + ASTContext &getASTContext() const { + return static_cast<ASTUnit *>(TU->TUData)->getASTContext(); + } + + /// \brief We are looking to find all semantically relevant identifiers, + /// so the definition of "canonical" here is different than in the AST, e.g. + /// + /// \code + /// class C { + /// C() {} + /// }; + /// \endcode + /// + /// we consider the canonical decl of the constructor decl to be the class + /// itself, so both 'C' can be highlighted. + Decl *getCanonical(Decl *D) const { + D = D->getCanonicalDecl(); + + if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) + return getCanonical(ImplD->getClassInterface()); + if (CXXConstructorDecl *CXXCtorD = dyn_cast<CXXConstructorDecl>(D)) + return getCanonical(CXXCtorD->getParent()); + + return D; + } + + bool isHit(Decl *D) const { + D = getCanonical(D); + if (D == Dcl) + return true; + + if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D)) + return isOverriddingMethod(D); + + return false; + } + +private: + bool isOverriddingMethod(Decl *D) const { + if (std::find(TopMethods.begin(), TopMethods.end(), D) != + TopMethods.end()) + return true; + + TopMethodsTy methods; + getTopOverriddenMethods(TU, D, methods); + for (TopMethodsTy::iterator + I = methods.begin(), E = methods.end(); I != E; ++I) { + if (std::find(TopMethods.begin(), TopMethods.end(), *I) != + TopMethods.end()) + return true; + } + + return false; + } +}; + +} // end anonymous namespace. + +/// \brief For a macro \arg Loc, returns the file spelling location and sets +/// to \arg isMacroArg whether the spelling resides inside a macro definition or +/// a macro argument. +static SourceLocation getFileSpellingLoc(SourceManager &SM, + SourceLocation Loc, + bool &isMacroArg) { + assert(Loc.isMacroID()); + SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc); + if (SpellLoc.isMacroID()) + return getFileSpellingLoc(SM, SpellLoc, isMacroArg); + + isMacroArg = SM.isMacroArgExpansion(Loc); + return SpellLoc; +} + +static enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor, + CXCursor parent, + CXClientData client_data) { + CXCursor declCursor = clang_getCursorReferenced(cursor); + if (!clang_isDeclaration(declCursor.kind)) + return CXChildVisit_Recurse; + + Decl *D = cxcursor::getCursorDecl(declCursor); + FindFileIdRefVisitData *data = (FindFileIdRefVisitData *)client_data; + if (data->isHit(D)) { + cursor = cxcursor::getSelectorIdentifierCursor(data->SelectorIdIdx, cursor); + + // We are looking for identifiers to highlight so for objc methods (and + // not a parameter) we can only highlight the selector identifiers. + if ((cursor.kind == CXCursor_ObjCClassMethodDecl || + cursor.kind == CXCursor_ObjCInstanceMethodDecl) && + cxcursor::getSelectorIdentifierIndex(cursor) == -1) + return CXChildVisit_Recurse; + + if (clang_isExpression(cursor.kind)) { + if (cursor.kind == CXCursor_DeclRefExpr || + cursor.kind == CXCursor_MemberRefExpr) { + // continue.. + + } else if (cursor.kind == CXCursor_ObjCMessageExpr && + cxcursor::getSelectorIdentifierIndex(cursor) != -1) { + // continue.. + + } else + return CXChildVisit_Recurse; + } + + SourceLocation + Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor)); + SourceLocation SelIdLoc = cxcursor::getSelectorIdentifierLoc(cursor); + if (SelIdLoc.isValid()) + Loc = SelIdLoc; + + SourceManager &SM = data->getASTContext().getSourceManager(); + bool isInMacroDef = false; + if (Loc.isMacroID()) { + bool isMacroArg; + Loc = getFileSpellingLoc(SM, Loc, isMacroArg); + isInMacroDef = !isMacroArg; + } + + // We are looking for identifiers in a specific file. + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + if (LocInfo.first != data->FID) + return CXChildVisit_Recurse; + + if (isInMacroDef) { + // FIXME: For a macro definition make sure that all expansions + // of it expand to the same reference before allowing to point to it. + Loc = SourceLocation(); + } + + data->visitor.visit(data->visitor.context, cursor, + cxloc::translateSourceRange(D->getASTContext(), Loc)); + } + return CXChildVisit_Recurse; +} + +static void findIdRefsInFile(CXTranslationUnit TU, CXCursor declCursor, + const FileEntry *File, + CXCursorAndRangeVisitor Visitor) { + assert(clang_isDeclaration(declCursor.kind)); + ASTUnit *Unit = static_cast<ASTUnit*>(TU->TUData); + ASTContext &Ctx = Unit->getASTContext(); + SourceManager &SM = Unit->getSourceManager(); + + FileID FID = SM.translateFile(File); + Decl *Dcl = cxcursor::getCursorDecl(declCursor); + FindFileIdRefVisitData data(TU, FID, Dcl, + cxcursor::getSelectorIdentifierIndex(declCursor), + Visitor); + + if (DeclContext *DC = Dcl->getParentFunctionOrMethod()) { + clang_visitChildren(cxcursor::MakeCXCursor(cast<Decl>(DC), TU), + findFileIdRefVisit, &data); + return; + } + + if (FID == SM.getMainFileID() && !Unit->isMainFileAST()) { + SourceLocation FileLoc = SM.getLocForStartOfFile(FID); + TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl(); + CXCursor TUCursor = clang_getTranslationUnitCursor(TU); + for (DeclContext::decl_iterator + I = TUD->noload_decls_begin(), E = TUD->noload_decls_end(); + I != E; ++I) { + Decl *D = *I; + + SourceRange R = D->getSourceRange(); + if (R.isInvalid()) + continue; + if (SM.isBeforeInTranslationUnit(R.getEnd(), FileLoc)) + continue; + + if (TagDecl *TD = dyn_cast<TagDecl>(D)) + if (!TD->isFreeStanding()) + continue; + + CXCursor CurCursor = cxcursor::MakeCXCursor(D, TU); + findFileIdRefVisit(CurCursor, TUCursor, &data); + clang_visitChildren(CurCursor, findFileIdRefVisit, &data); + } + return; + } + + clang_visitChildren(clang_getTranslationUnitCursor(TU), + findFileIdRefVisit, &data); +} + + +//===----------------------------------------------------------------------===// +// libclang public APIs. +//===----------------------------------------------------------------------===// + +extern "C" { + +void clang_findReferencesInFile(CXCursor cursor, CXFile file, + CXCursorAndRangeVisitor visitor) { + bool Logging = ::getenv("LIBCLANG_LOGGING"); + + if (clang_Cursor_isNull(cursor)) { + if (Logging) + llvm::errs() << "clang_findReferencesInFile: Null cursor\n"; + return; + } + if (!file) { + if (Logging) + llvm::errs() << "clang_findReferencesInFile: Null file\n"; + return; + } + if (!visitor.visit) { + if (Logging) + llvm::errs() << "clang_findReferencesInFile: Null visitor\n"; + return; + } + + // We are interested in semantics of identifiers so for C++ constructor exprs + // prefer type references, e.g.: + // + // return MyStruct(); + // + // for 'MyStruct' we'll have a cursor pointing at the constructor decl but + // we are actually interested in the type declaration. + cursor = cxcursor::getTypeRefCursor(cursor); + + CXCursor refCursor = clang_getCursorReferenced(cursor); + + if (!clang_isDeclaration(refCursor.kind)) { + if (Logging) + llvm::errs() << "clang_findReferencesInFile: cursor is not referencing a " + "declaration\n"; + return; + } + + ASTUnit *CXXUnit = cxcursor::getCursorASTUnit(cursor); + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + + findIdRefsInFile(cxcursor::getCursorTU(cursor), + refCursor, + static_cast<const FileEntry *>(file), + visitor); +} + +static enum CXVisitorResult _visitCursorAndRange(void *context, + CXCursor cursor, + CXSourceRange range) { + CXCursorAndRangeVisitorBlock block = (CXCursorAndRangeVisitorBlock)context; + return INVOKE_BLOCK2(block, cursor, range); +} + +void clang_findReferencesInFileWithBlock(CXCursor cursor, + CXFile file, + CXCursorAndRangeVisitorBlock block) { + CXCursorAndRangeVisitor visitor = { block, + block ? _visitCursorAndRange : 0 }; + return clang_findReferencesInFile(cursor, file, visitor); +} + +} // end: extern "C" + diff --git a/tools/libclang/CIndexInclusionStack.cpp b/tools/libclang/CIndexInclusionStack.cpp index 6bc4f2e..848ca31 100644 --- a/tools/libclang/CIndexInclusionStack.cpp +++ b/tools/libclang/CIndexInclusionStack.cpp @@ -29,19 +29,22 @@ void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB, SourceManager &SM = CXXUnit->getSourceManager(); ASTContext &Ctx = CXXUnit->getASTContext(); - llvm::SmallVector<CXSourceLocation, 10> InclusionStack; - unsigned i = SM.sloc_loaded_entry_size(); - unsigned n = SM.sloc_entry_size(); + SmallVector<CXSourceLocation, 10> InclusionStack; + unsigned n = SM.local_sloc_entry_size(); // In the case where all the SLocEntries are in an external source, traverse // those SLocEntries as well. This is the case where we are looking // at the inclusion stack of an AST/PCH file. - if (i >= n) - i = 0; - - for ( ; i < n ; ++i) { + const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const; + if (n == 1) { + Getter = &SourceManager::getLoadedSLocEntry; + n = SM.loaded_sloc_entry_size(); + } else + Getter = &SourceManager::getLocalSLocEntry; + + for (unsigned i = 0 ; i < n ; ++i) { bool Invalid = false; - const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i, &Invalid); + const SrcMgr::SLocEntry &SL = (SM.*Getter)(i, &Invalid); if (!SL.isFile() || Invalid) continue; diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index 4f1f071..121d67d 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -31,28 +31,28 @@ using namespace clang::cxstring; namespace { class USRGenerator : public DeclVisitor<USRGenerator> { llvm::OwningPtr<llvm::SmallString<128> > OwnedBuf; - llvm::SmallVectorImpl<char> &Buf; + SmallVectorImpl<char> &Buf; llvm::raw_svector_ostream Out; bool IgnoreResults; - ASTUnit *AU; + ASTContext *Context; bool generatedLoc; llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; public: - USRGenerator(const CXCursor *C = 0, llvm::SmallVectorImpl<char> *extBuf = 0) + explicit USRGenerator(ASTContext *Ctx = 0, SmallVectorImpl<char> *extBuf = 0) : OwnedBuf(extBuf ? 0 : new llvm::SmallString<128>()), Buf(extBuf ? *extBuf : *OwnedBuf.get()), Out(Buf), IgnoreResults(false), - AU(C ? cxcursor::getCursorASTUnit(*C) : 0), + Context(Ctx), generatedLoc(false) { // Add the USR space prefix. Out << "c:"; } - llvm::StringRef str() { + StringRef str() { return Out.str(); } @@ -114,19 +114,19 @@ public: /// itself. /// Generate a USR for an Objective-C class. - void GenObjCClass(llvm::StringRef cls); + void GenObjCClass(StringRef cls); /// Generate a USR for an Objective-C class category. - void GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat); + void GenObjCCategory(StringRef cls, StringRef cat); /// Generate a USR fragment for an Objective-C instance variable. The /// complete USR can be created by concatenating the USR for the /// encompassing class with this USR fragment. - void GenObjCIvar(llvm::StringRef ivar); + void GenObjCIvar(StringRef ivar); /// Generate a USR fragment for an Objective-C method. - void GenObjCMethod(llvm::StringRef sel, bool isInstanceMethod); + void GenObjCMethod(StringRef sel, bool isInstanceMethod); /// Generate a USR fragment for an Objective-C property. - void GenObjCProperty(llvm::StringRef prop); + void GenObjCProperty(StringRef prop); /// Generate a USR for an Objective-C protocol. - void GenObjCProtocol(llvm::StringRef prot); + void GenObjCProtocol(StringRef prot); void VisitType(QualType T); void VisitTemplateParameterList(const TemplateParameterList *Params); @@ -190,7 +190,7 @@ void USRGenerator::VisitFunctionDecl(FunctionDecl *D) { Out << "@F@"; D->printName(Out); - ASTContext &Ctx = AU->getASTContext(); + ASTContext &Ctx = *Context; if (!Ctx.getLangOptions().CPlusPlus || D->isExternC()) return; @@ -235,7 +235,7 @@ void USRGenerator::VisitVarDecl(VarDecl *D) { VisitDeclContext(D->getDeclContext()); // Variables always have simple names. - llvm::StringRef s = D->getName(); + StringRef s = D->getName(); // The string can be empty if the declaration has no name; e.g., it is // the ParmDecl with no name for declaration of a function pointer type, e.g.: @@ -320,7 +320,7 @@ void USRGenerator::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { switch (D->getKind()) { default: - assert(false && "Invalid ObjC container."); + llvm_unreachable("Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: GenObjCClass(D->getName()); @@ -433,7 +433,7 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { if (EmitDeclName(D)) { if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { Buf[off] = 'A'; - Out << '@' << TD; + Out << '@' << *TD; } else Buf[off] = 'a'; @@ -480,13 +480,13 @@ bool USRGenerator::GenLoc(const Decl *D) { // Use the location of canonical decl. D = D->getCanonicalDecl(); - const SourceManager &SM = AU->getSourceManager(); + const SourceManager &SM = Context->getSourceManager(); SourceLocation L = D->getLocStart(); if (L.isInvalid()) { IgnoreResults = true; return true; } - L = SM.getInstantiationLoc(L); + L = SM.getExpansionLoc(L); const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L); const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); if (FE) { @@ -508,7 +508,7 @@ void USRGenerator::VisitType(QualType T) { // This method mangles in USR information for types. It can possibly // just reuse the naming-mangling logic used by codegen, although the // requirements for USRs might not be the same. - ASTContext &Ctx = AU->getASTContext(); + ASTContext &Ctx = *Context; do { T = Ctx.getCanonicalType(T); @@ -570,6 +570,8 @@ void USRGenerator::VisitType(QualType T) { c = 'K'; break; case BuiltinType::Int128: c = 'J'; break; + case BuiltinType::Half: + c = 'h'; break; case BuiltinType::Float: c = 'f'; break; case BuiltinType::Double: @@ -755,27 +757,27 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { // General purpose USR generation methods. //===----------------------------------------------------------------------===// -void USRGenerator::GenObjCClass(llvm::StringRef cls) { +void USRGenerator::GenObjCClass(StringRef cls) { Out << "objc(cs)" << cls; } -void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) { +void USRGenerator::GenObjCCategory(StringRef cls, StringRef cat) { Out << "objc(cy)" << cls << '@' << cat; } -void USRGenerator::GenObjCIvar(llvm::StringRef ivar) { +void USRGenerator::GenObjCIvar(StringRef ivar) { Out << '@' << ivar; } -void USRGenerator::GenObjCMethod(llvm::StringRef meth, bool isInstanceMethod) { +void USRGenerator::GenObjCMethod(StringRef meth, bool isInstanceMethod) { Out << (isInstanceMethod ? "(im)" : "(cm)") << meth; } -void USRGenerator::GenObjCProperty(llvm::StringRef prop) { +void USRGenerator::GenObjCProperty(StringRef prop) { Out << "(py)" << prop; } -void USRGenerator::GenObjCProtocol(llvm::StringRef prot) { +void USRGenerator::GenObjCProtocol(StringRef prot) { Out << "objc(pl)" << prot; } @@ -783,16 +785,14 @@ void USRGenerator::GenObjCProtocol(llvm::StringRef prot) { // API hooks. //===----------------------------------------------------------------------===// -static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) { +static inline StringRef extractUSRSuffix(StringRef s) { return s.startswith("c:") ? s.substr(2) : ""; } -static CXString getDeclCursorUSR(const CXCursor &C) { - Decl *D = cxcursor::getCursorDecl(C); - +bool cxcursor::getDeclCursorUSR(Decl *D, SmallVectorImpl<char> &Buf) { // Don't generate USRs for things with invalid locations. if (!D || D->getLocStart().isInvalid()) - return createCXString(""); + return true; // Check if the cursor has 'NoLinkage'. if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) @@ -817,27 +817,15 @@ static CXString getDeclCursorUSR(const CXCursor &C) { break; } - CXTranslationUnit TU = cxcursor::getCursorTU(C); - if (!TU) - return createCXString(""); - - CXStringBuf *buf = cxstring::getCXStringBuf(TU); - if (!buf) - return createCXString(""); - { - USRGenerator UG(&C, &buf->Data); + USRGenerator UG(&D->getASTContext(), &Buf); UG->Visit(D); - if (UG->ignoreResults()) { - disposeCXStringBuf(buf); - return createCXString(""); - } + if (UG->ignoreResults()) + return true; } - // Return the C-string, but don't make a copy since it is already in - // the string buffer. - buf->Data.push_back('\0'); - return createCXString(buf); + + return false; } extern "C" { @@ -845,8 +833,27 @@ extern "C" { CXString clang_getCursorUSR(CXCursor C) { const CXCursorKind &K = clang_getCursorKind(C); - if (clang_isDeclaration(K)) - return getDeclCursorUSR(C); + if (clang_isDeclaration(K)) { + Decl *D = cxcursor::getCursorDecl(C); + CXTranslationUnit TU = cxcursor::getCursorTU(C); + if (!TU) + return createCXString(""); + + CXStringBuf *buf = cxstring::getCXStringBuf(TU); + if (!buf) + return createCXString(""); + + bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data); + if (Ignore) { + disposeCXStringBuf(buf); + return createCXString(""); + } + + // Return the C-string, but don't make a copy since it is already in + // the string buffer. + buf->Data.push_back('\0'); + return createCXString(buf); + } if (K == CXCursor_MacroDefinition) { CXTranslationUnit TU = cxcursor::getCursorTU(C); @@ -858,7 +865,8 @@ CXString clang_getCursorUSR(CXCursor C) { return createCXString(""); { - USRGenerator UG(&C, &buf->Data); + USRGenerator UG(&cxcursor::getCursorASTUnit(C)->getASTContext(), + &buf->Data); UG << "macro@" << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart(); } diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp index 56974b9..995a8fe 100644 --- a/tools/libclang/CIndexer.cpp +++ b/tools/libclang/CIndexer.cpp @@ -74,7 +74,7 @@ std::string CIndexer::getClangResourcesPath() { // This silly cast below avoids a C++ warning. Dl_info info; if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0) - assert(0 && "Call to dladdr() failed"); + llvm_unreachable("Call to dladdr() failed"); llvm::sys::Path LibClangPath(info.dli_fname); diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt index f45389f..f754e98 100644 --- a/tools/libclang/CMakeLists.txt +++ b/tools/libclang/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES CIndexCXX.cpp CIndexCodeCompletion.cpp CIndexDiagnostic.cpp + CIndexHigh.cpp CIndexInclusionStack.cpp CIndexUSRs.cpp CIndexer.cpp diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index b3c57dc..db275001 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -20,8 +20,10 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang-c/Index.h" #include "llvm/Support/ErrorHandling.h" @@ -30,7 +32,7 @@ using namespace cxcursor; CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) { assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid); - CXCursor C = { K, { 0, 0, 0 } }; + CXCursor C = { K, 0, { 0, 0, 0 } }; return C; } @@ -41,6 +43,9 @@ static CXCursorKind GetCursorKind(const Attr *A) { case attr::IBAction: return CXCursor_IBActionAttr; case attr::IBOutlet: return CXCursor_IBOutletAttr; case attr::IBOutletCollection: return CXCursor_IBOutletCollectionAttr; + case attr::Final: return CXCursor_CXXFinalAttr; + case attr::Override: return CXCursor_CXXOverrideAttr; + case attr::Annotate: return CXCursor_AnnotateAttr; } return CXCursor_UnexposedAttr; @@ -49,152 +54,369 @@ static CXCursorKind GetCursorKind(const Attr *A) { CXCursor cxcursor::MakeCXCursor(const Attr *A, Decl *Parent, CXTranslationUnit TU) { assert(A && Parent && TU && "Invalid arguments!"); - CXCursor C = { GetCursorKind(A), { Parent, (void*)A, TU } }; + CXCursor C = { GetCursorKind(A), 0, { Parent, (void*)A, TU } }; return C; } CXCursor cxcursor::MakeCXCursor(Decl *D, CXTranslationUnit TU, + SourceRange RegionOfInterest, bool FirstInDeclGroup) { assert(D && TU && "Invalid arguments!"); - CXCursor C = { getCursorKindForDecl(D), - { D, (void*)(intptr_t) (FirstInDeclGroup ? 1 : 0), TU } - }; + + CXCursorKind K = getCursorKindForDecl(D); + + if (K == CXCursor_ObjCClassMethodDecl || + K == CXCursor_ObjCInstanceMethodDecl) { + int SelectorIdIndex = -1; + // Check if cursor points to a selector id. + if (RegionOfInterest.isValid() && + RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) { + SmallVector<SourceLocation, 16> SelLocs; + cast<ObjCMethodDecl>(D)->getSelectorLocs(SelLocs); + SmallVector<SourceLocation, 16>::iterator + I=std::find(SelLocs.begin(), SelLocs.end(),RegionOfInterest.getBegin()); + if (I != SelLocs.end()) + SelectorIdIndex = I - SelLocs.begin(); + } + CXCursor C = { K, SelectorIdIndex, + { D, (void*)(intptr_t) (FirstInDeclGroup ? 1 : 0), TU }}; + return C; + } + + CXCursor C = { K, 0, { D, (void*)(intptr_t) (FirstInDeclGroup ? 1 : 0), TU }}; return C; } -CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, - CXTranslationUnit TU) { +CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU, + SourceRange RegionOfInterest) { assert(S && TU && "Invalid arguments!"); CXCursorKind K = CXCursor_NotImplemented; switch (S->getStmtClass()) { case Stmt::NoStmtClass: break; - - case Stmt::NullStmtClass: - case Stmt::CompoundStmtClass: + case Stmt::CaseStmtClass: + K = CXCursor_CaseStmt; + break; + case Stmt::DefaultStmtClass: - case Stmt::IfStmtClass: - case Stmt::SwitchStmtClass: - case Stmt::WhileStmtClass: - case Stmt::DoStmtClass: - case Stmt::ForStmtClass: - case Stmt::GotoStmtClass: + K = CXCursor_DefaultStmt; + break; + + case Stmt::IfStmtClass: + K = CXCursor_IfStmt; + break; + + case Stmt::SwitchStmtClass: + K = CXCursor_SwitchStmt; + break; + + case Stmt::WhileStmtClass: + K = CXCursor_WhileStmt; + break; + + case Stmt::DoStmtClass: + K = CXCursor_DoStmt; + break; + + case Stmt::ForStmtClass: + K = CXCursor_ForStmt; + break; + + case Stmt::GotoStmtClass: + K = CXCursor_GotoStmt; + break; + case Stmt::IndirectGotoStmtClass: - case Stmt::ContinueStmtClass: - case Stmt::BreakStmtClass: - case Stmt::ReturnStmtClass: - case Stmt::DeclStmtClass: - case Stmt::AsmStmtClass: - case Stmt::ObjCAtTryStmtClass: - case Stmt::ObjCAtCatchStmtClass: - case Stmt::ObjCAtFinallyStmtClass: - case Stmt::ObjCAtThrowStmtClass: - case Stmt::ObjCAtSynchronizedStmtClass: - case Stmt::ObjCAutoreleasePoolStmtClass: + K = CXCursor_IndirectGotoStmt; + break; + + case Stmt::ContinueStmtClass: + K = CXCursor_ContinueStmt; + break; + + case Stmt::BreakStmtClass: + K = CXCursor_BreakStmt; + break; + + case Stmt::ReturnStmtClass: + K = CXCursor_ReturnStmt; + break; + + case Stmt::AsmStmtClass: + K = CXCursor_AsmStmt; + break; + + case Stmt::ObjCAtTryStmtClass: + K = CXCursor_ObjCAtTryStmt; + break; + + case Stmt::ObjCAtCatchStmtClass: + K = CXCursor_ObjCAtCatchStmt; + break; + + case Stmt::ObjCAtFinallyStmtClass: + K = CXCursor_ObjCAtFinallyStmt; + break; + + case Stmt::ObjCAtThrowStmtClass: + K = CXCursor_ObjCAtThrowStmt; + break; + + case Stmt::ObjCAtSynchronizedStmtClass: + K = CXCursor_ObjCAtSynchronizedStmt; + break; + + case Stmt::ObjCAutoreleasePoolStmtClass: + K = CXCursor_ObjCAutoreleasePoolStmt; + break; + case Stmt::ObjCForCollectionStmtClass: + K = CXCursor_ObjCForCollectionStmt; + break; + case Stmt::CXXCatchStmtClass: - case Stmt::CXXTryStmtClass: - case Stmt::CXXForRangeStmtClass: + K = CXCursor_CXXCatchStmt; + break; + + case Stmt::CXXTryStmtClass: + K = CXCursor_CXXTryStmt; + break; + + case Stmt::CXXForRangeStmtClass: + K = CXCursor_CXXForRangeStmt; + break; + case Stmt::SEHTryStmtClass: + K = CXCursor_SEHTryStmt; + break; + case Stmt::SEHExceptStmtClass: + K = CXCursor_SEHExceptStmt; + break; + case Stmt::SEHFinallyStmtClass: + K = CXCursor_SEHFinallyStmt; + break; + + case Stmt::ArrayTypeTraitExprClass: + case Stmt::AsTypeExprClass: + case Stmt::AtomicExprClass: + case Stmt::BinaryConditionalOperatorClass: + case Stmt::BinaryTypeTraitExprClass: + case Stmt::CXXBindTemporaryExprClass: + case Stmt::CXXDefaultArgExprClass: + case Stmt::CXXScalarValueInitExprClass: + case Stmt::CXXUuidofExprClass: + case Stmt::ChooseExprClass: + case Stmt::DesignatedInitExprClass: + case Stmt::ExprWithCleanupsClass: + case Stmt::ExpressionTraitExprClass: + case Stmt::ExtVectorElementExprClass: + case Stmt::ImplicitCastExprClass: + case Stmt::ImplicitValueInitExprClass: case Stmt::MaterializeTemporaryExprClass: - K = CXCursor_UnexposedStmt; + case Stmt::ObjCIndirectCopyRestoreExprClass: + case Stmt::OffsetOfExprClass: + case Stmt::OpaqueValueExprClass: + case Stmt::ParenListExprClass: + case Stmt::PredefinedExprClass: + case Stmt::ShuffleVectorExprClass: + case Stmt::UnaryExprOrTypeTraitExprClass: + case Stmt::UnaryTypeTraitExprClass: + case Stmt::VAArgExprClass: + K = CXCursor_UnexposedExpr; + break; + + case Stmt::CompoundStmtClass: + K = CXCursor_CompoundStmt; break; - case Stmt::LabelStmtClass: - K = CXCursor_LabelStmt; + case Stmt::NullStmtClass: + K = CXCursor_NullStmt; break; - case Stmt::PredefinedExprClass: - case Stmt::IntegerLiteralClass: - case Stmt::FloatingLiteralClass: - case Stmt::ImaginaryLiteralClass: - case Stmt::StringLiteralClass: - case Stmt::CharacterLiteralClass: - case Stmt::ParenExprClass: + case Stmt::LabelStmtClass: + K = CXCursor_LabelStmt; + break; + + case Stmt::DeclStmtClass: + K = CXCursor_DeclStmt; + break; + + case Stmt::IntegerLiteralClass: + K = CXCursor_IntegerLiteral; + break; + + case Stmt::FloatingLiteralClass: + K = CXCursor_FloatingLiteral; + break; + + case Stmt::ImaginaryLiteralClass: + K = CXCursor_ImaginaryLiteral; + break; + + case Stmt::StringLiteralClass: + K = CXCursor_StringLiteral; + break; + + case Stmt::CharacterLiteralClass: + K = CXCursor_CharacterLiteral; + break; + + case Stmt::ParenExprClass: + K = CXCursor_ParenExpr; + break; + case Stmt::UnaryOperatorClass: - case Stmt::OffsetOfExprClass: - case Stmt::UnaryExprOrTypeTraitExprClass: - case Stmt::ArraySubscriptExprClass: - case Stmt::BinaryOperatorClass: + K = CXCursor_UnaryOperator; + break; + + case Stmt::CXXNoexceptExprClass: + K = CXCursor_UnaryExpr; + break; + + case Stmt::ArraySubscriptExprClass: + K = CXCursor_ArraySubscriptExpr; + break; + + case Stmt::BinaryOperatorClass: + K = CXCursor_BinaryOperator; + break; + case Stmt::CompoundAssignOperatorClass: - case Stmt::ConditionalOperatorClass: - case Stmt::BinaryConditionalOperatorClass: - case Stmt::ImplicitCastExprClass: + K = CXCursor_CompoundAssignOperator; + break; + + case Stmt::ConditionalOperatorClass: + K = CXCursor_ConditionalOperator; + break; + case Stmt::CStyleCastExprClass: - case Stmt::CompoundLiteralExprClass: - case Stmt::ExtVectorElementExprClass: - case Stmt::InitListExprClass: - case Stmt::DesignatedInitExprClass: - case Stmt::ImplicitValueInitExprClass: - case Stmt::ParenListExprClass: - case Stmt::VAArgExprClass: - case Stmt::AddrLabelExprClass: - case Stmt::StmtExprClass: - case Stmt::ChooseExprClass: + K = CXCursor_CStyleCastExpr; + break; + + case Stmt::CompoundLiteralExprClass: + K = CXCursor_CompoundLiteralExpr; + break; + + case Stmt::InitListExprClass: + K = CXCursor_InitListExpr; + break; + + case Stmt::AddrLabelExprClass: + K = CXCursor_AddrLabelExpr; + break; + + case Stmt::StmtExprClass: + K = CXCursor_StmtExpr; + break; + case Stmt::GenericSelectionExprClass: - case Stmt::GNUNullExprClass: - case Stmt::CXXStaticCastExprClass: - case Stmt::CXXDynamicCastExprClass: - case Stmt::CXXReinterpretCastExprClass: - case Stmt::CXXConstCastExprClass: + K = CXCursor_GenericSelectionExpr; + break; + + case Stmt::GNUNullExprClass: + K = CXCursor_GNUNullExpr; + break; + + case Stmt::CXXStaticCastExprClass: + K = CXCursor_CXXStaticCastExpr; + break; + + case Stmt::CXXDynamicCastExprClass: + K = CXCursor_CXXDynamicCastExpr; + break; + + case Stmt::CXXReinterpretCastExprClass: + K = CXCursor_CXXReinterpretCastExpr; + break; + + case Stmt::CXXConstCastExprClass: + K = CXCursor_CXXConstCastExpr; + break; + case Stmt::CXXFunctionalCastExprClass: - case Stmt::CXXTypeidExprClass: - case Stmt::CXXUuidofExprClass: - case Stmt::CXXBoolLiteralExprClass: - case Stmt::CXXNullPtrLiteralExprClass: - case Stmt::CXXThisExprClass: - case Stmt::CXXThrowExprClass: - case Stmt::CXXDefaultArgExprClass: - case Stmt::CXXScalarValueInitExprClass: - case Stmt::CXXNewExprClass: - case Stmt::CXXDeleteExprClass: - case Stmt::CXXPseudoDestructorExprClass: - case Stmt::UnresolvedLookupExprClass: - case Stmt::UnaryTypeTraitExprClass: - case Stmt::BinaryTypeTraitExprClass: - case Stmt::ArrayTypeTraitExprClass: - case Stmt::ExpressionTraitExprClass: - case Stmt::DependentScopeDeclRefExprClass: - case Stmt::CXXBindTemporaryExprClass: - case Stmt::ExprWithCleanupsClass: - case Stmt::CXXUnresolvedConstructExprClass: - case Stmt::CXXDependentScopeMemberExprClass: - case Stmt::UnresolvedMemberExprClass: - case Stmt::CXXNoexceptExprClass: - case Stmt::ObjCStringLiteralClass: - case Stmt::ObjCEncodeExprClass: - case Stmt::ObjCSelectorExprClass: - case Stmt::ObjCProtocolExprClass: - case Stmt::ObjCIsaExprClass: - case Stmt::ObjCIndirectCopyRestoreExprClass: + K = CXCursor_CXXFunctionalCastExpr; + break; + + case Stmt::CXXTypeidExprClass: + K = CXCursor_CXXTypeidExpr; + break; + + case Stmt::CXXBoolLiteralExprClass: + K = CXCursor_CXXBoolLiteralExpr; + break; + + case Stmt::CXXNullPtrLiteralExprClass: + K = CXCursor_CXXNullPtrLiteralExpr; + break; + + case Stmt::CXXThisExprClass: + K = CXCursor_CXXThisExpr; + break; + + case Stmt::CXXThrowExprClass: + K = CXCursor_CXXThrowExpr; + break; + + case Stmt::CXXNewExprClass: + K = CXCursor_CXXNewExpr; + break; + + case Stmt::CXXDeleteExprClass: + K = CXCursor_CXXDeleteExpr; + break; + + case Stmt::ObjCStringLiteralClass: + K = CXCursor_ObjCStringLiteral; + break; + + case Stmt::ObjCEncodeExprClass: + K = CXCursor_ObjCEncodeExpr; + break; + + case Stmt::ObjCSelectorExprClass: + K = CXCursor_ObjCSelectorExpr; + break; + + case Stmt::ObjCProtocolExprClass: + K = CXCursor_ObjCProtocolExpr; + break; + case Stmt::ObjCBridgedCastExprClass: - case Stmt::ShuffleVectorExprClass: - case Stmt::BlockExprClass: - case Stmt::OpaqueValueExprClass: + K = CXCursor_ObjCBridgedCastExpr; + break; + + case Stmt::BlockExprClass: + K = CXCursor_BlockExpr; + break; + case Stmt::PackExpansionExprClass: + K = CXCursor_PackExpansionExpr; + break; + case Stmt::SizeOfPackExprClass: - case Stmt::AsTypeExprClass: - K = CXCursor_UnexposedExpr; + K = CXCursor_SizeOfPackExpr; break; - - case Stmt::DeclRefExprClass: + case Stmt::BlockDeclRefExprClass: + case Stmt::DeclRefExprClass: + case Stmt::DependentScopeDeclRefExprClass: case Stmt::SubstNonTypeTemplateParmExprClass: case Stmt::SubstNonTypeTemplateParmPackExprClass: - // FIXME: UnresolvedLookupExpr? - // FIXME: DependentScopeDeclRefExpr? + case Stmt::UnresolvedLookupExprClass: K = CXCursor_DeclRefExpr; break; + case Stmt::CXXDependentScopeMemberExprClass: + case Stmt::CXXPseudoDestructorExprClass: case Stmt::MemberExprClass: + case Stmt::ObjCIsaExprClass: case Stmt::ObjCIvarRefExprClass: case Stmt::ObjCPropertyRefExprClass: - // FIXME: UnresolvedMemberExpr? - // FIXME: CXXDependentScopeMemberExpr? + case Stmt::UnresolvedMemberExprClass: K = CXCursor_MemberRefExpr; break; @@ -204,16 +426,28 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, case Stmt::CUDAKernelCallExprClass: case Stmt::CXXConstructExprClass: case Stmt::CXXTemporaryObjectExprClass: - // FIXME: CXXUnresolvedConstructExpr + case Stmt::CXXUnresolvedConstructExprClass: K = CXCursor_CallExpr; break; case Stmt::ObjCMessageExprClass: K = CXCursor_ObjCMessageExpr; - break; + int SelectorIdIndex = -1; + // Check if cursor points to a selector id. + if (RegionOfInterest.isValid() && + RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) { + SmallVector<SourceLocation, 16> SelLocs; + cast<ObjCMessageExpr>(S)->getSelectorLocs(SelLocs); + SmallVector<SourceLocation, 16>::iterator + I=std::find(SelLocs.begin(), SelLocs.end(),RegionOfInterest.getBegin()); + if (I != SelLocs.end()) + SelectorIdIndex = I - SelLocs.begin(); + } + CXCursor C = { K, 0, { Parent, S, TU } }; + return getSelectorIdentifierCursor(SelectorIdIndex, C); } - CXCursor C = { K, { Parent, S, TU } }; + CXCursor C = { K, 0, { Parent, S, TU } }; return C; } @@ -222,7 +456,7 @@ CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super, CXTranslationUnit TU) { assert(Super && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_ObjCSuperClassRef, { Super, RawLoc, TU } }; + CXCursor C = { CXCursor_ObjCSuperClassRef, 0, { Super, RawLoc, TU } }; return C; } @@ -239,7 +473,7 @@ CXCursor cxcursor::MakeCursorObjCProtocolRef(ObjCProtocolDecl *Super, CXTranslationUnit TU) { assert(Super && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_ObjCProtocolRef, { Super, RawLoc, TU } }; + CXCursor C = { CXCursor_ObjCProtocolRef, 0, { Super, RawLoc, TU } }; return C; } @@ -259,7 +493,7 @@ CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, return MakeCXCursorInvalid(CXCursor_InvalidCode); assert(TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } }; + CXCursor C = { CXCursor_ObjCClassRef, 0, { Class, RawLoc, TU } }; return C; } @@ -275,7 +509,7 @@ CXCursor cxcursor::MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, CXTranslationUnit TU) { assert(Type && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_TypeRef, { Type, RawLoc, TU } }; + CXCursor C = { CXCursor_TypeRef, 0, { Type, RawLoc, TU } }; return C; } @@ -292,7 +526,7 @@ CXCursor cxcursor::MakeCursorTemplateRef(TemplateDecl *Template, CXTranslationUnit TU) { assert(Template && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_TemplateRef, { Template, RawLoc, TU } }; + CXCursor C = { CXCursor_TemplateRef, 0, { Template, RawLoc, TU } }; return C; } @@ -310,7 +544,7 @@ CXCursor cxcursor::MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc, assert(NS && (isa<NamespaceDecl>(NS) || isa<NamespaceAliasDecl>(NS)) && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_NamespaceRef, { NS, RawLoc, TU } }; + CXCursor C = { CXCursor_NamespaceRef, 0, { NS, RawLoc, TU } }; return C; } @@ -327,7 +561,7 @@ CXCursor cxcursor::MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc, assert(Field && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_MemberRef, { Field, RawLoc, TU } }; + CXCursor C = { CXCursor_MemberRef, 0, { Field, RawLoc, TU } }; return C; } @@ -341,7 +575,7 @@ cxcursor::getCursorMemberRef(CXCursor C) { CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, CXTranslationUnit TU){ - CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } }; + CXCursor C = { CXCursor_CXXBaseSpecifier, 0, { B, 0, TU } }; return C; } @@ -352,7 +586,7 @@ CXXBaseSpecifier *cxcursor::getCursorCXXBaseSpecifier(CXCursor C) { CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range, CXTranslationUnit TU) { - CXCursor C = { CXCursor_PreprocessingDirective, + CXCursor C = { CXCursor_PreprocessingDirective, 0, { reinterpret_cast<void *>(Range.getBegin().getRawEncoding()), reinterpret_cast<void *>(Range.getEnd().getRawEncoding()), TU } @@ -362,15 +596,17 @@ CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range, SourceRange cxcursor::getCursorPreprocessingDirective(CXCursor C) { assert(C.kind == CXCursor_PreprocessingDirective); - return SourceRange(SourceLocation::getFromRawEncoding( + SourceRange Range = SourceRange(SourceLocation::getFromRawEncoding( reinterpret_cast<uintptr_t> (C.data[0])), SourceLocation::getFromRawEncoding( reinterpret_cast<uintptr_t> (C.data[1]))); + ASTUnit *TU = getCursorASTUnit(C); + return TU->mapRangeFromPreamble(Range); } CXCursor cxcursor::MakeMacroDefinitionCursor(MacroDefinition *MI, CXTranslationUnit TU) { - CXCursor C = { CXCursor_MacroDefinition, { MI, 0, TU } }; + CXCursor C = { CXCursor_MacroDefinition, 0, { MI, 0, TU } }; return C; } @@ -381,7 +617,7 @@ MacroDefinition *cxcursor::getCursorMacroDefinition(CXCursor C) { CXCursor cxcursor::MakeMacroExpansionCursor(MacroExpansion *MI, CXTranslationUnit TU) { - CXCursor C = { CXCursor_MacroExpansion, { MI, 0, TU } }; + CXCursor C = { CXCursor_MacroExpansion, 0, { MI, 0, TU } }; return C; } @@ -392,7 +628,7 @@ MacroExpansion *cxcursor::getCursorMacroExpansion(CXCursor C) { CXCursor cxcursor::MakeInclusionDirectiveCursor(InclusionDirective *ID, CXTranslationUnit TU) { - CXCursor C = { CXCursor_InclusionDirective, { ID, 0, TU } }; + CXCursor C = { CXCursor_InclusionDirective, 0, { ID, 0, TU } }; return C; } @@ -406,7 +642,7 @@ CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, assert(Label && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); - CXCursor C = { CXCursor_LabelRef, { Label, RawLoc, TU } }; + CXCursor C = { CXCursor_LabelRef, 0, { Label, RawLoc, TU } }; return C; } @@ -424,7 +660,7 @@ CXCursor cxcursor::MakeCursorOverloadedDeclRef(OverloadExpr *E, OverloadedDeclRefStorage Storage(E); void *RawLoc = reinterpret_cast<void *>(E->getNameLoc().getRawEncoding()); CXCursor C = { - CXCursor_OverloadedDeclRef, + CXCursor_OverloadedDeclRef, 0, { Storage.getOpaqueValue(), RawLoc, TU } }; return C; @@ -437,7 +673,7 @@ CXCursor cxcursor::MakeCursorOverloadedDeclRef(Decl *D, void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); OverloadedDeclRefStorage Storage(D); CXCursor C = { - CXCursor_OverloadedDeclRef, + CXCursor_OverloadedDeclRef, 0, { Storage.getOpaqueValue(), RawLoc, TU } }; return C; @@ -450,7 +686,7 @@ CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name, void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate()); CXCursor C = { - CXCursor_OverloadedDeclRef, + CXCursor_OverloadedDeclRef, 0, { Storage.getOpaqueValue(), RawLoc, TU } }; return C; @@ -502,6 +738,173 @@ CXTranslationUnit cxcursor::getCursorTU(CXCursor Cursor) { return static_cast<CXTranslationUnit>(Cursor.data[2]); } +static void CollectOverriddenMethods(CXTranslationUnit TU, + DeclContext *Ctx, + ObjCMethodDecl *Method, + SmallVectorImpl<CXCursor> &Methods) { + if (!Ctx) + return; + + // If we have a class or category implementation, jump straight to the + // interface. + if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx)) + return CollectOverriddenMethods(TU, Impl->getClassInterface(), + Method, Methods); + + ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx); + if (!Container) + return; + + // Check whether we have a matching method at this level. + if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + if (Method != Overridden) { + // We found an override at this level; there is no need to look + // into other protocols or categories. + Methods.push_back(MakeCXCursor(Overridden, TU)); + return; + } + + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), + PEnd = Protocol->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethods(TU, *P, Method, Methods); + } + + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { + for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethods(TU, *P, Method, Methods); + } + + if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { + for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), + PEnd = Interface->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethods(TU, *P, Method, Methods); + + for (ObjCCategoryDecl *Category = Interface->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + CollectOverriddenMethods(TU, Category, Method, Methods); + + // We only look into the superclass if we haven't found anything yet. + if (Methods.empty()) + if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) + return CollectOverriddenMethods(TU, Super, Method, Methods); + } +} + +void cxcursor::getOverriddenCursors(CXCursor cursor, + SmallVectorImpl<CXCursor> &overridden) { + if (!clang_isDeclaration(cursor.kind)) + return; + + Decl *D = getCursorDecl(cursor); + if (!D) + return; + + // Handle C++ member functions. + CXTranslationUnit TU = getCursorTU(cursor); + if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { + for (CXXMethodDecl::method_iterator + M = CXXMethod->begin_overridden_methods(), + MEnd = CXXMethod->end_overridden_methods(); + M != MEnd; ++M) + overridden.push_back(MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU)); + return; + } + + ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); + if (!Method) + return; + + // Handle Objective-C methods. + CollectOverriddenMethods(TU, Method->getDeclContext(), Method, overridden); +} + +std::pair<int, SourceLocation> +cxcursor::getSelectorIdentifierIndexAndLoc(CXCursor cursor) { + if (cursor.kind == CXCursor_ObjCMessageExpr) { + if (cursor.xdata != -1) + return std::make_pair(cursor.xdata, + cast<ObjCMessageExpr>(getCursorExpr(cursor)) + ->getSelectorLoc(cursor.xdata)); + } else if (cursor.kind == CXCursor_ObjCClassMethodDecl || + cursor.kind == CXCursor_ObjCInstanceMethodDecl) { + if (cursor.xdata != -1) + return std::make_pair(cursor.xdata, + cast<ObjCMethodDecl>(getCursorDecl(cursor)) + ->getSelectorLoc(cursor.xdata)); + } + + return std::make_pair(-1, SourceLocation()); +} + +CXCursor cxcursor::getSelectorIdentifierCursor(int SelIdx, CXCursor cursor) { + CXCursor newCursor = cursor; + + if (cursor.kind == CXCursor_ObjCMessageExpr) { + if (SelIdx == -1 || + unsigned(SelIdx) >= cast<ObjCMessageExpr>(getCursorExpr(cursor)) + ->getNumSelectorLocs()) + newCursor.xdata = -1; + else + newCursor.xdata = SelIdx; + } else if (cursor.kind == CXCursor_ObjCClassMethodDecl || + cursor.kind == CXCursor_ObjCInstanceMethodDecl) { + if (SelIdx == -1 || + unsigned(SelIdx) >= cast<ObjCMethodDecl>(getCursorDecl(cursor)) + ->getNumSelectorLocs()) + newCursor.xdata = -1; + else + newCursor.xdata = SelIdx; + } + + return newCursor; +} + +CXCursor cxcursor::getTypeRefCursor(CXCursor cursor) { + if (cursor.kind != CXCursor_CallExpr) + return cursor; + + if (cursor.xdata == 0) + return cursor; + + Expr *E = getCursorExpr(cursor); + TypeSourceInfo *Type = 0; + if (CXXUnresolvedConstructExpr * + UnCtor = dyn_cast<CXXUnresolvedConstructExpr>(E)) { + Type = UnCtor->getTypeSourceInfo(); + } else if (CXXTemporaryObjectExpr *Tmp = dyn_cast<CXXTemporaryObjectExpr>(E)){ + Type = Tmp->getTypeSourceInfo(); + } + + if (!Type) + return cursor; + + CXTranslationUnit TU = getCursorTU(cursor); + QualType Ty = Type->getType(); + TypeLoc TL = Type->getTypeLoc(); + SourceLocation Loc = TL.getBeginLoc(); + + if (const ElaboratedType *ElabT = Ty->getAs<ElaboratedType>()) { + Ty = ElabT->getNamedType(); + ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(TL); + Loc = ElabTL.getNamedTypeLoc().getBeginLoc(); + } + + if (const TypedefType *Typedef = Ty->getAs<TypedefType>()) + return MakeCursorTypeRef(Typedef->getDecl(), Loc, TU); + if (const TagType *Tag = Ty->getAs<TagType>()) + return MakeCursorTypeRef(Tag->getDecl(), Loc, TU); + if (const TemplateTypeParmType *TemplP = Ty->getAs<TemplateTypeParmType>()) + return MakeCursorTypeRef(TemplP->getDecl(), Loc, TU); + + return cursor; +} + bool cxcursor::operator==(CXCursor X, CXCursor Y) { return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] && X.data[2] == Y.data[2]; @@ -515,6 +918,22 @@ bool cxcursor::isFirstInDeclGroup(CXCursor C) { } //===----------------------------------------------------------------------===// +// libclang CXCursor APIs +//===----------------------------------------------------------------------===// + +extern "C" { + +int clang_Cursor_isNull(CXCursor cursor) { + return clang_equalCursors(cursor, clang_getNullCursor()); +} + +CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor cursor) { + return getCursorTU(cursor); +} + +} // end: extern "C" + +//===----------------------------------------------------------------------===// // CXCursorSet. //===----------------------------------------------------------------------===// @@ -577,4 +996,40 @@ unsigned clang_CXCursorSet_insert(CXCursorSet set, CXCursor cursor) { entry = 1; return flag; } + +CXCompletionString clang_getCursorCompletionString(CXCursor cursor) { + enum CXCursorKind kind = clang_getCursorKind(cursor); + if (clang_isDeclaration(kind)) { + Decl *decl = getCursorDecl(cursor); + if (isa<NamedDecl>(decl)) { + NamedDecl *namedDecl = (NamedDecl *)decl; + ASTUnit *unit = getCursorASTUnit(cursor); + if (unit->hasSema()) { + Sema &S = unit->getSema(); + CodeCompletionAllocator *Allocator + = unit->getCursorCompletionAllocator().getPtr(); + CodeCompletionResult Result(namedDecl); + CodeCompletionString *String + = Result.CreateCodeCompletionString(S, *Allocator); + return String; + } + } + } + else if (kind == CXCursor_MacroDefinition) { + MacroDefinition *definition = getCursorMacroDefinition(cursor); + const IdentifierInfo *MacroInfo = definition->getName(); + ASTUnit *unit = getCursorASTUnit(cursor); + if (unit->hasSema()) { + Sema &S = unit->getSema(); + CodeCompletionAllocator *Allocator + = unit->getCursorCompletionAllocator().getPtr(); + CodeCompletionResult Result(const_cast<IdentifierInfo *>(MacroInfo)); + CodeCompletionString *String + = Result.CreateCodeCompletionString(S, *Allocator); + return String; + } + } + return NULL; +} + } // end: extern "C" diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h index 68d09e7..e402d7f 100644 --- a/tools/libclang/CXCursor.h +++ b/tools/libclang/CXCursor.h @@ -43,13 +43,17 @@ class TemplateName; class TypeDecl; namespace cxcursor { + +CXCursor getCursor(CXTranslationUnit, SourceLocation); CXCursor MakeCXCursor(const clang::Attr *A, clang::Decl *Parent, CXTranslationUnit TU); CXCursor MakeCXCursor(clang::Decl *D, CXTranslationUnit TU, + SourceRange RegionOfInterest = SourceRange(), bool FirstInDeclGroup = true); CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent, - CXTranslationUnit TU); + CXTranslationUnit TU, + SourceRange RegionOfInterest = SourceRange()); CXCursor MakeCXCursorInvalid(CXCursorKind K); /// \brief Create an Objective-C superclass reference at the given location. @@ -189,7 +193,36 @@ Decl *getCursorParentDecl(CXCursor Cursor); ASTContext &getCursorContext(CXCursor Cursor); ASTUnit *getCursorASTUnit(CXCursor Cursor); CXTranslationUnit getCursorTU(CXCursor Cursor); - + +void getOverriddenCursors(CXCursor cursor, + SmallVectorImpl<CXCursor> &overridden); + +/// \brief Returns a index/location pair for a selector identifier if the cursor +/// points to one. +std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor); +static inline int getSelectorIdentifierIndex(CXCursor cursor) { + return getSelectorIdentifierIndexAndLoc(cursor).first; +} +static inline SourceLocation getSelectorIdentifierLoc(CXCursor cursor) { + return getSelectorIdentifierIndexAndLoc(cursor).second; +} + +CXCursor getSelectorIdentifierCursor(int SelIdx, CXCursor cursor); + +static inline CXCursor getTypeRefedCallExprCursor(CXCursor cursor) { + CXCursor newCursor = cursor; + if (cursor.kind == CXCursor_CallExpr) + newCursor.xdata = 1; + return newCursor; +} + +CXCursor getTypeRefCursor(CXCursor cursor); + +/// \brief Generate a USR for \arg D and put it in \arg Buf. +/// \returns true if no USR was computed or the result should be ignored, +/// false otherwise. +bool getDeclCursorUSR(Decl *D, SmallVectorImpl<char> &Buf); + bool operator==(CXCursor X, CXCursor Y); inline bool operator!=(CXCursor X, CXCursor Y) { diff --git a/tools/libclang/CXString.cpp b/tools/libclang/CXString.cpp index f2a6b09..bb09cd5 100644 --- a/tools/libclang/CXString.cpp +++ b/tools/libclang/CXString.cpp @@ -41,7 +41,7 @@ CXString cxstring::createCXString(const char *String, bool DupString){ return Str; } -CXString cxstring::createCXString(llvm::StringRef String, bool DupString) { +CXString cxstring::createCXString(StringRef String, bool DupString) { CXString Result; if (DupString || (!String.empty() && String.data()[String.size()] != 0)) { char *Spelling = (char *)malloc(String.size() + 1); @@ -101,6 +101,10 @@ void cxstring::disposeCXStringBuf(CXStringBuf *buf) { static_cast<CXStringPool*>(buf->TU->StringPool)->push_back(buf); } +bool cxstring::isManagedByPool(CXString str) { + return ((CXStringFlag) str.private_flags) == CXS_StringBuf; +} + //===----------------------------------------------------------------------===// // libClang public APIs. //===----------------------------------------------------------------------===// diff --git a/tools/libclang/CXString.h b/tools/libclang/CXString.h index f03a6b2..d36c7c1 100644 --- a/tools/libclang/CXString.h +++ b/tools/libclang/CXString.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_CXSTRING_H #include "clang-c/Index.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" @@ -31,7 +32,7 @@ struct CXStringBuf { CXString createCXString(const char *String, bool DupString = false); /// \brief Create a CXString object from a StringRef. -CXString createCXString(llvm::StringRef String, bool DupString = true); +CXString createCXString(StringRef String, bool DupString = true); /// \brief Create a CXString object that is backed by a string buffer. CXString createCXString(CXStringBuf *buf); @@ -46,6 +47,9 @@ CXStringBuf *getCXStringBuf(CXTranslationUnit TU); void disposeCXStringBuf(CXStringBuf *buf); +/// \brief Returns true if the CXString data is managed by a pool. +bool isManagedByPool(CXString str); + } } diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h index 6df85b7..2b8f977 100644 --- a/tools/libclang/CXTranslationUnit.h +++ b/tools/libclang/CXTranslationUnit.h @@ -21,4 +21,13 @@ struct CXTranslationUnitImpl { }; } +namespace clang { + class ASTUnit; + +namespace cxtu { + +CXTranslationUnitImpl *MakeCXTranslationUnit(ASTUnit *TU); + +}} // end namespace clang::cxtu + #endif diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 45c7346..0e62e27 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -84,6 +84,7 @@ static CXTypeKind GetTypeKind(QualType T) { TKCASE(ObjCObjectPointer); TKCASE(FunctionNoProto); TKCASE(FunctionProto); + TKCASE(ConstantArray); default: return CXType_Unexposed; } @@ -330,6 +331,7 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) { TKIND(ObjCObjectPointer); TKIND(FunctionNoProto); TKIND(FunctionProto); + TKIND(ConstantArray); } #undef TKIND return cxstring::createCXString(s); @@ -373,6 +375,40 @@ unsigned clang_isPODType(CXType X) { return T.isPODType(AU->getASTContext()) ? 1 : 0; } +CXType clang_getArrayElementType(CXType CT) { + QualType ET = QualType(); + QualType T = GetQualType(CT); + const Type *TP = T.getTypePtrOrNull(); + + if (TP) { + switch (TP->getTypeClass()) { + case Type::ConstantArray: + ET = cast<ConstantArrayType> (TP)->getElementType(); + break; + default: + break; + } + } + return MakeCXType(ET, GetTU(CT)); +} + +long long clang_getArraySize(CXType CT) { + long long result = -1; + QualType T = GetQualType(CT); + const Type *TP = T.getTypePtrOrNull(); + + if (TP) { + switch (TP->getTypeClass()) { + case Type::ConstantArray: + result = cast<ConstantArrayType> (TP)->getSize().getSExtValue(); + break; + default: + break; + } + } + return result; +} + CXString clang_getDeclObjCTypeEncoding(CXCursor C) { if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl)) return cxstring::createCXString(""); diff --git a/tools/libclang/Index_Internal.h b/tools/libclang/Index_Internal.h new file mode 100644 index 0000000..df54d7c --- /dev/null +++ b/tools/libclang/Index_Internal.h @@ -0,0 +1,43 @@ +//===- CXString.h - Routines for manipulating CXStrings -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines routines for manipulating CXStrings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBCLANG_INDEX_INTERNAL_H +#define LLVM_LIBCLANG_INDEX_INTERNAL_H + +#include "clang-c/Index.h" + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#if __has_feature(blocks) + +#define INVOKE_BLOCK2(block, arg1, arg2) block(arg1, arg2) + +#else +// If we are compiled with a compiler that doesn't have native blocks support, +// define and call the block manually. + +#define INVOKE_BLOCK2(block, arg1, arg2) block->invoke(block, arg1, arg2) + +typedef struct _CXCursorAndRangeVisitorBlock { + void *isa; + int flags; + int reserved; + enum CXVisitorResult (*invoke)(_CXCursorAndRangeVisitorBlock *, + CXCursor, CXSourceRange); +} *CXCursorAndRangeVisitorBlock; + +#endif // !__has_feature(blocks) + +#endif diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports deleted file mode 100644 index bfc5be9..0000000 --- a/tools/libclang/libclang.darwin.exports +++ /dev/null @@ -1,143 +0,0 @@ -_clang_CXCursorSet_contains -_clang_CXCursorSet_insert -_clang_CXXMethod_isStatic -_clang_CXXMethod_isVirtual -_clang_annotateTokens -_clang_codeCompleteAt -_clang_codeCompleteGetDiagnostic -_clang_codeCompleteGetNumDiagnostics -_clang_codeCompleteGetContexts -_clang_constructUSR_ObjCCategory -_clang_constructUSR_ObjCClass -_clang_constructUSR_ObjCIvar -_clang_constructUSR_ObjCMethod -_clang_constructUSR_ObjCProperty -_clang_constructUSR_ObjCProtocol -_clang_createCXCursorSet -_clang_createIndex -_clang_createTranslationUnit -_clang_createTranslationUnitFromSourceFile -_clang_defaultCodeCompleteOptions -_clang_defaultDiagnosticDisplayOptions -_clang_defaultEditingTranslationUnitOptions -_clang_defaultReparseOptions -_clang_defaultSaveOptions -_clang_disposeCXCursorSet -_clang_disposeCXTUResourceUsage -_clang_disposeCodeCompleteResults -_clang_disposeDiagnostic -_clang_disposeIndex -_clang_disposeOverriddenCursors -_clang_disposeString -_clang_disposeTokens -_clang_disposeTranslationUnit -_clang_enableStackTraces -_clang_equalCursors -_clang_equalLocations -_clang_equalTypes -_clang_executeOnThread -_clang_formatDiagnostic -_clang_getCString -_clang_getCXTUResourceUsage -_clang_getCXXAccessSpecifier -_clang_getCanonicalCursor -_clang_getCanonicalType -_clang_getClangVersion -_clang_getCompletionAvailability -_clang_getCompletionChunkCompletionString -_clang_getCompletionChunkKind -_clang_getCompletionChunkText -_clang_getCompletionPriority -_clang_getCursor -_clang_getCursorAvailability -_clang_getCursorDefinition -_clang_getCursorDisplayName -_clang_getCursorExtent -_clang_getCursorKind -_clang_getCursorKindSpelling -_clang_getCursorLanguage -_clang_getCursorLexicalParent -_clang_getCursorLinkage -_clang_getCursorLocation -_clang_getCursorReferenced -_clang_getCursorResultType -_clang_getCursorSemanticParent -_clang_getCursorSpelling -_clang_getCursorType -_clang_getCursorUSR -_clang_getDeclObjCTypeEncoding -_clang_getDefinitionSpellingAndExtent -_clang_getDiagnostic -_clang_getDiagnosticCategory -_clang_getDiagnosticCategoryName -_clang_getDiagnosticFixIt -_clang_getDiagnosticLocation -_clang_getDiagnosticNumFixIts -_clang_getDiagnosticNumRanges -_clang_getDiagnosticOption -_clang_getDiagnosticRange -_clang_getDiagnosticSeverity -_clang_getDiagnosticSpelling -_clang_getFile -_clang_getFileName -_clang_getFileTime -_clang_getIBOutletCollectionType -_clang_getIncludedFile -_clang_getInclusions -_clang_getInstantiationLocation -_clang_getLocation -_clang_getLocationForOffset -_clang_getNullCursor -_clang_getNullLocation -_clang_getNullRange -_clang_getNumCompletionChunks -_clang_getNumDiagnostics -_clang_getNumOverloadedDecls -_clang_getOverloadedDecl -_clang_getOverriddenCursors -_clang_getPointeeType -_clang_getRange -_clang_getRangeEnd -_clang_getRangeStart -_clang_getResultType -_clang_getSpecializedCursorTemplate -_clang_getSpellingLocation -_clang_getTUResourceUsageName -_clang_getTemplateCursorKind -_clang_getTokenExtent -_clang_getTokenKind -_clang_getTokenLocation -_clang_getTokenSpelling -_clang_getTranslationUnitCursor -_clang_getTranslationUnitSpelling -_clang_getTypeDeclaration -_clang_getTypeKindSpelling -_clang_hashCursor -_clang_isAttribute -_clang_isConstQualifiedType -_clang_isCursorDefinition -_clang_isDeclaration -_clang_isExpression -_clang_isFileMultipleIncludeGuarded -_clang_isInvalid -_clang_isPODType -_clang_isPreprocessing -_clang_isReference -_clang_isRestrictQualifiedType -_clang_isStatement -_clang_isTranslationUnit -_clang_isUnexposed -_clang_isVirtualBase -_clang_isVolatileQualifiedType -_clang_parseTranslationUnit -_clang_reparseTranslationUnit -_clang_saveTranslationUnit -_clang_sortCodeCompletionResults -_clang_toggleCrashRecovery -_clang_tokenize -_clang_visitChildren -_clang_visitChildrenWithBlock -_clang_getRemappings -_clang_remap_getNumFiles -_clang_remap_getFilenames -_clang_remap_dispose diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 47b7030..989ed83 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -4,9 +4,12 @@ clang_CXXMethod_isStatic clang_CXXMethod_isVirtual clang_annotateTokens clang_codeCompleteAt +clang_codeCompleteGetContainerKind +clang_codeCompleteGetContainerUSR +clang_codeCompleteGetContexts clang_codeCompleteGetDiagnostic clang_codeCompleteGetNumDiagnostics -clang_codeCompleteGetContexts +clang_codeCompleteGetObjCSelector clang_constructUSR_ObjCCategory clang_constructUSR_ObjCClass clang_constructUSR_ObjCIvar @@ -17,6 +20,8 @@ clang_createCXCursorSet clang_createIndex clang_createTranslationUnit clang_createTranslationUnitFromSourceFile +clang_Cursor_getTranslationUnit +clang_Cursor_isNull clang_defaultCodeCompleteOptions clang_defaultDiagnosticDisplayOptions clang_defaultEditingTranslationUnitOptions @@ -34,9 +39,14 @@ clang_disposeTranslationUnit clang_enableStackTraces clang_equalCursors clang_equalLocations +clang_equalRanges clang_equalTypes clang_executeOnThread +clang_findReferencesInFile +clang_findReferencesInFileWithBlock clang_formatDiagnostic +clang_getArrayElementType +clang_getArraySize clang_getCString clang_getCXTUResourceUsage clang_getCXXAccessSpecifier @@ -44,12 +54,15 @@ clang_getCanonicalCursor clang_getCanonicalType clang_getClangVersion clang_getCompletionAvailability +clang_getCompletionAnnotation clang_getCompletionChunkCompletionString clang_getCompletionChunkKind clang_getCompletionChunkText +clang_getCompletionNumAnnotations clang_getCompletionPriority clang_getCursor clang_getCursorAvailability +clang_getCursorCompletionString clang_getCursorDefinition clang_getCursorDisplayName clang_getCursorExtent @@ -59,6 +72,7 @@ clang_getCursorLanguage clang_getCursorLexicalParent clang_getCursorLinkage clang_getCursorLocation +clang_getCursorReferenceNameRange clang_getCursorReferenced clang_getCursorResultType clang_getCursorSemanticParent @@ -96,9 +110,11 @@ clang_getNumOverloadedDecls clang_getOverloadedDecl clang_getOverriddenCursors clang_getPointeeType +clang_getPresumedLocation clang_getRange clang_getRangeEnd clang_getRangeStart +clang_getRemappings clang_getResultType clang_getSpecializedCursorTemplate clang_getSpellingLocation @@ -130,6 +146,10 @@ clang_isUnexposed clang_isVirtualBase clang_isVolatileQualifiedType clang_parseTranslationUnit +clang_Range_isNull +clang_remap_dispose +clang_remap_getFilenames +clang_remap_getNumFiles clang_reparseTranslationUnit clang_saveTranslationUnit clang_sortCodeCompletionResults @@ -137,7 +157,3 @@ clang_toggleCrashRecovery clang_tokenize clang_visitChildren clang_visitChildrenWithBlock -clang_getRemappings -clang_remap_getNumFiles -clang_remap_getFilenames -clang_remap_dispose diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer index 5697b21..c39e417 100755 --- a/tools/scan-build/ccc-analyzer +++ b/tools/scan-build/ccc-analyzer @@ -55,7 +55,10 @@ my $ResultFile; # Remove any stale files at exit. END { - if (defined $CleanupFile && -z $CleanupFile) { + if (defined $ResultFile && -z $ResultFile) { + `rm -f $ResultFile`; + } + if (defined $CleanupFile) { `rm -f $CleanupFile`; } } @@ -365,9 +368,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 = ( @@ -380,14 +385,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. ##----------------------------------------------------------------------------## @@ -621,9 +623,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; @@ -632,7 +634,10 @@ if ($Action eq 'compile' or $Action eq 'link') { my ($h, $f) = tempfile("report-XXXXXX", SUFFIX => ".plist", DIR => $HtmlDir); $ResultFile = $f; - $CleanupFile = $f; + # If the HtmlDir is not set, we sould clean up the plist files. + if (!defined $HtmlDir || -z $HtmlDir) { + $CleanupFile = $f; + } } } diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index f835ca3..dae86f4 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -61,7 +61,7 @@ sub DiagCrashes { Diag ("The analyzer encountered problems on some source files.\n"); Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n"); Diag ("Please consider submitting a bug report using these files:\n"); - Diag (" http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n") + Diag (" http://clang-analyzer.llvm.org/filing_bugs.html\n") } sub DieDiag { @@ -802,7 +802,7 @@ ENDTEXT } print OUT "</table>\n"; } - print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n"; + print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang-analyzer.llvm.org/filing_bugs.html\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n"; } print OUT "</body></html>\n"; |