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