diff options
Diffstat (limited to 'tools/c-index-test/c-index-test.c')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 249 |
1 files changed, 216 insertions, 33 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 99f05669b64c7..70ab11866edd5 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -64,7 +64,7 @@ extern char *basename(const char *); extern char *dirname(char *); #endif -/** \brief Return the default parsing options. */ +/** Return the default parsing options. */ static unsigned getDefaultParsingOptions() { unsigned options = CXTranslationUnit_DetailedPreprocessingRecord; @@ -82,11 +82,76 @@ static unsigned getDefaultParsingOptions() { options |= CXTranslationUnit_CreatePreambleOnFirstParse; if (getenv("CINDEXTEST_KEEP_GOING")) options |= CXTranslationUnit_KeepGoing; + if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE")) + options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble; return options; } -/** \brief Returns 0 in case of success, non-zero in case of a failure. */ +static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) { + struct Mapping { + const char *name; + enum CXPrintingPolicyProperty property; + }; + struct Mapping mappings[] = { + {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS", + CXPrintingPolicy_SuppressSpecifiers}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD", + CXPrintingPolicy_SuppressTagKeyword}, + {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION", + CXPrintingPolicy_IncludeTagDefinition}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE", + CXPrintingPolicy_SuppressScope}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE", + CXPrintingPolicy_SuppressUnwrittenScope}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS", + CXPrintingPolicy_SuppressInitializers}, + {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN", + CXPrintingPolicy_ConstantArraySizeAsWritten}, + {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS", + CXPrintingPolicy_AnonymousTagLocations}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME", + CXPrintingPolicy_SuppressStrongLifetime}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS", + CXPrintingPolicy_SuppressLifetimeQualifiers}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS", + CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors}, + {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool}, + {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict}, + {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof}, + {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF", + CXPrintingPolicy_UnderscoreAlignof}, + {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS", + CXPrintingPolicy_UseVoidForZeroParams}, + {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput}, + {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION", + CXPrintingPolicy_PolishForDeclaration}, + {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half}, + {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar}, + {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES", + CXPrintingPolicy_IncludeNewlines}, + {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING", + CXPrintingPolicy_MSVCFormatting}, + {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN", + CXPrintingPolicy_ConstantsAsWritten}, + {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE", + CXPrintingPolicy_SuppressImplicitBase}, + {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME", + CXPrintingPolicy_FullyQualifiedName}, + }; + + unsigned i; + for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) { + char *value = getenv(mappings[i].name); + if (value) { + clang_PrintingPolicy_setProperty(Policy, mappings[i].property, + (unsigned)strtoul(value, 0L, 10)); + } + } +} + +/** Returns 0 in case of success, non-zero in case of a failure. */ static int checkForErrors(CXTranslationUnit TU); static void describeLibclangFailure(enum CXErrorCode Err) { @@ -169,6 +234,7 @@ static int parse_remapped_files_with_opt(const char *opt_name, *unsaved_files = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * *num_unsaved_files); + assert(*unsaved_files); for (i = 0; i != *num_unsaved_files; ++i) { struct CXUnsavedFile *unsaved = *unsaved_files + i; const char *arg_string = argv[arg_indices[i]] + prefix_len; @@ -204,6 +270,7 @@ static int parse_remapped_files_with_opt(const char *opt_name, /* Read the contents of the file we're remapping to. */ contents = (char *)malloc(unsaved->Length + 1); + assert(contents); 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"), sep + 1); @@ -223,6 +290,7 @@ static int parse_remapped_files_with_opt(const char *opt_name, /* Copy the file name that we're remapping from. */ filename_len = sep - arg_string; filename = (char *)malloc(filename_len + 1); + assert(filename); memcpy(filename, arg_string, filename_len); filename[filename_len] = 0; unsaved->Filename = filename; @@ -277,6 +345,7 @@ static int parse_remapped_files_with_try(int try_idx, = (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx, sizeof(struct CXUnsavedFile) * *num_unsaved_files); + assert(*unsaved_files); memcpy(*unsaved_files + num_unsaved_files_no_try_idx, unsaved_files_try_idx, sizeof(struct CXUnsavedFile) * num_unsaved_files_try_idx); @@ -356,7 +425,11 @@ static void PrintRange(CXSourceRange R, const char *str) { PrintExtent(stdout, begin_line, begin_column, end_line, end_column); } -int want_display_name = 0; +static enum DisplayType { + DisplayType_Spelling, + DisplayType_DisplayName, + DisplayType_Pretty +} wanted_display_type = DisplayType_Spelling; static void printVersion(const char *Prefix, CXVersion Version) { if (Version.Major < 0) @@ -591,7 +664,7 @@ static void ValidateCommentXML(const char *Str, const char *CommentSchemaFile) { printf(" CommentXMLValid"); else if (status > 0) { xmlErrorPtr Error = xmlGetLastError(); - printf(" CommentXMLInvalid [not vaild XML: %s]", Error->message); + printf(" CommentXMLInvalid [not valid XML: %s]", Error->message); } else printf(" libXMLError"); @@ -656,6 +729,28 @@ static int lineCol_cmp(const void *p1, const void *p2) { return (int)lhs->col - (int)rhs->col; } +static CXString CursorToText(CXCursor Cursor) { + CXString text; + switch (wanted_display_type) { + case DisplayType_Spelling: + return clang_getCursorSpelling(Cursor); + case DisplayType_DisplayName: + return clang_getCursorDisplayName(Cursor); + case DisplayType_Pretty: { + CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor); + ModifyPrintingPolicyAccordingToEnv(Policy); + text = clang_getCursorPrettyPrinted(Cursor, Policy); + clang_PrintingPolicy_dispose(Policy); + return text; + } + } + assert(0 && "unknown display type"); /* no llvm_unreachable in C. */ + /* Set to NULL to prevent uninitialized variable warnings. */ + text.data = NULL; + text.private_flags = 0; + return text; +} + static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); if (clang_isInvalid(Cursor.kind)) { @@ -682,8 +777,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { int I; ks = clang_getCursorKindSpelling(Cursor.kind); - string = want_display_name? clang_getCursorDisplayName(Cursor) - : clang_getCursorSpelling(Cursor); + string = CursorToText(Cursor); printf("%s=%s", clang_getCString(ks), clang_getCString(string)); clang_disposeString(ks); @@ -812,6 +906,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { printf(" (variadic)"); if (clang_Cursor_isObjCOptional(Cursor)) printf(" (@optional)"); + if (clang_isInvalidDeclaration(Cursor)) + printf(" (invalid)"); switch (clang_getCursorExceptionSpecificationType(Cursor)) { @@ -1038,6 +1134,13 @@ static const char* GetCursorSource(CXCursor Cursor) { } } +static CXString createCXString(const char *CS) { + CXString Str; + Str.data = (const void *) CS; + Str.private_flags = 0; + return Str; +} + /******************************************************************************/ /* Callbacks. */ /******************************************************************************/ @@ -1684,7 +1787,12 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, else if (!strcmp(filter, "all-display") || !strcmp(filter, "local-display")) { ck = NULL; - want_display_name = 1; + wanted_display_type = DisplayType_DisplayName; + } + else if (!strcmp(filter, "all-pretty") || + !strcmp(filter, "local-pretty")) { + ck = NULL; + wanted_display_type = DisplayType_Pretty; } else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0; else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl; @@ -1752,8 +1860,11 @@ int perform_test_load_source(int argc, const char **argv, const char *InvocationPath; Idx = clang_createIndex(/* excludeDeclsFromPCH */ - (!strcmp(filter, "local") || - !strcmp(filter, "local-display"))? 1 : 0, + (!strcmp(filter, "local") || + !strcmp(filter, "local-display") || + !strcmp(filter, "local-pretty")) + ? 1 + : 0, /* displayDiagnostics=*/1); InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH"); if (InvocationPath) @@ -2064,6 +2175,7 @@ int parse_file_line_column(const char *input, char **filename, unsigned *line, /* Copy the file name. */ *filename = (char*)malloc(last_colon - input + 1); + assert(*filename); memcpy(*filename, input, last_colon - input); (*filename)[last_colon - input] = 0; return 0; @@ -2158,8 +2270,33 @@ static void print_completion_string(CXCompletionString completion_string, } -static void print_completion_result(CXCompletionResult *completion_result, +static void print_line_column(CXSourceLocation location, FILE *file) { + unsigned line, column; + clang_getExpansionLocation(location, NULL, &line, &column, NULL); + fprintf(file, "%d:%d", line, column); +} + +static void print_token_range(CXTranslationUnit translation_unit, + CXSourceLocation start, FILE *file) { + CXToken *token = clang_getToken(translation_unit, start); + + fprintf(file, "{"); + if (token != NULL) { + CXSourceRange token_range = clang_getTokenExtent(translation_unit, *token); + print_line_column(clang_getRangeStart(token_range), file); + fprintf(file, "-"); + print_line_column(clang_getRangeEnd(token_range), file); + clang_disposeTokens(translation_unit, token, 1); + } + + fprintf(file, "}"); +} + +static void print_completion_result(CXTranslationUnit translation_unit, + CXCodeCompleteResults *completion_results, + unsigned index, FILE *file) { + CXCompletionResult *completion_result = completion_results->Results + index; CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); unsigned annotationCount; enum CXCursorKind ParentKind; @@ -2167,6 +2304,7 @@ static void print_completion_result(CXCompletionResult *completion_result, CXString BriefComment; CXString Annotation; const char *BriefCommentCString; + unsigned i; fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); @@ -2227,7 +2365,19 @@ static void print_completion_result(CXCompletionResult *completion_result, fprintf(file, "(brief comment: %s)", BriefCommentCString); } clang_disposeString(BriefComment); - + + for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index); + ++i) { + CXSourceRange correction_range; + CXString FixIt = clang_getCompletionFixIt(completion_results, index, i, + &correction_range); + fprintf(file, " (requires fix-it: "); + print_token_range(translation_unit, clang_getRangeStart(correction_range), + file); + fprintf(file, " to \"%s\")", clang_getCString(FixIt)); + clang_disposeString(FixIt); + } + fprintf(file, "\n"); } @@ -2324,6 +2474,10 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { completionOptions |= CXCodeComplete_IncludeCodePatterns; if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) completionOptions |= CXCodeComplete_IncludeBriefComments; + if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE")) + completionOptions |= CXCodeComplete_SkipPreamble; + if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS")) + completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts; if (timing_only) input += strlen("-code-completion-timing="); @@ -2388,7 +2542,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { clang_sortCodeCompletionResults(results->Results, results->NumResults); for (i = 0; i != n; ++i) - print_completion_result(results->Results + i, stdout); + print_completion_result(TU, results, i, stdout); } n = clang_codeCompleteGetNumDiagnostics(results); for (i = 0; i != n; ++i) { @@ -2471,6 +2625,7 @@ static int inspect_cursor_at(int argc, const char **argv, assert(NumLocations > 0 && "Unable to count locations?"); Locations = (CursorSourceLocation *)malloc( NumLocations * sizeof(CursorSourceLocation)); + assert(Locations); for (Loc = 0; Loc < NumLocations; ++Loc) { const char *input = argv[Loc + 1] + strlen(locations_flag); if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename, @@ -2764,6 +2919,7 @@ static int find_file_refs_at(int argc, const char **argv) { assert(NumLocations > 0 && "Unable to count locations?"); Locations = (CursorSourceLocation *)malloc( NumLocations * sizeof(CursorSourceLocation)); + assert(Locations); 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, @@ -2871,6 +3027,7 @@ static int find_file_includes_in(int argc, const char **argv) { /* Parse the locations. */ assert(NumFilenames > 0 && "Unable to count filenames?"); Filenames = (const char **)malloc(NumFilenames * sizeof(const char *)); + assert(Filenames); for (I = 0; I < NumFilenames; ++I) { const char *input = argv[I + 1] + strlen("-file-includes-in="); /* Copy the file name. */ @@ -2954,7 +3111,9 @@ typedef struct { static ImportedASTFilesData *importedASTs_create() { ImportedASTFilesData *p; p = malloc(sizeof(ImportedASTFilesData)); + assert(p); p->filenames = malloc(MAX_IMPORTED_ASTFILES * sizeof(const char *)); + assert(p->filenames); p->num_files = 0; return p; } @@ -2990,7 +3149,7 @@ typedef struct { int first_check_printed; int fail_for_error; int abort; - const char *main_filename; + CXString main_filename; ImportedASTFilesData *importedASTs; IndexDataStringList *strings; CXTranslationUnit TU; @@ -3029,6 +3188,7 @@ static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) { const char *cname; CXIdxClientFile file; unsigned line, column; + const char *main_filename; int isMainFile; index_data = (IndexData *)client_data; @@ -3043,7 +3203,8 @@ static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) { } filename = clang_getFileName((CXFile)file); cname = clang_getCString(filename); - if (strcmp(cname, index_data->main_filename) == 0) + main_filename = clang_getCString(index_data->main_filename); + if (strcmp(cname, main_filename) == 0) isMainFile = 1; else isMainFile = 0; @@ -3085,6 +3246,7 @@ static CXIdxClientContainer makeClientContainer(CXClientData *client_data, node = (IndexDataStringList *)malloc(sizeof(IndexDataStringList) + strlen(name) + digitCount(line) + digitCount(column) + 2); + assert(node); newStr = node->data; sprintf(newStr, "%s:%d:%d", name, line, column); @@ -3217,6 +3379,27 @@ static void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo, } } +static void printSymbolRole(CXSymbolRole role) { + if (role & CXSymbolRole_Declaration) + printf(" decl"); + if (role & CXSymbolRole_Definition) + printf(" def"); + if (role & CXSymbolRole_Reference) + printf(" ref"); + if (role & CXSymbolRole_Read) + printf(" read"); + if (role & CXSymbolRole_Write) + printf(" write"); + if (role & CXSymbolRole_Call) + printf(" call"); + if (role & CXSymbolRole_Dynamic) + printf(" dyn"); + if (role & CXSymbolRole_AddressOf) + printf(" addr"); + if (role & CXSymbolRole_Implicit) + printf(" implicit"); +} + static void index_diagnostic(CXClientData client_data, CXDiagnosticSet diagSet, void *reserved) { CXString str; @@ -3245,14 +3428,11 @@ static void index_diagnostic(CXClientData client_data, static CXIdxClientFile index_enteredMainFile(CXClientData client_data, CXFile file, void *reserved) { IndexData *index_data; - CXString filename; index_data = (IndexData *)client_data; printCheck(index_data); - filename = clang_getFileName(file); - index_data->main_filename = clang_getCString(filename); - clang_disposeString(filename); + index_data->main_filename = clang_getFileName(file); printf("[enteredMainFile]: "); printCXIndexFile((CXIdxClientFile)file); @@ -3438,9 +3618,11 @@ static void index_indexEntityReference(CXClientData client_data, printCXIndexContainer(info->container); printf(" | refkind: "); switch (info->kind) { - case CXIdxEntityRef_Direct: printf("direct"); break; - case CXIdxEntityRef_Implicit: printf("implicit"); break; + case CXIdxEntityRef_Direct: printf("direct"); break; + case CXIdxEntityRef_Implicit: printf("implicit"); break; } + printf(" | role:"); + printSymbolRole(info->role); printf("\n"); } @@ -3470,6 +3652,8 @@ static unsigned getIndexOptions(void) { index_opts |= CXIndexOpt_IndexFunctionLocalSymbols; if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES")) index_opts |= CXIndexOpt_SkipParsedBodiesInSession; + if (getenv("CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS")) + index_opts |= CXIndexOpt_IndexImplicitTemplateInstantiations; return index_opts; } @@ -3491,7 +3675,7 @@ static int index_compile_args(int num_args, const char **args, index_data.first_check_printed = 0; index_data.fail_for_error = 0; index_data.abort = 0; - index_data.main_filename = ""; + index_data.main_filename = createCXString(""); index_data.importedASTs = importedASTs; index_data.strings = NULL; index_data.TU = NULL; @@ -3507,6 +3691,7 @@ static int index_compile_args(int num_args, const char **args, if (index_data.fail_for_error) result = -1; + clang_disposeString(index_data.main_filename); free_client_data(&index_data); return result; } @@ -3528,7 +3713,7 @@ static int index_ast_file(const char *ast_file, index_data.first_check_printed = 0; index_data.fail_for_error = 0; index_data.abort = 0; - index_data.main_filename = ""; + index_data.main_filename = createCXString(""); index_data.importedASTs = importedASTs; index_data.strings = NULL; index_data.TU = TU; @@ -3541,6 +3726,7 @@ static int index_ast_file(const char *ast_file, result = -1; clang_disposeTranslationUnit(TU); + clang_disposeString(index_data.main_filename); free_client_data(&index_data); return result; } @@ -3664,6 +3850,7 @@ static int index_compile_db(int argc, const char **argv) { len = strlen(database); tmp = (char *) malloc(len+1); + assert(tmp); memcpy(tmp, database, len+1); buildDir = dirname(tmp); @@ -3845,6 +4032,7 @@ int perform_token_annotation(int argc, const char **argv) { } cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor)); + assert(cursors); clang_annotateTokens(TU, tokens, num_tokens, cursors); if (checkForErrors(TU) != 0) { @@ -3919,6 +4107,7 @@ perform_test_compilation_db(const char *database, int argc, const char **argv) { len = strlen(database); tmp = (char *) malloc(len+1); + assert(tmp); memcpy(tmp, database, len+1); buildDir = dirname(tmp); @@ -4033,9 +4222,7 @@ int print_usrs(const char **I, const char **E) { if (!isUSR(I[2])) return not_usr("<class USR>", I[2]); else { - CXString x; - x.data = (void*) I[2]; - x.private_flags = 0; + CXString x = createCXString(I[2]); print_usr(clang_constructUSR_ObjCIvar(I[1], x)); } @@ -4060,9 +4247,7 @@ int print_usrs(const char **I, const char **E) { if (!isUSR(I[3])) return not_usr("<class USR>", I[3]); else { - CXString x; - x.data = (void*) I[3]; - x.private_flags = 0; + CXString x = createCXString(I[3]); print_usr(clang_constructUSR_ObjCMethod(I[1], atoi(I[2]), x)); } I += 4; @@ -4090,9 +4275,7 @@ int print_usrs(const char **I, const char **E) { if (!isUSR(I[2])) return not_usr("<class USR>", I[2]); else { - CXString x; - x.data = (void*) I[2]; - x.private_flags = 0; + CXString x = createCXString(I[2]); print_usr(clang_constructUSR_ObjCProperty(I[1], x)); } I += 3; @@ -4261,10 +4444,10 @@ static void printLocation(CXSourceLocation L) { CXFile File; CXString FileName; unsigned line, column, offset; - + clang_getExpansionLocation(L, &File, &line, &column, &offset); FileName = clang_getFileName(File); - + fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column); clang_disposeString(FileName); } |