diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
commit | 173a4f43a911175643bda81ee675e8d9269056ea (patch) | |
tree | 47df2c12b57214af6c31e47404b005675b8b7ffc /tools/c-index-test/c-index-test.c | |
parent | 88f7a7d5251a2d813460274c92decc143a11569b (diff) | |
download | FreeBSD-src-173a4f43a911175643bda81ee675e8d9269056ea.zip FreeBSD-src-173a4f43a911175643bda81ee675e8d9269056ea.tar.gz |
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_350/final@216957
Diffstat (limited to 'tools/c-index-test/c-index-test.c')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 553 |
1 files changed, 390 insertions, 163 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 90a6528..07be22a 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1,8 +1,10 @@ /* c-index-test.c */ +#include "clang/Config/config.h" #include "clang-c/Index.h" #include "clang-c/CXCompilationDatabase.h" -#include "llvm/Config/config.h" +#include "clang-c/BuildSystem.h" +#include "clang-c/Documentation.h" #include <ctype.h> #include <stdlib.h> #include <stdio.h> @@ -78,8 +80,33 @@ static unsigned getDefaultParsingOptions() { return options; } +/** \brief Returns 0 in case of success, non-zero in case of a failure. */ static int checkForErrors(CXTranslationUnit TU); +static void describeLibclangFailure(enum CXErrorCode Err) { + switch (Err) { + case CXError_Success: + fprintf(stderr, "Success\n"); + return; + + case CXError_Failure: + fprintf(stderr, "Failure (no details available)\n"); + return; + + case CXError_Crashed: + fprintf(stderr, "Failure: libclang crashed\n"); + return; + + case CXError_InvalidArguments: + fprintf(stderr, "Failure: invalid arguments passed to a libclang routine\n"); + return; + + case CXError_ASTReadError: + fprintf(stderr, "Failure: AST deserialization error occurred\n"); + return; + } +} + static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column, unsigned end_line, unsigned end_column) { fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column, @@ -88,10 +115,11 @@ static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column, static unsigned CreateTranslationUnit(CXIndex Idx, const char *file, CXTranslationUnit *TU) { - - *TU = clang_createTranslationUnit(Idx, file); - if (!*TU) { + enum CXErrorCode Err = clang_createTranslationUnit2(Idx, file, TU); + if (Err != CXError_Success) { fprintf(stderr, "Unable to load translation unit from '%s'!\n", file); + describeLibclangFailure(Err); + *TU = 0; return 0; } return 1; @@ -107,20 +135,25 @@ void free_remapped_files(struct CXUnsavedFile *unsaved_files, free(unsaved_files); } -int parse_remapped_files(int argc, const char **argv, int start_arg, - struct CXUnsavedFile **unsaved_files, - int *num_unsaved_files) { +static int parse_remapped_files_with_opt(const char *opt_name, + int argc, const char **argv, + int start_arg, + struct CXUnsavedFile **unsaved_files, + int *num_unsaved_files) { int i; int arg; - int prefix_len = strlen("-remap-file="); + int prefix_len = strlen(opt_name); + int arg_indices[20]; *unsaved_files = 0; *num_unsaved_files = 0; /* Count the number of remapped files. */ for (arg = start_arg; arg < argc; ++arg) { - if (strncmp(argv[arg], "-remap-file=", prefix_len)) - break; + if (strncmp(argv[arg], opt_name, prefix_len)) + continue; + assert(*num_unsaved_files < (int)(sizeof(arg_indices)/sizeof(int))); + arg_indices[*num_unsaved_files] = arg; ++*num_unsaved_files; } @@ -130,17 +163,17 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, *unsaved_files = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * *num_unsaved_files); - for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) { + for (i = 0; i != *num_unsaved_files; ++i) { struct CXUnsavedFile *unsaved = *unsaved_files + i; - const char *arg_string = argv[arg] + prefix_len; + const char *arg_string = argv[arg_indices[i]] + prefix_len; int filename_len; char *filename; char *contents; FILE *to_file; - const char *semi = strchr(arg_string, ';'); - if (!semi) { + const char *sep = strchr(arg_string, ','); + if (!sep) { fprintf(stderr, - "error: -remap-file=from;to argument is missing semicolon\n"); + "error: %sfrom:to argument is missing comma\n", opt_name); free_remapped_files(*unsaved_files, i); *unsaved_files = 0; *num_unsaved_files = 0; @@ -148,10 +181,10 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, } /* Open the file that we're remapping to. */ - to_file = fopen(semi + 1, "rb"); + to_file = fopen(sep + 1, "rb"); if (!to_file) { fprintf(stderr, "error: cannot open file %s that we are remapping to\n", - semi + 1); + sep + 1); free_remapped_files(*unsaved_files, i); *unsaved_files = 0; *num_unsaved_files = 0; @@ -167,7 +200,7 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, contents = (char *)malloc(unsaved->Length + 1); if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) { fprintf(stderr, "error: unexpected %s reading 'to' file %s\n", - (feof(to_file) ? "EOF" : "error"), semi + 1); + (feof(to_file) ? "EOF" : "error"), sep + 1); fclose(to_file); free_remapped_files(*unsaved_files, i); free(contents); @@ -182,7 +215,7 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, fclose(to_file); /* Copy the file name that we're remapping from. */ - filename_len = semi - arg_string; + filename_len = sep - arg_string; filename = (char *)malloc(filename_len + 1); memcpy(filename, arg_string, filename_len); filename[filename_len] = 0; @@ -192,6 +225,48 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, return 0; } +static int parse_remapped_files(int argc, const char **argv, int start_arg, + struct CXUnsavedFile **unsaved_files, + int *num_unsaved_files) { + return parse_remapped_files_with_opt("-remap-file=", argc, argv, start_arg, + unsaved_files, num_unsaved_files); +} + +static int parse_remapped_files_with_try(int try_idx, + int argc, const char **argv, + int start_arg, + struct CXUnsavedFile **unsaved_files, + int *num_unsaved_files) { + struct CXUnsavedFile *unsaved_files_no_try_idx; + int num_unsaved_files_no_try_idx; + struct CXUnsavedFile *unsaved_files_try_idx; + int num_unsaved_files_try_idx; + int ret; + char opt_name[32]; + + ret = parse_remapped_files(argc, argv, start_arg, + &unsaved_files_no_try_idx, &num_unsaved_files_no_try_idx); + if (ret) + return ret; + + sprintf(opt_name, "-remap-file-%d=", try_idx); + ret = parse_remapped_files_with_opt(opt_name, argc, argv, start_arg, + &unsaved_files_try_idx, &num_unsaved_files_try_idx); + if (ret) + return ret; + + *num_unsaved_files = num_unsaved_files_no_try_idx + num_unsaved_files_try_idx; + *unsaved_files + = (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx, + sizeof(struct CXUnsavedFile) * + *num_unsaved_files); + memcpy(*unsaved_files + num_unsaved_files_no_try_idx, + unsaved_files_try_idx, sizeof(struct CXUnsavedFile) * + num_unsaved_files_try_idx); + free(unsaved_files_try_idx); + return 0; +} + static const char *parse_comments_schema(int argc, const char **argv) { const char *CommentsSchemaArg = "-comments-xml-schema="; const char *CommentSchemaFile = NULL; @@ -467,33 +542,23 @@ static void DumpCXComment(CXComment Comment) { printf("]"); } -typedef struct { - const char *CommentSchemaFile; +static void ValidateCommentXML(const char *Str, const char *CommentSchemaFile) { #ifdef CLANG_HAVE_LIBXML xmlRelaxNGParserCtxtPtr RNGParser; xmlRelaxNGPtr Schema; -#endif -} CommentXMLValidationData; - -static void ValidateCommentXML(const char *Str, - CommentXMLValidationData *ValidationData) { -#ifdef CLANG_HAVE_LIBXML xmlDocPtr Doc; xmlRelaxNGValidCtxtPtr ValidationCtxt; int status; - if (!ValidationData || !ValidationData->CommentSchemaFile) + if (!CommentSchemaFile) return; - if (!ValidationData->RNGParser) { - ValidationData->RNGParser = - xmlRelaxNGNewParserCtxt(ValidationData->CommentSchemaFile); - ValidationData->Schema = xmlRelaxNGParse(ValidationData->RNGParser); - } - if (!ValidationData->RNGParser) { + RNGParser = xmlRelaxNGNewParserCtxt(CommentSchemaFile); + if (!RNGParser) { printf(" libXMLError"); return; } + Schema = xmlRelaxNGParse(RNGParser); Doc = xmlParseDoc((const xmlChar *) Str); @@ -503,7 +568,7 @@ static void ValidateCommentXML(const char *Str, return; } - ValidationCtxt = xmlRelaxNGNewValidCtxt(ValidationData->Schema); + ValidationCtxt = xmlRelaxNGNewValidCtxt(Schema); status = xmlRelaxNGValidateDoc(ValidationCtxt, Doc); if (!status) printf(" CommentXMLValid"); @@ -515,11 +580,13 @@ static void ValidateCommentXML(const char *Str, xmlRelaxNGFreeValidCtxt(ValidationCtxt); xmlFreeDoc(Doc); + xmlRelaxNGFree(Schema); + xmlRelaxNGFreeParserCtxt(RNGParser); #endif } static void PrintCursorComments(CXCursor Cursor, - CommentXMLValidationData *ValidationData) { + const char *CommentSchemaFile) { { CXString RawComment; const char *RawCommentCString; @@ -550,7 +617,7 @@ static void PrintCursorComments(CXCursor Cursor, CXString XML; XML = clang_FullComment_getAsXML(Comment); PrintCXStringWithPrefix("FullCommentAsXML", XML); - ValidateCommentXML(clang_getCString(XML), ValidationData); + ValidateCommentXML(clang_getCString(XML), CommentSchemaFile); clang_disposeString(XML); } @@ -572,8 +639,7 @@ static int lineCol_cmp(const void *p1, const void *p2) { return (int)lhs->col - (int)rhs->col; } -static void PrintCursor(CXCursor Cursor, - CommentXMLValidationData *ValidationData) { +static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); if (clang_isInvalid(Cursor.kind)) { CXString ks = clang_getCursorKindSpelling(Cursor.kind); @@ -694,6 +760,8 @@ static void PrintCursor(CXCursor Cursor, printf(" (static)"); if (clang_CXXMethod_isVirtual(Cursor)) printf(" (virtual)"); + if (clang_CXXMethod_isConst(Cursor)) + printf(" (const)"); if (clang_CXXMethod_isPureVirtual(Cursor)) printf(" (pure)"); if (clang_Cursor_isVariadic(Cursor)) @@ -792,7 +860,7 @@ static void PrintCursor(CXCursor Cursor, PrintRange(RefNameRange, "RefName"); } - PrintCursorComments(Cursor, ValidationData); + PrintCursorComments(Cursor, CommentSchemaFile); { unsigned PropAttrs = clang_Cursor_getObjCPropertyAttributes(Cursor, 0); @@ -909,7 +977,6 @@ void PrintDiagnostic(CXDiagnostic Diagnostic) { PrintExtent(out, start_line, start_column, end_line, end_column); fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text)); } - break; } clang_disposeString(insertion_text); } @@ -962,7 +1029,7 @@ static void PrintCursorExtent(CXCursor C) { typedef struct { CXTranslationUnit TU; enum CXCursorKind *Filter; - CommentXMLValidationData ValidationData; + const char *CommentSchemaFile; } VisitorData; @@ -976,7 +1043,7 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor, clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Cursor), line, column); - PrintCursor(Cursor, &Data->ValidationData); + PrintCursor(Cursor, Data->CommentSchemaFile); PrintCursorExtent(Cursor); if (clang_isDeclaration(Cursor.kind)) { enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor); @@ -1046,7 +1113,7 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor, } else if (Ref.kind != CXCursor_FunctionDecl) { printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref), curLine, curColumn); - PrintCursor(Ref, &Data->ValidationData); + PrintCursor(Ref, Data->CommentSchemaFile); printf("\n"); } } @@ -1189,11 +1256,11 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, } /* Print the argument types if they exist. */ { - int numArgs = clang_Cursor_getNumArguments(cursor); - if (numArgs != -1 && numArgs != 0) { + int NumArgs = clang_Cursor_getNumArguments(cursor); + if (NumArgs != -1 && NumArgs != 0) { int i; printf(" [args="); - for (i = 0; i < numArgs; ++i) { + for (i = 0; i < NumArgs; ++i) { CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i)); if (T.kind != CXType_Invalid) { PrintTypeAndTypeKind(T, " [%s] [%s]"); @@ -1202,8 +1269,30 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, printf("]"); } } + /* Print the template argument types if they exist. */ + { + int NumTArgs = clang_Type_getNumTemplateArguments(T); + if (NumTArgs != -1 && NumTArgs != 0) { + int i; + printf(" [templateargs/%d=", NumTArgs); + for (i = 0; i < NumTArgs; ++i) { + CXType TArg = clang_Type_getTemplateArgumentAsType(T, i); + if (TArg.kind != CXType_Invalid) { + PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]"); + } + } + printf("]"); + } + } /* Print if this is a non-POD type. */ printf(" [isPOD=%d]", clang_isPODType(T)); + /* Print the pointee type. */ + { + CXType PT = clang_getPointeeType(T); + if (PT.kind != CXType_Invalid) { + PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]"); + } + } printf("\n"); } @@ -1235,18 +1324,25 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p, } /* Print the record field offset if applicable. */ { - const char *FieldName = clang_getCString(clang_getCursorSpelling(cursor)); + CXString FieldSpelling = clang_getCursorSpelling(cursor); + const char *FieldName = clang_getCString(FieldSpelling); /* recurse to get the root anonymous record parent */ CXCursor Parent, Root; - if (clang_getCursorKind(cursor) == CXCursor_FieldDecl ) { - const char *RootParentName; - Root = Parent = p; + if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) { + CXString RootParentSpelling; + const char *RootParentName = 0; + Parent = p; do { + if (RootParentName != 0) + clang_disposeString(RootParentSpelling); + Root = Parent; - RootParentName = clang_getCString(clang_getCursorSpelling(Root)); + RootParentSpelling = clang_getCursorSpelling(Root); + RootParentName = clang_getCString(RootParentSpelling); Parent = clang_getCursorSemanticParent(Root); - } while ( clang_getCursorType(Parent).kind == CXType_Record && - !strcmp(RootParentName, "") ); + } while (clang_getCursorType(Parent).kind == CXType_Record && + !strcmp(RootParentName, "")); + clang_disposeString(RootParentSpelling); /* if RootParentName is "", record is anonymous. */ { long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Root), @@ -1254,6 +1350,7 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p, printf(" [offsetof=%lld]", Offset); } } + clang_disposeString(FieldSpelling); } /* Print if its a bitfield */ { @@ -1323,11 +1420,7 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, Data.TU = TU; Data.Filter = ck; - Data.ValidationData.CommentSchemaFile = CommentSchemaFile; -#ifdef CLANG_HAVE_LIBXML - Data.ValidationData.RNGParser = NULL; - Data.ValidationData.Schema = NULL; -#endif + Data.CommentSchemaFile = CommentSchemaFile; clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data); } @@ -1372,8 +1465,9 @@ int perform_test_load_source(int argc, const char **argv, const char *CommentSchemaFile; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; + enum CXErrorCode Err; int result; - + Idx = clang_createIndex(/* excludeDeclsFromPCH */ (!strcmp(filter, "local") || !strcmp(filter, "local-display"))? 1 : 0, @@ -1389,13 +1483,14 @@ int perform_test_load_source(int argc, const char **argv, return -1; } - TU = clang_parseTranslationUnit(Idx, 0, - argv + num_unsaved_files, - argc - num_unsaved_files, - unsaved_files, num_unsaved_files, - getDefaultParsingOptions()); - if (!TU) { + Err = clang_parseTranslationUnit2(Idx, 0, + argv + num_unsaved_files, + argc - num_unsaved_files, + unsaved_files, num_unsaved_files, + getDefaultParsingOptions(), &TU); + if (Err != CXError_Success) { fprintf(stderr, "Unable to load translation unit!\n"); + describeLibclangFailure(Err); free_remapped_files(unsaved_files, num_unsaved_files); clang_disposeIndex(Idx); return 1; @@ -1415,7 +1510,9 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, CXTranslationUnit TU; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; - int result; + int compiler_arg_idx = 0; + enum CXErrorCode Err; + int result, i; int trial; int remap_after_trial = 0; char *endptr = 0; @@ -1428,15 +1525,25 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, clang_disposeIndex(Idx); return -1; } + + for (i = 0; i < argc; ++i) { + if (strcmp(argv[i], "--") == 0) + break; + } + if (i < argc) + compiler_arg_idx = i+1; + if (num_unsaved_files > compiler_arg_idx) + compiler_arg_idx = num_unsaved_files; /* Load the initial translation unit -- we do this without honoring remapped * files, so that we have a way to test results after changing the source. */ - TU = clang_parseTranslationUnit(Idx, 0, - argv + num_unsaved_files, - argc - num_unsaved_files, - 0, 0, getDefaultParsingOptions()); - if (!TU) { + Err = clang_parseTranslationUnit2(Idx, 0, + argv + compiler_arg_idx, + argc - compiler_arg_idx, + 0, 0, getDefaultParsingOptions(), &TU); + if (Err != CXError_Success) { fprintf(stderr, "Unable to load translation unit!\n"); + describeLibclangFailure(Err); free_remapped_files(unsaved_files, num_unsaved_files); clang_disposeIndex(Idx); return 1; @@ -1451,11 +1558,22 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, } for (trial = 0; trial < trials; ++trial) { - if (clang_reparseTranslationUnit(TU, - trial >= remap_after_trial ? num_unsaved_files : 0, - trial >= remap_after_trial ? unsaved_files : 0, - clang_defaultReparseOptions(TU))) { + free_remapped_files(unsaved_files, num_unsaved_files); + if (parse_remapped_files_with_try(trial, argc, argv, 0, + &unsaved_files, &num_unsaved_files)) { + clang_disposeTranslationUnit(TU); + clang_disposeIndex(Idx); + return -1; + } + + Err = clang_reparseTranslationUnit( + TU, + trial >= remap_after_trial ? num_unsaved_files : 0, + trial >= remap_after_trial ? unsaved_files : 0, + clang_defaultReparseOptions(TU)); + if (Err != CXError_Success) { fprintf(stderr, "Unable to reparse translation unit!\n"); + describeLibclangFailure(Err); clang_disposeTranslationUnit(TU); free_remapped_files(unsaved_files, num_unsaved_files); clang_disposeIndex(Idx); @@ -1669,7 +1787,8 @@ static int checkForErrors(CXTranslationUnit TU) { return 0; } -void print_completion_string(CXCompletionString completion_string, FILE *file) { +static void print_completion_string(CXCompletionString completion_string, + FILE *file) { int I, N; N = clang_getNumCompletionChunks(completion_string); @@ -1703,9 +1822,8 @@ void print_completion_string(CXCompletionString completion_string, FILE *file) { } -void print_completion_result(CXCompletionResult *completion_result, - CXClientData client_data) { - FILE *file = (FILE *)client_data; +static void print_completion_result(CXCompletionResult *completion_result, + FILE *file) { CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); unsigned annotationCount; enum CXCursorKind ParentKind; @@ -1877,7 +1995,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; CXCodeCompleteResults *results = 0; - CXTranslationUnit TU = 0; + enum CXErrorCode Err; + CXTranslationUnit TU; unsigned I, Repeats = 1; unsigned completionOptions = clang_defaultCodeCompleteOptions(); @@ -1902,21 +2021,27 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { if (getenv("CINDEXTEST_EDITING")) Repeats = 5; - - TU = clang_parseTranslationUnit(CIdx, 0, - argv + num_unsaved_files + 2, - argc - num_unsaved_files - 2, - 0, 0, getDefaultParsingOptions()); - if (!TU) { + + Err = clang_parseTranslationUnit2(CIdx, 0, + argv + num_unsaved_files + 2, + argc - num_unsaved_files - 2, + 0, 0, getDefaultParsingOptions(), &TU); + if (Err != CXError_Success) { fprintf(stderr, "Unable to load translation unit!\n"); + describeLibclangFailure(Err); return 1; } - if (clang_reparseTranslationUnit(TU, 0, 0, clang_defaultReparseOptions(TU))) { + Err = clang_reparseTranslationUnit(TU, 0, 0, + clang_defaultReparseOptions(TU)); + + if (Err != CXError_Success) { fprintf(stderr, "Unable to reparse translation init!\n"); + describeLibclangFailure(Err); + clang_disposeTranslationUnit(TU); return 1; } - + for (I = 0; I != Repeats; ++I) { results = clang_codeCompleteAt(TU, filename, line, column, unsaved_files, num_unsaved_files, @@ -2003,6 +2128,7 @@ static int inspect_cursor_at(int argc, const char **argv) { int errorCode; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; + enum CXErrorCode Err; CXTranslationUnit TU; CXCursor Cursor; CursorSourceLocation *Locations = 0; @@ -2036,15 +2162,15 @@ static int inspect_cursor_at(int argc, const char **argv) { /* 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) { + Err = clang_parseTranslationUnit2(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(), &TU); + if (Err != CXError_Success) { fprintf(stderr, "unable to parse input\n"); + describeLibclangFailure(Err); return -1; } @@ -2052,11 +2178,14 @@ static int inspect_cursor_at(int argc, const char **argv) { 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; + if (Repeats > 1) { + Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU)); + if (Err != CXError_Success) { + describeLibclangFailure(Err); + clang_disposeTranslationUnit(TU); + return 1; + } } if (checkForErrors(TU) != 0) @@ -2101,7 +2230,8 @@ static int inspect_cursor_at(int argc, const char **argv) { } clang_disposeString(Spelling); if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1) - printf(" Selector index=%d",clang_Cursor_getObjCSelectorIndex(Cursor)); + printf(" Selector index=%d", + clang_Cursor_getObjCSelectorIndex(Cursor)); if (clang_Cursor_isDynamicCall(Cursor)) printf(" Dynamic-call"); if (Cursor.kind == CXCursor_ObjCMessageExpr) { @@ -2121,9 +2251,9 @@ static int inspect_cursor_at(int argc, const char **argv) { astFilename = clang_getFileName(astFile); name = clang_Module_getFullName(mod); numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod); - printf(" ModuleName=%s (%s) Headers(%d):", + printf(" ModuleName=%s (%s) system=%d Headers(%d):", clang_getCString(name), clang_getCString(astFilename), - numHeaders); + clang_Module_isSystem(mod), numHeaders); clang_disposeString(name); clang_disposeString(astFilename); for (i = 0; i < numHeaders; ++i) { @@ -2169,6 +2299,7 @@ static int find_file_refs_at(int argc, const char **argv) { int errorCode; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; + enum CXErrorCode Err; CXTranslationUnit TU; CXCursor Cursor; CursorSourceLocation *Locations = 0; @@ -2202,15 +2333,16 @@ static int find_file_refs_at(int argc, const char **argv) { /* 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) { + Err = clang_parseTranslationUnit2(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(), &TU); + if (Err != CXError_Success) { fprintf(stderr, "unable to parse input\n"); + describeLibclangFailure(Err); + clang_disposeTranslationUnit(TU); return -1; } @@ -2218,11 +2350,14 @@ static int find_file_refs_at(int argc, const char **argv) { 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; + if (Repeats > 1) { + Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU)); + if (Err != CXError_Success) { + describeLibclangFailure(Err); + clang_disposeTranslationUnit(TU); + return 1; + } } if (checkForErrors(TU) != 0) @@ -2273,6 +2408,7 @@ static int find_file_includes_in(int argc, const char **argv) { CXIndex CIdx; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; + enum CXErrorCode Err; CXTranslationUnit TU; const char **Filenames = 0; unsigned NumFilenames = 0; @@ -2302,15 +2438,17 @@ static int find_file_includes_in(int argc, const char **argv) { /* 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 + NumFilenames, - argc - num_unsaved_files - 2 - NumFilenames, - unsaved_files, - Repeats > 1? 0 : num_unsaved_files, - getDefaultParsingOptions()); - - if (!TU) { + Err = clang_parseTranslationUnit2( + CIdx, argv[argc - 1], + argv + num_unsaved_files + 1 + NumFilenames, + argc - num_unsaved_files - 2 - NumFilenames, + unsaved_files, + Repeats > 1 ? 0 : num_unsaved_files, getDefaultParsingOptions(), &TU); + + if (Err != CXError_Success) { fprintf(stderr, "unable to parse input\n"); + describeLibclangFailure(Err); + clang_disposeTranslationUnit(TU); return -1; } @@ -2318,11 +2456,14 @@ static int find_file_includes_in(int argc, const char **argv) { 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; + if (Repeats > 1) { + Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU)); + if (Err != CXError_Success) { + describeLibclangFailure(Err); + clang_disposeTranslationUnit(TU); + return 1; + } } if (checkForErrors(TU) != 0) @@ -2390,6 +2531,11 @@ static void importedASTS_insert(ImportedASTFilesData *p, const char *file) { p->filenames[p->num_files++] = strdup(file); } +typedef struct IndexDataStringList_ { + struct IndexDataStringList_ *next; + char data[1]; /* Dynamically sized. */ +} IndexDataStringList; + typedef struct { const char *check_prefix; int first_check_printed; @@ -2397,8 +2543,20 @@ typedef struct { int abort; const char *main_filename; ImportedASTFilesData *importedASTs; + IndexDataStringList *strings; + CXTranslationUnit TU; } IndexData; +static void free_client_data(IndexData *index_data) { + IndexDataStringList *node = index_data->strings; + while (node) { + IndexDataStringList *next = node->next; + free(node); + node = next; + } + index_data->strings = NULL; +} + static void printCheck(IndexData *data) { if (data->check_prefix) { if (data->first_check_printed) { @@ -2459,8 +2617,11 @@ static unsigned digitCount(unsigned val) { } } -static CXIdxClientContainer makeClientContainer(const CXIdxEntityInfo *info, +static CXIdxClientContainer makeClientContainer(CXClientData *client_data, + const CXIdxEntityInfo *info, CXIdxLoc loc) { + IndexData *index_data; + IndexDataStringList *node; const char *name; char *newStr; CXIdxClientFile file; @@ -2471,10 +2632,18 @@ static CXIdxClientContainer makeClientContainer(const CXIdxEntityInfo *info, name = "<anon-tag>"; clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0); - /* FIXME: free these.*/ - newStr = (char *)malloc(strlen(name) + - digitCount(line) + digitCount(column) + 3); + + node = + (IndexDataStringList *)malloc(sizeof(IndexDataStringList) + strlen(name) + + digitCount(line) + digitCount(column) + 2); + newStr = node->data; sprintf(newStr, "%s:%d:%d", name, line, column); + + /* Remember string so it can be freed later. */ + index_data = (IndexData *)client_data; + node->next = index_data->strings; + index_data->strings = node; + return (CXIdxClientContainer)newStr; } @@ -2645,6 +2814,7 @@ static CXIdxClientFile index_enteredMainFile(CXClientData client_data, static CXIdxClientFile index_ppIncludedFile(CXClientData client_data, const CXIdxIncludedFileInfo *info) { IndexData *index_data; + CXModule Mod; index_data = (IndexData *)client_data; printCheck(index_data); @@ -2653,8 +2823,18 @@ static CXIdxClientFile index_ppIncludedFile(CXClientData client_data, printf(" | name: \"%s\"", info->filename); printf(" | hash loc: "); printCXIndexLoc(info->hashLoc, client_data); - printf(" | isImport: %d | isAngled: %d | isModule: %d\n", + printf(" | isImport: %d | isAngled: %d | isModule: %d", info->isImport, info->isAngled, info->isModuleImport); + + Mod = clang_getModuleForFile(index_data->TU, (CXFile)info->file); + if (Mod) { + CXString str = clang_Module_getFullName(Mod); + const char *cstr = clang_getCString(str); + printf(" | module: %s", cstr); + clang_disposeString(str); + } + + printf("\n"); return (CXIdxClientFile)info->file; } @@ -2688,8 +2868,8 @@ static CXIdxClientFile index_importedASTFile(CXClientData client_data, return (CXIdxClientFile)info->file; } -static CXIdxClientContainer index_startedTranslationUnit(CXClientData client_data, - void *reserved) { +static CXIdxClientContainer +index_startedTranslationUnit(CXClientData client_data, void *reserved) { IndexData *index_data; index_data = (IndexData *)client_data; printCheck(index_data); @@ -2790,13 +2970,15 @@ static void index_indexDeclaration(CXClientData client_data, } if (info->declAsContainer) - clang_index_setClientContainer(info->declAsContainer, - makeClientContainer(info->entityInfo, info->loc)); + clang_index_setClientContainer( + info->declAsContainer, + makeClientContainer(client_data, info->entityInfo, info->loc)); } static void index_indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo *info) { - printEntityInfo("[indexEntityReference]", client_data, info->referencedEntity); + printEntityInfo("[indexEntityReference]", client_data, + info->referencedEntity); printf(" | cursor: "); PrintCursor(info->cursor, NULL); printf(" | loc: "); @@ -2861,15 +3043,21 @@ static int index_compile_args(int num_args, const char **args, index_data.abort = 0; index_data.main_filename = ""; index_data.importedASTs = importedASTs; + index_data.strings = NULL; + index_data.TU = NULL; index_opts = getIndexOptions(); result = clang_indexSourceFile(idxAction, &index_data, &IndexCB,sizeof(IndexCB), index_opts, 0, args, num_args, 0, 0, 0, getDefaultParsingOptions()); + if (result != CXError_Success) + describeLibclangFailure(result); + if (index_data.fail_for_error) result = -1; + free_client_data(&index_data); return result; } @@ -2892,6 +3080,8 @@ static int index_ast_file(const char *ast_file, index_data.abort = 0; index_data.main_filename = ""; index_data.importedASTs = importedASTs; + index_data.strings = NULL; + index_data.TU = TU; index_opts = getIndexOptions(); result = clang_indexTranslationUnit(idxAction, &index_data, @@ -2901,6 +3091,7 @@ static int index_ast_file(const char *ast_file, result = -1; clang_disposeTranslationUnit(TU); + free_client_data(&index_data); return result; } @@ -3118,6 +3309,8 @@ int perform_token_annotation(int argc, const char **argv) { CXSourceLocation startLoc, endLoc; CXFile file = 0; CXCursor *cursors = 0; + CXSourceRangeList *skipped_ranges = 0; + enum CXErrorCode Err; unsigned i; input += strlen("-test-annotate-tokens="); @@ -3131,14 +3324,15 @@ int perform_token_annotation(int argc, const char **argv) { } CIdx = clang_createIndex(0, 1); - TU = clang_parseTranslationUnit(CIdx, argv[argc - 1], - argv + num_unsaved_files + 2, - argc - num_unsaved_files - 3, - unsaved_files, - num_unsaved_files, - getDefaultParsingOptions()); - if (!TU) { + Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1], + argv + num_unsaved_files + 2, + argc - num_unsaved_files - 3, + unsaved_files, + num_unsaved_files, + getDefaultParsingOptions(), &TU); + if (Err != CXError_Success) { fprintf(stderr, "unable to parse input\n"); + describeLibclangFailure(Err); clang_disposeIndex(CIdx); free(filename); free_remapped_files(unsaved_files, num_unsaved_files); @@ -3153,9 +3347,11 @@ int perform_token_annotation(int argc, const char **argv) { if (getenv("CINDEXTEST_EDITING")) { for (i = 0; i < 5; ++i) { - if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, - clang_defaultReparseOptions(TU))) { + Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, + clang_defaultReparseOptions(TU)); + if (Err != CXError_Success) { fprintf(stderr, "Unable to reparse translation unit!\n"); + describeLibclangFailure(Err); errorCode = -1; goto teardown; } @@ -3206,6 +3402,19 @@ int perform_token_annotation(int argc, const char **argv) { goto teardown; } + skipped_ranges = clang_getSkippedRanges(TU, file); + for (i = 0; i != skipped_ranges->count; ++i) { + unsigned start_line, start_column, end_line, end_column; + clang_getSpellingLocation(clang_getRangeStart(skipped_ranges->ranges[i]), + 0, &start_line, &start_column, 0); + clang_getSpellingLocation(clang_getRangeEnd(skipped_ranges->ranges[i]), + 0, &end_line, &end_column, 0); + printf("Skipping: "); + PrintExtent(stdout, start_line, start_column, end_line, end_column); + printf("\n"); + } + clang_disposeSourceRangeList(skipped_ranges); + for (i = 0; i != num_tokens; ++i) { const char *kind = "<unknown>"; CXString spelling = clang_getTokenSpelling(TU, tokens[i]); @@ -3506,6 +3715,7 @@ int write_pch_file(const char *filename, int argc, const char *argv[]) { CXTranslationUnit TU; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; + enum CXErrorCode Err; int result = 0; Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1); @@ -3514,18 +3724,19 @@ int write_pch_file(const char *filename, int argc, const char *argv[]) { clang_disposeIndex(Idx); return -1; } - - TU = clang_parseTranslationUnit(Idx, 0, - argv + num_unsaved_files, - argc - num_unsaved_files, - unsaved_files, - num_unsaved_files, - CXTranslationUnit_Incomplete | - CXTranslationUnit_DetailedPreprocessingRecord| - CXTranslationUnit_ForSerialization); - if (!TU) { + + Err = clang_parseTranslationUnit2( + Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files, + unsaved_files, num_unsaved_files, + CXTranslationUnit_Incomplete | + CXTranslationUnit_DetailedPreprocessingRecord | + CXTranslationUnit_ForSerialization, + &TU); + if (Err != CXError_Success) { fprintf(stderr, "Unable to load translation unit!\n"); + describeLibclangFailure(Err); free_remapped_files(unsaved_files, num_unsaved_files); + clang_disposeTranslationUnit(TU); clang_disposeIndex(Idx); return 1; } @@ -3697,6 +3908,7 @@ static void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) { clang_disposeString(FileName); clang_disposeString(DiagSpelling); clang_disposeString(DiagOption); + clang_disposeString(DiagCat); } } @@ -3721,6 +3933,11 @@ static int read_diagnostics(const char *filename) { return 0; } +static int perform_print_build_session_timestamp(void) { + printf("%lld\n", clang_getBuildSessionTimestamp()); + return 0; +} + /******************************************************************************/ /* Command line processing. */ /******************************************************************************/ @@ -3777,6 +3994,8 @@ static void print_usage(void) { fprintf(stderr, " c-index-test -compilation-db [lookup <filename>] database\n"); fprintf(stderr, + " c-index-test -print-build-session-timestamp\n"); + fprintf(stderr, " c-index-test -read-diagnostics <file>\n\n"); fprintf(stderr, " <symbol filter> values:\n%s", @@ -3876,6 +4095,8 @@ int cindextest_main(int argc, const char **argv) { return write_pch_file(argv[2], argc - 3, argv + 3); else if (argc > 2 && strcmp(argv[1], "-compilation-db") == 0) return perform_test_compilation_db(argv[argc-1], argc - 3, argv + 2); + else if (argc == 2 && strcmp(argv[1], "-print-build-session-timestamp") == 0) + return perform_print_build_session_timestamp(); print_usage(); return 1; @@ -3895,14 +4116,20 @@ typedef struct thread_info { void thread_runner(void *client_data_v) { thread_info *client_data = client_data_v; client_data->result = cindextest_main(client_data->argc, client_data->argv); -#ifdef __CYGWIN__ - fflush(stdout); /* stdout is not flushed on Cygwin. */ -#endif +} + +static void flush_atexit(void) { + /* stdout, and surprisingly even stderr, are not always flushed on process + * and thread exit, particularly when the system is under heavy load. */ + fflush(stdout); + fflush(stderr); } int main(int argc, const char **argv) { thread_info client_data; + atexit(flush_atexit); + #ifdef CLANG_HAVE_LIBXML LIBXML_TEST_VERSION #endif |