3 #include "clang-c/BuildSystem.h"
4 #include "clang-c/CXCompilationDatabase.h"
5 #include "clang-c/CXErrorCode.h"
6 #include "clang-c/CXSourceLocation.h"
7 #include "clang-c/CXString.h"
8 #include "clang-c/Documentation.h"
9 #include "clang-c/Index.h"
10 #include "clang/Config/config.h"
11 #include "llvm/Support/AutoConvert.h"
18 #ifdef CLANG_HAVE_LIBXML
19 #include <libxml/parser.h>
20 #include <libxml/relaxng.h>
21 #include <libxml/xmlerror.h>
30 extern int indextest_core_main(int argc
, const char **argv
);
31 extern int indextest_perform_shell_execution(const char *command_line
);
33 /******************************************************************************/
34 /* Utility functions. */
35 /******************************************************************************/
38 char *basename(const char* path
)
40 char* base1
= (char*)strrchr(path
, '/');
41 char* base2
= (char*)strrchr(path
, '\\');
43 return((base1
> base2
) ? base1
+ 1 : base2
+ 1);
50 #pragma clang diagnostic push
51 #pragma clang diagnostic ignored "-Wcast-qual"
53 return ((char *)path
);
55 #pragma clang diagnostic pop
58 char *dirname(char* path
)
60 char* base1
= (char*)strrchr(path
, '/');
61 char* base2
= (char*)strrchr(path
, '\\');
75 extern char *basename(const char *);
76 extern char *dirname(char *);
79 CXIndex
createIndexWithInvocationEmissionPath(int ExcludeDeclarationsFromPCH
,
80 int DisplayDiagnostics
) {
84 memset(&Opts
, 0, sizeof(Opts
));
85 Opts
.Size
= sizeof(CXIndexOptions
);
86 Opts
.ExcludeDeclarationsFromPCH
= ExcludeDeclarationsFromPCH
;
87 Opts
.DisplayDiagnostics
= DisplayDiagnostics
;
88 Opts
.InvocationEmissionPath
= getenv("CINDEXTEST_INVOCATION_EMISSION_PATH");
90 Idx
= clang_createIndexWithOptions(&Opts
);
93 "clang_createIndexWithOptions() failed. "
94 "CINDEX_VERSION_MINOR = %d, sizeof(CXIndexOptions) = %u\n",
95 CINDEX_VERSION_MINOR
, Opts
.Size
);
100 /** Return the default parsing options. */
101 static unsigned getDefaultParsingOptions(void) {
102 unsigned options
= CXTranslationUnit_DetailedPreprocessingRecord
;
104 if (getenv("CINDEXTEST_EDITING"))
105 options
|= clang_defaultEditingTranslationUnitOptions();
106 if (getenv("CINDEXTEST_COMPLETION_CACHING"))
107 options
|= CXTranslationUnit_CacheCompletionResults
;
108 if (getenv("CINDEXTEST_COMPLETION_NO_CACHING"))
109 options
&= ~CXTranslationUnit_CacheCompletionResults
;
110 if (getenv("CINDEXTEST_SKIP_FUNCTION_BODIES"))
111 options
|= CXTranslationUnit_SkipFunctionBodies
;
112 if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
113 options
|= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion
;
114 if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE"))
115 options
|= CXTranslationUnit_CreatePreambleOnFirstParse
;
116 if (getenv("CINDEXTEST_KEEP_GOING"))
117 options
|= CXTranslationUnit_KeepGoing
;
118 if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE"))
119 options
|= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble
;
120 if (getenv("CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES"))
121 options
|= CXTranslationUnit_IncludeAttributedTypes
;
122 if (getenv("CINDEXTEST_VISIT_IMPLICIT_ATTRIBUTES"))
123 options
|= CXTranslationUnit_VisitImplicitAttributes
;
124 if (getenv("CINDEXTEST_IGNORE_NONERRORS_FROM_INCLUDED_FILES"))
125 options
|= CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles
;
130 static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy
) {
133 enum CXPrintingPolicyProperty property
;
135 struct Mapping mappings
[] = {
136 {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation
},
137 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS",
138 CXPrintingPolicy_SuppressSpecifiers
},
139 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD",
140 CXPrintingPolicy_SuppressTagKeyword
},
141 {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION",
142 CXPrintingPolicy_IncludeTagDefinition
},
143 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE",
144 CXPrintingPolicy_SuppressScope
},
145 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE",
146 CXPrintingPolicy_SuppressUnwrittenScope
},
147 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS",
148 CXPrintingPolicy_SuppressInitializers
},
149 {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN",
150 CXPrintingPolicy_ConstantArraySizeAsWritten
},
151 {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS",
152 CXPrintingPolicy_AnonymousTagLocations
},
153 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME",
154 CXPrintingPolicy_SuppressStrongLifetime
},
155 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS",
156 CXPrintingPolicy_SuppressLifetimeQualifiers
},
157 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS",
158 CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors
},
159 {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool
},
160 {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict
},
161 {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof
},
162 {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF",
163 CXPrintingPolicy_UnderscoreAlignof
},
164 {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS",
165 CXPrintingPolicy_UseVoidForZeroParams
},
166 {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput
},
167 {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION",
168 CXPrintingPolicy_PolishForDeclaration
},
169 {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half
},
170 {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar
},
171 {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES",
172 CXPrintingPolicy_IncludeNewlines
},
173 {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING",
174 CXPrintingPolicy_MSVCFormatting
},
175 {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN",
176 CXPrintingPolicy_ConstantsAsWritten
},
177 {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE",
178 CXPrintingPolicy_SuppressImplicitBase
},
179 {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME",
180 CXPrintingPolicy_FullyQualifiedName
},
184 for (i
= 0; i
< sizeof(mappings
) / sizeof(struct Mapping
); i
++) {
185 char *value
= getenv(mappings
[i
].name
);
187 clang_PrintingPolicy_setProperty(Policy
, mappings
[i
].property
,
188 (unsigned)strtoul(value
, 0L, 10));
193 /** Returns 0 in case of success, non-zero in case of a failure. */
194 static int checkForErrors(CXTranslationUnit TU
);
196 static void describeLibclangFailure(enum CXErrorCode Err
) {
198 case CXError_Success
:
199 fprintf(stderr
, "Success\n");
202 case CXError_Failure
:
203 fprintf(stderr
, "Failure (no details available)\n");
206 case CXError_Crashed
:
207 fprintf(stderr
, "Failure: libclang crashed\n");
210 case CXError_InvalidArguments
:
211 fprintf(stderr
, "Failure: invalid arguments passed to a libclang routine\n");
214 case CXError_ASTReadError
:
215 fprintf(stderr
, "Failure: AST deserialization error occurred\n");
220 static void PrintExtent(FILE *out
, unsigned begin_line
, unsigned begin_column
,
221 unsigned end_line
, unsigned end_column
) {
222 fprintf(out
, "[%d:%d - %d:%d]", begin_line
, begin_column
,
223 end_line
, end_column
);
226 static unsigned CreateTranslationUnit(CXIndex Idx
, const char *file
,
227 CXTranslationUnit
*TU
) {
228 enum CXErrorCode Err
= clang_createTranslationUnit2(Idx
, file
, TU
);
229 if (Err
!= CXError_Success
) {
230 fprintf(stderr
, "Unable to load translation unit from '%s'!\n", file
);
231 describeLibclangFailure(Err
);
238 void free_remapped_files(struct CXUnsavedFile
*unsaved_files
,
239 int num_unsaved_files
) {
241 for (i
= 0; i
!= num_unsaved_files
; ++i
) {
243 #pragma GCC diagnostic push
244 #pragma GCC diagnostic ignored "-Wcast-qual"
245 #elif defined(__clang__)
246 #pragma clang diagnostic push
247 #pragma clang diagnostic ignored "-Wcast-qual"
249 free((char *)unsaved_files
[i
].Filename
);
250 free((char *)unsaved_files
[i
].Contents
);
252 #pragma GCC diagnostic pop
253 #elif defined(__clang__)
254 #pragma clang diagnostic pop
260 static int parse_remapped_files_with_opt(const char *opt_name
,
261 int argc
, const char **argv
,
263 struct CXUnsavedFile
**unsaved_files
,
264 int *num_unsaved_files
) {
267 int prefix_len
= strlen(opt_name
);
270 *num_unsaved_files
= 0;
272 /* Count the number of remapped files. */
273 for (arg
= start_arg
; arg
< argc
; ++arg
) {
274 if (strncmp(argv
[arg
], opt_name
, prefix_len
))
277 assert(*num_unsaved_files
< (int)(sizeof(arg_indices
)/sizeof(int)));
278 arg_indices
[*num_unsaved_files
] = arg
;
279 ++*num_unsaved_files
;
282 if (*num_unsaved_files
== 0)
286 = (struct CXUnsavedFile
*)malloc(sizeof(struct CXUnsavedFile
) *
288 assert(*unsaved_files
);
289 for (i
= 0; i
!= *num_unsaved_files
; ++i
) {
290 struct CXUnsavedFile
*unsaved
= *unsaved_files
+ i
;
291 const char *arg_string
= argv
[arg_indices
[i
]] + prefix_len
;
296 const char *sep
= strchr(arg_string
, ',');
299 "error: %sfrom:to argument is missing comma\n", opt_name
);
300 free_remapped_files(*unsaved_files
, i
);
302 *num_unsaved_files
= 0;
306 /* Open the file that we're remapping to. */
307 to_file
= fopen(sep
+ 1, "rb");
309 fprintf(stderr
, "error: cannot open file %s that we are remapping to\n",
311 free_remapped_files(*unsaved_files
, i
);
313 *num_unsaved_files
= 0;
317 /* Determine the length of the file we're remapping to. */
318 fseek(to_file
, 0, SEEK_END
);
319 unsaved
->Length
= ftell(to_file
);
320 fseek(to_file
, 0, SEEK_SET
);
322 /* Read the contents of the file we're remapping to. */
323 contents
= (char *)malloc(unsaved
->Length
+ 1);
325 if (fread(contents
, 1, unsaved
->Length
, to_file
) != unsaved
->Length
) {
326 fprintf(stderr
, "error: unexpected %s reading 'to' file %s\n",
327 (feof(to_file
) ? "EOF" : "error"), sep
+ 1);
329 free_remapped_files(*unsaved_files
, i
);
332 *num_unsaved_files
= 0;
335 contents
[unsaved
->Length
] = 0;
336 unsaved
->Contents
= contents
;
338 /* Close the file. */
341 /* Copy the file name that we're remapping from. */
342 filename_len
= sep
- arg_string
;
343 filename
= (char *)malloc(filename_len
+ 1);
345 memcpy(filename
, arg_string
, filename_len
);
346 filename
[filename_len
] = 0;
347 unsaved
->Filename
= filename
;
353 static int parse_remapped_files(int argc
, const char **argv
, int start_arg
,
354 struct CXUnsavedFile
**unsaved_files
,
355 int *num_unsaved_files
) {
356 return parse_remapped_files_with_opt("-remap-file=", argc
, argv
, start_arg
,
357 unsaved_files
, num_unsaved_files
);
360 static int parse_remapped_files_with_try(int try_idx
,
361 int argc
, const char **argv
,
363 struct CXUnsavedFile
**unsaved_files
,
364 int *num_unsaved_files
) {
365 struct CXUnsavedFile
*unsaved_files_no_try_idx
;
366 int num_unsaved_files_no_try_idx
;
367 struct CXUnsavedFile
*unsaved_files_try_idx
;
368 int num_unsaved_files_try_idx
;
372 ret
= parse_remapped_files(argc
, argv
, start_arg
,
373 &unsaved_files_no_try_idx
, &num_unsaved_files_no_try_idx
);
377 sprintf(opt_name
, "-remap-file-%d=", try_idx
);
378 ret
= parse_remapped_files_with_opt(opt_name
, argc
, argv
, start_arg
,
379 &unsaved_files_try_idx
, &num_unsaved_files_try_idx
);
383 if (num_unsaved_files_no_try_idx
== 0) {
384 *unsaved_files
= unsaved_files_try_idx
;
385 *num_unsaved_files
= num_unsaved_files_try_idx
;
388 if (num_unsaved_files_try_idx
== 0) {
389 *unsaved_files
= unsaved_files_no_try_idx
;
390 *num_unsaved_files
= num_unsaved_files_no_try_idx
;
394 *num_unsaved_files
= num_unsaved_files_no_try_idx
+ num_unsaved_files_try_idx
;
396 = (struct CXUnsavedFile
*)realloc(unsaved_files_no_try_idx
,
397 sizeof(struct CXUnsavedFile
) *
399 assert(*unsaved_files
);
400 memcpy(*unsaved_files
+ num_unsaved_files_no_try_idx
,
401 unsaved_files_try_idx
, sizeof(struct CXUnsavedFile
) *
402 num_unsaved_files_try_idx
);
403 free(unsaved_files_try_idx
);
407 static const char *parse_comments_schema(int argc
, const char **argv
) {
408 const char *CommentsSchemaArg
= "-comments-xml-schema=";
409 const char *CommentSchemaFile
= NULL
;
412 return CommentSchemaFile
;
414 if (!strncmp(argv
[0], CommentsSchemaArg
, strlen(CommentsSchemaArg
)))
415 CommentSchemaFile
= argv
[0] + strlen(CommentsSchemaArg
);
417 return CommentSchemaFile
;
420 /******************************************************************************/
421 /* Pretty-printing. */
422 /******************************************************************************/
424 static const char *FileCheckPrefix
= "CHECK";
426 static void PrintCString(const char *CStr
) {
427 if (CStr
!= NULL
&& CStr
[0] != '\0') {
428 for ( ; *CStr
; ++CStr
) {
429 const char C
= *CStr
;
431 case '\n': printf("\\n"); break;
432 case '\r': printf("\\r"); break;
433 case '\t': printf("\\t"); break;
434 case '\v': printf("\\v"); break;
435 case '\f': printf("\\f"); break;
436 default: putchar(C
); break;
442 static void PrintCStringWithPrefix(const char *Prefix
, const char *CStr
) {
443 printf(" %s=[", Prefix
);
448 static void PrintCXStringAndDispose(CXString Str
) {
449 PrintCString(clang_getCString(Str
));
450 clang_disposeString(Str
);
453 static void PrintCXStringWithPrefix(const char *Prefix
, CXString Str
) {
454 PrintCStringWithPrefix(Prefix
, clang_getCString(Str
));
457 static void PrintCXStringWithPrefixAndDispose(const char *Prefix
,
459 PrintCStringWithPrefix(Prefix
, clang_getCString(Str
));
460 clang_disposeString(Str
);
463 static void PrintRange(CXSourceRange R
, const char *str
) {
464 CXFile begin_file
, end_file
;
465 unsigned begin_line
, begin_column
, end_line
, end_column
;
467 clang_getFileLocation(clang_getRangeStart(R
), &begin_file
, &begin_line
,
469 clang_getFileLocation(clang_getRangeEnd(R
), &end_file
, &end_line
, &end_column
,
471 if (!begin_file
|| !end_file
)
476 PrintExtent(stdout
, begin_line
, begin_column
, end_line
, end_column
);
479 static enum DisplayType
{
480 DisplayType_Spelling
,
481 DisplayType_DisplayName
,
483 } wanted_display_type
= DisplayType_Spelling
;
485 static void printVersion(const char *Prefix
, CXVersion Version
) {
486 if (Version
.Major
< 0)
488 printf("%s%d", Prefix
, Version
.Major
);
490 if (Version
.Minor
< 0)
492 printf(".%d", Version
.Minor
);
494 if (Version
.Subminor
< 0)
496 printf(".%d", Version
.Subminor
);
499 struct CommentASTDumpingContext
{
503 static void DumpCXCommentInternal(struct CommentASTDumpingContext
*Ctx
,
507 enum CXCommentKind Kind
= clang_Comment_getKind(Comment
);
510 for (i
= 0, e
= Ctx
->IndentLevel
; i
!= e
; ++i
)
516 printf("CXComment_Null");
519 printf("CXComment_Text");
520 PrintCXStringWithPrefixAndDispose("Text",
521 clang_TextComment_getText(Comment
));
522 if (clang_Comment_isWhitespace(Comment
))
523 printf(" IsWhitespace");
524 if (clang_InlineContentComment_hasTrailingNewline(Comment
))
525 printf(" HasTrailingNewline");
527 case CXComment_InlineCommand
:
528 printf("CXComment_InlineCommand");
529 PrintCXStringWithPrefixAndDispose(
531 clang_InlineCommandComment_getCommandName(Comment
));
532 switch (clang_InlineCommandComment_getRenderKind(Comment
)) {
533 case CXCommentInlineCommandRenderKind_Normal
:
534 printf(" RenderNormal");
536 case CXCommentInlineCommandRenderKind_Bold
:
537 printf(" RenderBold");
539 case CXCommentInlineCommandRenderKind_Monospaced
:
540 printf(" RenderMonospaced");
542 case CXCommentInlineCommandRenderKind_Emphasized
:
543 printf(" RenderEmphasized");
545 case CXCommentInlineCommandRenderKind_Anchor
:
546 printf(" RenderAnchor");
549 for (i
= 0, e
= clang_InlineCommandComment_getNumArgs(Comment
);
551 printf(" Arg[%u]=", i
);
552 PrintCXStringAndDispose(
553 clang_InlineCommandComment_getArgText(Comment
, i
));
555 if (clang_InlineContentComment_hasTrailingNewline(Comment
))
556 printf(" HasTrailingNewline");
558 case CXComment_HTMLStartTag
: {
560 printf("CXComment_HTMLStartTag");
561 PrintCXStringWithPrefixAndDispose(
563 clang_HTMLTagComment_getTagName(Comment
));
564 NumAttrs
= clang_HTMLStartTag_getNumAttrs(Comment
);
567 for (i
= 0; i
!= NumAttrs
; ++i
) {
569 PrintCXStringAndDispose(clang_HTMLStartTag_getAttrName(Comment
, i
));
571 PrintCXStringAndDispose(clang_HTMLStartTag_getAttrValue(Comment
, i
));
574 if (clang_HTMLStartTagComment_isSelfClosing(Comment
))
575 printf(" SelfClosing");
576 if (clang_InlineContentComment_hasTrailingNewline(Comment
))
577 printf(" HasTrailingNewline");
580 case CXComment_HTMLEndTag
:
581 printf("CXComment_HTMLEndTag");
582 PrintCXStringWithPrefixAndDispose(
584 clang_HTMLTagComment_getTagName(Comment
));
585 if (clang_InlineContentComment_hasTrailingNewline(Comment
))
586 printf(" HasTrailingNewline");
588 case CXComment_Paragraph
:
589 printf("CXComment_Paragraph");
590 if (clang_Comment_isWhitespace(Comment
))
591 printf(" IsWhitespace");
593 case CXComment_BlockCommand
:
594 printf("CXComment_BlockCommand");
595 PrintCXStringWithPrefixAndDispose(
597 clang_BlockCommandComment_getCommandName(Comment
));
598 for (i
= 0, e
= clang_BlockCommandComment_getNumArgs(Comment
);
600 printf(" Arg[%u]=", i
);
601 PrintCXStringAndDispose(
602 clang_BlockCommandComment_getArgText(Comment
, i
));
605 case CXComment_ParamCommand
:
606 printf("CXComment_ParamCommand");
607 switch (clang_ParamCommandComment_getDirection(Comment
)) {
608 case CXCommentParamPassDirection_In
:
611 case CXCommentParamPassDirection_Out
:
614 case CXCommentParamPassDirection_InOut
:
618 if (clang_ParamCommandComment_isDirectionExplicit(Comment
))
619 printf(" explicitly");
621 printf(" implicitly");
622 PrintCXStringWithPrefixAndDispose(
624 clang_ParamCommandComment_getParamName(Comment
));
625 if (clang_ParamCommandComment_isParamIndexValid(Comment
))
626 printf(" ParamIndex=%u", clang_ParamCommandComment_getParamIndex(Comment
));
628 printf(" ParamIndex=Invalid");
630 case CXComment_TParamCommand
:
631 printf("CXComment_TParamCommand");
632 PrintCXStringWithPrefixAndDispose(
634 clang_TParamCommandComment_getParamName(Comment
));
635 if (clang_TParamCommandComment_isParamPositionValid(Comment
)) {
636 printf(" ParamPosition={");
637 for (i
= 0, e
= clang_TParamCommandComment_getDepth(Comment
);
639 printf("%u", clang_TParamCommandComment_getIndex(Comment
, i
));
645 printf(" ParamPosition=Invalid");
647 case CXComment_VerbatimBlockCommand
:
648 printf("CXComment_VerbatimBlockCommand");
649 PrintCXStringWithPrefixAndDispose(
651 clang_BlockCommandComment_getCommandName(Comment
));
653 case CXComment_VerbatimBlockLine
:
654 printf("CXComment_VerbatimBlockLine");
655 PrintCXStringWithPrefixAndDispose(
657 clang_VerbatimBlockLineComment_getText(Comment
));
659 case CXComment_VerbatimLine
:
660 printf("CXComment_VerbatimLine");
661 PrintCXStringWithPrefixAndDispose(
663 clang_VerbatimLineComment_getText(Comment
));
665 case CXComment_FullComment
:
666 printf("CXComment_FullComment");
669 if (Kind
!= CXComment_Null
) {
670 const unsigned NumChildren
= clang_Comment_getNumChildren(Comment
);
672 for (i
= 0; i
!= NumChildren
; ++i
) {
673 printf("\n// %s: ", FileCheckPrefix
);
674 DumpCXCommentInternal(Ctx
, clang_Comment_getChild(Comment
, i
));
681 static void DumpCXComment(CXComment Comment
) {
682 struct CommentASTDumpingContext Ctx
;
684 printf("\n// %s: CommentAST=[\n// %s:", FileCheckPrefix
, FileCheckPrefix
);
685 DumpCXCommentInternal(&Ctx
, Comment
);
689 static void ValidateCommentXML(const char *Str
, const char *CommentSchemaFile
) {
690 #ifdef CLANG_HAVE_LIBXML
691 xmlRelaxNGParserCtxtPtr RNGParser
;
692 xmlRelaxNGPtr Schema
;
694 xmlRelaxNGValidCtxtPtr ValidationCtxt
;
697 if (!CommentSchemaFile
)
700 RNGParser
= xmlRelaxNGNewParserCtxt(CommentSchemaFile
);
702 printf(" libXMLError");
705 Schema
= xmlRelaxNGParse(RNGParser
);
707 Doc
= xmlParseDoc((const xmlChar
*) Str
);
710 const xmlError
*Error
= xmlGetLastError();
711 printf(" CommentXMLInvalid [not well-formed XML: %s]", Error
->message
);
715 ValidationCtxt
= xmlRelaxNGNewValidCtxt(Schema
);
716 status
= xmlRelaxNGValidateDoc(ValidationCtxt
, Doc
);
718 printf(" CommentXMLValid");
719 else if (status
> 0) {
720 const xmlError
*Error
= xmlGetLastError();
721 printf(" CommentXMLInvalid [not valid XML: %s]", Error
->message
);
723 printf(" libXMLError");
725 xmlRelaxNGFreeValidCtxt(ValidationCtxt
);
727 xmlRelaxNGFree(Schema
);
728 xmlRelaxNGFreeParserCtxt(RNGParser
);
732 static void PrintCursorComments(CXCursor Cursor
,
733 const char *CommentSchemaFile
) {
736 const char *RawCommentCString
;
737 CXString BriefComment
;
738 const char *BriefCommentCString
;
740 RawComment
= clang_Cursor_getRawCommentText(Cursor
);
741 RawCommentCString
= clang_getCString(RawComment
);
742 if (RawCommentCString
!= NULL
&& RawCommentCString
[0] != '\0') {
743 PrintCStringWithPrefix("RawComment", RawCommentCString
);
744 PrintRange(clang_Cursor_getCommentRange(Cursor
), "RawCommentRange");
746 BriefComment
= clang_Cursor_getBriefCommentText(Cursor
);
747 BriefCommentCString
= clang_getCString(BriefComment
);
748 if (BriefCommentCString
!= NULL
&& BriefCommentCString
[0] != '\0')
749 PrintCStringWithPrefix("BriefComment", BriefCommentCString
);
750 clang_disposeString(BriefComment
);
752 clang_disposeString(RawComment
);
756 CXComment Comment
= clang_Cursor_getParsedComment(Cursor
);
757 if (clang_Comment_getKind(Comment
) != CXComment_Null
) {
758 PrintCXStringWithPrefixAndDispose("FullCommentAsHTML",
759 clang_FullComment_getAsHTML(Comment
));
762 XML
= clang_FullComment_getAsXML(Comment
);
763 PrintCXStringWithPrefix("FullCommentAsXML", XML
);
764 ValidateCommentXML(clang_getCString(XML
), CommentSchemaFile
);
765 clang_disposeString(XML
);
768 DumpCXComment(Comment
);
778 static int lineCol_cmp(const void *p1
, const void *p2
) {
779 const LineCol
*lhs
= p1
;
780 const LineCol
*rhs
= p2
;
781 if (lhs
->line
!= rhs
->line
)
782 return (int)lhs
->line
- (int)rhs
->line
;
783 return (int)lhs
->col
- (int)rhs
->col
;
786 static CXString
CursorToText(CXCursor Cursor
) {
788 switch (wanted_display_type
) {
789 case DisplayType_Spelling
:
790 return clang_getCursorSpelling(Cursor
);
791 case DisplayType_DisplayName
:
792 return clang_getCursorDisplayName(Cursor
);
793 case DisplayType_Pretty
: {
794 CXPrintingPolicy Policy
= clang_getCursorPrintingPolicy(Cursor
);
795 ModifyPrintingPolicyAccordingToEnv(Policy
);
796 text
= clang_getCursorPrettyPrinted(Cursor
, Policy
);
797 clang_PrintingPolicy_dispose(Policy
);
801 assert(0 && "unknown display type"); /* no llvm_unreachable in C. */
802 /* Set to NULL to prevent uninitialized variable warnings. */
804 text
.private_flags
= 0;
808 static void PrintCursor(CXCursor Cursor
, const char *CommentSchemaFile
) {
809 CXTranslationUnit TU
= clang_Cursor_getTranslationUnit(Cursor
);
810 if (clang_isInvalid(Cursor
.kind
)) {
811 CXString ks
= clang_getCursorKindSpelling(Cursor
.kind
);
812 printf("Invalid Cursor => %s", clang_getCString(ks
));
813 clang_disposeString(ks
);
818 unsigned line
, column
;
819 CXCursor SpecializationOf
;
820 CXCursor
*overridden
;
821 unsigned num_overridden
;
822 unsigned RefNameRangeNr
;
823 CXSourceRange CursorExtent
;
824 CXSourceRange RefNameRange
;
825 int AlwaysUnavailable
;
826 int AlwaysDeprecated
;
827 CXString UnavailableMessage
;
828 CXString DeprecatedMessage
;
829 CXPlatformAvailability PlatformAvailability
[2];
830 int NumPlatformAvailability
;
833 ks
= clang_getCursorKindSpelling(Cursor
.kind
);
834 string
= CursorToText(Cursor
);
835 printf("%s=%s", clang_getCString(ks
),
836 clang_getCString(string
));
837 clang_disposeString(ks
);
838 clang_disposeString(string
);
840 Referenced
= clang_getCursorReferenced(Cursor
);
841 if (!clang_equalCursors(Referenced
, clang_getNullCursor())) {
842 if (clang_getCursorKind(Referenced
) == CXCursor_OverloadedDeclRef
) {
843 unsigned I
, N
= clang_getNumOverloadedDecls(Referenced
);
845 for (I
= 0; I
!= N
; ++I
) {
846 CXCursor Ovl
= clang_getOverloadedDecl(Referenced
, I
);
847 CXSourceLocation Loc
;
851 Loc
= clang_getCursorLocation(Ovl
);
852 clang_getFileLocation(Loc
, 0, &line
, &column
, 0);
853 printf("%d:%d", line
, column
);
857 CXSourceLocation Loc
= clang_getCursorLocation(Referenced
);
858 clang_getFileLocation(Loc
, 0, &line
, &column
, 0);
859 printf(":%d:%d", line
, column
);
862 if (clang_getCursorKind(Referenced
) == CXCursor_TypedefDecl
) {
863 CXType T
= clang_getCursorType(Referenced
);
864 if (clang_Type_isTransparentTagTypedef(T
)) {
865 CXType Underlying
= clang_getTypedefDeclUnderlyingType(Referenced
);
866 CXString S
= clang_getTypeSpelling(Underlying
);
867 printf(" (Transparent: %s)", clang_getCString(S
));
868 clang_disposeString(S
);
873 if (clang_isCursorDefinition(Cursor
))
874 printf(" (Definition)");
876 switch (clang_getCursorAvailability(Cursor
)) {
877 case CXAvailability_Available
:
880 case CXAvailability_Deprecated
:
881 printf(" (deprecated)");
884 case CXAvailability_NotAvailable
:
885 printf(" (unavailable)");
888 case CXAvailability_NotAccessible
:
889 printf(" (inaccessible)");
893 NumPlatformAvailability
894 = clang_getCursorPlatformAvailability(Cursor
,
899 PlatformAvailability
, 2);
900 if (AlwaysUnavailable
) {
901 printf(" (always unavailable: \"%s\")",
902 clang_getCString(UnavailableMessage
));
903 } else if (AlwaysDeprecated
) {
904 printf(" (always deprecated: \"%s\")",
905 clang_getCString(DeprecatedMessage
));
907 for (I
= 0; I
!= NumPlatformAvailability
; ++I
) {
911 printf(" (%s", clang_getCString(PlatformAvailability
[I
].Platform
));
912 if (PlatformAvailability
[I
].Unavailable
)
913 printf(", unavailable");
915 printVersion(", introduced=", PlatformAvailability
[I
].Introduced
);
916 printVersion(", deprecated=", PlatformAvailability
[I
].Deprecated
);
917 printVersion(", obsoleted=", PlatformAvailability
[I
].Obsoleted
);
919 if (clang_getCString(PlatformAvailability
[I
].Message
)[0])
920 printf(", message=\"%s\"",
921 clang_getCString(PlatformAvailability
[I
].Message
));
925 for (I
= 0; I
!= NumPlatformAvailability
; ++I
) {
928 clang_disposeCXPlatformAvailability(PlatformAvailability
+ I
);
931 clang_disposeString(DeprecatedMessage
);
932 clang_disposeString(UnavailableMessage
);
934 if (clang_CXXConstructor_isDefaultConstructor(Cursor
))
935 printf(" (default constructor)");
937 if (clang_CXXConstructor_isMoveConstructor(Cursor
))
938 printf(" (move constructor)");
939 if (clang_CXXConstructor_isCopyConstructor(Cursor
))
940 printf(" (copy constructor)");
941 if (clang_CXXConstructor_isConvertingConstructor(Cursor
))
942 printf(" (converting constructor)");
943 if (clang_CXXField_isMutable(Cursor
))
944 printf(" (mutable)");
945 if (clang_CXXMethod_isDefaulted(Cursor
))
946 printf(" (defaulted)");
947 if (clang_CXXMethod_isDeleted(Cursor
))
948 printf(" (deleted)");
949 if (clang_CXXMethod_isStatic(Cursor
))
951 if (clang_CXXMethod_isVirtual(Cursor
))
952 printf(" (virtual)");
953 if (clang_CXXMethod_isConst(Cursor
))
955 if (clang_CXXMethod_isPureVirtual(Cursor
))
957 if (clang_CXXMethod_isCopyAssignmentOperator(Cursor
))
958 printf(" (copy-assignment operator)");
959 if (clang_CXXMethod_isMoveAssignmentOperator(Cursor
))
960 printf(" (move-assignment operator)");
961 if (clang_CXXMethod_isExplicit(Cursor
))
962 printf(" (explicit)");
963 if (clang_CXXRecord_isAbstract(Cursor
))
964 printf(" (abstract)");
965 if (clang_EnumDecl_isScoped(Cursor
))
967 if (clang_Cursor_isVariadic(Cursor
))
968 printf(" (variadic)");
969 if (clang_Cursor_isObjCOptional(Cursor
))
970 printf(" (@optional)");
971 if (clang_isInvalidDeclaration(Cursor
))
972 printf(" (invalid)");
974 switch (clang_getCursorExceptionSpecificationType(Cursor
))
976 case CXCursor_ExceptionSpecificationKind_None
:
979 case CXCursor_ExceptionSpecificationKind_DynamicNone
:
980 printf(" (noexcept dynamic none)");
983 case CXCursor_ExceptionSpecificationKind_Dynamic
:
984 printf(" (noexcept dynamic)");
987 case CXCursor_ExceptionSpecificationKind_MSAny
:
988 printf(" (noexcept dynamic any)");
991 case CXCursor_ExceptionSpecificationKind_BasicNoexcept
:
992 printf(" (noexcept)");
995 case CXCursor_ExceptionSpecificationKind_ComputedNoexcept
:
996 printf(" (computed-noexcept)");
999 case CXCursor_ExceptionSpecificationKind_Unevaluated
:
1000 case CXCursor_ExceptionSpecificationKind_Uninstantiated
:
1001 case CXCursor_ExceptionSpecificationKind_Unparsed
:
1009 if (clang_Cursor_isExternalSymbol(Cursor
, &language
, &definedIn
,
1011 printf(" (external lang: %s, defined: %s, gen: %d)",
1012 clang_getCString(language
), clang_getCString(definedIn
), generated
);
1013 clang_disposeString(language
);
1014 clang_disposeString(definedIn
);
1018 if (Cursor
.kind
== CXCursor_IBOutletCollectionAttr
) {
1020 clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor
));
1021 CXString S
= clang_getTypeKindSpelling(T
.kind
);
1022 printf(" [IBOutletCollection=%s]", clang_getCString(S
));
1023 clang_disposeString(S
);
1026 if (Cursor
.kind
== CXCursor_CXXBaseSpecifier
) {
1027 enum CX_CXXAccessSpecifier access
= clang_getCXXAccessSpecifier(Cursor
);
1028 unsigned isVirtual
= clang_isVirtualBase(Cursor
);
1029 const char *accessStr
= 0;
1032 case CX_CXXInvalidAccessSpecifier
:
1033 accessStr
= "invalid"; break;
1035 accessStr
= "public"; break;
1036 case CX_CXXProtected
:
1037 accessStr
= "protected"; break;
1039 accessStr
= "private"; break;
1042 printf(" [access=%s isVirtual=%s]", accessStr
,
1043 isVirtual
? "true" : "false");
1046 SpecializationOf
= clang_getSpecializedCursorTemplate(Cursor
);
1047 if (!clang_equalCursors(SpecializationOf
, clang_getNullCursor())) {
1048 CXSourceLocation Loc
= clang_getCursorLocation(SpecializationOf
);
1049 CXString Name
= clang_getCursorSpelling(SpecializationOf
);
1050 clang_getFileLocation(Loc
, 0, &line
, &column
, 0);
1051 printf(" [Specialization of %s:%d:%d]",
1052 clang_getCString(Name
), line
, column
);
1053 clang_disposeString(Name
);
1055 if (Cursor
.kind
== CXCursor_FunctionDecl
1056 || Cursor
.kind
== CXCursor_StructDecl
1057 || Cursor
.kind
== CXCursor_ClassDecl
1058 || Cursor
.kind
== CXCursor_ClassTemplatePartialSpecialization
) {
1059 /* Collect the template parameter kinds from the base template. */
1060 int NumTemplateArgs
= clang_Cursor_getNumTemplateArguments(Cursor
);
1062 if (NumTemplateArgs
< 0) {
1063 printf(" [no template arg info]");
1065 for (I
= 0; I
< NumTemplateArgs
; I
++) {
1066 enum CXTemplateArgumentKind TAK
=
1067 clang_Cursor_getTemplateArgumentKind(Cursor
, I
);
1069 case CXTemplateArgumentKind_Type
:
1071 CXType T
= clang_Cursor_getTemplateArgumentType(Cursor
, I
);
1072 CXString S
= clang_getTypeSpelling(T
);
1073 printf(" [Template arg %d: kind: %d, type: %s]",
1074 I
, TAK
, clang_getCString(S
));
1075 clang_disposeString(S
);
1078 case CXTemplateArgumentKind_Integral
:
1079 printf(" [Template arg %d: kind: %d, intval: %lld]",
1080 I
, TAK
, clang_Cursor_getTemplateArgumentValue(Cursor
, I
));
1083 printf(" [Template arg %d: kind: %d]\n", I
, TAK
);
1089 clang_getOverriddenCursors(Cursor
, &overridden
, &num_overridden
);
1090 if (num_overridden
) {
1092 LineCol lineCols
[50];
1093 assert(num_overridden
<= 50);
1094 printf(" [Overrides ");
1095 for (I
= 0; I
!= num_overridden
; ++I
) {
1096 CXSourceLocation Loc
= clang_getCursorLocation(overridden
[I
]);
1097 clang_getFileLocation(Loc
, 0, &line
, &column
, 0);
1098 lineCols
[I
].line
= line
;
1099 lineCols
[I
].col
= column
;
1101 /* Make the order of the override list deterministic. */
1102 qsort(lineCols
, num_overridden
, sizeof(LineCol
), lineCol_cmp
);
1103 for (I
= 0; I
!= num_overridden
; ++I
) {
1106 printf("@%d:%d", lineCols
[I
].line
, lineCols
[I
].col
);
1109 clang_disposeOverriddenCursors(overridden
);
1112 if (Cursor
.kind
== CXCursor_InclusionDirective
) {
1113 CXFile File
= clang_getIncludedFile(Cursor
);
1114 CXString Included
= clang_getFileName(File
);
1115 const char *IncludedString
= clang_getCString(Included
);
1116 printf(" (%s)", IncludedString
? IncludedString
: "(null)");
1117 clang_disposeString(Included
);
1119 if (clang_isFileMultipleIncludeGuarded(TU
, File
))
1120 printf(" [multi-include guarded]");
1123 CursorExtent
= clang_getCursorExtent(Cursor
);
1124 RefNameRange
= clang_getCursorReferenceNameRange(Cursor
,
1125 CXNameRange_WantQualifier
1126 | CXNameRange_WantSinglePiece
1127 | CXNameRange_WantTemplateArgs
,
1129 if (!clang_equalRanges(CursorExtent
, RefNameRange
))
1130 PrintRange(RefNameRange
, "SingleRefName");
1132 for (RefNameRangeNr
= 0; 1; RefNameRangeNr
++) {
1133 RefNameRange
= clang_getCursorReferenceNameRange(Cursor
,
1134 CXNameRange_WantQualifier
1135 | CXNameRange_WantTemplateArgs
,
1137 if (clang_equalRanges(clang_getNullRange(), RefNameRange
))
1139 if (!clang_equalRanges(CursorExtent
, RefNameRange
))
1140 PrintRange(RefNameRange
, "RefName");
1143 PrintCursorComments(Cursor
, CommentSchemaFile
);
1146 unsigned PropAttrs
= clang_Cursor_getObjCPropertyAttributes(Cursor
, 0);
1147 if (PropAttrs
!= CXObjCPropertyAttr_noattr
) {
1149 #define PRINT_PROP_ATTR(A) \
1150 if (PropAttrs & CXObjCPropertyAttr_##A) printf(#A ",")
1151 PRINT_PROP_ATTR(readonly
);
1152 PRINT_PROP_ATTR(getter
);
1153 PRINT_PROP_ATTR(assign
);
1154 PRINT_PROP_ATTR(readwrite
);
1155 PRINT_PROP_ATTR(retain
);
1156 PRINT_PROP_ATTR(copy
);
1157 PRINT_PROP_ATTR(nonatomic
);
1158 PRINT_PROP_ATTR(setter
);
1159 PRINT_PROP_ATTR(atomic
);
1160 PRINT_PROP_ATTR(weak
);
1161 PRINT_PROP_ATTR(strong
);
1162 PRINT_PROP_ATTR(unsafe_unretained
);
1163 PRINT_PROP_ATTR(class);
1168 if (Cursor
.kind
== CXCursor_ObjCPropertyDecl
) {
1169 CXString Name
= clang_Cursor_getObjCPropertyGetterName(Cursor
);
1170 CXString Spelling
= clang_getCursorSpelling(Cursor
);
1171 const char *CName
= clang_getCString(Name
);
1172 const char *CSpelling
= clang_getCString(Spelling
);
1173 if (CName
&& strcmp(CName
, CSpelling
)) {
1174 printf(" (getter=%s)", CName
);
1176 clang_disposeString(Spelling
);
1177 clang_disposeString(Name
);
1180 if (Cursor
.kind
== CXCursor_ObjCPropertyDecl
) {
1181 CXString Name
= clang_Cursor_getObjCPropertySetterName(Cursor
);
1182 CXString Spelling
= clang_getCursorSpelling(Cursor
);
1183 const char *CName
= clang_getCString(Name
);
1184 const char *CSpelling
= clang_getCString(Spelling
);
1185 char *DefaultSetter
= malloc(strlen(CSpelling
) + 5);
1186 sprintf(DefaultSetter
, "set%s:", CSpelling
);
1187 DefaultSetter
[3] &= ~(1 << 5); /* Make uppercase */
1188 if (CName
&& strcmp(CName
, DefaultSetter
)) {
1189 printf(" (setter=%s)", CName
);
1191 free(DefaultSetter
);
1192 clang_disposeString(Spelling
);
1193 clang_disposeString(Name
);
1197 unsigned QT
= clang_Cursor_getObjCDeclQualifiers(Cursor
);
1198 if (QT
!= CXObjCDeclQualifier_None
) {
1200 #define PRINT_OBJC_QUAL(A) \
1201 if (QT & CXObjCDeclQualifier_##A) printf(#A ",")
1202 PRINT_OBJC_QUAL(In
);
1203 PRINT_OBJC_QUAL(Inout
);
1204 PRINT_OBJC_QUAL(Out
);
1205 PRINT_OBJC_QUAL(Bycopy
);
1206 PRINT_OBJC_QUAL(Byref
);
1207 PRINT_OBJC_QUAL(Oneway
);
1214 static const char* GetCursorSource(CXCursor Cursor
) {
1215 CXSourceLocation Loc
= clang_getCursorLocation(Cursor
);
1218 clang_getExpansionLocation(Loc
, &file
, 0, 0, 0);
1219 source
= clang_getFileName(file
);
1220 if (!clang_getCString(source
)) {
1221 clang_disposeString(source
);
1222 return "<invalid loc>";
1225 const char *b
= basename(clang_getCString(source
));
1226 clang_disposeString(source
);
1231 static CXString
createCXString(const char *CS
) {
1233 Str
.data
= (const void *) CS
;
1234 Str
.private_flags
= 0;
1238 /******************************************************************************/
1240 /******************************************************************************/
1242 typedef void (*PostVisitTU
)(CXTranslationUnit
);
1244 void PrintDiagnostic(CXDiagnostic Diagnostic
) {
1248 unsigned display_opts
= CXDiagnostic_DisplaySourceLocation
1249 | CXDiagnostic_DisplayColumn
| CXDiagnostic_DisplaySourceRanges
1250 | CXDiagnostic_DisplayOption
;
1251 unsigned i
, num_fixits
;
1253 if (clang_getDiagnosticSeverity(Diagnostic
) == CXDiagnostic_Ignored
)
1256 Msg
= clang_formatDiagnostic(Diagnostic
, display_opts
);
1257 fprintf(stderr
, "%s\n", clang_getCString(Msg
));
1258 clang_disposeString(Msg
);
1260 clang_getFileLocation(clang_getDiagnosticLocation(Diagnostic
), &file
, 0, 0,
1265 num_fixits
= clang_getDiagnosticNumFixIts(Diagnostic
);
1266 fprintf(stderr
, "Number FIX-ITs = %d\n", num_fixits
);
1267 for (i
= 0; i
!= num_fixits
; ++i
) {
1268 CXSourceRange range
;
1269 CXString insertion_text
= clang_getDiagnosticFixIt(Diagnostic
, i
, &range
);
1270 CXSourceLocation start
= clang_getRangeStart(range
);
1271 CXSourceLocation end
= clang_getRangeEnd(range
);
1272 unsigned start_line
, start_column
, end_line
, end_column
;
1273 CXFile start_file
, end_file
;
1274 clang_getFileLocation(start
, &start_file
, &start_line
, &start_column
, 0);
1275 clang_getFileLocation(end
, &end_file
, &end_line
, &end_column
, 0);
1276 if (clang_equalLocations(start
, end
)) {
1278 if (start_file
== file
)
1279 fprintf(out
, "FIX-IT: Insert \"%s\" at %d:%d\n",
1280 clang_getCString(insertion_text
), start_line
, start_column
);
1281 } else if (strcmp(clang_getCString(insertion_text
), "") == 0) {
1283 if (start_file
== file
&& end_file
== file
) {
1284 fprintf(out
, "FIX-IT: Remove ");
1285 PrintExtent(out
, start_line
, start_column
, end_line
, end_column
);
1290 if (start_file
== end_file
) {
1291 fprintf(out
, "FIX-IT: Replace ");
1292 PrintExtent(out
, start_line
, start_column
, end_line
, end_column
);
1293 fprintf(out
, " with \"%s\"\n", clang_getCString(insertion_text
));
1296 clang_disposeString(insertion_text
);
1300 void PrintDiagnosticSet(CXDiagnosticSet Set
) {
1301 int i
= 0, n
= clang_getNumDiagnosticsInSet(Set
);
1302 for ( ; i
!= n
; ++i
) {
1303 CXDiagnostic Diag
= clang_getDiagnosticInSet(Set
, i
);
1304 CXDiagnosticSet ChildDiags
= clang_getChildDiagnostics(Diag
);
1305 PrintDiagnostic(Diag
);
1307 PrintDiagnosticSet(ChildDiags
);
1311 void PrintDiagnostics(CXTranslationUnit TU
) {
1312 CXDiagnosticSet TUSet
= clang_getDiagnosticSetFromTU(TU
);
1313 PrintDiagnosticSet(TUSet
);
1314 clang_disposeDiagnosticSet(TUSet
);
1317 void PrintMemoryUsage(CXTranslationUnit TU
) {
1318 unsigned long total
= 0;
1320 CXTUResourceUsage usage
= clang_getCXTUResourceUsage(TU
);
1321 fprintf(stderr
, "Memory usage:\n");
1322 for (i
= 0 ; i
!= usage
.numEntries
; ++i
) {
1323 const char *name
= clang_getTUResourceUsageName(usage
.entries
[i
].kind
);
1324 unsigned long amount
= usage
.entries
[i
].amount
;
1326 fprintf(stderr
, " %s : %ld bytes (%f MBytes)\n", name
, amount
,
1327 ((double) amount
)/(1024*1024));
1329 fprintf(stderr
, " TOTAL = %ld bytes (%f MBytes)\n", total
,
1330 ((double) total
)/(1024*1024));
1331 clang_disposeCXTUResourceUsage(usage
);
1334 /******************************************************************************/
1335 /* Logic for testing traversal. */
1336 /******************************************************************************/
1338 static void PrintCursorExtent(CXCursor C
) {
1339 CXSourceRange extent
= clang_getCursorExtent(C
);
1340 PrintRange(extent
, "Extent");
1343 /* Data used by the visitors. */
1345 CXTranslationUnit TU
;
1346 enum CXCursorKind
*Filter
;
1347 const char *CommentSchemaFile
;
1351 enum CXChildVisitResult
FilteredPrintingVisitor(CXCursor Cursor
,
1353 CXClientData ClientData
) {
1354 VisitorData
*Data
= (VisitorData
*)ClientData
;
1355 if (!Data
->Filter
|| (Cursor
.kind
== *(enum CXCursorKind
*)Data
->Filter
)) {
1356 CXSourceLocation Loc
= clang_getCursorLocation(Cursor
);
1357 unsigned line
, column
;
1358 clang_getFileLocation(Loc
, 0, &line
, &column
, 0);
1359 printf("// %s: %s:%d:%d: ", FileCheckPrefix
,
1360 GetCursorSource(Cursor
), line
, column
);
1361 PrintCursor(Cursor
, Data
->CommentSchemaFile
);
1362 PrintCursorExtent(Cursor
);
1363 if (clang_isDeclaration(Cursor
.kind
)) {
1364 enum CX_CXXAccessSpecifier access
= clang_getCXXAccessSpecifier(Cursor
);
1365 const char *accessStr
= 0;
1368 case CX_CXXInvalidAccessSpecifier
: break;
1370 accessStr
= "public"; break;
1371 case CX_CXXProtected
:
1372 accessStr
= "protected"; break;
1374 accessStr
= "private"; break;
1378 printf(" [access=%s]", accessStr
);
1381 return CXChildVisit_Recurse
;
1384 return CXChildVisit_Continue
;
1387 static enum CXChildVisitResult
FunctionScanVisitor(CXCursor Cursor
,
1389 CXClientData ClientData
) {
1390 const char *startBuf
, *endBuf
;
1391 unsigned startLine
, startColumn
, endLine
, endColumn
, curLine
, curColumn
;
1393 VisitorData
*Data
= (VisitorData
*)ClientData
;
1395 if (Cursor
.kind
!= CXCursor_FunctionDecl
||
1396 !clang_isCursorDefinition(Cursor
))
1397 return CXChildVisit_Continue
;
1399 clang_getDefinitionSpellingAndExtent(Cursor
, &startBuf
, &endBuf
,
1400 &startLine
, &startColumn
,
1401 &endLine
, &endColumn
);
1402 /* Probe the entire body, looking for both decls and refs. */
1403 curLine
= startLine
;
1404 curColumn
= startColumn
;
1406 while (startBuf
< endBuf
) {
1407 CXSourceLocation Loc
;
1411 if (*startBuf
== '\n') {
1415 } else if (*startBuf
!= '\t')
1418 Loc
= clang_getCursorLocation(Cursor
);
1419 clang_getFileLocation(Loc
, &file
, 0, 0, 0);
1421 source
= clang_getFileName(file
);
1422 if (clang_getCString(source
)) {
1423 CXSourceLocation RefLoc
1424 = clang_getLocation(Data
->TU
, file
, curLine
, curColumn
);
1425 Ref
= clang_getCursor(Data
->TU
, RefLoc
);
1426 if (Ref
.kind
== CXCursor_NoDeclFound
) {
1427 /* Nothing found here; that's fine. */
1428 } else if (Ref
.kind
!= CXCursor_FunctionDecl
) {
1429 printf("// %s: %s:%d:%d: ", FileCheckPrefix
, GetCursorSource(Ref
),
1430 curLine
, curColumn
);
1431 PrintCursor(Ref
, Data
->CommentSchemaFile
);
1435 clang_disposeString(source
);
1439 return CXChildVisit_Continue
;
1442 /******************************************************************************/
1444 /******************************************************************************/
1446 enum CXChildVisitResult
USRVisitor(CXCursor C
, CXCursor parent
,
1447 CXClientData ClientData
) {
1448 VisitorData
*Data
= (VisitorData
*)ClientData
;
1449 if (!Data
->Filter
|| (C
.kind
== *(enum CXCursorKind
*)Data
->Filter
)) {
1450 CXString USR
= clang_getCursorUSR(C
);
1451 const char *cstr
= clang_getCString(USR
);
1452 if (!cstr
|| cstr
[0] == '\0') {
1453 clang_disposeString(USR
);
1454 return CXChildVisit_Recurse
;
1456 printf("// %s: %s %s", FileCheckPrefix
, GetCursorSource(C
), cstr
);
1458 PrintCursorExtent(C
);
1460 clang_disposeString(USR
);
1462 return CXChildVisit_Recurse
;
1465 return CXChildVisit_Continue
;
1468 /******************************************************************************/
1469 /* Inclusion stack testing. */
1470 /******************************************************************************/
1472 void InclusionVisitor(CXFile includedFile
, CXSourceLocation
*includeStack
,
1473 unsigned includeStackLen
, CXClientData data
) {
1478 fname
= clang_getFileName(includedFile
);
1479 printf("file: %s\nincluded by:\n", clang_getCString(fname
));
1480 clang_disposeString(fname
);
1482 for (i
= 0; i
< includeStackLen
; ++i
) {
1483 CXFile includingFile
;
1484 unsigned line
, column
;
1485 clang_getFileLocation(includeStack
[i
], &includingFile
, &line
, &column
, 0);
1486 fname
= clang_getFileName(includingFile
);
1487 printf(" %s:%d:%d\n", clang_getCString(fname
), line
, column
);
1488 clang_disposeString(fname
);
1493 void PrintInclusionStack(CXTranslationUnit TU
) {
1494 clang_getInclusions(TU
, InclusionVisitor
, NULL
);
1497 /******************************************************************************/
1498 /* Linkage testing. */
1499 /******************************************************************************/
1501 static enum CXChildVisitResult
PrintLinkage(CXCursor cursor
, CXCursor p
,
1503 const char *linkage
= 0;
1505 if (clang_isInvalid(clang_getCursorKind(cursor
)))
1506 return CXChildVisit_Recurse
;
1508 switch (clang_getCursorLinkage(cursor
)) {
1509 case CXLinkage_Invalid
: break;
1510 case CXLinkage_NoLinkage
: linkage
= "NoLinkage"; break;
1511 case CXLinkage_Internal
: linkage
= "Internal"; break;
1512 case CXLinkage_UniqueExternal
: linkage
= "UniqueExternal"; break;
1513 case CXLinkage_External
: linkage
= "External"; break;
1517 PrintCursor(cursor
, NULL
);
1518 printf("linkage=%s\n", linkage
);
1521 return CXChildVisit_Recurse
;
1524 /******************************************************************************/
1525 /* Visibility testing. */
1526 /******************************************************************************/
1528 static enum CXChildVisitResult
PrintVisibility(CXCursor cursor
, CXCursor p
,
1530 const char *visibility
= 0;
1532 if (clang_isInvalid(clang_getCursorKind(cursor
)))
1533 return CXChildVisit_Recurse
;
1535 switch (clang_getCursorVisibility(cursor
)) {
1536 case CXVisibility_Invalid
: break;
1537 case CXVisibility_Hidden
: visibility
= "Hidden"; break;
1538 case CXVisibility_Protected
: visibility
= "Protected"; break;
1539 case CXVisibility_Default
: visibility
= "Default"; break;
1543 PrintCursor(cursor
, NULL
);
1544 printf("visibility=%s\n", visibility
);
1547 return CXChildVisit_Recurse
;
1550 /******************************************************************************/
1551 /* Typekind testing. */
1552 /******************************************************************************/
1554 static void PrintTypeAndTypeKind(CXType T
, const char *Format
) {
1555 CXString TypeSpelling
, TypeKindSpelling
;
1557 TypeSpelling
= clang_getTypeSpelling(T
);
1558 TypeKindSpelling
= clang_getTypeKindSpelling(T
.kind
);
1560 clang_getCString(TypeSpelling
),
1561 clang_getCString(TypeKindSpelling
));
1562 clang_disposeString(TypeSpelling
);
1563 clang_disposeString(TypeKindSpelling
);
1566 static enum CXVisitorResult
FieldVisitor(CXCursor C
,
1567 CXClientData client_data
) {
1568 (*(int *) client_data
)+=1;
1569 return CXVisit_Continue
;
1572 static void PrintTypeTemplateArgs(CXType T
, const char *Format
) {
1573 int NumTArgs
= clang_Type_getNumTemplateArguments(T
);
1574 if (NumTArgs
!= -1 && NumTArgs
!= 0) {
1577 printf(Format
, NumTArgs
);
1578 for (i
= 0; i
< NumTArgs
; ++i
) {
1579 TArg
= clang_Type_getTemplateArgumentAsType(T
, i
);
1580 if (TArg
.kind
!= CXType_Invalid
) {
1581 PrintTypeAndTypeKind(TArg
, " [type=%s] [typekind=%s]");
1584 /* Ensure that the returned type is invalid when indexing off-by-one. */
1585 TArg
= clang_Type_getTemplateArgumentAsType(T
, i
);
1586 assert(TArg
.kind
== CXType_Invalid
);
1591 static void PrintNullabilityKind(CXType T
, const char *Format
) {
1592 enum CXTypeNullabilityKind N
= clang_Type_getNullability(T
);
1594 const char *nullability
= 0;
1596 case CXTypeNullability_NonNull
:
1597 nullability
= "nonnull";
1599 case CXTypeNullability_Nullable
:
1600 nullability
= "nullable";
1602 case CXTypeNullability_NullableResult
:
1603 nullability
= "nullable_result";
1605 case CXTypeNullability_Unspecified
:
1606 nullability
= "unspecified";
1608 case CXTypeNullability_Invalid
:
1613 printf(Format
, nullability
);
1617 static enum CXChildVisitResult
PrintType(CXCursor cursor
, CXCursor p
,
1619 if (!clang_isInvalid(clang_getCursorKind(cursor
))) {
1620 CXType T
= clang_getCursorType(cursor
);
1621 CXType PT
= clang_getPointeeType(T
);
1622 enum CXRefQualifierKind RQ
= clang_Type_getCXXRefQualifier(T
);
1623 PrintCursor(cursor
, NULL
);
1624 PrintTypeAndTypeKind(T
, " [type=%s] [typekind=%s]");
1625 PrintNullabilityKind(T
, " [nullability=%s]");
1626 if (clang_isConstQualifiedType(T
))
1628 if (clang_isVolatileQualifiedType(T
))
1629 printf(" volatile");
1630 if (clang_isRestrictQualifiedType(T
))
1631 printf(" restrict");
1632 if (RQ
== CXRefQualifier_LValue
)
1633 printf(" lvalue-ref-qualifier");
1634 if (RQ
== CXRefQualifier_RValue
)
1635 printf(" rvalue-ref-qualifier");
1636 /* Print the template argument types if they exist. */
1637 PrintTypeTemplateArgs(T
, " [templateargs/%d=");
1638 /* Print the canonical type if it is different. */
1640 CXType CT
= clang_getCanonicalType(T
);
1641 if (!clang_equalTypes(T
, CT
)) {
1642 PrintTypeAndTypeKind(CT
, " [canonicaltype=%s] [canonicaltypekind=%s]");
1643 PrintTypeTemplateArgs(CT
, " [canonicaltemplateargs/%d=");
1646 /* Print the value type if it exists. */
1648 CXType VT
= clang_Type_getValueType(T
);
1649 if (VT
.kind
!= CXType_Invalid
)
1650 PrintTypeAndTypeKind(VT
, " [valuetype=%s] [valuetypekind=%s]");
1652 /* Print the modified type if it exists. */
1654 CXType MT
= clang_Type_getModifiedType(T
);
1655 if (MT
.kind
!= CXType_Invalid
) {
1656 PrintTypeAndTypeKind(MT
, " [modifiedtype=%s] [modifiedtypekind=%s]");
1659 /* Print the return type if it exists. */
1661 CXType RT
= clang_getCursorResultType(cursor
);
1662 if (RT
.kind
!= CXType_Invalid
) {
1663 PrintTypeAndTypeKind(RT
, " [resulttype=%s] [resulttypekind=%s]");
1665 PrintNullabilityKind(RT
, " [resultnullability=%s]");
1667 /* Print the argument types if they exist. */
1669 int NumArgs
= clang_Cursor_getNumArguments(cursor
);
1670 if (NumArgs
!= -1 && NumArgs
!= 0) {
1673 for (i
= 0; i
< NumArgs
; ++i
) {
1674 CXType T
= clang_getCursorType(clang_Cursor_getArgument(cursor
, i
));
1675 if (T
.kind
!= CXType_Invalid
) {
1676 PrintTypeAndTypeKind(T
, " [%s] [%s]");
1677 PrintNullabilityKind(T
, " [%s]");
1683 /* Print ObjC base types, type arguments, and protocol list if available. */
1685 CXType BT
= clang_Type_getObjCObjectBaseType(PT
);
1686 if (BT
.kind
!= CXType_Invalid
) {
1687 PrintTypeAndTypeKind(BT
, " [basetype=%s] [basekind=%s]");
1691 unsigned NumTypeArgs
= clang_Type_getNumObjCTypeArgs(PT
);
1692 if (NumTypeArgs
> 0) {
1694 printf(" [typeargs=");
1695 for (i
= 0; i
< NumTypeArgs
; ++i
) {
1696 CXType TA
= clang_Type_getObjCTypeArg(PT
, i
);
1697 if (TA
.kind
!= CXType_Invalid
) {
1698 PrintTypeAndTypeKind(TA
, " [%s] [%s]");
1705 unsigned NumProtocols
= clang_Type_getNumObjCProtocolRefs(PT
);
1706 if (NumProtocols
> 0) {
1708 printf(" [protocols=");
1709 for (i
= 0; i
< NumProtocols
; ++i
) {
1710 CXCursor P
= clang_Type_getObjCProtocolDecl(PT
, i
);
1711 if (!clang_isInvalid(clang_getCursorKind(P
))) {
1712 PrintCursor(P
, NULL
);
1718 /* Print if this is a non-POD type. */
1719 printf(" [isPOD=%d]", clang_isPODType(T
));
1720 /* Print the pointee type. */
1722 if (PT
.kind
!= CXType_Invalid
) {
1723 PrintTypeAndTypeKind(PT
, " [pointeetype=%s] [pointeekind=%s]");
1726 /* Print the number of fields if they exist. */
1729 if (clang_Type_visitFields(T
, FieldVisitor
, &numFields
)){
1730 if (numFields
!= 0) {
1731 printf(" [nbFields=%d]", numFields
);
1736 /* Print if it is an anonymous record or namespace. */
1738 unsigned isAnon
= clang_Cursor_isAnonymous(cursor
);
1740 printf(" [isAnon=%d]", isAnon
);
1744 /* Print if it is an anonymous record decl */
1746 unsigned isAnonRecDecl
= clang_Cursor_isAnonymousRecordDecl(cursor
);
1747 printf(" [isAnonRecDecl=%d]", isAnonRecDecl
);
1750 /* Print if it is an inline namespace decl */
1752 unsigned isInlineNamespace
= clang_Cursor_isInlineNamespace(cursor
);
1753 if (isInlineNamespace
!= 0)
1754 printf(" [isInlineNamespace=%d]", isInlineNamespace
);
1759 return CXChildVisit_Recurse
;
1762 static void PrintSingleTypeSize(CXType T
, const char *TypeKindFormat
,
1763 const char *SizeFormat
,
1764 const char *AlignFormat
) {
1765 PrintTypeAndTypeKind(T
, TypeKindFormat
);
1766 /* Print the type sizeof if applicable. */
1768 long long Size
= clang_Type_getSizeOf(T
);
1769 if (Size
>= 0 || Size
< -1 ) {
1770 printf(SizeFormat
, Size
);
1773 /* Print the type alignof if applicable. */
1775 long long Align
= clang_Type_getAlignOf(T
);
1776 if (Align
>= 0 || Align
< -1) {
1777 printf(AlignFormat
, Align
);
1781 /* Print the return type if it exists. */
1783 CXType RT
= clang_getResultType(T
);
1784 if (RT
.kind
!= CXType_Invalid
)
1785 PrintSingleTypeSize(RT
, " [resulttype=%s] [resulttypekind=%s]",
1786 " [resultsizeof=%lld]", " [resultalignof=%lld]");
1790 static enum CXChildVisitResult
PrintTypeSize(CXCursor cursor
, CXCursor p
,
1793 enum CXCursorKind K
= clang_getCursorKind(cursor
);
1794 if (clang_isInvalid(K
))
1795 return CXChildVisit_Recurse
;
1796 T
= clang_getCursorType(cursor
);
1797 PrintCursor(cursor
, NULL
);
1798 PrintSingleTypeSize(T
, " [type=%s] [typekind=%s]", " [sizeof=%lld]",
1800 /* Print the record field offset if applicable. */
1802 CXString FieldSpelling
= clang_getCursorSpelling(cursor
);
1803 const char *FieldName
= clang_getCString(FieldSpelling
);
1804 /* recurse to get the first parent record that is not anonymous. */
1805 unsigned RecordIsAnonymous
= 0;
1806 if (clang_getCursorKind(cursor
) == CXCursor_FieldDecl
) {
1808 CXCursor Parent
= p
;
1811 Parent
= clang_getCursorSemanticParent(Record
);
1812 RecordIsAnonymous
= clang_Cursor_isAnonymous(Record
);
1813 /* Recurse as long as the parent is a CXType_Record and the Record
1815 } while ( clang_getCursorType(Parent
).kind
== CXType_Record
&&
1816 RecordIsAnonymous
> 0);
1818 long long Offset
= clang_Type_getOffsetOf(clang_getCursorType(Record
),
1820 long long Offset2
= clang_Cursor_getOffsetOfField(cursor
);
1821 if (Offset
== Offset2
){
1822 printf(" [offsetof=%lld]", Offset
);
1824 /* Offsets will be different in anonymous records. */
1825 printf(" [offsetof=%lld/%lld]", Offset
, Offset2
);
1829 clang_disposeString(FieldSpelling
);
1831 /* Print if its a bitfield */
1833 int IsBitfield
= clang_Cursor_isBitField(cursor
);
1835 printf(" [BitFieldSize=%d]", clang_getFieldDeclBitWidth(cursor
));
1840 return CXChildVisit_Recurse
;
1843 static enum CXChildVisitResult
PrintBinOps(CXCursor C
, CXCursor p
,
1845 enum CXCursorKind ck
= clang_getCursorKind(C
);
1846 enum CX_BinaryOperatorKind bok
;
1848 if (ck
!= CXCursor_BinaryOperator
&& ck
!= CXCursor_CompoundAssignOperator
)
1849 return CXChildVisit_Recurse
;
1851 PrintCursor(C
, NULL
);
1852 bok
= clang_Cursor_getBinaryOpcode(C
);
1853 opstr
= clang_Cursor_getBinaryOpcodeStr(bok
);
1854 printf(" BinOp=%s %d\n", clang_getCString(opstr
), bok
);
1855 clang_disposeString(opstr
);
1856 return CXChildVisit_Recurse
;
1859 /******************************************************************************/
1860 /* Mangling testing. */
1861 /******************************************************************************/
1863 static enum CXChildVisitResult
PrintMangledName(CXCursor cursor
, CXCursor p
,
1865 CXString MangledName
;
1866 if (clang_isUnexposed(clang_getCursorKind(cursor
)))
1867 return CXChildVisit_Recurse
;
1868 if (clang_getCursorKind(cursor
) == CXCursor_LinkageSpec
)
1869 return CXChildVisit_Recurse
;
1870 PrintCursor(cursor
, NULL
);
1871 MangledName
= clang_Cursor_getMangling(cursor
);
1872 printf(" [mangled=%s]\n", clang_getCString(MangledName
));
1873 clang_disposeString(MangledName
);
1874 return CXChildVisit_Continue
;
1877 static enum CXChildVisitResult
PrintManglings(CXCursor cursor
, CXCursor p
,
1880 CXStringSet
*Manglings
= NULL
;
1881 if (clang_isUnexposed(clang_getCursorKind(cursor
)))
1882 return CXChildVisit_Recurse
;
1883 if (!clang_isDeclaration(clang_getCursorKind(cursor
)))
1884 return CXChildVisit_Recurse
;
1885 if (clang_getCursorKind(cursor
) == CXCursor_LinkageSpec
)
1886 return CXChildVisit_Recurse
;
1887 if (clang_getCursorKind(cursor
) == CXCursor_ParmDecl
)
1888 return CXChildVisit_Continue
;
1889 PrintCursor(cursor
, NULL
);
1890 Manglings
= clang_Cursor_getCXXManglings(cursor
);
1892 for (I
= 0, E
= Manglings
->Count
; I
< E
; ++I
)
1893 printf(" [mangled=%s]", clang_getCString(Manglings
->Strings
[I
]));
1894 clang_disposeStringSet(Manglings
);
1897 Manglings
= clang_Cursor_getObjCManglings(cursor
);
1899 for (I
= 0, E
= Manglings
->Count
; I
< E
; ++I
)
1900 printf(" [mangled=%s]", clang_getCString(Manglings
->Strings
[I
]));
1901 clang_disposeStringSet(Manglings
);
1904 return CXChildVisit_Recurse
;
1907 static enum CXChildVisitResult
1908 PrintSingleSymbolSGFs(CXCursor cursor
, CXCursor parent
, CXClientData data
) {
1909 CXString SGFData
= clang_getSymbolGraphForCursor(cursor
);
1910 const char *SGF
= clang_getCString(SGFData
);
1912 printf("%s\n", SGF
);
1914 clang_disposeString(SGFData
);
1916 return CXChildVisit_Recurse
;
1919 /******************************************************************************/
1920 /* Bitwidth testing. */
1921 /******************************************************************************/
1923 static enum CXChildVisitResult
PrintBitWidth(CXCursor cursor
, CXCursor p
,
1926 if (clang_getCursorKind(cursor
) != CXCursor_FieldDecl
)
1927 return CXChildVisit_Recurse
;
1929 Bitwidth
= clang_getFieldDeclBitWidth(cursor
);
1930 if (Bitwidth
>= 0) {
1931 PrintCursor(cursor
, NULL
);
1932 printf(" bitwidth=%d\n", Bitwidth
);
1935 return CXChildVisit_Recurse
;
1938 /******************************************************************************/
1939 /* Type declaration testing */
1940 /******************************************************************************/
1942 static enum CXChildVisitResult
PrintTypeDeclaration(CXCursor cursor
, CXCursor p
,
1944 CXCursor typeDeclaration
= clang_getTypeDeclaration(clang_getCursorType(cursor
));
1946 if (clang_isDeclaration(typeDeclaration
.kind
)) {
1947 PrintCursor(cursor
, NULL
);
1948 PrintTypeAndTypeKind(clang_getCursorType(typeDeclaration
), " [typedeclaration=%s] [typekind=%s]\n");
1951 return CXChildVisit_Recurse
;
1954 /******************************************************************************/
1955 /* Declaration attributes testing */
1956 /******************************************************************************/
1958 static enum CXChildVisitResult
PrintDeclAttributes(CXCursor cursor
, CXCursor p
,
1960 if (clang_isDeclaration(cursor
.kind
)) {
1962 PrintCursor(cursor
, NULL
);
1963 return CXChildVisit_Recurse
;
1964 } else if (clang_isAttribute(cursor
.kind
)) {
1966 PrintCursor(cursor
, NULL
);
1968 return CXChildVisit_Continue
;
1971 /******************************************************************************/
1972 /* Target information testing. */
1973 /******************************************************************************/
1975 static int print_target_info(int argc
, const char **argv
) {
1977 CXTranslationUnit TU
;
1978 CXTargetInfo TargetInfo
;
1980 const char *FileName
;
1981 enum CXErrorCode Err
;
1985 fprintf(stderr
, "No filename specified\n");
1991 Idx
= clang_createIndex(0, 1);
1992 Err
= clang_parseTranslationUnit2(Idx
, FileName
, argv
, argc
, NULL
, 0,
1993 getDefaultParsingOptions(), &TU
);
1994 if (Err
!= CXError_Success
) {
1995 fprintf(stderr
, "Couldn't parse translation unit!\n");
1996 describeLibclangFailure(Err
);
1997 clang_disposeIndex(Idx
);
2001 TargetInfo
= clang_getTranslationUnitTargetInfo(TU
);
2003 Triple
= clang_TargetInfo_getTriple(TargetInfo
);
2004 printf("TargetTriple: %s\n", clang_getCString(Triple
));
2005 clang_disposeString(Triple
);
2007 PointerWidth
= clang_TargetInfo_getPointerWidth(TargetInfo
);
2008 printf("PointerWidth: %d\n", PointerWidth
);
2010 clang_TargetInfo_dispose(TargetInfo
);
2011 clang_disposeTranslationUnit(TU
);
2012 clang_disposeIndex(Idx
);
2016 /******************************************************************************/
2017 /* Loading ASTs/source. */
2018 /******************************************************************************/
2020 static int perform_test_load(CXIndex Idx
, CXTranslationUnit TU
,
2021 const char *filter
, const char *prefix
,
2022 CXCursorVisitor Visitor
,
2024 const char *CommentSchemaFile
) {
2027 FileCheckPrefix
= prefix
;
2030 enum CXCursorKind K
= CXCursor_NotImplemented
;
2031 enum CXCursorKind
*ck
= &K
;
2034 /* Perform some simple filtering. */
2035 if (!strcmp(filter
, "all") || !strcmp(filter
, "local")) ck
= NULL
;
2036 else if (!strcmp(filter
, "all-display") ||
2037 !strcmp(filter
, "local-display")) {
2039 wanted_display_type
= DisplayType_DisplayName
;
2041 else if (!strcmp(filter
, "all-pretty") ||
2042 !strcmp(filter
, "local-pretty")) {
2044 wanted_display_type
= DisplayType_Pretty
;
2046 else if (!strcmp(filter
, "none")) K
= (enum CXCursorKind
) ~0;
2047 else if (!strcmp(filter
, "category")) K
= CXCursor_ObjCCategoryDecl
;
2048 else if (!strcmp(filter
, "interface")) K
= CXCursor_ObjCInterfaceDecl
;
2049 else if (!strcmp(filter
, "protocol")) K
= CXCursor_ObjCProtocolDecl
;
2050 else if (!strcmp(filter
, "function")) K
= CXCursor_FunctionDecl
;
2051 else if (!strcmp(filter
, "typedef")) K
= CXCursor_TypedefDecl
;
2052 else if (!strcmp(filter
, "scan-function")) Visitor
= FunctionScanVisitor
;
2054 fprintf(stderr
, "Unknown filter for -test-load-tu: %s\n", filter
);
2060 Data
.CommentSchemaFile
= CommentSchemaFile
;
2061 clang_visitChildren(clang_getTranslationUnitCursor(TU
), Visitor
, &Data
);
2067 PrintDiagnostics(TU
);
2068 if (checkForErrors(TU
) != 0) {
2069 clang_disposeTranslationUnit(TU
);
2073 clang_disposeTranslationUnit(TU
);
2077 int perform_test_load_tu(const char *file
, const char *filter
,
2078 const char *prefix
, CXCursorVisitor Visitor
,
2081 CXTranslationUnit TU
;
2083 Idx
= clang_createIndex(/* excludeDeclsFromPCH */
2084 !strcmp(filter
, "local") ? 1 : 0,
2085 /* displayDiagnostics=*/1);
2087 if (!CreateTranslationUnit(Idx
, file
, &TU
)) {
2088 clang_disposeIndex(Idx
);
2092 result
= perform_test_load(Idx
, TU
, filter
, prefix
, Visitor
, PV
, NULL
);
2093 clang_disposeIndex(Idx
);
2097 int perform_test_load_source(int argc
, const char **argv
,
2098 const char *filter
, CXCursorVisitor Visitor
,
2101 CXTranslationUnit TU
;
2102 const char *CommentSchemaFile
;
2103 struct CXUnsavedFile
*unsaved_files
= 0;
2104 int num_unsaved_files
= 0;
2105 enum CXErrorCode Err
;
2107 unsigned Repeats
= 0;
2111 createIndexWithInvocationEmissionPath(/* excludeDeclsFromPCH */
2112 (!strcmp(filter
, "local") ||
2113 !strcmp(filter
, "local-display") ||
2114 !strcmp(filter
, "local-pretty"))
2117 /* displayDiagnostics=*/1);
2121 if ((CommentSchemaFile
= parse_comments_schema(argc
, argv
))) {
2126 if (parse_remapped_files(argc
, argv
, 0, &unsaved_files
, &num_unsaved_files
)) {
2127 clang_disposeIndex(Idx
);
2131 if (getenv("CINDEXTEST_EDITING"))
2134 Err
= clang_parseTranslationUnit2(Idx
, 0,
2135 argv
+ num_unsaved_files
,
2136 argc
- num_unsaved_files
,
2137 unsaved_files
, num_unsaved_files
,
2138 getDefaultParsingOptions(), &TU
);
2139 if (Err
!= CXError_Success
) {
2140 fprintf(stderr
, "Unable to load translation unit!\n");
2141 describeLibclangFailure(Err
);
2142 free_remapped_files(unsaved_files
, num_unsaved_files
);
2143 clang_disposeIndex(Idx
);
2147 for (I
= 0; I
!= Repeats
; ++I
) {
2148 if (checkForErrors(TU
) != 0)
2152 clang_suspendTranslationUnit(TU
);
2154 Err
= clang_reparseTranslationUnit(TU
, num_unsaved_files
, unsaved_files
,
2155 clang_defaultReparseOptions(TU
));
2156 if (Err
!= CXError_Success
) {
2157 describeLibclangFailure(Err
);
2158 free_remapped_files(unsaved_files
, num_unsaved_files
);
2159 clang_disposeIndex(Idx
);
2165 result
= perform_test_load(Idx
, TU
, filter
, NULL
, Visitor
, PV
,
2167 free_remapped_files(unsaved_files
, num_unsaved_files
);
2168 clang_disposeIndex(Idx
);
2172 int perform_test_reparse_source(int argc
, const char **argv
, int trials
,
2173 const char *filter
, CXCursorVisitor Visitor
,
2176 CXTranslationUnit TU
;
2177 struct CXUnsavedFile
*unsaved_files
= 0;
2178 int num_unsaved_files
= 0;
2179 int compiler_arg_idx
= 0;
2180 enum CXErrorCode Err
;
2183 int execute_after_trial
= 0;
2184 const char *execute_command
= NULL
;
2185 int remap_after_trial
= 0;
2188 Idx
= clang_createIndex(/* excludeDeclsFromPCH */
2189 !strcmp(filter
, "local") ? 1 : 0,
2190 /* displayDiagnostics=*/1);
2192 if (parse_remapped_files(argc
, argv
, 0, &unsaved_files
, &num_unsaved_files
)) {
2193 clang_disposeIndex(Idx
);
2197 for (i
= 0; i
< argc
; ++i
) {
2198 if (strcmp(argv
[i
], "--") == 0)
2202 compiler_arg_idx
= i
+1;
2203 if (num_unsaved_files
> compiler_arg_idx
)
2204 compiler_arg_idx
= num_unsaved_files
;
2206 /* Load the initial translation unit -- we do this without honoring remapped
2207 * files, so that we have a way to test results after changing the source. */
2208 Err
= clang_parseTranslationUnit2(Idx
, 0,
2209 argv
+ compiler_arg_idx
,
2210 argc
- compiler_arg_idx
,
2211 0, 0, getDefaultParsingOptions(), &TU
);
2212 if (Err
!= CXError_Success
) {
2213 fprintf(stderr
, "Unable to load translation unit!\n");
2214 describeLibclangFailure(Err
);
2215 free_remapped_files(unsaved_files
, num_unsaved_files
);
2216 clang_disposeIndex(Idx
);
2220 if (checkForErrors(TU
) != 0)
2223 if (getenv("CINDEXTEST_EXECUTE_COMMAND")) {
2224 execute_command
= getenv("CINDEXTEST_EXECUTE_COMMAND");
2226 if (getenv("CINDEXTEST_EXECUTE_AFTER_TRIAL")) {
2227 execute_after_trial
=
2228 strtol(getenv("CINDEXTEST_EXECUTE_AFTER_TRIAL"), &endptr
, 10);
2231 if (getenv("CINDEXTEST_REMAP_AFTER_TRIAL")) {
2233 strtol(getenv("CINDEXTEST_REMAP_AFTER_TRIAL"), &endptr
, 10);
2236 for (trial
= 0; trial
< trials
; ++trial
) {
2237 if (execute_command
&& trial
== execute_after_trial
) {
2238 result
= indextest_perform_shell_execution(execute_command
);
2243 free_remapped_files(unsaved_files
, num_unsaved_files
);
2244 if (parse_remapped_files_with_try(trial
, argc
, argv
, 0,
2245 &unsaved_files
, &num_unsaved_files
)) {
2246 clang_disposeTranslationUnit(TU
);
2247 clang_disposeIndex(Idx
);
2251 Err
= clang_reparseTranslationUnit(
2253 trial
>= remap_after_trial
? num_unsaved_files
: 0,
2254 trial
>= remap_after_trial
? unsaved_files
: 0,
2255 clang_defaultReparseOptions(TU
));
2256 if (Err
!= CXError_Success
) {
2257 fprintf(stderr
, "Unable to reparse translation unit!\n");
2258 describeLibclangFailure(Err
);
2259 clang_disposeTranslationUnit(TU
);
2260 free_remapped_files(unsaved_files
, num_unsaved_files
);
2261 clang_disposeIndex(Idx
);
2265 if (checkForErrors(TU
) != 0)
2269 result
= perform_test_load(Idx
, TU
, filter
, NULL
, Visitor
, PV
, NULL
);
2271 free_remapped_files(unsaved_files
, num_unsaved_files
);
2272 clang_disposeIndex(Idx
);
2276 static int perform_single_file_parse(const char *filename
) {
2278 CXTranslationUnit TU
;
2279 enum CXErrorCode Err
;
2282 Idx
= clang_createIndex(/* excludeDeclsFromPCH */1,
2283 /* displayDiagnostics=*/1);
2285 Err
= clang_parseTranslationUnit2(Idx
, filename
,
2286 /*command_line_args=*/NULL
,
2287 /*num_command_line_args=*/0,
2288 /*unsaved_files=*/NULL
,
2289 /*num_unsaved_files=*/0,
2290 CXTranslationUnit_SingleFileParse
, &TU
);
2291 if (Err
!= CXError_Success
) {
2292 fprintf(stderr
, "Unable to load translation unit!\n");
2293 describeLibclangFailure(Err
);
2294 clang_disposeIndex(Idx
);
2298 result
= perform_test_load(Idx
, TU
, /*filter=*/"all", /*prefix=*/NULL
, FilteredPrintingVisitor
, /*PostVisit=*/NULL
,
2299 /*CommentSchemaFile=*/NULL
);
2300 clang_disposeIndex(Idx
);
2304 static int perform_file_retain_excluded_cb(const char *filename
) {
2306 CXTranslationUnit TU
;
2307 enum CXErrorCode Err
;
2310 Idx
= clang_createIndex(/* excludeDeclsFromPCH */1,
2311 /* displayDiagnostics=*/1);
2313 Err
= clang_parseTranslationUnit2(Idx
, filename
,
2314 /*command_line_args=*/NULL
,
2315 /*num_command_line_args=*/0,
2316 /*unsaved_files=*/NULL
,
2317 /*num_unsaved_files=*/0,
2318 CXTranslationUnit_RetainExcludedConditionalBlocks
, &TU
);
2319 if (Err
!= CXError_Success
) {
2320 fprintf(stderr
, "Unable to load translation unit!\n");
2321 describeLibclangFailure(Err
);
2322 clang_disposeIndex(Idx
);
2326 result
= perform_test_load(Idx
, TU
, /*filter=*/"all", /*prefix=*/NULL
, FilteredPrintingVisitor
, /*PostVisit=*/NULL
,
2327 /*CommentSchemaFile=*/NULL
);
2328 clang_disposeIndex(Idx
);
2332 /******************************************************************************/
2333 /* Logic for testing clang_getCursor(). */
2334 /******************************************************************************/
2336 static void print_cursor_file_scan(CXTranslationUnit TU
, CXCursor cursor
,
2337 unsigned start_line
, unsigned start_col
,
2338 unsigned end_line
, unsigned end_col
,
2339 const char *prefix
) {
2340 printf("// %s: ", FileCheckPrefix
);
2342 printf("-%s", prefix
);
2343 PrintExtent(stdout
, start_line
, start_col
, end_line
, end_col
);
2345 PrintCursor(cursor
, NULL
);
2349 static int perform_file_scan(const char *ast_file
, const char *source_file
,
2350 const char *prefix
) {
2352 CXTranslationUnit TU
;
2354 CXCursor prevCursor
= clang_getNullCursor();
2356 unsigned line
= 1, col
= 1;
2357 unsigned start_line
= 1, start_col
= 1;
2359 if (!(Idx
= clang_createIndex(/* excludeDeclsFromPCH */ 1,
2360 /* displayDiagnostics=*/1))) {
2361 fprintf(stderr
, "Could not create Index\n");
2365 if (!CreateTranslationUnit(Idx
, ast_file
, &TU
))
2368 if ((fp
= fopen(source_file
, "r")) == NULL
) {
2369 fprintf(stderr
, "Could not open '%s'\n", source_file
);
2370 clang_disposeTranslationUnit(TU
);
2374 file
= clang_getFile(TU
, source_file
);
2385 /* Check the cursor at this position, and dump the previous one if we have
2386 * found something new.
2388 cursor
= clang_getCursor(TU
, clang_getLocation(TU
, file
, line
, col
));
2389 if ((c
== EOF
|| !clang_equalCursors(cursor
, prevCursor
)) &&
2390 prevCursor
.kind
!= CXCursor_InvalidFile
) {
2391 print_cursor_file_scan(TU
, prevCursor
, start_line
, start_col
,
2399 prevCursor
= cursor
;
2403 clang_disposeTranslationUnit(TU
);
2404 clang_disposeIndex(Idx
);
2408 /******************************************************************************/
2409 /* Logic for testing clang code completion. */
2410 /******************************************************************************/
2412 /* Parse file:line:column from the input string. Returns 0 on success, non-zero
2413 on failure. If successful, the pointer *filename will contain newly-allocated
2414 memory (that will be owned by the caller) to store the file name. */
2415 int parse_file_line_column(const char *input
, char **filename
, unsigned *line
,
2416 unsigned *column
, unsigned *second_line
,
2417 unsigned *second_column
) {
2418 /* Find the second colon. */
2419 const char *last_colon
= strrchr(input
, ':');
2420 unsigned values
[4], i
;
2421 unsigned num_values
= (second_line
&& second_column
)? 4 : 2;
2424 if (!last_colon
|| last_colon
== input
) {
2425 if (num_values
== 4)
2426 fprintf(stderr
, "could not parse filename:line:column:line:column in "
2429 fprintf(stderr
, "could not parse filename:line:column in '%s'\n", input
);
2433 for (i
= 0; i
!= num_values
; ++i
) {
2434 const char *prev_colon
;
2436 /* Parse the next line or column. */
2437 values
[num_values
- i
- 1] = strtol(last_colon
+ 1, &endptr
, 10);
2438 if (*endptr
!= 0 && *endptr
!= ':') {
2439 fprintf(stderr
, "could not parse %s in '%s'\n",
2440 (i
% 2 ? "column" : "line"), input
);
2444 if (i
+ 1 == num_values
)
2447 /* Find the previous colon. */
2448 prev_colon
= last_colon
- 1;
2449 while (prev_colon
!= input
&& *prev_colon
!= ':')
2451 if (prev_colon
== input
) {
2452 fprintf(stderr
, "could not parse %s in '%s'\n",
2453 (i
% 2 == 0? "column" : "line"), input
);
2457 last_colon
= prev_colon
;
2461 *column
= values
[1];
2463 if (second_line
&& second_column
) {
2464 *second_line
= values
[2];
2465 *second_column
= values
[3];
2468 /* Copy the file name. */
2469 *filename
= (char*)malloc(last_colon
- input
+ 1);
2471 memcpy(*filename
, input
, last_colon
- input
);
2472 (*filename
)[last_colon
- input
] = 0;
2477 clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind
) {
2479 case CXCompletionChunk_Optional
: return "Optional";
2480 case CXCompletionChunk_TypedText
: return "TypedText";
2481 case CXCompletionChunk_Text
: return "Text";
2482 case CXCompletionChunk_Placeholder
: return "Placeholder";
2483 case CXCompletionChunk_Informative
: return "Informative";
2484 case CXCompletionChunk_CurrentParameter
: return "CurrentParameter";
2485 case CXCompletionChunk_LeftParen
: return "LeftParen";
2486 case CXCompletionChunk_RightParen
: return "RightParen";
2487 case CXCompletionChunk_LeftBracket
: return "LeftBracket";
2488 case CXCompletionChunk_RightBracket
: return "RightBracket";
2489 case CXCompletionChunk_LeftBrace
: return "LeftBrace";
2490 case CXCompletionChunk_RightBrace
: return "RightBrace";
2491 case CXCompletionChunk_LeftAngle
: return "LeftAngle";
2492 case CXCompletionChunk_RightAngle
: return "RightAngle";
2493 case CXCompletionChunk_Comma
: return "Comma";
2494 case CXCompletionChunk_ResultType
: return "ResultType";
2495 case CXCompletionChunk_Colon
: return "Colon";
2496 case CXCompletionChunk_SemiColon
: return "SemiColon";
2497 case CXCompletionChunk_Equal
: return "Equal";
2498 case CXCompletionChunk_HorizontalSpace
: return "HorizontalSpace";
2499 case CXCompletionChunk_VerticalSpace
: return "VerticalSpace";
2505 static int checkForErrors(CXTranslationUnit TU
) {
2510 if (!getenv("CINDEXTEST_FAILONERROR"))
2513 Num
= clang_getNumDiagnostics(TU
);
2514 for (i
= 0; i
!= Num
; ++i
) {
2515 Diag
= clang_getDiagnostic(TU
, i
);
2516 if (clang_getDiagnosticSeverity(Diag
) >= CXDiagnostic_Error
) {
2517 DiagStr
= clang_formatDiagnostic(Diag
,
2518 clang_defaultDiagnosticDisplayOptions());
2519 fprintf(stderr
, "%s\n", clang_getCString(DiagStr
));
2520 clang_disposeString(DiagStr
);
2521 clang_disposeDiagnostic(Diag
);
2524 clang_disposeDiagnostic(Diag
);
2530 static void print_completion_string(CXCompletionString completion_string
,
2534 N
= clang_getNumCompletionChunks(completion_string
);
2535 for (I
= 0; I
!= N
; ++I
) {
2538 enum CXCompletionChunkKind Kind
2539 = clang_getCompletionChunkKind(completion_string
, I
);
2541 if (Kind
== CXCompletionChunk_Optional
) {
2542 fprintf(file
, "{Optional ");
2543 print_completion_string(
2544 clang_getCompletionChunkCompletionString(completion_string
, I
),
2550 if (Kind
== CXCompletionChunk_VerticalSpace
) {
2551 fprintf(file
, "{VerticalSpace }");
2555 text
= clang_getCompletionChunkText(completion_string
, I
);
2556 cstr
= clang_getCString(text
);
2557 fprintf(file
, "{%s %s}",
2558 clang_getCompletionChunkKindSpelling(Kind
),
2560 clang_disposeString(text
);
2565 static void print_line_column(CXSourceLocation location
, FILE *file
) {
2566 unsigned line
, column
;
2567 clang_getExpansionLocation(location
, NULL
, &line
, &column
, NULL
);
2568 fprintf(file
, "%d:%d", line
, column
);
2571 static void print_token_range(CXTranslationUnit translation_unit
,
2572 CXSourceLocation start
, FILE *file
) {
2573 CXToken
*token
= clang_getToken(translation_unit
, start
);
2576 if (token
!= NULL
) {
2577 CXSourceRange token_range
= clang_getTokenExtent(translation_unit
, *token
);
2578 print_line_column(clang_getRangeStart(token_range
), file
);
2580 print_line_column(clang_getRangeEnd(token_range
), file
);
2581 clang_disposeTokens(translation_unit
, token
, 1);
2587 static void print_completion_result(CXTranslationUnit translation_unit
,
2588 CXCodeCompleteResults
*completion_results
,
2591 CXCompletionResult
*completion_result
= completion_results
->Results
+ index
;
2592 CXString ks
= clang_getCursorKindSpelling(completion_result
->CursorKind
);
2593 unsigned annotationCount
;
2594 enum CXCursorKind ParentKind
;
2595 CXString ParentName
;
2596 CXString BriefComment
;
2597 CXString Annotation
;
2598 const char *BriefCommentCString
;
2601 fprintf(file
, "%s:", clang_getCString(ks
));
2602 clang_disposeString(ks
);
2604 print_completion_string(completion_result
->CompletionString
, file
);
2605 fprintf(file
, " (%u)",
2606 clang_getCompletionPriority(completion_result
->CompletionString
));
2607 switch (clang_getCompletionAvailability(completion_result
->CompletionString
)){
2608 case CXAvailability_Available
:
2611 case CXAvailability_Deprecated
:
2612 fprintf(file
, " (deprecated)");
2615 case CXAvailability_NotAvailable
:
2616 fprintf(file
, " (unavailable)");
2619 case CXAvailability_NotAccessible
:
2620 fprintf(file
, " (inaccessible)");
2624 annotationCount
= clang_getCompletionNumAnnotations(
2625 completion_result
->CompletionString
);
2626 if (annotationCount
) {
2628 fprintf(file
, " (");
2629 for (i
= 0; i
< annotationCount
; ++i
) {
2631 fprintf(file
, ", ");
2633 clang_getCompletionAnnotation(completion_result
->CompletionString
, i
);
2634 fprintf(file
, "\"%s\"", clang_getCString(Annotation
));
2635 clang_disposeString(Annotation
);
2640 if (!getenv("CINDEXTEST_NO_COMPLETION_PARENTS")) {
2641 ParentName
= clang_getCompletionParent(completion_result
->CompletionString
,
2643 if (ParentKind
!= CXCursor_NotImplemented
) {
2644 CXString KindSpelling
= clang_getCursorKindSpelling(ParentKind
);
2645 fprintf(file
, " (parent: %s '%s')",
2646 clang_getCString(KindSpelling
),
2647 clang_getCString(ParentName
));
2648 clang_disposeString(KindSpelling
);
2650 clang_disposeString(ParentName
);
2653 BriefComment
= clang_getCompletionBriefComment(
2654 completion_result
->CompletionString
);
2655 BriefCommentCString
= clang_getCString(BriefComment
);
2656 if (BriefCommentCString
&& *BriefCommentCString
!= '\0') {
2657 fprintf(file
, "(brief comment: %s)", BriefCommentCString
);
2659 clang_disposeString(BriefComment
);
2661 for (i
= 0; i
< clang_getCompletionNumFixIts(completion_results
, index
);
2663 CXSourceRange correction_range
;
2664 CXString FixIt
= clang_getCompletionFixIt(completion_results
, index
, i
,
2666 fprintf(file
, " (requires fix-it: ");
2667 print_token_range(translation_unit
, clang_getRangeStart(correction_range
),
2669 fprintf(file
, " to \"%s\")", clang_getCString(FixIt
));
2670 clang_disposeString(FixIt
);
2673 fprintf(file
, "\n");
2676 void print_completion_contexts(unsigned long long contexts
, FILE *file
) {
2677 fprintf(file
, "Completion contexts:\n");
2678 if (contexts
== CXCompletionContext_Unknown
) {
2679 fprintf(file
, "Unknown\n");
2681 if (contexts
& CXCompletionContext_AnyType
) {
2682 fprintf(file
, "Any type\n");
2684 if (contexts
& CXCompletionContext_AnyValue
) {
2685 fprintf(file
, "Any value\n");
2687 if (contexts
& CXCompletionContext_ObjCObjectValue
) {
2688 fprintf(file
, "Objective-C object value\n");
2690 if (contexts
& CXCompletionContext_ObjCSelectorValue
) {
2691 fprintf(file
, "Objective-C selector value\n");
2693 if (contexts
& CXCompletionContext_CXXClassTypeValue
) {
2694 fprintf(file
, "C++ class type value\n");
2696 if (contexts
& CXCompletionContext_DotMemberAccess
) {
2697 fprintf(file
, "Dot member access\n");
2699 if (contexts
& CXCompletionContext_ArrowMemberAccess
) {
2700 fprintf(file
, "Arrow member access\n");
2702 if (contexts
& CXCompletionContext_ObjCPropertyAccess
) {
2703 fprintf(file
, "Objective-C property access\n");
2705 if (contexts
& CXCompletionContext_EnumTag
) {
2706 fprintf(file
, "Enum tag\n");
2708 if (contexts
& CXCompletionContext_UnionTag
) {
2709 fprintf(file
, "Union tag\n");
2711 if (contexts
& CXCompletionContext_StructTag
) {
2712 fprintf(file
, "Struct tag\n");
2714 if (contexts
& CXCompletionContext_ClassTag
) {
2715 fprintf(file
, "Class name\n");
2717 if (contexts
& CXCompletionContext_Namespace
) {
2718 fprintf(file
, "Namespace or namespace alias\n");
2720 if (contexts
& CXCompletionContext_NestedNameSpecifier
) {
2721 fprintf(file
, "Nested name specifier\n");
2723 if (contexts
& CXCompletionContext_ObjCInterface
) {
2724 fprintf(file
, "Objective-C interface\n");
2726 if (contexts
& CXCompletionContext_ObjCProtocol
) {
2727 fprintf(file
, "Objective-C protocol\n");
2729 if (contexts
& CXCompletionContext_ObjCCategory
) {
2730 fprintf(file
, "Objective-C category\n");
2732 if (contexts
& CXCompletionContext_ObjCInstanceMessage
) {
2733 fprintf(file
, "Objective-C instance method\n");
2735 if (contexts
& CXCompletionContext_ObjCClassMessage
) {
2736 fprintf(file
, "Objective-C class method\n");
2738 if (contexts
& CXCompletionContext_ObjCSelectorName
) {
2739 fprintf(file
, "Objective-C selector name\n");
2741 if (contexts
& CXCompletionContext_MacroName
) {
2742 fprintf(file
, "Macro name\n");
2744 if (contexts
& CXCompletionContext_NaturalLanguage
) {
2745 fprintf(file
, "Natural language\n");
2749 int perform_code_completion(int argc
, const char **argv
, int timing_only
) {
2750 const char *input
= argv
[1];
2756 struct CXUnsavedFile
*unsaved_files
= 0;
2757 int num_unsaved_files
= 0;
2758 CXCodeCompleteResults
*results
= 0;
2759 enum CXErrorCode Err
;
2760 CXTranslationUnit TU
;
2761 unsigned I
, Repeats
= 1;
2762 unsigned completionOptions
= clang_defaultCodeCompleteOptions();
2764 if (getenv("CINDEXTEST_CODE_COMPLETE_PATTERNS"))
2765 completionOptions
|= CXCodeComplete_IncludeCodePatterns
;
2766 if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
2767 completionOptions
|= CXCodeComplete_IncludeBriefComments
;
2768 if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE"))
2769 completionOptions
|= CXCodeComplete_SkipPreamble
;
2770 if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS"))
2771 completionOptions
|= CXCodeComplete_IncludeCompletionsWithFixIts
;
2774 input
+= strlen("-code-completion-timing=");
2776 input
+= strlen("-code-completion-at=");
2778 if ((errorCode
= parse_file_line_column(input
, &filename
, &line
, &column
,
2782 if (parse_remapped_files(argc
, argv
, 2, &unsaved_files
, &num_unsaved_files
))
2785 CIdx
= createIndexWithInvocationEmissionPath(0, 0);
2789 if (getenv("CINDEXTEST_EDITING"))
2792 Err
= clang_parseTranslationUnit2(CIdx
, 0,
2793 argv
+ num_unsaved_files
+ 2,
2794 argc
- num_unsaved_files
- 2,
2795 0, 0, getDefaultParsingOptions(), &TU
);
2796 if (Err
!= CXError_Success
) {
2797 fprintf(stderr
, "Unable to load translation unit!\n");
2798 describeLibclangFailure(Err
);
2802 Err
= clang_reparseTranslationUnit(TU
, 0, 0,
2803 clang_defaultReparseOptions(TU
));
2805 if (Err
!= CXError_Success
) {
2806 fprintf(stderr
, "Unable to reparse translation unit!\n");
2807 describeLibclangFailure(Err
);
2808 clang_disposeTranslationUnit(TU
);
2812 for (I
= 0; I
!= Repeats
; ++I
) {
2813 results
= clang_codeCompleteAt(TU
, filename
, line
, column
,
2814 unsaved_files
, num_unsaved_files
,
2817 fprintf(stderr
, "Unable to perform code completion!\n");
2821 clang_disposeCodeCompleteResults(results
);
2825 unsigned i
, n
= results
->NumResults
, containerIsIncomplete
= 0;
2826 unsigned long long contexts
;
2827 enum CXCursorKind containerKind
;
2828 CXString objCSelector
;
2829 const char *selectorString
;
2831 /* Sort the code-completion results based on the typed text. */
2832 clang_sortCodeCompletionResults(results
->Results
, results
->NumResults
);
2834 for (i
= 0; i
!= n
; ++i
)
2835 print_completion_result(TU
, results
, i
, stdout
);
2837 n
= clang_codeCompleteGetNumDiagnostics(results
);
2838 for (i
= 0; i
!= n
; ++i
) {
2839 CXDiagnostic diag
= clang_codeCompleteGetDiagnostic(results
, i
);
2840 PrintDiagnostic(diag
);
2841 clang_disposeDiagnostic(diag
);
2844 contexts
= clang_codeCompleteGetContexts(results
);
2845 print_completion_contexts(contexts
, stdout
);
2847 containerKind
= clang_codeCompleteGetContainerKind(results
,
2848 &containerIsIncomplete
);
2850 if (containerKind
!= CXCursor_InvalidCode
) {
2851 /* We have found a container */
2852 CXString containerUSR
, containerKindSpelling
;
2853 containerKindSpelling
= clang_getCursorKindSpelling(containerKind
);
2854 printf("Container Kind: %s\n", clang_getCString(containerKindSpelling
));
2855 clang_disposeString(containerKindSpelling
);
2857 if (containerIsIncomplete
) {
2858 printf("Container is incomplete\n");
2861 printf("Container is complete\n");
2864 containerUSR
= clang_codeCompleteGetContainerUSR(results
);
2865 printf("Container USR: %s\n", clang_getCString(containerUSR
));
2866 clang_disposeString(containerUSR
);
2869 objCSelector
= clang_codeCompleteGetObjCSelector(results
);
2870 selectorString
= clang_getCString(objCSelector
);
2871 if (selectorString
&& strlen(selectorString
) > 0) {
2872 printf("Objective-C selector: %s\n", selectorString
);
2874 clang_disposeString(objCSelector
);
2876 clang_disposeCodeCompleteResults(results
);
2878 clang_disposeTranslationUnit(TU
);
2879 clang_disposeIndex(CIdx
);
2882 free_remapped_files(unsaved_files
, num_unsaved_files
);
2891 } CursorSourceLocation
;
2893 typedef void (*cursor_handler_t
)(CXCursor cursor
);
2895 static int inspect_cursor_at(int argc
, const char **argv
,
2896 const char *locations_flag
,
2897 cursor_handler_t handler
) {
2900 struct CXUnsavedFile
*unsaved_files
= 0;
2901 int num_unsaved_files
= 0;
2902 enum CXErrorCode Err
;
2903 CXTranslationUnit TU
;
2905 CursorSourceLocation
*Locations
= 0;
2906 unsigned NumLocations
= 0, Loc
;
2907 unsigned Repeats
= 1;
2910 /* Count the number of locations. */
2911 while (strstr(argv
[NumLocations
+1], locations_flag
) == argv
[NumLocations
+1])
2914 /* Parse the locations. */
2915 assert(NumLocations
> 0 && "Unable to count locations?");
2916 Locations
= (CursorSourceLocation
*)malloc(
2917 NumLocations
* sizeof(CursorSourceLocation
));
2919 for (Loc
= 0; Loc
< NumLocations
; ++Loc
) {
2920 const char *input
= argv
[Loc
+ 1] + strlen(locations_flag
);
2921 if ((errorCode
= parse_file_line_column(input
, &Locations
[Loc
].filename
,
2922 &Locations
[Loc
].line
,
2923 &Locations
[Loc
].column
, 0, 0)))
2927 if (parse_remapped_files(argc
, argv
, NumLocations
+ 1, &unsaved_files
,
2928 &num_unsaved_files
))
2931 if (getenv("CINDEXTEST_EDITING"))
2934 /* Parse the translation unit. When we're testing clang_getCursor() after
2935 reparsing, don't remap unsaved files until the second parse. */
2936 CIdx
= clang_createIndex(1, 1);
2937 Err
= clang_parseTranslationUnit2(CIdx
, argv
[argc
- 1],
2938 argv
+ num_unsaved_files
+ 1 + NumLocations
,
2939 argc
- num_unsaved_files
- 2 - NumLocations
,
2941 Repeats
> 1? 0 : num_unsaved_files
,
2942 getDefaultParsingOptions(), &TU
);
2943 if (Err
!= CXError_Success
) {
2944 fprintf(stderr
, "unable to parse input\n");
2945 describeLibclangFailure(Err
);
2949 if (checkForErrors(TU
) != 0)
2952 for (I
= 0; I
!= Repeats
; ++I
) {
2954 Err
= clang_reparseTranslationUnit(TU
, num_unsaved_files
, unsaved_files
,
2955 clang_defaultReparseOptions(TU
));
2956 if (Err
!= CXError_Success
) {
2957 describeLibclangFailure(Err
);
2958 clang_disposeTranslationUnit(TU
);
2963 if (checkForErrors(TU
) != 0)
2966 for (Loc
= 0; Loc
< NumLocations
; ++Loc
) {
2967 CXFile file
= clang_getFile(TU
, Locations
[Loc
].filename
);
2971 Cursor
= clang_getCursor(TU
,
2972 clang_getLocation(TU
, file
, Locations
[Loc
].line
,
2973 Locations
[Loc
].column
));
2975 if (checkForErrors(TU
) != 0)
2978 if (I
+ 1 == Repeats
) {
2980 free(Locations
[Loc
].filename
);
2985 PrintDiagnostics(TU
);
2986 clang_disposeTranslationUnit(TU
);
2987 clang_disposeIndex(CIdx
);
2989 free_remapped_files(unsaved_files
, num_unsaved_files
);
2993 static void inspect_print_cursor(CXCursor Cursor
) {
2994 CXTranslationUnit TU
= clang_Cursor_getTranslationUnit(Cursor
);
2995 CXCompletionString completionString
= clang_getCursorCompletionString(
2997 CXSourceLocation CursorLoc
= clang_getCursorLocation(Cursor
);
3000 unsigned line
, column
;
3001 clang_getFileLocation(CursorLoc
, 0, &line
, &column
, 0);
3002 printf("%d:%d ", line
, column
);
3003 PrintCursor(Cursor
, NULL
);
3004 PrintCursorExtent(Cursor
);
3005 Spelling
= clang_getCursorSpelling(Cursor
);
3006 cspell
= clang_getCString(Spelling
);
3007 if (cspell
&& strlen(cspell
) != 0) {
3008 unsigned pieceIndex
;
3009 printf(" Spelling=%s (", cspell
);
3010 for (pieceIndex
= 0; ; ++pieceIndex
) {
3011 CXSourceRange range
=
3012 clang_Cursor_getSpellingNameRange(Cursor
, pieceIndex
, 0);
3013 if (clang_Range_isNull(range
))
3015 PrintRange(range
, 0);
3019 clang_disposeString(Spelling
);
3020 if (clang_Cursor_getObjCSelectorIndex(Cursor
) != -1)
3021 printf(" Selector index=%d",
3022 clang_Cursor_getObjCSelectorIndex(Cursor
));
3023 if (clang_Cursor_isDynamicCall(Cursor
))
3024 printf(" Dynamic-call");
3025 if (Cursor
.kind
== CXCursor_ObjCMessageExpr
||
3026 Cursor
.kind
== CXCursor_MemberRefExpr
) {
3027 CXType T
= clang_Cursor_getReceiverType(Cursor
);
3028 if (T
.kind
!= CXType_Invalid
) {
3029 CXString S
= clang_getTypeKindSpelling(T
.kind
);
3030 printf(" Receiver-type=%s", clang_getCString(S
));
3031 clang_disposeString(S
);
3036 CXModule mod
= clang_Cursor_getModule(Cursor
);
3038 CXString name
, astFilename
;
3039 unsigned i
, numHeaders
;
3041 astFile
= clang_Module_getASTFile(mod
);
3042 astFilename
= clang_getFileName(astFile
);
3043 name
= clang_Module_getFullName(mod
);
3044 numHeaders
= clang_Module_getNumTopLevelHeaders(TU
, mod
);
3045 printf(" ModuleName=%s (%s) system=%d Headers(%d):",
3046 clang_getCString(name
), clang_getCString(astFilename
),
3047 clang_Module_isSystem(mod
), numHeaders
);
3048 clang_disposeString(name
);
3049 clang_disposeString(astFilename
);
3050 for (i
= 0; i
< numHeaders
; ++i
) {
3051 CXFile file
= clang_Module_getTopLevelHeader(TU
, mod
, i
);
3052 CXString filename
= clang_getFileName(file
);
3053 printf("\n%s", clang_getCString(filename
));
3054 clang_disposeString(filename
);
3059 if (completionString
!= NULL
) {
3060 printf("\nCompletion string: ");
3061 print_completion_string(completionString
, stdout
);
3066 static void display_evaluate_results(CXEvalResult result
) {
3067 switch (clang_EvalResult_getKind(result
)) {
3070 printf("Kind: Int, ");
3071 if (clang_EvalResult_isUnsignedInt(result
)) {
3072 unsigned long long val
= clang_EvalResult_getAsUnsigned(result
);
3073 printf("unsigned, Value: %llu", val
);
3075 long long val
= clang_EvalResult_getAsLongLong(result
);
3076 printf("Value: %lld", val
);
3082 double val
= clang_EvalResult_getAsDouble(result
);
3083 printf("Kind: Float , Value: %f", val
);
3086 case CXEval_ObjCStrLiteral
:
3088 const char* str
= clang_EvalResult_getAsStr(result
);
3089 printf("Kind: ObjCString , Value: %s", str
);
3092 case CXEval_StrLiteral
:
3094 const char* str
= clang_EvalResult_getAsStr(result
);
3095 printf("Kind: CString , Value: %s", str
);
3100 const char* str
= clang_EvalResult_getAsStr(result
);
3101 printf("Kind: CFString , Value: %s", str
);
3105 printf("Unexposed");
3110 static void inspect_evaluate_cursor(CXCursor Cursor
) {
3111 CXSourceLocation CursorLoc
= clang_getCursorLocation(Cursor
);
3114 unsigned line
, column
;
3117 clang_getFileLocation(CursorLoc
, 0, &line
, &column
, 0);
3118 printf("%d:%d ", line
, column
);
3119 PrintCursor(Cursor
, NULL
);
3120 PrintCursorExtent(Cursor
);
3121 Spelling
= clang_getCursorSpelling(Cursor
);
3122 cspell
= clang_getCString(Spelling
);
3123 if (cspell
&& strlen(cspell
) != 0) {
3124 unsigned pieceIndex
;
3125 printf(" Spelling=%s (", cspell
);
3126 for (pieceIndex
= 0; ; ++pieceIndex
) {
3127 CXSourceRange range
=
3128 clang_Cursor_getSpellingNameRange(Cursor
, pieceIndex
, 0);
3129 if (clang_Range_isNull(range
))
3131 PrintRange(range
, 0);
3135 clang_disposeString(Spelling
);
3137 ER
= clang_Cursor_Evaluate(Cursor
);
3139 printf("Not Evaluatable");
3141 display_evaluate_results(ER
);
3142 clang_EvalResult_dispose(ER
);
3147 static void inspect_macroinfo_cursor(CXCursor Cursor
) {
3148 CXSourceLocation CursorLoc
= clang_getCursorLocation(Cursor
);
3151 unsigned line
, column
;
3152 clang_getFileLocation(CursorLoc
, 0, &line
, &column
, 0);
3153 printf("%d:%d ", line
, column
);
3154 PrintCursor(Cursor
, NULL
);
3155 PrintCursorExtent(Cursor
);
3156 Spelling
= clang_getCursorSpelling(Cursor
);
3157 cspell
= clang_getCString(Spelling
);
3158 if (cspell
&& strlen(cspell
) != 0) {
3159 unsigned pieceIndex
;
3160 printf(" Spelling=%s (", cspell
);
3161 for (pieceIndex
= 0; ; ++pieceIndex
) {
3162 CXSourceRange range
=
3163 clang_Cursor_getSpellingNameRange(Cursor
, pieceIndex
, 0);
3164 if (clang_Range_isNull(range
))
3166 PrintRange(range
, 0);
3170 clang_disposeString(Spelling
);
3172 if (clang_Cursor_isMacroBuiltin(Cursor
)) {
3173 printf("[builtin macro]");
3174 } else if (clang_Cursor_isMacroFunctionLike(Cursor
)) {
3175 printf("[function macro]");
3180 static enum CXVisitorResult
findFileRefsVisit(void *context
,
3181 CXCursor cursor
, CXSourceRange range
) {
3182 if (clang_Range_isNull(range
))
3183 return CXVisit_Continue
;
3185 PrintCursor(cursor
, NULL
);
3186 PrintRange(range
, "");
3188 return CXVisit_Continue
;
3191 static int find_file_refs_at(int argc
, const char **argv
) {
3194 struct CXUnsavedFile
*unsaved_files
= 0;
3195 int num_unsaved_files
= 0;
3196 enum CXErrorCode Err
;
3197 CXTranslationUnit TU
;
3199 CursorSourceLocation
*Locations
= 0;
3200 unsigned NumLocations
= 0, Loc
;
3201 unsigned Repeats
= 1;
3204 /* Count the number of locations. */
3205 while (strstr(argv
[NumLocations
+1], "-file-refs-at=") == argv
[NumLocations
+1])
3208 /* Parse the locations. */
3209 assert(NumLocations
> 0 && "Unable to count locations?");
3210 Locations
= (CursorSourceLocation
*)malloc(
3211 NumLocations
* sizeof(CursorSourceLocation
));
3213 for (Loc
= 0; Loc
< NumLocations
; ++Loc
) {
3214 const char *input
= argv
[Loc
+ 1] + strlen("-file-refs-at=");
3215 if ((errorCode
= parse_file_line_column(input
, &Locations
[Loc
].filename
,
3216 &Locations
[Loc
].line
,
3217 &Locations
[Loc
].column
, 0, 0)))
3221 if (parse_remapped_files(argc
, argv
, NumLocations
+ 1, &unsaved_files
,
3222 &num_unsaved_files
))
3225 if (getenv("CINDEXTEST_EDITING"))
3228 /* Parse the translation unit. When we're testing clang_getCursor() after
3229 reparsing, don't remap unsaved files until the second parse. */
3230 CIdx
= clang_createIndex(1, 1);
3231 Err
= clang_parseTranslationUnit2(CIdx
, argv
[argc
- 1],
3232 argv
+ num_unsaved_files
+ 1 + NumLocations
,
3233 argc
- num_unsaved_files
- 2 - NumLocations
,
3235 Repeats
> 1? 0 : num_unsaved_files
,
3236 getDefaultParsingOptions(), &TU
);
3237 if (Err
!= CXError_Success
) {
3238 fprintf(stderr
, "unable to parse input\n");
3239 describeLibclangFailure(Err
);
3240 clang_disposeTranslationUnit(TU
);
3244 if (checkForErrors(TU
) != 0)
3247 for (I
= 0; I
!= Repeats
; ++I
) {
3249 Err
= clang_reparseTranslationUnit(TU
, num_unsaved_files
, unsaved_files
,
3250 clang_defaultReparseOptions(TU
));
3251 if (Err
!= CXError_Success
) {
3252 describeLibclangFailure(Err
);
3253 clang_disposeTranslationUnit(TU
);
3258 if (checkForErrors(TU
) != 0)
3261 for (Loc
= 0; Loc
< NumLocations
; ++Loc
) {
3262 CXFile file
= clang_getFile(TU
, Locations
[Loc
].filename
);
3266 Cursor
= clang_getCursor(TU
,
3267 clang_getLocation(TU
, file
, Locations
[Loc
].line
,
3268 Locations
[Loc
].column
));
3270 if (checkForErrors(TU
) != 0)
3273 if (I
+ 1 == Repeats
) {
3274 CXCursorAndRangeVisitor visitor
= { 0, findFileRefsVisit
};
3275 PrintCursor(Cursor
, NULL
);
3277 clang_findReferencesInFile(Cursor
, file
, visitor
);
3278 free(Locations
[Loc
].filename
);
3280 if (checkForErrors(TU
) != 0)
3286 PrintDiagnostics(TU
);
3287 clang_disposeTranslationUnit(TU
);
3288 clang_disposeIndex(CIdx
);
3290 free_remapped_files(unsaved_files
, num_unsaved_files
);
3294 static enum CXVisitorResult
findFileIncludesVisit(void *context
,
3295 CXCursor cursor
, CXSourceRange range
) {
3296 PrintCursor(cursor
, NULL
);
3297 PrintRange(range
, "");
3299 return CXVisit_Continue
;
3302 static int find_file_includes_in(int argc
, const char **argv
) {
3304 struct CXUnsavedFile
*unsaved_files
= 0;
3305 int num_unsaved_files
= 0;
3306 enum CXErrorCode Err
;
3307 CXTranslationUnit TU
;
3308 const char **Filenames
= 0;
3309 unsigned NumFilenames
= 0;
3310 unsigned Repeats
= 1;
3313 /* Count the number of locations. */
3314 while (strstr(argv
[NumFilenames
+1], "-file-includes-in=") == argv
[NumFilenames
+1])
3317 /* Parse the locations. */
3318 assert(NumFilenames
> 0 && "Unable to count filenames?");
3319 Filenames
= (const char **)malloc(NumFilenames
* sizeof(const char *));
3321 for (I
= 0; I
< NumFilenames
; ++I
) {
3322 const char *input
= argv
[I
+ 1] + strlen("-file-includes-in=");
3323 /* Copy the file name. */
3324 Filenames
[I
] = input
;
3327 if (parse_remapped_files(argc
, argv
, NumFilenames
+ 1, &unsaved_files
,
3328 &num_unsaved_files
))
3331 if (getenv("CINDEXTEST_EDITING"))
3334 /* Parse the translation unit. When we're testing clang_getCursor() after
3335 reparsing, don't remap unsaved files until the second parse. */
3336 CIdx
= clang_createIndex(1, 1);
3337 Err
= clang_parseTranslationUnit2(
3338 CIdx
, argv
[argc
- 1],
3339 argv
+ num_unsaved_files
+ 1 + NumFilenames
,
3340 argc
- num_unsaved_files
- 2 - NumFilenames
,
3342 Repeats
> 1 ? 0 : num_unsaved_files
, getDefaultParsingOptions(), &TU
);
3344 if (Err
!= CXError_Success
) {
3345 fprintf(stderr
, "unable to parse input\n");
3346 describeLibclangFailure(Err
);
3347 clang_disposeTranslationUnit(TU
);
3351 if (checkForErrors(TU
) != 0)
3354 for (I
= 0; I
!= Repeats
; ++I
) {
3356 Err
= clang_reparseTranslationUnit(TU
, num_unsaved_files
, unsaved_files
,
3357 clang_defaultReparseOptions(TU
));
3358 if (Err
!= CXError_Success
) {
3359 describeLibclangFailure(Err
);
3360 clang_disposeTranslationUnit(TU
);
3365 if (checkForErrors(TU
) != 0)
3368 for (FI
= 0; FI
< NumFilenames
; ++FI
) {
3369 CXFile file
= clang_getFile(TU
, Filenames
[FI
]);
3373 if (checkForErrors(TU
) != 0)
3376 if (I
+ 1 == Repeats
) {
3377 CXCursorAndRangeVisitor visitor
= { 0, findFileIncludesVisit
};
3378 clang_findIncludesInFile(TU
, file
, visitor
);
3380 if (checkForErrors(TU
) != 0)
3386 PrintDiagnostics(TU
);
3387 clang_disposeTranslationUnit(TU
);
3388 clang_disposeIndex(CIdx
);
3389 free((void *)Filenames
);
3390 free_remapped_files(unsaved_files
, num_unsaved_files
);
3394 #define MAX_IMPORTED_ASTFILES 200
3399 } ImportedASTFilesData
;
3401 static ImportedASTFilesData
*importedASTs_create(void) {
3402 ImportedASTFilesData
*p
;
3403 p
= malloc(sizeof(ImportedASTFilesData
));
3405 p
->filenames
= malloc(MAX_IMPORTED_ASTFILES
* sizeof(const char *));
3406 assert(p
->filenames
);
3411 static void importedASTs_dispose(ImportedASTFilesData
*p
) {
3416 for (i
= 0; i
< p
->num_files
; ++i
)
3417 free(p
->filenames
[i
]);
3422 static void importedASTS_insert(ImportedASTFilesData
*p
, const char *file
) {
3425 for (i
= 0; i
< p
->num_files
; ++i
)
3426 if (strcmp(file
, p
->filenames
[i
]) == 0)
3428 assert(p
->num_files
+ 1 < MAX_IMPORTED_ASTFILES
);
3429 p
->filenames
[p
->num_files
++] = strdup(file
);
3432 typedef struct IndexDataStringList_
{
3433 struct IndexDataStringList_
*next
;
3434 char data
[1]; /* Dynamically sized. */
3435 } IndexDataStringList
;
3438 const char *check_prefix
;
3439 int first_check_printed
;
3442 CXString main_filename
;
3443 ImportedASTFilesData
*importedASTs
;
3444 IndexDataStringList
*strings
;
3445 CXTranslationUnit TU
;
3448 static void free_client_data(IndexData
*index_data
) {
3449 IndexDataStringList
*node
= index_data
->strings
;
3451 IndexDataStringList
*next
= node
->next
;
3455 index_data
->strings
= NULL
;
3458 static void printCheck(IndexData
*data
) {
3459 if (data
->check_prefix
) {
3460 if (data
->first_check_printed
) {
3461 printf("// %s-NEXT: ", data
->check_prefix
);
3463 printf("// %s : ", data
->check_prefix
);
3464 data
->first_check_printed
= 1;
3469 static void printCXIndexFile(CXIdxClientFile file
) {
3470 CXString filename
= clang_getFileName((CXFile
)file
);
3471 printf("%s", clang_getCString(filename
));
3472 clang_disposeString(filename
);
3475 static void printCXIndexLoc(CXIdxLoc loc
, CXClientData client_data
) {
3476 IndexData
*index_data
;
3479 CXIdxClientFile file
;
3480 unsigned line
, column
;
3481 const char *main_filename
;
3484 index_data
= (IndexData
*)client_data
;
3485 clang_indexLoc_getFileLocation(loc
, &file
, 0, &line
, &column
, 0);
3487 printf("<invalid>");
3491 printf("<no idxfile>");
3494 filename
= clang_getFileName((CXFile
)file
);
3495 cname
= clang_getCString(filename
);
3496 main_filename
= clang_getCString(index_data
->main_filename
);
3497 if (strcmp(cname
, main_filename
) == 0)
3501 clang_disposeString(filename
);
3504 printCXIndexFile(file
);
3507 printf("%d:%d", line
, column
);
3510 static unsigned digitCount(unsigned val
) {
3520 static CXIdxClientContainer
makeClientContainer(CXClientData
*client_data
,
3521 const CXIdxEntityInfo
*info
,
3523 IndexData
*index_data
;
3524 IndexDataStringList
*node
;
3527 CXIdxClientFile file
;
3528 unsigned line
, column
;
3532 name
= "<anon-tag>";
3534 clang_indexLoc_getFileLocation(loc
, &file
, 0, &line
, &column
, 0);
3537 (IndexDataStringList
*)malloc(sizeof(IndexDataStringList
) + strlen(name
) +
3538 digitCount(line
) + digitCount(column
) + 2);
3540 newStr
= node
->data
;
3541 sprintf(newStr
, "%s:%d:%d", name
, line
, column
);
3543 /* Remember string so it can be freed later. */
3544 index_data
= (IndexData
*)client_data
;
3545 node
->next
= index_data
->strings
;
3546 index_data
->strings
= node
;
3548 return (CXIdxClientContainer
)newStr
;
3551 static void printCXIndexContainer(const CXIdxContainerInfo
*info
) {
3552 CXIdxClientContainer container
;
3553 container
= clang_index_getClientContainer(info
);
3555 printf("[<<NULL>>]");
3557 printf("[%s]", (const char *)container
);
3560 static const char *getEntityKindString(CXIdxEntityKind kind
) {
3562 case CXIdxEntity_Unexposed
: return "<<UNEXPOSED>>";
3563 case CXIdxEntity_Typedef
: return "typedef";
3564 case CXIdxEntity_Function
: return "function";
3565 case CXIdxEntity_Variable
: return "variable";
3566 case CXIdxEntity_Field
: return "field";
3567 case CXIdxEntity_EnumConstant
: return "enumerator";
3568 case CXIdxEntity_ObjCClass
: return "objc-class";
3569 case CXIdxEntity_ObjCProtocol
: return "objc-protocol";
3570 case CXIdxEntity_ObjCCategory
: return "objc-category";
3571 case CXIdxEntity_ObjCInstanceMethod
: return "objc-instance-method";
3572 case CXIdxEntity_ObjCClassMethod
: return "objc-class-method";
3573 case CXIdxEntity_ObjCProperty
: return "objc-property";
3574 case CXIdxEntity_ObjCIvar
: return "objc-ivar";
3575 case CXIdxEntity_Enum
: return "enum";
3576 case CXIdxEntity_Struct
: return "struct";
3577 case CXIdxEntity_Union
: return "union";
3578 case CXIdxEntity_CXXClass
: return "c++-class";
3579 case CXIdxEntity_CXXNamespace
: return "namespace";
3580 case CXIdxEntity_CXXNamespaceAlias
: return "namespace-alias";
3581 case CXIdxEntity_CXXStaticVariable
: return "c++-static-var";
3582 case CXIdxEntity_CXXStaticMethod
: return "c++-static-method";
3583 case CXIdxEntity_CXXInstanceMethod
: return "c++-instance-method";
3584 case CXIdxEntity_CXXConstructor
: return "constructor";
3585 case CXIdxEntity_CXXDestructor
: return "destructor";
3586 case CXIdxEntity_CXXConversionFunction
: return "conversion-func";
3587 case CXIdxEntity_CXXTypeAlias
: return "type-alias";
3588 case CXIdxEntity_CXXInterface
: return "c++-__interface";
3589 case CXIdxEntity_CXXConcept
:
3592 assert(0 && "Garbage entity kind");
3596 static const char *getEntityTemplateKindString(CXIdxEntityCXXTemplateKind kind
) {
3598 case CXIdxEntity_NonTemplate
: return "";
3599 case CXIdxEntity_Template
: return "-template";
3600 case CXIdxEntity_TemplatePartialSpecialization
:
3601 return "-template-partial-spec";
3602 case CXIdxEntity_TemplateSpecialization
: return "-template-spec";
3604 assert(0 && "Garbage entity kind");
3608 static const char *getEntityLanguageString(CXIdxEntityLanguage kind
) {
3610 case CXIdxEntityLang_None
: return "<none>";
3611 case CXIdxEntityLang_C
: return "C";
3612 case CXIdxEntityLang_ObjC
: return "ObjC";
3613 case CXIdxEntityLang_CXX
: return "C++";
3614 case CXIdxEntityLang_Swift
: return "Swift";
3616 assert(0 && "Garbage language kind");
3620 static void printEntityInfo(const char *cb
,
3621 CXClientData client_data
,
3622 const CXIdxEntityInfo
*info
) {
3624 IndexData
*index_data
;
3626 index_data
= (IndexData
*)client_data
;
3627 printCheck(index_data
);
3630 printf("%s: <<NULL>>", cb
);
3636 name
= "<anon-tag>";
3638 printf("%s: kind: %s%s", cb
, getEntityKindString(info
->kind
),
3639 getEntityTemplateKindString(info
->templateKind
));
3640 printf(" | name: %s", name
);
3641 printf(" | USR: %s", info
->USR
);
3642 printf(" | lang: %s", getEntityLanguageString(info
->lang
));
3644 for (i
= 0; i
!= info
->numAttributes
; ++i
) {
3645 const CXIdxAttrInfo
*Attr
= info
->attributes
[i
];
3646 printf(" <attribute>: ");
3647 PrintCursor(Attr
->cursor
, NULL
);
3651 static void printBaseClassInfo(CXClientData client_data
,
3652 const CXIdxBaseClassInfo
*info
) {
3653 printEntityInfo(" <base>", client_data
, info
->base
);
3654 printf(" | cursor: ");
3655 PrintCursor(info
->cursor
, NULL
);
3657 printCXIndexLoc(info
->loc
, client_data
);
3660 static void printProtocolList(const CXIdxObjCProtocolRefListInfo
*ProtoInfo
,
3661 CXClientData client_data
) {
3663 for (i
= 0; i
< ProtoInfo
->numProtocols
; ++i
) {
3664 printEntityInfo(" <protocol>", client_data
,
3665 ProtoInfo
->protocols
[i
]->protocol
);
3666 printf(" | cursor: ");
3667 PrintCursor(ProtoInfo
->protocols
[i
]->cursor
, NULL
);
3669 printCXIndexLoc(ProtoInfo
->protocols
[i
]->loc
, client_data
);
3674 static void printSymbolRole(CXSymbolRole role
) {
3675 if (role
& CXSymbolRole_Declaration
)
3677 if (role
& CXSymbolRole_Definition
)
3679 if (role
& CXSymbolRole_Reference
)
3681 if (role
& CXSymbolRole_Read
)
3683 if (role
& CXSymbolRole_Write
)
3685 if (role
& CXSymbolRole_Call
)
3687 if (role
& CXSymbolRole_Dynamic
)
3689 if (role
& CXSymbolRole_AddressOf
)
3691 if (role
& CXSymbolRole_Implicit
)
3692 printf(" implicit");
3695 static void index_diagnostic(CXClientData client_data
,
3696 CXDiagnosticSet diagSet
, void *reserved
) {
3699 unsigned numDiags
, i
;
3701 IndexData
*index_data
;
3702 index_data
= (IndexData
*)client_data
;
3703 printCheck(index_data
);
3705 numDiags
= clang_getNumDiagnosticsInSet(diagSet
);
3706 for (i
= 0; i
!= numDiags
; ++i
) {
3707 diag
= clang_getDiagnosticInSet(diagSet
, i
);
3708 str
= clang_formatDiagnostic(diag
, clang_defaultDiagnosticDisplayOptions());
3709 cstr
= clang_getCString(str
);
3710 printf("[diagnostic]: %s\n", cstr
);
3711 clang_disposeString(str
);
3713 if (getenv("CINDEXTEST_FAILONERROR") &&
3714 clang_getDiagnosticSeverity(diag
) >= CXDiagnostic_Error
) {
3715 index_data
->fail_for_error
= 1;
3720 static CXIdxClientFile
index_enteredMainFile(CXClientData client_data
,
3721 CXFile file
, void *reserved
) {
3722 IndexData
*index_data
;
3724 index_data
= (IndexData
*)client_data
;
3725 printCheck(index_data
);
3727 index_data
->main_filename
= clang_getFileName(file
);
3729 printf("[enteredMainFile]: ");
3730 printCXIndexFile((CXIdxClientFile
)file
);
3733 return (CXIdxClientFile
)file
;
3736 static CXIdxClientFile
index_ppIncludedFile(CXClientData client_data
,
3737 const CXIdxIncludedFileInfo
*info
) {
3738 IndexData
*index_data
;
3740 index_data
= (IndexData
*)client_data
;
3741 printCheck(index_data
);
3743 printf("[ppIncludedFile]: ");
3744 printCXIndexFile((CXIdxClientFile
)info
->file
);
3745 printf(" | name: \"%s\"", info
->filename
);
3746 printf(" | hash loc: ");
3747 printCXIndexLoc(info
->hashLoc
, client_data
);
3748 printf(" | isImport: %d | isAngled: %d | isModule: %d",
3749 info
->isImport
, info
->isAngled
, info
->isModuleImport
);
3751 Mod
= clang_getModuleForFile(index_data
->TU
, (CXFile
)info
->file
);
3753 CXString str
= clang_Module_getFullName(Mod
);
3754 const char *cstr
= clang_getCString(str
);
3755 printf(" | module: %s", cstr
);
3756 clang_disposeString(str
);
3761 return (CXIdxClientFile
)info
->file
;
3764 static CXIdxClientFile
index_importedASTFile(CXClientData client_data
,
3765 const CXIdxImportedASTFileInfo
*info
) {
3766 IndexData
*index_data
;
3767 index_data
= (IndexData
*)client_data
;
3768 printCheck(index_data
);
3770 if (index_data
->importedASTs
) {
3771 CXString filename
= clang_getFileName(info
->file
);
3772 importedASTS_insert(index_data
->importedASTs
, clang_getCString(filename
));
3773 clang_disposeString(filename
);
3776 printf("[importedASTFile]: ");
3777 printCXIndexFile((CXIdxClientFile
)info
->file
);
3779 CXString name
= clang_Module_getFullName(info
->module
);
3781 printCXIndexLoc(info
->loc
, client_data
);
3782 printf(" | name: \"%s\"", clang_getCString(name
));
3783 printf(" | isImplicit: %d\n", info
->isImplicit
);
3784 clang_disposeString(name
);
3786 /* PCH file, the rest are not relevant. */
3790 return (CXIdxClientFile
)info
->file
;
3793 static CXIdxClientContainer
3794 index_startedTranslationUnit(CXClientData client_data
, void *reserved
) {
3795 IndexData
*index_data
;
3796 index_data
= (IndexData
*)client_data
;
3797 printCheck(index_data
);
3799 printf("[startedTranslationUnit]\n");
3801 #pragma GCC diagnostic push
3802 #pragma GCC diagnostic ignored "-Wcast-qual"
3804 return (CXIdxClientContainer
)"TU";
3806 #pragma GCC diagnostic pop
3810 static void index_indexDeclaration(CXClientData client_data
,
3811 const CXIdxDeclInfo
*info
) {
3812 IndexData
*index_data
;
3813 const CXIdxObjCCategoryDeclInfo
*CatInfo
;
3814 const CXIdxObjCInterfaceDeclInfo
*InterInfo
;
3815 const CXIdxObjCProtocolRefListInfo
*ProtoInfo
;
3816 const CXIdxObjCPropertyDeclInfo
*PropInfo
;
3817 const CXIdxCXXClassDeclInfo
*CXXClassInfo
;
3819 index_data
= (IndexData
*)client_data
;
3821 printEntityInfo("[indexDeclaration]", client_data
, info
->entityInfo
);
3822 printf(" | cursor: ");
3823 PrintCursor(info
->cursor
, NULL
);
3825 printCXIndexLoc(info
->loc
, client_data
);
3826 printf(" | semantic-container: ");
3827 printCXIndexContainer(info
->semanticContainer
);
3828 printf(" | lexical-container: ");
3829 printCXIndexContainer(info
->lexicalContainer
);
3830 printf(" | isRedecl: %d", info
->isRedeclaration
);
3831 printf(" | isDef: %d", info
->isDefinition
);
3832 if (info
->flags
& CXIdxDeclFlag_Skipped
) {
3833 assert(!info
->isContainer
);
3834 printf(" | isContainer: skipped");
3836 printf(" | isContainer: %d", info
->isContainer
);
3838 printf(" | isImplicit: %d\n", info
->isImplicit
);
3840 for (i
= 0; i
!= info
->numAttributes
; ++i
) {
3841 const CXIdxAttrInfo
*Attr
= info
->attributes
[i
];
3842 printf(" <attribute>: ");
3843 PrintCursor(Attr
->cursor
, NULL
);
3847 if (clang_index_isEntityObjCContainerKind(info
->entityInfo
->kind
)) {
3848 const char *kindName
= 0;
3849 CXIdxObjCContainerKind K
= clang_index_getObjCContainerDeclInfo(info
)->kind
;
3851 case CXIdxObjCContainer_ForwardRef
:
3852 kindName
= "forward-ref"; break;
3853 case CXIdxObjCContainer_Interface
:
3854 kindName
= "interface"; break;
3855 case CXIdxObjCContainer_Implementation
:
3856 kindName
= "implementation"; break;
3858 printCheck(index_data
);
3859 printf(" <ObjCContainerInfo>: kind: %s\n", kindName
);
3862 if ((CatInfo
= clang_index_getObjCCategoryDeclInfo(info
))) {
3863 printEntityInfo(" <ObjCCategoryInfo>: class", client_data
,
3864 CatInfo
->objcClass
);
3865 printf(" | cursor: ");
3866 PrintCursor(CatInfo
->classCursor
, NULL
);
3868 printCXIndexLoc(CatInfo
->classLoc
, client_data
);
3872 if ((InterInfo
= clang_index_getObjCInterfaceDeclInfo(info
))) {
3873 if (InterInfo
->superInfo
) {
3874 printBaseClassInfo(client_data
, InterInfo
->superInfo
);
3879 if ((ProtoInfo
= clang_index_getObjCProtocolRefListInfo(info
))) {
3880 printProtocolList(ProtoInfo
, client_data
);
3883 if ((PropInfo
= clang_index_getObjCPropertyDeclInfo(info
))) {
3884 if (PropInfo
->getter
) {
3885 printEntityInfo(" <getter>", client_data
, PropInfo
->getter
);
3888 if (PropInfo
->setter
) {
3889 printEntityInfo(" <setter>", client_data
, PropInfo
->setter
);
3894 if ((CXXClassInfo
= clang_index_getCXXClassDeclInfo(info
))) {
3895 for (i
= 0; i
!= CXXClassInfo
->numBases
; ++i
) {
3896 printBaseClassInfo(client_data
, CXXClassInfo
->bases
[i
]);
3901 if (info
->declAsContainer
)
3902 clang_index_setClientContainer(
3903 info
->declAsContainer
,
3904 makeClientContainer(client_data
, info
->entityInfo
, info
->loc
));
3907 static void index_indexEntityReference(CXClientData client_data
,
3908 const CXIdxEntityRefInfo
*info
) {
3909 printEntityInfo("[indexEntityReference]", client_data
,
3910 info
->referencedEntity
);
3911 printf(" | cursor: ");
3912 PrintCursor(info
->cursor
, NULL
);
3914 printCXIndexLoc(info
->loc
, client_data
);
3915 printEntityInfo(" | <parent>:", client_data
, info
->parentEntity
);
3916 printf(" | container: ");
3917 printCXIndexContainer(info
->container
);
3918 printf(" | refkind: ");
3919 switch (info
->kind
) {
3920 case CXIdxEntityRef_Direct
: printf("direct"); break;
3921 case CXIdxEntityRef_Implicit
: printf("implicit"); break;
3924 printSymbolRole(info
->role
);
3928 static int index_abortQuery(CXClientData client_data
, void *reserved
) {
3929 IndexData
*index_data
;
3930 index_data
= (IndexData
*)client_data
;
3931 return index_data
->abort
;
3934 static IndexerCallbacks IndexCB
= {
3937 index_enteredMainFile
,
3938 index_ppIncludedFile
,
3939 index_importedASTFile
,
3940 index_startedTranslationUnit
,
3941 index_indexDeclaration
,
3942 index_indexEntityReference
3945 static unsigned getIndexOptions(void) {
3946 unsigned index_opts
;
3948 if (getenv("CINDEXTEST_SUPPRESSREFS"))
3949 index_opts
|= CXIndexOpt_SuppressRedundantRefs
;
3950 if (getenv("CINDEXTEST_INDEXLOCALSYMBOLS"))
3951 index_opts
|= CXIndexOpt_IndexFunctionLocalSymbols
;
3952 if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES"))
3953 index_opts
|= CXIndexOpt_SkipParsedBodiesInSession
;
3954 if (getenv("CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS"))
3955 index_opts
|= CXIndexOpt_IndexImplicitTemplateInstantiations
;
3960 static int index_compile_args(int num_args
, const char **args
,
3961 CXIndexAction idxAction
,
3962 ImportedASTFilesData
*importedASTs
,
3963 const char *check_prefix
) {
3964 IndexData index_data
;
3965 unsigned index_opts
;
3968 if (num_args
== 0) {
3969 fprintf(stderr
, "no compiler arguments\n");
3973 index_data
.check_prefix
= check_prefix
;
3974 index_data
.first_check_printed
= 0;
3975 index_data
.fail_for_error
= 0;
3976 index_data
.abort
= 0;
3977 index_data
.main_filename
= createCXString("");
3978 index_data
.importedASTs
= importedASTs
;
3979 index_data
.strings
= NULL
;
3980 index_data
.TU
= NULL
;
3982 index_opts
= getIndexOptions();
3983 result
= clang_indexSourceFile(idxAction
, &index_data
,
3984 &IndexCB
,sizeof(IndexCB
), index_opts
,
3985 0, args
, num_args
, 0, 0, 0,
3986 getDefaultParsingOptions());
3987 if (result
!= CXError_Success
)
3988 describeLibclangFailure(result
);
3990 if (index_data
.fail_for_error
)
3993 clang_disposeString(index_data
.main_filename
);
3994 free_client_data(&index_data
);
3998 static int index_ast_file(const char *ast_file
,
4000 CXIndexAction idxAction
,
4001 ImportedASTFilesData
*importedASTs
,
4002 const char *check_prefix
) {
4003 CXTranslationUnit TU
;
4004 IndexData index_data
;
4005 unsigned index_opts
;
4008 if (!CreateTranslationUnit(Idx
, ast_file
, &TU
))
4011 index_data
.check_prefix
= check_prefix
;
4012 index_data
.first_check_printed
= 0;
4013 index_data
.fail_for_error
= 0;
4014 index_data
.abort
= 0;
4015 index_data
.main_filename
= createCXString("");
4016 index_data
.importedASTs
= importedASTs
;
4017 index_data
.strings
= NULL
;
4020 index_opts
= getIndexOptions();
4021 result
= clang_indexTranslationUnit(idxAction
, &index_data
,
4022 &IndexCB
,sizeof(IndexCB
),
4024 if (index_data
.fail_for_error
)
4027 clang_disposeTranslationUnit(TU
);
4028 clang_disposeString(index_data
.main_filename
);
4029 free_client_data(&index_data
);
4033 static int index_file(int argc
, const char **argv
, int full
) {
4034 const char *check_prefix
;
4036 CXIndexAction idxAction
;
4037 ImportedASTFilesData
*importedASTs
;
4042 if (strstr(argv
[0], "-check-prefix=") == argv
[0]) {
4043 check_prefix
= argv
[0] + strlen("-check-prefix=");
4049 if (!(Idx
= clang_createIndex(/* excludeDeclsFromPCH */ 1,
4050 /* displayDiagnostics=*/1))) {
4051 fprintf(stderr
, "Could not create Index\n");
4054 idxAction
= clang_IndexAction_create(Idx
);
4057 importedASTs
= importedASTs_create();
4059 result
= index_compile_args(argc
, argv
, idxAction
, importedASTs
, check_prefix
);
4065 for (i
= 0; i
< importedASTs
->num_files
&& result
== 0; ++i
) {
4066 result
= index_ast_file(importedASTs
->filenames
[i
], Idx
, idxAction
,
4067 importedASTs
, check_prefix
);
4072 importedASTs_dispose(importedASTs
);
4073 clang_IndexAction_dispose(idxAction
);
4074 clang_disposeIndex(Idx
);
4078 static int index_tu(int argc
, const char **argv
) {
4079 const char *check_prefix
;
4081 CXIndexAction idxAction
;
4086 if (strstr(argv
[0], "-check-prefix=") == argv
[0]) {
4087 check_prefix
= argv
[0] + strlen("-check-prefix=");
4093 if (!(Idx
= clang_createIndex(/* excludeDeclsFromPCH */ 1,
4094 /* displayDiagnostics=*/1))) {
4095 fprintf(stderr
, "Could not create Index\n");
4098 idxAction
= clang_IndexAction_create(Idx
);
4100 result
= index_ast_file(argv
[0], Idx
, idxAction
,
4101 /*importedASTs=*/0, check_prefix
);
4103 clang_IndexAction_dispose(idxAction
);
4104 clang_disposeIndex(Idx
);
4108 static int index_compile_db(int argc
, const char **argv
) {
4109 const char *check_prefix
;
4111 CXIndexAction idxAction
;
4116 if (strstr(argv
[0], "-check-prefix=") == argv
[0]) {
4117 check_prefix
= argv
[0] + strlen("-check-prefix=");
4124 fprintf(stderr
, "no compilation database\n");
4128 if (!(Idx
= clang_createIndex(/* excludeDeclsFromPCH */ 1,
4129 /* displayDiagnostics=*/1))) {
4130 fprintf(stderr
, "Could not create Index\n");
4133 idxAction
= clang_IndexAction_create(Idx
);
4136 const char *database
= argv
[0];
4137 CXCompilationDatabase db
= 0;
4138 CXCompileCommands CCmds
= 0;
4139 CXCompileCommand CCmd
;
4140 CXCompilationDatabase_Error ec
;
4142 #define MAX_COMPILE_ARGS 512
4143 CXString cxargs
[MAX_COMPILE_ARGS
];
4144 const char *args
[MAX_COMPILE_ARGS
];
4148 int i
, a
, numCmds
, numArgs
;
4150 len
= strlen(database
);
4151 tmp
= (char *) malloc(len
+1);
4153 memcpy(tmp
, database
, len
+1);
4154 buildDir
= dirname(tmp
);
4156 db
= clang_CompilationDatabase_fromDirectory(buildDir
, &ec
);
4160 if (ec
!=CXCompilationDatabase_NoError
) {
4161 printf("unexpected error %d code while loading compilation database\n", ec
);
4166 if (chdir(buildDir
) != 0) {
4167 printf("Could not chdir to %s\n", buildDir
);
4172 CCmds
= clang_CompilationDatabase_getAllCompileCommands(db
);
4174 printf("compilation db is empty\n");
4179 numCmds
= clang_CompileCommands_getSize(CCmds
);
4182 fprintf(stderr
, "should not get an empty compileCommand set\n");
4187 for (i
=0; i
<numCmds
&& errorCode
== 0; ++i
) {
4188 CCmd
= clang_CompileCommands_getCommand(CCmds
, i
);
4190 wd
= clang_CompileCommand_getDirectory(CCmd
);
4191 if (chdir(clang_getCString(wd
)) != 0) {
4192 printf("Could not chdir to %s\n", clang_getCString(wd
));
4196 clang_disposeString(wd
);
4198 numArgs
= clang_CompileCommand_getNumArgs(CCmd
);
4199 if (numArgs
> MAX_COMPILE_ARGS
){
4200 fprintf(stderr
, "got more compile arguments than maximum\n");
4204 for (a
=0; a
<numArgs
; ++a
) {
4205 cxargs
[a
] = clang_CompileCommand_getArg(CCmd
, a
);
4206 args
[a
] = clang_getCString(cxargs
[a
]);
4209 errorCode
= index_compile_args(numArgs
, args
, idxAction
,
4210 /*importedASTs=*/0, check_prefix
);
4212 for (a
=0; a
<numArgs
; ++a
)
4213 clang_disposeString(cxargs
[a
]);
4216 printf("database loading failed with error code %d.\n", ec
);
4221 clang_CompileCommands_dispose(CCmds
);
4222 clang_CompilationDatabase_dispose(db
);
4227 clang_IndexAction_dispose(idxAction
);
4228 clang_disposeIndex(Idx
);
4232 int perform_token_annotation(int argc
, const char **argv
) {
4233 const char *input
= argv
[1];
4235 unsigned line
, second_line
;
4236 unsigned column
, second_column
;
4238 CXTranslationUnit TU
= 0;
4240 struct CXUnsavedFile
*unsaved_files
= 0;
4241 int num_unsaved_files
= 0;
4243 unsigned num_tokens
;
4244 CXSourceRange range
;
4245 CXSourceLocation startLoc
, endLoc
;
4247 CXCursor
*cursors
= 0;
4248 CXSourceRangeList
*skipped_ranges
= 0;
4249 enum CXErrorCode Err
;
4252 input
+= strlen("-test-annotate-tokens=");
4253 if ((errorCode
= parse_file_line_column(input
, &filename
, &line
, &column
,
4254 &second_line
, &second_column
)))
4257 if (parse_remapped_files(argc
, argv
, 2, &unsaved_files
, &num_unsaved_files
)) {
4262 CIdx
= clang_createIndex(0, 1);
4263 Err
= clang_parseTranslationUnit2(CIdx
, argv
[argc
- 1],
4264 argv
+ num_unsaved_files
+ 2,
4265 argc
- num_unsaved_files
- 3,
4268 getDefaultParsingOptions(), &TU
);
4269 if (Err
!= CXError_Success
) {
4270 fprintf(stderr
, "unable to parse input\n");
4271 describeLibclangFailure(Err
);
4272 clang_disposeIndex(CIdx
);
4274 free_remapped_files(unsaved_files
, num_unsaved_files
);
4279 if (checkForErrors(TU
) != 0) {
4284 if (getenv("CINDEXTEST_EDITING")) {
4285 for (i
= 0; i
< 5; ++i
) {
4286 Err
= clang_reparseTranslationUnit(TU
, num_unsaved_files
, unsaved_files
,
4287 clang_defaultReparseOptions(TU
));
4288 if (Err
!= CXError_Success
) {
4289 fprintf(stderr
, "Unable to reparse translation unit!\n");
4290 describeLibclangFailure(Err
);
4297 if (checkForErrors(TU
) != 0) {
4302 file
= clang_getFile(TU
, filename
);
4304 fprintf(stderr
, "file %s is not in this translation unit\n", filename
);
4309 startLoc
= clang_getLocation(TU
, file
, line
, column
);
4310 if (clang_equalLocations(clang_getNullLocation(), startLoc
)) {
4311 fprintf(stderr
, "invalid source location %s:%d:%d\n", filename
, line
,
4317 endLoc
= clang_getLocation(TU
, file
, second_line
, second_column
);
4318 if (clang_equalLocations(clang_getNullLocation(), endLoc
)) {
4319 fprintf(stderr
, "invalid source location %s:%d:%d\n", filename
,
4320 second_line
, second_column
);
4325 range
= clang_getRange(startLoc
, endLoc
);
4326 clang_tokenize(TU
, range
, &tokens
, &num_tokens
);
4328 if (checkForErrors(TU
) != 0) {
4333 cursors
= (CXCursor
*)malloc(num_tokens
* sizeof(CXCursor
));
4335 clang_annotateTokens(TU
, tokens
, num_tokens
, cursors
);
4337 if (checkForErrors(TU
) != 0) {
4342 skipped_ranges
= clang_getSkippedRanges(TU
, file
);
4343 for (i
= 0; i
!= skipped_ranges
->count
; ++i
) {
4344 unsigned start_line
, start_column
, end_line
, end_column
;
4345 clang_getFileLocation(clang_getRangeStart(skipped_ranges
->ranges
[i
]), 0,
4346 &start_line
, &start_column
, 0);
4347 clang_getFileLocation(clang_getRangeEnd(skipped_ranges
->ranges
[i
]), 0,
4348 &end_line
, &end_column
, 0);
4349 printf("Skipping: ");
4350 PrintExtent(stdout
, start_line
, start_column
, end_line
, end_column
);
4353 clang_disposeSourceRangeList(skipped_ranges
);
4355 for (i
= 0; i
!= num_tokens
; ++i
) {
4356 const char *kind
= "<unknown>";
4357 CXString spelling
= clang_getTokenSpelling(TU
, tokens
[i
]);
4358 CXSourceRange extent
= clang_getTokenExtent(TU
, tokens
[i
]);
4359 unsigned start_line
, start_column
, end_line
, end_column
;
4361 switch (clang_getTokenKind(tokens
[i
])) {
4362 case CXToken_Punctuation
: kind
= "Punctuation"; break;
4363 case CXToken_Keyword
: kind
= "Keyword"; break;
4364 case CXToken_Identifier
: kind
= "Identifier"; break;
4365 case CXToken_Literal
: kind
= "Literal"; break;
4366 case CXToken_Comment
: kind
= "Comment"; break;
4368 clang_getFileLocation(clang_getRangeStart(extent
), 0, &start_line
,
4370 clang_getFileLocation(clang_getRangeEnd(extent
), 0, &end_line
, &end_column
,
4372 printf("%s: \"%s\" ", kind
, clang_getCString(spelling
));
4373 clang_disposeString(spelling
);
4374 PrintExtent(stdout
, start_line
, start_column
, end_line
, end_column
);
4375 if (!clang_isInvalid(cursors
[i
].kind
)) {
4377 PrintCursor(cursors
[i
], NULL
);
4382 clang_disposeTokens(TU
, tokens
, num_tokens
);
4385 PrintDiagnostics(TU
);
4386 clang_disposeTranslationUnit(TU
);
4387 clang_disposeIndex(CIdx
);
4389 free_remapped_files(unsaved_files
, num_unsaved_files
);
4394 perform_test_compilation_db(const char *database
, int argc
, const char **argv
) {
4395 CXCompilationDatabase db
;
4396 CXCompileCommands CCmds
;
4397 CXCompileCommand CCmd
;
4398 CXCompilationDatabase_Error ec
;
4405 int i
, j
, a
, numCmds
, numArgs
;
4407 len
= strlen(database
);
4408 tmp
= (char *) malloc(len
+1);
4410 memcpy(tmp
, database
, len
+1);
4411 buildDir
= dirname(tmp
);
4413 db
= clang_CompilationDatabase_fromDirectory(buildDir
, &ec
);
4417 if (ec
!=CXCompilationDatabase_NoError
) {
4418 printf("unexpected error %d code while loading compilation database\n", ec
);
4423 for (i
=0; i
<argc
&& errorCode
==0; ) {
4424 if (strcmp(argv
[i
],"lookup")==0){
4425 CCmds
= clang_CompilationDatabase_getCompileCommands(db
, argv
[i
+1]);
4428 printf("file %s not found in compilation db\n", argv
[i
+1]);
4433 numCmds
= clang_CompileCommands_getSize(CCmds
);
4436 fprintf(stderr
, "should not get an empty compileCommand set for file"
4437 " '%s'\n", argv
[i
+1]);
4442 for (j
=0; j
<numCmds
; ++j
) {
4443 CCmd
= clang_CompileCommands_getCommand(CCmds
, j
);
4445 wd
= clang_CompileCommand_getDirectory(CCmd
);
4446 printf("workdir:'%s'", clang_getCString(wd
));
4447 clang_disposeString(wd
);
4449 printf(" cmdline:'");
4450 numArgs
= clang_CompileCommand_getNumArgs(CCmd
);
4451 for (a
=0; a
<numArgs
; ++a
) {
4453 arg
= clang_CompileCommand_getArg(CCmd
, a
);
4454 printf("%s", clang_getCString(arg
));
4455 clang_disposeString(arg
);
4460 clang_CompileCommands_dispose(CCmds
);
4465 clang_CompilationDatabase_dispose(db
);
4467 printf("database loading failed with error code %d.\n", ec
);
4477 /******************************************************************************/
4479 /******************************************************************************/
4481 static int insufficient_usr(const char *kind
, const char *usage
) {
4482 fprintf(stderr
, "USR for '%s' requires: %s\n", kind
, usage
);
4486 static unsigned isUSR(const char *s
) {
4487 return s
[0] == 'c' && s
[1] == ':';
4490 static int not_usr(const char *s
, const char *arg
) {
4491 fprintf(stderr
, "'%s' argument ('%s') is not a USR\n", s
, arg
);
4495 static void print_usr(CXString usr
) {
4496 const char *s
= clang_getCString(usr
);
4498 clang_disposeString(usr
);
4501 static void display_usrs(void) {
4502 fprintf(stderr
, "-print-usrs options:\n"
4503 " ObjCCategory <class name> <category name>\n"
4504 " ObjCClass <class name>\n"
4505 " ObjCIvar <ivar name> <class USR>\n"
4506 " ObjCMethod <selector> [0=class method|1=instance method] "
4508 " ObjCProperty <property name> <class USR>\n"
4509 " ObjCProtocol <protocol name>\n");
4512 int print_usrs(const char **I
, const char **E
) {
4514 const char *kind
= *I
;
4515 unsigned len
= strlen(kind
);
4518 if (memcmp(kind
, "ObjCIvar", 8) == 0) {
4520 return insufficient_usr(kind
, "<ivar name> <class USR>");
4522 return not_usr("<class USR>", I
[2]);
4524 CXString x
= createCXString(I
[2]);
4525 print_usr(clang_constructUSR_ObjCIvar(I
[1], x
));
4533 if (memcmp(kind
, "ObjCClass", 9) == 0) {
4535 return insufficient_usr(kind
, "<class name>");
4536 print_usr(clang_constructUSR_ObjCClass(I
[1]));
4542 if (memcmp(kind
, "ObjCMethod", 10) == 0) {
4544 return insufficient_usr(kind
, "<method selector> "
4545 "[0=class method|1=instance method] <class USR>");
4547 return not_usr("<class USR>", I
[3]);
4549 CXString x
= createCXString(I
[3]);
4550 print_usr(clang_constructUSR_ObjCMethod(I
[1], atoi(I
[2]), x
));
4557 if (memcmp(kind
, "ObjCCategory", 12) == 0) {
4559 return insufficient_usr(kind
, "<class name> <category name>");
4560 print_usr(clang_constructUSR_ObjCCategory(I
[1], I
[2]));
4564 if (memcmp(kind
, "ObjCProtocol", 12) == 0) {
4566 return insufficient_usr(kind
, "<protocol name>");
4567 print_usr(clang_constructUSR_ObjCProtocol(I
[1]));
4571 if (memcmp(kind
, "ObjCProperty", 12) == 0) {
4573 return insufficient_usr(kind
, "<property name> <class USR>");
4575 return not_usr("<class USR>", I
[2]);
4577 CXString x
= createCXString(I
[2]);
4578 print_usr(clang_constructUSR_ObjCProperty(I
[1], x
));
4591 fprintf(stderr
, "Invalid USR kind: %s\n", *I
);
4598 int print_usrs_file(const char *file_name
) {
4600 const char *args
[128];
4601 unsigned numChars
= 0;
4603 FILE *fp
= fopen(file_name
, "r");
4605 fprintf(stderr
, "error: cannot open '%s'\n", file_name
);
4609 /* This code is not really all that safe, but it works fine for testing. */
4619 line
[numChars
] = '\0';
4622 if (line
[0] == '/' && line
[1] == '/')
4625 s
= strtok(line
, " ");
4631 if (print_usrs(&args
[0], &args
[i
]))
4635 line
[numChars
++] = c
;
4642 /******************************************************************************/
4643 /* Command line processing. */
4644 /******************************************************************************/
4645 int write_pch_file(const char *filename
, int argc
, const char *argv
[]) {
4647 CXTranslationUnit TU
;
4648 struct CXUnsavedFile
*unsaved_files
= 0;
4649 int num_unsaved_files
= 0;
4650 enum CXErrorCode Err
;
4653 Idx
= clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1);
4655 if (parse_remapped_files(argc
, argv
, 0, &unsaved_files
, &num_unsaved_files
)) {
4656 clang_disposeIndex(Idx
);
4660 Err
= clang_parseTranslationUnit2(
4661 Idx
, 0, argv
+ num_unsaved_files
, argc
- num_unsaved_files
,
4662 unsaved_files
, num_unsaved_files
,
4663 CXTranslationUnit_Incomplete
|
4664 CXTranslationUnit_DetailedPreprocessingRecord
|
4665 CXTranslationUnit_ForSerialization
,
4667 if (Err
!= CXError_Success
) {
4668 fprintf(stderr
, "Unable to load translation unit!\n");
4669 describeLibclangFailure(Err
);
4670 free_remapped_files(unsaved_files
, num_unsaved_files
);
4671 clang_disposeTranslationUnit(TU
);
4672 clang_disposeIndex(Idx
);
4676 switch (clang_saveTranslationUnit(TU
, filename
,
4677 clang_defaultSaveOptions(TU
))) {
4678 case CXSaveError_None
:
4681 case CXSaveError_TranslationErrors
:
4682 fprintf(stderr
, "Unable to write PCH file %s: translation errors\n",
4687 case CXSaveError_InvalidTU
:
4688 fprintf(stderr
, "Unable to write PCH file %s: invalid translation unit\n",
4693 case CXSaveError_Unknown
:
4695 fprintf(stderr
, "Unable to write PCH file %s: unknown error \n", filename
);
4700 clang_disposeTranslationUnit(TU
);
4701 free_remapped_files(unsaved_files
, num_unsaved_files
);
4702 clang_disposeIndex(Idx
);
4706 /******************************************************************************/
4707 /* Serialized diagnostics. */
4708 /******************************************************************************/
4710 static const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error
) {
4712 case CXLoadDiag_CannotLoad
: return "Cannot Load File";
4713 case CXLoadDiag_None
: break;
4714 case CXLoadDiag_Unknown
: return "Unknown";
4715 case CXLoadDiag_InvalidFile
: return "Invalid File";
4720 static const char *getSeverityString(enum CXDiagnosticSeverity severity
) {
4722 case CXDiagnostic_Note
: return "note";
4723 case CXDiagnostic_Error
: return "error";
4724 case CXDiagnostic_Fatal
: return "fatal";
4725 case CXDiagnostic_Ignored
: return "ignored";
4726 case CXDiagnostic_Warning
: return "warning";
4731 static void printIndent(unsigned indent
) {
4734 fprintf(stderr
, "+");
4736 while (indent
> 0) {
4737 fprintf(stderr
, "-");
4742 static void printLocation(CXSourceLocation L
) {
4745 unsigned line
, column
, offset
;
4747 clang_getExpansionLocation(L
, &File
, &line
, &column
, &offset
);
4748 FileName
= clang_getFileName(File
);
4750 fprintf(stderr
, "%s:%d:%d", clang_getCString(FileName
), line
, column
);
4751 clang_disposeString(FileName
);
4754 static void printRanges(CXDiagnostic D
, unsigned indent
) {
4755 unsigned i
, n
= clang_getDiagnosticNumRanges(D
);
4757 for (i
= 0; i
< n
; ++i
) {
4758 CXSourceLocation Start
, End
;
4759 CXSourceRange SR
= clang_getDiagnosticRange(D
, i
);
4760 Start
= clang_getRangeStart(SR
);
4761 End
= clang_getRangeEnd(SR
);
4763 printIndent(indent
);
4764 fprintf(stderr
, "Range: ");
4765 printLocation(Start
);
4766 fprintf(stderr
, " ");
4768 fprintf(stderr
, "\n");
4772 static void printFixIts(CXDiagnostic D
, unsigned indent
) {
4773 unsigned i
, n
= clang_getDiagnosticNumFixIts(D
);
4774 fprintf(stderr
, "Number FIXITs = %d\n", n
);
4775 for (i
= 0 ; i
< n
; ++i
) {
4776 CXSourceRange ReplacementRange
;
4778 text
= clang_getDiagnosticFixIt(D
, i
, &ReplacementRange
);
4780 printIndent(indent
);
4781 fprintf(stderr
, "FIXIT: (");
4782 printLocation(clang_getRangeStart(ReplacementRange
));
4783 fprintf(stderr
, " - ");
4784 printLocation(clang_getRangeEnd(ReplacementRange
));
4785 fprintf(stderr
, "): \"%s\"\n", clang_getCString(text
));
4786 clang_disposeString(text
);
4790 static void printDiagnosticSet(CXDiagnosticSet Diags
, unsigned indent
) {
4796 n
= clang_getNumDiagnosticsInSet(Diags
);
4797 for (i
= 0; i
< n
; ++i
) {
4798 CXSourceLocation DiagLoc
;
4801 CXString FileName
, DiagSpelling
, DiagOption
, DiagCat
;
4802 unsigned line
, column
, offset
;
4803 const char *FileNameStr
= 0, *DiagOptionStr
= 0, *DiagCatStr
= 0;
4805 D
= clang_getDiagnosticInSet(Diags
, i
);
4806 DiagLoc
= clang_getDiagnosticLocation(D
);
4807 clang_getExpansionLocation(DiagLoc
, &File
, &line
, &column
, &offset
);
4808 FileName
= clang_getFileName(File
);
4809 FileNameStr
= clang_getCString(FileName
);
4810 DiagSpelling
= clang_getDiagnosticSpelling(D
);
4812 printIndent(indent
);
4814 fprintf(stderr
, "%s:%d:%d: %s: %s",
4815 FileNameStr
? FileNameStr
: "(null)",
4818 getSeverityString(clang_getDiagnosticSeverity(D
)),
4819 clang_getCString(DiagSpelling
));
4821 DiagOption
= clang_getDiagnosticOption(D
, 0);
4822 DiagOptionStr
= clang_getCString(DiagOption
);
4823 if (DiagOptionStr
) {
4824 fprintf(stderr
, " [%s]", DiagOptionStr
);
4827 DiagCat
= clang_getDiagnosticCategoryText(D
);
4828 DiagCatStr
= clang_getCString(DiagCat
);
4830 fprintf(stderr
, " [%s]", DiagCatStr
);
4833 fprintf(stderr
, "\n");
4835 printRanges(D
, indent
);
4836 printFixIts(D
, indent
);
4838 /* Print subdiagnostics. */
4839 printDiagnosticSet(clang_getChildDiagnostics(D
), indent
+2);
4841 clang_disposeString(FileName
);
4842 clang_disposeString(DiagSpelling
);
4843 clang_disposeString(DiagOption
);
4844 clang_disposeString(DiagCat
);
4848 static int read_diagnostics(const char *filename
) {
4849 enum CXLoadDiag_Error error
;
4850 CXString errorString
;
4851 CXDiagnosticSet Diags
= 0;
4853 Diags
= clang_loadDiagnostics(filename
, &error
, &errorString
);
4855 fprintf(stderr
, "Trouble deserializing file (%s): %s\n",
4856 getDiagnosticCodeStr(error
),
4857 clang_getCString(errorString
));
4858 clang_disposeString(errorString
);
4862 printDiagnosticSet(Diags
, 0);
4863 fprintf(stderr
, "Number of diagnostics: %d\n",
4864 clang_getNumDiagnosticsInSet(Diags
));
4865 clang_disposeDiagnosticSet(Diags
);
4869 static int perform_print_build_session_timestamp(void) {
4870 printf("%lld\n", clang_getBuildSessionTimestamp());
4874 static int perform_test_single_symbol_sgf(const char *input
, int argc
,
4875 const char *argv
[]) {
4877 CXTranslationUnit TU
;
4879 struct CXUnsavedFile
*unsaved_files
= 0;
4880 int num_unsaved_files
= 0;
4881 enum CXErrorCode Err
;
4886 usr
= input
+ strlen("-single-symbol-sgf-for=");
4888 Idx
= createIndexWithInvocationEmissionPath(/* excludeDeclsFromPCH */ 1,
4889 /* displayDiagnostics=*/0);
4893 if (parse_remapped_files(argc
, argv
, 0, &unsaved_files
, &num_unsaved_files
)) {
4898 Err
= clang_parseTranslationUnit2(
4899 Idx
, 0, argv
+ num_unsaved_files
, argc
- num_unsaved_files
, unsaved_files
,
4900 num_unsaved_files
, getDefaultParsingOptions(), &TU
);
4901 if (Err
!= CXError_Success
) {
4902 fprintf(stderr
, "Unable to load translation unit!\n");
4903 describeLibclangFailure(Err
);
4905 goto free_remapped_files
;
4908 Err
= clang_createAPISet(TU
, &API
);
4909 if (Err
!= CXError_Success
) {
4911 "Unable to create API Set for API information extraction!\n");
4916 SGF
= clang_getSymbolGraphForUSR(usr
, API
);
4917 printf("%s", clang_getCString(SGF
));
4919 clang_disposeString(SGF
);
4920 clang_disposeAPISet(API
);
4922 clang_disposeTranslationUnit(TU
);
4923 free_remapped_files
:
4924 free_remapped_files(unsaved_files
, num_unsaved_files
);
4926 clang_disposeIndex(Idx
);
4930 static void inspect_single_symbol_sgf_cursor(CXCursor Cursor
) {
4931 CXSourceLocation CursorLoc
;
4934 unsigned line
, column
;
4935 CursorLoc
= clang_getCursorLocation(Cursor
);
4936 clang_getSpellingLocation(CursorLoc
, 0, &line
, &column
, 0);
4938 SGFData
= clang_getSymbolGraphForCursor(Cursor
);
4939 SGF
= clang_getCString(SGFData
);
4941 printf("%d:%d: %s\n", line
, column
, SGF
);
4943 clang_disposeString(SGFData
);
4946 /******************************************************************************/
4947 /* Command line processing. */
4948 /******************************************************************************/
4950 static CXCursorVisitor
GetVisitor(const char *s
) {
4952 return FilteredPrintingVisitor
;
4953 if (strcmp(s
, "-usrs") == 0)
4955 if (strncmp(s
, "-memory-usage", 13) == 0)
4956 return GetVisitor(s
+ 13);
4960 static void print_usage(void) {
4962 "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
4963 " c-index-test -code-completion-timing=<site> <compiler arguments>\n"
4964 " c-index-test -cursor-at=<site> <compiler arguments>\n"
4965 " c-index-test -evaluate-cursor-at=<site> <compiler arguments>\n"
4966 " c-index-test -get-macro-info-cursor-at=<site> <compiler arguments>\n"
4967 " c-index-test -file-refs-at=<site> <compiler arguments>\n"
4968 " c-index-test -file-includes-in=<filename> <compiler arguments>\n");
4970 " c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
4971 " c-index-test -index-file-full [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
4972 " c-index-test -index-tu [-check-prefix=<FileCheck prefix>] <AST file>\n"
4973 " c-index-test -index-compile-db [-check-prefix=<FileCheck prefix>] <compilation database>\n"
4974 " c-index-test -test-file-scan <AST file> <source file> "
4975 "[FileCheck prefix]\n");
4977 " c-index-test -test-load-tu <AST file> <symbol filter> "
4978 "[FileCheck prefix]\n"
4979 " c-index-test -test-load-tu-usrs <AST file> <symbol filter> "
4980 "[FileCheck prefix]\n"
4981 " c-index-test -test-load-source <symbol filter> {<args>}*\n");
4983 " c-index-test -test-load-source-memory-usage "
4984 "<symbol filter> {<args>}*\n"
4985 " c-index-test -test-load-source-reparse <trials> <symbol filter> "
4987 " c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
4988 " c-index-test -test-load-source-usrs-memory-usage "
4989 "<symbol filter> {<args>}*\n"
4990 " c-index-test -test-annotate-tokens=<range> {<args>}*\n"
4991 " c-index-test -test-inclusion-stack-source {<args>}*\n"
4992 " c-index-test -test-inclusion-stack-tu <AST file>\n");
4994 " c-index-test -test-print-linkage-source {<args>}*\n"
4995 " c-index-test -test-print-visibility {<args>}*\n"
4996 " c-index-test -test-print-type {<args>}*\n"
4997 " c-index-test -test-print-type-size {<args>}*\n"
4998 " c-index-test -test-print-bitwidth {<args>}*\n"
4999 " c-index-test -test-print-target-info {<args>}*\n"
5000 " c-index-test -test-print-type-declaration {<args>}*\n"
5001 " c-index-test -print-usr [<CursorKind> {<args>}]*\n"
5002 " c-index-test -print-usr-file <file>\n");
5004 " c-index-test -single-symbol-sgfs <symbol filter> {<args>*}\n"
5005 " c-index-test -single-symbol-sgf-at=<site> {<args>*}\n"
5006 " c-index-test -single-symbol-sgf-for=<usr> {<args>}*\n");
5008 " c-index-test -write-pch <file> <compiler arguments>\n"
5009 " c-index-test -compilation-db [lookup <filename>] database\n");
5011 " c-index-test -print-build-session-timestamp\n");
5013 " c-index-test -read-diagnostics <file>\n\n");
5015 " <symbol filter> values:\n%s",
5016 " all - load all symbols, including those from PCH\n"
5017 " local - load all symbols except those in PCH\n"
5018 " category - only load ObjC categories (non-PCH)\n"
5019 " interface - only load ObjC interfaces (non-PCH)\n"
5020 " protocol - only load ObjC protocols (non-PCH)\n"
5021 " function - only load functions (non-PCH)\n"
5022 " typedef - only load typdefs (non-PCH)\n"
5023 " scan-function - scan function bodies (non-PCH)\n\n");
5028 int cindextest_main(int argc
, const char **argv
) {
5029 clang_enableStackTraces();
5030 if (argc
> 2 && strcmp(argv
[1], "-read-diagnostics") == 0)
5031 return read_diagnostics(argv
[2]);
5032 if (argc
> 2 && strstr(argv
[1], "-code-completion-at=") == argv
[1])
5033 return perform_code_completion(argc
, argv
, 0);
5034 if (argc
> 2 && strstr(argv
[1], "-code-completion-timing=") == argv
[1])
5035 return perform_code_completion(argc
, argv
, 1);
5036 if (argc
> 2 && strstr(argv
[1], "-cursor-at=") == argv
[1])
5037 return inspect_cursor_at(argc
, argv
, "-cursor-at=", inspect_print_cursor
);
5038 if (argc
> 2 && strstr(argv
[1], "-evaluate-cursor-at=") == argv
[1])
5039 return inspect_cursor_at(argc
, argv
, "-evaluate-cursor-at=",
5040 inspect_evaluate_cursor
);
5041 if (argc
> 2 && strstr(argv
[1], "-get-macro-info-cursor-at=") == argv
[1])
5042 return inspect_cursor_at(argc
, argv
, "-get-macro-info-cursor-at=",
5043 inspect_macroinfo_cursor
);
5044 if (argc
> 2 && strstr(argv
[1], "-file-refs-at=") == argv
[1])
5045 return find_file_refs_at(argc
, argv
);
5046 if (argc
> 2 && strstr(argv
[1], "-file-includes-in=") == argv
[1])
5047 return find_file_includes_in(argc
, argv
);
5048 if (argc
> 2 && strcmp(argv
[1], "-index-file") == 0)
5049 return index_file(argc
- 2, argv
+ 2, /*full=*/0);
5050 if (argc
> 2 && strcmp(argv
[1], "-index-file-full") == 0)
5051 return index_file(argc
- 2, argv
+ 2, /*full=*/1);
5052 if (argc
> 2 && strcmp(argv
[1], "-index-tu") == 0)
5053 return index_tu(argc
- 2, argv
+ 2);
5054 if (argc
> 2 && strcmp(argv
[1], "-index-compile-db") == 0)
5055 return index_compile_db(argc
- 2, argv
+ 2);
5056 else if (argc
>= 4 && strncmp(argv
[1], "-test-load-tu", 13) == 0) {
5057 CXCursorVisitor I
= GetVisitor(argv
[1] + 13);
5059 return perform_test_load_tu(argv
[2], argv
[3], argc
>= 5 ? argv
[4] : 0, I
,
5062 else if (argc
>= 5 && strncmp(argv
[1], "-test-load-source-reparse", 25) == 0){
5063 CXCursorVisitor I
= GetVisitor(argv
[1] + 25);
5065 int trials
= atoi(argv
[2]);
5066 return perform_test_reparse_source(argc
- 4, argv
+ 4, trials
, argv
[3], I
,
5070 else if (argc
>= 4 && strncmp(argv
[1], "-test-load-source", 17) == 0) {
5071 CXCursorVisitor I
= GetVisitor(argv
[1] + 17);
5073 PostVisitTU postVisit
= 0;
5074 if (strstr(argv
[1], "-memory-usage"))
5075 postVisit
= PrintMemoryUsage
;
5078 return perform_test_load_source(argc
- 3, argv
+ 3, argv
[2], I
,
5081 else if (argc
>= 3 && strcmp(argv
[1], "-single-file-parse") == 0)
5082 return perform_single_file_parse(argv
[2]);
5083 else if (argc
>= 3 && strcmp(argv
[1], "-retain-excluded-conditional-blocks") == 0)
5084 return perform_file_retain_excluded_cb(argv
[2]);
5085 else if (argc
>= 4 && strcmp(argv
[1], "-test-file-scan") == 0)
5086 return perform_file_scan(argv
[2], argv
[3],
5087 argc
>= 5 ? argv
[4] : 0);
5088 else if (argc
> 2 && strstr(argv
[1], "-test-annotate-tokens=") == argv
[1])
5089 return perform_token_annotation(argc
, argv
);
5090 else if (argc
> 2 && strcmp(argv
[1], "-test-inclusion-stack-source") == 0)
5091 return perform_test_load_source(argc
- 2, argv
+ 2, "all", NULL
,
5092 PrintInclusionStack
);
5093 else if (argc
> 2 && strcmp(argv
[1], "-test-inclusion-stack-tu") == 0)
5094 return perform_test_load_tu(argv
[2], "all", NULL
, NULL
,
5095 PrintInclusionStack
);
5096 else if (argc
> 2 && strcmp(argv
[1], "-test-print-linkage-source") == 0)
5097 return perform_test_load_source(argc
- 2, argv
+ 2, "all", PrintLinkage
,
5099 else if (argc
> 2 && strcmp(argv
[1], "-test-print-visibility") == 0)
5100 return perform_test_load_source(argc
- 2, argv
+ 2, "all", PrintVisibility
,
5102 else if (argc
> 2 && strcmp(argv
[1], "-test-print-type") == 0)
5103 return perform_test_load_source(argc
- 2, argv
+ 2, "all",
5105 else if (argc
> 2 && strcmp(argv
[1], "-test-print-type-size") == 0)
5106 return perform_test_load_source(argc
- 2, argv
+ 2, "all",
5108 else if (argc
> 2 && strcmp(argv
[1], "-test-print-type-declaration") == 0)
5109 return perform_test_load_source(argc
- 2, argv
+ 2, "all",
5110 PrintTypeDeclaration
, 0);
5111 else if (argc
> 2 && strcmp(argv
[1], "-test-print-decl-attributes") == 0)
5112 return perform_test_load_source(argc
- 2, argv
+ 2, "all",
5113 PrintDeclAttributes
, 0);
5114 else if (argc
> 2 && strcmp(argv
[1], "-test-print-bitwidth") == 0)
5115 return perform_test_load_source(argc
- 2, argv
+ 2, "all",
5117 else if (argc
> 2 && strcmp(argv
[1], "-test-print-binops") == 0)
5118 return perform_test_load_source(argc
- 2, argv
+ 2, "all", PrintBinOps
, 0);
5119 else if (argc
> 2 && strcmp(argv
[1], "-test-print-mangle") == 0)
5120 return perform_test_load_tu(argv
[2], "all", NULL
, PrintMangledName
, NULL
);
5121 else if (argc
> 2 && strcmp(argv
[1], "-test-print-manglings") == 0)
5122 return perform_test_load_tu(argv
[2], "all", NULL
, PrintManglings
, NULL
);
5123 else if (argc
> 2 && strcmp(argv
[1], "-test-print-target-info") == 0)
5124 return print_target_info(argc
- 2, argv
+ 2);
5125 else if (argc
> 1 && strcmp(argv
[1], "-print-usr") == 0) {
5127 return print_usrs(argv
+ 2, argv
+ argc
);
5133 else if (argc
> 2 && strcmp(argv
[1], "-print-usr-file") == 0)
5134 return print_usrs_file(argv
[2]);
5135 else if (argc
> 2 && strcmp(argv
[1], "-write-pch") == 0)
5136 return write_pch_file(argv
[2], argc
- 3, argv
+ 3);
5137 else if (argc
> 2 && strcmp(argv
[1], "-compilation-db") == 0)
5138 return perform_test_compilation_db(argv
[argc
-1], argc
- 3, argv
+ 2);
5139 else if (argc
== 2 && strcmp(argv
[1], "-print-build-session-timestamp") == 0)
5140 return perform_print_build_session_timestamp();
5141 else if (argc
> 3 && strcmp(argv
[1], "-single-symbol-sgfs") == 0)
5142 return perform_test_load_source(argc
- 3, argv
+ 3, argv
[2],
5143 PrintSingleSymbolSGFs
, NULL
);
5144 else if (argc
> 2 && strstr(argv
[1], "-single-symbol-sgf-at=") == argv
[1])
5145 return inspect_cursor_at(
5146 argc
, argv
, "-single-symbol-sgf-at=", inspect_single_symbol_sgf_cursor
);
5147 else if (argc
> 2 && strstr(argv
[1], "-single-symbol-sgf-for=") == argv
[1])
5148 return perform_test_single_symbol_sgf(argv
[1], argc
- 2, argv
+ 2);
5156 /* We intentionally run in a separate thread to ensure we at least minimal
5157 * testing of a multithreaded environment (for example, having a reduced stack
5160 typedef struct thread_info
{
5161 int (*main_func
)(int argc
, const char **argv
);
5166 void thread_runner(void *client_data_v
) {
5167 thread_info
*client_data
= client_data_v
;
5168 client_data
->result
= client_data
->main_func(client_data
->argc
,
5172 static void flush_atexit(void) {
5173 /* stdout, and surprisingly even stderr, are not always flushed on process
5174 * and thread exit, particularly when the system is under heavy load. */
5179 int main(int argc
, const char **argv
) {
5180 thread_info client_data
;
5183 if (enablezOSAutoConversion(fileno(stdout
)) == -1)
5184 fprintf(stderr
, "Setting conversion on stdout failed\n");
5186 if (enablezOSAutoConversion(fileno(stderr
)) == -1)
5187 fprintf(stderr
, "Setting conversion on stderr failed\n");
5190 atexit(flush_atexit
);
5192 #ifdef CLANG_HAVE_LIBXML
5196 if (argc
> 1 && strcmp(argv
[1], "core") == 0)
5197 return indextest_core_main(argc
, argv
);
5199 client_data
.main_func
= cindextest_main
;
5200 client_data
.argc
= argc
;
5201 client_data
.argv
= argv
;
5203 if (getenv("CINDEXTEST_NOTHREADS"))
5204 return client_data
.main_func(client_data
.argc
, client_data
.argv
);
5206 clang_executeOnThread(thread_runner
, &client_data
, 0);
5207 return client_data
.result
;