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