1 1.1 joerg /* c-index-test.c */ 2 1.1 joerg 3 1.1 joerg #include "clang/Config/config.h" 4 1.1 joerg #include "clang-c/Index.h" 5 1.1 joerg #include "clang-c/CXCompilationDatabase.h" 6 1.1 joerg #include "clang-c/BuildSystem.h" 7 1.1 joerg #include "clang-c/Documentation.h" 8 1.1 joerg #include <ctype.h> 9 1.1 joerg #include <stdlib.h> 10 1.1 joerg #include <stdio.h> 11 1.1 joerg #include <string.h> 12 1.1 joerg #include <assert.h> 13 1.1 joerg 14 1.1 joerg #ifdef CLANG_HAVE_LIBXML 15 1.1 joerg #include <libxml/parser.h> 16 1.1 joerg #include <libxml/relaxng.h> 17 1.1 joerg #include <libxml/xmlerror.h> 18 1.1 joerg #endif 19 1.1 joerg 20 1.1 joerg #ifdef _WIN32 21 1.1 joerg # include <direct.h> 22 1.1 joerg #else 23 1.1 joerg # include <unistd.h> 24 1.1 joerg #endif 25 1.1 joerg 26 1.1 joerg extern int indextest_core_main(int argc, const char **argv); 27 1.1.1.2 joerg extern int indextest_perform_shell_execution(const char *command_line); 28 1.1 joerg 29 1.1 joerg /******************************************************************************/ 30 1.1 joerg /* Utility functions. */ 31 1.1 joerg /******************************************************************************/ 32 1.1 joerg 33 1.1 joerg #ifdef _MSC_VER 34 1.1 joerg char *basename(const char* path) 35 1.1 joerg { 36 1.1 joerg char* base1 = (char*)strrchr(path, '/'); 37 1.1 joerg char* base2 = (char*)strrchr(path, '\\'); 38 1.1 joerg if (base1 && base2) 39 1.1 joerg return((base1 > base2) ? base1 + 1 : base2 + 1); 40 1.1 joerg else if (base1) 41 1.1 joerg return(base1 + 1); 42 1.1 joerg else if (base2) 43 1.1 joerg return(base2 + 1); 44 1.1 joerg 45 1.1 joerg return((char*)path); 46 1.1 joerg } 47 1.1 joerg char *dirname(char* path) 48 1.1 joerg { 49 1.1 joerg char* base1 = (char*)strrchr(path, '/'); 50 1.1 joerg char* base2 = (char*)strrchr(path, '\\'); 51 1.1 joerg if (base1 && base2) 52 1.1 joerg if (base1 > base2) 53 1.1 joerg *base1 = 0; 54 1.1 joerg else 55 1.1 joerg *base2 = 0; 56 1.1 joerg else if (base1) 57 1.1 joerg *base1 = 0; 58 1.1 joerg else if (base2) 59 1.1 joerg *base2 = 0; 60 1.1 joerg 61 1.1 joerg return path; 62 1.1 joerg } 63 1.1 joerg #else 64 1.1 joerg extern char *basename(const char *); 65 1.1 joerg extern char *dirname(char *); 66 1.1 joerg #endif 67 1.1 joerg 68 1.1 joerg /** Return the default parsing options. */ 69 1.1 joerg static unsigned getDefaultParsingOptions() { 70 1.1 joerg unsigned options = CXTranslationUnit_DetailedPreprocessingRecord; 71 1.1 joerg 72 1.1 joerg if (getenv("CINDEXTEST_EDITING")) 73 1.1 joerg options |= clang_defaultEditingTranslationUnitOptions(); 74 1.1 joerg if (getenv("CINDEXTEST_COMPLETION_CACHING")) 75 1.1 joerg options |= CXTranslationUnit_CacheCompletionResults; 76 1.1 joerg if (getenv("CINDEXTEST_COMPLETION_NO_CACHING")) 77 1.1 joerg options &= ~CXTranslationUnit_CacheCompletionResults; 78 1.1 joerg if (getenv("CINDEXTEST_SKIP_FUNCTION_BODIES")) 79 1.1 joerg options |= CXTranslationUnit_SkipFunctionBodies; 80 1.1 joerg if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) 81 1.1 joerg options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion; 82 1.1 joerg if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE")) 83 1.1 joerg options |= CXTranslationUnit_CreatePreambleOnFirstParse; 84 1.1 joerg if (getenv("CINDEXTEST_KEEP_GOING")) 85 1.1 joerg options |= CXTranslationUnit_KeepGoing; 86 1.1 joerg if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE")) 87 1.1 joerg options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble; 88 1.1 joerg if (getenv("CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES")) 89 1.1 joerg options |= CXTranslationUnit_IncludeAttributedTypes; 90 1.1 joerg if (getenv("CINDEXTEST_VISIT_IMPLICIT_ATTRIBUTES")) 91 1.1 joerg options |= CXTranslationUnit_VisitImplicitAttributes; 92 1.1 joerg if (getenv("CINDEXTEST_IGNORE_NONERRORS_FROM_INCLUDED_FILES")) 93 1.1 joerg options |= CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles; 94 1.1 joerg 95 1.1 joerg return options; 96 1.1 joerg } 97 1.1 joerg 98 1.1 joerg static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) { 99 1.1 joerg struct Mapping { 100 1.1 joerg const char *name; 101 1.1 joerg enum CXPrintingPolicyProperty property; 102 1.1 joerg }; 103 1.1 joerg struct Mapping mappings[] = { 104 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation}, 105 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS", 106 1.1 joerg CXPrintingPolicy_SuppressSpecifiers}, 107 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD", 108 1.1 joerg CXPrintingPolicy_SuppressTagKeyword}, 109 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION", 110 1.1 joerg CXPrintingPolicy_IncludeTagDefinition}, 111 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE", 112 1.1 joerg CXPrintingPolicy_SuppressScope}, 113 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE", 114 1.1 joerg CXPrintingPolicy_SuppressUnwrittenScope}, 115 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS", 116 1.1 joerg CXPrintingPolicy_SuppressInitializers}, 117 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN", 118 1.1 joerg CXPrintingPolicy_ConstantArraySizeAsWritten}, 119 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS", 120 1.1 joerg CXPrintingPolicy_AnonymousTagLocations}, 121 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME", 122 1.1 joerg CXPrintingPolicy_SuppressStrongLifetime}, 123 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS", 124 1.1 joerg CXPrintingPolicy_SuppressLifetimeQualifiers}, 125 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS", 126 1.1 joerg CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors}, 127 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool}, 128 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict}, 129 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof}, 130 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF", 131 1.1 joerg CXPrintingPolicy_UnderscoreAlignof}, 132 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS", 133 1.1 joerg CXPrintingPolicy_UseVoidForZeroParams}, 134 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput}, 135 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION", 136 1.1 joerg CXPrintingPolicy_PolishForDeclaration}, 137 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half}, 138 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar}, 139 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES", 140 1.1 joerg CXPrintingPolicy_IncludeNewlines}, 141 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING", 142 1.1 joerg CXPrintingPolicy_MSVCFormatting}, 143 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN", 144 1.1 joerg CXPrintingPolicy_ConstantsAsWritten}, 145 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE", 146 1.1 joerg CXPrintingPolicy_SuppressImplicitBase}, 147 1.1 joerg {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME", 148 1.1 joerg CXPrintingPolicy_FullyQualifiedName}, 149 1.1 joerg }; 150 1.1 joerg 151 1.1 joerg unsigned i; 152 1.1 joerg for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) { 153 1.1 joerg char *value = getenv(mappings[i].name); 154 1.1 joerg if (value) { 155 1.1 joerg clang_PrintingPolicy_setProperty(Policy, mappings[i].property, 156 1.1 joerg (unsigned)strtoul(value, 0L, 10)); 157 1.1 joerg } 158 1.1 joerg } 159 1.1 joerg } 160 1.1 joerg 161 1.1 joerg /** Returns 0 in case of success, non-zero in case of a failure. */ 162 1.1 joerg static int checkForErrors(CXTranslationUnit TU); 163 1.1 joerg 164 1.1 joerg static void describeLibclangFailure(enum CXErrorCode Err) { 165 1.1 joerg switch (Err) { 166 1.1 joerg case CXError_Success: 167 1.1 joerg fprintf(stderr, "Success\n"); 168 1.1 joerg return; 169 1.1 joerg 170 1.1 joerg case CXError_Failure: 171 1.1 joerg fprintf(stderr, "Failure (no details available)\n"); 172 1.1 joerg return; 173 1.1 joerg 174 1.1 joerg case CXError_Crashed: 175 1.1 joerg fprintf(stderr, "Failure: libclang crashed\n"); 176 1.1 joerg return; 177 1.1 joerg 178 1.1 joerg case CXError_InvalidArguments: 179 1.1 joerg fprintf(stderr, "Failure: invalid arguments passed to a libclang routine\n"); 180 1.1 joerg return; 181 1.1 joerg 182 1.1 joerg case CXError_ASTReadError: 183 1.1 joerg fprintf(stderr, "Failure: AST deserialization error occurred\n"); 184 1.1 joerg return; 185 1.1 joerg } 186 1.1 joerg } 187 1.1 joerg 188 1.1 joerg static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column, 189 1.1 joerg unsigned end_line, unsigned end_column) { 190 1.1 joerg fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column, 191 1.1 joerg end_line, end_column); 192 1.1 joerg } 193 1.1 joerg 194 1.1 joerg static unsigned CreateTranslationUnit(CXIndex Idx, const char *file, 195 1.1 joerg CXTranslationUnit *TU) { 196 1.1 joerg enum CXErrorCode Err = clang_createTranslationUnit2(Idx, file, TU); 197 1.1 joerg if (Err != CXError_Success) { 198 1.1 joerg fprintf(stderr, "Unable to load translation unit from '%s'!\n", file); 199 1.1 joerg describeLibclangFailure(Err); 200 1.1 joerg *TU = 0; 201 1.1 joerg return 0; 202 1.1 joerg } 203 1.1 joerg return 1; 204 1.1 joerg } 205 1.1 joerg 206 1.1 joerg void free_remapped_files(struct CXUnsavedFile *unsaved_files, 207 1.1 joerg int num_unsaved_files) { 208 1.1 joerg int i; 209 1.1 joerg for (i = 0; i != num_unsaved_files; ++i) { 210 1.1 joerg free((char *)unsaved_files[i].Filename); 211 1.1 joerg free((char *)unsaved_files[i].Contents); 212 1.1 joerg } 213 1.1 joerg free(unsaved_files); 214 1.1 joerg } 215 1.1 joerg 216 1.1 joerg static int parse_remapped_files_with_opt(const char *opt_name, 217 1.1 joerg int argc, const char **argv, 218 1.1 joerg int start_arg, 219 1.1 joerg struct CXUnsavedFile **unsaved_files, 220 1.1 joerg int *num_unsaved_files) { 221 1.1 joerg int i; 222 1.1 joerg int arg; 223 1.1 joerg int prefix_len = strlen(opt_name); 224 1.1 joerg int arg_indices[20]; 225 1.1 joerg *unsaved_files = 0; 226 1.1 joerg *num_unsaved_files = 0; 227 1.1 joerg 228 1.1 joerg /* Count the number of remapped files. */ 229 1.1 joerg for (arg = start_arg; arg < argc; ++arg) { 230 1.1 joerg if (strncmp(argv[arg], opt_name, prefix_len)) 231 1.1 joerg continue; 232 1.1 joerg 233 1.1 joerg assert(*num_unsaved_files < (int)(sizeof(arg_indices)/sizeof(int))); 234 1.1 joerg arg_indices[*num_unsaved_files] = arg; 235 1.1 joerg ++*num_unsaved_files; 236 1.1 joerg } 237 1.1 joerg 238 1.1 joerg if (*num_unsaved_files == 0) 239 1.1 joerg return 0; 240 1.1 joerg 241 1.1 joerg *unsaved_files 242 1.1 joerg = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * 243 1.1 joerg *num_unsaved_files); 244 1.1 joerg assert(*unsaved_files); 245 1.1 joerg for (i = 0; i != *num_unsaved_files; ++i) { 246 1.1 joerg struct CXUnsavedFile *unsaved = *unsaved_files + i; 247 1.1 joerg const char *arg_string = argv[arg_indices[i]] + prefix_len; 248 1.1 joerg int filename_len; 249 1.1 joerg char *filename; 250 1.1 joerg char *contents; 251 1.1 joerg FILE *to_file; 252 1.1 joerg const char *sep = strchr(arg_string, ','); 253 1.1 joerg if (!sep) { 254 1.1 joerg fprintf(stderr, 255 1.1 joerg "error: %sfrom:to argument is missing comma\n", opt_name); 256 1.1 joerg free_remapped_files(*unsaved_files, i); 257 1.1 joerg *unsaved_files = 0; 258 1.1 joerg *num_unsaved_files = 0; 259 1.1 joerg return -1; 260 1.1 joerg } 261 1.1 joerg 262 1.1 joerg /* Open the file that we're remapping to. */ 263 1.1 joerg to_file = fopen(sep + 1, "rb"); 264 1.1 joerg if (!to_file) { 265 1.1 joerg fprintf(stderr, "error: cannot open file %s that we are remapping to\n", 266 1.1 joerg sep + 1); 267 1.1 joerg free_remapped_files(*unsaved_files, i); 268 1.1 joerg *unsaved_files = 0; 269 1.1 joerg *num_unsaved_files = 0; 270 1.1 joerg return -1; 271 1.1 joerg } 272 1.1 joerg 273 1.1 joerg /* Determine the length of the file we're remapping to. */ 274 1.1 joerg fseek(to_file, 0, SEEK_END); 275 1.1 joerg unsaved->Length = ftell(to_file); 276 1.1 joerg fseek(to_file, 0, SEEK_SET); 277 1.1 joerg 278 1.1 joerg /* Read the contents of the file we're remapping to. */ 279 1.1 joerg contents = (char *)malloc(unsaved->Length + 1); 280 1.1 joerg assert(contents); 281 1.1 joerg if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) { 282 1.1 joerg fprintf(stderr, "error: unexpected %s reading 'to' file %s\n", 283 1.1 joerg (feof(to_file) ? "EOF" : "error"), sep + 1); 284 1.1 joerg fclose(to_file); 285 1.1 joerg free_remapped_files(*unsaved_files, i); 286 1.1 joerg free(contents); 287 1.1 joerg *unsaved_files = 0; 288 1.1 joerg *num_unsaved_files = 0; 289 1.1 joerg return -1; 290 1.1 joerg } 291 1.1 joerg contents[unsaved->Length] = 0; 292 1.1 joerg unsaved->Contents = contents; 293 1.1 joerg 294 1.1 joerg /* Close the file. */ 295 1.1 joerg fclose(to_file); 296 1.1 joerg 297 1.1 joerg /* Copy the file name that we're remapping from. */ 298 1.1 joerg filename_len = sep - arg_string; 299 1.1 joerg filename = (char *)malloc(filename_len + 1); 300 1.1 joerg assert(filename); 301 1.1 joerg memcpy(filename, arg_string, filename_len); 302 1.1 joerg filename[filename_len] = 0; 303 1.1 joerg unsaved->Filename = filename; 304 1.1 joerg } 305 1.1 joerg 306 1.1 joerg return 0; 307 1.1 joerg } 308 1.1 joerg 309 1.1 joerg static int parse_remapped_files(int argc, const char **argv, int start_arg, 310 1.1 joerg struct CXUnsavedFile **unsaved_files, 311 1.1 joerg int *num_unsaved_files) { 312 1.1 joerg return parse_remapped_files_with_opt("-remap-file=", argc, argv, start_arg, 313 1.1 joerg unsaved_files, num_unsaved_files); 314 1.1 joerg } 315 1.1 joerg 316 1.1 joerg static int parse_remapped_files_with_try(int try_idx, 317 1.1 joerg int argc, const char **argv, 318 1.1 joerg int start_arg, 319 1.1 joerg struct CXUnsavedFile **unsaved_files, 320 1.1 joerg int *num_unsaved_files) { 321 1.1 joerg struct CXUnsavedFile *unsaved_files_no_try_idx; 322 1.1 joerg int num_unsaved_files_no_try_idx; 323 1.1 joerg struct CXUnsavedFile *unsaved_files_try_idx; 324 1.1 joerg int num_unsaved_files_try_idx; 325 1.1 joerg int ret; 326 1.1 joerg char opt_name[32]; 327 1.1 joerg 328 1.1 joerg ret = parse_remapped_files(argc, argv, start_arg, 329 1.1 joerg &unsaved_files_no_try_idx, &num_unsaved_files_no_try_idx); 330 1.1 joerg if (ret) 331 1.1 joerg return ret; 332 1.1 joerg 333 1.1 joerg sprintf(opt_name, "-remap-file-%d=", try_idx); 334 1.1 joerg ret = parse_remapped_files_with_opt(opt_name, argc, argv, start_arg, 335 1.1 joerg &unsaved_files_try_idx, &num_unsaved_files_try_idx); 336 1.1 joerg if (ret) 337 1.1 joerg return ret; 338 1.1 joerg 339 1.1 joerg if (num_unsaved_files_no_try_idx == 0) { 340 1.1 joerg *unsaved_files = unsaved_files_try_idx; 341 1.1 joerg *num_unsaved_files = num_unsaved_files_try_idx; 342 1.1 joerg return 0; 343 1.1 joerg } 344 1.1 joerg if (num_unsaved_files_try_idx == 0) { 345 1.1 joerg *unsaved_files = unsaved_files_no_try_idx; 346 1.1 joerg *num_unsaved_files = num_unsaved_files_no_try_idx; 347 1.1 joerg return 0; 348 1.1 joerg } 349 1.1 joerg 350 1.1 joerg *num_unsaved_files = num_unsaved_files_no_try_idx + num_unsaved_files_try_idx; 351 1.1 joerg *unsaved_files 352 1.1 joerg = (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx, 353 1.1 joerg sizeof(struct CXUnsavedFile) * 354 1.1 joerg *num_unsaved_files); 355 1.1 joerg assert(*unsaved_files); 356 1.1 joerg memcpy(*unsaved_files + num_unsaved_files_no_try_idx, 357 1.1 joerg unsaved_files_try_idx, sizeof(struct CXUnsavedFile) * 358 1.1 joerg num_unsaved_files_try_idx); 359 1.1 joerg free(unsaved_files_try_idx); 360 1.1 joerg return 0; 361 1.1 joerg } 362 1.1 joerg 363 1.1 joerg static const char *parse_comments_schema(int argc, const char **argv) { 364 1.1 joerg const char *CommentsSchemaArg = "-comments-xml-schema="; 365 1.1 joerg const char *CommentSchemaFile = NULL; 366 1.1 joerg 367 1.1 joerg if (argc == 0) 368 1.1 joerg return CommentSchemaFile; 369 1.1 joerg 370 1.1 joerg if (!strncmp(argv[0], CommentsSchemaArg, strlen(CommentsSchemaArg))) 371 1.1 joerg CommentSchemaFile = argv[0] + strlen(CommentsSchemaArg); 372 1.1 joerg 373 1.1 joerg return CommentSchemaFile; 374 1.1 joerg } 375 1.1 joerg 376 1.1 joerg /******************************************************************************/ 377 1.1 joerg /* Pretty-printing. */ 378 1.1 joerg /******************************************************************************/ 379 1.1 joerg 380 1.1 joerg static const char *FileCheckPrefix = "CHECK"; 381 1.1 joerg 382 1.1 joerg static void PrintCString(const char *CStr) { 383 1.1 joerg if (CStr != NULL && CStr[0] != '\0') { 384 1.1 joerg for ( ; *CStr; ++CStr) { 385 1.1 joerg const char C = *CStr; 386 1.1 joerg switch (C) { 387 1.1 joerg case '\n': printf("\\n"); break; 388 1.1 joerg case '\r': printf("\\r"); break; 389 1.1 joerg case '\t': printf("\\t"); break; 390 1.1 joerg case '\v': printf("\\v"); break; 391 1.1 joerg case '\f': printf("\\f"); break; 392 1.1 joerg default: putchar(C); break; 393 1.1 joerg } 394 1.1 joerg } 395 1.1 joerg } 396 1.1 joerg } 397 1.1 joerg 398 1.1 joerg static void PrintCStringWithPrefix(const char *Prefix, const char *CStr) { 399 1.1 joerg printf(" %s=[", Prefix); 400 1.1 joerg PrintCString(CStr); 401 1.1 joerg printf("]"); 402 1.1 joerg } 403 1.1 joerg 404 1.1 joerg static void PrintCXStringAndDispose(CXString Str) { 405 1.1 joerg PrintCString(clang_getCString(Str)); 406 1.1 joerg clang_disposeString(Str); 407 1.1 joerg } 408 1.1 joerg 409 1.1 joerg static void PrintCXStringWithPrefix(const char *Prefix, CXString Str) { 410 1.1 joerg PrintCStringWithPrefix(Prefix, clang_getCString(Str)); 411 1.1 joerg } 412 1.1 joerg 413 1.1 joerg static void PrintCXStringWithPrefixAndDispose(const char *Prefix, 414 1.1 joerg CXString Str) { 415 1.1 joerg PrintCStringWithPrefix(Prefix, clang_getCString(Str)); 416 1.1 joerg clang_disposeString(Str); 417 1.1 joerg } 418 1.1 joerg 419 1.1 joerg static void PrintRange(CXSourceRange R, const char *str) { 420 1.1 joerg CXFile begin_file, end_file; 421 1.1 joerg unsigned begin_line, begin_column, end_line, end_column; 422 1.1 joerg 423 1.1 joerg clang_getSpellingLocation(clang_getRangeStart(R), 424 1.1 joerg &begin_file, &begin_line, &begin_column, 0); 425 1.1 joerg clang_getSpellingLocation(clang_getRangeEnd(R), 426 1.1 joerg &end_file, &end_line, &end_column, 0); 427 1.1 joerg if (!begin_file || !end_file) 428 1.1 joerg return; 429 1.1 joerg 430 1.1 joerg if (str) 431 1.1 joerg printf(" %s=", str); 432 1.1 joerg PrintExtent(stdout, begin_line, begin_column, end_line, end_column); 433 1.1 joerg } 434 1.1 joerg 435 1.1 joerg static enum DisplayType { 436 1.1 joerg DisplayType_Spelling, 437 1.1 joerg DisplayType_DisplayName, 438 1.1 joerg DisplayType_Pretty 439 1.1 joerg } wanted_display_type = DisplayType_Spelling; 440 1.1 joerg 441 1.1 joerg static void printVersion(const char *Prefix, CXVersion Version) { 442 1.1 joerg if (Version.Major < 0) 443 1.1 joerg return; 444 1.1 joerg printf("%s%d", Prefix, Version.Major); 445 1.1 joerg 446 1.1 joerg if (Version.Minor < 0) 447 1.1 joerg return; 448 1.1 joerg printf(".%d", Version.Minor); 449 1.1 joerg 450 1.1 joerg if (Version.Subminor < 0) 451 1.1 joerg return; 452 1.1 joerg printf(".%d", Version.Subminor); 453 1.1 joerg } 454 1.1 joerg 455 1.1 joerg struct CommentASTDumpingContext { 456 1.1 joerg int IndentLevel; 457 1.1 joerg }; 458 1.1 joerg 459 1.1 joerg static void DumpCXCommentInternal(struct CommentASTDumpingContext *Ctx, 460 1.1 joerg CXComment Comment) { 461 1.1 joerg unsigned i; 462 1.1 joerg unsigned e; 463 1.1 joerg enum CXCommentKind Kind = clang_Comment_getKind(Comment); 464 1.1 joerg 465 1.1 joerg Ctx->IndentLevel++; 466 1.1 joerg for (i = 0, e = Ctx->IndentLevel; i != e; ++i) 467 1.1 joerg printf(" "); 468 1.1 joerg 469 1.1 joerg printf("("); 470 1.1 joerg switch (Kind) { 471 1.1 joerg case CXComment_Null: 472 1.1 joerg printf("CXComment_Null"); 473 1.1 joerg break; 474 1.1 joerg case CXComment_Text: 475 1.1 joerg printf("CXComment_Text"); 476 1.1 joerg PrintCXStringWithPrefixAndDispose("Text", 477 1.1 joerg clang_TextComment_getText(Comment)); 478 1.1 joerg if (clang_Comment_isWhitespace(Comment)) 479 1.1 joerg printf(" IsWhitespace"); 480 1.1 joerg if (clang_InlineContentComment_hasTrailingNewline(Comment)) 481 1.1 joerg printf(" HasTrailingNewline"); 482 1.1 joerg break; 483 1.1 joerg case CXComment_InlineCommand: 484 1.1 joerg printf("CXComment_InlineCommand"); 485 1.1 joerg PrintCXStringWithPrefixAndDispose( 486 1.1 joerg "CommandName", 487 1.1 joerg clang_InlineCommandComment_getCommandName(Comment)); 488 1.1 joerg switch (clang_InlineCommandComment_getRenderKind(Comment)) { 489 1.1 joerg case CXCommentInlineCommandRenderKind_Normal: 490 1.1 joerg printf(" RenderNormal"); 491 1.1 joerg break; 492 1.1 joerg case CXCommentInlineCommandRenderKind_Bold: 493 1.1 joerg printf(" RenderBold"); 494 1.1 joerg break; 495 1.1 joerg case CXCommentInlineCommandRenderKind_Monospaced: 496 1.1 joerg printf(" RenderMonospaced"); 497 1.1 joerg break; 498 1.1 joerg case CXCommentInlineCommandRenderKind_Emphasized: 499 1.1 joerg printf(" RenderEmphasized"); 500 1.1 joerg break; 501 1.1.1.2 joerg case CXCommentInlineCommandRenderKind_Anchor: 502 1.1.1.2 joerg printf(" RenderAnchor"); 503 1.1.1.2 joerg break; 504 1.1 joerg } 505 1.1 joerg for (i = 0, e = clang_InlineCommandComment_getNumArgs(Comment); 506 1.1 joerg i != e; ++i) { 507 1.1 joerg printf(" Arg[%u]=", i); 508 1.1 joerg PrintCXStringAndDispose( 509 1.1 joerg clang_InlineCommandComment_getArgText(Comment, i)); 510 1.1 joerg } 511 1.1 joerg if (clang_InlineContentComment_hasTrailingNewline(Comment)) 512 1.1 joerg printf(" HasTrailingNewline"); 513 1.1 joerg break; 514 1.1 joerg case CXComment_HTMLStartTag: { 515 1.1 joerg unsigned NumAttrs; 516 1.1 joerg printf("CXComment_HTMLStartTag"); 517 1.1 joerg PrintCXStringWithPrefixAndDispose( 518 1.1 joerg "Name", 519 1.1 joerg clang_HTMLTagComment_getTagName(Comment)); 520 1.1 joerg NumAttrs = clang_HTMLStartTag_getNumAttrs(Comment); 521 1.1 joerg if (NumAttrs != 0) { 522 1.1 joerg printf(" Attrs:"); 523 1.1 joerg for (i = 0; i != NumAttrs; ++i) { 524 1.1 joerg printf(" "); 525 1.1 joerg PrintCXStringAndDispose(clang_HTMLStartTag_getAttrName(Comment, i)); 526 1.1 joerg printf("="); 527 1.1 joerg PrintCXStringAndDispose(clang_HTMLStartTag_getAttrValue(Comment, i)); 528 1.1 joerg } 529 1.1 joerg } 530 1.1 joerg if (clang_HTMLStartTagComment_isSelfClosing(Comment)) 531 1.1 joerg printf(" SelfClosing"); 532 1.1 joerg if (clang_InlineContentComment_hasTrailingNewline(Comment)) 533 1.1 joerg printf(" HasTrailingNewline"); 534 1.1 joerg break; 535 1.1 joerg } 536 1.1 joerg case CXComment_HTMLEndTag: 537 1.1 joerg printf("CXComment_HTMLEndTag"); 538 1.1 joerg PrintCXStringWithPrefixAndDispose( 539 1.1 joerg "Name", 540 1.1 joerg clang_HTMLTagComment_getTagName(Comment)); 541 1.1 joerg if (clang_InlineContentComment_hasTrailingNewline(Comment)) 542 1.1 joerg printf(" HasTrailingNewline"); 543 1.1 joerg break; 544 1.1 joerg case CXComment_Paragraph: 545 1.1 joerg printf("CXComment_Paragraph"); 546 1.1 joerg if (clang_Comment_isWhitespace(Comment)) 547 1.1 joerg printf(" IsWhitespace"); 548 1.1 joerg break; 549 1.1 joerg case CXComment_BlockCommand: 550 1.1 joerg printf("CXComment_BlockCommand"); 551 1.1 joerg PrintCXStringWithPrefixAndDispose( 552 1.1 joerg "CommandName", 553 1.1 joerg clang_BlockCommandComment_getCommandName(Comment)); 554 1.1 joerg for (i = 0, e = clang_BlockCommandComment_getNumArgs(Comment); 555 1.1 joerg i != e; ++i) { 556 1.1 joerg printf(" Arg[%u]=", i); 557 1.1 joerg PrintCXStringAndDispose( 558 1.1 joerg clang_BlockCommandComment_getArgText(Comment, i)); 559 1.1 joerg } 560 1.1 joerg break; 561 1.1 joerg case CXComment_ParamCommand: 562 1.1 joerg printf("CXComment_ParamCommand"); 563 1.1 joerg switch (clang_ParamCommandComment_getDirection(Comment)) { 564 1.1 joerg case CXCommentParamPassDirection_In: 565 1.1 joerg printf(" in"); 566 1.1 joerg break; 567 1.1 joerg case CXCommentParamPassDirection_Out: 568 1.1 joerg printf(" out"); 569 1.1 joerg break; 570 1.1 joerg case CXCommentParamPassDirection_InOut: 571 1.1 joerg printf(" in,out"); 572 1.1 joerg break; 573 1.1 joerg } 574 1.1 joerg if (clang_ParamCommandComment_isDirectionExplicit(Comment)) 575 1.1 joerg printf(" explicitly"); 576 1.1 joerg else 577 1.1 joerg printf(" implicitly"); 578 1.1 joerg PrintCXStringWithPrefixAndDispose( 579 1.1 joerg "ParamName", 580 1.1 joerg clang_ParamCommandComment_getParamName(Comment)); 581 1.1 joerg if (clang_ParamCommandComment_isParamIndexValid(Comment)) 582 1.1 joerg printf(" ParamIndex=%u", clang_ParamCommandComment_getParamIndex(Comment)); 583 1.1 joerg else 584 1.1 joerg printf(" ParamIndex=Invalid"); 585 1.1 joerg break; 586 1.1 joerg case CXComment_TParamCommand: 587 1.1 joerg printf("CXComment_TParamCommand"); 588 1.1 joerg PrintCXStringWithPrefixAndDispose( 589 1.1 joerg "ParamName", 590 1.1 joerg clang_TParamCommandComment_getParamName(Comment)); 591 1.1 joerg if (clang_TParamCommandComment_isParamPositionValid(Comment)) { 592 1.1 joerg printf(" ParamPosition={"); 593 1.1 joerg for (i = 0, e = clang_TParamCommandComment_getDepth(Comment); 594 1.1 joerg i != e; ++i) { 595 1.1 joerg printf("%u", clang_TParamCommandComment_getIndex(Comment, i)); 596 1.1 joerg if (i != e - 1) 597 1.1 joerg printf(", "); 598 1.1 joerg } 599 1.1 joerg printf("}"); 600 1.1 joerg } else 601 1.1 joerg printf(" ParamPosition=Invalid"); 602 1.1 joerg break; 603 1.1 joerg case CXComment_VerbatimBlockCommand: 604 1.1 joerg printf("CXComment_VerbatimBlockCommand"); 605 1.1 joerg PrintCXStringWithPrefixAndDispose( 606 1.1 joerg "CommandName", 607 1.1 joerg clang_BlockCommandComment_getCommandName(Comment)); 608 1.1 joerg break; 609 1.1 joerg case CXComment_VerbatimBlockLine: 610 1.1 joerg printf("CXComment_VerbatimBlockLine"); 611 1.1 joerg PrintCXStringWithPrefixAndDispose( 612 1.1 joerg "Text", 613 1.1 joerg clang_VerbatimBlockLineComment_getText(Comment)); 614 1.1 joerg break; 615 1.1 joerg case CXComment_VerbatimLine: 616 1.1 joerg printf("CXComment_VerbatimLine"); 617 1.1 joerg PrintCXStringWithPrefixAndDispose( 618 1.1 joerg "Text", 619 1.1 joerg clang_VerbatimLineComment_getText(Comment)); 620 1.1 joerg break; 621 1.1 joerg case CXComment_FullComment: 622 1.1 joerg printf("CXComment_FullComment"); 623 1.1 joerg break; 624 1.1 joerg } 625 1.1 joerg if (Kind != CXComment_Null) { 626 1.1 joerg const unsigned NumChildren = clang_Comment_getNumChildren(Comment); 627 1.1 joerg unsigned i; 628 1.1 joerg for (i = 0; i != NumChildren; ++i) { 629 1.1 joerg printf("\n// %s: ", FileCheckPrefix); 630 1.1 joerg DumpCXCommentInternal(Ctx, clang_Comment_getChild(Comment, i)); 631 1.1 joerg } 632 1.1 joerg } 633 1.1 joerg printf(")"); 634 1.1 joerg Ctx->IndentLevel--; 635 1.1 joerg } 636 1.1 joerg 637 1.1 joerg static void DumpCXComment(CXComment Comment) { 638 1.1 joerg struct CommentASTDumpingContext Ctx; 639 1.1 joerg Ctx.IndentLevel = 1; 640 1.1 joerg printf("\n// %s: CommentAST=[\n// %s:", FileCheckPrefix, FileCheckPrefix); 641 1.1 joerg DumpCXCommentInternal(&Ctx, Comment); 642 1.1 joerg printf("]"); 643 1.1 joerg } 644 1.1 joerg 645 1.1 joerg static void ValidateCommentXML(const char *Str, const char *CommentSchemaFile) { 646 1.1 joerg #ifdef CLANG_HAVE_LIBXML 647 1.1 joerg xmlRelaxNGParserCtxtPtr RNGParser; 648 1.1 joerg xmlRelaxNGPtr Schema; 649 1.1 joerg xmlDocPtr Doc; 650 1.1 joerg xmlRelaxNGValidCtxtPtr ValidationCtxt; 651 1.1 joerg int status; 652 1.1 joerg 653 1.1 joerg if (!CommentSchemaFile) 654 1.1 joerg return; 655 1.1 joerg 656 1.1 joerg RNGParser = xmlRelaxNGNewParserCtxt(CommentSchemaFile); 657 1.1 joerg if (!RNGParser) { 658 1.1 joerg printf(" libXMLError"); 659 1.1 joerg return; 660 1.1 joerg } 661 1.1 joerg Schema = xmlRelaxNGParse(RNGParser); 662 1.1 joerg 663 1.1 joerg Doc = xmlParseDoc((const xmlChar *) Str); 664 1.1 joerg 665 1.1 joerg if (!Doc) { 666 1.1 joerg xmlErrorPtr Error = xmlGetLastError(); 667 1.1 joerg printf(" CommentXMLInvalid [not well-formed XML: %s]", Error->message); 668 1.1 joerg return; 669 1.1 joerg } 670 1.1 joerg 671 1.1 joerg ValidationCtxt = xmlRelaxNGNewValidCtxt(Schema); 672 1.1 joerg status = xmlRelaxNGValidateDoc(ValidationCtxt, Doc); 673 1.1 joerg if (!status) 674 1.1 joerg printf(" CommentXMLValid"); 675 1.1 joerg else if (status > 0) { 676 1.1 joerg xmlErrorPtr Error = xmlGetLastError(); 677 1.1 joerg printf(" CommentXMLInvalid [not valid XML: %s]", Error->message); 678 1.1 joerg } else 679 1.1 joerg printf(" libXMLError"); 680 1.1 joerg 681 1.1 joerg xmlRelaxNGFreeValidCtxt(ValidationCtxt); 682 1.1 joerg xmlFreeDoc(Doc); 683 1.1 joerg xmlRelaxNGFree(Schema); 684 1.1 joerg xmlRelaxNGFreeParserCtxt(RNGParser); 685 1.1 joerg #endif 686 1.1 joerg } 687 1.1 joerg 688 1.1 joerg static void PrintCursorComments(CXCursor Cursor, 689 1.1 joerg const char *CommentSchemaFile) { 690 1.1 joerg { 691 1.1 joerg CXString RawComment; 692 1.1 joerg const char *RawCommentCString; 693 1.1 joerg CXString BriefComment; 694 1.1 joerg const char *BriefCommentCString; 695 1.1 joerg 696 1.1 joerg RawComment = clang_Cursor_getRawCommentText(Cursor); 697 1.1 joerg RawCommentCString = clang_getCString(RawComment); 698 1.1 joerg if (RawCommentCString != NULL && RawCommentCString[0] != '\0') { 699 1.1 joerg PrintCStringWithPrefix("RawComment", RawCommentCString); 700 1.1 joerg PrintRange(clang_Cursor_getCommentRange(Cursor), "RawCommentRange"); 701 1.1 joerg 702 1.1 joerg BriefComment = clang_Cursor_getBriefCommentText(Cursor); 703 1.1 joerg BriefCommentCString = clang_getCString(BriefComment); 704 1.1 joerg if (BriefCommentCString != NULL && BriefCommentCString[0] != '\0') 705 1.1 joerg PrintCStringWithPrefix("BriefComment", BriefCommentCString); 706 1.1 joerg clang_disposeString(BriefComment); 707 1.1 joerg } 708 1.1 joerg clang_disposeString(RawComment); 709 1.1 joerg } 710 1.1 joerg 711 1.1 joerg { 712 1.1 joerg CXComment Comment = clang_Cursor_getParsedComment(Cursor); 713 1.1 joerg if (clang_Comment_getKind(Comment) != CXComment_Null) { 714 1.1 joerg PrintCXStringWithPrefixAndDispose("FullCommentAsHTML", 715 1.1 joerg clang_FullComment_getAsHTML(Comment)); 716 1.1 joerg { 717 1.1 joerg CXString XML; 718 1.1 joerg XML = clang_FullComment_getAsXML(Comment); 719 1.1 joerg PrintCXStringWithPrefix("FullCommentAsXML", XML); 720 1.1 joerg ValidateCommentXML(clang_getCString(XML), CommentSchemaFile); 721 1.1 joerg clang_disposeString(XML); 722 1.1 joerg } 723 1.1 joerg 724 1.1 joerg DumpCXComment(Comment); 725 1.1 joerg } 726 1.1 joerg } 727 1.1 joerg } 728 1.1 joerg 729 1.1 joerg typedef struct { 730 1.1 joerg unsigned line; 731 1.1 joerg unsigned col; 732 1.1 joerg } LineCol; 733 1.1 joerg 734 1.1 joerg static int lineCol_cmp(const void *p1, const void *p2) { 735 1.1 joerg const LineCol *lhs = p1; 736 1.1 joerg const LineCol *rhs = p2; 737 1.1 joerg if (lhs->line != rhs->line) 738 1.1 joerg return (int)lhs->line - (int)rhs->line; 739 1.1 joerg return (int)lhs->col - (int)rhs->col; 740 1.1 joerg } 741 1.1 joerg 742 1.1 joerg static CXString CursorToText(CXCursor Cursor) { 743 1.1 joerg CXString text; 744 1.1 joerg switch (wanted_display_type) { 745 1.1 joerg case DisplayType_Spelling: 746 1.1 joerg return clang_getCursorSpelling(Cursor); 747 1.1 joerg case DisplayType_DisplayName: 748 1.1 joerg return clang_getCursorDisplayName(Cursor); 749 1.1 joerg case DisplayType_Pretty: { 750 1.1 joerg CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor); 751 1.1 joerg ModifyPrintingPolicyAccordingToEnv(Policy); 752 1.1 joerg text = clang_getCursorPrettyPrinted(Cursor, Policy); 753 1.1 joerg clang_PrintingPolicy_dispose(Policy); 754 1.1 joerg return text; 755 1.1 joerg } 756 1.1 joerg } 757 1.1 joerg assert(0 && "unknown display type"); /* no llvm_unreachable in C. */ 758 1.1 joerg /* Set to NULL to prevent uninitialized variable warnings. */ 759 1.1 joerg text.data = NULL; 760 1.1 joerg text.private_flags = 0; 761 1.1 joerg return text; 762 1.1 joerg } 763 1.1 joerg 764 1.1 joerg static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { 765 1.1 joerg CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); 766 1.1 joerg if (clang_isInvalid(Cursor.kind)) { 767 1.1 joerg CXString ks = clang_getCursorKindSpelling(Cursor.kind); 768 1.1 joerg printf("Invalid Cursor => %s", clang_getCString(ks)); 769 1.1 joerg clang_disposeString(ks); 770 1.1 joerg } 771 1.1 joerg else { 772 1.1 joerg CXString string, ks; 773 1.1 joerg CXCursor Referenced; 774 1.1 joerg unsigned line, column; 775 1.1 joerg CXCursor SpecializationOf; 776 1.1 joerg CXCursor *overridden; 777 1.1 joerg unsigned num_overridden; 778 1.1 joerg unsigned RefNameRangeNr; 779 1.1 joerg CXSourceRange CursorExtent; 780 1.1 joerg CXSourceRange RefNameRange; 781 1.1 joerg int AlwaysUnavailable; 782 1.1 joerg int AlwaysDeprecated; 783 1.1 joerg CXString UnavailableMessage; 784 1.1 joerg CXString DeprecatedMessage; 785 1.1 joerg CXPlatformAvailability PlatformAvailability[2]; 786 1.1 joerg int NumPlatformAvailability; 787 1.1 joerg int I; 788 1.1 joerg 789 1.1 joerg ks = clang_getCursorKindSpelling(Cursor.kind); 790 1.1 joerg string = CursorToText(Cursor); 791 1.1 joerg printf("%s=%s", clang_getCString(ks), 792 1.1 joerg clang_getCString(string)); 793 1.1 joerg clang_disposeString(ks); 794 1.1 joerg clang_disposeString(string); 795 1.1 joerg 796 1.1 joerg Referenced = clang_getCursorReferenced(Cursor); 797 1.1 joerg if (!clang_equalCursors(Referenced, clang_getNullCursor())) { 798 1.1 joerg if (clang_getCursorKind(Referenced) == CXCursor_OverloadedDeclRef) { 799 1.1 joerg unsigned I, N = clang_getNumOverloadedDecls(Referenced); 800 1.1 joerg printf("["); 801 1.1 joerg for (I = 0; I != N; ++I) { 802 1.1 joerg CXCursor Ovl = clang_getOverloadedDecl(Referenced, I); 803 1.1 joerg CXSourceLocation Loc; 804 1.1 joerg if (I) 805 1.1 joerg printf(", "); 806 1.1 joerg 807 1.1 joerg Loc = clang_getCursorLocation(Ovl); 808 1.1 joerg clang_getSpellingLocation(Loc, 0, &line, &column, 0); 809 1.1 joerg printf("%d:%d", line, column); 810 1.1 joerg } 811 1.1 joerg printf("]"); 812 1.1 joerg } else { 813 1.1 joerg CXSourceLocation Loc = clang_getCursorLocation(Referenced); 814 1.1 joerg clang_getSpellingLocation(Loc, 0, &line, &column, 0); 815 1.1 joerg printf(":%d:%d", line, column); 816 1.1 joerg } 817 1.1 joerg 818 1.1 joerg if (clang_getCursorKind(Referenced) == CXCursor_TypedefDecl) { 819 1.1 joerg CXType T = clang_getCursorType(Referenced); 820 1.1 joerg if (clang_Type_isTransparentTagTypedef(T)) { 821 1.1 joerg CXType Underlying = clang_getTypedefDeclUnderlyingType(Referenced); 822 1.1 joerg CXString S = clang_getTypeSpelling(Underlying); 823 1.1 joerg printf(" (Transparent: %s)", clang_getCString(S)); 824 1.1 joerg clang_disposeString(S); 825 1.1 joerg } 826 1.1 joerg } 827 1.1 joerg } 828 1.1 joerg 829 1.1 joerg if (clang_isCursorDefinition(Cursor)) 830 1.1 joerg printf(" (Definition)"); 831 1.1 joerg 832 1.1 joerg switch (clang_getCursorAvailability(Cursor)) { 833 1.1 joerg case CXAvailability_Available: 834 1.1 joerg break; 835 1.1 joerg 836 1.1 joerg case CXAvailability_Deprecated: 837 1.1 joerg printf(" (deprecated)"); 838 1.1 joerg break; 839 1.1 joerg 840 1.1 joerg case CXAvailability_NotAvailable: 841 1.1 joerg printf(" (unavailable)"); 842 1.1 joerg break; 843 1.1 joerg 844 1.1 joerg case CXAvailability_NotAccessible: 845 1.1 joerg printf(" (inaccessible)"); 846 1.1 joerg break; 847 1.1 joerg } 848 1.1 joerg 849 1.1 joerg NumPlatformAvailability 850 1.1 joerg = clang_getCursorPlatformAvailability(Cursor, 851 1.1 joerg &AlwaysDeprecated, 852 1.1 joerg &DeprecatedMessage, 853 1.1 joerg &AlwaysUnavailable, 854 1.1 joerg &UnavailableMessage, 855 1.1 joerg PlatformAvailability, 2); 856 1.1 joerg if (AlwaysUnavailable) { 857 1.1 joerg printf(" (always unavailable: \"%s\")", 858 1.1 joerg clang_getCString(UnavailableMessage)); 859 1.1 joerg } else if (AlwaysDeprecated) { 860 1.1 joerg printf(" (always deprecated: \"%s\")", 861 1.1 joerg clang_getCString(DeprecatedMessage)); 862 1.1 joerg } else { 863 1.1 joerg for (I = 0; I != NumPlatformAvailability; ++I) { 864 1.1 joerg if (I >= 2) 865 1.1 joerg break; 866 1.1 joerg 867 1.1 joerg printf(" (%s", clang_getCString(PlatformAvailability[I].Platform)); 868 1.1 joerg if (PlatformAvailability[I].Unavailable) 869 1.1 joerg printf(", unavailable"); 870 1.1 joerg else { 871 1.1 joerg printVersion(", introduced=", PlatformAvailability[I].Introduced); 872 1.1 joerg printVersion(", deprecated=", PlatformAvailability[I].Deprecated); 873 1.1 joerg printVersion(", obsoleted=", PlatformAvailability[I].Obsoleted); 874 1.1 joerg } 875 1.1 joerg if (clang_getCString(PlatformAvailability[I].Message)[0]) 876 1.1 joerg printf(", message=\"%s\"", 877 1.1 joerg clang_getCString(PlatformAvailability[I].Message)); 878 1.1 joerg printf(")"); 879 1.1 joerg } 880 1.1 joerg } 881 1.1 joerg for (I = 0; I != NumPlatformAvailability; ++I) { 882 1.1 joerg if (I >= 2) 883 1.1 joerg break; 884 1.1 joerg clang_disposeCXPlatformAvailability(PlatformAvailability + I); 885 1.1 joerg } 886 1.1 joerg 887 1.1 joerg clang_disposeString(DeprecatedMessage); 888 1.1 joerg clang_disposeString(UnavailableMessage); 889 1.1 joerg 890 1.1 joerg if (clang_CXXConstructor_isDefaultConstructor(Cursor)) 891 1.1 joerg printf(" (default constructor)"); 892 1.1 joerg 893 1.1 joerg if (clang_CXXConstructor_isMoveConstructor(Cursor)) 894 1.1 joerg printf(" (move constructor)"); 895 1.1 joerg if (clang_CXXConstructor_isCopyConstructor(Cursor)) 896 1.1 joerg printf(" (copy constructor)"); 897 1.1 joerg if (clang_CXXConstructor_isConvertingConstructor(Cursor)) 898 1.1 joerg printf(" (converting constructor)"); 899 1.1 joerg if (clang_CXXField_isMutable(Cursor)) 900 1.1 joerg printf(" (mutable)"); 901 1.1 joerg if (clang_CXXMethod_isDefaulted(Cursor)) 902 1.1 joerg printf(" (defaulted)"); 903 1.1 joerg if (clang_CXXMethod_isStatic(Cursor)) 904 1.1 joerg printf(" (static)"); 905 1.1 joerg if (clang_CXXMethod_isVirtual(Cursor)) 906 1.1 joerg printf(" (virtual)"); 907 1.1 joerg if (clang_CXXMethod_isConst(Cursor)) 908 1.1 joerg printf(" (const)"); 909 1.1 joerg if (clang_CXXMethod_isPureVirtual(Cursor)) 910 1.1 joerg printf(" (pure)"); 911 1.1 joerg if (clang_CXXRecord_isAbstract(Cursor)) 912 1.1 joerg printf(" (abstract)"); 913 1.1 joerg if (clang_EnumDecl_isScoped(Cursor)) 914 1.1 joerg printf(" (scoped)"); 915 1.1 joerg if (clang_Cursor_isVariadic(Cursor)) 916 1.1 joerg printf(" (variadic)"); 917 1.1 joerg if (clang_Cursor_isObjCOptional(Cursor)) 918 1.1 joerg printf(" (@optional)"); 919 1.1 joerg if (clang_isInvalidDeclaration(Cursor)) 920 1.1 joerg printf(" (invalid)"); 921 1.1 joerg 922 1.1 joerg switch (clang_getCursorExceptionSpecificationType(Cursor)) 923 1.1 joerg { 924 1.1 joerg case CXCursor_ExceptionSpecificationKind_None: 925 1.1 joerg break; 926 1.1 joerg 927 1.1 joerg case CXCursor_ExceptionSpecificationKind_DynamicNone: 928 1.1 joerg printf(" (noexcept dynamic none)"); 929 1.1 joerg break; 930 1.1 joerg 931 1.1 joerg case CXCursor_ExceptionSpecificationKind_Dynamic: 932 1.1 joerg printf(" (noexcept dynamic)"); 933 1.1 joerg break; 934 1.1 joerg 935 1.1 joerg case CXCursor_ExceptionSpecificationKind_MSAny: 936 1.1 joerg printf(" (noexcept dynamic any)"); 937 1.1 joerg break; 938 1.1 joerg 939 1.1 joerg case CXCursor_ExceptionSpecificationKind_BasicNoexcept: 940 1.1 joerg printf(" (noexcept)"); 941 1.1 joerg break; 942 1.1 joerg 943 1.1 joerg case CXCursor_ExceptionSpecificationKind_ComputedNoexcept: 944 1.1 joerg printf(" (computed-noexcept)"); 945 1.1 joerg break; 946 1.1 joerg 947 1.1 joerg case CXCursor_ExceptionSpecificationKind_Unevaluated: 948 1.1 joerg case CXCursor_ExceptionSpecificationKind_Uninstantiated: 949 1.1 joerg case CXCursor_ExceptionSpecificationKind_Unparsed: 950 1.1 joerg break; 951 1.1 joerg } 952 1.1 joerg 953 1.1 joerg { 954 1.1 joerg CXString language; 955 1.1 joerg CXString definedIn; 956 1.1 joerg unsigned generated; 957 1.1 joerg if (clang_Cursor_isExternalSymbol(Cursor, &language, &definedIn, 958 1.1 joerg &generated)) { 959 1.1 joerg printf(" (external lang: %s, defined: %s, gen: %d)", 960 1.1 joerg clang_getCString(language), clang_getCString(definedIn), generated); 961 1.1 joerg clang_disposeString(language); 962 1.1 joerg clang_disposeString(definedIn); 963 1.1 joerg } 964 1.1 joerg } 965 1.1 joerg 966 1.1 joerg if (Cursor.kind == CXCursor_IBOutletCollectionAttr) { 967 1.1 joerg CXType T = 968 1.1 joerg clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor)); 969 1.1 joerg CXString S = clang_getTypeKindSpelling(T.kind); 970 1.1 joerg printf(" [IBOutletCollection=%s]", clang_getCString(S)); 971 1.1 joerg clang_disposeString(S); 972 1.1 joerg } 973 1.1 joerg 974 1.1 joerg if (Cursor.kind == CXCursor_CXXBaseSpecifier) { 975 1.1 joerg enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor); 976 1.1 joerg unsigned isVirtual = clang_isVirtualBase(Cursor); 977 1.1 joerg const char *accessStr = 0; 978 1.1 joerg 979 1.1 joerg switch (access) { 980 1.1 joerg case CX_CXXInvalidAccessSpecifier: 981 1.1 joerg accessStr = "invalid"; break; 982 1.1 joerg case CX_CXXPublic: 983 1.1 joerg accessStr = "public"; break; 984 1.1 joerg case CX_CXXProtected: 985 1.1 joerg accessStr = "protected"; break; 986 1.1 joerg case CX_CXXPrivate: 987 1.1 joerg accessStr = "private"; break; 988 1.1 joerg } 989 1.1 joerg 990 1.1 joerg printf(" [access=%s isVirtual=%s]", accessStr, 991 1.1 joerg isVirtual ? "true" : "false"); 992 1.1 joerg } 993 1.1 joerg 994 1.1 joerg SpecializationOf = clang_getSpecializedCursorTemplate(Cursor); 995 1.1 joerg if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) { 996 1.1 joerg CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf); 997 1.1 joerg CXString Name = clang_getCursorSpelling(SpecializationOf); 998 1.1 joerg clang_getSpellingLocation(Loc, 0, &line, &column, 0); 999 1.1 joerg printf(" [Specialization of %s:%d:%d]", 1000 1.1 joerg clang_getCString(Name), line, column); 1001 1.1 joerg clang_disposeString(Name); 1002 1.1 joerg 1003 1.1 joerg if (Cursor.kind == CXCursor_FunctionDecl) { 1004 1.1 joerg /* Collect the template parameter kinds from the base template. */ 1005 1.1 joerg int NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor); 1006 1.1 joerg int I; 1007 1.1 joerg if (NumTemplateArgs < 0) { 1008 1.1 joerg printf(" [no template arg info]"); 1009 1.1 joerg } 1010 1.1 joerg for (I = 0; I < NumTemplateArgs; I++) { 1011 1.1 joerg enum CXTemplateArgumentKind TAK = 1012 1.1 joerg clang_Cursor_getTemplateArgumentKind(Cursor, I); 1013 1.1 joerg switch(TAK) { 1014 1.1 joerg case CXTemplateArgumentKind_Type: 1015 1.1 joerg { 1016 1.1 joerg CXType T = clang_Cursor_getTemplateArgumentType(Cursor, I); 1017 1.1 joerg CXString S = clang_getTypeSpelling(T); 1018 1.1 joerg printf(" [Template arg %d: kind: %d, type: %s]", 1019 1.1 joerg I, TAK, clang_getCString(S)); 1020 1.1 joerg clang_disposeString(S); 1021 1.1 joerg } 1022 1.1 joerg break; 1023 1.1 joerg case CXTemplateArgumentKind_Integral: 1024 1.1 joerg printf(" [Template arg %d: kind: %d, intval: %lld]", 1025 1.1 joerg I, TAK, clang_Cursor_getTemplateArgumentValue(Cursor, I)); 1026 1.1 joerg break; 1027 1.1 joerg default: 1028 1.1 joerg printf(" [Template arg %d: kind: %d]\n", I, TAK); 1029 1.1 joerg } 1030 1.1 joerg } 1031 1.1 joerg } 1032 1.1 joerg } 1033 1.1 joerg 1034 1.1 joerg clang_getOverriddenCursors(Cursor, &overridden, &num_overridden); 1035 1.1 joerg if (num_overridden) { 1036 1.1 joerg unsigned I; 1037 1.1 joerg LineCol lineCols[50]; 1038 1.1 joerg assert(num_overridden <= 50); 1039 1.1 joerg printf(" [Overrides "); 1040 1.1 joerg for (I = 0; I != num_overridden; ++I) { 1041 1.1 joerg CXSourceLocation Loc = clang_getCursorLocation(overridden[I]); 1042 1.1 joerg clang_getSpellingLocation(Loc, 0, &line, &column, 0); 1043 1.1 joerg lineCols[I].line = line; 1044 1.1 joerg lineCols[I].col = column; 1045 1.1 joerg } 1046 1.1 joerg /* Make the order of the override list deterministic. */ 1047 1.1 joerg qsort(lineCols, num_overridden, sizeof(LineCol), lineCol_cmp); 1048 1.1 joerg for (I = 0; I != num_overridden; ++I) { 1049 1.1 joerg if (I) 1050 1.1 joerg printf(", "); 1051 1.1 joerg printf("@%d:%d", lineCols[I].line, lineCols[I].col); 1052 1.1 joerg } 1053 1.1 joerg printf("]"); 1054 1.1 joerg clang_disposeOverriddenCursors(overridden); 1055 1.1 joerg } 1056 1.1 joerg 1057 1.1 joerg if (Cursor.kind == CXCursor_InclusionDirective) { 1058 1.1 joerg CXFile File = clang_getIncludedFile(Cursor); 1059 1.1 joerg CXString Included = clang_getFileName(File); 1060 1.1 joerg const char *IncludedString = clang_getCString(Included); 1061 1.1 joerg printf(" (%s)", IncludedString ? IncludedString : "(null)"); 1062 1.1 joerg clang_disposeString(Included); 1063 1.1 joerg 1064 1.1 joerg if (clang_isFileMultipleIncludeGuarded(TU, File)) 1065 1.1 joerg printf(" [multi-include guarded]"); 1066 1.1 joerg } 1067 1.1 joerg 1068 1.1 joerg CursorExtent = clang_getCursorExtent(Cursor); 1069 1.1 joerg RefNameRange = clang_getCursorReferenceNameRange(Cursor, 1070 1.1 joerg CXNameRange_WantQualifier 1071 1.1 joerg | CXNameRange_WantSinglePiece 1072 1.1 joerg | CXNameRange_WantTemplateArgs, 1073 1.1 joerg 0); 1074 1.1 joerg if (!clang_equalRanges(CursorExtent, RefNameRange)) 1075 1.1 joerg PrintRange(RefNameRange, "SingleRefName"); 1076 1.1 joerg 1077 1.1 joerg for (RefNameRangeNr = 0; 1; RefNameRangeNr++) { 1078 1.1 joerg RefNameRange = clang_getCursorReferenceNameRange(Cursor, 1079 1.1 joerg CXNameRange_WantQualifier 1080 1.1 joerg | CXNameRange_WantTemplateArgs, 1081 1.1 joerg RefNameRangeNr); 1082 1.1 joerg if (clang_equalRanges(clang_getNullRange(), RefNameRange)) 1083 1.1 joerg break; 1084 1.1 joerg if (!clang_equalRanges(CursorExtent, RefNameRange)) 1085 1.1 joerg PrintRange(RefNameRange, "RefName"); 1086 1.1 joerg } 1087 1.1 joerg 1088 1.1 joerg PrintCursorComments(Cursor, CommentSchemaFile); 1089 1.1 joerg 1090 1.1 joerg { 1091 1.1 joerg unsigned PropAttrs = clang_Cursor_getObjCPropertyAttributes(Cursor, 0); 1092 1.1 joerg if (PropAttrs != CXObjCPropertyAttr_noattr) { 1093 1.1 joerg printf(" ["); 1094 1.1 joerg #define PRINT_PROP_ATTR(A) \ 1095 1.1 joerg if (PropAttrs & CXObjCPropertyAttr_##A) printf(#A ",") 1096 1.1 joerg PRINT_PROP_ATTR(readonly); 1097 1.1 joerg PRINT_PROP_ATTR(getter); 1098 1.1 joerg PRINT_PROP_ATTR(assign); 1099 1.1 joerg PRINT_PROP_ATTR(readwrite); 1100 1.1 joerg PRINT_PROP_ATTR(retain); 1101 1.1 joerg PRINT_PROP_ATTR(copy); 1102 1.1 joerg PRINT_PROP_ATTR(nonatomic); 1103 1.1 joerg PRINT_PROP_ATTR(setter); 1104 1.1 joerg PRINT_PROP_ATTR(atomic); 1105 1.1 joerg PRINT_PROP_ATTR(weak); 1106 1.1 joerg PRINT_PROP_ATTR(strong); 1107 1.1 joerg PRINT_PROP_ATTR(unsafe_unretained); 1108 1.1 joerg PRINT_PROP_ATTR(class); 1109 1.1 joerg printf("]"); 1110 1.1 joerg } 1111 1.1 joerg } 1112 1.1 joerg 1113 1.1 joerg if (Cursor.kind == CXCursor_ObjCPropertyDecl) { 1114 1.1 joerg CXString Name = clang_Cursor_getObjCPropertyGetterName(Cursor); 1115 1.1 joerg CXString Spelling = clang_getCursorSpelling(Cursor); 1116 1.1 joerg const char *CName = clang_getCString(Name); 1117 1.1 joerg const char *CSpelling = clang_getCString(Spelling); 1118 1.1 joerg if (CName && strcmp(CName, CSpelling)) { 1119 1.1 joerg printf(" (getter=%s)", CName); 1120 1.1 joerg } 1121 1.1 joerg clang_disposeString(Spelling); 1122 1.1 joerg clang_disposeString(Name); 1123 1.1 joerg } 1124 1.1 joerg 1125 1.1 joerg if (Cursor.kind == CXCursor_ObjCPropertyDecl) { 1126 1.1 joerg CXString Name = clang_Cursor_getObjCPropertySetterName(Cursor); 1127 1.1 joerg CXString Spelling = clang_getCursorSpelling(Cursor); 1128 1.1 joerg const char *CName = clang_getCString(Name); 1129 1.1 joerg const char *CSpelling = clang_getCString(Spelling); 1130 1.1 joerg char *DefaultSetter = malloc(strlen(CSpelling) + 5); 1131 1.1 joerg sprintf(DefaultSetter, "set%s:", CSpelling); 1132 1.1 joerg DefaultSetter[3] &= ~(1 << 5); /* Make uppercase */ 1133 1.1 joerg if (CName && strcmp(CName, DefaultSetter)) { 1134 1.1 joerg printf(" (setter=%s)", CName); 1135 1.1 joerg } 1136 1.1 joerg free(DefaultSetter); 1137 1.1 joerg clang_disposeString(Spelling); 1138 1.1 joerg clang_disposeString(Name); 1139 1.1 joerg } 1140 1.1 joerg 1141 1.1 joerg { 1142 1.1 joerg unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor); 1143 1.1 joerg if (QT != CXObjCDeclQualifier_None) { 1144 1.1 joerg printf(" ["); 1145 1.1 joerg #define PRINT_OBJC_QUAL(A) \ 1146 1.1 joerg if (QT & CXObjCDeclQualifier_##A) printf(#A ",") 1147 1.1 joerg PRINT_OBJC_QUAL(In); 1148 1.1 joerg PRINT_OBJC_QUAL(Inout); 1149 1.1 joerg PRINT_OBJC_QUAL(Out); 1150 1.1 joerg PRINT_OBJC_QUAL(Bycopy); 1151 1.1 joerg PRINT_OBJC_QUAL(Byref); 1152 1.1 joerg PRINT_OBJC_QUAL(Oneway); 1153 1.1 joerg printf("]"); 1154 1.1 joerg } 1155 1.1 joerg } 1156 1.1 joerg } 1157 1.1 joerg } 1158 1.1 joerg 1159 1.1 joerg static const char* GetCursorSource(CXCursor Cursor) { 1160 1.1 joerg CXSourceLocation Loc = clang_getCursorLocation(Cursor); 1161 1.1 joerg CXString source; 1162 1.1 joerg CXFile file; 1163 1.1 joerg clang_getExpansionLocation(Loc, &file, 0, 0, 0); 1164 1.1 joerg source = clang_getFileName(file); 1165 1.1 joerg if (!clang_getCString(source)) { 1166 1.1 joerg clang_disposeString(source); 1167 1.1 joerg return "<invalid loc>"; 1168 1.1 joerg } 1169 1.1 joerg else { 1170 1.1 joerg const char *b = basename(clang_getCString(source)); 1171 1.1 joerg clang_disposeString(source); 1172 1.1 joerg return b; 1173 1.1 joerg } 1174 1.1 joerg } 1175 1.1 joerg 1176 1.1 joerg static CXString createCXString(const char *CS) { 1177 1.1 joerg CXString Str; 1178 1.1 joerg Str.data = (const void *) CS; 1179 1.1 joerg Str.private_flags = 0; 1180 1.1 joerg return Str; 1181 1.1 joerg } 1182 1.1 joerg 1183 1.1 joerg /******************************************************************************/ 1184 1.1 joerg /* Callbacks. */ 1185 1.1 joerg /******************************************************************************/ 1186 1.1 joerg 1187 1.1 joerg typedef void (*PostVisitTU)(CXTranslationUnit); 1188 1.1 joerg 1189 1.1 joerg void PrintDiagnostic(CXDiagnostic Diagnostic) { 1190 1.1 joerg FILE *out = stderr; 1191 1.1 joerg CXFile file; 1192 1.1 joerg CXString Msg; 1193 1.1 joerg unsigned display_opts = CXDiagnostic_DisplaySourceLocation 1194 1.1 joerg | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges 1195 1.1 joerg | CXDiagnostic_DisplayOption; 1196 1.1 joerg unsigned i, num_fixits; 1197 1.1 joerg 1198 1.1 joerg if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored) 1199 1.1 joerg return; 1200 1.1 joerg 1201 1.1 joerg Msg = clang_formatDiagnostic(Diagnostic, display_opts); 1202 1.1 joerg fprintf(stderr, "%s\n", clang_getCString(Msg)); 1203 1.1 joerg clang_disposeString(Msg); 1204 1.1 joerg 1205 1.1 joerg clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), 1206 1.1 joerg &file, 0, 0, 0); 1207 1.1 joerg if (!file) 1208 1.1 joerg return; 1209 1.1 joerg 1210 1.1 joerg num_fixits = clang_getDiagnosticNumFixIts(Diagnostic); 1211 1.1 joerg fprintf(stderr, "Number FIX-ITs = %d\n", num_fixits); 1212 1.1 joerg for (i = 0; i != num_fixits; ++i) { 1213 1.1 joerg CXSourceRange range; 1214 1.1 joerg CXString insertion_text = clang_getDiagnosticFixIt(Diagnostic, i, &range); 1215 1.1 joerg CXSourceLocation start = clang_getRangeStart(range); 1216 1.1 joerg CXSourceLocation end = clang_getRangeEnd(range); 1217 1.1 joerg unsigned start_line, start_column, end_line, end_column; 1218 1.1 joerg CXFile start_file, end_file; 1219 1.1 joerg clang_getSpellingLocation(start, &start_file, &start_line, 1220 1.1 joerg &start_column, 0); 1221 1.1 joerg clang_getSpellingLocation(end, &end_file, &end_line, &end_column, 0); 1222 1.1 joerg if (clang_equalLocations(start, end)) { 1223 1.1 joerg /* Insertion. */ 1224 1.1 joerg if (start_file == file) 1225 1.1 joerg fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n", 1226 1.1 joerg clang_getCString(insertion_text), start_line, start_column); 1227 1.1 joerg } else if (strcmp(clang_getCString(insertion_text), "") == 0) { 1228 1.1 joerg /* Removal. */ 1229 1.1 joerg if (start_file == file && end_file == file) { 1230 1.1 joerg fprintf(out, "FIX-IT: Remove "); 1231 1.1 joerg PrintExtent(out, start_line, start_column, end_line, end_column); 1232 1.1 joerg fprintf(out, "\n"); 1233 1.1 joerg } 1234 1.1 joerg } else { 1235 1.1 joerg /* Replacement. */ 1236 1.1 joerg if (start_file == end_file) { 1237 1.1 joerg fprintf(out, "FIX-IT: Replace "); 1238 1.1 joerg PrintExtent(out, start_line, start_column, end_line, end_column); 1239 1.1 joerg fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text)); 1240 1.1 joerg } 1241 1.1 joerg } 1242 1.1 joerg clang_disposeString(insertion_text); 1243 1.1 joerg } 1244 1.1 joerg } 1245 1.1 joerg 1246 1.1 joerg void PrintDiagnosticSet(CXDiagnosticSet Set) { 1247 1.1 joerg int i = 0, n = clang_getNumDiagnosticsInSet(Set); 1248 1.1 joerg for ( ; i != n ; ++i) { 1249 1.1 joerg CXDiagnostic Diag = clang_getDiagnosticInSet(Set, i); 1250 1.1 joerg CXDiagnosticSet ChildDiags = clang_getChildDiagnostics(Diag); 1251 1.1 joerg PrintDiagnostic(Diag); 1252 1.1 joerg if (ChildDiags) 1253 1.1 joerg PrintDiagnosticSet(ChildDiags); 1254 1.1 joerg } 1255 1.1 joerg } 1256 1.1 joerg 1257 1.1 joerg void PrintDiagnostics(CXTranslationUnit TU) { 1258 1.1 joerg CXDiagnosticSet TUSet = clang_getDiagnosticSetFromTU(TU); 1259 1.1 joerg PrintDiagnosticSet(TUSet); 1260 1.1 joerg clang_disposeDiagnosticSet(TUSet); 1261 1.1 joerg } 1262 1.1 joerg 1263 1.1 joerg void PrintMemoryUsage(CXTranslationUnit TU) { 1264 1.1 joerg unsigned long total = 0; 1265 1.1 joerg unsigned i = 0; 1266 1.1 joerg CXTUResourceUsage usage = clang_getCXTUResourceUsage(TU); 1267 1.1 joerg fprintf(stderr, "Memory usage:\n"); 1268 1.1 joerg for (i = 0 ; i != usage.numEntries; ++i) { 1269 1.1 joerg const char *name = clang_getTUResourceUsageName(usage.entries[i].kind); 1270 1.1 joerg unsigned long amount = usage.entries[i].amount; 1271 1.1 joerg total += amount; 1272 1.1 joerg fprintf(stderr, " %s : %ld bytes (%f MBytes)\n", name, amount, 1273 1.1 joerg ((double) amount)/(1024*1024)); 1274 1.1 joerg } 1275 1.1 joerg fprintf(stderr, " TOTAL = %ld bytes (%f MBytes)\n", total, 1276 1.1 joerg ((double) total)/(1024*1024)); 1277 1.1 joerg clang_disposeCXTUResourceUsage(usage); 1278 1.1 joerg } 1279 1.1 joerg 1280 1.1 joerg /******************************************************************************/ 1281 1.1 joerg /* Logic for testing traversal. */ 1282 1.1 joerg /******************************************************************************/ 1283 1.1 joerg 1284 1.1 joerg static void PrintCursorExtent(CXCursor C) { 1285 1.1 joerg CXSourceRange extent = clang_getCursorExtent(C); 1286 1.1 joerg PrintRange(extent, "Extent"); 1287 1.1 joerg } 1288 1.1 joerg 1289 1.1 joerg /* Data used by the visitors. */ 1290 1.1 joerg typedef struct { 1291 1.1 joerg CXTranslationUnit TU; 1292 1.1 joerg enum CXCursorKind *Filter; 1293 1.1 joerg const char *CommentSchemaFile; 1294 1.1 joerg } VisitorData; 1295 1.1 joerg 1296 1.1 joerg 1297 1.1 joerg enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor, 1298 1.1 joerg CXCursor Parent, 1299 1.1 joerg CXClientData ClientData) { 1300 1.1 joerg VisitorData *Data = (VisitorData *)ClientData; 1301 1.1 joerg if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) { 1302 1.1 joerg CXSourceLocation Loc = clang_getCursorLocation(Cursor); 1303 1.1 joerg unsigned line, column; 1304 1.1 joerg clang_getSpellingLocation(Loc, 0, &line, &column, 0); 1305 1.1 joerg printf("// %s: %s:%d:%d: ", FileCheckPrefix, 1306 1.1 joerg GetCursorSource(Cursor), line, column); 1307 1.1 joerg PrintCursor(Cursor, Data->CommentSchemaFile); 1308 1.1 joerg PrintCursorExtent(Cursor); 1309 1.1 joerg if (clang_isDeclaration(Cursor.kind)) { 1310 1.1 joerg enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor); 1311 1.1 joerg const char *accessStr = 0; 1312 1.1 joerg 1313 1.1 joerg switch (access) { 1314 1.1 joerg case CX_CXXInvalidAccessSpecifier: break; 1315 1.1 joerg case CX_CXXPublic: 1316 1.1 joerg accessStr = "public"; break; 1317 1.1 joerg case CX_CXXProtected: 1318 1.1 joerg accessStr = "protected"; break; 1319 1.1 joerg case CX_CXXPrivate: 1320 1.1 joerg accessStr = "private"; break; 1321 1.1 joerg } 1322 1.1 joerg 1323 1.1 joerg if (accessStr) 1324 1.1 joerg printf(" [access=%s]", accessStr); 1325 1.1 joerg } 1326 1.1 joerg printf("\n"); 1327 1.1 joerg return CXChildVisit_Recurse; 1328 1.1 joerg } 1329 1.1 joerg 1330 1.1 joerg return CXChildVisit_Continue; 1331 1.1 joerg } 1332 1.1 joerg 1333 1.1 joerg static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor, 1334 1.1 joerg CXCursor Parent, 1335 1.1 joerg CXClientData ClientData) { 1336 1.1 joerg const char *startBuf, *endBuf; 1337 1.1 joerg unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn; 1338 1.1 joerg CXCursor Ref; 1339 1.1 joerg VisitorData *Data = (VisitorData *)ClientData; 1340 1.1 joerg 1341 1.1 joerg if (Cursor.kind != CXCursor_FunctionDecl || 1342 1.1 joerg !clang_isCursorDefinition(Cursor)) 1343 1.1 joerg return CXChildVisit_Continue; 1344 1.1 joerg 1345 1.1 joerg clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf, 1346 1.1 joerg &startLine, &startColumn, 1347 1.1 joerg &endLine, &endColumn); 1348 1.1 joerg /* Probe the entire body, looking for both decls and refs. */ 1349 1.1 joerg curLine = startLine; 1350 1.1 joerg curColumn = startColumn; 1351 1.1 joerg 1352 1.1 joerg while (startBuf < endBuf) { 1353 1.1 joerg CXSourceLocation Loc; 1354 1.1 joerg CXFile file; 1355 1.1 joerg CXString source; 1356 1.1 joerg 1357 1.1 joerg if (*startBuf == '\n') { 1358 1.1 joerg startBuf++; 1359 1.1 joerg curLine++; 1360 1.1 joerg curColumn = 1; 1361 1.1 joerg } else if (*startBuf != '\t') 1362 1.1 joerg curColumn++; 1363 1.1 joerg 1364 1.1 joerg Loc = clang_getCursorLocation(Cursor); 1365 1.1 joerg clang_getSpellingLocation(Loc, &file, 0, 0, 0); 1366 1.1 joerg 1367 1.1 joerg source = clang_getFileName(file); 1368 1.1 joerg if (clang_getCString(source)) { 1369 1.1 joerg CXSourceLocation RefLoc 1370 1.1 joerg = clang_getLocation(Data->TU, file, curLine, curColumn); 1371 1.1 joerg Ref = clang_getCursor(Data->TU, RefLoc); 1372 1.1 joerg if (Ref.kind == CXCursor_NoDeclFound) { 1373 1.1 joerg /* Nothing found here; that's fine. */ 1374 1.1 joerg } else if (Ref.kind != CXCursor_FunctionDecl) { 1375 1.1 joerg printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref), 1376 1.1 joerg curLine, curColumn); 1377 1.1 joerg PrintCursor(Ref, Data->CommentSchemaFile); 1378 1.1 joerg printf("\n"); 1379 1.1 joerg } 1380 1.1 joerg } 1381 1.1 joerg clang_disposeString(source); 1382 1.1 joerg startBuf++; 1383 1.1 joerg } 1384 1.1 joerg 1385 1.1 joerg return CXChildVisit_Continue; 1386 1.1 joerg } 1387 1.1 joerg 1388 1.1 joerg /******************************************************************************/ 1389 1.1 joerg /* USR testing. */ 1390 1.1 joerg /******************************************************************************/ 1391 1.1 joerg 1392 1.1 joerg enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent, 1393 1.1 joerg CXClientData ClientData) { 1394 1.1 joerg VisitorData *Data = (VisitorData *)ClientData; 1395 1.1 joerg if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) { 1396 1.1 joerg CXString USR = clang_getCursorUSR(C); 1397 1.1 joerg const char *cstr = clang_getCString(USR); 1398 1.1 joerg if (!cstr || cstr[0] == '\0') { 1399 1.1 joerg clang_disposeString(USR); 1400 1.1 joerg return CXChildVisit_Recurse; 1401 1.1 joerg } 1402 1.1 joerg printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr); 1403 1.1 joerg 1404 1.1 joerg PrintCursorExtent(C); 1405 1.1 joerg printf("\n"); 1406 1.1 joerg clang_disposeString(USR); 1407 1.1 joerg 1408 1.1 joerg return CXChildVisit_Recurse; 1409 1.1 joerg } 1410 1.1 joerg 1411 1.1 joerg return CXChildVisit_Continue; 1412 1.1 joerg } 1413 1.1 joerg 1414 1.1 joerg /******************************************************************************/ 1415 1.1 joerg /* Inclusion stack testing. */ 1416 1.1 joerg /******************************************************************************/ 1417 1.1 joerg 1418 1.1 joerg void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack, 1419 1.1 joerg unsigned includeStackLen, CXClientData data) { 1420 1.1 joerg 1421 1.1 joerg unsigned i; 1422 1.1 joerg CXString fname; 1423 1.1 joerg 1424 1.1 joerg fname = clang_getFileName(includedFile); 1425 1.1 joerg printf("file: %s\nincluded by:\n", clang_getCString(fname)); 1426 1.1 joerg clang_disposeString(fname); 1427 1.1 joerg 1428 1.1 joerg for (i = 0; i < includeStackLen; ++i) { 1429 1.1 joerg CXFile includingFile; 1430 1.1 joerg unsigned line, column; 1431 1.1 joerg clang_getSpellingLocation(includeStack[i], &includingFile, &line, 1432 1.1 joerg &column, 0); 1433 1.1 joerg fname = clang_getFileName(includingFile); 1434 1.1 joerg printf(" %s:%d:%d\n", clang_getCString(fname), line, column); 1435 1.1 joerg clang_disposeString(fname); 1436 1.1 joerg } 1437 1.1 joerg printf("\n"); 1438 1.1 joerg } 1439 1.1 joerg 1440 1.1 joerg void PrintInclusionStack(CXTranslationUnit TU) { 1441 1.1 joerg clang_getInclusions(TU, InclusionVisitor, NULL); 1442 1.1 joerg } 1443 1.1 joerg 1444 1.1 joerg /******************************************************************************/ 1445 1.1 joerg /* Linkage testing. */ 1446 1.1 joerg /******************************************************************************/ 1447 1.1 joerg 1448 1.1 joerg static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p, 1449 1.1 joerg CXClientData d) { 1450 1.1 joerg const char *linkage = 0; 1451 1.1 joerg 1452 1.1 joerg if (clang_isInvalid(clang_getCursorKind(cursor))) 1453 1.1 joerg return CXChildVisit_Recurse; 1454 1.1 joerg 1455 1.1 joerg switch (clang_getCursorLinkage(cursor)) { 1456 1.1 joerg case CXLinkage_Invalid: break; 1457 1.1 joerg case CXLinkage_NoLinkage: linkage = "NoLinkage"; break; 1458 1.1 joerg case CXLinkage_Internal: linkage = "Internal"; break; 1459 1.1 joerg case CXLinkage_UniqueExternal: linkage = "UniqueExternal"; break; 1460 1.1 joerg case CXLinkage_External: linkage = "External"; break; 1461 1.1 joerg } 1462 1.1 joerg 1463 1.1 joerg if (linkage) { 1464 1.1 joerg PrintCursor(cursor, NULL); 1465 1.1 joerg printf("linkage=%s\n", linkage); 1466 1.1 joerg } 1467 1.1 joerg 1468 1.1 joerg return CXChildVisit_Recurse; 1469 1.1 joerg } 1470 1.1 joerg 1471 1.1 joerg /******************************************************************************/ 1472 1.1 joerg /* Visibility testing. */ 1473 1.1 joerg /******************************************************************************/ 1474 1.1 joerg 1475 1.1 joerg static enum CXChildVisitResult PrintVisibility(CXCursor cursor, CXCursor p, 1476 1.1 joerg CXClientData d) { 1477 1.1 joerg const char *visibility = 0; 1478 1.1 joerg 1479 1.1 joerg if (clang_isInvalid(clang_getCursorKind(cursor))) 1480 1.1 joerg return CXChildVisit_Recurse; 1481 1.1 joerg 1482 1.1 joerg switch (clang_getCursorVisibility(cursor)) { 1483 1.1 joerg case CXVisibility_Invalid: break; 1484 1.1 joerg case CXVisibility_Hidden: visibility = "Hidden"; break; 1485 1.1 joerg case CXVisibility_Protected: visibility = "Protected"; break; 1486 1.1 joerg case CXVisibility_Default: visibility = "Default"; break; 1487 1.1 joerg } 1488 1.1 joerg 1489 1.1 joerg if (visibility) { 1490 1.1 joerg PrintCursor(cursor, NULL); 1491 1.1 joerg printf("visibility=%s\n", visibility); 1492 1.1 joerg } 1493 1.1 joerg 1494 1.1 joerg return CXChildVisit_Recurse; 1495 1.1 joerg } 1496 1.1 joerg 1497 1.1 joerg /******************************************************************************/ 1498 1.1 joerg /* Typekind testing. */ 1499 1.1 joerg /******************************************************************************/ 1500 1.1 joerg 1501 1.1 joerg static void PrintTypeAndTypeKind(CXType T, const char *Format) { 1502 1.1 joerg CXString TypeSpelling, TypeKindSpelling; 1503 1.1 joerg 1504 1.1 joerg TypeSpelling = clang_getTypeSpelling(T); 1505 1.1 joerg TypeKindSpelling = clang_getTypeKindSpelling(T.kind); 1506 1.1 joerg printf(Format, 1507 1.1 joerg clang_getCString(TypeSpelling), 1508 1.1 joerg clang_getCString(TypeKindSpelling)); 1509 1.1 joerg clang_disposeString(TypeSpelling); 1510 1.1 joerg clang_disposeString(TypeKindSpelling); 1511 1.1 joerg } 1512 1.1 joerg 1513 1.1 joerg static enum CXVisitorResult FieldVisitor(CXCursor C, 1514 1.1 joerg CXClientData client_data) { 1515 1.1 joerg (*(int *) client_data)+=1; 1516 1.1 joerg return CXVisit_Continue; 1517 1.1 joerg } 1518 1.1 joerg 1519 1.1 joerg static void PrintTypeTemplateArgs(CXType T, const char *Format) { 1520 1.1 joerg int NumTArgs = clang_Type_getNumTemplateArguments(T); 1521 1.1 joerg if (NumTArgs != -1 && NumTArgs != 0) { 1522 1.1 joerg int i; 1523 1.1 joerg CXType TArg; 1524 1.1 joerg printf(Format, NumTArgs); 1525 1.1 joerg for (i = 0; i < NumTArgs; ++i) { 1526 1.1 joerg TArg = clang_Type_getTemplateArgumentAsType(T, i); 1527 1.1 joerg if (TArg.kind != CXType_Invalid) { 1528 1.1 joerg PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]"); 1529 1.1 joerg } 1530 1.1 joerg } 1531 1.1 joerg /* Ensure that the returned type is invalid when indexing off-by-one. */ 1532 1.1 joerg TArg = clang_Type_getTemplateArgumentAsType(T, i); 1533 1.1 joerg assert(TArg.kind == CXType_Invalid); 1534 1.1 joerg printf("]"); 1535 1.1 joerg } 1536 1.1 joerg } 1537 1.1 joerg 1538 1.1 joerg static void PrintNullabilityKind(CXType T, const char *Format) { 1539 1.1 joerg enum CXTypeNullabilityKind N = clang_Type_getNullability(T); 1540 1.1 joerg 1541 1.1 joerg const char *nullability = 0; 1542 1.1 joerg switch (N) { 1543 1.1.1.2 joerg case CXTypeNullability_NonNull: 1544 1.1.1.2 joerg nullability = "nonnull"; 1545 1.1.1.2 joerg break; 1546 1.1.1.2 joerg case CXTypeNullability_Nullable: 1547 1.1.1.2 joerg nullability = "nullable"; 1548 1.1.1.2 joerg break; 1549 1.1.1.2 joerg case CXTypeNullability_NullableResult: 1550 1.1.1.2 joerg nullability = "nullable_result"; 1551 1.1.1.2 joerg break; 1552 1.1.1.2 joerg case CXTypeNullability_Unspecified: 1553 1.1.1.2 joerg nullability = "unspecified"; 1554 1.1.1.2 joerg break; 1555 1.1.1.2 joerg case CXTypeNullability_Invalid: 1556 1.1.1.2 joerg break; 1557 1.1 joerg } 1558 1.1 joerg 1559 1.1 joerg if (nullability) { 1560 1.1 joerg printf(Format, nullability); 1561 1.1 joerg } 1562 1.1 joerg } 1563 1.1 joerg 1564 1.1 joerg static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, 1565 1.1 joerg CXClientData d) { 1566 1.1 joerg if (!clang_isInvalid(clang_getCursorKind(cursor))) { 1567 1.1 joerg CXType T = clang_getCursorType(cursor); 1568 1.1 joerg CXType PT = clang_getPointeeType(T); 1569 1.1 joerg enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T); 1570 1.1 joerg PrintCursor(cursor, NULL); 1571 1.1 joerg PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); 1572 1.1 joerg PrintNullabilityKind(T, " [nullability=%s]"); 1573 1.1 joerg if (clang_isConstQualifiedType(T)) 1574 1.1 joerg printf(" const"); 1575 1.1 joerg if (clang_isVolatileQualifiedType(T)) 1576 1.1 joerg printf(" volatile"); 1577 1.1 joerg if (clang_isRestrictQualifiedType(T)) 1578 1.1 joerg printf(" restrict"); 1579 1.1 joerg if (RQ == CXRefQualifier_LValue) 1580 1.1 joerg printf(" lvalue-ref-qualifier"); 1581 1.1 joerg if (RQ == CXRefQualifier_RValue) 1582 1.1 joerg printf(" rvalue-ref-qualifier"); 1583 1.1 joerg /* Print the template argument types if they exist. */ 1584 1.1 joerg PrintTypeTemplateArgs(T, " [templateargs/%d="); 1585 1.1 joerg /* Print the canonical type if it is different. */ 1586 1.1 joerg { 1587 1.1 joerg CXType CT = clang_getCanonicalType(T); 1588 1.1 joerg if (!clang_equalTypes(T, CT)) { 1589 1.1 joerg PrintTypeAndTypeKind(CT, " [canonicaltype=%s] [canonicaltypekind=%s]"); 1590 1.1 joerg PrintTypeTemplateArgs(CT, " [canonicaltemplateargs/%d="); 1591 1.1 joerg } 1592 1.1 joerg } 1593 1.1.1.2 joerg /* Print the value type if it exists. */ 1594 1.1.1.2 joerg { 1595 1.1.1.2 joerg CXType VT = clang_Type_getValueType(T); 1596 1.1.1.2 joerg if (VT.kind != CXType_Invalid) 1597 1.1.1.2 joerg PrintTypeAndTypeKind(VT, " [valuetype=%s] [valuetypekind=%s]"); 1598 1.1.1.2 joerg } 1599 1.1 joerg /* Print the modified type if it exists. */ 1600 1.1 joerg { 1601 1.1 joerg CXType MT = clang_Type_getModifiedType(T); 1602 1.1 joerg if (MT.kind != CXType_Invalid) { 1603 1.1 joerg PrintTypeAndTypeKind(MT, " [modifiedtype=%s] [modifiedtypekind=%s]"); 1604 1.1 joerg } 1605 1.1 joerg } 1606 1.1 joerg /* Print the return type if it exists. */ 1607 1.1 joerg { 1608 1.1 joerg CXType RT = clang_getCursorResultType(cursor); 1609 1.1 joerg if (RT.kind != CXType_Invalid) { 1610 1.1 joerg PrintTypeAndTypeKind(RT, " [resulttype=%s] [resulttypekind=%s]"); 1611 1.1 joerg } 1612 1.1 joerg PrintNullabilityKind(RT, " [resultnullability=%s]"); 1613 1.1 joerg } 1614 1.1 joerg /* Print the argument types if they exist. */ 1615 1.1 joerg { 1616 1.1 joerg int NumArgs = clang_Cursor_getNumArguments(cursor); 1617 1.1 joerg if (NumArgs != -1 && NumArgs != 0) { 1618 1.1 joerg int i; 1619 1.1 joerg printf(" [args="); 1620 1.1 joerg for (i = 0; i < NumArgs; ++i) { 1621 1.1 joerg CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i)); 1622 1.1 joerg if (T.kind != CXType_Invalid) { 1623 1.1 joerg PrintTypeAndTypeKind(T, " [%s] [%s]"); 1624 1.1 joerg PrintNullabilityKind(T, " [%s]"); 1625 1.1 joerg } 1626 1.1 joerg } 1627 1.1 joerg printf("]"); 1628 1.1 joerg } 1629 1.1 joerg } 1630 1.1 joerg /* Print ObjC base types, type arguments, and protocol list if available. */ 1631 1.1 joerg { 1632 1.1 joerg CXType BT = clang_Type_getObjCObjectBaseType(PT); 1633 1.1 joerg if (BT.kind != CXType_Invalid) { 1634 1.1 joerg PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]"); 1635 1.1 joerg } 1636 1.1 joerg } 1637 1.1 joerg { 1638 1.1 joerg unsigned NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT); 1639 1.1 joerg if (NumTypeArgs > 0) { 1640 1.1 joerg unsigned i; 1641 1.1 joerg printf(" [typeargs="); 1642 1.1 joerg for (i = 0; i < NumTypeArgs; ++i) { 1643 1.1 joerg CXType TA = clang_Type_getObjCTypeArg(PT, i); 1644 1.1 joerg if (TA.kind != CXType_Invalid) { 1645 1.1 joerg PrintTypeAndTypeKind(TA, " [%s] [%s]"); 1646 1.1 joerg } 1647 1.1 joerg } 1648 1.1 joerg printf("]"); 1649 1.1 joerg } 1650 1.1 joerg } 1651 1.1 joerg { 1652 1.1 joerg unsigned NumProtocols = clang_Type_getNumObjCProtocolRefs(PT); 1653 1.1 joerg if (NumProtocols > 0) { 1654 1.1 joerg unsigned i; 1655 1.1 joerg printf(" [protocols="); 1656 1.1 joerg for (i = 0; i < NumProtocols; ++i) { 1657 1.1 joerg CXCursor P = clang_Type_getObjCProtocolDecl(PT, i); 1658 1.1 joerg if (!clang_isInvalid(clang_getCursorKind(P))) { 1659 1.1 joerg PrintCursor(P, NULL); 1660 1.1 joerg } 1661 1.1 joerg } 1662 1.1 joerg printf("]"); 1663 1.1 joerg } 1664 1.1 joerg } 1665 1.1 joerg /* Print if this is a non-POD type. */ 1666 1.1 joerg printf(" [isPOD=%d]", clang_isPODType(T)); 1667 1.1 joerg /* Print the pointee type. */ 1668 1.1 joerg { 1669 1.1 joerg if (PT.kind != CXType_Invalid) { 1670 1.1 joerg PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]"); 1671 1.1 joerg } 1672 1.1 joerg } 1673 1.1 joerg /* Print the number of fields if they exist. */ 1674 1.1 joerg { 1675 1.1 joerg int numFields = 0; 1676 1.1 joerg if (clang_Type_visitFields(T, FieldVisitor, &numFields)){ 1677 1.1 joerg if (numFields != 0) { 1678 1.1 joerg printf(" [nbFields=%d]", numFields); 1679 1.1 joerg } 1680 1.1 joerg } 1681 1.1 joerg } 1682 1.1 joerg 1683 1.1 joerg /* Print if it is an anonymous record or namespace. */ 1684 1.1 joerg { 1685 1.1 joerg unsigned isAnon = clang_Cursor_isAnonymous(cursor); 1686 1.1 joerg if (isAnon != 0) { 1687 1.1 joerg printf(" [isAnon=%d]", isAnon); 1688 1.1 joerg } 1689 1.1 joerg } 1690 1.1 joerg 1691 1.1 joerg /* Print if it is an anonymous record decl */ 1692 1.1 joerg { 1693 1.1 joerg unsigned isAnonRecDecl = clang_Cursor_isAnonymousRecordDecl(cursor); 1694 1.1 joerg printf(" [isAnonRecDecl=%d]", isAnonRecDecl); 1695 1.1 joerg } 1696 1.1 joerg 1697 1.1 joerg /* Print if it is an inline namespace decl */ 1698 1.1 joerg { 1699 1.1 joerg unsigned isInlineNamespace = clang_Cursor_isInlineNamespace(cursor); 1700 1.1 joerg if (isInlineNamespace != 0) 1701 1.1 joerg printf(" [isInlineNamespace=%d]", isInlineNamespace); 1702 1.1 joerg } 1703 1.1 joerg 1704 1.1 joerg printf("\n"); 1705 1.1 joerg } 1706 1.1 joerg return CXChildVisit_Recurse; 1707 1.1 joerg } 1708 1.1 joerg 1709 1.1 joerg static void PrintSingleTypeSize(CXType T, const char *TypeKindFormat, 1710 1.1 joerg const char *SizeFormat, 1711 1.1 joerg const char *AlignFormat) { 1712 1.1 joerg PrintTypeAndTypeKind(T, TypeKindFormat); 1713 1.1 joerg /* Print the type sizeof if applicable. */ 1714 1.1 joerg { 1715 1.1 joerg long long Size = clang_Type_getSizeOf(T); 1716 1.1 joerg if (Size >= 0 || Size < -1 ) { 1717 1.1 joerg printf(SizeFormat, Size); 1718 1.1 joerg } 1719 1.1 joerg } 1720 1.1 joerg /* Print the type alignof if applicable. */ 1721 1.1 joerg { 1722 1.1 joerg long long Align = clang_Type_getAlignOf(T); 1723 1.1 joerg if (Align >= 0 || Align < -1) { 1724 1.1 joerg printf(AlignFormat, Align); 1725 1.1 joerg } 1726 1.1 joerg } 1727 1.1 joerg 1728 1.1 joerg /* Print the return type if it exists. */ 1729 1.1 joerg { 1730 1.1 joerg CXType RT = clang_getResultType(T); 1731 1.1 joerg if (RT.kind != CXType_Invalid) 1732 1.1 joerg PrintSingleTypeSize(RT, " [resulttype=%s] [resulttypekind=%s]", 1733 1.1 joerg " [resultsizeof=%lld]", " [resultalignof=%lld]"); 1734 1.1 joerg } 1735 1.1 joerg } 1736 1.1 joerg 1737 1.1 joerg static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p, 1738 1.1 joerg CXClientData d) { 1739 1.1 joerg CXType T; 1740 1.1 joerg enum CXCursorKind K = clang_getCursorKind(cursor); 1741 1.1 joerg if (clang_isInvalid(K)) 1742 1.1 joerg return CXChildVisit_Recurse; 1743 1.1 joerg T = clang_getCursorType(cursor); 1744 1.1 joerg PrintCursor(cursor, NULL); 1745 1.1 joerg PrintSingleTypeSize(T, " [type=%s] [typekind=%s]", " [sizeof=%lld]", 1746 1.1 joerg " [alignof=%lld]"); 1747 1.1 joerg /* Print the record field offset if applicable. */ 1748 1.1 joerg { 1749 1.1 joerg CXString FieldSpelling = clang_getCursorSpelling(cursor); 1750 1.1 joerg const char *FieldName = clang_getCString(FieldSpelling); 1751 1.1 joerg /* recurse to get the first parent record that is not anonymous. */ 1752 1.1 joerg unsigned RecordIsAnonymous = 0; 1753 1.1 joerg if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) { 1754 1.1 joerg CXCursor Record; 1755 1.1 joerg CXCursor Parent = p; 1756 1.1 joerg do { 1757 1.1 joerg Record = Parent; 1758 1.1 joerg Parent = clang_getCursorSemanticParent(Record); 1759 1.1 joerg RecordIsAnonymous = clang_Cursor_isAnonymous(Record); 1760 1.1 joerg /* Recurse as long as the parent is a CXType_Record and the Record 1761 1.1 joerg is anonymous */ 1762 1.1 joerg } while ( clang_getCursorType(Parent).kind == CXType_Record && 1763 1.1 joerg RecordIsAnonymous > 0); 1764 1.1 joerg { 1765 1.1 joerg long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Record), 1766 1.1 joerg FieldName); 1767 1.1 joerg long long Offset2 = clang_Cursor_getOffsetOfField(cursor); 1768 1.1 joerg if (Offset == Offset2){ 1769 1.1 joerg printf(" [offsetof=%lld]", Offset); 1770 1.1 joerg } else { 1771 1.1 joerg /* Offsets will be different in anonymous records. */ 1772 1.1 joerg printf(" [offsetof=%lld/%lld]", Offset, Offset2); 1773 1.1 joerg } 1774 1.1 joerg } 1775 1.1 joerg } 1776 1.1 joerg clang_disposeString(FieldSpelling); 1777 1.1 joerg } 1778 1.1 joerg /* Print if its a bitfield */ 1779 1.1 joerg { 1780 1.1 joerg int IsBitfield = clang_Cursor_isBitField(cursor); 1781 1.1 joerg if (IsBitfield) 1782 1.1 joerg printf(" [BitFieldSize=%d]", clang_getFieldDeclBitWidth(cursor)); 1783 1.1 joerg } 1784 1.1 joerg 1785 1.1 joerg printf("\n"); 1786 1.1 joerg 1787 1.1 joerg return CXChildVisit_Recurse; 1788 1.1 joerg } 1789 1.1 joerg 1790 1.1 joerg /******************************************************************************/ 1791 1.1 joerg /* Mangling testing. */ 1792 1.1 joerg /******************************************************************************/ 1793 1.1 joerg 1794 1.1 joerg static enum CXChildVisitResult PrintMangledName(CXCursor cursor, CXCursor p, 1795 1.1 joerg CXClientData d) { 1796 1.1 joerg CXString MangledName; 1797 1.1 joerg if (clang_isUnexposed(clang_getCursorKind(cursor))) 1798 1.1 joerg return CXChildVisit_Recurse; 1799 1.1 joerg PrintCursor(cursor, NULL); 1800 1.1 joerg MangledName = clang_Cursor_getMangling(cursor); 1801 1.1 joerg printf(" [mangled=%s]\n", clang_getCString(MangledName)); 1802 1.1 joerg clang_disposeString(MangledName); 1803 1.1 joerg return CXChildVisit_Continue; 1804 1.1 joerg } 1805 1.1 joerg 1806 1.1 joerg static enum CXChildVisitResult PrintManglings(CXCursor cursor, CXCursor p, 1807 1.1 joerg CXClientData d) { 1808 1.1 joerg unsigned I, E; 1809 1.1 joerg CXStringSet *Manglings = NULL; 1810 1.1 joerg if (clang_isUnexposed(clang_getCursorKind(cursor))) 1811 1.1 joerg return CXChildVisit_Recurse; 1812 1.1 joerg if (!clang_isDeclaration(clang_getCursorKind(cursor))) 1813 1.1 joerg return CXChildVisit_Recurse; 1814 1.1 joerg if (clang_getCursorKind(cursor) == CXCursor_ParmDecl) 1815 1.1 joerg return CXChildVisit_Continue; 1816 1.1 joerg PrintCursor(cursor, NULL); 1817 1.1 joerg Manglings = clang_Cursor_getCXXManglings(cursor); 1818 1.1 joerg if (Manglings) { 1819 1.1 joerg for (I = 0, E = Manglings->Count; I < E; ++I) 1820 1.1 joerg printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I])); 1821 1.1 joerg clang_disposeStringSet(Manglings); 1822 1.1 joerg printf("\n"); 1823 1.1 joerg } 1824 1.1 joerg Manglings = clang_Cursor_getObjCManglings(cursor); 1825 1.1 joerg if (Manglings) { 1826 1.1 joerg for (I = 0, E = Manglings->Count; I < E; ++I) 1827 1.1 joerg printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I])); 1828 1.1 joerg clang_disposeStringSet(Manglings); 1829 1.1 joerg printf("\n"); 1830 1.1 joerg } 1831 1.1 joerg return CXChildVisit_Recurse; 1832 1.1 joerg } 1833 1.1 joerg 1834 1.1 joerg /******************************************************************************/ 1835 1.1 joerg /* Bitwidth testing. */ 1836 1.1 joerg /******************************************************************************/ 1837 1.1 joerg 1838 1.1 joerg static enum CXChildVisitResult PrintBitWidth(CXCursor cursor, CXCursor p, 1839 1.1 joerg CXClientData d) { 1840 1.1 joerg int Bitwidth; 1841 1.1 joerg if (clang_getCursorKind(cursor) != CXCursor_FieldDecl) 1842 1.1 joerg return CXChildVisit_Recurse; 1843 1.1 joerg 1844 1.1 joerg Bitwidth = clang_getFieldDeclBitWidth(cursor); 1845 1.1 joerg if (Bitwidth >= 0) { 1846 1.1 joerg PrintCursor(cursor, NULL); 1847 1.1 joerg printf(" bitwidth=%d\n", Bitwidth); 1848 1.1 joerg } 1849 1.1 joerg 1850 1.1 joerg return CXChildVisit_Recurse; 1851 1.1 joerg } 1852 1.1 joerg 1853 1.1 joerg /******************************************************************************/ 1854 1.1 joerg /* Type declaration testing */ 1855 1.1 joerg /******************************************************************************/ 1856 1.1 joerg 1857 1.1 joerg static enum CXChildVisitResult PrintTypeDeclaration(CXCursor cursor, CXCursor p, 1858 1.1 joerg CXClientData d) { 1859 1.1 joerg CXCursor typeDeclaration = clang_getTypeDeclaration(clang_getCursorType(cursor)); 1860 1.1 joerg 1861 1.1 joerg if (clang_isDeclaration(typeDeclaration.kind)) { 1862 1.1 joerg PrintCursor(cursor, NULL); 1863 1.1 joerg PrintTypeAndTypeKind(clang_getCursorType(typeDeclaration), " [typedeclaration=%s] [typekind=%s]\n"); 1864 1.1 joerg } 1865 1.1 joerg 1866 1.1 joerg return CXChildVisit_Recurse; 1867 1.1 joerg } 1868 1.1 joerg 1869 1.1 joerg /******************************************************************************/ 1870 1.1 joerg /* Declaration attributes testing */ 1871 1.1 joerg /******************************************************************************/ 1872 1.1 joerg 1873 1.1 joerg static enum CXChildVisitResult PrintDeclAttributes(CXCursor cursor, CXCursor p, 1874 1.1 joerg CXClientData d) { 1875 1.1 joerg if (clang_isDeclaration(cursor.kind)) { 1876 1.1 joerg printf("\n"); 1877 1.1 joerg PrintCursor(cursor, NULL); 1878 1.1 joerg return CXChildVisit_Recurse; 1879 1.1 joerg } else if (clang_isAttribute(cursor.kind)) { 1880 1.1 joerg printf(" "); 1881 1.1 joerg PrintCursor(cursor, NULL); 1882 1.1 joerg } 1883 1.1 joerg return CXChildVisit_Continue; 1884 1.1 joerg } 1885 1.1 joerg 1886 1.1 joerg /******************************************************************************/ 1887 1.1 joerg /* Target information testing. */ 1888 1.1 joerg /******************************************************************************/ 1889 1.1 joerg 1890 1.1 joerg static int print_target_info(int argc, const char **argv) { 1891 1.1 joerg CXIndex Idx; 1892 1.1 joerg CXTranslationUnit TU; 1893 1.1 joerg CXTargetInfo TargetInfo; 1894 1.1 joerg CXString Triple; 1895 1.1 joerg const char *FileName; 1896 1.1 joerg enum CXErrorCode Err; 1897 1.1 joerg int PointerWidth; 1898 1.1 joerg 1899 1.1 joerg if (argc == 0) { 1900 1.1 joerg fprintf(stderr, "No filename specified\n"); 1901 1.1 joerg return 1; 1902 1.1 joerg } 1903 1.1 joerg 1904 1.1 joerg FileName = argv[1]; 1905 1.1 joerg 1906 1.1 joerg Idx = clang_createIndex(0, 1); 1907 1.1 joerg Err = clang_parseTranslationUnit2(Idx, FileName, argv, argc, NULL, 0, 1908 1.1 joerg getDefaultParsingOptions(), &TU); 1909 1.1 joerg if (Err != CXError_Success) { 1910 1.1 joerg fprintf(stderr, "Couldn't parse translation unit!\n"); 1911 1.1 joerg describeLibclangFailure(Err); 1912 1.1 joerg clang_disposeIndex(Idx); 1913 1.1 joerg return 1; 1914 1.1 joerg } 1915 1.1 joerg 1916 1.1 joerg TargetInfo = clang_getTranslationUnitTargetInfo(TU); 1917 1.1 joerg 1918 1.1 joerg Triple = clang_TargetInfo_getTriple(TargetInfo); 1919 1.1 joerg printf("TargetTriple: %s\n", clang_getCString(Triple)); 1920 1.1 joerg clang_disposeString(Triple); 1921 1.1 joerg 1922 1.1 joerg PointerWidth = clang_TargetInfo_getPointerWidth(TargetInfo); 1923 1.1 joerg printf("PointerWidth: %d\n", PointerWidth); 1924 1.1 joerg 1925 1.1 joerg clang_TargetInfo_dispose(TargetInfo); 1926 1.1 joerg clang_disposeTranslationUnit(TU); 1927 1.1 joerg clang_disposeIndex(Idx); 1928 1.1 joerg return 0; 1929 1.1 joerg } 1930 1.1 joerg 1931 1.1 joerg /******************************************************************************/ 1932 1.1 joerg /* Loading ASTs/source. */ 1933 1.1 joerg /******************************************************************************/ 1934 1.1 joerg 1935 1.1 joerg static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, 1936 1.1 joerg const char *filter, const char *prefix, 1937 1.1 joerg CXCursorVisitor Visitor, 1938 1.1 joerg PostVisitTU PV, 1939 1.1 joerg const char *CommentSchemaFile) { 1940 1.1 joerg 1941 1.1 joerg if (prefix) 1942 1.1 joerg FileCheckPrefix = prefix; 1943 1.1 joerg 1944 1.1 joerg if (Visitor) { 1945 1.1 joerg enum CXCursorKind K = CXCursor_NotImplemented; 1946 1.1 joerg enum CXCursorKind *ck = &K; 1947 1.1 joerg VisitorData Data; 1948 1.1 joerg 1949 1.1 joerg /* Perform some simple filtering. */ 1950 1.1 joerg if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL; 1951 1.1 joerg else if (!strcmp(filter, "all-display") || 1952 1.1 joerg !strcmp(filter, "local-display")) { 1953 1.1 joerg ck = NULL; 1954 1.1 joerg wanted_display_type = DisplayType_DisplayName; 1955 1.1 joerg } 1956 1.1 joerg else if (!strcmp(filter, "all-pretty") || 1957 1.1 joerg !strcmp(filter, "local-pretty")) { 1958 1.1 joerg ck = NULL; 1959 1.1 joerg wanted_display_type = DisplayType_Pretty; 1960 1.1 joerg } 1961 1.1 joerg else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0; 1962 1.1 joerg else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl; 1963 1.1 joerg else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl; 1964 1.1 joerg else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl; 1965 1.1 joerg else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl; 1966 1.1 joerg else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl; 1967 1.1 joerg else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor; 1968 1.1 joerg else { 1969 1.1 joerg fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter); 1970 1.1 joerg return 1; 1971 1.1 joerg } 1972 1.1 joerg 1973 1.1 joerg Data.TU = TU; 1974 1.1 joerg Data.Filter = ck; 1975 1.1 joerg Data.CommentSchemaFile = CommentSchemaFile; 1976 1.1 joerg clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data); 1977 1.1 joerg } 1978 1.1 joerg 1979 1.1 joerg if (PV) 1980 1.1 joerg PV(TU); 1981 1.1 joerg 1982 1.1 joerg PrintDiagnostics(TU); 1983 1.1 joerg if (checkForErrors(TU) != 0) { 1984 1.1 joerg clang_disposeTranslationUnit(TU); 1985 1.1 joerg return -1; 1986 1.1 joerg } 1987 1.1 joerg 1988 1.1 joerg clang_disposeTranslationUnit(TU); 1989 1.1 joerg return 0; 1990 1.1 joerg } 1991 1.1 joerg 1992 1.1 joerg int perform_test_load_tu(const char *file, const char *filter, 1993 1.1 joerg const char *prefix, CXCursorVisitor Visitor, 1994 1.1 joerg PostVisitTU PV) { 1995 1.1 joerg CXIndex Idx; 1996 1.1 joerg CXTranslationUnit TU; 1997 1.1 joerg int result; 1998 1.1 joerg Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1999 1.1 joerg !strcmp(filter, "local") ? 1 : 0, 2000 1.1 joerg /* displayDiagnostics=*/1); 2001 1.1 joerg 2002 1.1 joerg if (!CreateTranslationUnit(Idx, file, &TU)) { 2003 1.1 joerg clang_disposeIndex(Idx); 2004 1.1 joerg return 1; 2005 1.1 joerg } 2006 1.1 joerg 2007 1.1 joerg result = perform_test_load(Idx, TU, filter, prefix, Visitor, PV, NULL); 2008 1.1 joerg clang_disposeIndex(Idx); 2009 1.1 joerg return result; 2010 1.1 joerg } 2011 1.1 joerg 2012 1.1 joerg int perform_test_load_source(int argc, const char **argv, 2013 1.1 joerg const char *filter, CXCursorVisitor Visitor, 2014 1.1 joerg PostVisitTU PV) { 2015 1.1 joerg CXIndex Idx; 2016 1.1 joerg CXTranslationUnit TU; 2017 1.1 joerg const char *CommentSchemaFile; 2018 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 2019 1.1 joerg int num_unsaved_files = 0; 2020 1.1 joerg enum CXErrorCode Err; 2021 1.1 joerg int result; 2022 1.1 joerg unsigned Repeats = 0; 2023 1.1 joerg unsigned I; 2024 1.1 joerg const char *InvocationPath; 2025 1.1 joerg 2026 1.1 joerg Idx = clang_createIndex(/* excludeDeclsFromPCH */ 2027 1.1 joerg (!strcmp(filter, "local") || 2028 1.1 joerg !strcmp(filter, "local-display") || 2029 1.1 joerg !strcmp(filter, "local-pretty")) 2030 1.1 joerg ? 1 2031 1.1 joerg : 0, 2032 1.1 joerg /* displayDiagnostics=*/1); 2033 1.1 joerg InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH"); 2034 1.1 joerg if (InvocationPath) 2035 1.1 joerg clang_CXIndex_setInvocationEmissionPathOption(Idx, InvocationPath); 2036 1.1 joerg 2037 1.1 joerg if ((CommentSchemaFile = parse_comments_schema(argc, argv))) { 2038 1.1 joerg argc--; 2039 1.1 joerg argv++; 2040 1.1 joerg } 2041 1.1 joerg 2042 1.1 joerg if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) { 2043 1.1 joerg clang_disposeIndex(Idx); 2044 1.1 joerg return -1; 2045 1.1 joerg } 2046 1.1 joerg 2047 1.1 joerg if (getenv("CINDEXTEST_EDITING")) 2048 1.1 joerg Repeats = 5; 2049 1.1 joerg 2050 1.1 joerg Err = clang_parseTranslationUnit2(Idx, 0, 2051 1.1 joerg argv + num_unsaved_files, 2052 1.1 joerg argc - num_unsaved_files, 2053 1.1 joerg unsaved_files, num_unsaved_files, 2054 1.1 joerg getDefaultParsingOptions(), &TU); 2055 1.1 joerg if (Err != CXError_Success) { 2056 1.1 joerg fprintf(stderr, "Unable to load translation unit!\n"); 2057 1.1 joerg describeLibclangFailure(Err); 2058 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2059 1.1 joerg clang_disposeIndex(Idx); 2060 1.1 joerg return 1; 2061 1.1 joerg } 2062 1.1 joerg 2063 1.1 joerg for (I = 0; I != Repeats; ++I) { 2064 1.1 joerg if (checkForErrors(TU) != 0) 2065 1.1 joerg return -1; 2066 1.1 joerg 2067 1.1 joerg if (Repeats > 1) { 2068 1.1 joerg clang_suspendTranslationUnit(TU); 2069 1.1 joerg 2070 1.1 joerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, 2071 1.1 joerg clang_defaultReparseOptions(TU)); 2072 1.1 joerg if (Err != CXError_Success) { 2073 1.1 joerg describeLibclangFailure(Err); 2074 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2075 1.1 joerg clang_disposeIndex(Idx); 2076 1.1 joerg return 1; 2077 1.1 joerg } 2078 1.1 joerg } 2079 1.1 joerg } 2080 1.1 joerg 2081 1.1 joerg result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, 2082 1.1 joerg CommentSchemaFile); 2083 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2084 1.1 joerg clang_disposeIndex(Idx); 2085 1.1 joerg return result; 2086 1.1 joerg } 2087 1.1 joerg 2088 1.1 joerg int perform_test_reparse_source(int argc, const char **argv, int trials, 2089 1.1 joerg const char *filter, CXCursorVisitor Visitor, 2090 1.1 joerg PostVisitTU PV) { 2091 1.1 joerg CXIndex Idx; 2092 1.1 joerg CXTranslationUnit TU; 2093 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 2094 1.1 joerg int num_unsaved_files = 0; 2095 1.1 joerg int compiler_arg_idx = 0; 2096 1.1 joerg enum CXErrorCode Err; 2097 1.1 joerg int result, i; 2098 1.1 joerg int trial; 2099 1.1.1.2 joerg int execute_after_trial = 0; 2100 1.1.1.2 joerg const char *execute_command = NULL; 2101 1.1 joerg int remap_after_trial = 0; 2102 1.1 joerg char *endptr = 0; 2103 1.1 joerg 2104 1.1 joerg Idx = clang_createIndex(/* excludeDeclsFromPCH */ 2105 1.1 joerg !strcmp(filter, "local") ? 1 : 0, 2106 1.1 joerg /* displayDiagnostics=*/1); 2107 1.1 joerg 2108 1.1 joerg if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) { 2109 1.1 joerg clang_disposeIndex(Idx); 2110 1.1 joerg return -1; 2111 1.1 joerg } 2112 1.1 joerg 2113 1.1 joerg for (i = 0; i < argc; ++i) { 2114 1.1 joerg if (strcmp(argv[i], "--") == 0) 2115 1.1 joerg break; 2116 1.1 joerg } 2117 1.1 joerg if (i < argc) 2118 1.1 joerg compiler_arg_idx = i+1; 2119 1.1 joerg if (num_unsaved_files > compiler_arg_idx) 2120 1.1 joerg compiler_arg_idx = num_unsaved_files; 2121 1.1 joerg 2122 1.1 joerg /* Load the initial translation unit -- we do this without honoring remapped 2123 1.1 joerg * files, so that we have a way to test results after changing the source. */ 2124 1.1 joerg Err = clang_parseTranslationUnit2(Idx, 0, 2125 1.1 joerg argv + compiler_arg_idx, 2126 1.1 joerg argc - compiler_arg_idx, 2127 1.1 joerg 0, 0, getDefaultParsingOptions(), &TU); 2128 1.1 joerg if (Err != CXError_Success) { 2129 1.1 joerg fprintf(stderr, "Unable to load translation unit!\n"); 2130 1.1 joerg describeLibclangFailure(Err); 2131 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2132 1.1 joerg clang_disposeIndex(Idx); 2133 1.1 joerg return 1; 2134 1.1 joerg } 2135 1.1 joerg 2136 1.1 joerg if (checkForErrors(TU) != 0) 2137 1.1 joerg return -1; 2138 1.1 joerg 2139 1.1.1.2 joerg if (getenv("CINDEXTEST_EXECUTE_COMMAND")) { 2140 1.1.1.2 joerg execute_command = getenv("CINDEXTEST_EXECUTE_COMMAND"); 2141 1.1.1.2 joerg } 2142 1.1.1.2 joerg if (getenv("CINDEXTEST_EXECUTE_AFTER_TRIAL")) { 2143 1.1.1.2 joerg execute_after_trial = 2144 1.1.1.2 joerg strtol(getenv("CINDEXTEST_EXECUTE_AFTER_TRIAL"), &endptr, 10); 2145 1.1.1.2 joerg } 2146 1.1.1.2 joerg 2147 1.1 joerg if (getenv("CINDEXTEST_REMAP_AFTER_TRIAL")) { 2148 1.1 joerg remap_after_trial = 2149 1.1 joerg strtol(getenv("CINDEXTEST_REMAP_AFTER_TRIAL"), &endptr, 10); 2150 1.1 joerg } 2151 1.1 joerg 2152 1.1 joerg for (trial = 0; trial < trials; ++trial) { 2153 1.1.1.2 joerg if (execute_command && trial == execute_after_trial) { 2154 1.1.1.2 joerg result = indextest_perform_shell_execution(execute_command); 2155 1.1.1.2 joerg if (result != 0) 2156 1.1.1.2 joerg return result; 2157 1.1.1.2 joerg } 2158 1.1.1.2 joerg 2159 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2160 1.1 joerg if (parse_remapped_files_with_try(trial, argc, argv, 0, 2161 1.1 joerg &unsaved_files, &num_unsaved_files)) { 2162 1.1 joerg clang_disposeTranslationUnit(TU); 2163 1.1 joerg clang_disposeIndex(Idx); 2164 1.1 joerg return -1; 2165 1.1 joerg } 2166 1.1 joerg 2167 1.1 joerg Err = clang_reparseTranslationUnit( 2168 1.1 joerg TU, 2169 1.1 joerg trial >= remap_after_trial ? num_unsaved_files : 0, 2170 1.1 joerg trial >= remap_after_trial ? unsaved_files : 0, 2171 1.1 joerg clang_defaultReparseOptions(TU)); 2172 1.1 joerg if (Err != CXError_Success) { 2173 1.1 joerg fprintf(stderr, "Unable to reparse translation unit!\n"); 2174 1.1 joerg describeLibclangFailure(Err); 2175 1.1 joerg clang_disposeTranslationUnit(TU); 2176 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2177 1.1 joerg clang_disposeIndex(Idx); 2178 1.1 joerg return -1; 2179 1.1 joerg } 2180 1.1 joerg 2181 1.1 joerg if (checkForErrors(TU) != 0) 2182 1.1 joerg return -1; 2183 1.1 joerg } 2184 1.1 joerg 2185 1.1 joerg result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, NULL); 2186 1.1 joerg 2187 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2188 1.1 joerg clang_disposeIndex(Idx); 2189 1.1 joerg return result; 2190 1.1 joerg } 2191 1.1 joerg 2192 1.1 joerg static int perform_single_file_parse(const char *filename) { 2193 1.1 joerg CXIndex Idx; 2194 1.1 joerg CXTranslationUnit TU; 2195 1.1 joerg enum CXErrorCode Err; 2196 1.1 joerg int result; 2197 1.1 joerg 2198 1.1 joerg Idx = clang_createIndex(/* excludeDeclsFromPCH */1, 2199 1.1 joerg /* displayDiagnostics=*/1); 2200 1.1 joerg 2201 1.1 joerg Err = clang_parseTranslationUnit2(Idx, filename, 2202 1.1 joerg /*command_line_args=*/NULL, 2203 1.1 joerg /*num_command_line_args=*/0, 2204 1.1 joerg /*unsaved_files=*/NULL, 2205 1.1 joerg /*num_unsaved_files=*/0, 2206 1.1 joerg CXTranslationUnit_SingleFileParse, &TU); 2207 1.1 joerg if (Err != CXError_Success) { 2208 1.1 joerg fprintf(stderr, "Unable to load translation unit!\n"); 2209 1.1 joerg describeLibclangFailure(Err); 2210 1.1 joerg clang_disposeIndex(Idx); 2211 1.1 joerg return 1; 2212 1.1 joerg } 2213 1.1 joerg 2214 1.1 joerg result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL, 2215 1.1 joerg /*CommentSchemaFile=*/NULL); 2216 1.1 joerg clang_disposeIndex(Idx); 2217 1.1 joerg return result; 2218 1.1 joerg } 2219 1.1 joerg 2220 1.1 joerg static int perform_file_retain_excluded_cb(const char *filename) { 2221 1.1 joerg CXIndex Idx; 2222 1.1 joerg CXTranslationUnit TU; 2223 1.1 joerg enum CXErrorCode Err; 2224 1.1 joerg int result; 2225 1.1 joerg 2226 1.1 joerg Idx = clang_createIndex(/* excludeDeclsFromPCH */1, 2227 1.1 joerg /* displayDiagnostics=*/1); 2228 1.1 joerg 2229 1.1 joerg Err = clang_parseTranslationUnit2(Idx, filename, 2230 1.1 joerg /*command_line_args=*/NULL, 2231 1.1 joerg /*num_command_line_args=*/0, 2232 1.1 joerg /*unsaved_files=*/NULL, 2233 1.1 joerg /*num_unsaved_files=*/0, 2234 1.1 joerg CXTranslationUnit_RetainExcludedConditionalBlocks, &TU); 2235 1.1 joerg if (Err != CXError_Success) { 2236 1.1 joerg fprintf(stderr, "Unable to load translation unit!\n"); 2237 1.1 joerg describeLibclangFailure(Err); 2238 1.1 joerg clang_disposeIndex(Idx); 2239 1.1 joerg return 1; 2240 1.1 joerg } 2241 1.1 joerg 2242 1.1 joerg result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL, 2243 1.1 joerg /*CommentSchemaFile=*/NULL); 2244 1.1 joerg clang_disposeIndex(Idx); 2245 1.1 joerg return result; 2246 1.1 joerg } 2247 1.1 joerg 2248 1.1 joerg /******************************************************************************/ 2249 1.1 joerg /* Logic for testing clang_getCursor(). */ 2250 1.1 joerg /******************************************************************************/ 2251 1.1 joerg 2252 1.1 joerg static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor, 2253 1.1 joerg unsigned start_line, unsigned start_col, 2254 1.1 joerg unsigned end_line, unsigned end_col, 2255 1.1 joerg const char *prefix) { 2256 1.1 joerg printf("// %s: ", FileCheckPrefix); 2257 1.1 joerg if (prefix) 2258 1.1 joerg printf("-%s", prefix); 2259 1.1 joerg PrintExtent(stdout, start_line, start_col, end_line, end_col); 2260 1.1 joerg printf(" "); 2261 1.1 joerg PrintCursor(cursor, NULL); 2262 1.1 joerg printf("\n"); 2263 1.1 joerg } 2264 1.1 joerg 2265 1.1 joerg static int perform_file_scan(const char *ast_file, const char *source_file, 2266 1.1 joerg const char *prefix) { 2267 1.1 joerg CXIndex Idx; 2268 1.1 joerg CXTranslationUnit TU; 2269 1.1 joerg FILE *fp; 2270 1.1 joerg CXCursor prevCursor = clang_getNullCursor(); 2271 1.1 joerg CXFile file; 2272 1.1 joerg unsigned line = 1, col = 1; 2273 1.1 joerg unsigned start_line = 1, start_col = 1; 2274 1.1 joerg 2275 1.1 joerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1, 2276 1.1 joerg /* displayDiagnostics=*/1))) { 2277 1.1 joerg fprintf(stderr, "Could not create Index\n"); 2278 1.1 joerg return 1; 2279 1.1 joerg } 2280 1.1 joerg 2281 1.1 joerg if (!CreateTranslationUnit(Idx, ast_file, &TU)) 2282 1.1 joerg return 1; 2283 1.1 joerg 2284 1.1 joerg if ((fp = fopen(source_file, "r")) == NULL) { 2285 1.1 joerg fprintf(stderr, "Could not open '%s'\n", source_file); 2286 1.1 joerg clang_disposeTranslationUnit(TU); 2287 1.1 joerg return 1; 2288 1.1 joerg } 2289 1.1 joerg 2290 1.1 joerg file = clang_getFile(TU, source_file); 2291 1.1 joerg for (;;) { 2292 1.1 joerg CXCursor cursor; 2293 1.1 joerg int c = fgetc(fp); 2294 1.1 joerg 2295 1.1 joerg if (c == '\n') { 2296 1.1 joerg ++line; 2297 1.1 joerg col = 1; 2298 1.1 joerg } else 2299 1.1 joerg ++col; 2300 1.1 joerg 2301 1.1 joerg /* Check the cursor at this position, and dump the previous one if we have 2302 1.1 joerg * found something new. 2303 1.1 joerg */ 2304 1.1 joerg cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, col)); 2305 1.1 joerg if ((c == EOF || !clang_equalCursors(cursor, prevCursor)) && 2306 1.1 joerg prevCursor.kind != CXCursor_InvalidFile) { 2307 1.1 joerg print_cursor_file_scan(TU, prevCursor, start_line, start_col, 2308 1.1 joerg line, col, prefix); 2309 1.1 joerg start_line = line; 2310 1.1 joerg start_col = col; 2311 1.1 joerg } 2312 1.1 joerg if (c == EOF) 2313 1.1 joerg break; 2314 1.1 joerg 2315 1.1 joerg prevCursor = cursor; 2316 1.1 joerg } 2317 1.1 joerg 2318 1.1 joerg fclose(fp); 2319 1.1 joerg clang_disposeTranslationUnit(TU); 2320 1.1 joerg clang_disposeIndex(Idx); 2321 1.1 joerg return 0; 2322 1.1 joerg } 2323 1.1 joerg 2324 1.1 joerg /******************************************************************************/ 2325 1.1 joerg /* Logic for testing clang code completion. */ 2326 1.1 joerg /******************************************************************************/ 2327 1.1 joerg 2328 1.1 joerg /* Parse file:line:column from the input string. Returns 0 on success, non-zero 2329 1.1 joerg on failure. If successful, the pointer *filename will contain newly-allocated 2330 1.1 joerg memory (that will be owned by the caller) to store the file name. */ 2331 1.1 joerg int parse_file_line_column(const char *input, char **filename, unsigned *line, 2332 1.1 joerg unsigned *column, unsigned *second_line, 2333 1.1 joerg unsigned *second_column) { 2334 1.1 joerg /* Find the second colon. */ 2335 1.1 joerg const char *last_colon = strrchr(input, ':'); 2336 1.1 joerg unsigned values[4], i; 2337 1.1 joerg unsigned num_values = (second_line && second_column)? 4 : 2; 2338 1.1 joerg 2339 1.1 joerg char *endptr = 0; 2340 1.1 joerg if (!last_colon || last_colon == input) { 2341 1.1 joerg if (num_values == 4) 2342 1.1 joerg fprintf(stderr, "could not parse filename:line:column:line:column in " 2343 1.1 joerg "'%s'\n", input); 2344 1.1 joerg else 2345 1.1 joerg fprintf(stderr, "could not parse filename:line:column in '%s'\n", input); 2346 1.1 joerg return 1; 2347 1.1 joerg } 2348 1.1 joerg 2349 1.1 joerg for (i = 0; i != num_values; ++i) { 2350 1.1 joerg const char *prev_colon; 2351 1.1 joerg 2352 1.1 joerg /* Parse the next line or column. */ 2353 1.1 joerg values[num_values - i - 1] = strtol(last_colon + 1, &endptr, 10); 2354 1.1 joerg if (*endptr != 0 && *endptr != ':') { 2355 1.1 joerg fprintf(stderr, "could not parse %s in '%s'\n", 2356 1.1 joerg (i % 2 ? "column" : "line"), input); 2357 1.1 joerg return 1; 2358 1.1 joerg } 2359 1.1 joerg 2360 1.1 joerg if (i + 1 == num_values) 2361 1.1 joerg break; 2362 1.1 joerg 2363 1.1 joerg /* Find the previous colon. */ 2364 1.1 joerg prev_colon = last_colon - 1; 2365 1.1 joerg while (prev_colon != input && *prev_colon != ':') 2366 1.1 joerg --prev_colon; 2367 1.1 joerg if (prev_colon == input) { 2368 1.1 joerg fprintf(stderr, "could not parse %s in '%s'\n", 2369 1.1 joerg (i % 2 == 0? "column" : "line"), input); 2370 1.1 joerg return 1; 2371 1.1 joerg } 2372 1.1 joerg 2373 1.1 joerg last_colon = prev_colon; 2374 1.1 joerg } 2375 1.1 joerg 2376 1.1 joerg *line = values[0]; 2377 1.1 joerg *column = values[1]; 2378 1.1 joerg 2379 1.1 joerg if (second_line && second_column) { 2380 1.1 joerg *second_line = values[2]; 2381 1.1 joerg *second_column = values[3]; 2382 1.1 joerg } 2383 1.1 joerg 2384 1.1 joerg /* Copy the file name. */ 2385 1.1 joerg *filename = (char*)malloc(last_colon - input + 1); 2386 1.1 joerg assert(*filename); 2387 1.1 joerg memcpy(*filename, input, last_colon - input); 2388 1.1 joerg (*filename)[last_colon - input] = 0; 2389 1.1 joerg return 0; 2390 1.1 joerg } 2391 1.1 joerg 2392 1.1 joerg const char * 2393 1.1 joerg clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) { 2394 1.1 joerg switch (Kind) { 2395 1.1 joerg case CXCompletionChunk_Optional: return "Optional"; 2396 1.1 joerg case CXCompletionChunk_TypedText: return "TypedText"; 2397 1.1 joerg case CXCompletionChunk_Text: return "Text"; 2398 1.1 joerg case CXCompletionChunk_Placeholder: return "Placeholder"; 2399 1.1 joerg case CXCompletionChunk_Informative: return "Informative"; 2400 1.1 joerg case CXCompletionChunk_CurrentParameter: return "CurrentParameter"; 2401 1.1 joerg case CXCompletionChunk_LeftParen: return "LeftParen"; 2402 1.1 joerg case CXCompletionChunk_RightParen: return "RightParen"; 2403 1.1 joerg case CXCompletionChunk_LeftBracket: return "LeftBracket"; 2404 1.1 joerg case CXCompletionChunk_RightBracket: return "RightBracket"; 2405 1.1 joerg case CXCompletionChunk_LeftBrace: return "LeftBrace"; 2406 1.1 joerg case CXCompletionChunk_RightBrace: return "RightBrace"; 2407 1.1 joerg case CXCompletionChunk_LeftAngle: return "LeftAngle"; 2408 1.1 joerg case CXCompletionChunk_RightAngle: return "RightAngle"; 2409 1.1 joerg case CXCompletionChunk_Comma: return "Comma"; 2410 1.1 joerg case CXCompletionChunk_ResultType: return "ResultType"; 2411 1.1 joerg case CXCompletionChunk_Colon: return "Colon"; 2412 1.1 joerg case CXCompletionChunk_SemiColon: return "SemiColon"; 2413 1.1 joerg case CXCompletionChunk_Equal: return "Equal"; 2414 1.1 joerg case CXCompletionChunk_HorizontalSpace: return "HorizontalSpace"; 2415 1.1 joerg case CXCompletionChunk_VerticalSpace: return "VerticalSpace"; 2416 1.1 joerg } 2417 1.1 joerg 2418 1.1 joerg return "Unknown"; 2419 1.1 joerg } 2420 1.1 joerg 2421 1.1 joerg static int checkForErrors(CXTranslationUnit TU) { 2422 1.1 joerg unsigned Num, i; 2423 1.1 joerg CXDiagnostic Diag; 2424 1.1 joerg CXString DiagStr; 2425 1.1 joerg 2426 1.1 joerg if (!getenv("CINDEXTEST_FAILONERROR")) 2427 1.1 joerg return 0; 2428 1.1 joerg 2429 1.1 joerg Num = clang_getNumDiagnostics(TU); 2430 1.1 joerg for (i = 0; i != Num; ++i) { 2431 1.1 joerg Diag = clang_getDiagnostic(TU, i); 2432 1.1 joerg if (clang_getDiagnosticSeverity(Diag) >= CXDiagnostic_Error) { 2433 1.1 joerg DiagStr = clang_formatDiagnostic(Diag, 2434 1.1 joerg clang_defaultDiagnosticDisplayOptions()); 2435 1.1 joerg fprintf(stderr, "%s\n", clang_getCString(DiagStr)); 2436 1.1 joerg clang_disposeString(DiagStr); 2437 1.1 joerg clang_disposeDiagnostic(Diag); 2438 1.1 joerg return -1; 2439 1.1 joerg } 2440 1.1 joerg clang_disposeDiagnostic(Diag); 2441 1.1 joerg } 2442 1.1 joerg 2443 1.1 joerg return 0; 2444 1.1 joerg } 2445 1.1 joerg 2446 1.1 joerg static void print_completion_string(CXCompletionString completion_string, 2447 1.1 joerg FILE *file) { 2448 1.1 joerg int I, N; 2449 1.1 joerg 2450 1.1 joerg N = clang_getNumCompletionChunks(completion_string); 2451 1.1 joerg for (I = 0; I != N; ++I) { 2452 1.1 joerg CXString text; 2453 1.1 joerg const char *cstr; 2454 1.1 joerg enum CXCompletionChunkKind Kind 2455 1.1 joerg = clang_getCompletionChunkKind(completion_string, I); 2456 1.1 joerg 2457 1.1 joerg if (Kind == CXCompletionChunk_Optional) { 2458 1.1 joerg fprintf(file, "{Optional "); 2459 1.1 joerg print_completion_string( 2460 1.1 joerg clang_getCompletionChunkCompletionString(completion_string, I), 2461 1.1 joerg file); 2462 1.1 joerg fprintf(file, "}"); 2463 1.1 joerg continue; 2464 1.1 joerg } 2465 1.1 joerg 2466 1.1 joerg if (Kind == CXCompletionChunk_VerticalSpace) { 2467 1.1 joerg fprintf(file, "{VerticalSpace }"); 2468 1.1 joerg continue; 2469 1.1 joerg } 2470 1.1 joerg 2471 1.1 joerg text = clang_getCompletionChunkText(completion_string, I); 2472 1.1 joerg cstr = clang_getCString(text); 2473 1.1 joerg fprintf(file, "{%s %s}", 2474 1.1 joerg clang_getCompletionChunkKindSpelling(Kind), 2475 1.1 joerg cstr ? cstr : ""); 2476 1.1 joerg clang_disposeString(text); 2477 1.1 joerg } 2478 1.1 joerg 2479 1.1 joerg } 2480 1.1 joerg 2481 1.1 joerg static void print_line_column(CXSourceLocation location, FILE *file) { 2482 1.1 joerg unsigned line, column; 2483 1.1 joerg clang_getExpansionLocation(location, NULL, &line, &column, NULL); 2484 1.1 joerg fprintf(file, "%d:%d", line, column); 2485 1.1 joerg } 2486 1.1 joerg 2487 1.1 joerg static void print_token_range(CXTranslationUnit translation_unit, 2488 1.1 joerg CXSourceLocation start, FILE *file) { 2489 1.1 joerg CXToken *token = clang_getToken(translation_unit, start); 2490 1.1 joerg 2491 1.1 joerg fprintf(file, "{"); 2492 1.1 joerg if (token != NULL) { 2493 1.1 joerg CXSourceRange token_range = clang_getTokenExtent(translation_unit, *token); 2494 1.1 joerg print_line_column(clang_getRangeStart(token_range), file); 2495 1.1 joerg fprintf(file, "-"); 2496 1.1 joerg print_line_column(clang_getRangeEnd(token_range), file); 2497 1.1 joerg clang_disposeTokens(translation_unit, token, 1); 2498 1.1 joerg } 2499 1.1 joerg 2500 1.1 joerg fprintf(file, "}"); 2501 1.1 joerg } 2502 1.1 joerg 2503 1.1 joerg static void print_completion_result(CXTranslationUnit translation_unit, 2504 1.1 joerg CXCodeCompleteResults *completion_results, 2505 1.1 joerg unsigned index, 2506 1.1 joerg FILE *file) { 2507 1.1 joerg CXCompletionResult *completion_result = completion_results->Results + index; 2508 1.1 joerg CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); 2509 1.1 joerg unsigned annotationCount; 2510 1.1 joerg enum CXCursorKind ParentKind; 2511 1.1 joerg CXString ParentName; 2512 1.1 joerg CXString BriefComment; 2513 1.1 joerg CXString Annotation; 2514 1.1 joerg const char *BriefCommentCString; 2515 1.1 joerg unsigned i; 2516 1.1 joerg 2517 1.1 joerg fprintf(file, "%s:", clang_getCString(ks)); 2518 1.1 joerg clang_disposeString(ks); 2519 1.1 joerg 2520 1.1 joerg print_completion_string(completion_result->CompletionString, file); 2521 1.1 joerg fprintf(file, " (%u)", 2522 1.1 joerg clang_getCompletionPriority(completion_result->CompletionString)); 2523 1.1 joerg switch (clang_getCompletionAvailability(completion_result->CompletionString)){ 2524 1.1 joerg case CXAvailability_Available: 2525 1.1 joerg break; 2526 1.1 joerg 2527 1.1 joerg case CXAvailability_Deprecated: 2528 1.1 joerg fprintf(file, " (deprecated)"); 2529 1.1 joerg break; 2530 1.1 joerg 2531 1.1 joerg case CXAvailability_NotAvailable: 2532 1.1 joerg fprintf(file, " (unavailable)"); 2533 1.1 joerg break; 2534 1.1 joerg 2535 1.1 joerg case CXAvailability_NotAccessible: 2536 1.1 joerg fprintf(file, " (inaccessible)"); 2537 1.1 joerg break; 2538 1.1 joerg } 2539 1.1 joerg 2540 1.1 joerg annotationCount = clang_getCompletionNumAnnotations( 2541 1.1 joerg completion_result->CompletionString); 2542 1.1 joerg if (annotationCount) { 2543 1.1 joerg unsigned i; 2544 1.1 joerg fprintf(file, " ("); 2545 1.1 joerg for (i = 0; i < annotationCount; ++i) { 2546 1.1 joerg if (i != 0) 2547 1.1 joerg fprintf(file, ", "); 2548 1.1 joerg Annotation = 2549 1.1 joerg clang_getCompletionAnnotation(completion_result->CompletionString, i); 2550 1.1 joerg fprintf(file, "\"%s\"", clang_getCString(Annotation)); 2551 1.1 joerg clang_disposeString(Annotation); 2552 1.1 joerg } 2553 1.1 joerg fprintf(file, ")"); 2554 1.1 joerg } 2555 1.1 joerg 2556 1.1 joerg if (!getenv("CINDEXTEST_NO_COMPLETION_PARENTS")) { 2557 1.1 joerg ParentName = clang_getCompletionParent(completion_result->CompletionString, 2558 1.1 joerg &ParentKind); 2559 1.1 joerg if (ParentKind != CXCursor_NotImplemented) { 2560 1.1 joerg CXString KindSpelling = clang_getCursorKindSpelling(ParentKind); 2561 1.1 joerg fprintf(file, " (parent: %s '%s')", 2562 1.1 joerg clang_getCString(KindSpelling), 2563 1.1 joerg clang_getCString(ParentName)); 2564 1.1 joerg clang_disposeString(KindSpelling); 2565 1.1 joerg } 2566 1.1 joerg clang_disposeString(ParentName); 2567 1.1 joerg } 2568 1.1 joerg 2569 1.1 joerg BriefComment = clang_getCompletionBriefComment( 2570 1.1 joerg completion_result->CompletionString); 2571 1.1 joerg BriefCommentCString = clang_getCString(BriefComment); 2572 1.1 joerg if (BriefCommentCString && *BriefCommentCString != '\0') { 2573 1.1 joerg fprintf(file, "(brief comment: %s)", BriefCommentCString); 2574 1.1 joerg } 2575 1.1 joerg clang_disposeString(BriefComment); 2576 1.1 joerg 2577 1.1 joerg for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index); 2578 1.1 joerg ++i) { 2579 1.1 joerg CXSourceRange correction_range; 2580 1.1 joerg CXString FixIt = clang_getCompletionFixIt(completion_results, index, i, 2581 1.1 joerg &correction_range); 2582 1.1 joerg fprintf(file, " (requires fix-it: "); 2583 1.1 joerg print_token_range(translation_unit, clang_getRangeStart(correction_range), 2584 1.1 joerg file); 2585 1.1 joerg fprintf(file, " to \"%s\")", clang_getCString(FixIt)); 2586 1.1 joerg clang_disposeString(FixIt); 2587 1.1 joerg } 2588 1.1 joerg 2589 1.1 joerg fprintf(file, "\n"); 2590 1.1 joerg } 2591 1.1 joerg 2592 1.1 joerg void print_completion_contexts(unsigned long long contexts, FILE *file) { 2593 1.1 joerg fprintf(file, "Completion contexts:\n"); 2594 1.1 joerg if (contexts == CXCompletionContext_Unknown) { 2595 1.1 joerg fprintf(file, "Unknown\n"); 2596 1.1 joerg } 2597 1.1 joerg if (contexts & CXCompletionContext_AnyType) { 2598 1.1 joerg fprintf(file, "Any type\n"); 2599 1.1 joerg } 2600 1.1 joerg if (contexts & CXCompletionContext_AnyValue) { 2601 1.1 joerg fprintf(file, "Any value\n"); 2602 1.1 joerg } 2603 1.1 joerg if (contexts & CXCompletionContext_ObjCObjectValue) { 2604 1.1 joerg fprintf(file, "Objective-C object value\n"); 2605 1.1 joerg } 2606 1.1 joerg if (contexts & CXCompletionContext_ObjCSelectorValue) { 2607 1.1 joerg fprintf(file, "Objective-C selector value\n"); 2608 1.1 joerg } 2609 1.1 joerg if (contexts & CXCompletionContext_CXXClassTypeValue) { 2610 1.1 joerg fprintf(file, "C++ class type value\n"); 2611 1.1 joerg } 2612 1.1 joerg if (contexts & CXCompletionContext_DotMemberAccess) { 2613 1.1 joerg fprintf(file, "Dot member access\n"); 2614 1.1 joerg } 2615 1.1 joerg if (contexts & CXCompletionContext_ArrowMemberAccess) { 2616 1.1 joerg fprintf(file, "Arrow member access\n"); 2617 1.1 joerg } 2618 1.1 joerg if (contexts & CXCompletionContext_ObjCPropertyAccess) { 2619 1.1 joerg fprintf(file, "Objective-C property access\n"); 2620 1.1 joerg } 2621 1.1 joerg if (contexts & CXCompletionContext_EnumTag) { 2622 1.1 joerg fprintf(file, "Enum tag\n"); 2623 1.1 joerg } 2624 1.1 joerg if (contexts & CXCompletionContext_UnionTag) { 2625 1.1 joerg fprintf(file, "Union tag\n"); 2626 1.1 joerg } 2627 1.1 joerg if (contexts & CXCompletionContext_StructTag) { 2628 1.1 joerg fprintf(file, "Struct tag\n"); 2629 1.1 joerg } 2630 1.1 joerg if (contexts & CXCompletionContext_ClassTag) { 2631 1.1 joerg fprintf(file, "Class name\n"); 2632 1.1 joerg } 2633 1.1 joerg if (contexts & CXCompletionContext_Namespace) { 2634 1.1 joerg fprintf(file, "Namespace or namespace alias\n"); 2635 1.1 joerg } 2636 1.1 joerg if (contexts & CXCompletionContext_NestedNameSpecifier) { 2637 1.1 joerg fprintf(file, "Nested name specifier\n"); 2638 1.1 joerg } 2639 1.1 joerg if (contexts & CXCompletionContext_ObjCInterface) { 2640 1.1 joerg fprintf(file, "Objective-C interface\n"); 2641 1.1 joerg } 2642 1.1 joerg if (contexts & CXCompletionContext_ObjCProtocol) { 2643 1.1 joerg fprintf(file, "Objective-C protocol\n"); 2644 1.1 joerg } 2645 1.1 joerg if (contexts & CXCompletionContext_ObjCCategory) { 2646 1.1 joerg fprintf(file, "Objective-C category\n"); 2647 1.1 joerg } 2648 1.1 joerg if (contexts & CXCompletionContext_ObjCInstanceMessage) { 2649 1.1 joerg fprintf(file, "Objective-C instance method\n"); 2650 1.1 joerg } 2651 1.1 joerg if (contexts & CXCompletionContext_ObjCClassMessage) { 2652 1.1 joerg fprintf(file, "Objective-C class method\n"); 2653 1.1 joerg } 2654 1.1 joerg if (contexts & CXCompletionContext_ObjCSelectorName) { 2655 1.1 joerg fprintf(file, "Objective-C selector name\n"); 2656 1.1 joerg } 2657 1.1 joerg if (contexts & CXCompletionContext_MacroName) { 2658 1.1 joerg fprintf(file, "Macro name\n"); 2659 1.1 joerg } 2660 1.1 joerg if (contexts & CXCompletionContext_NaturalLanguage) { 2661 1.1 joerg fprintf(file, "Natural language\n"); 2662 1.1 joerg } 2663 1.1 joerg } 2664 1.1 joerg 2665 1.1 joerg int perform_code_completion(int argc, const char **argv, int timing_only) { 2666 1.1 joerg const char *input = argv[1]; 2667 1.1 joerg char *filename = 0; 2668 1.1 joerg unsigned line; 2669 1.1 joerg unsigned column; 2670 1.1 joerg CXIndex CIdx; 2671 1.1 joerg int errorCode; 2672 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 2673 1.1 joerg int num_unsaved_files = 0; 2674 1.1 joerg CXCodeCompleteResults *results = 0; 2675 1.1 joerg enum CXErrorCode Err; 2676 1.1 joerg CXTranslationUnit TU; 2677 1.1 joerg unsigned I, Repeats = 1; 2678 1.1 joerg unsigned completionOptions = clang_defaultCodeCompleteOptions(); 2679 1.1 joerg const char *InvocationPath; 2680 1.1 joerg 2681 1.1 joerg if (getenv("CINDEXTEST_CODE_COMPLETE_PATTERNS")) 2682 1.1 joerg completionOptions |= CXCodeComplete_IncludeCodePatterns; 2683 1.1 joerg if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) 2684 1.1 joerg completionOptions |= CXCodeComplete_IncludeBriefComments; 2685 1.1 joerg if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE")) 2686 1.1 joerg completionOptions |= CXCodeComplete_SkipPreamble; 2687 1.1 joerg if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS")) 2688 1.1 joerg completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts; 2689 1.1 joerg 2690 1.1 joerg if (timing_only) 2691 1.1 joerg input += strlen("-code-completion-timing="); 2692 1.1 joerg else 2693 1.1 joerg input += strlen("-code-completion-at="); 2694 1.1 joerg 2695 1.1 joerg if ((errorCode = parse_file_line_column(input, &filename, &line, &column, 2696 1.1 joerg 0, 0))) 2697 1.1 joerg return errorCode; 2698 1.1 joerg 2699 1.1 joerg if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) 2700 1.1 joerg return -1; 2701 1.1 joerg 2702 1.1 joerg CIdx = clang_createIndex(0, 0); 2703 1.1 joerg InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH"); 2704 1.1 joerg if (InvocationPath) 2705 1.1 joerg clang_CXIndex_setInvocationEmissionPathOption(CIdx, InvocationPath); 2706 1.1 joerg 2707 1.1 joerg if (getenv("CINDEXTEST_EDITING")) 2708 1.1 joerg Repeats = 5; 2709 1.1 joerg 2710 1.1 joerg Err = clang_parseTranslationUnit2(CIdx, 0, 2711 1.1 joerg argv + num_unsaved_files + 2, 2712 1.1 joerg argc - num_unsaved_files - 2, 2713 1.1 joerg 0, 0, getDefaultParsingOptions(), &TU); 2714 1.1 joerg if (Err != CXError_Success) { 2715 1.1 joerg fprintf(stderr, "Unable to load translation unit!\n"); 2716 1.1 joerg describeLibclangFailure(Err); 2717 1.1 joerg return 1; 2718 1.1 joerg } 2719 1.1 joerg 2720 1.1 joerg Err = clang_reparseTranslationUnit(TU, 0, 0, 2721 1.1 joerg clang_defaultReparseOptions(TU)); 2722 1.1 joerg 2723 1.1 joerg if (Err != CXError_Success) { 2724 1.1 joerg fprintf(stderr, "Unable to reparse translation unit!\n"); 2725 1.1 joerg describeLibclangFailure(Err); 2726 1.1 joerg clang_disposeTranslationUnit(TU); 2727 1.1 joerg return 1; 2728 1.1 joerg } 2729 1.1 joerg 2730 1.1 joerg for (I = 0; I != Repeats; ++I) { 2731 1.1 joerg results = clang_codeCompleteAt(TU, filename, line, column, 2732 1.1 joerg unsaved_files, num_unsaved_files, 2733 1.1 joerg completionOptions); 2734 1.1 joerg if (!results) { 2735 1.1 joerg fprintf(stderr, "Unable to perform code completion!\n"); 2736 1.1 joerg return 1; 2737 1.1 joerg } 2738 1.1 joerg if (I != Repeats-1) 2739 1.1 joerg clang_disposeCodeCompleteResults(results); 2740 1.1 joerg } 2741 1.1 joerg 2742 1.1 joerg if (results) { 2743 1.1 joerg unsigned i, n = results->NumResults, containerIsIncomplete = 0; 2744 1.1 joerg unsigned long long contexts; 2745 1.1 joerg enum CXCursorKind containerKind; 2746 1.1 joerg CXString objCSelector; 2747 1.1 joerg const char *selectorString; 2748 1.1 joerg if (!timing_only) { 2749 1.1 joerg /* Sort the code-completion results based on the typed text. */ 2750 1.1 joerg clang_sortCodeCompletionResults(results->Results, results->NumResults); 2751 1.1 joerg 2752 1.1 joerg for (i = 0; i != n; ++i) 2753 1.1 joerg print_completion_result(TU, results, i, stdout); 2754 1.1 joerg } 2755 1.1 joerg n = clang_codeCompleteGetNumDiagnostics(results); 2756 1.1 joerg for (i = 0; i != n; ++i) { 2757 1.1 joerg CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i); 2758 1.1 joerg PrintDiagnostic(diag); 2759 1.1 joerg clang_disposeDiagnostic(diag); 2760 1.1 joerg } 2761 1.1 joerg 2762 1.1 joerg contexts = clang_codeCompleteGetContexts(results); 2763 1.1 joerg print_completion_contexts(contexts, stdout); 2764 1.1 joerg 2765 1.1 joerg containerKind = clang_codeCompleteGetContainerKind(results, 2766 1.1 joerg &containerIsIncomplete); 2767 1.1 joerg 2768 1.1 joerg if (containerKind != CXCursor_InvalidCode) { 2769 1.1 joerg /* We have found a container */ 2770 1.1 joerg CXString containerUSR, containerKindSpelling; 2771 1.1 joerg containerKindSpelling = clang_getCursorKindSpelling(containerKind); 2772 1.1 joerg printf("Container Kind: %s\n", clang_getCString(containerKindSpelling)); 2773 1.1 joerg clang_disposeString(containerKindSpelling); 2774 1.1 joerg 2775 1.1 joerg if (containerIsIncomplete) { 2776 1.1 joerg printf("Container is incomplete\n"); 2777 1.1 joerg } 2778 1.1 joerg else { 2779 1.1 joerg printf("Container is complete\n"); 2780 1.1 joerg } 2781 1.1 joerg 2782 1.1 joerg containerUSR = clang_codeCompleteGetContainerUSR(results); 2783 1.1 joerg printf("Container USR: %s\n", clang_getCString(containerUSR)); 2784 1.1 joerg clang_disposeString(containerUSR); 2785 1.1 joerg } 2786 1.1 joerg 2787 1.1 joerg objCSelector = clang_codeCompleteGetObjCSelector(results); 2788 1.1 joerg selectorString = clang_getCString(objCSelector); 2789 1.1 joerg if (selectorString && strlen(selectorString) > 0) { 2790 1.1 joerg printf("Objective-C selector: %s\n", selectorString); 2791 1.1 joerg } 2792 1.1 joerg clang_disposeString(objCSelector); 2793 1.1 joerg 2794 1.1 joerg clang_disposeCodeCompleteResults(results); 2795 1.1 joerg } 2796 1.1 joerg clang_disposeTranslationUnit(TU); 2797 1.1 joerg clang_disposeIndex(CIdx); 2798 1.1 joerg free(filename); 2799 1.1 joerg 2800 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2801 1.1 joerg 2802 1.1 joerg return 0; 2803 1.1 joerg } 2804 1.1 joerg 2805 1.1 joerg typedef struct { 2806 1.1 joerg char *filename; 2807 1.1 joerg unsigned line; 2808 1.1 joerg unsigned column; 2809 1.1 joerg } CursorSourceLocation; 2810 1.1 joerg 2811 1.1 joerg typedef void (*cursor_handler_t)(CXCursor cursor); 2812 1.1 joerg 2813 1.1 joerg static int inspect_cursor_at(int argc, const char **argv, 2814 1.1 joerg const char *locations_flag, 2815 1.1 joerg cursor_handler_t handler) { 2816 1.1 joerg CXIndex CIdx; 2817 1.1 joerg int errorCode; 2818 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 2819 1.1 joerg int num_unsaved_files = 0; 2820 1.1 joerg enum CXErrorCode Err; 2821 1.1 joerg CXTranslationUnit TU; 2822 1.1 joerg CXCursor Cursor; 2823 1.1 joerg CursorSourceLocation *Locations = 0; 2824 1.1 joerg unsigned NumLocations = 0, Loc; 2825 1.1 joerg unsigned Repeats = 1; 2826 1.1 joerg unsigned I; 2827 1.1 joerg 2828 1.1 joerg /* Count the number of locations. */ 2829 1.1 joerg while (strstr(argv[NumLocations+1], locations_flag) == argv[NumLocations+1]) 2830 1.1 joerg ++NumLocations; 2831 1.1 joerg 2832 1.1 joerg /* Parse the locations. */ 2833 1.1 joerg assert(NumLocations > 0 && "Unable to count locations?"); 2834 1.1 joerg Locations = (CursorSourceLocation *)malloc( 2835 1.1 joerg NumLocations * sizeof(CursorSourceLocation)); 2836 1.1 joerg assert(Locations); 2837 1.1 joerg for (Loc = 0; Loc < NumLocations; ++Loc) { 2838 1.1 joerg const char *input = argv[Loc + 1] + strlen(locations_flag); 2839 1.1 joerg if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename, 2840 1.1 joerg &Locations[Loc].line, 2841 1.1 joerg &Locations[Loc].column, 0, 0))) 2842 1.1 joerg return errorCode; 2843 1.1 joerg } 2844 1.1 joerg 2845 1.1 joerg if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files, 2846 1.1 joerg &num_unsaved_files)) 2847 1.1 joerg return -1; 2848 1.1 joerg 2849 1.1 joerg if (getenv("CINDEXTEST_EDITING")) 2850 1.1 joerg Repeats = 5; 2851 1.1 joerg 2852 1.1 joerg /* Parse the translation unit. When we're testing clang_getCursor() after 2853 1.1 joerg reparsing, don't remap unsaved files until the second parse. */ 2854 1.1 joerg CIdx = clang_createIndex(1, 1); 2855 1.1 joerg Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1], 2856 1.1 joerg argv + num_unsaved_files + 1 + NumLocations, 2857 1.1 joerg argc - num_unsaved_files - 2 - NumLocations, 2858 1.1 joerg unsaved_files, 2859 1.1 joerg Repeats > 1? 0 : num_unsaved_files, 2860 1.1 joerg getDefaultParsingOptions(), &TU); 2861 1.1 joerg if (Err != CXError_Success) { 2862 1.1 joerg fprintf(stderr, "unable to parse input\n"); 2863 1.1 joerg describeLibclangFailure(Err); 2864 1.1 joerg return -1; 2865 1.1 joerg } 2866 1.1 joerg 2867 1.1 joerg if (checkForErrors(TU) != 0) 2868 1.1 joerg return -1; 2869 1.1 joerg 2870 1.1 joerg for (I = 0; I != Repeats; ++I) { 2871 1.1 joerg if (Repeats > 1) { 2872 1.1 joerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, 2873 1.1 joerg clang_defaultReparseOptions(TU)); 2874 1.1 joerg if (Err != CXError_Success) { 2875 1.1 joerg describeLibclangFailure(Err); 2876 1.1 joerg clang_disposeTranslationUnit(TU); 2877 1.1 joerg return 1; 2878 1.1 joerg } 2879 1.1 joerg } 2880 1.1 joerg 2881 1.1 joerg if (checkForErrors(TU) != 0) 2882 1.1 joerg return -1; 2883 1.1 joerg 2884 1.1 joerg for (Loc = 0; Loc < NumLocations; ++Loc) { 2885 1.1 joerg CXFile file = clang_getFile(TU, Locations[Loc].filename); 2886 1.1 joerg if (!file) 2887 1.1 joerg continue; 2888 1.1 joerg 2889 1.1 joerg Cursor = clang_getCursor(TU, 2890 1.1 joerg clang_getLocation(TU, file, Locations[Loc].line, 2891 1.1 joerg Locations[Loc].column)); 2892 1.1 joerg 2893 1.1 joerg if (checkForErrors(TU) != 0) 2894 1.1 joerg return -1; 2895 1.1 joerg 2896 1.1 joerg if (I + 1 == Repeats) { 2897 1.1 joerg handler(Cursor); 2898 1.1 joerg free(Locations[Loc].filename); 2899 1.1 joerg } 2900 1.1 joerg } 2901 1.1 joerg } 2902 1.1 joerg 2903 1.1 joerg PrintDiagnostics(TU); 2904 1.1 joerg clang_disposeTranslationUnit(TU); 2905 1.1 joerg clang_disposeIndex(CIdx); 2906 1.1 joerg free(Locations); 2907 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 2908 1.1 joerg return 0; 2909 1.1 joerg } 2910 1.1 joerg 2911 1.1 joerg static void inspect_print_cursor(CXCursor Cursor) { 2912 1.1 joerg CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); 2913 1.1 joerg CXCompletionString completionString = clang_getCursorCompletionString( 2914 1.1 joerg Cursor); 2915 1.1 joerg CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); 2916 1.1 joerg CXString Spelling; 2917 1.1 joerg const char *cspell; 2918 1.1 joerg unsigned line, column; 2919 1.1 joerg clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); 2920 1.1 joerg printf("%d:%d ", line, column); 2921 1.1 joerg PrintCursor(Cursor, NULL); 2922 1.1 joerg PrintCursorExtent(Cursor); 2923 1.1 joerg Spelling = clang_getCursorSpelling(Cursor); 2924 1.1 joerg cspell = clang_getCString(Spelling); 2925 1.1 joerg if (cspell && strlen(cspell) != 0) { 2926 1.1 joerg unsigned pieceIndex; 2927 1.1 joerg printf(" Spelling=%s (", cspell); 2928 1.1 joerg for (pieceIndex = 0; ; ++pieceIndex) { 2929 1.1 joerg CXSourceRange range = 2930 1.1 joerg clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); 2931 1.1 joerg if (clang_Range_isNull(range)) 2932 1.1 joerg break; 2933 1.1 joerg PrintRange(range, 0); 2934 1.1 joerg } 2935 1.1 joerg printf(")"); 2936 1.1 joerg } 2937 1.1 joerg clang_disposeString(Spelling); 2938 1.1 joerg if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1) 2939 1.1 joerg printf(" Selector index=%d", 2940 1.1 joerg clang_Cursor_getObjCSelectorIndex(Cursor)); 2941 1.1 joerg if (clang_Cursor_isDynamicCall(Cursor)) 2942 1.1 joerg printf(" Dynamic-call"); 2943 1.1 joerg if (Cursor.kind == CXCursor_ObjCMessageExpr || 2944 1.1 joerg Cursor.kind == CXCursor_MemberRefExpr) { 2945 1.1 joerg CXType T = clang_Cursor_getReceiverType(Cursor); 2946 1.1 joerg if (T.kind != CXType_Invalid) { 2947 1.1 joerg CXString S = clang_getTypeKindSpelling(T.kind); 2948 1.1 joerg printf(" Receiver-type=%s", clang_getCString(S)); 2949 1.1 joerg clang_disposeString(S); 2950 1.1 joerg } 2951 1.1 joerg } 2952 1.1 joerg 2953 1.1 joerg { 2954 1.1 joerg CXModule mod = clang_Cursor_getModule(Cursor); 2955 1.1 joerg CXFile astFile; 2956 1.1 joerg CXString name, astFilename; 2957 1.1 joerg unsigned i, numHeaders; 2958 1.1 joerg if (mod) { 2959 1.1 joerg astFile = clang_Module_getASTFile(mod); 2960 1.1 joerg astFilename = clang_getFileName(astFile); 2961 1.1 joerg name = clang_Module_getFullName(mod); 2962 1.1 joerg numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod); 2963 1.1 joerg printf(" ModuleName=%s (%s) system=%d Headers(%d):", 2964 1.1 joerg clang_getCString(name), clang_getCString(astFilename), 2965 1.1 joerg clang_Module_isSystem(mod), numHeaders); 2966 1.1 joerg clang_disposeString(name); 2967 1.1 joerg clang_disposeString(astFilename); 2968 1.1 joerg for (i = 0; i < numHeaders; ++i) { 2969 1.1 joerg CXFile file = clang_Module_getTopLevelHeader(TU, mod, i); 2970 1.1 joerg CXString filename = clang_getFileName(file); 2971 1.1 joerg printf("\n%s", clang_getCString(filename)); 2972 1.1 joerg clang_disposeString(filename); 2973 1.1 joerg } 2974 1.1 joerg } 2975 1.1 joerg } 2976 1.1 joerg 2977 1.1 joerg if (completionString != NULL) { 2978 1.1 joerg printf("\nCompletion string: "); 2979 1.1 joerg print_completion_string(completionString, stdout); 2980 1.1 joerg } 2981 1.1 joerg printf("\n"); 2982 1.1 joerg } 2983 1.1 joerg 2984 1.1 joerg static void display_evaluate_results(CXEvalResult result) { 2985 1.1 joerg switch (clang_EvalResult_getKind(result)) { 2986 1.1 joerg case CXEval_Int: 2987 1.1 joerg { 2988 1.1 joerg printf("Kind: Int, "); 2989 1.1 joerg if (clang_EvalResult_isUnsignedInt(result)) { 2990 1.1 joerg unsigned long long val = clang_EvalResult_getAsUnsigned(result); 2991 1.1 joerg printf("unsigned, Value: %llu", val); 2992 1.1 joerg } else { 2993 1.1 joerg long long val = clang_EvalResult_getAsLongLong(result); 2994 1.1 joerg printf("Value: %lld", val); 2995 1.1 joerg } 2996 1.1 joerg break; 2997 1.1 joerg } 2998 1.1 joerg case CXEval_Float: 2999 1.1 joerg { 3000 1.1 joerg double val = clang_EvalResult_getAsDouble(result); 3001 1.1 joerg printf("Kind: Float , Value: %f", val); 3002 1.1 joerg break; 3003 1.1 joerg } 3004 1.1 joerg case CXEval_ObjCStrLiteral: 3005 1.1 joerg { 3006 1.1 joerg const char* str = clang_EvalResult_getAsStr(result); 3007 1.1 joerg printf("Kind: ObjCString , Value: %s", str); 3008 1.1 joerg break; 3009 1.1 joerg } 3010 1.1 joerg case CXEval_StrLiteral: 3011 1.1 joerg { 3012 1.1 joerg const char* str = clang_EvalResult_getAsStr(result); 3013 1.1 joerg printf("Kind: CString , Value: %s", str); 3014 1.1 joerg break; 3015 1.1 joerg } 3016 1.1 joerg case CXEval_CFStr: 3017 1.1 joerg { 3018 1.1 joerg const char* str = clang_EvalResult_getAsStr(result); 3019 1.1 joerg printf("Kind: CFString , Value: %s", str); 3020 1.1 joerg break; 3021 1.1 joerg } 3022 1.1 joerg default: 3023 1.1 joerg printf("Unexposed"); 3024 1.1 joerg break; 3025 1.1 joerg } 3026 1.1 joerg } 3027 1.1 joerg 3028 1.1 joerg static void inspect_evaluate_cursor(CXCursor Cursor) { 3029 1.1 joerg CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); 3030 1.1 joerg CXString Spelling; 3031 1.1 joerg const char *cspell; 3032 1.1 joerg unsigned line, column; 3033 1.1 joerg CXEvalResult ER; 3034 1.1 joerg 3035 1.1 joerg clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); 3036 1.1 joerg printf("%d:%d ", line, column); 3037 1.1 joerg PrintCursor(Cursor, NULL); 3038 1.1 joerg PrintCursorExtent(Cursor); 3039 1.1 joerg Spelling = clang_getCursorSpelling(Cursor); 3040 1.1 joerg cspell = clang_getCString(Spelling); 3041 1.1 joerg if (cspell && strlen(cspell) != 0) { 3042 1.1 joerg unsigned pieceIndex; 3043 1.1 joerg printf(" Spelling=%s (", cspell); 3044 1.1 joerg for (pieceIndex = 0; ; ++pieceIndex) { 3045 1.1 joerg CXSourceRange range = 3046 1.1 joerg clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); 3047 1.1 joerg if (clang_Range_isNull(range)) 3048 1.1 joerg break; 3049 1.1 joerg PrintRange(range, 0); 3050 1.1 joerg } 3051 1.1 joerg printf(")"); 3052 1.1 joerg } 3053 1.1 joerg clang_disposeString(Spelling); 3054 1.1 joerg 3055 1.1 joerg ER = clang_Cursor_Evaluate(Cursor); 3056 1.1 joerg if (!ER) { 3057 1.1 joerg printf("Not Evaluatable"); 3058 1.1 joerg } else { 3059 1.1 joerg display_evaluate_results(ER); 3060 1.1 joerg clang_EvalResult_dispose(ER); 3061 1.1 joerg } 3062 1.1 joerg printf("\n"); 3063 1.1 joerg } 3064 1.1 joerg 3065 1.1 joerg static void inspect_macroinfo_cursor(CXCursor Cursor) { 3066 1.1 joerg CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor); 3067 1.1 joerg CXString Spelling; 3068 1.1 joerg const char *cspell; 3069 1.1 joerg unsigned line, column; 3070 1.1 joerg clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); 3071 1.1 joerg printf("%d:%d ", line, column); 3072 1.1 joerg PrintCursor(Cursor, NULL); 3073 1.1 joerg PrintCursorExtent(Cursor); 3074 1.1 joerg Spelling = clang_getCursorSpelling(Cursor); 3075 1.1 joerg cspell = clang_getCString(Spelling); 3076 1.1 joerg if (cspell && strlen(cspell) != 0) { 3077 1.1 joerg unsigned pieceIndex; 3078 1.1 joerg printf(" Spelling=%s (", cspell); 3079 1.1 joerg for (pieceIndex = 0; ; ++pieceIndex) { 3080 1.1 joerg CXSourceRange range = 3081 1.1 joerg clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0); 3082 1.1 joerg if (clang_Range_isNull(range)) 3083 1.1 joerg break; 3084 1.1 joerg PrintRange(range, 0); 3085 1.1 joerg } 3086 1.1 joerg printf(")"); 3087 1.1 joerg } 3088 1.1 joerg clang_disposeString(Spelling); 3089 1.1 joerg 3090 1.1 joerg if (clang_Cursor_isMacroBuiltin(Cursor)) { 3091 1.1 joerg printf("[builtin macro]"); 3092 1.1 joerg } else if (clang_Cursor_isMacroFunctionLike(Cursor)) { 3093 1.1 joerg printf("[function macro]"); 3094 1.1 joerg } 3095 1.1 joerg printf("\n"); 3096 1.1 joerg } 3097 1.1 joerg 3098 1.1 joerg static enum CXVisitorResult findFileRefsVisit(void *context, 3099 1.1 joerg CXCursor cursor, CXSourceRange range) { 3100 1.1 joerg if (clang_Range_isNull(range)) 3101 1.1 joerg return CXVisit_Continue; 3102 1.1 joerg 3103 1.1 joerg PrintCursor(cursor, NULL); 3104 1.1 joerg PrintRange(range, ""); 3105 1.1 joerg printf("\n"); 3106 1.1 joerg return CXVisit_Continue; 3107 1.1 joerg } 3108 1.1 joerg 3109 1.1 joerg static int find_file_refs_at(int argc, const char **argv) { 3110 1.1 joerg CXIndex CIdx; 3111 1.1 joerg int errorCode; 3112 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 3113 1.1 joerg int num_unsaved_files = 0; 3114 1.1 joerg enum CXErrorCode Err; 3115 1.1 joerg CXTranslationUnit TU; 3116 1.1 joerg CXCursor Cursor; 3117 1.1 joerg CursorSourceLocation *Locations = 0; 3118 1.1 joerg unsigned NumLocations = 0, Loc; 3119 1.1 joerg unsigned Repeats = 1; 3120 1.1 joerg unsigned I; 3121 1.1 joerg 3122 1.1 joerg /* Count the number of locations. */ 3123 1.1 joerg while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1]) 3124 1.1 joerg ++NumLocations; 3125 1.1 joerg 3126 1.1 joerg /* Parse the locations. */ 3127 1.1 joerg assert(NumLocations > 0 && "Unable to count locations?"); 3128 1.1 joerg Locations = (CursorSourceLocation *)malloc( 3129 1.1 joerg NumLocations * sizeof(CursorSourceLocation)); 3130 1.1 joerg assert(Locations); 3131 1.1 joerg for (Loc = 0; Loc < NumLocations; ++Loc) { 3132 1.1 joerg const char *input = argv[Loc + 1] + strlen("-file-refs-at="); 3133 1.1 joerg if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename, 3134 1.1 joerg &Locations[Loc].line, 3135 1.1 joerg &Locations[Loc].column, 0, 0))) 3136 1.1 joerg return errorCode; 3137 1.1 joerg } 3138 1.1 joerg 3139 1.1 joerg if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files, 3140 1.1 joerg &num_unsaved_files)) 3141 1.1 joerg return -1; 3142 1.1 joerg 3143 1.1 joerg if (getenv("CINDEXTEST_EDITING")) 3144 1.1 joerg Repeats = 5; 3145 1.1 joerg 3146 1.1 joerg /* Parse the translation unit. When we're testing clang_getCursor() after 3147 1.1 joerg reparsing, don't remap unsaved files until the second parse. */ 3148 1.1 joerg CIdx = clang_createIndex(1, 1); 3149 1.1 joerg Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1], 3150 1.1 joerg argv + num_unsaved_files + 1 + NumLocations, 3151 1.1 joerg argc - num_unsaved_files - 2 - NumLocations, 3152 1.1 joerg unsaved_files, 3153 1.1 joerg Repeats > 1? 0 : num_unsaved_files, 3154 1.1 joerg getDefaultParsingOptions(), &TU); 3155 1.1 joerg if (Err != CXError_Success) { 3156 1.1 joerg fprintf(stderr, "unable to parse input\n"); 3157 1.1 joerg describeLibclangFailure(Err); 3158 1.1 joerg clang_disposeTranslationUnit(TU); 3159 1.1 joerg return -1; 3160 1.1 joerg } 3161 1.1 joerg 3162 1.1 joerg if (checkForErrors(TU) != 0) 3163 1.1 joerg return -1; 3164 1.1 joerg 3165 1.1 joerg for (I = 0; I != Repeats; ++I) { 3166 1.1 joerg if (Repeats > 1) { 3167 1.1 joerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, 3168 1.1 joerg clang_defaultReparseOptions(TU)); 3169 1.1 joerg if (Err != CXError_Success) { 3170 1.1 joerg describeLibclangFailure(Err); 3171 1.1 joerg clang_disposeTranslationUnit(TU); 3172 1.1 joerg return 1; 3173 1.1 joerg } 3174 1.1 joerg } 3175 1.1 joerg 3176 1.1 joerg if (checkForErrors(TU) != 0) 3177 1.1 joerg return -1; 3178 1.1 joerg 3179 1.1 joerg for (Loc = 0; Loc < NumLocations; ++Loc) { 3180 1.1 joerg CXFile file = clang_getFile(TU, Locations[Loc].filename); 3181 1.1 joerg if (!file) 3182 1.1 joerg continue; 3183 1.1 joerg 3184 1.1 joerg Cursor = clang_getCursor(TU, 3185 1.1 joerg clang_getLocation(TU, file, Locations[Loc].line, 3186 1.1 joerg Locations[Loc].column)); 3187 1.1 joerg 3188 1.1 joerg if (checkForErrors(TU) != 0) 3189 1.1 joerg return -1; 3190 1.1 joerg 3191 1.1 joerg if (I + 1 == Repeats) { 3192 1.1 joerg CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit }; 3193 1.1 joerg PrintCursor(Cursor, NULL); 3194 1.1 joerg printf("\n"); 3195 1.1 joerg clang_findReferencesInFile(Cursor, file, visitor); 3196 1.1 joerg free(Locations[Loc].filename); 3197 1.1 joerg 3198 1.1 joerg if (checkForErrors(TU) != 0) 3199 1.1 joerg return -1; 3200 1.1 joerg } 3201 1.1 joerg } 3202 1.1 joerg } 3203 1.1 joerg 3204 1.1 joerg PrintDiagnostics(TU); 3205 1.1 joerg clang_disposeTranslationUnit(TU); 3206 1.1 joerg clang_disposeIndex(CIdx); 3207 1.1 joerg free(Locations); 3208 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 3209 1.1 joerg return 0; 3210 1.1 joerg } 3211 1.1 joerg 3212 1.1 joerg static enum CXVisitorResult findFileIncludesVisit(void *context, 3213 1.1 joerg CXCursor cursor, CXSourceRange range) { 3214 1.1 joerg PrintCursor(cursor, NULL); 3215 1.1 joerg PrintRange(range, ""); 3216 1.1 joerg printf("\n"); 3217 1.1 joerg return CXVisit_Continue; 3218 1.1 joerg } 3219 1.1 joerg 3220 1.1 joerg static int find_file_includes_in(int argc, const char **argv) { 3221 1.1 joerg CXIndex CIdx; 3222 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 3223 1.1 joerg int num_unsaved_files = 0; 3224 1.1 joerg enum CXErrorCode Err; 3225 1.1 joerg CXTranslationUnit TU; 3226 1.1 joerg const char **Filenames = 0; 3227 1.1 joerg unsigned NumFilenames = 0; 3228 1.1 joerg unsigned Repeats = 1; 3229 1.1 joerg unsigned I, FI; 3230 1.1 joerg 3231 1.1 joerg /* Count the number of locations. */ 3232 1.1 joerg while (strstr(argv[NumFilenames+1], "-file-includes-in=") == argv[NumFilenames+1]) 3233 1.1 joerg ++NumFilenames; 3234 1.1 joerg 3235 1.1 joerg /* Parse the locations. */ 3236 1.1 joerg assert(NumFilenames > 0 && "Unable to count filenames?"); 3237 1.1 joerg Filenames = (const char **)malloc(NumFilenames * sizeof(const char *)); 3238 1.1 joerg assert(Filenames); 3239 1.1 joerg for (I = 0; I < NumFilenames; ++I) { 3240 1.1 joerg const char *input = argv[I + 1] + strlen("-file-includes-in="); 3241 1.1 joerg /* Copy the file name. */ 3242 1.1 joerg Filenames[I] = input; 3243 1.1 joerg } 3244 1.1 joerg 3245 1.1 joerg if (parse_remapped_files(argc, argv, NumFilenames + 1, &unsaved_files, 3246 1.1 joerg &num_unsaved_files)) 3247 1.1 joerg return -1; 3248 1.1 joerg 3249 1.1 joerg if (getenv("CINDEXTEST_EDITING")) 3250 1.1 joerg Repeats = 2; 3251 1.1 joerg 3252 1.1 joerg /* Parse the translation unit. When we're testing clang_getCursor() after 3253 1.1 joerg reparsing, don't remap unsaved files until the second parse. */ 3254 1.1 joerg CIdx = clang_createIndex(1, 1); 3255 1.1 joerg Err = clang_parseTranslationUnit2( 3256 1.1 joerg CIdx, argv[argc - 1], 3257 1.1 joerg argv + num_unsaved_files + 1 + NumFilenames, 3258 1.1 joerg argc - num_unsaved_files - 2 - NumFilenames, 3259 1.1 joerg unsaved_files, 3260 1.1 joerg Repeats > 1 ? 0 : num_unsaved_files, getDefaultParsingOptions(), &TU); 3261 1.1 joerg 3262 1.1 joerg if (Err != CXError_Success) { 3263 1.1 joerg fprintf(stderr, "unable to parse input\n"); 3264 1.1 joerg describeLibclangFailure(Err); 3265 1.1 joerg clang_disposeTranslationUnit(TU); 3266 1.1 joerg return -1; 3267 1.1 joerg } 3268 1.1 joerg 3269 1.1 joerg if (checkForErrors(TU) != 0) 3270 1.1 joerg return -1; 3271 1.1 joerg 3272 1.1 joerg for (I = 0; I != Repeats; ++I) { 3273 1.1 joerg if (Repeats > 1) { 3274 1.1 joerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, 3275 1.1 joerg clang_defaultReparseOptions(TU)); 3276 1.1 joerg if (Err != CXError_Success) { 3277 1.1 joerg describeLibclangFailure(Err); 3278 1.1 joerg clang_disposeTranslationUnit(TU); 3279 1.1 joerg return 1; 3280 1.1 joerg } 3281 1.1 joerg } 3282 1.1 joerg 3283 1.1 joerg if (checkForErrors(TU) != 0) 3284 1.1 joerg return -1; 3285 1.1 joerg 3286 1.1 joerg for (FI = 0; FI < NumFilenames; ++FI) { 3287 1.1 joerg CXFile file = clang_getFile(TU, Filenames[FI]); 3288 1.1 joerg if (!file) 3289 1.1 joerg continue; 3290 1.1 joerg 3291 1.1 joerg if (checkForErrors(TU) != 0) 3292 1.1 joerg return -1; 3293 1.1 joerg 3294 1.1 joerg if (I + 1 == Repeats) { 3295 1.1 joerg CXCursorAndRangeVisitor visitor = { 0, findFileIncludesVisit }; 3296 1.1 joerg clang_findIncludesInFile(TU, file, visitor); 3297 1.1 joerg 3298 1.1 joerg if (checkForErrors(TU) != 0) 3299 1.1 joerg return -1; 3300 1.1 joerg } 3301 1.1 joerg } 3302 1.1 joerg } 3303 1.1 joerg 3304 1.1 joerg PrintDiagnostics(TU); 3305 1.1 joerg clang_disposeTranslationUnit(TU); 3306 1.1 joerg clang_disposeIndex(CIdx); 3307 1.1 joerg free((void *)Filenames); 3308 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 3309 1.1 joerg return 0; 3310 1.1 joerg } 3311 1.1 joerg 3312 1.1 joerg #define MAX_IMPORTED_ASTFILES 200 3313 1.1 joerg 3314 1.1 joerg typedef struct { 3315 1.1 joerg char **filenames; 3316 1.1 joerg unsigned num_files; 3317 1.1 joerg } ImportedASTFilesData; 3318 1.1 joerg 3319 1.1 joerg static ImportedASTFilesData *importedASTs_create() { 3320 1.1 joerg ImportedASTFilesData *p; 3321 1.1 joerg p = malloc(sizeof(ImportedASTFilesData)); 3322 1.1 joerg assert(p); 3323 1.1 joerg p->filenames = malloc(MAX_IMPORTED_ASTFILES * sizeof(const char *)); 3324 1.1 joerg assert(p->filenames); 3325 1.1 joerg p->num_files = 0; 3326 1.1 joerg return p; 3327 1.1 joerg } 3328 1.1 joerg 3329 1.1 joerg static void importedASTs_dispose(ImportedASTFilesData *p) { 3330 1.1 joerg unsigned i; 3331 1.1 joerg if (!p) 3332 1.1 joerg return; 3333 1.1 joerg 3334 1.1 joerg for (i = 0; i < p->num_files; ++i) 3335 1.1 joerg free(p->filenames[i]); 3336 1.1 joerg free(p->filenames); 3337 1.1 joerg free(p); 3338 1.1 joerg } 3339 1.1 joerg 3340 1.1 joerg static void importedASTS_insert(ImportedASTFilesData *p, const char *file) { 3341 1.1 joerg unsigned i; 3342 1.1 joerg assert(p && file); 3343 1.1 joerg for (i = 0; i < p->num_files; ++i) 3344 1.1 joerg if (strcmp(file, p->filenames[i]) == 0) 3345 1.1 joerg return; 3346 1.1 joerg assert(p->num_files + 1 < MAX_IMPORTED_ASTFILES); 3347 1.1 joerg p->filenames[p->num_files++] = strdup(file); 3348 1.1 joerg } 3349 1.1 joerg 3350 1.1 joerg typedef struct IndexDataStringList_ { 3351 1.1 joerg struct IndexDataStringList_ *next; 3352 1.1 joerg char data[1]; /* Dynamically sized. */ 3353 1.1 joerg } IndexDataStringList; 3354 1.1 joerg 3355 1.1 joerg typedef struct { 3356 1.1 joerg const char *check_prefix; 3357 1.1 joerg int first_check_printed; 3358 1.1 joerg int fail_for_error; 3359 1.1 joerg int abort; 3360 1.1 joerg CXString main_filename; 3361 1.1 joerg ImportedASTFilesData *importedASTs; 3362 1.1 joerg IndexDataStringList *strings; 3363 1.1 joerg CXTranslationUnit TU; 3364 1.1 joerg } IndexData; 3365 1.1 joerg 3366 1.1 joerg static void free_client_data(IndexData *index_data) { 3367 1.1 joerg IndexDataStringList *node = index_data->strings; 3368 1.1 joerg while (node) { 3369 1.1 joerg IndexDataStringList *next = node->next; 3370 1.1 joerg free(node); 3371 1.1 joerg node = next; 3372 1.1 joerg } 3373 1.1 joerg index_data->strings = NULL; 3374 1.1 joerg } 3375 1.1 joerg 3376 1.1 joerg static void printCheck(IndexData *data) { 3377 1.1 joerg if (data->check_prefix) { 3378 1.1 joerg if (data->first_check_printed) { 3379 1.1 joerg printf("// %s-NEXT: ", data->check_prefix); 3380 1.1 joerg } else { 3381 1.1 joerg printf("// %s : ", data->check_prefix); 3382 1.1 joerg data->first_check_printed = 1; 3383 1.1 joerg } 3384 1.1 joerg } 3385 1.1 joerg } 3386 1.1 joerg 3387 1.1 joerg static void printCXIndexFile(CXIdxClientFile file) { 3388 1.1 joerg CXString filename = clang_getFileName((CXFile)file); 3389 1.1 joerg printf("%s", clang_getCString(filename)); 3390 1.1 joerg clang_disposeString(filename); 3391 1.1 joerg } 3392 1.1 joerg 3393 1.1 joerg static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) { 3394 1.1 joerg IndexData *index_data; 3395 1.1 joerg CXString filename; 3396 1.1 joerg const char *cname; 3397 1.1 joerg CXIdxClientFile file; 3398 1.1 joerg unsigned line, column; 3399 1.1 joerg const char *main_filename; 3400 1.1 joerg int isMainFile; 3401 1.1 joerg 3402 1.1 joerg index_data = (IndexData *)client_data; 3403 1.1 joerg clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0); 3404 1.1 joerg if (line == 0) { 3405 1.1 joerg printf("<invalid>"); 3406 1.1 joerg return; 3407 1.1 joerg } 3408 1.1 joerg if (!file) { 3409 1.1 joerg printf("<no idxfile>"); 3410 1.1 joerg return; 3411 1.1 joerg } 3412 1.1 joerg filename = clang_getFileName((CXFile)file); 3413 1.1 joerg cname = clang_getCString(filename); 3414 1.1 joerg main_filename = clang_getCString(index_data->main_filename); 3415 1.1 joerg if (strcmp(cname, main_filename) == 0) 3416 1.1 joerg isMainFile = 1; 3417 1.1 joerg else 3418 1.1 joerg isMainFile = 0; 3419 1.1 joerg clang_disposeString(filename); 3420 1.1 joerg 3421 1.1 joerg if (!isMainFile) { 3422 1.1 joerg printCXIndexFile(file); 3423 1.1 joerg printf(":"); 3424 1.1 joerg } 3425 1.1 joerg printf("%d:%d", line, column); 3426 1.1 joerg } 3427 1.1 joerg 3428 1.1 joerg static unsigned digitCount(unsigned val) { 3429 1.1 joerg unsigned c = 1; 3430 1.1 joerg while (1) { 3431 1.1 joerg if (val < 10) 3432 1.1 joerg return c; 3433 1.1 joerg ++c; 3434 1.1 joerg val /= 10; 3435 1.1 joerg } 3436 1.1 joerg } 3437 1.1 joerg 3438 1.1 joerg static CXIdxClientContainer makeClientContainer(CXClientData *client_data, 3439 1.1 joerg const CXIdxEntityInfo *info, 3440 1.1 joerg CXIdxLoc loc) { 3441 1.1 joerg IndexData *index_data; 3442 1.1 joerg IndexDataStringList *node; 3443 1.1 joerg const char *name; 3444 1.1 joerg char *newStr; 3445 1.1 joerg CXIdxClientFile file; 3446 1.1 joerg unsigned line, column; 3447 1.1 joerg 3448 1.1 joerg name = info->name; 3449 1.1 joerg if (!name) 3450 1.1 joerg name = "<anon-tag>"; 3451 1.1 joerg 3452 1.1 joerg clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0); 3453 1.1 joerg 3454 1.1 joerg node = 3455 1.1 joerg (IndexDataStringList *)malloc(sizeof(IndexDataStringList) + strlen(name) + 3456 1.1 joerg digitCount(line) + digitCount(column) + 2); 3457 1.1 joerg assert(node); 3458 1.1 joerg newStr = node->data; 3459 1.1 joerg sprintf(newStr, "%s:%d:%d", name, line, column); 3460 1.1 joerg 3461 1.1 joerg /* Remember string so it can be freed later. */ 3462 1.1 joerg index_data = (IndexData *)client_data; 3463 1.1 joerg node->next = index_data->strings; 3464 1.1 joerg index_data->strings = node; 3465 1.1 joerg 3466 1.1 joerg return (CXIdxClientContainer)newStr; 3467 1.1 joerg } 3468 1.1 joerg 3469 1.1 joerg static void printCXIndexContainer(const CXIdxContainerInfo *info) { 3470 1.1 joerg CXIdxClientContainer container; 3471 1.1 joerg container = clang_index_getClientContainer(info); 3472 1.1 joerg if (!container) 3473 1.1 joerg printf("[<<NULL>>]"); 3474 1.1 joerg else 3475 1.1 joerg printf("[%s]", (const char *)container); 3476 1.1 joerg } 3477 1.1 joerg 3478 1.1 joerg static const char *getEntityKindString(CXIdxEntityKind kind) { 3479 1.1 joerg switch (kind) { 3480 1.1 joerg case CXIdxEntity_Unexposed: return "<<UNEXPOSED>>"; 3481 1.1 joerg case CXIdxEntity_Typedef: return "typedef"; 3482 1.1 joerg case CXIdxEntity_Function: return "function"; 3483 1.1 joerg case CXIdxEntity_Variable: return "variable"; 3484 1.1 joerg case CXIdxEntity_Field: return "field"; 3485 1.1 joerg case CXIdxEntity_EnumConstant: return "enumerator"; 3486 1.1 joerg case CXIdxEntity_ObjCClass: return "objc-class"; 3487 1.1 joerg case CXIdxEntity_ObjCProtocol: return "objc-protocol"; 3488 1.1 joerg case CXIdxEntity_ObjCCategory: return "objc-category"; 3489 1.1 joerg case CXIdxEntity_ObjCInstanceMethod: return "objc-instance-method"; 3490 1.1 joerg case CXIdxEntity_ObjCClassMethod: return "objc-class-method"; 3491 1.1 joerg case CXIdxEntity_ObjCProperty: return "objc-property"; 3492 1.1 joerg case CXIdxEntity_ObjCIvar: return "objc-ivar"; 3493 1.1 joerg case CXIdxEntity_Enum: return "enum"; 3494 1.1 joerg case CXIdxEntity_Struct: return "struct"; 3495 1.1 joerg case CXIdxEntity_Union: return "union"; 3496 1.1 joerg case CXIdxEntity_CXXClass: return "c++-class"; 3497 1.1 joerg case CXIdxEntity_CXXNamespace: return "namespace"; 3498 1.1 joerg case CXIdxEntity_CXXNamespaceAlias: return "namespace-alias"; 3499 1.1 joerg case CXIdxEntity_CXXStaticVariable: return "c++-static-var"; 3500 1.1 joerg case CXIdxEntity_CXXStaticMethod: return "c++-static-method"; 3501 1.1 joerg case CXIdxEntity_CXXInstanceMethod: return "c++-instance-method"; 3502 1.1 joerg case CXIdxEntity_CXXConstructor: return "constructor"; 3503 1.1 joerg case CXIdxEntity_CXXDestructor: return "destructor"; 3504 1.1 joerg case CXIdxEntity_CXXConversionFunction: return "conversion-func"; 3505 1.1 joerg case CXIdxEntity_CXXTypeAlias: return "type-alias"; 3506 1.1 joerg case CXIdxEntity_CXXInterface: return "c++-__interface"; 3507 1.1 joerg } 3508 1.1 joerg assert(0 && "Garbage entity kind"); 3509 1.1 joerg return 0; 3510 1.1 joerg } 3511 1.1 joerg 3512 1.1 joerg static const char *getEntityTemplateKindString(CXIdxEntityCXXTemplateKind kind) { 3513 1.1 joerg switch (kind) { 3514 1.1 joerg case CXIdxEntity_NonTemplate: return ""; 3515 1.1 joerg case CXIdxEntity_Template: return "-template"; 3516 1.1 joerg case CXIdxEntity_TemplatePartialSpecialization: 3517 1.1 joerg return "-template-partial-spec"; 3518 1.1 joerg case CXIdxEntity_TemplateSpecialization: return "-template-spec"; 3519 1.1 joerg } 3520 1.1 joerg assert(0 && "Garbage entity kind"); 3521 1.1 joerg return 0; 3522 1.1 joerg } 3523 1.1 joerg 3524 1.1 joerg static const char *getEntityLanguageString(CXIdxEntityLanguage kind) { 3525 1.1 joerg switch (kind) { 3526 1.1 joerg case CXIdxEntityLang_None: return "<none>"; 3527 1.1 joerg case CXIdxEntityLang_C: return "C"; 3528 1.1 joerg case CXIdxEntityLang_ObjC: return "ObjC"; 3529 1.1 joerg case CXIdxEntityLang_CXX: return "C++"; 3530 1.1 joerg case CXIdxEntityLang_Swift: return "Swift"; 3531 1.1 joerg } 3532 1.1 joerg assert(0 && "Garbage language kind"); 3533 1.1 joerg return 0; 3534 1.1 joerg } 3535 1.1 joerg 3536 1.1 joerg static void printEntityInfo(const char *cb, 3537 1.1 joerg CXClientData client_data, 3538 1.1 joerg const CXIdxEntityInfo *info) { 3539 1.1 joerg const char *name; 3540 1.1 joerg IndexData *index_data; 3541 1.1 joerg unsigned i; 3542 1.1 joerg index_data = (IndexData *)client_data; 3543 1.1 joerg printCheck(index_data); 3544 1.1 joerg 3545 1.1 joerg if (!info) { 3546 1.1 joerg printf("%s: <<NULL>>", cb); 3547 1.1 joerg return; 3548 1.1 joerg } 3549 1.1 joerg 3550 1.1 joerg name = info->name; 3551 1.1 joerg if (!name) 3552 1.1 joerg name = "<anon-tag>"; 3553 1.1 joerg 3554 1.1 joerg printf("%s: kind: %s%s", cb, getEntityKindString(info->kind), 3555 1.1 joerg getEntityTemplateKindString(info->templateKind)); 3556 1.1 joerg printf(" | name: %s", name); 3557 1.1 joerg printf(" | USR: %s", info->USR); 3558 1.1 joerg printf(" | lang: %s", getEntityLanguageString(info->lang)); 3559 1.1 joerg 3560 1.1 joerg for (i = 0; i != info->numAttributes; ++i) { 3561 1.1 joerg const CXIdxAttrInfo *Attr = info->attributes[i]; 3562 1.1 joerg printf(" <attribute>: "); 3563 1.1 joerg PrintCursor(Attr->cursor, NULL); 3564 1.1 joerg } 3565 1.1 joerg } 3566 1.1 joerg 3567 1.1 joerg static void printBaseClassInfo(CXClientData client_data, 3568 1.1 joerg const CXIdxBaseClassInfo *info) { 3569 1.1 joerg printEntityInfo(" <base>", client_data, info->base); 3570 1.1 joerg printf(" | cursor: "); 3571 1.1 joerg PrintCursor(info->cursor, NULL); 3572 1.1 joerg printf(" | loc: "); 3573 1.1 joerg printCXIndexLoc(info->loc, client_data); 3574 1.1 joerg } 3575 1.1 joerg 3576 1.1 joerg static void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo, 3577 1.1 joerg CXClientData client_data) { 3578 1.1 joerg unsigned i; 3579 1.1 joerg for (i = 0; i < ProtoInfo->numProtocols; ++i) { 3580 1.1 joerg printEntityInfo(" <protocol>", client_data, 3581 1.1 joerg ProtoInfo->protocols[i]->protocol); 3582 1.1 joerg printf(" | cursor: "); 3583 1.1 joerg PrintCursor(ProtoInfo->protocols[i]->cursor, NULL); 3584 1.1 joerg printf(" | loc: "); 3585 1.1 joerg printCXIndexLoc(ProtoInfo->protocols[i]->loc, client_data); 3586 1.1 joerg printf("\n"); 3587 1.1 joerg } 3588 1.1 joerg } 3589 1.1 joerg 3590 1.1 joerg static void printSymbolRole(CXSymbolRole role) { 3591 1.1 joerg if (role & CXSymbolRole_Declaration) 3592 1.1 joerg printf(" decl"); 3593 1.1 joerg if (role & CXSymbolRole_Definition) 3594 1.1 joerg printf(" def"); 3595 1.1 joerg if (role & CXSymbolRole_Reference) 3596 1.1 joerg printf(" ref"); 3597 1.1 joerg if (role & CXSymbolRole_Read) 3598 1.1 joerg printf(" read"); 3599 1.1 joerg if (role & CXSymbolRole_Write) 3600 1.1 joerg printf(" write"); 3601 1.1 joerg if (role & CXSymbolRole_Call) 3602 1.1 joerg printf(" call"); 3603 1.1 joerg if (role & CXSymbolRole_Dynamic) 3604 1.1 joerg printf(" dyn"); 3605 1.1 joerg if (role & CXSymbolRole_AddressOf) 3606 1.1 joerg printf(" addr"); 3607 1.1 joerg if (role & CXSymbolRole_Implicit) 3608 1.1 joerg printf(" implicit"); 3609 1.1 joerg } 3610 1.1 joerg 3611 1.1 joerg static void index_diagnostic(CXClientData client_data, 3612 1.1 joerg CXDiagnosticSet diagSet, void *reserved) { 3613 1.1 joerg CXString str; 3614 1.1 joerg const char *cstr; 3615 1.1 joerg unsigned numDiags, i; 3616 1.1 joerg CXDiagnostic diag; 3617 1.1 joerg IndexData *index_data; 3618 1.1 joerg index_data = (IndexData *)client_data; 3619 1.1 joerg printCheck(index_data); 3620 1.1 joerg 3621 1.1 joerg numDiags = clang_getNumDiagnosticsInSet(diagSet); 3622 1.1 joerg for (i = 0; i != numDiags; ++i) { 3623 1.1 joerg diag = clang_getDiagnosticInSet(diagSet, i); 3624 1.1 joerg str = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions()); 3625 1.1 joerg cstr = clang_getCString(str); 3626 1.1 joerg printf("[diagnostic]: %s\n", cstr); 3627 1.1 joerg clang_disposeString(str); 3628 1.1 joerg 3629 1.1 joerg if (getenv("CINDEXTEST_FAILONERROR") && 3630 1.1 joerg clang_getDiagnosticSeverity(diag) >= CXDiagnostic_Error) { 3631 1.1 joerg index_data->fail_for_error = 1; 3632 1.1 joerg } 3633 1.1 joerg } 3634 1.1 joerg } 3635 1.1 joerg 3636 1.1 joerg static CXIdxClientFile index_enteredMainFile(CXClientData client_data, 3637 1.1 joerg CXFile file, void *reserved) { 3638 1.1 joerg IndexData *index_data; 3639 1.1 joerg 3640 1.1 joerg index_data = (IndexData *)client_data; 3641 1.1 joerg printCheck(index_data); 3642 1.1 joerg 3643 1.1 joerg index_data->main_filename = clang_getFileName(file); 3644 1.1 joerg 3645 1.1 joerg printf("[enteredMainFile]: "); 3646 1.1 joerg printCXIndexFile((CXIdxClientFile)file); 3647 1.1 joerg printf("\n"); 3648 1.1 joerg 3649 1.1 joerg return (CXIdxClientFile)file; 3650 1.1 joerg } 3651 1.1 joerg 3652 1.1 joerg static CXIdxClientFile index_ppIncludedFile(CXClientData client_data, 3653 1.1 joerg const CXIdxIncludedFileInfo *info) { 3654 1.1 joerg IndexData *index_data; 3655 1.1 joerg CXModule Mod; 3656 1.1 joerg index_data = (IndexData *)client_data; 3657 1.1 joerg printCheck(index_data); 3658 1.1 joerg 3659 1.1 joerg printf("[ppIncludedFile]: "); 3660 1.1 joerg printCXIndexFile((CXIdxClientFile)info->file); 3661 1.1 joerg printf(" | name: \"%s\"", info->filename); 3662 1.1 joerg printf(" | hash loc: "); 3663 1.1 joerg printCXIndexLoc(info->hashLoc, client_data); 3664 1.1 joerg printf(" | isImport: %d | isAngled: %d | isModule: %d", 3665 1.1 joerg info->isImport, info->isAngled, info->isModuleImport); 3666 1.1 joerg 3667 1.1 joerg Mod = clang_getModuleForFile(index_data->TU, (CXFile)info->file); 3668 1.1 joerg if (Mod) { 3669 1.1 joerg CXString str = clang_Module_getFullName(Mod); 3670 1.1 joerg const char *cstr = clang_getCString(str); 3671 1.1 joerg printf(" | module: %s", cstr); 3672 1.1 joerg clang_disposeString(str); 3673 1.1 joerg } 3674 1.1 joerg 3675 1.1 joerg printf("\n"); 3676 1.1 joerg 3677 1.1 joerg return (CXIdxClientFile)info->file; 3678 1.1 joerg } 3679 1.1 joerg 3680 1.1 joerg static CXIdxClientFile index_importedASTFile(CXClientData client_data, 3681 1.1 joerg const CXIdxImportedASTFileInfo *info) { 3682 1.1 joerg IndexData *index_data; 3683 1.1 joerg index_data = (IndexData *)client_data; 3684 1.1 joerg printCheck(index_data); 3685 1.1 joerg 3686 1.1 joerg if (index_data->importedASTs) { 3687 1.1 joerg CXString filename = clang_getFileName(info->file); 3688 1.1 joerg importedASTS_insert(index_data->importedASTs, clang_getCString(filename)); 3689 1.1 joerg clang_disposeString(filename); 3690 1.1 joerg } 3691 1.1 joerg 3692 1.1 joerg printf("[importedASTFile]: "); 3693 1.1 joerg printCXIndexFile((CXIdxClientFile)info->file); 3694 1.1 joerg if (info->module) { 3695 1.1 joerg CXString name = clang_Module_getFullName(info->module); 3696 1.1 joerg printf(" | loc: "); 3697 1.1 joerg printCXIndexLoc(info->loc, client_data); 3698 1.1 joerg printf(" | name: \"%s\"", clang_getCString(name)); 3699 1.1 joerg printf(" | isImplicit: %d\n", info->isImplicit); 3700 1.1 joerg clang_disposeString(name); 3701 1.1 joerg } else { 3702 1.1 joerg /* PCH file, the rest are not relevant. */ 3703 1.1 joerg printf("\n"); 3704 1.1 joerg } 3705 1.1 joerg 3706 1.1 joerg return (CXIdxClientFile)info->file; 3707 1.1 joerg } 3708 1.1 joerg 3709 1.1 joerg static CXIdxClientContainer 3710 1.1 joerg index_startedTranslationUnit(CXClientData client_data, void *reserved) { 3711 1.1 joerg IndexData *index_data; 3712 1.1 joerg index_data = (IndexData *)client_data; 3713 1.1 joerg printCheck(index_data); 3714 1.1 joerg 3715 1.1 joerg printf("[startedTranslationUnit]\n"); 3716 1.1 joerg return (CXIdxClientContainer)"TU"; 3717 1.1 joerg } 3718 1.1 joerg 3719 1.1 joerg static void index_indexDeclaration(CXClientData client_data, 3720 1.1 joerg const CXIdxDeclInfo *info) { 3721 1.1 joerg IndexData *index_data; 3722 1.1 joerg const CXIdxObjCCategoryDeclInfo *CatInfo; 3723 1.1 joerg const CXIdxObjCInterfaceDeclInfo *InterInfo; 3724 1.1 joerg const CXIdxObjCProtocolRefListInfo *ProtoInfo; 3725 1.1 joerg const CXIdxObjCPropertyDeclInfo *PropInfo; 3726 1.1 joerg const CXIdxCXXClassDeclInfo *CXXClassInfo; 3727 1.1 joerg unsigned i; 3728 1.1 joerg index_data = (IndexData *)client_data; 3729 1.1 joerg 3730 1.1 joerg printEntityInfo("[indexDeclaration]", client_data, info->entityInfo); 3731 1.1 joerg printf(" | cursor: "); 3732 1.1 joerg PrintCursor(info->cursor, NULL); 3733 1.1 joerg printf(" | loc: "); 3734 1.1 joerg printCXIndexLoc(info->loc, client_data); 3735 1.1 joerg printf(" | semantic-container: "); 3736 1.1 joerg printCXIndexContainer(info->semanticContainer); 3737 1.1 joerg printf(" | lexical-container: "); 3738 1.1 joerg printCXIndexContainer(info->lexicalContainer); 3739 1.1 joerg printf(" | isRedecl: %d", info->isRedeclaration); 3740 1.1 joerg printf(" | isDef: %d", info->isDefinition); 3741 1.1 joerg if (info->flags & CXIdxDeclFlag_Skipped) { 3742 1.1 joerg assert(!info->isContainer); 3743 1.1 joerg printf(" | isContainer: skipped"); 3744 1.1 joerg } else { 3745 1.1 joerg printf(" | isContainer: %d", info->isContainer); 3746 1.1 joerg } 3747 1.1 joerg printf(" | isImplicit: %d\n", info->isImplicit); 3748 1.1 joerg 3749 1.1 joerg for (i = 0; i != info->numAttributes; ++i) { 3750 1.1 joerg const CXIdxAttrInfo *Attr = info->attributes[i]; 3751 1.1 joerg printf(" <attribute>: "); 3752 1.1 joerg PrintCursor(Attr->cursor, NULL); 3753 1.1 joerg printf("\n"); 3754 1.1 joerg } 3755 1.1 joerg 3756 1.1 joerg if (clang_index_isEntityObjCContainerKind(info->entityInfo->kind)) { 3757 1.1 joerg const char *kindName = 0; 3758 1.1 joerg CXIdxObjCContainerKind K = clang_index_getObjCContainerDeclInfo(info)->kind; 3759 1.1 joerg switch (K) { 3760 1.1 joerg case CXIdxObjCContainer_ForwardRef: 3761 1.1 joerg kindName = "forward-ref"; break; 3762 1.1 joerg case CXIdxObjCContainer_Interface: 3763 1.1 joerg kindName = "interface"; break; 3764 1.1 joerg case CXIdxObjCContainer_Implementation: 3765 1.1 joerg kindName = "implementation"; break; 3766 1.1 joerg } 3767 1.1 joerg printCheck(index_data); 3768 1.1 joerg printf(" <ObjCContainerInfo>: kind: %s\n", kindName); 3769 1.1 joerg } 3770 1.1 joerg 3771 1.1 joerg if ((CatInfo = clang_index_getObjCCategoryDeclInfo(info))) { 3772 1.1 joerg printEntityInfo(" <ObjCCategoryInfo>: class", client_data, 3773 1.1 joerg CatInfo->objcClass); 3774 1.1 joerg printf(" | cursor: "); 3775 1.1 joerg PrintCursor(CatInfo->classCursor, NULL); 3776 1.1 joerg printf(" | loc: "); 3777 1.1 joerg printCXIndexLoc(CatInfo->classLoc, client_data); 3778 1.1 joerg printf("\n"); 3779 1.1 joerg } 3780 1.1 joerg 3781 1.1 joerg if ((InterInfo = clang_index_getObjCInterfaceDeclInfo(info))) { 3782 1.1 joerg if (InterInfo->superInfo) { 3783 1.1 joerg printBaseClassInfo(client_data, InterInfo->superInfo); 3784 1.1 joerg printf("\n"); 3785 1.1 joerg } 3786 1.1 joerg } 3787 1.1 joerg 3788 1.1 joerg if ((ProtoInfo = clang_index_getObjCProtocolRefListInfo(info))) { 3789 1.1 joerg printProtocolList(ProtoInfo, client_data); 3790 1.1 joerg } 3791 1.1 joerg 3792 1.1 joerg if ((PropInfo = clang_index_getObjCPropertyDeclInfo(info))) { 3793 1.1 joerg if (PropInfo->getter) { 3794 1.1 joerg printEntityInfo(" <getter>", client_data, PropInfo->getter); 3795 1.1 joerg printf("\n"); 3796 1.1 joerg } 3797 1.1 joerg if (PropInfo->setter) { 3798 1.1 joerg printEntityInfo(" <setter>", client_data, PropInfo->setter); 3799 1.1 joerg printf("\n"); 3800 1.1 joerg } 3801 1.1 joerg } 3802 1.1 joerg 3803 1.1 joerg if ((CXXClassInfo = clang_index_getCXXClassDeclInfo(info))) { 3804 1.1 joerg for (i = 0; i != CXXClassInfo->numBases; ++i) { 3805 1.1 joerg printBaseClassInfo(client_data, CXXClassInfo->bases[i]); 3806 1.1 joerg printf("\n"); 3807 1.1 joerg } 3808 1.1 joerg } 3809 1.1 joerg 3810 1.1 joerg if (info->declAsContainer) 3811 1.1 joerg clang_index_setClientContainer( 3812 1.1 joerg info->declAsContainer, 3813 1.1 joerg makeClientContainer(client_data, info->entityInfo, info->loc)); 3814 1.1 joerg } 3815 1.1 joerg 3816 1.1 joerg static void index_indexEntityReference(CXClientData client_data, 3817 1.1 joerg const CXIdxEntityRefInfo *info) { 3818 1.1 joerg printEntityInfo("[indexEntityReference]", client_data, 3819 1.1 joerg info->referencedEntity); 3820 1.1 joerg printf(" | cursor: "); 3821 1.1 joerg PrintCursor(info->cursor, NULL); 3822 1.1 joerg printf(" | loc: "); 3823 1.1 joerg printCXIndexLoc(info->loc, client_data); 3824 1.1 joerg printEntityInfo(" | <parent>:", client_data, info->parentEntity); 3825 1.1 joerg printf(" | container: "); 3826 1.1 joerg printCXIndexContainer(info->container); 3827 1.1 joerg printf(" | refkind: "); 3828 1.1 joerg switch (info->kind) { 3829 1.1 joerg case CXIdxEntityRef_Direct: printf("direct"); break; 3830 1.1 joerg case CXIdxEntityRef_Implicit: printf("implicit"); break; 3831 1.1 joerg } 3832 1.1 joerg printf(" | role:"); 3833 1.1 joerg printSymbolRole(info->role); 3834 1.1 joerg printf("\n"); 3835 1.1 joerg } 3836 1.1 joerg 3837 1.1 joerg static int index_abortQuery(CXClientData client_data, void *reserved) { 3838 1.1 joerg IndexData *index_data; 3839 1.1 joerg index_data = (IndexData *)client_data; 3840 1.1 joerg return index_data->abort; 3841 1.1 joerg } 3842 1.1 joerg 3843 1.1 joerg static IndexerCallbacks IndexCB = { 3844 1.1 joerg index_abortQuery, 3845 1.1 joerg index_diagnostic, 3846 1.1 joerg index_enteredMainFile, 3847 1.1 joerg index_ppIncludedFile, 3848 1.1 joerg index_importedASTFile, 3849 1.1 joerg index_startedTranslationUnit, 3850 1.1 joerg index_indexDeclaration, 3851 1.1 joerg index_indexEntityReference 3852 1.1 joerg }; 3853 1.1 joerg 3854 1.1 joerg static unsigned getIndexOptions(void) { 3855 1.1 joerg unsigned index_opts; 3856 1.1 joerg index_opts = 0; 3857 1.1 joerg if (getenv("CINDEXTEST_SUPPRESSREFS")) 3858 1.1 joerg index_opts |= CXIndexOpt_SuppressRedundantRefs; 3859 1.1 joerg if (getenv("CINDEXTEST_INDEXLOCALSYMBOLS")) 3860 1.1 joerg index_opts |= CXIndexOpt_IndexFunctionLocalSymbols; 3861 1.1 joerg if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES")) 3862 1.1 joerg index_opts |= CXIndexOpt_SkipParsedBodiesInSession; 3863 1.1 joerg if (getenv("CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS")) 3864 1.1 joerg index_opts |= CXIndexOpt_IndexImplicitTemplateInstantiations; 3865 1.1 joerg 3866 1.1 joerg return index_opts; 3867 1.1 joerg } 3868 1.1 joerg 3869 1.1 joerg static int index_compile_args(int num_args, const char **args, 3870 1.1 joerg CXIndexAction idxAction, 3871 1.1 joerg ImportedASTFilesData *importedASTs, 3872 1.1 joerg const char *check_prefix) { 3873 1.1 joerg IndexData index_data; 3874 1.1 joerg unsigned index_opts; 3875 1.1 joerg int result; 3876 1.1 joerg 3877 1.1 joerg if (num_args == 0) { 3878 1.1 joerg fprintf(stderr, "no compiler arguments\n"); 3879 1.1 joerg return -1; 3880 1.1 joerg } 3881 1.1 joerg 3882 1.1 joerg index_data.check_prefix = check_prefix; 3883 1.1 joerg index_data.first_check_printed = 0; 3884 1.1 joerg index_data.fail_for_error = 0; 3885 1.1 joerg index_data.abort = 0; 3886 1.1 joerg index_data.main_filename = createCXString(""); 3887 1.1 joerg index_data.importedASTs = importedASTs; 3888 1.1 joerg index_data.strings = NULL; 3889 1.1 joerg index_data.TU = NULL; 3890 1.1 joerg 3891 1.1 joerg index_opts = getIndexOptions(); 3892 1.1 joerg result = clang_indexSourceFile(idxAction, &index_data, 3893 1.1 joerg &IndexCB,sizeof(IndexCB), index_opts, 3894 1.1 joerg 0, args, num_args, 0, 0, 0, 3895 1.1 joerg getDefaultParsingOptions()); 3896 1.1 joerg if (result != CXError_Success) 3897 1.1 joerg describeLibclangFailure(result); 3898 1.1 joerg 3899 1.1 joerg if (index_data.fail_for_error) 3900 1.1 joerg result = -1; 3901 1.1 joerg 3902 1.1 joerg clang_disposeString(index_data.main_filename); 3903 1.1 joerg free_client_data(&index_data); 3904 1.1 joerg return result; 3905 1.1 joerg } 3906 1.1 joerg 3907 1.1 joerg static int index_ast_file(const char *ast_file, 3908 1.1 joerg CXIndex Idx, 3909 1.1 joerg CXIndexAction idxAction, 3910 1.1 joerg ImportedASTFilesData *importedASTs, 3911 1.1 joerg const char *check_prefix) { 3912 1.1 joerg CXTranslationUnit TU; 3913 1.1 joerg IndexData index_data; 3914 1.1 joerg unsigned index_opts; 3915 1.1 joerg int result; 3916 1.1 joerg 3917 1.1 joerg if (!CreateTranslationUnit(Idx, ast_file, &TU)) 3918 1.1 joerg return -1; 3919 1.1 joerg 3920 1.1 joerg index_data.check_prefix = check_prefix; 3921 1.1 joerg index_data.first_check_printed = 0; 3922 1.1 joerg index_data.fail_for_error = 0; 3923 1.1 joerg index_data.abort = 0; 3924 1.1 joerg index_data.main_filename = createCXString(""); 3925 1.1 joerg index_data.importedASTs = importedASTs; 3926 1.1 joerg index_data.strings = NULL; 3927 1.1 joerg index_data.TU = TU; 3928 1.1 joerg 3929 1.1 joerg index_opts = getIndexOptions(); 3930 1.1 joerg result = clang_indexTranslationUnit(idxAction, &index_data, 3931 1.1 joerg &IndexCB,sizeof(IndexCB), 3932 1.1 joerg index_opts, TU); 3933 1.1 joerg if (index_data.fail_for_error) 3934 1.1 joerg result = -1; 3935 1.1 joerg 3936 1.1 joerg clang_disposeTranslationUnit(TU); 3937 1.1 joerg clang_disposeString(index_data.main_filename); 3938 1.1 joerg free_client_data(&index_data); 3939 1.1 joerg return result; 3940 1.1 joerg } 3941 1.1 joerg 3942 1.1 joerg static int index_file(int argc, const char **argv, int full) { 3943 1.1 joerg const char *check_prefix; 3944 1.1 joerg CXIndex Idx; 3945 1.1 joerg CXIndexAction idxAction; 3946 1.1 joerg ImportedASTFilesData *importedASTs; 3947 1.1 joerg int result; 3948 1.1 joerg 3949 1.1 joerg check_prefix = 0; 3950 1.1 joerg if (argc > 0) { 3951 1.1 joerg if (strstr(argv[0], "-check-prefix=") == argv[0]) { 3952 1.1 joerg check_prefix = argv[0] + strlen("-check-prefix="); 3953 1.1 joerg ++argv; 3954 1.1 joerg --argc; 3955 1.1 joerg } 3956 1.1 joerg } 3957 1.1 joerg 3958 1.1 joerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1, 3959 1.1 joerg /* displayDiagnostics=*/1))) { 3960 1.1 joerg fprintf(stderr, "Could not create Index\n"); 3961 1.1 joerg return 1; 3962 1.1 joerg } 3963 1.1 joerg idxAction = clang_IndexAction_create(Idx); 3964 1.1 joerg importedASTs = 0; 3965 1.1 joerg if (full) 3966 1.1 joerg importedASTs = importedASTs_create(); 3967 1.1 joerg 3968 1.1 joerg result = index_compile_args(argc, argv, idxAction, importedASTs, check_prefix); 3969 1.1 joerg if (result != 0) 3970 1.1 joerg goto finished; 3971 1.1 joerg 3972 1.1 joerg if (full) { 3973 1.1 joerg unsigned i; 3974 1.1 joerg for (i = 0; i < importedASTs->num_files && result == 0; ++i) { 3975 1.1 joerg result = index_ast_file(importedASTs->filenames[i], Idx, idxAction, 3976 1.1 joerg importedASTs, check_prefix); 3977 1.1 joerg } 3978 1.1 joerg } 3979 1.1 joerg 3980 1.1 joerg finished: 3981 1.1 joerg importedASTs_dispose(importedASTs); 3982 1.1 joerg clang_IndexAction_dispose(idxAction); 3983 1.1 joerg clang_disposeIndex(Idx); 3984 1.1 joerg return result; 3985 1.1 joerg } 3986 1.1 joerg 3987 1.1 joerg static int index_tu(int argc, const char **argv) { 3988 1.1 joerg const char *check_prefix; 3989 1.1 joerg CXIndex Idx; 3990 1.1 joerg CXIndexAction idxAction; 3991 1.1 joerg int result; 3992 1.1 joerg 3993 1.1 joerg check_prefix = 0; 3994 1.1 joerg if (argc > 0) { 3995 1.1 joerg if (strstr(argv[0], "-check-prefix=") == argv[0]) { 3996 1.1 joerg check_prefix = argv[0] + strlen("-check-prefix="); 3997 1.1 joerg ++argv; 3998 1.1 joerg --argc; 3999 1.1 joerg } 4000 1.1 joerg } 4001 1.1 joerg 4002 1.1 joerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1, 4003 1.1 joerg /* displayDiagnostics=*/1))) { 4004 1.1 joerg fprintf(stderr, "Could not create Index\n"); 4005 1.1 joerg return 1; 4006 1.1 joerg } 4007 1.1 joerg idxAction = clang_IndexAction_create(Idx); 4008 1.1 joerg 4009 1.1 joerg result = index_ast_file(argv[0], Idx, idxAction, 4010 1.1 joerg /*importedASTs=*/0, check_prefix); 4011 1.1 joerg 4012 1.1 joerg clang_IndexAction_dispose(idxAction); 4013 1.1 joerg clang_disposeIndex(Idx); 4014 1.1 joerg return result; 4015 1.1 joerg } 4016 1.1 joerg 4017 1.1 joerg static int index_compile_db(int argc, const char **argv) { 4018 1.1 joerg const char *check_prefix; 4019 1.1 joerg CXIndex Idx; 4020 1.1 joerg CXIndexAction idxAction; 4021 1.1 joerg int errorCode = 0; 4022 1.1 joerg 4023 1.1 joerg check_prefix = 0; 4024 1.1 joerg if (argc > 0) { 4025 1.1 joerg if (strstr(argv[0], "-check-prefix=") == argv[0]) { 4026 1.1 joerg check_prefix = argv[0] + strlen("-check-prefix="); 4027 1.1 joerg ++argv; 4028 1.1 joerg --argc; 4029 1.1 joerg } 4030 1.1 joerg } 4031 1.1 joerg 4032 1.1 joerg if (argc == 0) { 4033 1.1 joerg fprintf(stderr, "no compilation database\n"); 4034 1.1 joerg return -1; 4035 1.1 joerg } 4036 1.1 joerg 4037 1.1 joerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1, 4038 1.1 joerg /* displayDiagnostics=*/1))) { 4039 1.1 joerg fprintf(stderr, "Could not create Index\n"); 4040 1.1 joerg return 1; 4041 1.1 joerg } 4042 1.1 joerg idxAction = clang_IndexAction_create(Idx); 4043 1.1 joerg 4044 1.1 joerg { 4045 1.1 joerg const char *database = argv[0]; 4046 1.1 joerg CXCompilationDatabase db = 0; 4047 1.1 joerg CXCompileCommands CCmds = 0; 4048 1.1 joerg CXCompileCommand CCmd; 4049 1.1 joerg CXCompilationDatabase_Error ec; 4050 1.1 joerg CXString wd; 4051 1.1 joerg #define MAX_COMPILE_ARGS 512 4052 1.1 joerg CXString cxargs[MAX_COMPILE_ARGS]; 4053 1.1 joerg const char *args[MAX_COMPILE_ARGS]; 4054 1.1 joerg char *tmp; 4055 1.1 joerg unsigned len; 4056 1.1 joerg char *buildDir; 4057 1.1 joerg int i, a, numCmds, numArgs; 4058 1.1 joerg 4059 1.1 joerg len = strlen(database); 4060 1.1 joerg tmp = (char *) malloc(len+1); 4061 1.1 joerg assert(tmp); 4062 1.1 joerg memcpy(tmp, database, len+1); 4063 1.1 joerg buildDir = dirname(tmp); 4064 1.1 joerg 4065 1.1 joerg db = clang_CompilationDatabase_fromDirectory(buildDir, &ec); 4066 1.1 joerg 4067 1.1 joerg if (db) { 4068 1.1 joerg 4069 1.1 joerg if (ec!=CXCompilationDatabase_NoError) { 4070 1.1 joerg printf("unexpected error %d code while loading compilation database\n", ec); 4071 1.1 joerg errorCode = -1; 4072 1.1 joerg goto cdb_end; 4073 1.1 joerg } 4074 1.1 joerg 4075 1.1 joerg if (chdir(buildDir) != 0) { 4076 1.1 joerg printf("Could not chdir to %s\n", buildDir); 4077 1.1 joerg errorCode = -1; 4078 1.1 joerg goto cdb_end; 4079 1.1 joerg } 4080 1.1 joerg 4081 1.1 joerg CCmds = clang_CompilationDatabase_getAllCompileCommands(db); 4082 1.1 joerg if (!CCmds) { 4083 1.1 joerg printf("compilation db is empty\n"); 4084 1.1 joerg errorCode = -1; 4085 1.1 joerg goto cdb_end; 4086 1.1 joerg } 4087 1.1 joerg 4088 1.1 joerg numCmds = clang_CompileCommands_getSize(CCmds); 4089 1.1 joerg 4090 1.1 joerg if (numCmds==0) { 4091 1.1 joerg fprintf(stderr, "should not get an empty compileCommand set\n"); 4092 1.1 joerg errorCode = -1; 4093 1.1 joerg goto cdb_end; 4094 1.1 joerg } 4095 1.1 joerg 4096 1.1 joerg for (i=0; i<numCmds && errorCode == 0; ++i) { 4097 1.1 joerg CCmd = clang_CompileCommands_getCommand(CCmds, i); 4098 1.1 joerg 4099 1.1 joerg wd = clang_CompileCommand_getDirectory(CCmd); 4100 1.1 joerg if (chdir(clang_getCString(wd)) != 0) { 4101 1.1 joerg printf("Could not chdir to %s\n", clang_getCString(wd)); 4102 1.1 joerg errorCode = -1; 4103 1.1 joerg goto cdb_end; 4104 1.1 joerg } 4105 1.1 joerg clang_disposeString(wd); 4106 1.1 joerg 4107 1.1 joerg numArgs = clang_CompileCommand_getNumArgs(CCmd); 4108 1.1 joerg if (numArgs > MAX_COMPILE_ARGS){ 4109 1.1 joerg fprintf(stderr, "got more compile arguments than maximum\n"); 4110 1.1 joerg errorCode = -1; 4111 1.1 joerg goto cdb_end; 4112 1.1 joerg } 4113 1.1 joerg for (a=0; a<numArgs; ++a) { 4114 1.1 joerg cxargs[a] = clang_CompileCommand_getArg(CCmd, a); 4115 1.1 joerg args[a] = clang_getCString(cxargs[a]); 4116 1.1 joerg } 4117 1.1 joerg 4118 1.1 joerg errorCode = index_compile_args(numArgs, args, idxAction, 4119 1.1 joerg /*importedASTs=*/0, check_prefix); 4120 1.1 joerg 4121 1.1 joerg for (a=0; a<numArgs; ++a) 4122 1.1 joerg clang_disposeString(cxargs[a]); 4123 1.1 joerg } 4124 1.1 joerg } else { 4125 1.1 joerg printf("database loading failed with error code %d.\n", ec); 4126 1.1 joerg errorCode = -1; 4127 1.1 joerg } 4128 1.1 joerg 4129 1.1 joerg cdb_end: 4130 1.1 joerg clang_CompileCommands_dispose(CCmds); 4131 1.1 joerg clang_CompilationDatabase_dispose(db); 4132 1.1 joerg free(tmp); 4133 1.1 joerg 4134 1.1 joerg } 4135 1.1 joerg 4136 1.1 joerg clang_IndexAction_dispose(idxAction); 4137 1.1 joerg clang_disposeIndex(Idx); 4138 1.1 joerg return errorCode; 4139 1.1 joerg } 4140 1.1 joerg 4141 1.1 joerg int perform_token_annotation(int argc, const char **argv) { 4142 1.1 joerg const char *input = argv[1]; 4143 1.1 joerg char *filename = 0; 4144 1.1 joerg unsigned line, second_line; 4145 1.1 joerg unsigned column, second_column; 4146 1.1 joerg CXIndex CIdx; 4147 1.1 joerg CXTranslationUnit TU = 0; 4148 1.1 joerg int errorCode; 4149 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 4150 1.1 joerg int num_unsaved_files = 0; 4151 1.1 joerg CXToken *tokens; 4152 1.1 joerg unsigned num_tokens; 4153 1.1 joerg CXSourceRange range; 4154 1.1 joerg CXSourceLocation startLoc, endLoc; 4155 1.1 joerg CXFile file = 0; 4156 1.1 joerg CXCursor *cursors = 0; 4157 1.1 joerg CXSourceRangeList *skipped_ranges = 0; 4158 1.1 joerg enum CXErrorCode Err; 4159 1.1 joerg unsigned i; 4160 1.1 joerg 4161 1.1 joerg input += strlen("-test-annotate-tokens="); 4162 1.1 joerg if ((errorCode = parse_file_line_column(input, &filename, &line, &column, 4163 1.1 joerg &second_line, &second_column))) 4164 1.1 joerg return errorCode; 4165 1.1 joerg 4166 1.1 joerg if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) { 4167 1.1 joerg free(filename); 4168 1.1 joerg return -1; 4169 1.1 joerg } 4170 1.1 joerg 4171 1.1 joerg CIdx = clang_createIndex(0, 1); 4172 1.1 joerg Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1], 4173 1.1 joerg argv + num_unsaved_files + 2, 4174 1.1 joerg argc - num_unsaved_files - 3, 4175 1.1 joerg unsaved_files, 4176 1.1 joerg num_unsaved_files, 4177 1.1 joerg getDefaultParsingOptions(), &TU); 4178 1.1 joerg if (Err != CXError_Success) { 4179 1.1 joerg fprintf(stderr, "unable to parse input\n"); 4180 1.1 joerg describeLibclangFailure(Err); 4181 1.1 joerg clang_disposeIndex(CIdx); 4182 1.1 joerg free(filename); 4183 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 4184 1.1 joerg return -1; 4185 1.1 joerg } 4186 1.1 joerg errorCode = 0; 4187 1.1 joerg 4188 1.1 joerg if (checkForErrors(TU) != 0) { 4189 1.1 joerg errorCode = -1; 4190 1.1 joerg goto teardown; 4191 1.1 joerg } 4192 1.1 joerg 4193 1.1 joerg if (getenv("CINDEXTEST_EDITING")) { 4194 1.1 joerg for (i = 0; i < 5; ++i) { 4195 1.1 joerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files, 4196 1.1 joerg clang_defaultReparseOptions(TU)); 4197 1.1 joerg if (Err != CXError_Success) { 4198 1.1 joerg fprintf(stderr, "Unable to reparse translation unit!\n"); 4199 1.1 joerg describeLibclangFailure(Err); 4200 1.1 joerg errorCode = -1; 4201 1.1 joerg goto teardown; 4202 1.1 joerg } 4203 1.1 joerg } 4204 1.1 joerg } 4205 1.1 joerg 4206 1.1 joerg if (checkForErrors(TU) != 0) { 4207 1.1 joerg errorCode = -1; 4208 1.1 joerg goto teardown; 4209 1.1 joerg } 4210 1.1 joerg 4211 1.1 joerg file = clang_getFile(TU, filename); 4212 1.1 joerg if (!file) { 4213 1.1 joerg fprintf(stderr, "file %s is not in this translation unit\n", filename); 4214 1.1 joerg errorCode = -1; 4215 1.1 joerg goto teardown; 4216 1.1 joerg } 4217 1.1 joerg 4218 1.1 joerg startLoc = clang_getLocation(TU, file, line, column); 4219 1.1 joerg if (clang_equalLocations(clang_getNullLocation(), startLoc)) { 4220 1.1 joerg fprintf(stderr, "invalid source location %s:%d:%d\n", filename, line, 4221 1.1 joerg column); 4222 1.1 joerg errorCode = -1; 4223 1.1 joerg goto teardown; 4224 1.1 joerg } 4225 1.1 joerg 4226 1.1 joerg endLoc = clang_getLocation(TU, file, second_line, second_column); 4227 1.1 joerg if (clang_equalLocations(clang_getNullLocation(), endLoc)) { 4228 1.1 joerg fprintf(stderr, "invalid source location %s:%d:%d\n", filename, 4229 1.1 joerg second_line, second_column); 4230 1.1 joerg errorCode = -1; 4231 1.1 joerg goto teardown; 4232 1.1 joerg } 4233 1.1 joerg 4234 1.1 joerg range = clang_getRange(startLoc, endLoc); 4235 1.1 joerg clang_tokenize(TU, range, &tokens, &num_tokens); 4236 1.1 joerg 4237 1.1 joerg if (checkForErrors(TU) != 0) { 4238 1.1 joerg errorCode = -1; 4239 1.1 joerg goto teardown; 4240 1.1 joerg } 4241 1.1 joerg 4242 1.1 joerg cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor)); 4243 1.1 joerg assert(cursors); 4244 1.1 joerg clang_annotateTokens(TU, tokens, num_tokens, cursors); 4245 1.1 joerg 4246 1.1 joerg if (checkForErrors(TU) != 0) { 4247 1.1 joerg errorCode = -1; 4248 1.1 joerg goto teardown; 4249 1.1 joerg } 4250 1.1 joerg 4251 1.1 joerg skipped_ranges = clang_getSkippedRanges(TU, file); 4252 1.1 joerg for (i = 0; i != skipped_ranges->count; ++i) { 4253 1.1 joerg unsigned start_line, start_column, end_line, end_column; 4254 1.1 joerg clang_getSpellingLocation(clang_getRangeStart(skipped_ranges->ranges[i]), 4255 1.1 joerg 0, &start_line, &start_column, 0); 4256 1.1 joerg clang_getSpellingLocation(clang_getRangeEnd(skipped_ranges->ranges[i]), 4257 1.1 joerg 0, &end_line, &end_column, 0); 4258 1.1 joerg printf("Skipping: "); 4259 1.1 joerg PrintExtent(stdout, start_line, start_column, end_line, end_column); 4260 1.1 joerg printf("\n"); 4261 1.1 joerg } 4262 1.1 joerg clang_disposeSourceRangeList(skipped_ranges); 4263 1.1 joerg 4264 1.1 joerg for (i = 0; i != num_tokens; ++i) { 4265 1.1 joerg const char *kind = "<unknown>"; 4266 1.1 joerg CXString spelling = clang_getTokenSpelling(TU, tokens[i]); 4267 1.1 joerg CXSourceRange extent = clang_getTokenExtent(TU, tokens[i]); 4268 1.1 joerg unsigned start_line, start_column, end_line, end_column; 4269 1.1 joerg 4270 1.1 joerg switch (clang_getTokenKind(tokens[i])) { 4271 1.1 joerg case CXToken_Punctuation: kind = "Punctuation"; break; 4272 1.1 joerg case CXToken_Keyword: kind = "Keyword"; break; 4273 1.1 joerg case CXToken_Identifier: kind = "Identifier"; break; 4274 1.1 joerg case CXToken_Literal: kind = "Literal"; break; 4275 1.1 joerg case CXToken_Comment: kind = "Comment"; break; 4276 1.1 joerg } 4277 1.1 joerg clang_getSpellingLocation(clang_getRangeStart(extent), 4278 1.1 joerg 0, &start_line, &start_column, 0); 4279 1.1 joerg clang_getSpellingLocation(clang_getRangeEnd(extent), 4280 1.1 joerg 0, &end_line, &end_column, 0); 4281 1.1 joerg printf("%s: \"%s\" ", kind, clang_getCString(spelling)); 4282 1.1 joerg clang_disposeString(spelling); 4283 1.1 joerg PrintExtent(stdout, start_line, start_column, end_line, end_column); 4284 1.1 joerg if (!clang_isInvalid(cursors[i].kind)) { 4285 1.1 joerg printf(" "); 4286 1.1 joerg PrintCursor(cursors[i], NULL); 4287 1.1 joerg } 4288 1.1 joerg printf("\n"); 4289 1.1 joerg } 4290 1.1 joerg free(cursors); 4291 1.1 joerg clang_disposeTokens(TU, tokens, num_tokens); 4292 1.1 joerg 4293 1.1 joerg teardown: 4294 1.1 joerg PrintDiagnostics(TU); 4295 1.1 joerg clang_disposeTranslationUnit(TU); 4296 1.1 joerg clang_disposeIndex(CIdx); 4297 1.1 joerg free(filename); 4298 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 4299 1.1 joerg return errorCode; 4300 1.1 joerg } 4301 1.1 joerg 4302 1.1 joerg static int 4303 1.1 joerg perform_test_compilation_db(const char *database, int argc, const char **argv) { 4304 1.1 joerg CXCompilationDatabase db; 4305 1.1 joerg CXCompileCommands CCmds; 4306 1.1 joerg CXCompileCommand CCmd; 4307 1.1 joerg CXCompilationDatabase_Error ec; 4308 1.1 joerg CXString wd; 4309 1.1 joerg CXString arg; 4310 1.1 joerg int errorCode = 0; 4311 1.1 joerg char *tmp; 4312 1.1 joerg unsigned len; 4313 1.1 joerg char *buildDir; 4314 1.1 joerg int i, j, a, numCmds, numArgs; 4315 1.1 joerg 4316 1.1 joerg len = strlen(database); 4317 1.1 joerg tmp = (char *) malloc(len+1); 4318 1.1 joerg assert(tmp); 4319 1.1 joerg memcpy(tmp, database, len+1); 4320 1.1 joerg buildDir = dirname(tmp); 4321 1.1 joerg 4322 1.1 joerg db = clang_CompilationDatabase_fromDirectory(buildDir, &ec); 4323 1.1 joerg 4324 1.1 joerg if (db) { 4325 1.1 joerg 4326 1.1 joerg if (ec!=CXCompilationDatabase_NoError) { 4327 1.1 joerg printf("unexpected error %d code while loading compilation database\n", ec); 4328 1.1 joerg errorCode = -1; 4329 1.1 joerg goto cdb_end; 4330 1.1 joerg } 4331 1.1 joerg 4332 1.1 joerg for (i=0; i<argc && errorCode==0; ) { 4333 1.1 joerg if (strcmp(argv[i],"lookup")==0){ 4334 1.1 joerg CCmds = clang_CompilationDatabase_getCompileCommands(db, argv[i+1]); 4335 1.1 joerg 4336 1.1 joerg if (!CCmds) { 4337 1.1 joerg printf("file %s not found in compilation db\n", argv[i+1]); 4338 1.1 joerg errorCode = -1; 4339 1.1 joerg break; 4340 1.1 joerg } 4341 1.1 joerg 4342 1.1 joerg numCmds = clang_CompileCommands_getSize(CCmds); 4343 1.1 joerg 4344 1.1 joerg if (numCmds==0) { 4345 1.1 joerg fprintf(stderr, "should not get an empty compileCommand set for file" 4346 1.1 joerg " '%s'\n", argv[i+1]); 4347 1.1 joerg errorCode = -1; 4348 1.1 joerg break; 4349 1.1 joerg } 4350 1.1 joerg 4351 1.1 joerg for (j=0; j<numCmds; ++j) { 4352 1.1 joerg CCmd = clang_CompileCommands_getCommand(CCmds, j); 4353 1.1 joerg 4354 1.1 joerg wd = clang_CompileCommand_getDirectory(CCmd); 4355 1.1 joerg printf("workdir:'%s'", clang_getCString(wd)); 4356 1.1 joerg clang_disposeString(wd); 4357 1.1 joerg 4358 1.1 joerg printf(" cmdline:'"); 4359 1.1 joerg numArgs = clang_CompileCommand_getNumArgs(CCmd); 4360 1.1 joerg for (a=0; a<numArgs; ++a) { 4361 1.1 joerg if (a) printf(" "); 4362 1.1 joerg arg = clang_CompileCommand_getArg(CCmd, a); 4363 1.1 joerg printf("%s", clang_getCString(arg)); 4364 1.1 joerg clang_disposeString(arg); 4365 1.1 joerg } 4366 1.1 joerg printf("'\n"); 4367 1.1 joerg } 4368 1.1 joerg 4369 1.1 joerg clang_CompileCommands_dispose(CCmds); 4370 1.1 joerg 4371 1.1 joerg i += 2; 4372 1.1 joerg } 4373 1.1 joerg } 4374 1.1 joerg clang_CompilationDatabase_dispose(db); 4375 1.1 joerg } else { 4376 1.1 joerg printf("database loading failed with error code %d.\n", ec); 4377 1.1 joerg errorCode = -1; 4378 1.1 joerg } 4379 1.1 joerg 4380 1.1 joerg cdb_end: 4381 1.1 joerg free(tmp); 4382 1.1 joerg 4383 1.1 joerg return errorCode; 4384 1.1 joerg } 4385 1.1 joerg 4386 1.1 joerg /******************************************************************************/ 4387 1.1 joerg /* USR printing. */ 4388 1.1 joerg /******************************************************************************/ 4389 1.1 joerg 4390 1.1 joerg static int insufficient_usr(const char *kind, const char *usage) { 4391 1.1 joerg fprintf(stderr, "USR for '%s' requires: %s\n", kind, usage); 4392 1.1 joerg return 1; 4393 1.1 joerg } 4394 1.1 joerg 4395 1.1 joerg static unsigned isUSR(const char *s) { 4396 1.1 joerg return s[0] == 'c' && s[1] == ':'; 4397 1.1 joerg } 4398 1.1 joerg 4399 1.1 joerg static int not_usr(const char *s, const char *arg) { 4400 1.1 joerg fprintf(stderr, "'%s' argument ('%s') is not a USR\n", s, arg); 4401 1.1 joerg return 1; 4402 1.1 joerg } 4403 1.1 joerg 4404 1.1 joerg static void print_usr(CXString usr) { 4405 1.1 joerg const char *s = clang_getCString(usr); 4406 1.1 joerg printf("%s\n", s); 4407 1.1 joerg clang_disposeString(usr); 4408 1.1 joerg } 4409 1.1 joerg 4410 1.1 joerg static void display_usrs() { 4411 1.1 joerg fprintf(stderr, "-print-usrs options:\n" 4412 1.1 joerg " ObjCCategory <class name> <category name>\n" 4413 1.1 joerg " ObjCClass <class name>\n" 4414 1.1 joerg " ObjCIvar <ivar name> <class USR>\n" 4415 1.1 joerg " ObjCMethod <selector> [0=class method|1=instance method] " 4416 1.1 joerg "<class USR>\n" 4417 1.1 joerg " ObjCProperty <property name> <class USR>\n" 4418 1.1 joerg " ObjCProtocol <protocol name>\n"); 4419 1.1 joerg } 4420 1.1 joerg 4421 1.1 joerg int print_usrs(const char **I, const char **E) { 4422 1.1 joerg while (I != E) { 4423 1.1 joerg const char *kind = *I; 4424 1.1 joerg unsigned len = strlen(kind); 4425 1.1 joerg switch (len) { 4426 1.1 joerg case 8: 4427 1.1 joerg if (memcmp(kind, "ObjCIvar", 8) == 0) { 4428 1.1 joerg if (I + 2 >= E) 4429 1.1 joerg return insufficient_usr(kind, "<ivar name> <class USR>"); 4430 1.1 joerg if (!isUSR(I[2])) 4431 1.1 joerg return not_usr("<class USR>", I[2]); 4432 1.1 joerg else { 4433 1.1 joerg CXString x = createCXString(I[2]); 4434 1.1 joerg print_usr(clang_constructUSR_ObjCIvar(I[1], x)); 4435 1.1 joerg } 4436 1.1 joerg 4437 1.1 joerg I += 3; 4438 1.1 joerg continue; 4439 1.1 joerg } 4440 1.1 joerg break; 4441 1.1 joerg case 9: 4442 1.1 joerg if (memcmp(kind, "ObjCClass", 9) == 0) { 4443 1.1 joerg if (I + 1 >= E) 4444 1.1 joerg return insufficient_usr(kind, "<class name>"); 4445 1.1 joerg print_usr(clang_constructUSR_ObjCClass(I[1])); 4446 1.1 joerg I += 2; 4447 1.1 joerg continue; 4448 1.1 joerg } 4449 1.1 joerg break; 4450 1.1 joerg case 10: 4451 1.1 joerg if (memcmp(kind, "ObjCMethod", 10) == 0) { 4452 1.1 joerg if (I + 3 >= E) 4453 1.1 joerg return insufficient_usr(kind, "<method selector> " 4454 1.1 joerg "[0=class method|1=instance method] <class USR>"); 4455 1.1 joerg if (!isUSR(I[3])) 4456 1.1 joerg return not_usr("<class USR>", I[3]); 4457 1.1 joerg else { 4458 1.1 joerg CXString x = createCXString(I[3]); 4459 1.1 joerg print_usr(clang_constructUSR_ObjCMethod(I[1], atoi(I[2]), x)); 4460 1.1 joerg } 4461 1.1 joerg I += 4; 4462 1.1 joerg continue; 4463 1.1 joerg } 4464 1.1 joerg break; 4465 1.1 joerg case 12: 4466 1.1 joerg if (memcmp(kind, "ObjCCategory", 12) == 0) { 4467 1.1 joerg if (I + 2 >= E) 4468 1.1 joerg return insufficient_usr(kind, "<class name> <category name>"); 4469 1.1 joerg print_usr(clang_constructUSR_ObjCCategory(I[1], I[2])); 4470 1.1 joerg I += 3; 4471 1.1 joerg continue; 4472 1.1 joerg } 4473 1.1 joerg if (memcmp(kind, "ObjCProtocol", 12) == 0) { 4474 1.1 joerg if (I + 1 >= E) 4475 1.1 joerg return insufficient_usr(kind, "<protocol name>"); 4476 1.1 joerg print_usr(clang_constructUSR_ObjCProtocol(I[1])); 4477 1.1 joerg I += 2; 4478 1.1 joerg continue; 4479 1.1 joerg } 4480 1.1 joerg if (memcmp(kind, "ObjCProperty", 12) == 0) { 4481 1.1 joerg if (I + 2 >= E) 4482 1.1 joerg return insufficient_usr(kind, "<property name> <class USR>"); 4483 1.1 joerg if (!isUSR(I[2])) 4484 1.1 joerg return not_usr("<class USR>", I[2]); 4485 1.1 joerg else { 4486 1.1 joerg CXString x = createCXString(I[2]); 4487 1.1 joerg print_usr(clang_constructUSR_ObjCProperty(I[1], x)); 4488 1.1 joerg } 4489 1.1 joerg I += 3; 4490 1.1 joerg continue; 4491 1.1 joerg } 4492 1.1 joerg break; 4493 1.1 joerg default: 4494 1.1 joerg break; 4495 1.1 joerg } 4496 1.1 joerg break; 4497 1.1 joerg } 4498 1.1 joerg 4499 1.1 joerg if (I != E) { 4500 1.1 joerg fprintf(stderr, "Invalid USR kind: %s\n", *I); 4501 1.1 joerg display_usrs(); 4502 1.1 joerg return 1; 4503 1.1 joerg } 4504 1.1 joerg return 0; 4505 1.1 joerg } 4506 1.1 joerg 4507 1.1 joerg int print_usrs_file(const char *file_name) { 4508 1.1 joerg char line[2048]; 4509 1.1 joerg const char *args[128]; 4510 1.1 joerg unsigned numChars = 0; 4511 1.1 joerg 4512 1.1 joerg FILE *fp = fopen(file_name, "r"); 4513 1.1 joerg if (!fp) { 4514 1.1 joerg fprintf(stderr, "error: cannot open '%s'\n", file_name); 4515 1.1 joerg return 1; 4516 1.1 joerg } 4517 1.1 joerg 4518 1.1 joerg /* This code is not really all that safe, but it works fine for testing. */ 4519 1.1 joerg while (!feof(fp)) { 4520 1.1 joerg char c = fgetc(fp); 4521 1.1 joerg if (c == '\n') { 4522 1.1 joerg unsigned i = 0; 4523 1.1 joerg const char *s = 0; 4524 1.1 joerg 4525 1.1 joerg if (numChars == 0) 4526 1.1 joerg continue; 4527 1.1 joerg 4528 1.1 joerg line[numChars] = '\0'; 4529 1.1 joerg numChars = 0; 4530 1.1 joerg 4531 1.1 joerg if (line[0] == '/' && line[1] == '/') 4532 1.1 joerg continue; 4533 1.1 joerg 4534 1.1 joerg s = strtok(line, " "); 4535 1.1 joerg while (s) { 4536 1.1 joerg args[i] = s; 4537 1.1 joerg ++i; 4538 1.1 joerg s = strtok(0, " "); 4539 1.1 joerg } 4540 1.1 joerg if (print_usrs(&args[0], &args[i])) 4541 1.1 joerg return 1; 4542 1.1 joerg } 4543 1.1 joerg else 4544 1.1 joerg line[numChars++] = c; 4545 1.1 joerg } 4546 1.1 joerg 4547 1.1 joerg fclose(fp); 4548 1.1 joerg return 0; 4549 1.1 joerg } 4550 1.1 joerg 4551 1.1 joerg /******************************************************************************/ 4552 1.1 joerg /* Command line processing. */ 4553 1.1 joerg /******************************************************************************/ 4554 1.1 joerg int write_pch_file(const char *filename, int argc, const char *argv[]) { 4555 1.1 joerg CXIndex Idx; 4556 1.1 joerg CXTranslationUnit TU; 4557 1.1 joerg struct CXUnsavedFile *unsaved_files = 0; 4558 1.1 joerg int num_unsaved_files = 0; 4559 1.1 joerg enum CXErrorCode Err; 4560 1.1 joerg int result = 0; 4561 1.1 joerg 4562 1.1 joerg Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1); 4563 1.1 joerg 4564 1.1 joerg if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) { 4565 1.1 joerg clang_disposeIndex(Idx); 4566 1.1 joerg return -1; 4567 1.1 joerg } 4568 1.1 joerg 4569 1.1 joerg Err = clang_parseTranslationUnit2( 4570 1.1 joerg Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files, 4571 1.1 joerg unsaved_files, num_unsaved_files, 4572 1.1 joerg CXTranslationUnit_Incomplete | 4573 1.1 joerg CXTranslationUnit_DetailedPreprocessingRecord | 4574 1.1 joerg CXTranslationUnit_ForSerialization, 4575 1.1 joerg &TU); 4576 1.1 joerg if (Err != CXError_Success) { 4577 1.1 joerg fprintf(stderr, "Unable to load translation unit!\n"); 4578 1.1 joerg describeLibclangFailure(Err); 4579 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 4580 1.1 joerg clang_disposeTranslationUnit(TU); 4581 1.1 joerg clang_disposeIndex(Idx); 4582 1.1 joerg return 1; 4583 1.1 joerg } 4584 1.1 joerg 4585 1.1 joerg switch (clang_saveTranslationUnit(TU, filename, 4586 1.1 joerg clang_defaultSaveOptions(TU))) { 4587 1.1 joerg case CXSaveError_None: 4588 1.1 joerg break; 4589 1.1 joerg 4590 1.1 joerg case CXSaveError_TranslationErrors: 4591 1.1 joerg fprintf(stderr, "Unable to write PCH file %s: translation errors\n", 4592 1.1 joerg filename); 4593 1.1 joerg result = 2; 4594 1.1 joerg break; 4595 1.1 joerg 4596 1.1 joerg case CXSaveError_InvalidTU: 4597 1.1 joerg fprintf(stderr, "Unable to write PCH file %s: invalid translation unit\n", 4598 1.1 joerg filename); 4599 1.1 joerg result = 3; 4600 1.1 joerg break; 4601 1.1 joerg 4602 1.1 joerg case CXSaveError_Unknown: 4603 1.1 joerg default: 4604 1.1 joerg fprintf(stderr, "Unable to write PCH file %s: unknown error \n", filename); 4605 1.1 joerg result = 1; 4606 1.1 joerg break; 4607 1.1 joerg } 4608 1.1 joerg 4609 1.1 joerg clang_disposeTranslationUnit(TU); 4610 1.1 joerg free_remapped_files(unsaved_files, num_unsaved_files); 4611 1.1 joerg clang_disposeIndex(Idx); 4612 1.1 joerg return result; 4613 1.1 joerg } 4614 1.1 joerg 4615 1.1 joerg /******************************************************************************/ 4616 1.1 joerg /* Serialized diagnostics. */ 4617 1.1 joerg /******************************************************************************/ 4618 1.1 joerg 4619 1.1 joerg static const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error) { 4620 1.1 joerg switch (error) { 4621 1.1 joerg case CXLoadDiag_CannotLoad: return "Cannot Load File"; 4622 1.1 joerg case CXLoadDiag_None: break; 4623 1.1 joerg case CXLoadDiag_Unknown: return "Unknown"; 4624 1.1 joerg case CXLoadDiag_InvalidFile: return "Invalid File"; 4625 1.1 joerg } 4626 1.1 joerg return "None"; 4627 1.1 joerg } 4628 1.1 joerg 4629 1.1 joerg static const char *getSeverityString(enum CXDiagnosticSeverity severity) { 4630 1.1 joerg switch (severity) { 4631 1.1 joerg case CXDiagnostic_Note: return "note"; 4632 1.1 joerg case CXDiagnostic_Error: return "error"; 4633 1.1 joerg case CXDiagnostic_Fatal: return "fatal"; 4634 1.1 joerg case CXDiagnostic_Ignored: return "ignored"; 4635 1.1 joerg case CXDiagnostic_Warning: return "warning"; 4636 1.1 joerg } 4637 1.1 joerg return "unknown"; 4638 1.1 joerg } 4639 1.1 joerg 4640 1.1 joerg static void printIndent(unsigned indent) { 4641 1.1 joerg if (indent == 0) 4642 1.1 joerg return; 4643 1.1 joerg fprintf(stderr, "+"); 4644 1.1 joerg --indent; 4645 1.1 joerg while (indent > 0) { 4646 1.1 joerg fprintf(stderr, "-"); 4647 1.1 joerg --indent; 4648 1.1 joerg } 4649 1.1 joerg } 4650 1.1 joerg 4651 1.1 joerg static void printLocation(CXSourceLocation L) { 4652 1.1 joerg CXFile File; 4653 1.1 joerg CXString FileName; 4654 1.1 joerg unsigned line, column, offset; 4655 1.1 joerg 4656 1.1 joerg clang_getExpansionLocation(L, &File, &line, &column, &offset); 4657 1.1 joerg FileName = clang_getFileName(File); 4658 1.1 joerg 4659 1.1 joerg fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column); 4660 1.1 joerg clang_disposeString(FileName); 4661 1.1 joerg } 4662 1.1 joerg 4663 1.1 joerg static void printRanges(CXDiagnostic D, unsigned indent) { 4664 1.1 joerg unsigned i, n = clang_getDiagnosticNumRanges(D); 4665 1.1 joerg 4666 1.1 joerg for (i = 0; i < n; ++i) { 4667 1.1 joerg CXSourceLocation Start, End; 4668 1.1 joerg CXSourceRange SR = clang_getDiagnosticRange(D, i); 4669 1.1 joerg Start = clang_getRangeStart(SR); 4670 1.1 joerg End = clang_getRangeEnd(SR); 4671 1.1 joerg 4672 1.1 joerg printIndent(indent); 4673 1.1 joerg fprintf(stderr, "Range: "); 4674 1.1 joerg printLocation(Start); 4675 1.1 joerg fprintf(stderr, " "); 4676 1.1 joerg printLocation(End); 4677 1.1 joerg fprintf(stderr, "\n"); 4678 1.1 joerg } 4679 1.1 joerg } 4680 1.1 joerg 4681 1.1 joerg static void printFixIts(CXDiagnostic D, unsigned indent) { 4682 1.1 joerg unsigned i, n = clang_getDiagnosticNumFixIts(D); 4683 1.1 joerg fprintf(stderr, "Number FIXITs = %d\n", n); 4684 1.1 joerg for (i = 0 ; i < n; ++i) { 4685 1.1 joerg CXSourceRange ReplacementRange; 4686 1.1 joerg CXString text; 4687 1.1 joerg text = clang_getDiagnosticFixIt(D, i, &ReplacementRange); 4688 1.1 joerg 4689 1.1 joerg printIndent(indent); 4690 1.1 joerg fprintf(stderr, "FIXIT: ("); 4691 1.1 joerg printLocation(clang_getRangeStart(ReplacementRange)); 4692 1.1 joerg fprintf(stderr, " - "); 4693 1.1 joerg printLocation(clang_getRangeEnd(ReplacementRange)); 4694 1.1 joerg fprintf(stderr, "): \"%s\"\n", clang_getCString(text)); 4695 1.1 joerg clang_disposeString(text); 4696 1.1 joerg } 4697 1.1 joerg } 4698 1.1 joerg 4699 1.1 joerg static void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) { 4700 1.1 joerg unsigned i, n; 4701 1.1 joerg 4702 1.1 joerg if (!Diags) 4703 1.1 joerg return; 4704 1.1 joerg 4705 1.1 joerg n = clang_getNumDiagnosticsInSet(Diags); 4706 1.1 joerg for (i = 0; i < n; ++i) { 4707 1.1 joerg CXSourceLocation DiagLoc; 4708 1.1 joerg CXDiagnostic D; 4709 1.1 joerg CXFile File; 4710 1.1 joerg CXString FileName, DiagSpelling, DiagOption, DiagCat; 4711 1.1 joerg unsigned line, column, offset; 4712 1.1 joerg const char *FileNameStr = 0, *DiagOptionStr = 0, *DiagCatStr = 0; 4713 1.1 joerg 4714 1.1 joerg D = clang_getDiagnosticInSet(Diags, i); 4715 1.1 joerg DiagLoc = clang_getDiagnosticLocation(D); 4716 1.1 joerg clang_getExpansionLocation(DiagLoc, &File, &line, &column, &offset); 4717 1.1 joerg FileName = clang_getFileName(File); 4718 1.1 joerg FileNameStr = clang_getCString(FileName); 4719 1.1 joerg DiagSpelling = clang_getDiagnosticSpelling(D); 4720 1.1 joerg 4721 1.1 joerg printIndent(indent); 4722 1.1 joerg 4723 1.1 joerg fprintf(stderr, "%s:%d:%d: %s: %s", 4724 1.1 joerg FileNameStr ? FileNameStr : "(null)", 4725 1.1 joerg line, 4726 1.1 joerg column, 4727 1.1 joerg getSeverityString(clang_getDiagnosticSeverity(D)), 4728 1.1 joerg clang_getCString(DiagSpelling)); 4729 1.1 joerg 4730 1.1 joerg DiagOption = clang_getDiagnosticOption(D, 0); 4731 1.1 joerg DiagOptionStr = clang_getCString(DiagOption); 4732 1.1 joerg if (DiagOptionStr) { 4733 1.1 joerg fprintf(stderr, " [%s]", DiagOptionStr); 4734 1.1 joerg } 4735 1.1 joerg 4736 1.1 joerg DiagCat = clang_getDiagnosticCategoryText(D); 4737 1.1 joerg DiagCatStr = clang_getCString(DiagCat); 4738 1.1 joerg if (DiagCatStr) { 4739 1.1 joerg fprintf(stderr, " [%s]", DiagCatStr); 4740 1.1 joerg } 4741 1.1 joerg 4742 1.1 joerg fprintf(stderr, "\n"); 4743 1.1 joerg 4744 1.1 joerg printRanges(D, indent); 4745 1.1 joerg printFixIts(D, indent); 4746 1.1 joerg 4747 1.1 joerg /* Print subdiagnostics. */ 4748 1.1 joerg printDiagnosticSet(clang_getChildDiagnostics(D), indent+2); 4749 1.1 joerg 4750 1.1 joerg clang_disposeString(FileName); 4751 1.1 joerg clang_disposeString(DiagSpelling); 4752 1.1 joerg clang_disposeString(DiagOption); 4753 1.1 joerg clang_disposeString(DiagCat); 4754 1.1 joerg } 4755 1.1 joerg } 4756 1.1 joerg 4757 1.1 joerg static int read_diagnostics(const char *filename) { 4758 1.1 joerg enum CXLoadDiag_Error error; 4759 1.1 joerg CXString errorString; 4760 1.1 joerg CXDiagnosticSet Diags = 0; 4761 1.1 joerg 4762 1.1 joerg Diags = clang_loadDiagnostics(filename, &error, &errorString); 4763 1.1 joerg if (!Diags) { 4764 1.1 joerg fprintf(stderr, "Trouble deserializing file (%s): %s\n", 4765 1.1 joerg getDiagnosticCodeStr(error), 4766 1.1 joerg clang_getCString(errorString)); 4767 1.1 joerg clang_disposeString(errorString); 4768 1.1 joerg return 1; 4769 1.1 joerg } 4770 1.1 joerg 4771 1.1 joerg printDiagnosticSet(Diags, 0); 4772 1.1 joerg fprintf(stderr, "Number of diagnostics: %d\n", 4773 1.1 joerg clang_getNumDiagnosticsInSet(Diags)); 4774 1.1 joerg clang_disposeDiagnosticSet(Diags); 4775 1.1 joerg return 0; 4776 1.1 joerg } 4777 1.1 joerg 4778 1.1 joerg static int perform_print_build_session_timestamp(void) { 4779 1.1 joerg printf("%lld\n", clang_getBuildSessionTimestamp()); 4780 1.1 joerg return 0; 4781 1.1 joerg } 4782 1.1 joerg 4783 1.1 joerg /******************************************************************************/ 4784 1.1 joerg /* Command line processing. */ 4785 1.1 joerg /******************************************************************************/ 4786 1.1 joerg 4787 1.1 joerg static CXCursorVisitor GetVisitor(const char *s) { 4788 1.1 joerg if (s[0] == '\0') 4789 1.1 joerg return FilteredPrintingVisitor; 4790 1.1 joerg if (strcmp(s, "-usrs") == 0) 4791 1.1 joerg return USRVisitor; 4792 1.1 joerg if (strncmp(s, "-memory-usage", 13) == 0) 4793 1.1 joerg return GetVisitor(s + 13); 4794 1.1 joerg return NULL; 4795 1.1 joerg } 4796 1.1 joerg 4797 1.1 joerg static void print_usage(void) { 4798 1.1 joerg fprintf(stderr, 4799 1.1 joerg "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n" 4800 1.1 joerg " c-index-test -code-completion-timing=<site> <compiler arguments>\n" 4801 1.1 joerg " c-index-test -cursor-at=<site> <compiler arguments>\n" 4802 1.1 joerg " c-index-test -evaluate-cursor-at=<site> <compiler arguments>\n" 4803 1.1 joerg " c-index-test -get-macro-info-cursor-at=<site> <compiler arguments>\n" 4804 1.1 joerg " c-index-test -file-refs-at=<site> <compiler arguments>\n" 4805 1.1 joerg " c-index-test -file-includes-in=<filename> <compiler arguments>\n"); 4806 1.1 joerg fprintf(stderr, 4807 1.1 joerg " c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n" 4808 1.1 joerg " c-index-test -index-file-full [-check-prefix=<FileCheck prefix>] <compiler arguments>\n" 4809 1.1 joerg " c-index-test -index-tu [-check-prefix=<FileCheck prefix>] <AST file>\n" 4810 1.1 joerg " c-index-test -index-compile-db [-check-prefix=<FileCheck prefix>] <compilation database>\n" 4811 1.1 joerg " c-index-test -test-file-scan <AST file> <source file> " 4812 1.1 joerg "[FileCheck prefix]\n"); 4813 1.1 joerg fprintf(stderr, 4814 1.1 joerg " c-index-test -test-load-tu <AST file> <symbol filter> " 4815 1.1 joerg "[FileCheck prefix]\n" 4816 1.1 joerg " c-index-test -test-load-tu-usrs <AST file> <symbol filter> " 4817 1.1 joerg "[FileCheck prefix]\n" 4818 1.1 joerg " c-index-test -test-load-source <symbol filter> {<args>}*\n"); 4819 1.1 joerg fprintf(stderr, 4820 1.1 joerg " c-index-test -test-load-source-memory-usage " 4821 1.1 joerg "<symbol filter> {<args>}*\n" 4822 1.1 joerg " c-index-test -test-load-source-reparse <trials> <symbol filter> " 4823 1.1 joerg " {<args>}*\n" 4824 1.1 joerg " c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n" 4825 1.1 joerg " c-index-test -test-load-source-usrs-memory-usage " 4826 1.1 joerg "<symbol filter> {<args>}*\n" 4827 1.1 joerg " c-index-test -test-annotate-tokens=<range> {<args>}*\n" 4828 1.1 joerg " c-index-test -test-inclusion-stack-source {<args>}*\n" 4829 1.1 joerg " c-index-test -test-inclusion-stack-tu <AST file>\n"); 4830 1.1 joerg fprintf(stderr, 4831 1.1 joerg " c-index-test -test-print-linkage-source {<args>}*\n" 4832 1.1 joerg " c-index-test -test-print-visibility {<args>}*\n" 4833 1.1 joerg " c-index-test -test-print-type {<args>}*\n" 4834 1.1 joerg " c-index-test -test-print-type-size {<args>}*\n" 4835 1.1 joerg " c-index-test -test-print-bitwidth {<args>}*\n" 4836 1.1 joerg " c-index-test -test-print-target-info {<args>}*\n" 4837 1.1 joerg " c-index-test -test-print-type-declaration {<args>}*\n" 4838 1.1 joerg " c-index-test -print-usr [<CursorKind> {<args>}]*\n" 4839 1.1 joerg " c-index-test -print-usr-file <file>\n"); 4840 1.1 joerg fprintf(stderr, 4841 1.1 joerg " c-index-test -write-pch <file> <compiler arguments>\n" 4842 1.1 joerg " c-index-test -compilation-db [lookup <filename>] database\n"); 4843 1.1 joerg fprintf(stderr, 4844 1.1 joerg " c-index-test -print-build-session-timestamp\n"); 4845 1.1 joerg fprintf(stderr, 4846 1.1 joerg " c-index-test -read-diagnostics <file>\n\n"); 4847 1.1 joerg fprintf(stderr, 4848 1.1 joerg " <symbol filter> values:\n%s", 4849 1.1 joerg " all - load all symbols, including those from PCH\n" 4850 1.1 joerg " local - load all symbols except those in PCH\n" 4851 1.1 joerg " category - only load ObjC categories (non-PCH)\n" 4852 1.1 joerg " interface - only load ObjC interfaces (non-PCH)\n" 4853 1.1 joerg " protocol - only load ObjC protocols (non-PCH)\n" 4854 1.1 joerg " function - only load functions (non-PCH)\n" 4855 1.1 joerg " typedef - only load typdefs (non-PCH)\n" 4856 1.1 joerg " scan-function - scan function bodies (non-PCH)\n\n"); 4857 1.1 joerg } 4858 1.1 joerg 4859 1.1 joerg /***/ 4860 1.1 joerg 4861 1.1 joerg int cindextest_main(int argc, const char **argv) { 4862 1.1 joerg clang_enableStackTraces(); 4863 1.1 joerg if (argc > 2 && strcmp(argv[1], "-read-diagnostics") == 0) 4864 1.1 joerg return read_diagnostics(argv[2]); 4865 1.1 joerg if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1]) 4866 1.1 joerg return perform_code_completion(argc, argv, 0); 4867 1.1 joerg if (argc > 2 && strstr(argv[1], "-code-completion-timing=") == argv[1]) 4868 1.1 joerg return perform_code_completion(argc, argv, 1); 4869 1.1 joerg if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1]) 4870 1.1 joerg return inspect_cursor_at(argc, argv, "-cursor-at=", inspect_print_cursor); 4871 1.1 joerg if (argc > 2 && strstr(argv[1], "-evaluate-cursor-at=") == argv[1]) 4872 1.1 joerg return inspect_cursor_at(argc, argv, "-evaluate-cursor-at=", 4873 1.1 joerg inspect_evaluate_cursor); 4874 1.1 joerg if (argc > 2 && strstr(argv[1], "-get-macro-info-cursor-at=") == argv[1]) 4875 1.1 joerg return inspect_cursor_at(argc, argv, "-get-macro-info-cursor-at=", 4876 1.1 joerg inspect_macroinfo_cursor); 4877 1.1 joerg if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1]) 4878 1.1 joerg return find_file_refs_at(argc, argv); 4879 1.1 joerg if (argc > 2 && strstr(argv[1], "-file-includes-in=") == argv[1]) 4880 1.1 joerg return find_file_includes_in(argc, argv); 4881 1.1 joerg if (argc > 2 && strcmp(argv[1], "-index-file") == 0) 4882 1.1 joerg return index_file(argc - 2, argv + 2, /*full=*/0); 4883 1.1 joerg if (argc > 2 && strcmp(argv[1], "-index-file-full") == 0) 4884 1.1 joerg return index_file(argc - 2, argv + 2, /*full=*/1); 4885 1.1 joerg if (argc > 2 && strcmp(argv[1], "-index-tu") == 0) 4886 1.1 joerg return index_tu(argc - 2, argv + 2); 4887 1.1 joerg if (argc > 2 && strcmp(argv[1], "-index-compile-db") == 0) 4888 1.1 joerg return index_compile_db(argc - 2, argv + 2); 4889 1.1 joerg else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) { 4890 1.1 joerg CXCursorVisitor I = GetVisitor(argv[1] + 13); 4891 1.1 joerg if (I) 4892 1.1 joerg return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I, 4893 1.1 joerg NULL); 4894 1.1 joerg } 4895 1.1 joerg else if (argc >= 5 && strncmp(argv[1], "-test-load-source-reparse", 25) == 0){ 4896 1.1 joerg CXCursorVisitor I = GetVisitor(argv[1] + 25); 4897 1.1 joerg if (I) { 4898 1.1 joerg int trials = atoi(argv[2]); 4899 1.1 joerg return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I, 4900 1.1 joerg NULL); 4901 1.1 joerg } 4902 1.1 joerg } 4903 1.1 joerg else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) { 4904 1.1 joerg CXCursorVisitor I = GetVisitor(argv[1] + 17); 4905 1.1 joerg 4906 1.1 joerg PostVisitTU postVisit = 0; 4907 1.1 joerg if (strstr(argv[1], "-memory-usage")) 4908 1.1 joerg postVisit = PrintMemoryUsage; 4909 1.1 joerg 4910 1.1 joerg if (I) 4911 1.1 joerg return perform_test_load_source(argc - 3, argv + 3, argv[2], I, 4912 1.1 joerg postVisit); 4913 1.1 joerg } 4914 1.1 joerg else if (argc >= 3 && strcmp(argv[1], "-single-file-parse") == 0) 4915 1.1 joerg return perform_single_file_parse(argv[2]); 4916 1.1 joerg else if (argc >= 3 && strcmp(argv[1], "-retain-excluded-conditional-blocks") == 0) 4917 1.1 joerg return perform_file_retain_excluded_cb(argv[2]); 4918 1.1 joerg else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0) 4919 1.1 joerg return perform_file_scan(argv[2], argv[3], 4920 1.1 joerg argc >= 5 ? argv[4] : 0); 4921 1.1 joerg else if (argc > 2 && strstr(argv[1], "-test-annotate-tokens=") == argv[1]) 4922 1.1 joerg return perform_token_annotation(argc, argv); 4923 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-source") == 0) 4924 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", NULL, 4925 1.1 joerg PrintInclusionStack); 4926 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-tu") == 0) 4927 1.1 joerg return perform_test_load_tu(argv[2], "all", NULL, NULL, 4928 1.1 joerg PrintInclusionStack); 4929 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0) 4930 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage, 4931 1.1 joerg NULL); 4932 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-visibility") == 0) 4933 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", PrintVisibility, 4934 1.1 joerg NULL); 4935 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0) 4936 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", 4937 1.1 joerg PrintType, 0); 4938 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-type-size") == 0) 4939 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", 4940 1.1 joerg PrintTypeSize, 0); 4941 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-type-declaration") == 0) 4942 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", 4943 1.1 joerg PrintTypeDeclaration, 0); 4944 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-decl-attributes") == 0) 4945 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", 4946 1.1 joerg PrintDeclAttributes, 0); 4947 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0) 4948 1.1 joerg return perform_test_load_source(argc - 2, argv + 2, "all", 4949 1.1 joerg PrintBitWidth, 0); 4950 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-mangle") == 0) 4951 1.1 joerg return perform_test_load_tu(argv[2], "all", NULL, PrintMangledName, NULL); 4952 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-manglings") == 0) 4953 1.1 joerg return perform_test_load_tu(argv[2], "all", NULL, PrintManglings, NULL); 4954 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-test-print-target-info") == 0) 4955 1.1 joerg return print_target_info(argc - 2, argv + 2); 4956 1.1 joerg else if (argc > 1 && strcmp(argv[1], "-print-usr") == 0) { 4957 1.1 joerg if (argc > 2) 4958 1.1 joerg return print_usrs(argv + 2, argv + argc); 4959 1.1 joerg else { 4960 1.1 joerg display_usrs(); 4961 1.1 joerg return 1; 4962 1.1 joerg } 4963 1.1 joerg } 4964 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-print-usr-file") == 0) 4965 1.1 joerg return print_usrs_file(argv[2]); 4966 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0) 4967 1.1 joerg return write_pch_file(argv[2], argc - 3, argv + 3); 4968 1.1 joerg else if (argc > 2 && strcmp(argv[1], "-compilation-db") == 0) 4969 1.1 joerg return perform_test_compilation_db(argv[argc-1], argc - 3, argv + 2); 4970 1.1 joerg else if (argc == 2 && strcmp(argv[1], "-print-build-session-timestamp") == 0) 4971 1.1 joerg return perform_print_build_session_timestamp(); 4972 1.1 joerg 4973 1.1 joerg print_usage(); 4974 1.1 joerg return 1; 4975 1.1 joerg } 4976 1.1 joerg 4977 1.1 joerg /***/ 4978 1.1 joerg 4979 1.1 joerg /* We intentionally run in a separate thread to ensure we at least minimal 4980 1.1 joerg * testing of a multithreaded environment (for example, having a reduced stack 4981 1.1 joerg * size). */ 4982 1.1 joerg 4983 1.1 joerg typedef struct thread_info { 4984 1.1 joerg int (*main_func)(int argc, const char **argv); 4985 1.1 joerg int argc; 4986 1.1 joerg const char **argv; 4987 1.1 joerg int result; 4988 1.1 joerg } thread_info; 4989 1.1 joerg void thread_runner(void *client_data_v) { 4990 1.1 joerg thread_info *client_data = client_data_v; 4991 1.1 joerg client_data->result = client_data->main_func(client_data->argc, 4992 1.1 joerg client_data->argv); 4993 1.1 joerg } 4994 1.1 joerg 4995 1.1 joerg static void flush_atexit(void) { 4996 1.1 joerg /* stdout, and surprisingly even stderr, are not always flushed on process 4997 1.1 joerg * and thread exit, particularly when the system is under heavy load. */ 4998 1.1 joerg fflush(stdout); 4999 1.1 joerg fflush(stderr); 5000 1.1 joerg } 5001 1.1 joerg 5002 1.1 joerg int main(int argc, const char **argv) { 5003 1.1 joerg thread_info client_data; 5004 1.1 joerg 5005 1.1 joerg atexit(flush_atexit); 5006 1.1 joerg 5007 1.1 joerg #ifdef CLANG_HAVE_LIBXML 5008 1.1 joerg LIBXML_TEST_VERSION 5009 1.1 joerg #endif 5010 1.1 joerg 5011 1.1 joerg if (argc > 1 && strcmp(argv[1], "core") == 0) 5012 1.1 joerg return indextest_core_main(argc, argv); 5013 1.1 joerg 5014 1.1 joerg client_data.main_func = cindextest_main; 5015 1.1 joerg client_data.argc = argc; 5016 1.1 joerg client_data.argv = argv; 5017 1.1 joerg 5018 1.1 joerg if (getenv("CINDEXTEST_NOTHREADS")) 5019 1.1 joerg return client_data.main_func(client_data.argc, client_data.argv); 5020 1.1 joerg 5021 1.1 joerg clang_executeOnThread(thread_runner, &client_data, 0); 5022 1.1 joerg return client_data.result; 5023 1.1 joerg } 5024