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