Bug Summary

File:tools/clang/tools/c-index-test/c-index-test.c
Warning:line 3039, column 13
Potential leak of memory pointed to by 'Filenames'

Annotated Source Code

Press '?' to see keyboard shortcuts

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