Bug Summary

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