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