c-index-test.c revision 3739b32a01b9778176757425e62252c288b85383
12b8ee6c2994f738e5162ff46b638974870f51662Steve Naroff/* c-index-test.c */
250398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff
350398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff#include "clang-c/Index.h"
41e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor#include <ctype.h>
50c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor#include <stdlib.h>
689922f86f4e7da383af2a62ef04ad8b93b941220Steve Naroff#include <stdio.h>
7af08ddc8f1c53fed8d8d0ad82aa2a0bb7d654bd1Steve Naroff#include <string.h>
8f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor#include <assert.h>
9af08ddc8f1c53fed8d8d0ad82aa2a0bb7d654bd1Steve Naroff
100d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
110d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/* Utility functions.                                                         */
120d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
130d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
142e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#ifdef _MSC_VER
152e06fc877a633abea3b40a64950c7316dac29ca8John Thompsonchar *basename(const char* path)
162e06fc877a633abea3b40a64950c7316dac29ca8John Thompson{
172e06fc877a633abea3b40a64950c7316dac29ca8John Thompson    char* base1 = (char*)strrchr(path, '/');
182e06fc877a633abea3b40a64950c7316dac29ca8John Thompson    char* base2 = (char*)strrchr(path, '\\');
192e06fc877a633abea3b40a64950c7316dac29ca8John Thompson    if (base1 && base2)
202e06fc877a633abea3b40a64950c7316dac29ca8John Thompson        return((base1 > base2) ? base1 + 1 : base2 + 1);
212e06fc877a633abea3b40a64950c7316dac29ca8John Thompson    else if (base1)
222e06fc877a633abea3b40a64950c7316dac29ca8John Thompson        return(base1 + 1);
232e06fc877a633abea3b40a64950c7316dac29ca8John Thompson    else if (base2)
242e06fc877a633abea3b40a64950c7316dac29ca8John Thompson        return(base2 + 1);
252e06fc877a633abea3b40a64950c7316dac29ca8John Thompson
262e06fc877a633abea3b40a64950c7316dac29ca8John Thompson    return((char*)path);
272e06fc877a633abea3b40a64950c7316dac29ca8John Thompson}
282e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#else
29ff9e18cb3863defa98257500ef49d93a9d2bc216Steve Naroffextern char *basename(const char *);
302e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#endif
31ff9e18cb3863defa98257500ef49d93a9d2bc216Steve Naroff
3245ba9a1b31110568d0d362c8d31c6133cf9011b7Douglas Gregor/** \brief Return the default parsing options. */
3344c181aec37789f25f6c15543c164416f72e562aDouglas Gregorstatic unsigned getDefaultParsingOptions() {
3444c181aec37789f25f6c15543c164416f72e562aDouglas Gregor  unsigned options = CXTranslationUnit_DetailedPreprocessingRecord;
3544c181aec37789f25f6c15543c164416f72e562aDouglas Gregor
3644c181aec37789f25f6c15543c164416f72e562aDouglas Gregor  if (getenv("CINDEXTEST_EDITING"))
37b1c031be513705d924038f497279b9b599868ba1Douglas Gregor    options |= clang_defaultEditingTranslationUnitOptions();
3887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor  if (getenv("CINDEXTEST_COMPLETION_CACHING"))
3987c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor    options |= CXTranslationUnit_CacheCompletionResults;
40dcaca015a2f08e03a6d86222fec2e83e04f6b848Argyrios Kyrtzidis  if (getenv("CINDEXTEST_COMPLETION_NO_CACHING"))
41dcaca015a2f08e03a6d86222fec2e83e04f6b848Argyrios Kyrtzidis    options &= ~CXTranslationUnit_CacheCompletionResults;
4244c181aec37789f25f6c15543c164416f72e562aDouglas Gregor
4344c181aec37789f25f6c15543c164416f72e562aDouglas Gregor  return options;
4444c181aec37789f25f6c15543c164416f72e562aDouglas Gregor}
4544c181aec37789f25f6c15543c164416f72e562aDouglas Gregor
46bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidisstatic int checkForErrors(CXTranslationUnit TU);
47bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis
4851b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbarstatic void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,
4951b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar                        unsigned end_line, unsigned end_column) {
5051b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar  fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,
51d52864bd33c66aacc84133460d8c9c0dfcdd5c18Daniel Dunbar          end_line, end_column);
5251b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar}
5351b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar
541c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenekstatic unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
551c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek                                      CXTranslationUnit *TU) {
56e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
57a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  *TU = clang_createTranslationUnit(Idx, file);
586be2a22979e6a4af575af32cccdf6a6190a8edcaDan Gohman  if (!*TU) {
591c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
601c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    return 0;
61e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  }
621c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  return 1;
631c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek}
641c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek
654db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregorvoid free_remapped_files(struct CXUnsavedFile *unsaved_files,
664db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                         int num_unsaved_files) {
674db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int i;
684db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  for (i = 0; i != num_unsaved_files; ++i) {
694db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    free((char *)unsaved_files[i].Filename);
704db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    free((char *)unsaved_files[i].Contents);
714db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  }
72653a55f4bc0cb1d0c1f3ff86e9559f744eb3c18fDouglas Gregor  free(unsaved_files);
734db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor}
744db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
754db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregorint parse_remapped_files(int argc, const char **argv, int start_arg,
764db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                         struct CXUnsavedFile **unsaved_files,
774db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                         int *num_unsaved_files) {
784db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int i;
794db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int arg;
804db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int prefix_len = strlen("-remap-file=");
814db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  *unsaved_files = 0;
824db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  *num_unsaved_files = 0;
83e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
844db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  /* Count the number of remapped files. */
854db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  for (arg = start_arg; arg < argc; ++arg) {
864db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    if (strncmp(argv[arg], "-remap-file=", prefix_len))
874db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      break;
88e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
894db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    ++*num_unsaved_files;
904db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  }
91e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
924db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  if (*num_unsaved_files == 0)
934db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    return 0;
94e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
954db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  *unsaved_files
96653a55f4bc0cb1d0c1f3ff86e9559f744eb3c18fDouglas Gregor    = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
97653a55f4bc0cb1d0c1f3ff86e9559f744eb3c18fDouglas Gregor                                     *num_unsaved_files);
984db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
994db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    struct CXUnsavedFile *unsaved = *unsaved_files + i;
1004db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    const char *arg_string = argv[arg] + prefix_len;
1014db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    int filename_len;
1024db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    char *filename;
1034db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    char *contents;
1044db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    FILE *to_file;
1054db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    const char *semi = strchr(arg_string, ';');
1064db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    if (!semi) {
107e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      fprintf(stderr,
1084db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor              "error: -remap-file=from;to argument is missing semicolon\n");
1094db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      free_remapped_files(*unsaved_files, i);
1104db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      *unsaved_files = 0;
1114db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      *num_unsaved_files = 0;
1124db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      return -1;
1134db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    }
114e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1154db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    /* Open the file that we're remapping to. */
116c44fe4bf2962bfcb323e93a63ba4a72d67839cdeFrancois Pichet    to_file = fopen(semi + 1, "rb");
1174db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    if (!to_file) {
1184db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
1194db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor              semi + 1);
1204db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      free_remapped_files(*unsaved_files, i);
1214db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      *unsaved_files = 0;
1224db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      *num_unsaved_files = 0;
1234db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      return -1;
1244db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    }
125e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1264db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    /* Determine the length of the file we're remapping to. */
1274db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    fseek(to_file, 0, SEEK_END);
1284db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    unsaved->Length = ftell(to_file);
1294db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    fseek(to_file, 0, SEEK_SET);
130e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1314db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    /* Read the contents of the file we're remapping to. */
1324db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    contents = (char *)malloc(unsaved->Length + 1);
1334db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
1344db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
1354db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor              (feof(to_file) ? "EOF" : "error"), semi + 1);
1364db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      fclose(to_file);
1374db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      free_remapped_files(*unsaved_files, i);
1384db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      *unsaved_files = 0;
1394db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      *num_unsaved_files = 0;
1404db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      return -1;
1414db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    }
1424db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    contents[unsaved->Length] = 0;
1434db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    unsaved->Contents = contents;
144e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1454db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    /* Close the file. */
1464db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    fclose(to_file);
147e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1484db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    /* Copy the file name that we're remapping from. */
1494db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    filename_len = semi - arg_string;
1504db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    filename = (char *)malloc(filename_len + 1);
1514db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    memcpy(filename, arg_string, filename_len);
1524db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    filename[filename_len] = 0;
1534db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    unsaved->Filename = filename;
1544db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  }
155e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1564db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  return 0;
1574db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor}
1584db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1590d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
1600d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/* Pretty-printing.                                                           */
1610d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
1620d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
163430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregorstatic void PrintRange(CXSourceRange R, const char *str) {
164430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  CXFile begin_file, end_file;
165430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  unsigned begin_line, begin_column, end_line, end_column;
166430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor
167430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  clang_getSpellingLocation(clang_getRangeStart(R),
168430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                            &begin_file, &begin_line, &begin_column, 0);
169430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  clang_getSpellingLocation(clang_getRangeEnd(R),
170430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                            &end_file, &end_line, &end_column, 0);
171430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  if (!begin_file || !end_file)
172430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    return;
173430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor
174430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  printf(" %s=", str);
175430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
176430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor}
177430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor
178358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregorint want_display_name = 0;
179358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor
180aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic void PrintCursor(CXCursor Cursor) {
181aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
182e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  if (clang_isInvalid(Cursor.kind)) {
183e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    CXString ks = clang_getCursorKindSpelling(Cursor.kind);
184e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    printf("Invalid Cursor => %s", clang_getCString(ks));
185e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    clang_disposeString(ks);
186e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  }
187699a07d8a0b1579c5178b3baf4bcf9edb6b38108Steve Naroff  else {
188e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    CXString string, ks;
189c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor    CXCursor Referenced;
1901db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor    unsigned line, column;
191e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    CXCursor SpecializationOf;
1929f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    CXCursor *overridden;
1939f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    unsigned num_overridden;
194430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    unsigned RefNameRangeNr;
195430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    CXSourceRange CursorExtent;
196430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    CXSourceRange RefNameRange;
1979f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor
198e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    ks = clang_getCursorKindSpelling(Cursor.kind);
199358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor    string = want_display_name? clang_getCursorDisplayName(Cursor)
200358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor                              : clang_getCursorSpelling(Cursor);
201e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    printf("%s=%s", clang_getCString(ks),
202e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek                    clang_getCString(string));
203e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    clang_disposeString(ks);
204ef0cef6cec8de5fc60e469a93436eed7212e0dc2Steve Naroff    clang_disposeString(string);
205e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
206c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor    Referenced = clang_getCursorReferenced(Cursor);
207c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor    if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
2081f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor      if (clang_getCursorKind(Referenced) == CXCursor_OverloadedDeclRef) {
2091f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        unsigned I, N = clang_getNumOverloadedDecls(Referenced);
2101f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        printf("[");
2111f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        for (I = 0; I != N; ++I) {
2121f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor          CXCursor Ovl = clang_getOverloadedDecl(Referenced, I);
2131f6206ed21e026ca7ddaf0bff9599c476301a695Douglas Gregor          CXSourceLocation Loc;
2141f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor          if (I)
2151f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor            printf(", ");
2161f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
2171f6206ed21e026ca7ddaf0bff9599c476301a695Douglas Gregor          Loc = clang_getCursorLocation(Ovl);
218a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor          clang_getSpellingLocation(Loc, 0, &line, &column, 0);
2191f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor          printf("%d:%d", line, column);
2201f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        }
2211f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        printf("]");
2221f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor      } else {
2231f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        CXSourceLocation Loc = clang_getCursorLocation(Referenced);
224a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor        clang_getSpellingLocation(Loc, 0, &line, &column, 0);
2251f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor        printf(":%d:%d", line, column);
2261f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor      }
227c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor    }
228b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor
229b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor    if (clang_isCursorDefinition(Cursor))
230b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor      printf(" (Definition)");
23158ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
23258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    switch (clang_getCursorAvailability(Cursor)) {
23358ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor      case CXAvailability_Available:
23458ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor        break;
23558ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
23658ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor      case CXAvailability_Deprecated:
23758ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor        printf(" (deprecated)");
23858ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor        break;
23958ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
24058ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor      case CXAvailability_NotAvailable:
24158ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor        printf(" (unavailable)");
24258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor        break;
243d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen
244d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen      case CXAvailability_NotAccessible:
245d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen        printf(" (inaccessible)");
246d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen        break;
24758ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    }
24895f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek
249b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor    if (clang_CXXMethod_isStatic(Cursor))
250b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor      printf(" (static)");
251b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor    if (clang_CXXMethod_isVirtual(Cursor))
252b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor      printf(" (virtual)");
253b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor
25495f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek    if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
25595f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek      CXType T =
25695f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek        clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor));
25795f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek      CXString S = clang_getTypeKindSpelling(T.kind);
25895f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek      printf(" [IBOutletCollection=%s]", clang_getCString(S));
25995f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek      clang_disposeString(S);
26095f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek    }
2613064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek
2623064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek    if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
2633064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek      enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
2643064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek      unsigned isVirtual = clang_isVirtualBase(Cursor);
2653064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek      const char *accessStr = 0;
2663064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek
2673064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek      switch (access) {
2683064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek        case CX_CXXInvalidAccessSpecifier:
2693064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek          accessStr = "invalid"; break;
2703064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek        case CX_CXXPublic:
2713064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek          accessStr = "public"; break;
2723064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek        case CX_CXXProtected:
2733064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek          accessStr = "protected"; break;
2743064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek        case CX_CXXPrivate:
2753064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek          accessStr = "private"; break;
2763064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek      }
2773064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek
2783064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek      printf(" [access=%s isVirtual=%s]", accessStr,
2793064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek             isVirtual ? "true" : "false");
2803064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek    }
281e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
282e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    SpecializationOf = clang_getSpecializedCursorTemplate(Cursor);
283e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {
284e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);
285e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      CXString Name = clang_getCursorSpelling(SpecializationOf);
286a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor      clang_getSpellingLocation(Loc, 0, &line, &column, 0);
287e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      printf(" [Specialization of %s:%d:%d]",
288e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor             clang_getCString(Name), line, column);
289e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      clang_disposeString(Name);
290e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    }
2919f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor
2929f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    clang_getOverriddenCursors(Cursor, &overridden, &num_overridden);
2939f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    if (num_overridden) {
2949f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      unsigned I;
2959f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      printf(" [Overrides ");
2969f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      for (I = 0; I != num_overridden; ++I) {
2979f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor        CXSourceLocation Loc = clang_getCursorLocation(overridden[I]);
298a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor        clang_getSpellingLocation(Loc, 0, &line, &column, 0);
2999f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor        if (I)
3009f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor          printf(", ");
3019f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor        printf("@%d:%d", line, column);
3029f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      }
3039f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      printf("]");
3049f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      clang_disposeOverriddenCursors(overridden);
3059f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    }
306ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor
307ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor    if (Cursor.kind == CXCursor_InclusionDirective) {
308ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor      CXFile File = clang_getIncludedFile(Cursor);
309ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor      CXString Included = clang_getFileName(File);
310ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor      printf(" (%s)", clang_getCString(Included));
311ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor      clang_disposeString(Included);
312dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor
313dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor      if (clang_isFileMultipleIncludeGuarded(TU, File))
314dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor        printf("  [multi-include guarded]");
315ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor    }
316430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor
317430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    CursorExtent = clang_getCursorExtent(Cursor);
318430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    RefNameRange = clang_getCursorReferenceNameRange(Cursor,
319430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                   CXNameRange_WantQualifier
320430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                 | CXNameRange_WantSinglePiece
321430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                 | CXNameRange_WantTemplateArgs,
322430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                     0);
323430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    if (!clang_equalRanges(CursorExtent, RefNameRange))
324430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor      PrintRange(RefNameRange, "SingleRefName");
325430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor
326430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    for (RefNameRangeNr = 0; 1; RefNameRangeNr++) {
327430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor      RefNameRange = clang_getCursorReferenceNameRange(Cursor,
328430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                   CXNameRange_WantQualifier
329430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                 | CXNameRange_WantTemplateArgs,
330430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor                                                       RefNameRangeNr);
331430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor      if (clang_equalRanges(clang_getNullRange(), RefNameRange))
332430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor        break;
333430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor      if (!clang_equalRanges(CursorExtent, RefNameRange))
334430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor        PrintRange(RefNameRange, "RefName");
335430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor    }
336699a07d8a0b1579c5178b3baf4bcf9edb6b38108Steve Naroff  }
337af08ddc8f1c53fed8d8d0ad82aa2a0bb7d654bd1Steve Naroff}
33889922f86f4e7da383af2a62ef04ad8b93b941220Steve Naroff
339e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenekstatic const char* GetCursorSource(CXCursor Cursor) {
3401db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor  CXSourceLocation Loc = clang_getCursorLocation(Cursor);
34174844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  CXString source;
3421db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor  CXFile file;
343b4efaa0a14dd2382aa028c03283b5a7f5345e24dArgyrios Kyrtzidis  clang_getExpansionLocation(Loc, &file, 0, 0, 0);
3441db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor  source = clang_getFileName(file);
345e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  if (!clang_getCString(source)) {
34674844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    clang_disposeString(source);
34774844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    return "<invalid loc>";
34874844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  }
34974844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  else {
350e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    const char *b = basename(clang_getCString(source));
35174844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    clang_disposeString(source);
35274844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    return b;
35374844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  }
3549298cfc7475c48fa42b168c37f628663d65ddde7Ted Kremenek}
3559298cfc7475c48fa42b168c37f628663d65ddde7Ted Kremenek
3560d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
357ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek/* Callbacks.                                                                 */
358ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek/******************************************************************************/
359ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek
360ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenektypedef void (*PostVisitTU)(CXTranslationUnit);
361ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek
362a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregorvoid PrintDiagnostic(CXDiagnostic Diagnostic) {
363a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  FILE *out = stderr;
3645352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor  CXFile file;
365274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor  CXString Msg;
3660a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  unsigned display_opts = CXDiagnostic_DisplaySourceLocation
367aa5f135f8db82b5e5fb1640fd51f8078e0b2d82dDouglas Gregor    | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges
368aa5f135f8db82b5e5fb1640fd51f8078e0b2d82dDouglas Gregor    | CXDiagnostic_DisplayOption;
3690a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  unsigned i, num_fixits;
370f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
3710a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
3725352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor    return;
373e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
374274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor  Msg = clang_formatDiagnostic(Diagnostic, display_opts);
375274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor  fprintf(stderr, "%s\n", clang_getCString(Msg));
376274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor  clang_disposeString(Msg);
377f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
378a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor  clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
379a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor                            &file, 0, 0, 0);
3800a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  if (!file)
3810a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    return;
382e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
3830a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
3843739b32a01b9778176757425e62252c288b85383Ted Kremenek  fprintf(stderr, "Number FIX-ITs = %d\n", num_fixits);
3850a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  for (i = 0; i != num_fixits; ++i) {
386473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    CXSourceRange range;
387473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    CXString insertion_text = clang_getDiagnosticFixIt(Diagnostic, i, &range);
388473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    CXSourceLocation start = clang_getRangeStart(range);
389473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    CXSourceLocation end = clang_getRangeEnd(range);
390473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    unsigned start_line, start_column, end_line, end_column;
391473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    CXFile start_file, end_file;
392a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(start, &start_file, &start_line,
393a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor                              &start_column, 0);
394a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(end, &end_file, &end_line, &end_column, 0);
395473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    if (clang_equalLocations(start, end)) {
396473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      /* Insertion. */
397473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      if (start_file == file)
3980a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
399473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor                clang_getCString(insertion_text), start_line, start_column);
400473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    } else if (strcmp(clang_getCString(insertion_text), "") == 0) {
401473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      /* Removal. */
4020a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      if (start_file == file && end_file == file) {
4030a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        fprintf(out, "FIX-IT: Remove ");
4040a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        PrintExtent(out, start_line, start_column, end_line, end_column);
4050a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        fprintf(out, "\n");
406436f3f0400c633251e4071f81358c47bab964adfDouglas Gregor      }
407473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    } else {
408473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      /* Replacement. */
4090a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      if (start_file == end_file) {
4100a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        fprintf(out, "FIX-IT: Replace ");
4110a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        PrintExtent(out, start_line, start_column, end_line, end_column);
412473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor        fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text));
41351c6d384551674facc19f745ecf6e289d28dc55fDouglas Gregor      }
4140a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      break;
4150a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    }
416473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    clang_disposeString(insertion_text);
41751c6d384551674facc19f745ecf6e289d28dc55fDouglas Gregor  }
4185352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor}
4195352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor
4207473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenekvoid PrintDiagnosticSet(CXDiagnosticSet Set) {
4217473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek  int i = 0, n = clang_getNumDiagnosticsInSet(Set);
4227473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek  for ( ; i != n ; ++i) {
4237473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek    CXDiagnostic Diag = clang_getDiagnosticInSet(Set, i);
4247473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek    CXDiagnosticSet ChildDiags = clang_getChildDiagnostics(Diag);
425a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    PrintDiagnostic(Diag);
4267473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek    if (ChildDiags)
4277473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek      PrintDiagnosticSet(ChildDiags);
4287473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek  }
4297473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek}
4307473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek
4317473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenekvoid PrintDiagnostics(CXTranslationUnit TU) {
4327473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek  CXDiagnosticSet TUSet = clang_getDiagnosticSetFromTU(TU);
4337473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek  PrintDiagnosticSet(TUSet);
4347473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek  clang_disposeDiagnosticSet(TUSet);
435a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor}
436a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor
43759fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenekvoid PrintMemoryUsage(CXTranslationUnit TU) {
438b22732365ca26fbccacc4bdd32e875342f571e94Matt Beaumont-Gay  unsigned long total = 0;
4394e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek  unsigned i = 0;
440f787002478f09af1741fb0f82a562002e6799c49Ted Kremenek  CXTUResourceUsage usage = clang_getCXTUResourceUsage(TU);
4413c683367073e2d98a9046060f9bc7db872a1c63dFrancois Pichet  fprintf(stderr, "Memory usage:\n");
4424e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek  for (i = 0 ; i != usage.numEntries; ++i) {
443f787002478f09af1741fb0f82a562002e6799c49Ted Kremenek    const char *name = clang_getTUResourceUsageName(usage.entries[i].kind);
44459fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    unsigned long amount = usage.entries[i].amount;
44559fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    total += amount;
4464e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek    fprintf(stderr, "  %s : %ld bytes (%f MBytes)\n", name, amount,
44759fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek            ((double) amount)/(1024*1024));
44859fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek  }
4494e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek  fprintf(stderr, "  TOTAL = %ld bytes (%f MBytes)\n", total,
45059fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek          ((double) total)/(1024*1024));
451f787002478f09af1741fb0f82a562002e6799c49Ted Kremenek  clang_disposeCXTUResourceUsage(usage);
45259fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek}
45359fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek
454ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek/******************************************************************************/
455e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor/* Logic for testing traversal.                                               */
4560d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
4570d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
458fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenekstatic const char *FileCheckPrefix = "CHECK";
459fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek
460a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregorstatic void PrintCursorExtent(CXCursor C) {
461a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregor  CXSourceRange extent = clang_getCursorExtent(C);
462430d7a1a621a126a9ffe442ad8987ba02b46dae9Douglas Gregor  PrintRange(extent, "Extent");
463fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek}
464fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek
465e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor/* Data used by all of the visitors. */
466e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregortypedef struct  {
467e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  CXTranslationUnit TU;
468e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  enum CXCursorKind *Filter;
469e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor} VisitorData;
470fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek
471625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar
472e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenekenum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
473e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor                                                CXCursor Parent,
474e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor                                                CXClientData ClientData) {
475e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  VisitorData *Data = (VisitorData *)ClientData;
476e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
47798258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor    CXSourceLocation Loc = clang_getCursorLocation(Cursor);
4781db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor    unsigned line, column;
479a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(Loc, 0, &line, &column, 0);
480fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek    printf("// %s: %s:%d:%d: ", FileCheckPrefix,
4811db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor           GetCursorSource(Cursor), line, column);
482aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    PrintCursor(Cursor);
483a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregor    PrintCursorExtent(Cursor);
484e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    printf("\n");
485e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    return CXChildVisit_Recurse;
486625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  }
487e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
488e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  return CXChildVisit_Continue;
489625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar}
490c857ea4d22e1e6dd9ede1f0e84d48b157c6924fdSteve Naroff
491e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenekstatic enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
492e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor                                                   CXCursor Parent,
493e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor                                                   CXClientData ClientData) {
494625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  const char *startBuf, *endBuf;
495625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn;
496625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  CXCursor Ref;
497e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  VisitorData *Data = (VisitorData *)ClientData;
498625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar
499b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor  if (Cursor.kind != CXCursor_FunctionDecl ||
500b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor      !clang_isCursorDefinition(Cursor))
501e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    return CXChildVisit_Continue;
502625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar
503625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,
504625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar                                       &startLine, &startColumn,
505625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar                                       &endLine, &endColumn);
506625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  /* Probe the entire body, looking for both decls and refs. */
507625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  curLine = startLine;
508625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  curColumn = startColumn;
509625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar
510625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  while (startBuf < endBuf) {
51198258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor    CXSourceLocation Loc;
5121db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor    CXFile file;
51374844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    CXString source;
514e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
515625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar    if (*startBuf == '\n') {
516625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar      startBuf++;
517625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar      curLine++;
518625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar      curColumn = 1;
519625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar    } else if (*startBuf != '\t')
520625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar      curColumn++;
521e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
52298258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor    Loc = clang_getCursorLocation(Cursor);
523a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(Loc, &file, 0, 0, 0);
524e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
5251db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor    source = clang_getFileName(file);
526e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    if (clang_getCString(source)) {
527b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor      CXSourceLocation RefLoc
528b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor        = clang_getLocation(Data->TU, file, curLine, curColumn);
529b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor      Ref = clang_getCursor(Data->TU, RefLoc);
53098258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor      if (Ref.kind == CXCursor_NoDeclFound) {
53198258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor        /* Nothing found here; that's fine. */
53298258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor      } else if (Ref.kind != CXCursor_FunctionDecl) {
53398258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor        printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
53498258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor               curLine, curColumn);
535aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        PrintCursor(Ref);
53698258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor        printf("\n");
53798258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor      }
5384ade6d6eae934f796ca43c81a5aa185e456dde9bSteve Naroff    }
53974844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    clang_disposeString(source);
540625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar    startBuf++;
5412d4d629d8a0de5112c7ae9d05c03ddbf6dcd956aSteve Naroff  }
542e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
543e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  return CXChildVisit_Continue;
54489922f86f4e7da383af2a62ef04ad8b93b941220Steve Naroff}
54550398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff
5467d40562f83552b7295411e10ee887d8d55470679Ted Kremenek/******************************************************************************/
5477d40562f83552b7295411e10ee887d8d55470679Ted Kremenek/* USR testing.                                                               */
5487d40562f83552b7295411e10ee887d8d55470679Ted Kremenek/******************************************************************************/
5497d40562f83552b7295411e10ee887d8d55470679Ted Kremenek
550e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregorenum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
551e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor                                   CXClientData ClientData) {
552e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  VisitorData *Data = (VisitorData *)ClientData;
553e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
554cf84aa46def41cccf4dd4c51cd0543b70c11e4ebTed Kremenek    CXString USR = clang_getCursorUSR(C);
555e542f7723a929d42bd9e4dfa526b4ede915b91a7Ted Kremenek    const char *cstr = clang_getCString(USR);
556e542f7723a929d42bd9e4dfa526b4ede915b91a7Ted Kremenek    if (!cstr || cstr[0] == '\0') {
5577d40562f83552b7295411e10ee887d8d55470679Ted Kremenek      clang_disposeString(USR);
558e74ef1289d5fff0a6ea573198bf354fa8cd84d51Ted Kremenek      return CXChildVisit_Recurse;
5597d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    }
560e542f7723a929d42bd9e4dfa526b4ede915b91a7Ted Kremenek    printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr);
561e542f7723a929d42bd9e4dfa526b4ede915b91a7Ted Kremenek
562a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregor    PrintCursorExtent(C);
5637d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    printf("\n");
5647d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    clang_disposeString(USR);
565e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
566e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    return CXChildVisit_Recurse;
567e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  }
568e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
569e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  return CXChildVisit_Continue;
5707d40562f83552b7295411e10ee887d8d55470679Ted Kremenek}
5717d40562f83552b7295411e10ee887d8d55470679Ted Kremenek
5727d40562f83552b7295411e10ee887d8d55470679Ted Kremenek/******************************************************************************/
57316b55a71695a33c094383295cc7b7a2080e098daTed Kremenek/* Inclusion stack testing.                                                   */
57416b55a71695a33c094383295cc7b7a2080e098daTed Kremenek/******************************************************************************/
57516b55a71695a33c094383295cc7b7a2080e098daTed Kremenek
57616b55a71695a33c094383295cc7b7a2080e098daTed Kremenekvoid InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack,
57716b55a71695a33c094383295cc7b7a2080e098daTed Kremenek                      unsigned includeStackLen, CXClientData data) {
578e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
57916b55a71695a33c094383295cc7b7a2080e098daTed Kremenek  unsigned i;
58074844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  CXString fname;
58174844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek
58274844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  fname = clang_getFileName(includedFile);
583e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  printf("file: %s\nincluded by:\n", clang_getCString(fname));
58474844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek  clang_disposeString(fname);
585e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
58616b55a71695a33c094383295cc7b7a2080e098daTed Kremenek  for (i = 0; i < includeStackLen; ++i) {
58716b55a71695a33c094383295cc7b7a2080e098daTed Kremenek    CXFile includingFile;
58816b55a71695a33c094383295cc7b7a2080e098daTed Kremenek    unsigned line, column;
589a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(includeStack[i], &includingFile, &line,
590a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor                              &column, 0);
59174844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    fname = clang_getFileName(includingFile);
592e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    printf("  %s:%d:%d\n", clang_getCString(fname), line, column);
59374844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    clang_disposeString(fname);
59416b55a71695a33c094383295cc7b7a2080e098daTed Kremenek  }
59516b55a71695a33c094383295cc7b7a2080e098daTed Kremenek  printf("\n");
59616b55a71695a33c094383295cc7b7a2080e098daTed Kremenek}
59716b55a71695a33c094383295cc7b7a2080e098daTed Kremenek
59816b55a71695a33c094383295cc7b7a2080e098daTed Kremenekvoid PrintInclusionStack(CXTranslationUnit TU) {
599e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  clang_getInclusions(TU, InclusionVisitor, NULL);
60016b55a71695a33c094383295cc7b7a2080e098daTed Kremenek}
60116b55a71695a33c094383295cc7b7a2080e098daTed Kremenek
60216b55a71695a33c094383295cc7b7a2080e098daTed Kremenek/******************************************************************************/
6033bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek/* Linkage testing.                                                           */
6043bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek/******************************************************************************/
6053bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek
6063bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenekstatic enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
6073bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek                                            CXClientData d) {
6083bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  const char *linkage = 0;
6093bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek
6103bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  if (clang_isInvalid(clang_getCursorKind(cursor)))
6113bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek    return CXChildVisit_Recurse;
6123bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek
6133bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  switch (clang_getCursorLinkage(cursor)) {
6143bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek    case CXLinkage_Invalid: break;
615c2a2b3c2c2da1086d76bf804633ed5c6c48ae722Douglas Gregor    case CXLinkage_NoLinkage: linkage = "NoLinkage"; break;
616c2a2b3c2c2da1086d76bf804633ed5c6c48ae722Douglas Gregor    case CXLinkage_Internal: linkage = "Internal"; break;
617c2a2b3c2c2da1086d76bf804633ed5c6c48ae722Douglas Gregor    case CXLinkage_UniqueExternal: linkage = "UniqueExternal"; break;
618c2a2b3c2c2da1086d76bf804633ed5c6c48ae722Douglas Gregor    case CXLinkage_External: linkage = "External"; break;
6193bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  }
6203bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek
6213bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  if (linkage) {
622aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    PrintCursor(cursor);
6233bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek    printf("linkage=%s\n", linkage);
6243bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  }
6253bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek
6263bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  return CXChildVisit_Recurse;
6273bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek}
6283bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek
6293bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek/******************************************************************************/
6308e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek/* Typekind testing.                                                          */
6318e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek/******************************************************************************/
6328e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek
6338e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenekstatic enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
6348e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek                                             CXClientData d) {
6358e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek  if (!clang_isInvalid(clang_getCursorKind(cursor))) {
6368e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek    CXType T = clang_getCursorType(cursor);
6378e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek    CXString S = clang_getTypeKindSpelling(T.kind);
638aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    PrintCursor(cursor);
6398e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek    printf(" typekind=%s", clang_getCString(S));
640e72fb6f40231a1e8372c7576b69f06f0a1eb28a7Douglas Gregor    if (clang_isConstQualifiedType(T))
641e72fb6f40231a1e8372c7576b69f06f0a1eb28a7Douglas Gregor      printf(" const");
642e72fb6f40231a1e8372c7576b69f06f0a1eb28a7Douglas Gregor    if (clang_isVolatileQualifiedType(T))
643e72fb6f40231a1e8372c7576b69f06f0a1eb28a7Douglas Gregor      printf(" volatile");
644e72fb6f40231a1e8372c7576b69f06f0a1eb28a7Douglas Gregor    if (clang_isRestrictQualifiedType(T))
645e72fb6f40231a1e8372c7576b69f06f0a1eb28a7Douglas Gregor      printf(" restrict");
6468e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek    clang_disposeString(S);
647e1403d2dcb06fc306e186c787a7bd0ca30e06edeBenjamin Kramer    /* Print the canonical type if it is different. */
64804c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek    {
64904c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek      CXType CT = clang_getCanonicalType(T);
65004c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek      if (!clang_equalTypes(T, CT)) {
65104c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek        CXString CS = clang_getTypeKindSpelling(CT.kind);
65204c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek        printf(" [canonical=%s]", clang_getCString(CS));
65304c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek        clang_disposeString(CS);
65404c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek      }
65504c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek    }
656e1403d2dcb06fc306e186c787a7bd0ca30e06edeBenjamin Kramer    /* Print the return type if it exists. */
65704c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek    {
6589a140845438c2fc31e7d48a6dedbc695f4c83c68Ted Kremenek      CXType RT = clang_getCursorResultType(cursor);
65904c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek      if (RT.kind != CXType_Invalid) {
66004c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek        CXString RS = clang_getTypeKindSpelling(RT.kind);
66104c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek        printf(" [result=%s]", clang_getCString(RS));
66204c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek        clang_disposeString(RS);
66304c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek      }
66404c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek    }
6653ce9e7d270e7df86c09c8126b4412d55be7c123bTed Kremenek    /* Print if this is a non-POD type. */
6663ce9e7d270e7df86c09c8126b4412d55be7c123bTed Kremenek    printf(" [isPOD=%d]", clang_isPODType(T));
66704c3cf35a80c09ab78e519f2e71ecccd5c5d8da0Ted Kremenek
6688e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek    printf("\n");
6698e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek  }
6708e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek  return CXChildVisit_Recurse;
6718e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek}
6728e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek
6738e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek
6748e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek/******************************************************************************/
6757d40562f83552b7295411e10ee887d8d55470679Ted Kremenek/* Loading ASTs/source.                                                       */
6767d40562f83552b7295411e10ee887d8d55470679Ted Kremenek/******************************************************************************/
6777d40562f83552b7295411e10ee887d8d55470679Ted Kremenek
678625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbarstatic int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
67998271567b6f10be85bcc75d0bbb67416c8cfb83aTed Kremenek                             const char *filter, const char *prefix,
680ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                             CXCursorVisitor Visitor,
681ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                             PostVisitTU PV) {
682e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
683fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek  if (prefix)
684e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    FileCheckPrefix = prefix;
685e3ee02a324559829142f387f75daf3da118442beTed Kremenek
686e3ee02a324559829142f387f75daf3da118442beTed Kremenek  if (Visitor) {
687e3ee02a324559829142f387f75daf3da118442beTed Kremenek    enum CXCursorKind K = CXCursor_NotImplemented;
688e3ee02a324559829142f387f75daf3da118442beTed Kremenek    enum CXCursorKind *ck = &K;
689e3ee02a324559829142f387f75daf3da118442beTed Kremenek    VisitorData Data;
690e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
691e3ee02a324559829142f387f75daf3da118442beTed Kremenek    /* Perform some simple filtering. */
692e3ee02a324559829142f387f75daf3da118442beTed Kremenek    if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
693358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor    else if (!strcmp(filter, "all-display") ||
694358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor             !strcmp(filter, "local-display")) {
695358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor      ck = NULL;
696358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor      want_display_name = 1;
697358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor    }
698b1ffee6e574d57b79ce2defd1b57052649221c03Daniel Dunbar    else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
699e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
700e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
701e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
702e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
703e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
704e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor;
705e3ee02a324559829142f387f75daf3da118442beTed Kremenek    else {
706e3ee02a324559829142f387f75daf3da118442beTed Kremenek      fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
707e3ee02a324559829142f387f75daf3da118442beTed Kremenek      return 1;
708e3ee02a324559829142f387f75daf3da118442beTed Kremenek    }
709e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
710e3ee02a324559829142f387f75daf3da118442beTed Kremenek    Data.TU = TU;
711e3ee02a324559829142f387f75daf3da118442beTed Kremenek    Data.Filter = ck;
712e3ee02a324559829142f387f75daf3da118442beTed Kremenek    clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data);
713e3ee02a324559829142f387f75daf3da118442beTed Kremenek  }
714e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
715ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek  if (PV)
716ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek    PV(TU);
717e3ee02a324559829142f387f75daf3da118442beTed Kremenek
718a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  PrintDiagnostics(TU);
71916ac8be58801d45358497e90a2f82bc155da8a44Argyrios Kyrtzidis  if (checkForErrors(TU) != 0) {
72016ac8be58801d45358497e90a2f82bc155da8a44Argyrios Kyrtzidis    clang_disposeTranslationUnit(TU);
72116ac8be58801d45358497e90a2f82bc155da8a44Argyrios Kyrtzidis    return -1;
72216ac8be58801d45358497e90a2f82bc155da8a44Argyrios Kyrtzidis  }
72316ac8be58801d45358497e90a2f82bc155da8a44Argyrios Kyrtzidis
7240d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek  clang_disposeTranslationUnit(TU);
7250d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek  return 0;
7260d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek}
7270d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
728fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenekint perform_test_load_tu(const char *file, const char *filter,
729ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                         const char *prefix, CXCursorVisitor Visitor,
730ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                         PostVisitTU PV) {
731625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  CXIndex Idx;
732625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  CXTranslationUnit TU;
733020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  int result;
734e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  Idx = clang_createIndex(/* excludeDeclsFromPCH */
7350a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor                          !strcmp(filter, "local") ? 1 : 0,
7360a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor                          /* displayDiagnosics=*/1);
737e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
738020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  if (!CreateTranslationUnit(Idx, file, &TU)) {
739020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek    clang_disposeIndex(Idx);
740625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar    return 1;
741020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  }
742625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar
743020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  result = perform_test_load(Idx, TU, filter, prefix, Visitor, PV);
744020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  clang_disposeIndex(Idx);
745020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  return result;
746625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar}
747625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar
748ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenekint perform_test_load_source(int argc, const char **argv,
749ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                             const char *filter, CXCursorVisitor Visitor,
750ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                             PostVisitTU PV) {
751ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar  CXIndex Idx;
752ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar  CXTranslationUnit TU;
7534db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  struct CXUnsavedFile *unsaved_files = 0;
7544db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int num_unsaved_files = 0;
7554db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int result;
756abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
757ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar  Idx = clang_createIndex(/* excludeDeclsFromPCH */
758358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor                          (!strcmp(filter, "local") ||
759358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor                           !strcmp(filter, "local-display"))? 1 : 0,
7604814fb560322daf009fda6226cffccb10bd44620Douglas Gregor                          /* displayDiagnosics=*/0);
761ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar
762020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
763020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek    clang_disposeIndex(Idx);
7644db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    return -1;
765020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  }
7664db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
767dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor  TU = clang_parseTranslationUnit(Idx, 0,
768dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  argv + num_unsaved_files,
769dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  argc - num_unsaved_files,
770dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  unsaved_files, num_unsaved_files,
771dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  getDefaultParsingOptions());
772ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar  if (!TU) {
773ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar    fprintf(stderr, "Unable to load translation unit!\n");
774abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    free_remapped_files(unsaved_files, num_unsaved_files);
775020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek    clang_disposeIndex(Idx);
776ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar    return 1;
777ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar  }
778ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar
779ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek  result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV);
7804db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  free_remapped_files(unsaved_files, num_unsaved_files);
781020a095de30ede5b1e3fc65dae501f225a1c89d3Ted Kremenek  clang_disposeIndex(Idx);
7824db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  return result;
783ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar}
784ada487d498d82277bbc60312fc6f6479f0afda76Daniel Dunbar
785abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregorint perform_test_reparse_source(int argc, const char **argv, int trials,
786abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor                                const char *filter, CXCursorVisitor Visitor,
787abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor                                PostVisitTU PV) {
788abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  CXIndex Idx;
789abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  CXTranslationUnit TU;
790abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  struct CXUnsavedFile *unsaved_files = 0;
791abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  int num_unsaved_files = 0;
792abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  int result;
793abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  int trial;
79440098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis  int remap_after_trial = 0;
79540098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis  char *endptr = 0;
796abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
797abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  Idx = clang_createIndex(/* excludeDeclsFromPCH */
798abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor                          !strcmp(filter, "local") ? 1 : 0,
7991aa27307c462baaa9e5fda14ff6797dd39fe8b84Douglas Gregor                          /* displayDiagnosics=*/0);
800abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
801abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
802abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    clang_disposeIndex(Idx);
803abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    return -1;
804abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  }
805abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
806c8a618002ca57495bf70e055bcafe918859cf4caDaniel Dunbar  /* Load the initial translation unit -- we do this without honoring remapped
807c8a618002ca57495bf70e055bcafe918859cf4caDaniel Dunbar   * files, so that we have a way to test results after changing the source. */
80844c181aec37789f25f6c15543c164416f72e562aDouglas Gregor  TU = clang_parseTranslationUnit(Idx, 0,
80944c181aec37789f25f6c15543c164416f72e562aDouglas Gregor                                  argv + num_unsaved_files,
81044c181aec37789f25f6c15543c164416f72e562aDouglas Gregor                                  argc - num_unsaved_files,
811c8a618002ca57495bf70e055bcafe918859cf4caDaniel Dunbar                                  0, 0, getDefaultParsingOptions());
812abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  if (!TU) {
813abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    fprintf(stderr, "Unable to load translation unit!\n");
814abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    free_remapped_files(unsaved_files, num_unsaved_files);
815abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    clang_disposeIndex(Idx);
816abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    return 1;
817abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  }
818abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
819bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0)
820bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis    return -1;
821bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis
82240098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis  if (getenv("CINDEXTEST_REMAP_AFTER_TRIAL")) {
82340098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis    remap_after_trial =
82440098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis        strtol(getenv("CINDEXTEST_REMAP_AFTER_TRIAL"), &endptr, 10);
82540098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis  }
82640098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis
827abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  for (trial = 0; trial < trials; ++trial) {
82840098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis    if (clang_reparseTranslationUnit(TU,
82940098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis                             trial >= remap_after_trial ? num_unsaved_files : 0,
83040098e8cd7268535ba581b50af0304b7ecacbef5Argyrios Kyrtzidis                             trial >= remap_after_trial ? unsaved_files : 0,
831e1e13bf568a7e37c95eda6fcfa626659a06e67b1Douglas Gregor                                     clang_defaultReparseOptions(TU))) {
832c8a618002ca57495bf70e055bcafe918859cf4caDaniel Dunbar      fprintf(stderr, "Unable to reparse translation unit!\n");
833abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      clang_disposeTranslationUnit(TU);
834abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      free_remapped_files(unsaved_files, num_unsaved_files);
835abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      clang_disposeIndex(Idx);
836abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      return -1;
837abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    }
838bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis
839bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis    if (checkForErrors(TU) != 0)
840bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis      return -1;
841abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  }
842abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
843abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV);
844bda536df1f5ccd71256eeeab4adbd2cf3769d89eArgyrios Kyrtzidis
845abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  free_remapped_files(unsaved_files, num_unsaved_files);
846abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  clang_disposeIndex(Idx);
847abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  return result;
848abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor}
849abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor
8500d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
8511c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek/* Logic for testing clang_getCursor().                                       */
8521c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek/******************************************************************************/
8531c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek
854dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregorstatic void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor,
8551c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek                                   unsigned start_line, unsigned start_col,
8561d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek                                   unsigned end_line, unsigned end_col,
8571d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek                                   const char *prefix) {
8589096a20fc0fd799911b738ce7a9134dbacaf64b7Ted Kremenek  printf("// %s: ", FileCheckPrefix);
8591d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek  if (prefix)
8601d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek    printf("-%s", prefix);
86151b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar  PrintExtent(stdout, start_line, start_col, end_line, end_col);
86251b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar  printf(" ");
863aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  PrintCursor(cursor);
8641c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  printf("\n");
8651c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek}
8661c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek
8671d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenekstatic int perform_file_scan(const char *ast_file, const char *source_file,
8681d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek                             const char *prefix) {
8691c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  CXIndex Idx;
8701c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  CXTranslationUnit TU;
8711c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  FILE *fp;
8722389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar  CXCursor prevCursor = clang_getNullCursor();
873b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor  CXFile file;
8742389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar  unsigned line = 1, col = 1;
8758f0bf81c0f3ab31881cc7db7914e6978bb2a19afDaniel Dunbar  unsigned start_line = 1, start_col = 1;
876e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
8770a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
8780a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor                                /* displayDiagnosics=*/1))) {
8791c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    fprintf(stderr, "Could not create Index\n");
8801c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    return 1;
8811c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  }
882e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
8831c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  if (!CreateTranslationUnit(Idx, ast_file, &TU))
8841c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    return 1;
885e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
8861c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  if ((fp = fopen(source_file, "r")) == NULL) {
8871c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    fprintf(stderr, "Could not open '%s'\n", source_file);
8881c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek    return 1;
8891c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  }
890e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
891b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor  file = clang_getFile(TU, source_file);
8922389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar  for (;;) {
8932389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    CXCursor cursor;
8942389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    int c = fgetc(fp);
8952389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar
8962389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    if (c == '\n') {
8972389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar      ++line;
8982389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar      col = 1;
8992389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    } else
9002389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar      ++col;
9012389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar
9022389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    /* Check the cursor at this position, and dump the previous one if we have
9032389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar     * found something new.
9042389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar     */
9052389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, col));
9062389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    if ((c == EOF || !clang_equalCursors(cursor, prevCursor)) &&
9072389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar        prevCursor.kind != CXCursor_InvalidFile) {
908dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor      print_cursor_file_scan(TU, prevCursor, start_line, start_col,
909d52864bd33c66aacc84133460d8c9c0dfcdd5c18Daniel Dunbar                             line, col, prefix);
9102389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar      start_line = line;
9112389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar      start_col = col;
912a9933b98399f656653a0876fc39e5b9093efb732Benjamin Kramer    }
9132389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    if (c == EOF)
9142389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar      break;
915a9933b98399f656653a0876fc39e5b9093efb732Benjamin Kramer
9162389eff26431b4f77d3383157adb2c8ccc15ff69Daniel Dunbar    prevCursor = cursor;
9171c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  }
918e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
9191c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  fclose(fp);
9204f5e21e24fb9e6ec473a13f83b5c9a2c41501a70Douglas Gregor  clang_disposeTranslationUnit(TU);
9214f5e21e24fb9e6ec473a13f83b5c9a2c41501a70Douglas Gregor  clang_disposeIndex(Idx);
9221c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  return 0;
9231c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek}
9241c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek
9251c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek/******************************************************************************/
92632be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor/* Logic for testing clang code completion.                                   */
9270d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
9280d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
9290c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor/* Parse file:line:column from the input string. Returns 0 on success, non-zero
9300c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor   on failure. If successful, the pointer *filename will contain newly-allocated
9310c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor   memory (that will be owned by the caller) to store the file name. */
932e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenekint parse_file_line_column(const char *input, char **filename, unsigned *line,
933fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor                           unsigned *column, unsigned *second_line,
934fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor                           unsigned *second_column) {
93588d23952eadb0737e5bd839654d69a0a578e19bcDouglas Gregor  /* Find the second colon. */
936fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  const char *last_colon = strrchr(input, ':');
937fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  unsigned values[4], i;
938fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  unsigned num_values = (second_line && second_column)? 4 : 2;
939fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
9400c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  char *endptr = 0;
941fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (!last_colon || last_colon == input) {
942fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    if (num_values == 4)
943fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor      fprintf(stderr, "could not parse filename:line:column:line:column in "
944fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor              "'%s'\n", input);
945fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    else
946fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor      fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
9470c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor    return 1;
9480c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  }
9490c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor
950fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  for (i = 0; i != num_values; ++i) {
951fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    const char *prev_colon;
95288d23952eadb0737e5bd839654d69a0a578e19bcDouglas Gregor
953fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    /* Parse the next line or column. */
954fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    values[num_values - i - 1] = strtol(last_colon + 1, &endptr, 10);
955fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    if (*endptr != 0 && *endptr != ':') {
956e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      fprintf(stderr, "could not parse %s in '%s'\n",
957fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor              (i % 2 ? "column" : "line"), input);
958fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor      return 1;
959fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    }
960e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
961fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    if (i + 1 == num_values)
962fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor      break;
96388d23952eadb0737e5bd839654d69a0a578e19bcDouglas Gregor
964fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    /* Find the previous colon. */
965fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    prev_colon = last_colon - 1;
966fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    while (prev_colon != input && *prev_colon != ':')
967fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor      --prev_colon;
968fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    if (prev_colon == input) {
969e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      fprintf(stderr, "could not parse %s in '%s'\n",
970fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor              (i % 2 == 0? "column" : "line"), input);
971e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      return 1;
972fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    }
973fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
974fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    last_colon = prev_colon;
9750c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  }
976fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
977fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  *line = values[0];
978fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  *column = values[1];
979e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
980fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (second_line && second_column) {
981fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    *second_line = values[2];
982fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    *second_column = values[3];
983fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  }
984fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
98588d23952eadb0737e5bd839654d69a0a578e19bcDouglas Gregor  /* Copy the file name. */
986fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  *filename = (char*)malloc(last_colon - input + 1);
987fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  memcpy(*filename, input, last_colon - input);
988fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  (*filename)[last_colon - input] = 0;
9890c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  return 0;
9900c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor}
9910c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor
9920c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregorconst char *
9930c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregorclang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
9940c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  switch (Kind) {
9950c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_Optional: return "Optional";
9960c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_TypedText: return "TypedText";
9970c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_Text: return "Text";
9980c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_Placeholder: return "Placeholder";
9990c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_Informative: return "Informative";
10000c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
10010c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_LeftParen: return "LeftParen";
10020c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_RightParen: return "RightParen";
10030c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_LeftBracket: return "LeftBracket";
10040c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_RightBracket: return "RightBracket";
10050c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_LeftBrace: return "LeftBrace";
10060c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_RightBrace: return "RightBrace";
10070c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_LeftAngle: return "LeftAngle";
10080c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_RightAngle: return "RightAngle";
10090c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  case CXCompletionChunk_Comma: return "Comma";
1010ff5ce6eefc7c253ef6edf4d4bfc996fdd82d09aaDouglas Gregor  case CXCompletionChunk_ResultType: return "ResultType";
101101dfea02d1da297e8b53db8eea3d3cc652acda8dDouglas Gregor  case CXCompletionChunk_Colon: return "Colon";
101201dfea02d1da297e8b53db8eea3d3cc652acda8dDouglas Gregor  case CXCompletionChunk_SemiColon: return "SemiColon";
101301dfea02d1da297e8b53db8eea3d3cc652acda8dDouglas Gregor  case CXCompletionChunk_Equal: return "Equal";
101401dfea02d1da297e8b53db8eea3d3cc652acda8dDouglas Gregor  case CXCompletionChunk_HorizontalSpace: return "HorizontalSpace";
101501dfea02d1da297e8b53db8eea3d3cc652acda8dDouglas Gregor  case CXCompletionChunk_VerticalSpace: return "VerticalSpace";
10160c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  }
1017e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
10180c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  return "Unknown";
10190c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor}
10200c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor
1021dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidisstatic int checkForErrors(CXTranslationUnit TU) {
1022dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  unsigned Num, i;
1023dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  CXDiagnostic Diag;
1024dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  CXString DiagStr;
1025dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1026dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (!getenv("CINDEXTEST_FAILONERROR"))
1027dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    return 0;
1028dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1029dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  Num = clang_getNumDiagnostics(TU);
1030dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  for (i = 0; i != Num; ++i) {
1031dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    Diag = clang_getDiagnostic(TU, i);
1032dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    if (clang_getDiagnosticSeverity(Diag) >= CXDiagnostic_Error) {
1033dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      DiagStr = clang_formatDiagnostic(Diag,
1034dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis                                       clang_defaultDiagnosticDisplayOptions());
1035dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      fprintf(stderr, "%s\n", clang_getCString(DiagStr));
1036dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      clang_disposeString(DiagStr);
1037dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      clang_disposeDiagnostic(Diag);
1038dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      return -1;
1039dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    }
1040dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    clang_disposeDiagnostic(Diag);
1041dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  }
1042dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1043dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  return 0;
1044dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis}
1045dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
10463ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregorvoid print_completion_string(CXCompletionString completion_string, FILE *file) {
1047f8297f1512d29c88f20bf2901f04cc04182a3eeeDaniel Dunbar  int I, N;
1048e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
10493ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor  N = clang_getNumCompletionChunks(completion_string);
10500c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  for (I = 0; I != N; ++I) {
10512ef6f8f5a35a60870594c5b04e0aa2bf22c6886fTed Kremenek    CXString text;
10522ef6f8f5a35a60870594c5b04e0aa2bf22c6886fTed Kremenek    const char *cstr;
10530c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor    enum CXCompletionChunkKind Kind
10543ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor      = clang_getCompletionChunkKind(completion_string, I);
1055e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
10563ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor    if (Kind == CXCompletionChunk_Optional) {
10573ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor      fprintf(file, "{Optional ");
10583ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor      print_completion_string(
1059e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek                clang_getCompletionChunkCompletionString(completion_string, I),
10603ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor                              file);
10613ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor      fprintf(file, "}");
10623ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor      continue;
10635a9c0bca4504eeda45a3fd0ae1c244b2994f38b2Douglas Gregor    }
10645a9c0bca4504eeda45a3fd0ae1c244b2994f38b2Douglas Gregor
10655a9c0bca4504eeda45a3fd0ae1c244b2994f38b2Douglas Gregor    if (Kind == CXCompletionChunk_VerticalSpace) {
10665a9c0bca4504eeda45a3fd0ae1c244b2994f38b2Douglas Gregor      fprintf(file, "{VerticalSpace  }");
10675a9c0bca4504eeda45a3fd0ae1c244b2994f38b2Douglas Gregor      continue;
10683ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor    }
1069e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1070d5a2089663d81faee0de031deabc418fa53ecf3bDouglas Gregor    text = clang_getCompletionChunkText(completion_string, I);
10712ef6f8f5a35a60870594c5b04e0aa2bf22c6886fTed Kremenek    cstr = clang_getCString(text);
1072e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    fprintf(file, "{%s %s}",
10730c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor            clang_getCompletionChunkKindSpelling(Kind),
10742ef6f8f5a35a60870594c5b04e0aa2bf22c6886fTed Kremenek            cstr ? cstr : "");
10752ef6f8f5a35a60870594c5b04e0aa2bf22c6886fTed Kremenek    clang_disposeString(text);
10760c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  }
10772ef6f8f5a35a60870594c5b04e0aa2bf22c6886fTed Kremenek
10783ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor}
10793ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor
10803ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregorvoid print_completion_result(CXCompletionResult *completion_result,
10813ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor                             CXClientData client_data) {
10823ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor  FILE *file = (FILE *)client_data;
1083e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
10846164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen  unsigned annotationCount;
1085e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1086e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  fprintf(file, "%s:", clang_getCString(ks));
1087e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  clang_disposeString(ks);
1088e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
10893ac738567fdf4df636b9e76c5a2d3dc3d6f80235Douglas Gregor  print_completion_string(completion_result->CompletionString, file);
109058ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  fprintf(file, " (%u)",
109112e131385e892e3723483a1081a89bcad29c8a84Douglas Gregor          clang_getCompletionPriority(completion_result->CompletionString));
109258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  switch (clang_getCompletionAvailability(completion_result->CompletionString)){
109358ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  case CXAvailability_Available:
109458ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    break;
109558ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
109658ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  case CXAvailability_Deprecated:
109758ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    fprintf(file, " (deprecated)");
109858ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    break;
109958ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
110058ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  case CXAvailability_NotAvailable:
110158ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    fprintf(file, " (unavailable)");
110258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    break;
1103d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen
1104d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen  case CXAvailability_NotAccessible:
1105d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen    fprintf(file, " (inaccessible)");
1106d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen    break;
110758ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  }
11086164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen
11096164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen  annotationCount = clang_getCompletionNumAnnotations(
11106164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen        completion_result->CompletionString);
11116164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen  if (annotationCount) {
11126164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen    unsigned i;
11136164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen    fprintf(file, " (");
11146164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen    for (i = 0; i < annotationCount; ++i) {
11156164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen      if (i != 0)
11166164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen        fprintf(file, ", ");
11176164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen      fprintf(file, "\"%s\"",
11186164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen              clang_getCString(clang_getCompletionAnnotation(
11196164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen                                 completion_result->CompletionString, i)));
11206164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen    }
11216164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen    fprintf(file, ")");
11226164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen  }
11236164ea1d75385b6fc3c19e5ab9bb686298436a5aErik Verbruggen
112458ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  fprintf(file, "\n");
11250c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor}
11260c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor
11273da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregorvoid print_completion_contexts(unsigned long long contexts, FILE *file) {
11283da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  fprintf(file, "Completion contexts:\n");
11293da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts == CXCompletionContext_Unknown) {
11303da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Unknown\n");
11313da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11323da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_AnyType) {
11333da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Any type\n");
11343da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11353da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_AnyValue) {
11363da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Any value\n");
11373da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11383da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCObjectValue) {
11393da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C object value\n");
11403da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11413da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCSelectorValue) {
11423da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C selector value\n");
11433da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11443da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_CXXClassTypeValue) {
11453da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "C++ class type value\n");
11463da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11473da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_DotMemberAccess) {
11483da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Dot member access\n");
11493da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11503da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ArrowMemberAccess) {
11513da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Arrow member access\n");
11523da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11533da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCPropertyAccess) {
11543da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C property access\n");
11553da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11563da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_EnumTag) {
11573da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Enum tag\n");
11583da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11593da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_UnionTag) {
11603da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Union tag\n");
11613da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11623da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_StructTag) {
11633da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Struct tag\n");
11643da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11653da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ClassTag) {
11663da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Class name\n");
11673da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11683da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_Namespace) {
11693da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Namespace or namespace alias\n");
11703da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11713da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_NestedNameSpecifier) {
11723da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Nested name specifier\n");
11733da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11743da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCInterface) {
11753da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C interface\n");
11763da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11773da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCProtocol) {
11783da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C protocol\n");
11793da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11803da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCCategory) {
11813da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C category\n");
11823da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11833da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCInstanceMessage) {
11843da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C instance method\n");
11853da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11863da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCClassMessage) {
11873da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C class method\n");
11883da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11893da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_ObjCSelectorName) {
11903da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Objective-C selector name\n");
11913da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11923da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_MacroName) {
11933da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Macro name\n");
11943da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11953da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  if (contexts & CXCompletionContext_NaturalLanguage) {
11963da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    fprintf(file, "Natural language\n");
11973da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor  }
11983da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor}
11993da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor
12001e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregorint my_stricmp(const char *s1, const char *s2) {
12011e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor  while (*s1 && *s2) {
12026d5552131a4637f9bbe8c93386648e9bbb2c30feNAKAMURA Takumi    int c1 = tolower((unsigned char)*s1), c2 = tolower((unsigned char)*s2);
12031e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    if (c1 < c2)
12041e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor      return -1;
12051e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    else if (c1 > c2)
12061e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor      return 1;
12071e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor
12081e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    ++s1;
12091e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    ++s2;
12101e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor  }
12111e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor
12121e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor  if (*s1)
12131e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    return 1;
12141e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor  else if (*s2)
12151e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    return -1;
12161e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor  return 0;
12171e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor}
12181e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor
12191982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregorint perform_code_completion(int argc, const char **argv, int timing_only) {
12200c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  const char *input = argv[1];
12210c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  char *filename = 0;
12220c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  unsigned line;
12230c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  unsigned column;
1224f8297f1512d29c88f20bf2901f04cc04182a3eeeDaniel Dunbar  CXIndex CIdx;
1225f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek  int errorCode;
1226735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor  struct CXUnsavedFile *unsaved_files = 0;
1227735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor  int num_unsaved_files = 0;
1228ec6762c709726bf2ee5f76c21df81e71a56e6f81Douglas Gregor  CXCodeCompleteResults *results = 0;
122925d9b00ab0b128d651d993c38726a00cd9969124Dawn Perchik  CXTranslationUnit TU = 0;
123032be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  unsigned I, Repeats = 1;
123132be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  unsigned completionOptions = clang_defaultCodeCompleteOptions();
123232be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor
123332be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  if (getenv("CINDEXTEST_CODE_COMPLETE_PATTERNS"))
123432be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    completionOptions |= CXCodeComplete_IncludeCodePatterns;
1235df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor
12361982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor  if (timing_only)
12371982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    input += strlen("-code-completion-timing=");
12381982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor  else
12391982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    input += strlen("-code-completion-at=");
12401982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor
1241e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
1242fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor                                          0, 0)))
1243f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek    return errorCode;
12440c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor
1245735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor  if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
1246735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor    return -1;
1247735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor
124832be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  CIdx = clang_createIndex(0, 0);
124932be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor
125032be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  if (getenv("CINDEXTEST_EDITING"))
125132be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    Repeats = 5;
125232be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor
125332be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  TU = clang_parseTranslationUnit(CIdx, 0,
125432be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor                                  argv + num_unsaved_files + 2,
125532be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor                                  argc - num_unsaved_files - 2,
125632be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor                                  0, 0, getDefaultParsingOptions());
125732be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  if (!TU) {
125832be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    fprintf(stderr, "Unable to load translation unit!\n");
125932be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    return 1;
126032be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  }
126108bb4c622d0b79c33b4ac78ce1bec79398953daaDouglas Gregor
126208bb4c622d0b79c33b4ac78ce1bec79398953daaDouglas Gregor  if (clang_reparseTranslationUnit(TU, 0, 0, clang_defaultReparseOptions(TU))) {
126308bb4c622d0b79c33b4ac78ce1bec79398953daaDouglas Gregor    fprintf(stderr, "Unable to reparse translation init!\n");
126408bb4c622d0b79c33b4ac78ce1bec79398953daaDouglas Gregor    return 1;
126508bb4c622d0b79c33b4ac78ce1bec79398953daaDouglas Gregor  }
126632be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor
126732be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  for (I = 0; I != Repeats; ++I) {
126832be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    results = clang_codeCompleteAt(TU, filename, line, column,
126932be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor                                   unsaved_files, num_unsaved_files,
127032be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor                                   completionOptions);
127132be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    if (!results) {
127232be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor      fprintf(stderr, "Unable to perform code completion!\n");
12732de41c9c99e0e9ae6488d04c08423a5c1190109eDaniel Dunbar      return 1;
12742de41c9c99e0e9ae6488d04c08423a5c1190109eDaniel Dunbar    }
127532be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor    if (I != Repeats-1)
127632be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor      clang_disposeCodeCompleteResults(results);
127732be4a588fbb87d0d163ead49c42f5438bf0b2b7Douglas Gregor  }
1278936ea3b590117d2cd73b1b92621d06c4a7edbe60Douglas Gregor
1279ec6762c709726bf2ee5f76c21df81e71a56e6f81Douglas Gregor  if (results) {
1280e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor    unsigned i, n = results->NumResults, containerIsIncomplete = 0;
12813da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    unsigned long long contexts;
1282e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor    enum CXCursorKind containerKind;
12830a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    CXString objCSelector;
12840a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    const char *selectorString;
12851e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    if (!timing_only) {
12861e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor      /* Sort the code-completion results based on the typed text. */
12871e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor      clang_sortCodeCompletionResults(results->Results, results->NumResults);
12881e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor
12891982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor      for (i = 0; i != n; ++i)
12901982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor        print_completion_result(results->Results + i, stdout);
12911e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor    }
1292a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    n = clang_codeCompleteGetNumDiagnostics(results);
1293a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    for (i = 0; i != n; ++i) {
1294a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i);
1295a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      PrintDiagnostic(diag);
1296a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      clang_disposeDiagnostic(diag);
1297a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    }
12983da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor
12993da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    contexts = clang_codeCompleteGetContexts(results);
13003da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor    print_completion_contexts(contexts, stdout);
13013da626b4f38eb0350de960d71271ca77af7a9cc8Douglas Gregor
13020a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    containerKind = clang_codeCompleteGetContainerKind(results,
13030a47d69af8bda945352997af3da4687a3356096aDouglas Gregor                                                       &containerIsIncomplete);
1304e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor
1305e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor    if (containerKind != CXCursor_InvalidCode) {
1306e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      /* We have found a container */
1307e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      CXString containerUSR, containerKindSpelling;
1308e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      containerKindSpelling = clang_getCursorKindSpelling(containerKind);
1309e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      printf("Container Kind: %s\n", clang_getCString(containerKindSpelling));
1310e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      clang_disposeString(containerKindSpelling);
1311e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor
1312e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      if (containerIsIncomplete) {
1313e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor        printf("Container is incomplete\n");
1314e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      }
1315e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      else {
1316e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor        printf("Container is complete\n");
1317e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      }
1318e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor
1319e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      containerUSR = clang_codeCompleteGetContainerUSR(results);
1320e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      printf("Container USR: %s\n", clang_getCString(containerUSR));
1321e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor      clang_disposeString(containerUSR);
1322e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor    }
1323e081a61bb0dc546fd623bf259435d17c9a4ea0d5Douglas Gregor
13240a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    objCSelector = clang_codeCompleteGetObjCSelector(results);
13250a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    selectorString = clang_getCString(objCSelector);
13260a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    if (selectorString && strlen(selectorString) > 0) {
13270a47d69af8bda945352997af3da4687a3356096aDouglas Gregor      printf("Objective-C selector: %s\n", selectorString);
13280a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    }
13290a47d69af8bda945352997af3da4687a3356096aDouglas Gregor    clang_disposeString(objCSelector);
13300a47d69af8bda945352997af3da4687a3356096aDouglas Gregor
1331ec6762c709726bf2ee5f76c21df81e71a56e6f81Douglas Gregor    clang_disposeCodeCompleteResults(results);
1332ec6762c709726bf2ee5f76c21df81e71a56e6f81Douglas Gregor  }
1333df95a13ec73d2cdaea79555cb412d767f4963120Douglas Gregor  clang_disposeTranslationUnit(TU);
13340c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  clang_disposeIndex(CIdx);
13350c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor  free(filename);
1336e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1337735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor  free_remapped_files(unsaved_files, num_unsaved_files);
1338735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor
1339f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek  return 0;
13400c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor}
13410c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor
1342f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregortypedef struct {
1343f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  char *filename;
1344f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  unsigned line;
1345f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  unsigned column;
1346f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor} CursorSourceLocation;
1347f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor
1348aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic int inspect_cursor_at(int argc, const char **argv) {
1349f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  CXIndex CIdx;
1350f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  int errorCode;
1351f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  struct CXUnsavedFile *unsaved_files = 0;
1352f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  int num_unsaved_files = 0;
1353f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  CXTranslationUnit TU;
1354f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  CXCursor Cursor;
1355f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  CursorSourceLocation *Locations = 0;
1356f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  unsigned NumLocations = 0, Loc;
13578e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor  unsigned Repeats = 1;
1358bdc4b366e80c125184a3b3c56fa4619cb4ac9e45Douglas Gregor  unsigned I;
13598e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor
1360e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  /* Count the number of locations. */
1361f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  while (strstr(argv[NumLocations+1], "-cursor-at=") == argv[NumLocations+1])
1362f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    ++NumLocations;
1363e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1364f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  /* Parse the locations. */
1365f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  assert(NumLocations > 0 && "Unable to count locations?");
1366f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  Locations = (CursorSourceLocation *)malloc(
1367f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor                                  NumLocations * sizeof(CursorSourceLocation));
1368f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  for (Loc = 0; Loc < NumLocations; ++Loc) {
1369f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    const char *input = argv[Loc + 1] + strlen("-cursor-at=");
1370e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
1371e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek                                            &Locations[Loc].line,
1372fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor                                            &Locations[Loc].column, 0, 0)))
1373f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor      return errorCode;
1374f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  }
1375e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1376e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
1377f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor                           &num_unsaved_files))
1378f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    return -1;
1379e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
13808e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor  if (getenv("CINDEXTEST_EDITING"))
13818e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor    Repeats = 5;
13828e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor
13838e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor  /* Parse the translation unit. When we're testing clang_getCursor() after
13848e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor     reparsing, don't remap unsaved files until the second parse. */
13858e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor  CIdx = clang_createIndex(1, 1);
13868e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
13878e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                                  argv + num_unsaved_files + 1 + NumLocations,
1388f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor                                  argc - num_unsaved_files - 2 - NumLocations,
13898e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                                  unsaved_files,
13908e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                                  Repeats > 1? 0 : num_unsaved_files,
13918e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                                  getDefaultParsingOptions());
13928e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor
1393f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  if (!TU) {
1394f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    fprintf(stderr, "unable to parse input\n");
1395f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    return -1;
1396f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  }
1397e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
1398dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0)
1399dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    return -1;
1400dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1401bdc4b366e80c125184a3b3c56fa4619cb4ac9e45Douglas Gregor  for (I = 0; I != Repeats; ++I) {
14028e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor    if (Repeats > 1 &&
14038e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor        clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
14048e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                                     clang_defaultReparseOptions(TU))) {
14058e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      clang_disposeTranslationUnit(TU);
14068e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      return 1;
14078e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor    }
1408dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1409dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    if (checkForErrors(TU) != 0)
1410dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      return -1;
14118e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor
14128e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor    for (Loc = 0; Loc < NumLocations; ++Loc) {
14138e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      CXFile file = clang_getFile(TU, Locations[Loc].filename);
14148e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      if (!file)
14158e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor        continue;
14168e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor
14178e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      Cursor = clang_getCursor(TU,
14188e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                               clang_getLocation(TU, file, Locations[Loc].line,
14198e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor                                                 Locations[Loc].column));
1420dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1421dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      if (checkForErrors(TU) != 0)
1422dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis        return -1;
1423dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
14248e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      if (I + 1 == Repeats) {
14258fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor        CXCompletionString completionString = clang_getCursorCompletionString(
14268fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor                                                                        Cursor);
1427aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        PrintCursor(Cursor);
14288fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor        if (completionString != NULL) {
14298fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor          printf("\nCompletion string: ");
14308fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor          print_completion_string(completionString, stdout);
14318fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor        }
14328e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor        printf("\n");
14338e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor        free(Locations[Loc].filename);
14348e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor      }
14358e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor    }
1436f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  }
14378e08dec6374473b11c019035aef130e0bb0551f9Douglas Gregor
1438a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  PrintDiagnostics(TU);
1439f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  clang_disposeTranslationUnit(TU);
1440f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  clang_disposeIndex(CIdx);
1441f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  free(Locations);
1442f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  free_remapped_files(unsaved_files, num_unsaved_files);
1443f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  return 0;
1444f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor}
1445f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor
1446aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic enum CXVisitorResult findFileRefsVisit(void *context,
1447aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                         CXCursor cursor, CXSourceRange range) {
1448aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (clang_Range_isNull(range))
1449aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return CXVisit_Continue;
1450aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1451aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  PrintCursor(cursor);
1452aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  PrintRange(range, "");
1453aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  printf("\n");
1454aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return CXVisit_Continue;
1455aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
1456aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1457aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisstatic int find_file_refs_at(int argc, const char **argv) {
1458aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXIndex CIdx;
1459aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  int errorCode;
1460aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  struct CXUnsavedFile *unsaved_files = 0;
1461aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  int num_unsaved_files = 0;
1462aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXTranslationUnit TU;
1463aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CXCursor Cursor;
1464aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CursorSourceLocation *Locations = 0;
1465aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  unsigned NumLocations = 0, Loc;
1466aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  unsigned Repeats = 1;
1467aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  unsigned I;
1468aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1469aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /* Count the number of locations. */
1470aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1])
1471aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    ++NumLocations;
1472aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1473aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /* Parse the locations. */
1474aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  assert(NumLocations > 0 && "Unable to count locations?");
1475aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  Locations = (CursorSourceLocation *)malloc(
1476aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                  NumLocations * sizeof(CursorSourceLocation));
1477aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  for (Loc = 0; Loc < NumLocations; ++Loc) {
1478aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    const char *input = argv[Loc + 1] + strlen("-file-refs-at=");
1479aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
1480aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                            &Locations[Loc].line,
1481aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                            &Locations[Loc].column, 0, 0)))
1482aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return errorCode;
1483aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
1484aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1485aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
1486aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                           &num_unsaved_files))
1487aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return -1;
1488aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1489aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (getenv("CINDEXTEST_EDITING"))
1490aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    Repeats = 5;
1491aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1492aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  /* Parse the translation unit. When we're testing clang_getCursor() after
1493aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis     reparsing, don't remap unsaved files until the second parse. */
1494aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  CIdx = clang_createIndex(1, 1);
1495aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
1496aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                  argv + num_unsaved_files + 1 + NumLocations,
1497aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                  argc - num_unsaved_files - 2 - NumLocations,
1498aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                  unsaved_files,
1499aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                  Repeats > 1? 0 : num_unsaved_files,
1500aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                  getDefaultParsingOptions());
1501aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1502aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!TU) {
1503aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    fprintf(stderr, "unable to parse input\n");
1504aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return -1;
1505aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
1506aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1507dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0)
1508dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    return -1;
1509dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1510aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  for (I = 0; I != Repeats; ++I) {
1511aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (Repeats > 1 &&
1512aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
1513aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                     clang_defaultReparseOptions(TU))) {
1514aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      clang_disposeTranslationUnit(TU);
1515aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      return 1;
1516aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
1517dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1518dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    if (checkForErrors(TU) != 0)
1519dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      return -1;
1520aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1521aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    for (Loc = 0; Loc < NumLocations; ++Loc) {
1522aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      CXFile file = clang_getFile(TU, Locations[Loc].filename);
1523aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      if (!file)
1524aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        continue;
1525aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1526aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      Cursor = clang_getCursor(TU,
1527aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                               clang_getLocation(TU, file, Locations[Loc].line,
1528aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                                                 Locations[Loc].column));
1529dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1530dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis      if (checkForErrors(TU) != 0)
1531dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis        return -1;
1532dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1533aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      if (I + 1 == Repeats) {
153426fc0f9a078b1a9120547b36804f97c626817bdfErik Verbruggen        CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit };
1535aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        PrintCursor(Cursor);
1536aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        printf("\n");
1537aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        clang_findReferencesInFile(Cursor, file, visitor);
1538aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis        free(Locations[Loc].filename);
1539dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
1540dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis        if (checkForErrors(TU) != 0)
1541dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis          return -1;
1542aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      }
1543aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
1544aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
1545aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
1546aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  PrintDiagnostics(TU);
1547aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  clang_disposeTranslationUnit(TU);
1548aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  clang_disposeIndex(CIdx);
1549aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  free(Locations);
1550aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  free_remapped_files(unsaved_files, num_unsaved_files);
1551aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return 0;
1552aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
1553aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
15544e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidistypedef struct {
15554e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const char *check_prefix;
15564e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  int first_check_printed;
1557dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  int fail_for_error;
15586f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  int abort;
155913c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  const char *main_filename;
15604e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis} IndexData;
15614e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
15624e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisstatic void printCheck(IndexData *data) {
15634e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (data->check_prefix) {
15644e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    if (data->first_check_printed) {
15654e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      printf("// %s-NEXT: ", data->check_prefix);
15664e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    } else {
15674e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      printf("// %s     : ", data->check_prefix);
15684e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      data->first_check_printed = 1;
15694e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    }
15704e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
15714e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
15724e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1573dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisstatic void printCXIndexFile(CXIdxClientFile file) {
15744e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  CXString filename = clang_getFileName((CXFile)file);
15754e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf("%s", clang_getCString(filename));
15764e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  clang_disposeString(filename);
15774e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
15784e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
157913c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidisstatic void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) {
158013c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  IndexData *index_data;
15814e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  CXString filename;
158213c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  const char *cname;
1583dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  CXIdxClientFile file;
15844e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  unsigned line, column;
158513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  int isMainFile;
15864e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
158713c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  index_data = (IndexData *)client_data;
15884e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
15894e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (line == 0) {
15904e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    printf("<null loc>");
15914e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return;
15924e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
1593c2be04eaec94e20fc825fb98b713112d9d82562fArgyrios Kyrtzidis  if (!file) {
1594c2be04eaec94e20fc825fb98b713112d9d82562fArgyrios Kyrtzidis    printf("<no idxfile>");
1595c2be04eaec94e20fc825fb98b713112d9d82562fArgyrios Kyrtzidis    return;
1596c2be04eaec94e20fc825fb98b713112d9d82562fArgyrios Kyrtzidis  }
15974e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  filename = clang_getFileName((CXFile)file);
15984e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  cname = clang_getCString(filename);
159913c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  if (strcmp(cname, index_data->main_filename) == 0)
160013c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    isMainFile = 1;
160113c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  else
160213c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    isMainFile = 0;
160313c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  clang_disposeString(filename);
160413c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis
160513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  if (!isMainFile) {
16064e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    printCXIndexFile(file);
16074e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    printf(":");
16084e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
16094e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf("%d:%d", line, column);
16104e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
16114e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
161213c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidisstatic unsigned digitCount(unsigned val) {
161313c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  unsigned c = 1;
161413c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  while (1) {
161513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    if (val < 10)
161613c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis      return c;
161713c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    ++c;
161813c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    val /= 10;
161913c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  }
162013c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis}
162113c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis
16226ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidisstatic CXIdxClientContainer makeClientContainer(const CXIdxEntityInfo *info,
16236ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis                                                CXIdxLoc loc) {
16244e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const char *name;
16254e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  char *newStr;
1626dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  CXIdxClientFile file;
16274e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  unsigned line, column;
16284e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1629dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  name = info->name;
16304e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (!name)
16314e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    name = "<anon-tag>";
16324e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
16334e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
1634f89bc0500c74a590ff9e99aab75bcc22d05bc760Argyrios Kyrtzidis  /* FIXME: free these.*/
163513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  newStr = (char *)malloc(strlen(name) +
163613c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis                          digitCount(line) + digitCount(column) + 3);
16374e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  sprintf(newStr, "%s:%d:%d", name, line, column);
16386ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  return (CXIdxClientContainer)newStr;
16394e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
16404e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
16412957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidisstatic void printCXIndexContainer(const CXIdxContainerInfo *info) {
16422957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  CXIdxClientContainer container;
16432957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  container = clang_index_getClientContainer(info);
16443e340a67f4522a2f633a719cb7f3389fe2474374Argyrios Kyrtzidis  if (!container)
16453e340a67f4522a2f633a719cb7f3389fe2474374Argyrios Kyrtzidis    printf("[<<NULL>>]");
16463e340a67f4522a2f633a719cb7f3389fe2474374Argyrios Kyrtzidis  else
16473e340a67f4522a2f633a719cb7f3389fe2474374Argyrios Kyrtzidis    printf("[%s]", (const char *)container);
16484e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
16494e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1650dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisstatic const char *getEntityKindString(CXIdxEntityKind kind) {
1651dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  switch (kind) {
1652dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Unexposed: return "<<UNEXPOSED>>";
1653dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Typedef: return "typedef";
1654dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Function: return "function";
1655dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Variable: return "variable";
1656dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Field: return "field";
1657dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_EnumConstant: return "enumerator";
1658dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_ObjCClass: return "objc-class";
1659dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_ObjCProtocol: return "objc-protocol";
1660dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_ObjCCategory: return "objc-category";
1661c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  case CXIdxEntity_ObjCInstanceMethod: return "objc-instance-method";
1662c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  case CXIdxEntity_ObjCClassMethod: return "objc-class-method";
1663dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_ObjCProperty: return "objc-property";
1664dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_ObjCIvar: return "objc-ivar";
1665dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Enum: return "enum";
1666dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Struct: return "struct";
1667dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_Union: return "union";
1668dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  case CXIdxEntity_CXXClass: return "c++-class";
16692957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXNamespace: return "namespace";
16702957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXNamespaceAlias: return "namespace-alias";
16712957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXStaticVariable: return "c++-static-var";
16722957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXStaticMethod: return "c++-static-method";
16732957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXInstanceMethod: return "c++-instance-method";
16742957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXConstructor: return "constructor";
16752957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXDestructor: return "destructor";
16762957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXConversionFunction: return "conversion-func";
16772957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_CXXTypeAlias: return "type-alias";
16782957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  }
16792957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  assert(0 && "Garbage entity kind");
16802957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  return 0;
16812957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis}
16822957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis
16832957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidisstatic const char *getEntityTemplateKindString(CXIdxEntityCXXTemplateKind kind) {
16842957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  switch (kind) {
16852957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_NonTemplate: return "";
16862957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_Template: return "-template";
16872957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_TemplatePartialSpecialization:
16882957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    return "-template-partial-spec";
16892957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  case CXIdxEntity_TemplateSpecialization: return "-template-spec";
1690dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  }
16916ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  assert(0 && "Garbage entity kind");
16926ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  return 0;
1693dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis}
1694dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis
1695838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidisstatic const char *getEntityLanguageString(CXIdxEntityLanguage kind) {
1696838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  switch (kind) {
1697838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  case CXIdxEntityLang_None: return "<none>";
1698838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  case CXIdxEntityLang_C: return "C";
1699838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  case CXIdxEntityLang_ObjC: return "ObjC";
1700838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  case CXIdxEntityLang_CXX: return "C++";
1701838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  }
1702838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  assert(0 && "Garbage language kind");
1703838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis  return 0;
1704838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis}
1705838d3c23204f52ae27a9f5e9a254238a7ac5d41bArgyrios Kyrtzidis
1706dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisstatic void printEntityInfo(const char *cb,
1707dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis                            CXClientData client_data,
17086ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis                            const CXIdxEntityInfo *info) {
17094e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const char *name;
17104e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  IndexData *index_data;
1711643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis  unsigned i;
17124e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_data = (IndexData *)client_data;
17134e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printCheck(index_data);
17144e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1715c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis  if (!info) {
1716c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis    printf("%s: <<NULL>>", cb);
1717c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis    return;
1718c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis  }
1719c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis
1720dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  name = info->name;
17214e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (!name)
17224e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    name = "<anon-tag>";
17234e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
17242957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  printf("%s: kind: %s%s", cb, getEntityKindString(info->kind),
17252957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis         getEntityTemplateKindString(info->templateKind));
1726dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf(" | name: %s", name);
1727dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf(" | USR: %s", info->USR);
1728c2be04eaec94e20fc825fb98b713112d9d82562fArgyrios Kyrtzidis  printf(" | lang: %s", getEntityLanguageString(info->lang));
1729643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis
1730643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis  for (i = 0; i != info->numAttributes; ++i) {
1731643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis    const CXIdxAttrInfo *Attr = info->attributes[i];
1732643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis    printf("     <attribute>: ");
1733643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis    PrintCursor(Attr->cursor);
1734643d3ce93c501d19353f2fa578fee3e97f1d1b4bArgyrios Kyrtzidis  }
17354e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
17364e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1737b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidisstatic void printBaseClassInfo(CXClientData client_data,
1738b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis                               const CXIdxBaseClassInfo *info) {
1739b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  printEntityInfo("     <base>", client_data, info->base);
1740b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  printf(" | cursor: ");
1741b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  PrintCursor(info->cursor);
1742b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  printf(" | loc: ");
174313c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  printCXIndexLoc(info->loc, client_data);
1744b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis}
1745b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis
1746c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidisstatic void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo,
1747c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis                              CXClientData client_data) {
1748c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  unsigned i;
1749c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  for (i = 0; i < ProtoInfo->numProtocols; ++i) {
1750c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis    printEntityInfo("     <protocol>", client_data,
1751c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis                    ProtoInfo->protocols[i]->protocol);
1752c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis    printf(" | cursor: ");
1753c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis    PrintCursor(ProtoInfo->protocols[i]->cursor);
1754c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis    printf(" | loc: ");
175513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    printCXIndexLoc(ProtoInfo->protocols[i]->loc, client_data);
1756c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis    printf("\n");
1757c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  }
1758c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis}
1759c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis
17604e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisstatic void index_diagnostic(CXClientData client_data,
1761996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis                             CXDiagnosticSet diagSet, void *reserved) {
17624e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  CXString str;
17634e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const char *cstr;
1764996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis  unsigned numDiags, i;
1765996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis  CXDiagnostic diag;
17664e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  IndexData *index_data;
17674e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_data = (IndexData *)client_data;
17684e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printCheck(index_data);
17694e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1770996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis  numDiags = clang_getNumDiagnosticsInSet(diagSet);
1771996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis  for (i = 0; i != numDiags; ++i) {
1772996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    diag = clang_getDiagnosticInSet(diagSet, i);
1773996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    str = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
1774996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    cstr = clang_getCString(str);
1775996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    printf("[diagnostic]: %s\n", cstr);
1776996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    clang_disposeString(str);
1777996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis
1778996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    if (getenv("CINDEXTEST_FAILONERROR") &&
1779996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis        clang_getDiagnosticSeverity(diag) >= CXDiagnostic_Error) {
1780996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis      index_data->fail_for_error = 1;
1781996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis    }
1782dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  }
17834e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
17844e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1785dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisstatic CXIdxClientFile index_enteredMainFile(CXClientData client_data,
1786dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis                                       CXFile file, void *reserved) {
1787dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  IndexData *index_data;
178862d7fea624f466d11001b2dc733bee12a3b90c3aArgyrios Kyrtzidis  CXString filename;
178962d7fea624f466d11001b2dc733bee12a3b90c3aArgyrios Kyrtzidis
1790dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  index_data = (IndexData *)client_data;
1791dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printCheck(index_data);
1792dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis
179362d7fea624f466d11001b2dc733bee12a3b90c3aArgyrios Kyrtzidis  filename = clang_getFileName(file);
179413c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  index_data->main_filename = clang_getCString(filename);
179513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  clang_disposeString(filename);
179613c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis
1797dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf("[enteredMainFile]: ");
1798dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printCXIndexFile((CXIdxClientFile)file);
1799dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf("\n");
1800dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis
1801dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  return (CXIdxClientFile)file;
18024e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
18034e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1804dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisstatic CXIdxClientFile index_ppIncludedFile(CXClientData client_data,
18056ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis                                            const CXIdxIncludedFileInfo *info) {
18064e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  IndexData *index_data;
18074e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_data = (IndexData *)client_data;
18084e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printCheck(index_data);
18094e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
181066042b32b3b37ddcba731ff05c2792e3bb572102Argyrios Kyrtzidis  printf("[ppIncludedFile]: ");
1811dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printCXIndexFile((CXIdxClientFile)info->file);
18124e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf(" | name: \"%s\"", info->filename);
18134e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf(" | hash loc: ");
181413c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  printCXIndexLoc(info->hashLoc, client_data);
18154e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf(" | isImport: %d | isAngled: %d\n", info->isImport, info->isAngled);
1816dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis
1817dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  return (CXIdxClientFile)info->file;
18184e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
18194e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1820dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidisstatic CXIdxClientContainer index_startedTranslationUnit(CXClientData client_data,
18214e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                                                   void *reserved) {
18224e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  IndexData *index_data;
18234e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_data = (IndexData *)client_data;
18244e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printCheck(index_data);
18254e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
182666042b32b3b37ddcba731ff05c2792e3bb572102Argyrios Kyrtzidis  printf("[startedTranslationUnit]\n");
1827dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  return (CXIdxClientContainer)"TU";
18284e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
18294e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
18306ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidisstatic void index_indexDeclaration(CXClientData client_data,
18312957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis                                   const CXIdxDeclInfo *info) {
1832dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  IndexData *index_data;
18336ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  const CXIdxObjCCategoryDeclInfo *CatInfo;
18346ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  const CXIdxObjCInterfaceDeclInfo *InterInfo;
1835c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  const CXIdxObjCProtocolRefListInfo *ProtoInfo;
1836792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis  const CXIdxObjCPropertyDeclInfo *PropInfo;
1837b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  const CXIdxCXXClassDeclInfo *CXXClassInfo;
1838b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  unsigned i;
1839dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  index_data = (IndexData *)client_data;
18404e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1841dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printEntityInfo("[indexDeclaration]", client_data, info->entityInfo);
1842dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf(" | cursor: ");
1843dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  PrintCursor(info->cursor);
1844dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf(" | loc: ");
184513c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  printCXIndexLoc(info->loc, client_data);
1846b1febb646bf7a2f319ad894c9833968c52d21711Argyrios Kyrtzidis  printf(" | semantic-container: ");
1847b1febb646bf7a2f319ad894c9833968c52d21711Argyrios Kyrtzidis  printCXIndexContainer(info->semanticContainer);
1848b1febb646bf7a2f319ad894c9833968c52d21711Argyrios Kyrtzidis  printf(" | lexical-container: ");
1849b1febb646bf7a2f319ad894c9833968c52d21711Argyrios Kyrtzidis  printCXIndexContainer(info->lexicalContainer);
1850dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printf(" | isRedecl: %d", info->isRedeclaration);
1851c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  printf(" | isDef: %d", info->isDefinition);
1852c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  printf(" | isContainer: %d", info->isContainer);
1853c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  printf(" | isImplicit: %d\n", info->isImplicit);
18544e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1855b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  for (i = 0; i != info->numAttributes; ++i) {
185687adb0bf9375390de4c66d9e2ad110cc492cd655NAKAMURA Takumi    const CXIdxAttrInfo *Attr = info->attributes[i];
1857b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis    printf("     <attribute>: ");
1858b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis    PrintCursor(Attr->cursor);
1859b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis    printf("\n");
1860b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  }
1861b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis
1862dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  if (clang_index_isEntityObjCContainerKind(info->entityInfo->kind)) {
1863dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    const char *kindName = 0;
1864dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    CXIdxObjCContainerKind K = clang_index_getObjCContainerDeclInfo(info)->kind;
1865dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    switch (K) {
1866dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    case CXIdxObjCContainer_ForwardRef:
1867dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis      kindName = "forward-ref"; break;
1868dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    case CXIdxObjCContainer_Interface:
1869dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis      kindName = "interface"; break;
1870dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    case CXIdxObjCContainer_Implementation:
1871dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis      kindName = "implementation"; break;
1872dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    }
1873dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    printCheck(index_data);
1874dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    printf("     <ObjCContainerInfo>: kind: %s\n", kindName);
1875dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  }
18764e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
18776ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  if ((CatInfo = clang_index_getObjCCategoryDeclInfo(info))) {
1878dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    printEntityInfo("     <ObjCCategoryInfo>: class", client_data,
1879dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis                    CatInfo->objcClass);
188021ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    printf(" | cursor: ");
188121ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    PrintCursor(CatInfo->classCursor);
188221ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    printf(" | loc: ");
188313c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis    printCXIndexLoc(CatInfo->classLoc, client_data);
1884dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis    printf("\n");
1885dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  }
18864e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
18876ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  if ((InterInfo = clang_index_getObjCInterfaceDeclInfo(info))) {
18886ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis    if (InterInfo->superInfo) {
1889b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis      printBaseClassInfo(client_data, InterInfo->superInfo);
18906ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis      printf("\n");
18916ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis    }
18924e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
18934e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1894c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  if ((ProtoInfo = clang_index_getObjCProtocolRefListInfo(info))) {
1895c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis    printProtocolList(ProtoInfo, client_data);
18966ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis  }
18974e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1898792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis  if ((PropInfo = clang_index_getObjCPropertyDeclInfo(info))) {
1899792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis    if (PropInfo->getter) {
1900792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis      printEntityInfo("     <getter>", client_data, PropInfo->getter);
1901792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis      printf("\n");
1902792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis    }
1903792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis    if (PropInfo->setter) {
1904792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis      printEntityInfo("     <setter>", client_data, PropInfo->setter);
1905792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis      printf("\n");
1906792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis    }
1907792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis  }
1908792db266f3d2f12a7a16bf37d90074f54bca1e6fArgyrios Kyrtzidis
1909b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  if ((CXXClassInfo = clang_index_getCXXClassDeclInfo(info))) {
1910b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis    for (i = 0; i != CXXClassInfo->numBases; ++i) {
1911b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis      printBaseClassInfo(client_data, CXXClassInfo->bases[i]);
1912b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis      printf("\n");
1913b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis    }
1914b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis  }
1915b526a871af40b84d9878eded54a181bf4003b376Argyrios Kyrtzidis
19162957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  if (info->declAsContainer)
19172957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    clang_index_setClientContainer(info->declAsContainer,
19182957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis                              makeClientContainer(info->entityInfo, info->loc));
19194e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
19204e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
19214e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisstatic void index_indexEntityReference(CXClientData client_data,
19226ec43adc39006a7fce94188956d0239bd54c0363Argyrios Kyrtzidis                                       const CXIdxEntityRefInfo *info) {
1923dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printEntityInfo("[indexEntityReference]", client_data, info->referencedEntity);
19244e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf(" | cursor: ");
19254e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  PrintCursor(info->cursor);
19264e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf(" | loc: ");
192713c20a77d486c1ce0b6db2b836f2d14daa9e95ffArgyrios Kyrtzidis  printCXIndexLoc(info->loc, client_data);
1928dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  printEntityInfo(" | <parent>:", client_data, info->parentEntity);
19294e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf(" | container: ");
19304e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printCXIndexContainer(info->container);
1931c71d55469e7d5f7b376a30620617a175a9442da9Argyrios Kyrtzidis  printf(" | refkind: ");
1932aca19be8731fc31cff68702de0dc7f30ce908979Argyrios Kyrtzidis  switch (info->kind) {
1933aca19be8731fc31cff68702de0dc7f30ce908979Argyrios Kyrtzidis  case CXIdxEntityRef_Direct: printf("direct"); break;
1934b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  case CXIdxEntityRef_Implicit: printf("implicit"); break;
1935aca19be8731fc31cff68702de0dc7f30ce908979Argyrios Kyrtzidis  }
19364e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  printf("\n");
19374e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
19384e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
19396f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidisstatic int index_abortQuery(CXClientData client_data, void *reserved) {
19406f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  IndexData *index_data;
19416f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  index_data = (IndexData *)client_data;
19426f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  return index_data->abort;
19436f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis}
19446f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis
19454e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisstatic IndexerCallbacks IndexCB = {
19466f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  index_abortQuery,
19474e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_diagnostic,
1948dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  index_enteredMainFile,
19494e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_ppIncludedFile,
1950f89bc0500c74a590ff9e99aab75bcc22d05bc760Argyrios Kyrtzidis  0, /*importedASTFile*/
19514e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_startedTranslationUnit,
1952dd93c596cd95e1b96031ff47efe0a5095ff3d7f1Argyrios Kyrtzidis  index_indexDeclaration,
19534e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_indexEntityReference
19544e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis};
19554e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
195622490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidisstatic unsigned getIndexOptions(void) {
195722490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  unsigned index_opts;
195822490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  index_opts = 0;
195922490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  if (getenv("CINDEXTEST_SUPPRESSREFS"))
196022490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis    index_opts |= CXIndexOpt_SuppressRedundantRefs;
196122490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  if (getenv("CINDEXTEST_INDEXLOCALSYMBOLS"))
196222490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis    index_opts |= CXIndexOpt_IndexFunctionLocalSymbols;
196322490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis
196422490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  return index_opts;
196522490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis}
196622490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis
19674e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisstatic int index_file(int argc, const char **argv) {
19684e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const char *check_prefix;
19692957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  CXIndex Idx;
19702957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  CXIndexAction idxAction;
19714e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  IndexData index_data;
1972b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  unsigned index_opts;
1973dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  int result;
19744e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
19754e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  check_prefix = 0;
19764e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (argc > 0) {
19774e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    if (strstr(argv[0], "-check-prefix=") == argv[0]) {
19784e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      check_prefix = argv[0] + strlen("-check-prefix=");
19794e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      ++argv;
19804e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      --argc;
19814e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    }
19824e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
19834e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
19844e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (argc == 0) {
19854e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    fprintf(stderr, "no compiler arguments\n");
19864e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return -1;
19874e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
19884e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
19892957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
19902957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis                                /* displayDiagnosics=*/1))) {
19912957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    fprintf(stderr, "Could not create Index\n");
19922957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    return 1;
19932957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  }
19942957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  idxAction = 0;
19952957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  result = 1;
19962957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis
19974e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_data.check_prefix = check_prefix;
19984e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  index_data.first_check_printed = 0;
1999dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  index_data.fail_for_error = 0;
20006f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  index_data.abort = 0;
2001dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
200222490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  index_opts = getIndexOptions();
20032957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  idxAction = clang_IndexAction_create(Idx);
20042957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  result = clang_indexSourceFile(idxAction, &index_data,
2005b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis                                 &IndexCB,sizeof(IndexCB), index_opts,
2006c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis                                 0, argv, argc, 0, 0, 0, 0);
200721ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  if (index_data.fail_for_error)
20082957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    result = -1;
200921ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
20102957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  clang_IndexAction_dispose(idxAction);
20112957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  clang_disposeIndex(Idx);
201221ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  return result;
201321ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis}
201421ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
201521ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidisstatic int index_tu(int argc, const char **argv) {
201621ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  CXIndex Idx;
20172957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  CXIndexAction idxAction;
201821ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  CXTranslationUnit TU;
201921ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  const char *check_prefix;
202021ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  IndexData index_data;
2021b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  unsigned index_opts;
202221ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  int result;
202321ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
202421ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  check_prefix = 0;
202521ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  if (argc > 0) {
202621ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    if (strstr(argv[0], "-check-prefix=") == argv[0]) {
202721ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis      check_prefix = argv[0] + strlen("-check-prefix=");
202821ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis      ++argv;
202921ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis      --argc;
203021ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    }
203121ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  }
203221ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
203321ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  if (argc == 0) {
203421ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    fprintf(stderr, "no ast file\n");
203521ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    return -1;
203621ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  }
203721ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
203821ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
203921ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis                                /* displayDiagnosics=*/1))) {
204021ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    fprintf(stderr, "Could not create Index\n");
204121ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    return 1;
204221ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  }
20432957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  idxAction = 0;
20442957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  result = 1;
204521ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
204621ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  if (!CreateTranslationUnit(Idx, argv[0], &TU))
20472957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    goto finished;
204821ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
204921ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  index_data.check_prefix = check_prefix;
205021ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  index_data.first_check_printed = 0;
205121ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  index_data.fail_for_error = 0;
20526f3ce979a7748fd117e6473d6272b16d643b6262Argyrios Kyrtzidis  index_data.abort = 0;
205321ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis
205422490747c123a78feec089539f30426084d348cfArgyrios Kyrtzidis  index_opts = getIndexOptions();
20552957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  idxAction = clang_IndexAction_create(Idx);
20562957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  result = clang_indexTranslationUnit(idxAction, &index_data,
2057c6b4a5099588fd21b49c80f730a596a64b2766c6Argyrios Kyrtzidis                                      &IndexCB,sizeof(IndexCB),
20582957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis                                      index_opts, TU);
2059dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (index_data.fail_for_error)
20602957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis    goto finished;
20614e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
20622957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  finished:
20632957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  clang_IndexAction_dispose(idxAction);
20642957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis  clang_disposeIndex(Idx);
20652957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis
2066dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  return result;
20674e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
20684e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
2069fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregorint perform_token_annotation(int argc, const char **argv) {
2070fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  const char *input = argv[1];
2071fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  char *filename = 0;
2072fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  unsigned line, second_line;
2073fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  unsigned column, second_column;
2074fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXIndex CIdx;
2075fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXTranslationUnit TU = 0;
2076fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  int errorCode;
2077fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  struct CXUnsavedFile *unsaved_files = 0;
2078fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  int num_unsaved_files = 0;
2079fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXToken *tokens;
2080fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  unsigned num_tokens;
2081fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXSourceRange range;
2082fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXSourceLocation startLoc, endLoc;
2083fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXFile file = 0;
2084fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  CXCursor *cursors = 0;
2085fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  unsigned i;
2086fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2087fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  input += strlen("-test-annotate-tokens=");
2088fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
2089fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor                                          &second_line, &second_column)))
2090fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    return errorCode;
2091fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2092fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
2093fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    return -1;
2094fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
20950a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  CIdx = clang_createIndex(0, 1);
2096dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
2097dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  argv + num_unsaved_files + 2,
2098dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  argc - num_unsaved_files - 3,
2099dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  unsaved_files,
2100dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  num_unsaved_files,
2101dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor                                  getDefaultParsingOptions());
2102fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (!TU) {
2103fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    fprintf(stderr, "unable to parse input\n");
2104fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    clang_disposeIndex(CIdx);
2105fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    free(filename);
2106fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    free_remapped_files(unsaved_files, num_unsaved_files);
2107fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    return -1;
2108e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  }
2109fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  errorCode = 0;
2110fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2111dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0)
2112dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    return -1;
2113dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
2114ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis  if (getenv("CINDEXTEST_EDITING")) {
2115ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis    for (i = 0; i < 5; ++i) {
2116ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis      if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
2117ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis                                       clang_defaultReparseOptions(TU))) {
2118ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis        fprintf(stderr, "Unable to reparse translation unit!\n");
2119ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis        errorCode = -1;
2120ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis        goto teardown;
2121ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis      }
2122ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis    }
2123ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis  }
2124ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis
2125dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0) {
2126dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    errorCode = -1;
2127dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    goto teardown;
2128dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  }
2129dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
2130fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  file = clang_getFile(TU, filename);
2131fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (!file) {
2132fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    fprintf(stderr, "file %s is not in this translation unit\n", filename);
2133fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    errorCode = -1;
2134fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    goto teardown;
2135fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  }
2136fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2137fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  startLoc = clang_getLocation(TU, file, line, column);
2138fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (clang_equalLocations(clang_getNullLocation(), startLoc)) {
2139e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    fprintf(stderr, "invalid source location %s:%d:%d\n", filename, line,
2140fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor            column);
2141fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    errorCode = -1;
2142e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    goto teardown;
2143fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  }
2144fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2145fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  endLoc = clang_getLocation(TU, file, second_line, second_column);
2146fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  if (clang_equalLocations(clang_getNullLocation(), endLoc)) {
2147e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    fprintf(stderr, "invalid source location %s:%d:%d\n", filename,
2148fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor            second_line, second_column);
2149fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    errorCode = -1;
2150e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    goto teardown;
2151fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  }
2152fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2153fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  range = clang_getRange(startLoc, endLoc);
2154fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  clang_tokenize(TU, range, &tokens, &num_tokens);
2155dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
2156dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0) {
2157dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    errorCode = -1;
2158dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    goto teardown;
2159dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  }
2160dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
2161fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor));
2162fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  clang_annotateTokens(TU, tokens, num_tokens, cursors);
2163dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
2164dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  if (checkForErrors(TU) != 0) {
2165dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    errorCode = -1;
2166dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis    goto teardown;
2167dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis  }
2168dfca64ddfbdbc48085119f7c943d05881899bf5eArgyrios Kyrtzidis
2169fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  for (i = 0; i != num_tokens; ++i) {
2170fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    const char *kind = "<unknown>";
2171fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    CXString spelling = clang_getTokenSpelling(TU, tokens[i]);
2172fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    CXSourceRange extent = clang_getTokenExtent(TU, tokens[i]);
2173fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    unsigned start_line, start_column, end_line, end_column;
2174fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2175fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    switch (clang_getTokenKind(tokens[i])) {
2176fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    case CXToken_Punctuation: kind = "Punctuation"; break;
2177fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    case CXToken_Keyword: kind = "Keyword"; break;
2178fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    case CXToken_Identifier: kind = "Identifier"; break;
2179fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    case CXToken_Literal: kind = "Literal"; break;
2180fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    case CXToken_Comment: kind = "Comment"; break;
2181fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    }
2182a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(clang_getRangeStart(extent),
2183a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor                              0, &start_line, &start_column, 0);
2184a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    clang_getSpellingLocation(clang_getRangeEnd(extent),
2185a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor                              0, &end_line, &end_column, 0);
218651b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar    printf("%s: \"%s\" ", kind, clang_getCString(spelling));
218751b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar    PrintExtent(stdout, start_line, start_column, end_line, end_column);
21880045e9fe1f7dfc37f1ea7bdb9b70bcdb6700f0c0Douglas Gregor    if (!clang_isInvalid(cursors[i].kind)) {
21890045e9fe1f7dfc37f1ea7bdb9b70bcdb6700f0c0Douglas Gregor      printf(" ");
2190aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      PrintCursor(cursors[i]);
21910045e9fe1f7dfc37f1ea7bdb9b70bcdb6700f0c0Douglas Gregor    }
21920045e9fe1f7dfc37f1ea7bdb9b70bcdb6700f0c0Douglas Gregor    printf("\n");
2193fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  }
2194fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  free(cursors);
219593f5e6a5d7690f90bc8a94e6b40d6c7d19719e0cTed Kremenek  clang_disposeTokens(TU, tokens, num_tokens);
2196fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
2197fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor teardown:
2198a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  PrintDiagnostics(TU);
2199fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  clang_disposeTranslationUnit(TU);
2200fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  clang_disposeIndex(CIdx);
2201fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  free(filename);
2202fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  free_remapped_files(unsaved_files, num_unsaved_files);
2203fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  return errorCode;
2204fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor}
2205fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor
22060d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
2207f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek/* USR printing.                                                              */
2208f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek/******************************************************************************/
2209f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2210f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekstatic int insufficient_usr(const char *kind, const char *usage) {
2211f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  fprintf(stderr, "USR for '%s' requires: %s\n", kind, usage);
2212f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  return 1;
2213f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2214f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2215f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekstatic unsigned isUSR(const char *s) {
2216f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  return s[0] == 'c' && s[1] == ':';
2217f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2218f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2219f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekstatic int not_usr(const char *s, const char *arg) {
2220f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  fprintf(stderr, "'%s' argument ('%s') is not a USR\n", s, arg);
2221f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  return 1;
2222f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2223f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2224f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekstatic void print_usr(CXString usr) {
2225f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  const char *s = clang_getCString(usr);
2226f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  printf("%s\n", s);
2227f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  clang_disposeString(usr);
2228f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2229f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2230f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekstatic void display_usrs() {
2231f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  fprintf(stderr, "-print-usrs options:\n"
2232f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        " ObjCCategory <class name> <category name>\n"
2233f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        " ObjCClass <class name>\n"
2234f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        " ObjCIvar <ivar name> <class USR>\n"
2235f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        " ObjCMethod <selector> [0=class method|1=instance method] "
2236f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            "<class USR>\n"
2237f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          " ObjCProperty <property name> <class USR>\n"
2238f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          " ObjCProtocol <protocol name>\n");
2239f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2240f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2241f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekint print_usrs(const char **I, const char **E) {
2242f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  while (I != E) {
2243f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    const char *kind = *I;
2244f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    unsigned len = strlen(kind);
2245f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    switch (len) {
2246f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      case 8:
2247f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        if (memcmp(kind, "ObjCIvar", 8) == 0) {
2248f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (I + 2 >= E)
2249f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return insufficient_usr(kind, "<ivar name> <class USR>");
2250f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (!isUSR(I[2]))
2251f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return not_usr("<class USR>", I[2]);
2252f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          else {
2253f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            CXString x;
2254a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek            x.data = (void*) I[2];
2255ed122735639d83c10f18c28c7fd117bfcd0f62cbTed Kremenek            x.private_flags = 0;
2256f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            print_usr(clang_constructUSR_ObjCIvar(I[1], x));
2257f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          }
2258f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2259f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          I += 3;
2260f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          continue;
2261f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        }
2262f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        break;
2263f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      case 9:
2264f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        if (memcmp(kind, "ObjCClass", 9) == 0) {
2265f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (I + 1 >= E)
2266f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return insufficient_usr(kind, "<class name>");
2267f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          print_usr(clang_constructUSR_ObjCClass(I[1]));
2268f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          I += 2;
2269f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          continue;
2270f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        }
2271f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        break;
2272f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      case 10:
2273f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        if (memcmp(kind, "ObjCMethod", 10) == 0) {
2274f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (I + 3 >= E)
2275f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return insufficient_usr(kind, "<method selector> "
2276f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek                "[0=class method|1=instance method] <class USR>");
2277f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (!isUSR(I[3]))
2278f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return not_usr("<class USR>", I[3]);
2279f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          else {
2280f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            CXString x;
2281a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek            x.data = (void*) I[3];
2282ed122735639d83c10f18c28c7fd117bfcd0f62cbTed Kremenek            x.private_flags = 0;
2283f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            print_usr(clang_constructUSR_ObjCMethod(I[1], atoi(I[2]), x));
2284f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          }
2285f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          I += 4;
2286f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          continue;
2287f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        }
2288f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        break;
2289f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      case 12:
2290f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        if (memcmp(kind, "ObjCCategory", 12) == 0) {
2291f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (I + 2 >= E)
2292f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return insufficient_usr(kind, "<class name> <category name>");
2293f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          print_usr(clang_constructUSR_ObjCCategory(I[1], I[2]));
2294f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          I += 3;
2295f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          continue;
2296f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        }
2297f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        if (memcmp(kind, "ObjCProtocol", 12) == 0) {
2298f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (I + 1 >= E)
2299f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return insufficient_usr(kind, "<protocol name>");
2300f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          print_usr(clang_constructUSR_ObjCProtocol(I[1]));
2301f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          I += 2;
2302f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          continue;
2303f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        }
2304f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        if (memcmp(kind, "ObjCProperty", 12) == 0) {
2305f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (I + 2 >= E)
2306f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return insufficient_usr(kind, "<property name> <class USR>");
2307f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          if (!isUSR(I[2]))
2308f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            return not_usr("<class USR>", I[2]);
2309f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          else {
2310f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            CXString x;
2311a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek            x.data = (void*) I[2];
2312ed122735639d83c10f18c28c7fd117bfcd0f62cbTed Kremenek            x.private_flags = 0;
2313f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek            print_usr(clang_constructUSR_ObjCProperty(I[1], x));
2314f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          }
2315f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          I += 3;
2316f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek          continue;
2317f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        }
2318f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        break;
2319f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      default:
2320f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        break;
2321f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    }
2322f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    break;
2323f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  }
2324f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2325f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  if (I != E) {
2326f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    fprintf(stderr, "Invalid USR kind: %s\n", *I);
2327f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    display_usrs();
2328f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    return 1;
2329f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  }
2330f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  return 0;
2331f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2332f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2333f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenekint print_usrs_file(const char *file_name) {
2334f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  char line[2048];
2335f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  const char *args[128];
2336f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  unsigned numChars = 0;
2337f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2338f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  FILE *fp = fopen(file_name, "r");
2339f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  if (!fp) {
2340f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    fprintf(stderr, "error: cannot open '%s'\n", file_name);
2341f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    return 1;
2342f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  }
2343f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2344f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  /* This code is not really all that safe, but it works fine for testing. */
2345f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  while (!feof(fp)) {
2346f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    char c = fgetc(fp);
2347f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    if (c == '\n') {
2348f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      unsigned i = 0;
2349f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      const char *s = 0;
2350f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2351f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      if (numChars == 0)
2352f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        continue;
2353f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2354f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      line[numChars] = '\0';
2355f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      numChars = 0;
2356f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2357f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      if (line[0] == '/' && line[1] == '/')
2358f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        continue;
2359f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2360f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      s = strtok(line, " ");
2361f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      while (s) {
2362f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        args[i] = s;
2363f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        ++i;
2364f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        s = strtok(0, " ");
2365f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      }
2366f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      if (print_usrs(&args[0], &args[i]))
2367f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek        return 1;
2368f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    }
2369f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    else
2370f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      line[numChars++] = c;
2371f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  }
2372f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2373f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  fclose(fp);
2374f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  return 0;
2375f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek}
2376f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek
2377f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek/******************************************************************************/
23780d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/* Command line processing.                                                   */
23790d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek/******************************************************************************/
23807ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregorint write_pch_file(const char *filename, int argc, const char *argv[]) {
23817ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  CXIndex Idx;
23827ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  CXTranslationUnit TU;
23837ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  struct CXUnsavedFile *unsaved_files = 0;
23847ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  int num_unsaved_files = 0;
238508aa622ab923fb8a2751f213feee0b9124ee86fbFrancois Pichet  int result = 0;
23867ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
23877ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnosics=*/1);
23887ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
23897ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
23907ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    clang_disposeIndex(Idx);
23917ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    return -1;
23927ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  }
23937ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
23947ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  TU = clang_parseTranslationUnit(Idx, 0,
23957ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor                                  argv + num_unsaved_files,
23967ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor                                  argc - num_unsaved_files,
23977ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor                                  unsaved_files,
23987ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor                                  num_unsaved_files,
23997ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor                                  CXTranslationUnit_Incomplete);
24007ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  if (!TU) {
24017ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    fprintf(stderr, "Unable to load translation unit!\n");
24027ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    free_remapped_files(unsaved_files, num_unsaved_files);
24037ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    clang_disposeIndex(Idx);
24047ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    return 1;
24057ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  }
24067ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
240739c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  switch (clang_saveTranslationUnit(TU, filename,
240839c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor                                    clang_defaultSaveOptions(TU))) {
240939c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  case CXSaveError_None:
241039c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    break;
241139c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor
241239c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  case CXSaveError_TranslationErrors:
241339c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    fprintf(stderr, "Unable to write PCH file %s: translation errors\n",
241439c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor            filename);
241539c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    result = 2;
241639c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    break;
241739c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor
241839c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  case CXSaveError_InvalidTU:
241939c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    fprintf(stderr, "Unable to write PCH file %s: invalid translation unit\n",
242039c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor            filename);
242139c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    result = 3;
242239c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    break;
242339c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor
242439c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  case CXSaveError_Unknown:
242539c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  default:
242639c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    fprintf(stderr, "Unable to write PCH file %s: unknown error \n", filename);
242739c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    result = 1;
242839c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor    break;
242939c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  }
243039c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor
24317ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  clang_disposeTranslationUnit(TU);
24327ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  free_remapped_files(unsaved_files, num_unsaved_files);
24337ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  clang_disposeIndex(Idx);
243439c411fa229b2a6747b92f945d1702ee674d3470Douglas Gregor  return result;
24357ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor}
24367ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
24377ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor/******************************************************************************/
2438153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek/* Serialized diagnostics.                                                    */
2439153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek/******************************************************************************/
2440153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2441153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error) {
2442153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  switch (error) {
2443153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXLoadDiag_CannotLoad: return "Cannot Load File";
2444153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXLoadDiag_None: break;
2445153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXLoadDiag_Unknown: return "Unknown";
2446153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXLoadDiag_InvalidFile: return "Invalid File";
2447153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2448153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return "None";
2449153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2450153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2451153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic const char *getSeverityString(enum CXDiagnosticSeverity severity) {
2452153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  switch (severity) {
2453153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXDiagnostic_Note: return "note";
2454153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXDiagnostic_Error: return "error";
2455153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXDiagnostic_Fatal: return "fatal";
2456153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXDiagnostic_Ignored: return "ignored";
2457153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case CXDiagnostic_Warning: return "warning";
2458153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2459153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return "unknown";
2460153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2461153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2462153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic void printIndent(unsigned indent) {
2463a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek  if (indent == 0)
2464a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek    return;
2465a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek  fprintf(stderr, "+");
2466a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek  --indent;
2467153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (indent > 0) {
2468a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek    fprintf(stderr, "-");
2469153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    --indent;
2470153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2471153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2472153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2473153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic void printLocation(CXSourceLocation L) {
2474153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXFile File;
2475153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXString FileName;
2476153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  unsigned line, column, offset;
2477153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2478153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  clang_getExpansionLocation(L, &File, &line, &column, &offset);
2479153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileName = clang_getFileName(File);
2480153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2481153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column);
2482153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  clang_disposeString(FileName);
2483153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2484153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2485153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic void printRanges(CXDiagnostic D, unsigned indent) {
2486153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  unsigned i, n = clang_getDiagnosticNumRanges(D);
2487153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2488153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  for (i = 0; i < n; ++i) {
2489153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXSourceLocation Start, End;
2490153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXSourceRange SR = clang_getDiagnosticRange(D, i);
2491153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Start = clang_getRangeStart(SR);
2492153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    End = clang_getRangeEnd(SR);
2493153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2494153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printIndent(indent);
2495153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "Range: ");
2496153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printLocation(Start);
2497153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, " ");
2498153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printLocation(End);
2499153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "\n");
2500153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2501153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2502153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2503153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic void printFixIts(CXDiagnostic D, unsigned indent) {
2504153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  unsigned i, n = clang_getDiagnosticNumFixIts(D);
25053739b32a01b9778176757425e62252c288b85383Ted Kremenek  fprintf(stderr, "Number FIXITs = %d\n", n);
2506153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  for (i = 0 ; i < n; ++i) {
2507153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXSourceRange ReplacementRange;
2508153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXString text;
2509153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    text = clang_getDiagnosticFixIt(D, i, &ReplacementRange);
2510153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2511153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printIndent(indent);
2512153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "FIXIT: (");
2513153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printLocation(clang_getRangeStart(ReplacementRange));
2514153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, " - ");
2515153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printLocation(clang_getRangeEnd(ReplacementRange));
2516153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "): \"%s\"\n", clang_getCString(text));
2517153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    clang_disposeString(text);
2518153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2519153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2520153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2521153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) {
25229190943fef9584edd30d1861f3225c3a4d1c4f53NAKAMURA Takumi  unsigned i, n;
25239190943fef9584edd30d1861f3225c3a4d1c4f53NAKAMURA Takumi
2524153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (!Diags)
2525153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return;
2526153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
25279190943fef9584edd30d1861f3225c3a4d1c4f53NAKAMURA Takumi  n = clang_getNumDiagnosticsInSet(Diags);
2528153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  for (i = 0; i < n; ++i) {
2529153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXSourceLocation DiagLoc;
2530153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXDiagnostic D;
2531153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXFile File;
2532153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    CXString FileName, DiagSpelling, DiagOption;
2533153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned line, column, offset;
2534153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    const char *DiagOptionStr = 0;
2535153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2536153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    D = clang_getDiagnosticInSet(Diags, i);
2537153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    DiagLoc = clang_getDiagnosticLocation(D);
2538153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    clang_getExpansionLocation(DiagLoc, &File, &line, &column, &offset);
2539153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    FileName = clang_getFileName(File);
2540153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    DiagSpelling = clang_getDiagnosticSpelling(D);
2541153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2542153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printIndent(indent);
2543153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2544153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "%s:%d:%d: %s: %s",
2545153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            clang_getCString(FileName),
2546153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            line,
2547153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            column,
2548153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            getSeverityString(clang_getDiagnosticSeverity(D)),
2549153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            clang_getCString(DiagSpelling));
2550153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2551153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    DiagOption = clang_getDiagnosticOption(D, 0);
2552153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    DiagOptionStr = clang_getCString(DiagOption);
2553153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (DiagOptionStr) {
2554153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      fprintf(stderr, " [%s]", DiagOptionStr);
2555153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
2556153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2557153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "\n");
2558153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2559153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printRanges(D, indent);
2560153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printFixIts(D, indent);
2561153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2562a4ca95a6ebe85d63df08f3290372e97ddaf0b02aNAKAMURA Takumi    /* Print subdiagnostics. */
2563153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    printDiagnosticSet(clang_getChildDiagnostics(D), indent+2);
2564153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2565153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    clang_disposeString(FileName);
2566153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    clang_disposeString(DiagSpelling);
2567153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    clang_disposeString(DiagOption);
2568153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2569153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2570153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2571153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic int read_diagnostics(const char *filename) {
2572153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  enum CXLoadDiag_Error error;
2573153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXString errorString;
2574153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXDiagnosticSet Diags = 0;
2575153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2576153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Diags = clang_loadDiagnostics(filename, &error, &errorString);
2577153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (!Diags) {
2578153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    fprintf(stderr, "Trouble deserializing file (%s): %s\n",
2579153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            getDiagnosticCodeStr(error),
2580153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            clang_getCString(errorString));
2581153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    clang_disposeString(errorString);
2582153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return 1;
2583153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
2584153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2585153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  printDiagnosticSet(Diags, 0);
2586a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek  fprintf(stderr, "Number of diagnostics: %d\n",
2587a7e8a8394ccaa7a1276d32d0c16515bf4e7b486eTed Kremenek          clang_getNumDiagnosticsInSet(Diags));
2588153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  clang_disposeDiagnosticSet(Diags);
2589153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return 0;
2590153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
2591153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2592153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek/******************************************************************************/
25937ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor/* Command line processing.                                                   */
25947ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor/******************************************************************************/
2595f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek
2596e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregorstatic CXCursorVisitor GetVisitor(const char *s) {
25977d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  if (s[0] == '\0')
2598e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    return FilteredPrintingVisitor;
25997d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  if (strcmp(s, "-usrs") == 0)
26007d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    return USRVisitor;
260159fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek  if (strncmp(s, "-memory-usage", 13) == 0)
260259fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    return GetVisitor(s + 13);
26037d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  return NULL;
26047d40562f83552b7295411e10ee887d8d55470679Ted Kremenek}
26057d40562f83552b7295411e10ee887d8d55470679Ted Kremenek
2606f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenekstatic void print_usage(void) {
2607f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek  fprintf(stderr,
26080d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
26091982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    "       c-index-test -code-completion-timing=<site> <compiler arguments>\n"
2610f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    "       c-index-test -cursor-at=<site> <compiler arguments>\n"
2611aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    "       c-index-test -file-refs-at=<site> <compiler arguments>\n"
26124e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    "       c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
261321ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    "       c-index-test -index-tu [-check-prefix=<FileCheck prefix>] <AST file>\n"
26141d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek    "       c-index-test -test-file-scan <AST file> <source file> "
261526fc0f9a078b1a9120547b36804f97c626817bdfErik Verbruggen          "[FileCheck prefix]\n");
261626fc0f9a078b1a9120547b36804f97c626817bdfErik Verbruggen  fprintf(stderr,
2617fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek    "       c-index-test -test-load-tu <AST file> <symbol filter> "
2618fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek          "[FileCheck prefix]\n"
26197d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    "       c-index-test -test-load-tu-usrs <AST file> <symbol filter> "
26207d40562f83552b7295411e10ee887d8d55470679Ted Kremenek           "[FileCheck prefix]\n"
26211982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    "       c-index-test -test-load-source <symbol filter> {<args>}*\n");
2622f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  fprintf(stderr,
262359fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    "       c-index-test -test-load-source-memory-usage "
262459fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    "<symbol filter> {<args>}*\n"
2625abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    "       c-index-test -test-load-source-reparse <trials> <symbol filter> "
2626abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    "          {<args>}*\n"
26271982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    "       c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
262859fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    "       c-index-test -test-load-source-usrs-memory-usage "
262959fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek          "<symbol filter> {<args>}*\n"
263016b55a71695a33c094383295cc7b7a2080e098daTed Kremenek    "       c-index-test -test-annotate-tokens=<range> {<args>}*\n"
263116b55a71695a33c094383295cc7b7a2080e098daTed Kremenek    "       c-index-test -test-inclusion-stack-source {<args>}*\n"
26324e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek    "       c-index-test -test-inclusion-stack-tu <AST file>\n");
263353513d2e24205965ffd5d4780a10f41cc335f17bChandler Carruth  fprintf(stderr,
26344e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek    "       c-index-test -test-print-linkage-source {<args>}*\n"
263559fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    "       c-index-test -test-print-typekind {<args>}*\n"
263659fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    "       c-index-test -print-usr [<CursorKind> {<args>}]*\n"
26377ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    "       c-index-test -print-usr-file <file>\n"
2638153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    "       c-index-test -write-pch <file> <compiler arguments>\n");
2639153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  fprintf(stderr,
2640153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    "       c-index-test -read-diagnostics <file>\n\n");
2641caf4bd3d3c66fd95b0159356e2c4da7fbf2897f3Douglas Gregor  fprintf(stderr,
26427d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    " <symbol filter> values:\n%s",
26430d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "   all - load all symbols, including those from PCH\n"
26440d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "   local - load all symbols except those in PCH\n"
26450d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "   category - only load ObjC categories (non-PCH)\n"
26460d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "   interface - only load ObjC interfaces (non-PCH)\n"
26470d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "   protocol - only load ObjC protocols (non-PCH)\n"
26480d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    "   function - only load functions (non-PCH)\n"
2649625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar    "   typedef - only load typdefs (non-PCH)\n"
2650625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar    "   scan-function - scan function bodies (non-PCH)\n\n");
2651f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek}
2652f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek
26536edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar/***/
26546edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar
26556edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbarint cindextest_main(int argc, const char **argv) {
26560a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor  clang_enableStackTraces();
2657153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (argc > 2 && strcmp(argv[1], "-read-diagnostics") == 0)
2658153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      return read_diagnostics(argv[2]);
2659f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek  if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
26601982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    return perform_code_completion(argc, argv, 0);
26611982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor  if (argc > 2 && strstr(argv[1], "-code-completion-timing=") == argv[1])
26621982c18522a4aefd57207bbd2d66d93945c41f92Douglas Gregor    return perform_code_completion(argc, argv, 1);
2663f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor  if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
2664f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor    return inspect_cursor_at(argc, argv);
2665aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1])
2666aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return find_file_refs_at(argc, argv);
26674e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (argc > 2 && strcmp(argv[1], "-index-file") == 0)
26684e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return index_file(argc - 2, argv + 2);
266921ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis  if (argc > 2 && strcmp(argv[1], "-index-tu") == 0)
267021ee5707e6e59d982d2f2ae28e079c7ff46dc519Argyrios Kyrtzidis    return index_tu(argc - 2, argv + 2);
26717d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
2672e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    CXCursorVisitor I = GetVisitor(argv[1] + 13);
26737d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    if (I)
2674ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek      return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I,
2675ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek                                  NULL);
26767d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  }
2677abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  else if (argc >= 5 && strncmp(argv[1], "-test-load-source-reparse", 25) == 0){
2678abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    CXCursorVisitor I = GetVisitor(argv[1] + 25);
2679abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    if (I) {
2680abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      int trials = atoi(argv[2]);
2681abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor      return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I,
2682abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor                                         NULL);
2683abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor    }
2684abc563f554951259bbe0315055cad92ee14d87e4Douglas Gregor  }
26857d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
2686e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    CXCursorVisitor I = GetVisitor(argv[1] + 17);
268759fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek
268859fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    PostVisitTU postVisit = 0;
268959fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    if (strstr(argv[1], "-memory-usage"))
269059fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek      postVisit = PrintMemoryUsage;
269159fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek
26927d40562f83552b7295411e10ee887d8d55470679Ted Kremenek    if (I)
269359fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek      return perform_test_load_source(argc - 3, argv + 3, argv[2], I,
269459fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek                                      postVisit);
26957d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  }
26967d40562f83552b7295411e10ee887d8d55470679Ted Kremenek  else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
26971d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek    return perform_file_scan(argv[2], argv[3],
26981d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2Ted Kremenek                             argc >= 5 ? argv[4] : 0);
2699fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor  else if (argc > 2 && strstr(argv[1], "-test-annotate-tokens=") == argv[1])
2700fc8ea23eb6cbaaa5046f2abb4c033e24c8659efdDouglas Gregor    return perform_token_annotation(argc, argv);
270116b55a71695a33c094383295cc7b7a2080e098daTed Kremenek  else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-source") == 0)
270216b55a71695a33c094383295cc7b7a2080e098daTed Kremenek    return perform_test_load_source(argc - 2, argv + 2, "all", NULL,
270316b55a71695a33c094383295cc7b7a2080e098daTed Kremenek                                    PrintInclusionStack);
270416b55a71695a33c094383295cc7b7a2080e098daTed Kremenek  else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-tu") == 0)
270516b55a71695a33c094383295cc7b7a2080e098daTed Kremenek    return perform_test_load_tu(argv[2], "all", NULL, NULL,
270616b55a71695a33c094383295cc7b7a2080e098daTed Kremenek                                PrintInclusionStack);
27073bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek  else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0)
27083bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek    return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage,
27093bed527b10502c6a5916ebb6e6abc49687ce1444Ted Kremenek                                    NULL);
27108e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek  else if (argc > 2 && strcmp(argv[1], "-test-print-typekind") == 0)
27118e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek    return perform_test_load_source(argc - 2, argv + 2, "all",
27128e0ac174c8c8c980927b3e1447f16f62fbe2a2e4Ted Kremenek                                    PrintTypeKind, 0);
2713f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  else if (argc > 1 && strcmp(argv[1], "-print-usr") == 0) {
2714f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    if (argc > 2)
2715f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      return print_usrs(argv + 2, argv + argc);
2716f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    else {
2717f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      display_usrs();
2718f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      return 1;
2719f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    }
2720f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  }
2721f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek  else if (argc > 2 && strcmp(argv[1], "-print-usr-file") == 0)
2722f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    return print_usrs_file(argv[2]);
27237ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor  else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0)
27247ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor    return write_pch_file(argv[2], argc - 3, argv + 3);
27257ae2faafd30524ef5f863bb3b8701977888839bbDouglas Gregor
2726f5d9c9340b1a5ecd6ab62b916600b6e19e69539fTed Kremenek  print_usage();
272750398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff  return 1;
272850398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff}
27296edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar
27306edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar/***/
27316edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar
27326edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar/* We intentionally run in a separate thread to ensure we at least minimal
27336edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar * testing of a multithreaded environment (for example, having a reduced stack
27346edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar * size). */
27356edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar
27366edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbartypedef struct thread_info {
27376edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  int argc;
27386edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  const char **argv;
27396edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  int result;
27406edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar} thread_info;
274184294911b83003bcac726d00ffa91143752feb57Benjamin Kramervoid thread_runner(void *client_data_v) {
27426edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  thread_info *client_data = client_data_v;
27436edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  client_data->result = cindextest_main(client_data->argc, client_data->argv);
27446edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar}
27456edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar
27466edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbarint main(int argc, const char **argv) {
27476edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  thread_info client_data;
27486edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar
27496160598bcd6549757525cbb463a551a0ad1615e4Douglas Gregor  if (getenv("CINDEXTEST_NOTHREADS"))
27506160598bcd6549757525cbb463a551a0ad1615e4Douglas Gregor    return cindextest_main(argc, argv);
27516160598bcd6549757525cbb463a551a0ad1615e4Douglas Gregor
27526edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  client_data.argc = argc;
27536edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  client_data.argv = argv;
2754a32a6e1abe6972b48b4d5ec79d81b6f7241723bfDaniel Dunbar  clang_executeOnThread(thread_runner, &client_data, 0);
27556edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar  return client_data.result;
27566edc8001f2c2f5a95ed29259d8f2c0b9faa4bc83Daniel Dunbar}
2757