17330f729Sjoerg /* c-index-test.c */
27330f729Sjoerg
37330f729Sjoerg #include "clang/Config/config.h"
47330f729Sjoerg #include "clang-c/Index.h"
57330f729Sjoerg #include "clang-c/CXCompilationDatabase.h"
67330f729Sjoerg #include "clang-c/BuildSystem.h"
77330f729Sjoerg #include "clang-c/Documentation.h"
87330f729Sjoerg #include <ctype.h>
97330f729Sjoerg #include <stdlib.h>
107330f729Sjoerg #include <stdio.h>
117330f729Sjoerg #include <string.h>
127330f729Sjoerg #include <assert.h>
137330f729Sjoerg
147330f729Sjoerg #ifdef CLANG_HAVE_LIBXML
157330f729Sjoerg #include <libxml/parser.h>
167330f729Sjoerg #include <libxml/relaxng.h>
177330f729Sjoerg #include <libxml/xmlerror.h>
187330f729Sjoerg #endif
197330f729Sjoerg
207330f729Sjoerg #ifdef _WIN32
217330f729Sjoerg # include <direct.h>
227330f729Sjoerg #else
237330f729Sjoerg # include <unistd.h>
247330f729Sjoerg #endif
257330f729Sjoerg
267330f729Sjoerg extern int indextest_core_main(int argc, const char **argv);
27*e038c9c4Sjoerg extern int indextest_perform_shell_execution(const char *command_line);
287330f729Sjoerg
297330f729Sjoerg /******************************************************************************/
307330f729Sjoerg /* Utility functions. */
317330f729Sjoerg /******************************************************************************/
327330f729Sjoerg
337330f729Sjoerg #ifdef _MSC_VER
basename(const char * path)347330f729Sjoerg char *basename(const char* path)
357330f729Sjoerg {
367330f729Sjoerg char* base1 = (char*)strrchr(path, '/');
377330f729Sjoerg char* base2 = (char*)strrchr(path, '\\');
387330f729Sjoerg if (base1 && base2)
397330f729Sjoerg return((base1 > base2) ? base1 + 1 : base2 + 1);
407330f729Sjoerg else if (base1)
417330f729Sjoerg return(base1 + 1);
427330f729Sjoerg else if (base2)
437330f729Sjoerg return(base2 + 1);
447330f729Sjoerg
457330f729Sjoerg return((char*)path);
467330f729Sjoerg }
dirname(char * path)477330f729Sjoerg char *dirname(char* path)
487330f729Sjoerg {
497330f729Sjoerg char* base1 = (char*)strrchr(path, '/');
507330f729Sjoerg char* base2 = (char*)strrchr(path, '\\');
517330f729Sjoerg if (base1 && base2)
527330f729Sjoerg if (base1 > base2)
537330f729Sjoerg *base1 = 0;
547330f729Sjoerg else
557330f729Sjoerg *base2 = 0;
567330f729Sjoerg else if (base1)
577330f729Sjoerg *base1 = 0;
587330f729Sjoerg else if (base2)
597330f729Sjoerg *base2 = 0;
607330f729Sjoerg
617330f729Sjoerg return path;
627330f729Sjoerg }
637330f729Sjoerg #else
647330f729Sjoerg extern char *basename(const char *);
657330f729Sjoerg extern char *dirname(char *);
667330f729Sjoerg #endif
677330f729Sjoerg
687330f729Sjoerg /** Return the default parsing options. */
getDefaultParsingOptions()697330f729Sjoerg static unsigned getDefaultParsingOptions() {
707330f729Sjoerg unsigned options = CXTranslationUnit_DetailedPreprocessingRecord;
717330f729Sjoerg
727330f729Sjoerg if (getenv("CINDEXTEST_EDITING"))
737330f729Sjoerg options |= clang_defaultEditingTranslationUnitOptions();
747330f729Sjoerg if (getenv("CINDEXTEST_COMPLETION_CACHING"))
757330f729Sjoerg options |= CXTranslationUnit_CacheCompletionResults;
767330f729Sjoerg if (getenv("CINDEXTEST_COMPLETION_NO_CACHING"))
777330f729Sjoerg options &= ~CXTranslationUnit_CacheCompletionResults;
787330f729Sjoerg if (getenv("CINDEXTEST_SKIP_FUNCTION_BODIES"))
797330f729Sjoerg options |= CXTranslationUnit_SkipFunctionBodies;
807330f729Sjoerg if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
817330f729Sjoerg options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
827330f729Sjoerg if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE"))
837330f729Sjoerg options |= CXTranslationUnit_CreatePreambleOnFirstParse;
847330f729Sjoerg if (getenv("CINDEXTEST_KEEP_GOING"))
857330f729Sjoerg options |= CXTranslationUnit_KeepGoing;
867330f729Sjoerg if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE"))
877330f729Sjoerg options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble;
887330f729Sjoerg if (getenv("CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES"))
897330f729Sjoerg options |= CXTranslationUnit_IncludeAttributedTypes;
907330f729Sjoerg if (getenv("CINDEXTEST_VISIT_IMPLICIT_ATTRIBUTES"))
917330f729Sjoerg options |= CXTranslationUnit_VisitImplicitAttributes;
927330f729Sjoerg if (getenv("CINDEXTEST_IGNORE_NONERRORS_FROM_INCLUDED_FILES"))
937330f729Sjoerg options |= CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles;
947330f729Sjoerg
957330f729Sjoerg return options;
967330f729Sjoerg }
977330f729Sjoerg
ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy)987330f729Sjoerg static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) {
997330f729Sjoerg struct Mapping {
1007330f729Sjoerg const char *name;
1017330f729Sjoerg enum CXPrintingPolicyProperty property;
1027330f729Sjoerg };
1037330f729Sjoerg struct Mapping mappings[] = {
1047330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation},
1057330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS",
1067330f729Sjoerg CXPrintingPolicy_SuppressSpecifiers},
1077330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD",
1087330f729Sjoerg CXPrintingPolicy_SuppressTagKeyword},
1097330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION",
1107330f729Sjoerg CXPrintingPolicy_IncludeTagDefinition},
1117330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE",
1127330f729Sjoerg CXPrintingPolicy_SuppressScope},
1137330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE",
1147330f729Sjoerg CXPrintingPolicy_SuppressUnwrittenScope},
1157330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS",
1167330f729Sjoerg CXPrintingPolicy_SuppressInitializers},
1177330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN",
1187330f729Sjoerg CXPrintingPolicy_ConstantArraySizeAsWritten},
1197330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS",
1207330f729Sjoerg CXPrintingPolicy_AnonymousTagLocations},
1217330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME",
1227330f729Sjoerg CXPrintingPolicy_SuppressStrongLifetime},
1237330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS",
1247330f729Sjoerg CXPrintingPolicy_SuppressLifetimeQualifiers},
1257330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS",
1267330f729Sjoerg CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors},
1277330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool},
1287330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict},
1297330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof},
1307330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF",
1317330f729Sjoerg CXPrintingPolicy_UnderscoreAlignof},
1327330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS",
1337330f729Sjoerg CXPrintingPolicy_UseVoidForZeroParams},
1347330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput},
1357330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION",
1367330f729Sjoerg CXPrintingPolicy_PolishForDeclaration},
1377330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half},
1387330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar},
1397330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES",
1407330f729Sjoerg CXPrintingPolicy_IncludeNewlines},
1417330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING",
1427330f729Sjoerg CXPrintingPolicy_MSVCFormatting},
1437330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN",
1447330f729Sjoerg CXPrintingPolicy_ConstantsAsWritten},
1457330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE",
1467330f729Sjoerg CXPrintingPolicy_SuppressImplicitBase},
1477330f729Sjoerg {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME",
1487330f729Sjoerg CXPrintingPolicy_FullyQualifiedName},
1497330f729Sjoerg };
1507330f729Sjoerg
1517330f729Sjoerg unsigned i;
1527330f729Sjoerg for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) {
1537330f729Sjoerg char *value = getenv(mappings[i].name);
1547330f729Sjoerg if (value) {
1557330f729Sjoerg clang_PrintingPolicy_setProperty(Policy, mappings[i].property,
1567330f729Sjoerg (unsigned)strtoul(value, 0L, 10));
1577330f729Sjoerg }
1587330f729Sjoerg }
1597330f729Sjoerg }
1607330f729Sjoerg
1617330f729Sjoerg /** Returns 0 in case of success, non-zero in case of a failure. */
1627330f729Sjoerg static int checkForErrors(CXTranslationUnit TU);
1637330f729Sjoerg
describeLibclangFailure(enum CXErrorCode Err)1647330f729Sjoerg static void describeLibclangFailure(enum CXErrorCode Err) {
1657330f729Sjoerg switch (Err) {
1667330f729Sjoerg case CXError_Success:
1677330f729Sjoerg fprintf(stderr, "Success\n");
1687330f729Sjoerg return;
1697330f729Sjoerg
1707330f729Sjoerg case CXError_Failure:
1717330f729Sjoerg fprintf(stderr, "Failure (no details available)\n");
1727330f729Sjoerg return;
1737330f729Sjoerg
1747330f729Sjoerg case CXError_Crashed:
1757330f729Sjoerg fprintf(stderr, "Failure: libclang crashed\n");
1767330f729Sjoerg return;
1777330f729Sjoerg
1787330f729Sjoerg case CXError_InvalidArguments:
1797330f729Sjoerg fprintf(stderr, "Failure: invalid arguments passed to a libclang routine\n");
1807330f729Sjoerg return;
1817330f729Sjoerg
1827330f729Sjoerg case CXError_ASTReadError:
1837330f729Sjoerg fprintf(stderr, "Failure: AST deserialization error occurred\n");
1847330f729Sjoerg return;
1857330f729Sjoerg }
1867330f729Sjoerg }
1877330f729Sjoerg
PrintExtent(FILE * out,unsigned begin_line,unsigned begin_column,unsigned end_line,unsigned end_column)1887330f729Sjoerg static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,
1897330f729Sjoerg unsigned end_line, unsigned end_column) {
1907330f729Sjoerg fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,
1917330f729Sjoerg end_line, end_column);
1927330f729Sjoerg }
1937330f729Sjoerg
CreateTranslationUnit(CXIndex Idx,const char * file,CXTranslationUnit * TU)1947330f729Sjoerg static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
1957330f729Sjoerg CXTranslationUnit *TU) {
1967330f729Sjoerg enum CXErrorCode Err = clang_createTranslationUnit2(Idx, file, TU);
1977330f729Sjoerg if (Err != CXError_Success) {
1987330f729Sjoerg fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
1997330f729Sjoerg describeLibclangFailure(Err);
2007330f729Sjoerg *TU = 0;
2017330f729Sjoerg return 0;
2027330f729Sjoerg }
2037330f729Sjoerg return 1;
2047330f729Sjoerg }
2057330f729Sjoerg
free_remapped_files(struct CXUnsavedFile * unsaved_files,int num_unsaved_files)2067330f729Sjoerg void free_remapped_files(struct CXUnsavedFile *unsaved_files,
2077330f729Sjoerg int num_unsaved_files) {
2087330f729Sjoerg int i;
2097330f729Sjoerg for (i = 0; i != num_unsaved_files; ++i) {
2107330f729Sjoerg free((char *)unsaved_files[i].Filename);
2117330f729Sjoerg free((char *)unsaved_files[i].Contents);
2127330f729Sjoerg }
2137330f729Sjoerg free(unsaved_files);
2147330f729Sjoerg }
2157330f729Sjoerg
parse_remapped_files_with_opt(const char * opt_name,int argc,const char ** argv,int start_arg,struct CXUnsavedFile ** unsaved_files,int * num_unsaved_files)2167330f729Sjoerg static int parse_remapped_files_with_opt(const char *opt_name,
2177330f729Sjoerg int argc, const char **argv,
2187330f729Sjoerg int start_arg,
2197330f729Sjoerg struct CXUnsavedFile **unsaved_files,
2207330f729Sjoerg int *num_unsaved_files) {
2217330f729Sjoerg int i;
2227330f729Sjoerg int arg;
2237330f729Sjoerg int prefix_len = strlen(opt_name);
2247330f729Sjoerg int arg_indices[20];
2257330f729Sjoerg *unsaved_files = 0;
2267330f729Sjoerg *num_unsaved_files = 0;
2277330f729Sjoerg
2287330f729Sjoerg /* Count the number of remapped files. */
2297330f729Sjoerg for (arg = start_arg; arg < argc; ++arg) {
2307330f729Sjoerg if (strncmp(argv[arg], opt_name, prefix_len))
2317330f729Sjoerg continue;
2327330f729Sjoerg
2337330f729Sjoerg assert(*num_unsaved_files < (int)(sizeof(arg_indices)/sizeof(int)));
2347330f729Sjoerg arg_indices[*num_unsaved_files] = arg;
2357330f729Sjoerg ++*num_unsaved_files;
2367330f729Sjoerg }
2377330f729Sjoerg
2387330f729Sjoerg if (*num_unsaved_files == 0)
2397330f729Sjoerg return 0;
2407330f729Sjoerg
2417330f729Sjoerg *unsaved_files
2427330f729Sjoerg = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
2437330f729Sjoerg *num_unsaved_files);
2447330f729Sjoerg assert(*unsaved_files);
2457330f729Sjoerg for (i = 0; i != *num_unsaved_files; ++i) {
2467330f729Sjoerg struct CXUnsavedFile *unsaved = *unsaved_files + i;
2477330f729Sjoerg const char *arg_string = argv[arg_indices[i]] + prefix_len;
2487330f729Sjoerg int filename_len;
2497330f729Sjoerg char *filename;
2507330f729Sjoerg char *contents;
2517330f729Sjoerg FILE *to_file;
2527330f729Sjoerg const char *sep = strchr(arg_string, ',');
2537330f729Sjoerg if (!sep) {
2547330f729Sjoerg fprintf(stderr,
2557330f729Sjoerg "error: %sfrom:to argument is missing comma\n", opt_name);
2567330f729Sjoerg free_remapped_files(*unsaved_files, i);
2577330f729Sjoerg *unsaved_files = 0;
2587330f729Sjoerg *num_unsaved_files = 0;
2597330f729Sjoerg return -1;
2607330f729Sjoerg }
2617330f729Sjoerg
2627330f729Sjoerg /* Open the file that we're remapping to. */
2637330f729Sjoerg to_file = fopen(sep + 1, "rb");
2647330f729Sjoerg if (!to_file) {
2657330f729Sjoerg fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
2667330f729Sjoerg sep + 1);
2677330f729Sjoerg free_remapped_files(*unsaved_files, i);
2687330f729Sjoerg *unsaved_files = 0;
2697330f729Sjoerg *num_unsaved_files = 0;
2707330f729Sjoerg return -1;
2717330f729Sjoerg }
2727330f729Sjoerg
2737330f729Sjoerg /* Determine the length of the file we're remapping to. */
2747330f729Sjoerg fseek(to_file, 0, SEEK_END);
2757330f729Sjoerg unsaved->Length = ftell(to_file);
2767330f729Sjoerg fseek(to_file, 0, SEEK_SET);
2777330f729Sjoerg
2787330f729Sjoerg /* Read the contents of the file we're remapping to. */
2797330f729Sjoerg contents = (char *)malloc(unsaved->Length + 1);
2807330f729Sjoerg assert(contents);
2817330f729Sjoerg if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
2827330f729Sjoerg fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
2837330f729Sjoerg (feof(to_file) ? "EOF" : "error"), sep + 1);
2847330f729Sjoerg fclose(to_file);
2857330f729Sjoerg free_remapped_files(*unsaved_files, i);
2867330f729Sjoerg free(contents);
2877330f729Sjoerg *unsaved_files = 0;
2887330f729Sjoerg *num_unsaved_files = 0;
2897330f729Sjoerg return -1;
2907330f729Sjoerg }
2917330f729Sjoerg contents[unsaved->Length] = 0;
2927330f729Sjoerg unsaved->Contents = contents;
2937330f729Sjoerg
2947330f729Sjoerg /* Close the file. */
2957330f729Sjoerg fclose(to_file);
2967330f729Sjoerg
2977330f729Sjoerg /* Copy the file name that we're remapping from. */
2987330f729Sjoerg filename_len = sep - arg_string;
2997330f729Sjoerg filename = (char *)malloc(filename_len + 1);
3007330f729Sjoerg assert(filename);
3017330f729Sjoerg memcpy(filename, arg_string, filename_len);
3027330f729Sjoerg filename[filename_len] = 0;
3037330f729Sjoerg unsaved->Filename = filename;
3047330f729Sjoerg }
3057330f729Sjoerg
3067330f729Sjoerg return 0;
3077330f729Sjoerg }
3087330f729Sjoerg
parse_remapped_files(int argc,const char ** argv,int start_arg,struct CXUnsavedFile ** unsaved_files,int * num_unsaved_files)3097330f729Sjoerg static int parse_remapped_files(int argc, const char **argv, int start_arg,
3107330f729Sjoerg struct CXUnsavedFile **unsaved_files,
3117330f729Sjoerg int *num_unsaved_files) {
3127330f729Sjoerg return parse_remapped_files_with_opt("-remap-file=", argc, argv, start_arg,
3137330f729Sjoerg unsaved_files, num_unsaved_files);
3147330f729Sjoerg }
3157330f729Sjoerg
parse_remapped_files_with_try(int try_idx,int argc,const char ** argv,int start_arg,struct CXUnsavedFile ** unsaved_files,int * num_unsaved_files)3167330f729Sjoerg static int parse_remapped_files_with_try(int try_idx,
3177330f729Sjoerg int argc, const char **argv,
3187330f729Sjoerg int start_arg,
3197330f729Sjoerg struct CXUnsavedFile **unsaved_files,
3207330f729Sjoerg int *num_unsaved_files) {
3217330f729Sjoerg struct CXUnsavedFile *unsaved_files_no_try_idx;
3227330f729Sjoerg int num_unsaved_files_no_try_idx;
3237330f729Sjoerg struct CXUnsavedFile *unsaved_files_try_idx;
3247330f729Sjoerg int num_unsaved_files_try_idx;
3257330f729Sjoerg int ret;
3267330f729Sjoerg char opt_name[32];
3277330f729Sjoerg
3287330f729Sjoerg ret = parse_remapped_files(argc, argv, start_arg,
3297330f729Sjoerg &unsaved_files_no_try_idx, &num_unsaved_files_no_try_idx);
3307330f729Sjoerg if (ret)
3317330f729Sjoerg return ret;
3327330f729Sjoerg
3337330f729Sjoerg sprintf(opt_name, "-remap-file-%d=", try_idx);
3347330f729Sjoerg ret = parse_remapped_files_with_opt(opt_name, argc, argv, start_arg,
3357330f729Sjoerg &unsaved_files_try_idx, &num_unsaved_files_try_idx);
3367330f729Sjoerg if (ret)
3377330f729Sjoerg return ret;
3387330f729Sjoerg
3397330f729Sjoerg if (num_unsaved_files_no_try_idx == 0) {
3407330f729Sjoerg *unsaved_files = unsaved_files_try_idx;
3417330f729Sjoerg *num_unsaved_files = num_unsaved_files_try_idx;
3427330f729Sjoerg return 0;
3437330f729Sjoerg }
3447330f729Sjoerg if (num_unsaved_files_try_idx == 0) {
3457330f729Sjoerg *unsaved_files = unsaved_files_no_try_idx;
3467330f729Sjoerg *num_unsaved_files = num_unsaved_files_no_try_idx;
3477330f729Sjoerg return 0;
3487330f729Sjoerg }
3497330f729Sjoerg
3507330f729Sjoerg *num_unsaved_files = num_unsaved_files_no_try_idx + num_unsaved_files_try_idx;
3517330f729Sjoerg *unsaved_files
3527330f729Sjoerg = (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx,
3537330f729Sjoerg sizeof(struct CXUnsavedFile) *
3547330f729Sjoerg *num_unsaved_files);
3557330f729Sjoerg assert(*unsaved_files);
3567330f729Sjoerg memcpy(*unsaved_files + num_unsaved_files_no_try_idx,
3577330f729Sjoerg unsaved_files_try_idx, sizeof(struct CXUnsavedFile) *
3587330f729Sjoerg num_unsaved_files_try_idx);
3597330f729Sjoerg free(unsaved_files_try_idx);
3607330f729Sjoerg return 0;
3617330f729Sjoerg }
3627330f729Sjoerg
parse_comments_schema(int argc,const char ** argv)3637330f729Sjoerg static const char *parse_comments_schema(int argc, const char **argv) {
3647330f729Sjoerg const char *CommentsSchemaArg = "-comments-xml-schema=";
3657330f729Sjoerg const char *CommentSchemaFile = NULL;
3667330f729Sjoerg
3677330f729Sjoerg if (argc == 0)
3687330f729Sjoerg return CommentSchemaFile;
3697330f729Sjoerg
3707330f729Sjoerg if (!strncmp(argv[0], CommentsSchemaArg, strlen(CommentsSchemaArg)))
3717330f729Sjoerg CommentSchemaFile = argv[0] + strlen(CommentsSchemaArg);
3727330f729Sjoerg
3737330f729Sjoerg return CommentSchemaFile;
3747330f729Sjoerg }
3757330f729Sjoerg
3767330f729Sjoerg /******************************************************************************/
3777330f729Sjoerg /* Pretty-printing. */
3787330f729Sjoerg /******************************************************************************/
3797330f729Sjoerg
3807330f729Sjoerg static const char *FileCheckPrefix = "CHECK";
3817330f729Sjoerg
PrintCString(const char * CStr)3827330f729Sjoerg static void PrintCString(const char *CStr) {
3837330f729Sjoerg if (CStr != NULL && CStr[0] != '\0') {
3847330f729Sjoerg for ( ; *CStr; ++CStr) {
3857330f729Sjoerg const char C = *CStr;
3867330f729Sjoerg switch (C) {
3877330f729Sjoerg case '\n': printf("\\n"); break;
3887330f729Sjoerg case '\r': printf("\\r"); break;
3897330f729Sjoerg case '\t': printf("\\t"); break;
3907330f729Sjoerg case '\v': printf("\\v"); break;
3917330f729Sjoerg case '\f': printf("\\f"); break;
3927330f729Sjoerg default: putchar(C); break;
3937330f729Sjoerg }
3947330f729Sjoerg }
3957330f729Sjoerg }
3967330f729Sjoerg }
3977330f729Sjoerg
PrintCStringWithPrefix(const char * Prefix,const char * CStr)3987330f729Sjoerg static void PrintCStringWithPrefix(const char *Prefix, const char *CStr) {
3997330f729Sjoerg printf(" %s=[", Prefix);
4007330f729Sjoerg PrintCString(CStr);
4017330f729Sjoerg printf("]");
4027330f729Sjoerg }
4037330f729Sjoerg
PrintCXStringAndDispose(CXString Str)4047330f729Sjoerg static void PrintCXStringAndDispose(CXString Str) {
4057330f729Sjoerg PrintCString(clang_getCString(Str));
4067330f729Sjoerg clang_disposeString(Str);
4077330f729Sjoerg }
4087330f729Sjoerg
PrintCXStringWithPrefix(const char * Prefix,CXString Str)4097330f729Sjoerg static void PrintCXStringWithPrefix(const char *Prefix, CXString Str) {
4107330f729Sjoerg PrintCStringWithPrefix(Prefix, clang_getCString(Str));
4117330f729Sjoerg }
4127330f729Sjoerg
PrintCXStringWithPrefixAndDispose(const char * Prefix,CXString Str)4137330f729Sjoerg static void PrintCXStringWithPrefixAndDispose(const char *Prefix,
4147330f729Sjoerg CXString Str) {
4157330f729Sjoerg PrintCStringWithPrefix(Prefix, clang_getCString(Str));
4167330f729Sjoerg clang_disposeString(Str);
4177330f729Sjoerg }
4187330f729Sjoerg
PrintRange(CXSourceRange R,const char * str)4197330f729Sjoerg static void PrintRange(CXSourceRange R, const char *str) {
4207330f729Sjoerg CXFile begin_file, end_file;
4217330f729Sjoerg unsigned begin_line, begin_column, end_line, end_column;
4227330f729Sjoerg
4237330f729Sjoerg clang_getSpellingLocation(clang_getRangeStart(R),
4247330f729Sjoerg &begin_file, &begin_line, &begin_column, 0);
4257330f729Sjoerg clang_getSpellingLocation(clang_getRangeEnd(R),
4267330f729Sjoerg &end_file, &end_line, &end_column, 0);
4277330f729Sjoerg if (!begin_file || !end_file)
4287330f729Sjoerg return;
4297330f729Sjoerg
4307330f729Sjoerg if (str)
4317330f729Sjoerg printf(" %s=", str);
4327330f729Sjoerg PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
4337330f729Sjoerg }
4347330f729Sjoerg
4357330f729Sjoerg static enum DisplayType {
4367330f729Sjoerg DisplayType_Spelling,
4377330f729Sjoerg DisplayType_DisplayName,
4387330f729Sjoerg DisplayType_Pretty
4397330f729Sjoerg } wanted_display_type = DisplayType_Spelling;
4407330f729Sjoerg
printVersion(const char * Prefix,CXVersion Version)4417330f729Sjoerg static void printVersion(const char *Prefix, CXVersion Version) {
4427330f729Sjoerg if (Version.Major < 0)
4437330f729Sjoerg return;
4447330f729Sjoerg printf("%s%d", Prefix, Version.Major);
4457330f729Sjoerg
4467330f729Sjoerg if (Version.Minor < 0)
4477330f729Sjoerg return;
4487330f729Sjoerg printf(".%d", Version.Minor);
4497330f729Sjoerg
4507330f729Sjoerg if (Version.Subminor < 0)
4517330f729Sjoerg return;
4527330f729Sjoerg printf(".%d", Version.Subminor);
4537330f729Sjoerg }
4547330f729Sjoerg
4557330f729Sjoerg struct CommentASTDumpingContext {
4567330f729Sjoerg int IndentLevel;
4577330f729Sjoerg };
4587330f729Sjoerg
DumpCXCommentInternal(struct CommentASTDumpingContext * Ctx,CXComment Comment)4597330f729Sjoerg static void DumpCXCommentInternal(struct CommentASTDumpingContext *Ctx,
4607330f729Sjoerg CXComment Comment) {
4617330f729Sjoerg unsigned i;
4627330f729Sjoerg unsigned e;
4637330f729Sjoerg enum CXCommentKind Kind = clang_Comment_getKind(Comment);
4647330f729Sjoerg
4657330f729Sjoerg Ctx->IndentLevel++;
4667330f729Sjoerg for (i = 0, e = Ctx->IndentLevel; i != e; ++i)
4677330f729Sjoerg printf(" ");
4687330f729Sjoerg
4697330f729Sjoerg printf("(");
4707330f729Sjoerg switch (Kind) {
4717330f729Sjoerg case CXComment_Null:
4727330f729Sjoerg printf("CXComment_Null");
4737330f729Sjoerg break;
4747330f729Sjoerg case CXComment_Text:
4757330f729Sjoerg printf("CXComment_Text");
4767330f729Sjoerg PrintCXStringWithPrefixAndDispose("Text",
4777330f729Sjoerg clang_TextComment_getText(Comment));
4787330f729Sjoerg if (clang_Comment_isWhitespace(Comment))
4797330f729Sjoerg printf(" IsWhitespace");
4807330f729Sjoerg if (clang_InlineContentComment_hasTrailingNewline(Comment))
4817330f729Sjoerg printf(" HasTrailingNewline");
4827330f729Sjoerg break;
4837330f729Sjoerg case CXComment_InlineCommand:
4847330f729Sjoerg printf("CXComment_InlineCommand");
4857330f729Sjoerg PrintCXStringWithPrefixAndDispose(
4867330f729Sjoerg "CommandName",
4877330f729Sjoerg clang_InlineCommandComment_getCommandName(Comment));
4887330f729Sjoerg switch (clang_InlineCommandComment_getRenderKind(Comment)) {
4897330f729Sjoerg case CXCommentInlineCommandRenderKind_Normal:
4907330f729Sjoerg printf(" RenderNormal");
4917330f729Sjoerg break;
4927330f729Sjoerg case CXCommentInlineCommandRenderKind_Bold:
4937330f729Sjoerg printf(" RenderBold");
4947330f729Sjoerg break;
4957330f729Sjoerg case CXCommentInlineCommandRenderKind_Monospaced:
4967330f729Sjoerg printf(" RenderMonospaced");
4977330f729Sjoerg break;
4987330f729Sjoerg case CXCommentInlineCommandRenderKind_Emphasized:
4997330f729Sjoerg printf(" RenderEmphasized");
5007330f729Sjoerg break;
501*e038c9c4Sjoerg case CXCommentInlineCommandRenderKind_Anchor:
502*e038c9c4Sjoerg printf(" RenderAnchor");
503*e038c9c4Sjoerg break;
5047330f729Sjoerg }
5057330f729Sjoerg for (i = 0, e = clang_InlineCommandComment_getNumArgs(Comment);
5067330f729Sjoerg i != e; ++i) {
5077330f729Sjoerg printf(" Arg[%u]=", i);
5087330f729Sjoerg PrintCXStringAndDispose(
5097330f729Sjoerg clang_InlineCommandComment_getArgText(Comment, i));
5107330f729Sjoerg }
5117330f729Sjoerg if (clang_InlineContentComment_hasTrailingNewline(Comment))
5127330f729Sjoerg printf(" HasTrailingNewline");
5137330f729Sjoerg break;
5147330f729Sjoerg case CXComment_HTMLStartTag: {
5157330f729Sjoerg unsigned NumAttrs;
5167330f729Sjoerg printf("CXComment_HTMLStartTag");
5177330f729Sjoerg PrintCXStringWithPrefixAndDispose(
5187330f729Sjoerg "Name",
5197330f729Sjoerg clang_HTMLTagComment_getTagName(Comment));
5207330f729Sjoerg NumAttrs = clang_HTMLStartTag_getNumAttrs(Comment);
5217330f729Sjoerg if (NumAttrs != 0) {
5227330f729Sjoerg printf(" Attrs:");
5237330f729Sjoerg for (i = 0; i != NumAttrs; ++i) {
5247330f729Sjoerg printf(" ");
5257330f729Sjoerg PrintCXStringAndDispose(clang_HTMLStartTag_getAttrName(Comment, i));
5267330f729Sjoerg printf("=");
5277330f729Sjoerg PrintCXStringAndDispose(clang_HTMLStartTag_getAttrValue(Comment, i));
5287330f729Sjoerg }
5297330f729Sjoerg }
5307330f729Sjoerg if (clang_HTMLStartTagComment_isSelfClosing(Comment))
5317330f729Sjoerg printf(" SelfClosing");
5327330f729Sjoerg if (clang_InlineContentComment_hasTrailingNewline(Comment))
5337330f729Sjoerg printf(" HasTrailingNewline");
5347330f729Sjoerg break;
5357330f729Sjoerg }
5367330f729Sjoerg case CXComment_HTMLEndTag:
5377330f729Sjoerg printf("CXComment_HTMLEndTag");
5387330f729Sjoerg PrintCXStringWithPrefixAndDispose(
5397330f729Sjoerg "Name",
5407330f729Sjoerg clang_HTMLTagComment_getTagName(Comment));
5417330f729Sjoerg if (clang_InlineContentComment_hasTrailingNewline(Comment))
5427330f729Sjoerg printf(" HasTrailingNewline");
5437330f729Sjoerg break;
5447330f729Sjoerg case CXComment_Paragraph:
5457330f729Sjoerg printf("CXComment_Paragraph");
5467330f729Sjoerg if (clang_Comment_isWhitespace(Comment))
5477330f729Sjoerg printf(" IsWhitespace");
5487330f729Sjoerg break;
5497330f729Sjoerg case CXComment_BlockCommand:
5507330f729Sjoerg printf("CXComment_BlockCommand");
5517330f729Sjoerg PrintCXStringWithPrefixAndDispose(
5527330f729Sjoerg "CommandName",
5537330f729Sjoerg clang_BlockCommandComment_getCommandName(Comment));
5547330f729Sjoerg for (i = 0, e = clang_BlockCommandComment_getNumArgs(Comment);
5557330f729Sjoerg i != e; ++i) {
5567330f729Sjoerg printf(" Arg[%u]=", i);
5577330f729Sjoerg PrintCXStringAndDispose(
5587330f729Sjoerg clang_BlockCommandComment_getArgText(Comment, i));
5597330f729Sjoerg }
5607330f729Sjoerg break;
5617330f729Sjoerg case CXComment_ParamCommand:
5627330f729Sjoerg printf("CXComment_ParamCommand");
5637330f729Sjoerg switch (clang_ParamCommandComment_getDirection(Comment)) {
5647330f729Sjoerg case CXCommentParamPassDirection_In:
5657330f729Sjoerg printf(" in");
5667330f729Sjoerg break;
5677330f729Sjoerg case CXCommentParamPassDirection_Out:
5687330f729Sjoerg printf(" out");
5697330f729Sjoerg break;
5707330f729Sjoerg case CXCommentParamPassDirection_InOut:
5717330f729Sjoerg printf(" in,out");
5727330f729Sjoerg break;
5737330f729Sjoerg }
5747330f729Sjoerg if (clang_ParamCommandComment_isDirectionExplicit(Comment))
5757330f729Sjoerg printf(" explicitly");
5767330f729Sjoerg else
5777330f729Sjoerg printf(" implicitly");
5787330f729Sjoerg PrintCXStringWithPrefixAndDispose(
5797330f729Sjoerg "ParamName",
5807330f729Sjoerg clang_ParamCommandComment_getParamName(Comment));
5817330f729Sjoerg if (clang_ParamCommandComment_isParamIndexValid(Comment))
5827330f729Sjoerg printf(" ParamIndex=%u", clang_ParamCommandComment_getParamIndex(Comment));
5837330f729Sjoerg else
5847330f729Sjoerg printf(" ParamIndex=Invalid");
5857330f729Sjoerg break;
5867330f729Sjoerg case CXComment_TParamCommand:
5877330f729Sjoerg printf("CXComment_TParamCommand");
5887330f729Sjoerg PrintCXStringWithPrefixAndDispose(
5897330f729Sjoerg "ParamName",
5907330f729Sjoerg clang_TParamCommandComment_getParamName(Comment));
5917330f729Sjoerg if (clang_TParamCommandComment_isParamPositionValid(Comment)) {
5927330f729Sjoerg printf(" ParamPosition={");
5937330f729Sjoerg for (i = 0, e = clang_TParamCommandComment_getDepth(Comment);
5947330f729Sjoerg i != e; ++i) {
5957330f729Sjoerg printf("%u", clang_TParamCommandComment_getIndex(Comment, i));
5967330f729Sjoerg if (i != e - 1)
5977330f729Sjoerg printf(", ");
5987330f729Sjoerg }
5997330f729Sjoerg printf("}");
6007330f729Sjoerg } else
6017330f729Sjoerg printf(" ParamPosition=Invalid");
6027330f729Sjoerg break;
6037330f729Sjoerg case CXComment_VerbatimBlockCommand:
6047330f729Sjoerg printf("CXComment_VerbatimBlockCommand");
6057330f729Sjoerg PrintCXStringWithPrefixAndDispose(
6067330f729Sjoerg "CommandName",
6077330f729Sjoerg clang_BlockCommandComment_getCommandName(Comment));
6087330f729Sjoerg break;
6097330f729Sjoerg case CXComment_VerbatimBlockLine:
6107330f729Sjoerg printf("CXComment_VerbatimBlockLine");
6117330f729Sjoerg PrintCXStringWithPrefixAndDispose(
6127330f729Sjoerg "Text",
6137330f729Sjoerg clang_VerbatimBlockLineComment_getText(Comment));
6147330f729Sjoerg break;
6157330f729Sjoerg case CXComment_VerbatimLine:
6167330f729Sjoerg printf("CXComment_VerbatimLine");
6177330f729Sjoerg PrintCXStringWithPrefixAndDispose(
6187330f729Sjoerg "Text",
6197330f729Sjoerg clang_VerbatimLineComment_getText(Comment));
6207330f729Sjoerg break;
6217330f729Sjoerg case CXComment_FullComment:
6227330f729Sjoerg printf("CXComment_FullComment");
6237330f729Sjoerg break;
6247330f729Sjoerg }
6257330f729Sjoerg if (Kind != CXComment_Null) {
6267330f729Sjoerg const unsigned NumChildren = clang_Comment_getNumChildren(Comment);
6277330f729Sjoerg unsigned i;
6287330f729Sjoerg for (i = 0; i != NumChildren; ++i) {
6297330f729Sjoerg printf("\n// %s: ", FileCheckPrefix);
6307330f729Sjoerg DumpCXCommentInternal(Ctx, clang_Comment_getChild(Comment, i));
6317330f729Sjoerg }
6327330f729Sjoerg }
6337330f729Sjoerg printf(")");
6347330f729Sjoerg Ctx->IndentLevel--;
6357330f729Sjoerg }
6367330f729Sjoerg
DumpCXComment(CXComment Comment)6377330f729Sjoerg static void DumpCXComment(CXComment Comment) {
6387330f729Sjoerg struct CommentASTDumpingContext Ctx;
6397330f729Sjoerg Ctx.IndentLevel = 1;
6407330f729Sjoerg printf("\n// %s: CommentAST=[\n// %s:", FileCheckPrefix, FileCheckPrefix);
6417330f729Sjoerg DumpCXCommentInternal(&Ctx, Comment);
6427330f729Sjoerg printf("]");
6437330f729Sjoerg }
6447330f729Sjoerg
ValidateCommentXML(const char * Str,const char * CommentSchemaFile)6457330f729Sjoerg static void ValidateCommentXML(const char *Str, const char *CommentSchemaFile) {
6467330f729Sjoerg #ifdef CLANG_HAVE_LIBXML
6477330f729Sjoerg xmlRelaxNGParserCtxtPtr RNGParser;
6487330f729Sjoerg xmlRelaxNGPtr Schema;
6497330f729Sjoerg xmlDocPtr Doc;
6507330f729Sjoerg xmlRelaxNGValidCtxtPtr ValidationCtxt;
6517330f729Sjoerg int status;
6527330f729Sjoerg
6537330f729Sjoerg if (!CommentSchemaFile)
6547330f729Sjoerg return;
6557330f729Sjoerg
6567330f729Sjoerg RNGParser = xmlRelaxNGNewParserCtxt(CommentSchemaFile);
6577330f729Sjoerg if (!RNGParser) {
6587330f729Sjoerg printf(" libXMLError");
6597330f729Sjoerg return;
6607330f729Sjoerg }
6617330f729Sjoerg Schema = xmlRelaxNGParse(RNGParser);
6627330f729Sjoerg
6637330f729Sjoerg Doc = xmlParseDoc((const xmlChar *) Str);
6647330f729Sjoerg
6657330f729Sjoerg if (!Doc) {
6667330f729Sjoerg xmlErrorPtr Error = xmlGetLastError();
6677330f729Sjoerg printf(" CommentXMLInvalid [not well-formed XML: %s]", Error->message);
6687330f729Sjoerg return;
6697330f729Sjoerg }
6707330f729Sjoerg
6717330f729Sjoerg ValidationCtxt = xmlRelaxNGNewValidCtxt(Schema);
6727330f729Sjoerg status = xmlRelaxNGValidateDoc(ValidationCtxt, Doc);
6737330f729Sjoerg if (!status)
6747330f729Sjoerg printf(" CommentXMLValid");
6757330f729Sjoerg else if (status > 0) {
6767330f729Sjoerg xmlErrorPtr Error = xmlGetLastError();
6777330f729Sjoerg printf(" CommentXMLInvalid [not valid XML: %s]", Error->message);
6787330f729Sjoerg } else
6797330f729Sjoerg printf(" libXMLError");
6807330f729Sjoerg
6817330f729Sjoerg xmlRelaxNGFreeValidCtxt(ValidationCtxt);
6827330f729Sjoerg xmlFreeDoc(Doc);
6837330f729Sjoerg xmlRelaxNGFree(Schema);
6847330f729Sjoerg xmlRelaxNGFreeParserCtxt(RNGParser);
6857330f729Sjoerg #endif
6867330f729Sjoerg }
6877330f729Sjoerg
PrintCursorComments(CXCursor Cursor,const char * CommentSchemaFile)6887330f729Sjoerg static void PrintCursorComments(CXCursor Cursor,
6897330f729Sjoerg const char *CommentSchemaFile) {
6907330f729Sjoerg {
6917330f729Sjoerg CXString RawComment;
6927330f729Sjoerg const char *RawCommentCString;
6937330f729Sjoerg CXString BriefComment;
6947330f729Sjoerg const char *BriefCommentCString;
6957330f729Sjoerg
6967330f729Sjoerg RawComment = clang_Cursor_getRawCommentText(Cursor);
6977330f729Sjoerg RawCommentCString = clang_getCString(RawComment);
6987330f729Sjoerg if (RawCommentCString != NULL && RawCommentCString[0] != '\0') {
6997330f729Sjoerg PrintCStringWithPrefix("RawComment", RawCommentCString);
7007330f729Sjoerg PrintRange(clang_Cursor_getCommentRange(Cursor), "RawCommentRange");
7017330f729Sjoerg
7027330f729Sjoerg BriefComment = clang_Cursor_getBriefCommentText(Cursor);
7037330f729Sjoerg BriefCommentCString = clang_getCString(BriefComment);
7047330f729Sjoerg if (BriefCommentCString != NULL && BriefCommentCString[0] != '\0')
7057330f729Sjoerg PrintCStringWithPrefix("BriefComment", BriefCommentCString);
7067330f729Sjoerg clang_disposeString(BriefComment);
7077330f729Sjoerg }
7087330f729Sjoerg clang_disposeString(RawComment);
7097330f729Sjoerg }
7107330f729Sjoerg
7117330f729Sjoerg {
7127330f729Sjoerg CXComment Comment = clang_Cursor_getParsedComment(Cursor);
7137330f729Sjoerg if (clang_Comment_getKind(Comment) != CXComment_Null) {
7147330f729Sjoerg PrintCXStringWithPrefixAndDispose("FullCommentAsHTML",
7157330f729Sjoerg clang_FullComment_getAsHTML(Comment));
7167330f729Sjoerg {
7177330f729Sjoerg CXString XML;
7187330f729Sjoerg XML = clang_FullComment_getAsXML(Comment);
7197330f729Sjoerg PrintCXStringWithPrefix("FullCommentAsXML", XML);
7207330f729Sjoerg ValidateCommentXML(clang_getCString(XML), CommentSchemaFile);
7217330f729Sjoerg clang_disposeString(XML);
7227330f729Sjoerg }
7237330f729Sjoerg
7247330f729Sjoerg DumpCXComment(Comment);
7257330f729Sjoerg }
7267330f729Sjoerg }
7277330f729Sjoerg }
7287330f729Sjoerg
7297330f729Sjoerg typedef struct {
7307330f729Sjoerg unsigned line;
7317330f729Sjoerg unsigned col;
7327330f729Sjoerg } LineCol;
7337330f729Sjoerg
lineCol_cmp(const void * p1,const void * p2)7347330f729Sjoerg static int lineCol_cmp(const void *p1, const void *p2) {
7357330f729Sjoerg const LineCol *lhs = p1;
7367330f729Sjoerg const LineCol *rhs = p2;
7377330f729Sjoerg if (lhs->line != rhs->line)
7387330f729Sjoerg return (int)lhs->line - (int)rhs->line;
7397330f729Sjoerg return (int)lhs->col - (int)rhs->col;
7407330f729Sjoerg }
7417330f729Sjoerg
CursorToText(CXCursor Cursor)7427330f729Sjoerg static CXString CursorToText(CXCursor Cursor) {
7437330f729Sjoerg CXString text;
7447330f729Sjoerg switch (wanted_display_type) {
7457330f729Sjoerg case DisplayType_Spelling:
7467330f729Sjoerg return clang_getCursorSpelling(Cursor);
7477330f729Sjoerg case DisplayType_DisplayName:
7487330f729Sjoerg return clang_getCursorDisplayName(Cursor);
7497330f729Sjoerg case DisplayType_Pretty: {
7507330f729Sjoerg CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor);
7517330f729Sjoerg ModifyPrintingPolicyAccordingToEnv(Policy);
7527330f729Sjoerg text = clang_getCursorPrettyPrinted(Cursor, Policy);
7537330f729Sjoerg clang_PrintingPolicy_dispose(Policy);
7547330f729Sjoerg return text;
7557330f729Sjoerg }
7567330f729Sjoerg }
7577330f729Sjoerg assert(0 && "unknown display type"); /* no llvm_unreachable in C. */
7587330f729Sjoerg /* Set to NULL to prevent uninitialized variable warnings. */
7597330f729Sjoerg text.data = NULL;
7607330f729Sjoerg text.private_flags = 0;
7617330f729Sjoerg return text;
7627330f729Sjoerg }
7637330f729Sjoerg
PrintCursor(CXCursor Cursor,const char * CommentSchemaFile)7647330f729Sjoerg static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
7657330f729Sjoerg CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
7667330f729Sjoerg if (clang_isInvalid(Cursor.kind)) {
7677330f729Sjoerg CXString ks = clang_getCursorKindSpelling(Cursor.kind);
7687330f729Sjoerg printf("Invalid Cursor => %s", clang_getCString(ks));
7697330f729Sjoerg clang_disposeString(ks);
7707330f729Sjoerg }
7717330f729Sjoerg else {
7727330f729Sjoerg CXString string, ks;
7737330f729Sjoerg CXCursor Referenced;
7747330f729Sjoerg unsigned line, column;
7757330f729Sjoerg CXCursor SpecializationOf;
7767330f729Sjoerg CXCursor *overridden;
7777330f729Sjoerg unsigned num_overridden;
7787330f729Sjoerg unsigned RefNameRangeNr;
7797330f729Sjoerg CXSourceRange CursorExtent;
7807330f729Sjoerg CXSourceRange RefNameRange;
7817330f729Sjoerg int AlwaysUnavailable;
7827330f729Sjoerg int AlwaysDeprecated;
7837330f729Sjoerg CXString UnavailableMessage;
7847330f729Sjoerg CXString DeprecatedMessage;
7857330f729Sjoerg CXPlatformAvailability PlatformAvailability[2];
7867330f729Sjoerg int NumPlatformAvailability;
7877330f729Sjoerg int I;
7887330f729Sjoerg
7897330f729Sjoerg ks = clang_getCursorKindSpelling(Cursor.kind);
7907330f729Sjoerg string = CursorToText(Cursor);
7917330f729Sjoerg printf("%s=%s", clang_getCString(ks),
7927330f729Sjoerg clang_getCString(string));
7937330f729Sjoerg clang_disposeString(ks);
7947330f729Sjoerg clang_disposeString(string);
7957330f729Sjoerg
7967330f729Sjoerg Referenced = clang_getCursorReferenced(Cursor);
7977330f729Sjoerg if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
7987330f729Sjoerg if (clang_getCursorKind(Referenced) == CXCursor_OverloadedDeclRef) {
7997330f729Sjoerg unsigned I, N = clang_getNumOverloadedDecls(Referenced);
8007330f729Sjoerg printf("[");
8017330f729Sjoerg for (I = 0; I != N; ++I) {
8027330f729Sjoerg CXCursor Ovl = clang_getOverloadedDecl(Referenced, I);
8037330f729Sjoerg CXSourceLocation Loc;
8047330f729Sjoerg if (I)
8057330f729Sjoerg printf(", ");
8067330f729Sjoerg
8077330f729Sjoerg Loc = clang_getCursorLocation(Ovl);
8087330f729Sjoerg clang_getSpellingLocation(Loc, 0, &line, &column, 0);
8097330f729Sjoerg printf("%d:%d", line, column);
8107330f729Sjoerg }
8117330f729Sjoerg printf("]");
8127330f729Sjoerg } else {
8137330f729Sjoerg CXSourceLocation Loc = clang_getCursorLocation(Referenced);
8147330f729Sjoerg clang_getSpellingLocation(Loc, 0, &line, &column, 0);
8157330f729Sjoerg printf(":%d:%d", line, column);
8167330f729Sjoerg }
8177330f729Sjoerg
8187330f729Sjoerg if (clang_getCursorKind(Referenced) == CXCursor_TypedefDecl) {
8197330f729Sjoerg CXType T = clang_getCursorType(Referenced);
8207330f729Sjoerg if (clang_Type_isTransparentTagTypedef(T)) {
8217330f729Sjoerg CXType Underlying = clang_getTypedefDeclUnderlyingType(Referenced);
8227330f729Sjoerg CXString S = clang_getTypeSpelling(Underlying);
8237330f729Sjoerg printf(" (Transparent: %s)", clang_getCString(S));
8247330f729Sjoerg clang_disposeString(S);
8257330f729Sjoerg }
8267330f729Sjoerg }
8277330f729Sjoerg }
8287330f729Sjoerg
8297330f729Sjoerg if (clang_isCursorDefinition(Cursor))
8307330f729Sjoerg printf(" (Definition)");
8317330f729Sjoerg
8327330f729Sjoerg switch (clang_getCursorAvailability(Cursor)) {
8337330f729Sjoerg case CXAvailability_Available:
8347330f729Sjoerg break;
8357330f729Sjoerg
8367330f729Sjoerg case CXAvailability_Deprecated:
8377330f729Sjoerg printf(" (deprecated)");
8387330f729Sjoerg break;
8397330f729Sjoerg
8407330f729Sjoerg case CXAvailability_NotAvailable:
8417330f729Sjoerg printf(" (unavailable)");
8427330f729Sjoerg break;
8437330f729Sjoerg
8447330f729Sjoerg case CXAvailability_NotAccessible:
8457330f729Sjoerg printf(" (inaccessible)");
8467330f729Sjoerg break;
8477330f729Sjoerg }
8487330f729Sjoerg
8497330f729Sjoerg NumPlatformAvailability
8507330f729Sjoerg = clang_getCursorPlatformAvailability(Cursor,
8517330f729Sjoerg &AlwaysDeprecated,
8527330f729Sjoerg &DeprecatedMessage,
8537330f729Sjoerg &AlwaysUnavailable,
8547330f729Sjoerg &UnavailableMessage,
8557330f729Sjoerg PlatformAvailability, 2);
8567330f729Sjoerg if (AlwaysUnavailable) {
8577330f729Sjoerg printf(" (always unavailable: \"%s\")",
8587330f729Sjoerg clang_getCString(UnavailableMessage));
8597330f729Sjoerg } else if (AlwaysDeprecated) {
8607330f729Sjoerg printf(" (always deprecated: \"%s\")",
8617330f729Sjoerg clang_getCString(DeprecatedMessage));
8627330f729Sjoerg } else {
8637330f729Sjoerg for (I = 0; I != NumPlatformAvailability; ++I) {
8647330f729Sjoerg if (I >= 2)
8657330f729Sjoerg break;
8667330f729Sjoerg
8677330f729Sjoerg printf(" (%s", clang_getCString(PlatformAvailability[I].Platform));
8687330f729Sjoerg if (PlatformAvailability[I].Unavailable)
8697330f729Sjoerg printf(", unavailable");
8707330f729Sjoerg else {
8717330f729Sjoerg printVersion(", introduced=", PlatformAvailability[I].Introduced);
8727330f729Sjoerg printVersion(", deprecated=", PlatformAvailability[I].Deprecated);
8737330f729Sjoerg printVersion(", obsoleted=", PlatformAvailability[I].Obsoleted);
8747330f729Sjoerg }
8757330f729Sjoerg if (clang_getCString(PlatformAvailability[I].Message)[0])
8767330f729Sjoerg printf(", message=\"%s\"",
8777330f729Sjoerg clang_getCString(PlatformAvailability[I].Message));
8787330f729Sjoerg printf(")");
8797330f729Sjoerg }
8807330f729Sjoerg }
8817330f729Sjoerg for (I = 0; I != NumPlatformAvailability; ++I) {
8827330f729Sjoerg if (I >= 2)
8837330f729Sjoerg break;
8847330f729Sjoerg clang_disposeCXPlatformAvailability(PlatformAvailability + I);
8857330f729Sjoerg }
8867330f729Sjoerg
8877330f729Sjoerg clang_disposeString(DeprecatedMessage);
8887330f729Sjoerg clang_disposeString(UnavailableMessage);
8897330f729Sjoerg
8907330f729Sjoerg if (clang_CXXConstructor_isDefaultConstructor(Cursor))
8917330f729Sjoerg printf(" (default constructor)");
8927330f729Sjoerg
8937330f729Sjoerg if (clang_CXXConstructor_isMoveConstructor(Cursor))
8947330f729Sjoerg printf(" (move constructor)");
8957330f729Sjoerg if (clang_CXXConstructor_isCopyConstructor(Cursor))
8967330f729Sjoerg printf(" (copy constructor)");
8977330f729Sjoerg if (clang_CXXConstructor_isConvertingConstructor(Cursor))
8987330f729Sjoerg printf(" (converting constructor)");
8997330f729Sjoerg if (clang_CXXField_isMutable(Cursor))
9007330f729Sjoerg printf(" (mutable)");
9017330f729Sjoerg if (clang_CXXMethod_isDefaulted(Cursor))
9027330f729Sjoerg printf(" (defaulted)");
9037330f729Sjoerg if (clang_CXXMethod_isStatic(Cursor))
9047330f729Sjoerg printf(" (static)");
9057330f729Sjoerg if (clang_CXXMethod_isVirtual(Cursor))
9067330f729Sjoerg printf(" (virtual)");
9077330f729Sjoerg if (clang_CXXMethod_isConst(Cursor))
9087330f729Sjoerg printf(" (const)");
9097330f729Sjoerg if (clang_CXXMethod_isPureVirtual(Cursor))
9107330f729Sjoerg printf(" (pure)");
9117330f729Sjoerg if (clang_CXXRecord_isAbstract(Cursor))
9127330f729Sjoerg printf(" (abstract)");
9137330f729Sjoerg if (clang_EnumDecl_isScoped(Cursor))
9147330f729Sjoerg printf(" (scoped)");
9157330f729Sjoerg if (clang_Cursor_isVariadic(Cursor))
9167330f729Sjoerg printf(" (variadic)");
9177330f729Sjoerg if (clang_Cursor_isObjCOptional(Cursor))
9187330f729Sjoerg printf(" (@optional)");
9197330f729Sjoerg if (clang_isInvalidDeclaration(Cursor))
9207330f729Sjoerg printf(" (invalid)");
9217330f729Sjoerg
9227330f729Sjoerg switch (clang_getCursorExceptionSpecificationType(Cursor))
9237330f729Sjoerg {
9247330f729Sjoerg case CXCursor_ExceptionSpecificationKind_None:
9257330f729Sjoerg break;
9267330f729Sjoerg
9277330f729Sjoerg case CXCursor_ExceptionSpecificationKind_DynamicNone:
9287330f729Sjoerg printf(" (noexcept dynamic none)");
9297330f729Sjoerg break;
9307330f729Sjoerg
9317330f729Sjoerg case CXCursor_ExceptionSpecificationKind_Dynamic:
9327330f729Sjoerg printf(" (noexcept dynamic)");
9337330f729Sjoerg break;
9347330f729Sjoerg
9357330f729Sjoerg case CXCursor_ExceptionSpecificationKind_MSAny:
9367330f729Sjoerg printf(" (noexcept dynamic any)");
9377330f729Sjoerg break;
9387330f729Sjoerg
9397330f729Sjoerg case CXCursor_ExceptionSpecificationKind_BasicNoexcept:
9407330f729Sjoerg printf(" (noexcept)");
9417330f729Sjoerg break;
9427330f729Sjoerg
9437330f729Sjoerg case CXCursor_ExceptionSpecificationKind_ComputedNoexcept:
9447330f729Sjoerg printf(" (computed-noexcept)");
9457330f729Sjoerg break;
9467330f729Sjoerg
9477330f729Sjoerg case CXCursor_ExceptionSpecificationKind_Unevaluated:
9487330f729Sjoerg case CXCursor_ExceptionSpecificationKind_Uninstantiated:
9497330f729Sjoerg case CXCursor_ExceptionSpecificationKind_Unparsed:
9507330f729Sjoerg break;
9517330f729Sjoerg }
9527330f729Sjoerg
9537330f729Sjoerg {
9547330f729Sjoerg CXString language;
9557330f729Sjoerg CXString definedIn;
9567330f729Sjoerg unsigned generated;
9577330f729Sjoerg if (clang_Cursor_isExternalSymbol(Cursor, &language, &definedIn,
9587330f729Sjoerg &generated)) {
9597330f729Sjoerg printf(" (external lang: %s, defined: %s, gen: %d)",
9607330f729Sjoerg clang_getCString(language), clang_getCString(definedIn), generated);
9617330f729Sjoerg clang_disposeString(language);
9627330f729Sjoerg clang_disposeString(definedIn);
9637330f729Sjoerg }
9647330f729Sjoerg }
9657330f729Sjoerg
9667330f729Sjoerg if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
9677330f729Sjoerg CXType T =
9687330f729Sjoerg clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor));
9697330f729Sjoerg CXString S = clang_getTypeKindSpelling(T.kind);
9707330f729Sjoerg printf(" [IBOutletCollection=%s]", clang_getCString(S));
9717330f729Sjoerg clang_disposeString(S);
9727330f729Sjoerg }
9737330f729Sjoerg
9747330f729Sjoerg if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
9757330f729Sjoerg enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
9767330f729Sjoerg unsigned isVirtual = clang_isVirtualBase(Cursor);
9777330f729Sjoerg const char *accessStr = 0;
9787330f729Sjoerg
9797330f729Sjoerg switch (access) {
9807330f729Sjoerg case CX_CXXInvalidAccessSpecifier:
9817330f729Sjoerg accessStr = "invalid"; break;
9827330f729Sjoerg case CX_CXXPublic:
9837330f729Sjoerg accessStr = "public"; break;
9847330f729Sjoerg case CX_CXXProtected:
9857330f729Sjoerg accessStr = "protected"; break;
9867330f729Sjoerg case CX_CXXPrivate:
9877330f729Sjoerg accessStr = "private"; break;
9887330f729Sjoerg }
9897330f729Sjoerg
9907330f729Sjoerg printf(" [access=%s isVirtual=%s]", accessStr,
9917330f729Sjoerg isVirtual ? "true" : "false");
9927330f729Sjoerg }
9937330f729Sjoerg
9947330f729Sjoerg SpecializationOf = clang_getSpecializedCursorTemplate(Cursor);
9957330f729Sjoerg if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {
9967330f729Sjoerg CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);
9977330f729Sjoerg CXString Name = clang_getCursorSpelling(SpecializationOf);
9987330f729Sjoerg clang_getSpellingLocation(Loc, 0, &line, &column, 0);
9997330f729Sjoerg printf(" [Specialization of %s:%d:%d]",
10007330f729Sjoerg clang_getCString(Name), line, column);
10017330f729Sjoerg clang_disposeString(Name);
10027330f729Sjoerg
10037330f729Sjoerg if (Cursor.kind == CXCursor_FunctionDecl) {
10047330f729Sjoerg /* Collect the template parameter kinds from the base template. */
10057330f729Sjoerg int NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
10067330f729Sjoerg int I;
10077330f729Sjoerg if (NumTemplateArgs < 0) {
10087330f729Sjoerg printf(" [no template arg info]");
10097330f729Sjoerg }
10107330f729Sjoerg for (I = 0; I < NumTemplateArgs; I++) {
10117330f729Sjoerg enum CXTemplateArgumentKind TAK =
10127330f729Sjoerg clang_Cursor_getTemplateArgumentKind(Cursor, I);
10137330f729Sjoerg switch(TAK) {
10147330f729Sjoerg case CXTemplateArgumentKind_Type:
10157330f729Sjoerg {
10167330f729Sjoerg CXType T = clang_Cursor_getTemplateArgumentType(Cursor, I);
10177330f729Sjoerg CXString S = clang_getTypeSpelling(T);
10187330f729Sjoerg printf(" [Template arg %d: kind: %d, type: %s]",
10197330f729Sjoerg I, TAK, clang_getCString(S));
10207330f729Sjoerg clang_disposeString(S);
10217330f729Sjoerg }
10227330f729Sjoerg break;
10237330f729Sjoerg case CXTemplateArgumentKind_Integral:
10247330f729Sjoerg printf(" [Template arg %d: kind: %d, intval: %lld]",
10257330f729Sjoerg I, TAK, clang_Cursor_getTemplateArgumentValue(Cursor, I));
10267330f729Sjoerg break;
10277330f729Sjoerg default:
10287330f729Sjoerg printf(" [Template arg %d: kind: %d]\n", I, TAK);
10297330f729Sjoerg }
10307330f729Sjoerg }
10317330f729Sjoerg }
10327330f729Sjoerg }
10337330f729Sjoerg
10347330f729Sjoerg clang_getOverriddenCursors(Cursor, &overridden, &num_overridden);
10357330f729Sjoerg if (num_overridden) {
10367330f729Sjoerg unsigned I;
10377330f729Sjoerg LineCol lineCols[50];
10387330f729Sjoerg assert(num_overridden <= 50);
10397330f729Sjoerg printf(" [Overrides ");
10407330f729Sjoerg for (I = 0; I != num_overridden; ++I) {
10417330f729Sjoerg CXSourceLocation Loc = clang_getCursorLocation(overridden[I]);
10427330f729Sjoerg clang_getSpellingLocation(Loc, 0, &line, &column, 0);
10437330f729Sjoerg lineCols[I].line = line;
10447330f729Sjoerg lineCols[I].col = column;
10457330f729Sjoerg }
10467330f729Sjoerg /* Make the order of the override list deterministic. */
10477330f729Sjoerg qsort(lineCols, num_overridden, sizeof(LineCol), lineCol_cmp);
10487330f729Sjoerg for (I = 0; I != num_overridden; ++I) {
10497330f729Sjoerg if (I)
10507330f729Sjoerg printf(", ");
10517330f729Sjoerg printf("@%d:%d", lineCols[I].line, lineCols[I].col);
10527330f729Sjoerg }
10537330f729Sjoerg printf("]");
10547330f729Sjoerg clang_disposeOverriddenCursors(overridden);
10557330f729Sjoerg }
10567330f729Sjoerg
10577330f729Sjoerg if (Cursor.kind == CXCursor_InclusionDirective) {
10587330f729Sjoerg CXFile File = clang_getIncludedFile(Cursor);
10597330f729Sjoerg CXString Included = clang_getFileName(File);
10607330f729Sjoerg const char *IncludedString = clang_getCString(Included);
10617330f729Sjoerg printf(" (%s)", IncludedString ? IncludedString : "(null)");
10627330f729Sjoerg clang_disposeString(Included);
10637330f729Sjoerg
10647330f729Sjoerg if (clang_isFileMultipleIncludeGuarded(TU, File))
10657330f729Sjoerg printf(" [multi-include guarded]");
10667330f729Sjoerg }
10677330f729Sjoerg
10687330f729Sjoerg CursorExtent = clang_getCursorExtent(Cursor);
10697330f729Sjoerg RefNameRange = clang_getCursorReferenceNameRange(Cursor,
10707330f729Sjoerg CXNameRange_WantQualifier
10717330f729Sjoerg | CXNameRange_WantSinglePiece
10727330f729Sjoerg | CXNameRange_WantTemplateArgs,
10737330f729Sjoerg 0);
10747330f729Sjoerg if (!clang_equalRanges(CursorExtent, RefNameRange))
10757330f729Sjoerg PrintRange(RefNameRange, "SingleRefName");
10767330f729Sjoerg
10777330f729Sjoerg for (RefNameRangeNr = 0; 1; RefNameRangeNr++) {
10787330f729Sjoerg RefNameRange = clang_getCursorReferenceNameRange(Cursor,
10797330f729Sjoerg CXNameRange_WantQualifier
10807330f729Sjoerg | CXNameRange_WantTemplateArgs,
10817330f729Sjoerg RefNameRangeNr);
10827330f729Sjoerg if (clang_equalRanges(clang_getNullRange(), RefNameRange))
10837330f729Sjoerg break;
10847330f729Sjoerg if (!clang_equalRanges(CursorExtent, RefNameRange))
10857330f729Sjoerg PrintRange(RefNameRange, "RefName");
10867330f729Sjoerg }
10877330f729Sjoerg
10887330f729Sjoerg PrintCursorComments(Cursor, CommentSchemaFile);
10897330f729Sjoerg
10907330f729Sjoerg {
10917330f729Sjoerg unsigned PropAttrs = clang_Cursor_getObjCPropertyAttributes(Cursor, 0);
10927330f729Sjoerg if (PropAttrs != CXObjCPropertyAttr_noattr) {
10937330f729Sjoerg printf(" [");
10947330f729Sjoerg #define PRINT_PROP_ATTR(A) \
10957330f729Sjoerg if (PropAttrs & CXObjCPropertyAttr_##A) printf(#A ",")
10967330f729Sjoerg PRINT_PROP_ATTR(readonly);
10977330f729Sjoerg PRINT_PROP_ATTR(getter);
10987330f729Sjoerg PRINT_PROP_ATTR(assign);
10997330f729Sjoerg PRINT_PROP_ATTR(readwrite);
11007330f729Sjoerg PRINT_PROP_ATTR(retain);
11017330f729Sjoerg PRINT_PROP_ATTR(copy);
11027330f729Sjoerg PRINT_PROP_ATTR(nonatomic);
11037330f729Sjoerg PRINT_PROP_ATTR(setter);
11047330f729Sjoerg PRINT_PROP_ATTR(atomic);
11057330f729Sjoerg PRINT_PROP_ATTR(weak);
11067330f729Sjoerg PRINT_PROP_ATTR(strong);
11077330f729Sjoerg PRINT_PROP_ATTR(unsafe_unretained);
11087330f729Sjoerg PRINT_PROP_ATTR(class);
11097330f729Sjoerg printf("]");
11107330f729Sjoerg }
11117330f729Sjoerg }
11127330f729Sjoerg
11137330f729Sjoerg if (Cursor.kind == CXCursor_ObjCPropertyDecl) {
11147330f729Sjoerg CXString Name = clang_Cursor_getObjCPropertyGetterName(Cursor);
11157330f729Sjoerg CXString Spelling = clang_getCursorSpelling(Cursor);
11167330f729Sjoerg const char *CName = clang_getCString(Name);
11177330f729Sjoerg const char *CSpelling = clang_getCString(Spelling);
11187330f729Sjoerg if (CName && strcmp(CName, CSpelling)) {
11197330f729Sjoerg printf(" (getter=%s)", CName);
11207330f729Sjoerg }
11217330f729Sjoerg clang_disposeString(Spelling);
11227330f729Sjoerg clang_disposeString(Name);
11237330f729Sjoerg }
11247330f729Sjoerg
11257330f729Sjoerg if (Cursor.kind == CXCursor_ObjCPropertyDecl) {
11267330f729Sjoerg CXString Name = clang_Cursor_getObjCPropertySetterName(Cursor);
11277330f729Sjoerg CXString Spelling = clang_getCursorSpelling(Cursor);
11287330f729Sjoerg const char *CName = clang_getCString(Name);
11297330f729Sjoerg const char *CSpelling = clang_getCString(Spelling);
11307330f729Sjoerg char *DefaultSetter = malloc(strlen(CSpelling) + 5);
11317330f729Sjoerg sprintf(DefaultSetter, "set%s:", CSpelling);
11327330f729Sjoerg DefaultSetter[3] &= ~(1 << 5); /* Make uppercase */
11337330f729Sjoerg if (CName && strcmp(CName, DefaultSetter)) {
11347330f729Sjoerg printf(" (setter=%s)", CName);
11357330f729Sjoerg }
11367330f729Sjoerg free(DefaultSetter);
11377330f729Sjoerg clang_disposeString(Spelling);
11387330f729Sjoerg clang_disposeString(Name);
11397330f729Sjoerg }
11407330f729Sjoerg
11417330f729Sjoerg {
11427330f729Sjoerg unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor);
11437330f729Sjoerg if (QT != CXObjCDeclQualifier_None) {
11447330f729Sjoerg printf(" [");
11457330f729Sjoerg #define PRINT_OBJC_QUAL(A) \
11467330f729Sjoerg if (QT & CXObjCDeclQualifier_##A) printf(#A ",")
11477330f729Sjoerg PRINT_OBJC_QUAL(In);
11487330f729Sjoerg PRINT_OBJC_QUAL(Inout);
11497330f729Sjoerg PRINT_OBJC_QUAL(Out);
11507330f729Sjoerg PRINT_OBJC_QUAL(Bycopy);
11517330f729Sjoerg PRINT_OBJC_QUAL(Byref);
11527330f729Sjoerg PRINT_OBJC_QUAL(Oneway);
11537330f729Sjoerg printf("]");
11547330f729Sjoerg }
11557330f729Sjoerg }
11567330f729Sjoerg }
11577330f729Sjoerg }
11587330f729Sjoerg
GetCursorSource(CXCursor Cursor)11597330f729Sjoerg static const char* GetCursorSource(CXCursor Cursor) {
11607330f729Sjoerg CXSourceLocation Loc = clang_getCursorLocation(Cursor);
11617330f729Sjoerg CXString source;
11627330f729Sjoerg CXFile file;
11637330f729Sjoerg clang_getExpansionLocation(Loc, &file, 0, 0, 0);
11647330f729Sjoerg source = clang_getFileName(file);
11657330f729Sjoerg if (!clang_getCString(source)) {
11667330f729Sjoerg clang_disposeString(source);
11677330f729Sjoerg return "<invalid loc>";
11687330f729Sjoerg }
11697330f729Sjoerg else {
11707330f729Sjoerg const char *b = basename(clang_getCString(source));
11717330f729Sjoerg clang_disposeString(source);
11727330f729Sjoerg return b;
11737330f729Sjoerg }
11747330f729Sjoerg }
11757330f729Sjoerg
createCXString(const char * CS)11767330f729Sjoerg static CXString createCXString(const char *CS) {
11777330f729Sjoerg CXString Str;
11787330f729Sjoerg Str.data = (const void *) CS;
11797330f729Sjoerg Str.private_flags = 0;
11807330f729Sjoerg return Str;
11817330f729Sjoerg }
11827330f729Sjoerg
11837330f729Sjoerg /******************************************************************************/
11847330f729Sjoerg /* Callbacks. */
11857330f729Sjoerg /******************************************************************************/
11867330f729Sjoerg
11877330f729Sjoerg typedef void (*PostVisitTU)(CXTranslationUnit);
11887330f729Sjoerg
PrintDiagnostic(CXDiagnostic Diagnostic)11897330f729Sjoerg void PrintDiagnostic(CXDiagnostic Diagnostic) {
11907330f729Sjoerg FILE *out = stderr;
11917330f729Sjoerg CXFile file;
11927330f729Sjoerg CXString Msg;
11937330f729Sjoerg unsigned display_opts = CXDiagnostic_DisplaySourceLocation
11947330f729Sjoerg | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges
11957330f729Sjoerg | CXDiagnostic_DisplayOption;
11967330f729Sjoerg unsigned i, num_fixits;
11977330f729Sjoerg
11987330f729Sjoerg if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
11997330f729Sjoerg return;
12007330f729Sjoerg
12017330f729Sjoerg Msg = clang_formatDiagnostic(Diagnostic, display_opts);
12027330f729Sjoerg fprintf(stderr, "%s\n", clang_getCString(Msg));
12037330f729Sjoerg clang_disposeString(Msg);
12047330f729Sjoerg
12057330f729Sjoerg clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
12067330f729Sjoerg &file, 0, 0, 0);
12077330f729Sjoerg if (!file)
12087330f729Sjoerg return;
12097330f729Sjoerg
12107330f729Sjoerg num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
12117330f729Sjoerg fprintf(stderr, "Number FIX-ITs = %d\n", num_fixits);
12127330f729Sjoerg for (i = 0; i != num_fixits; ++i) {
12137330f729Sjoerg CXSourceRange range;
12147330f729Sjoerg CXString insertion_text = clang_getDiagnosticFixIt(Diagnostic, i, &range);
12157330f729Sjoerg CXSourceLocation start = clang_getRangeStart(range);
12167330f729Sjoerg CXSourceLocation end = clang_getRangeEnd(range);
12177330f729Sjoerg unsigned start_line, start_column, end_line, end_column;
12187330f729Sjoerg CXFile start_file, end_file;
12197330f729Sjoerg clang_getSpellingLocation(start, &start_file, &start_line,
12207330f729Sjoerg &start_column, 0);
12217330f729Sjoerg clang_getSpellingLocation(end, &end_file, &end_line, &end_column, 0);
12227330f729Sjoerg if (clang_equalLocations(start, end)) {
12237330f729Sjoerg /* Insertion. */
12247330f729Sjoerg if (start_file == file)
12257330f729Sjoerg fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
12267330f729Sjoerg clang_getCString(insertion_text), start_line, start_column);
12277330f729Sjoerg } else if (strcmp(clang_getCString(insertion_text), "") == 0) {
12287330f729Sjoerg /* Removal. */
12297330f729Sjoerg if (start_file == file && end_file == file) {
12307330f729Sjoerg fprintf(out, "FIX-IT: Remove ");
12317330f729Sjoerg PrintExtent(out, start_line, start_column, end_line, end_column);
12327330f729Sjoerg fprintf(out, "\n");
12337330f729Sjoerg }
12347330f729Sjoerg } else {
12357330f729Sjoerg /* Replacement. */
12367330f729Sjoerg if (start_file == end_file) {
12377330f729Sjoerg fprintf(out, "FIX-IT: Replace ");
12387330f729Sjoerg PrintExtent(out, start_line, start_column, end_line, end_column);
12397330f729Sjoerg fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text));
12407330f729Sjoerg }
12417330f729Sjoerg }
12427330f729Sjoerg clang_disposeString(insertion_text);
12437330f729Sjoerg }
12447330f729Sjoerg }
12457330f729Sjoerg
PrintDiagnosticSet(CXDiagnosticSet Set)12467330f729Sjoerg void PrintDiagnosticSet(CXDiagnosticSet Set) {
12477330f729Sjoerg int i = 0, n = clang_getNumDiagnosticsInSet(Set);
12487330f729Sjoerg for ( ; i != n ; ++i) {
12497330f729Sjoerg CXDiagnostic Diag = clang_getDiagnosticInSet(Set, i);
12507330f729Sjoerg CXDiagnosticSet ChildDiags = clang_getChildDiagnostics(Diag);
12517330f729Sjoerg PrintDiagnostic(Diag);
12527330f729Sjoerg if (ChildDiags)
12537330f729Sjoerg PrintDiagnosticSet(ChildDiags);
12547330f729Sjoerg }
12557330f729Sjoerg }
12567330f729Sjoerg
PrintDiagnostics(CXTranslationUnit TU)12577330f729Sjoerg void PrintDiagnostics(CXTranslationUnit TU) {
12587330f729Sjoerg CXDiagnosticSet TUSet = clang_getDiagnosticSetFromTU(TU);
12597330f729Sjoerg PrintDiagnosticSet(TUSet);
12607330f729Sjoerg clang_disposeDiagnosticSet(TUSet);
12617330f729Sjoerg }
12627330f729Sjoerg
PrintMemoryUsage(CXTranslationUnit TU)12637330f729Sjoerg void PrintMemoryUsage(CXTranslationUnit TU) {
12647330f729Sjoerg unsigned long total = 0;
12657330f729Sjoerg unsigned i = 0;
12667330f729Sjoerg CXTUResourceUsage usage = clang_getCXTUResourceUsage(TU);
12677330f729Sjoerg fprintf(stderr, "Memory usage:\n");
12687330f729Sjoerg for (i = 0 ; i != usage.numEntries; ++i) {
12697330f729Sjoerg const char *name = clang_getTUResourceUsageName(usage.entries[i].kind);
12707330f729Sjoerg unsigned long amount = usage.entries[i].amount;
12717330f729Sjoerg total += amount;
12727330f729Sjoerg fprintf(stderr, " %s : %ld bytes (%f MBytes)\n", name, amount,
12737330f729Sjoerg ((double) amount)/(1024*1024));
12747330f729Sjoerg }
12757330f729Sjoerg fprintf(stderr, " TOTAL = %ld bytes (%f MBytes)\n", total,
12767330f729Sjoerg ((double) total)/(1024*1024));
12777330f729Sjoerg clang_disposeCXTUResourceUsage(usage);
12787330f729Sjoerg }
12797330f729Sjoerg
12807330f729Sjoerg /******************************************************************************/
12817330f729Sjoerg /* Logic for testing traversal. */
12827330f729Sjoerg /******************************************************************************/
12837330f729Sjoerg
PrintCursorExtent(CXCursor C)12847330f729Sjoerg static void PrintCursorExtent(CXCursor C) {
12857330f729Sjoerg CXSourceRange extent = clang_getCursorExtent(C);
12867330f729Sjoerg PrintRange(extent, "Extent");
12877330f729Sjoerg }
12887330f729Sjoerg
12897330f729Sjoerg /* Data used by the visitors. */
12907330f729Sjoerg typedef struct {
12917330f729Sjoerg CXTranslationUnit TU;
12927330f729Sjoerg enum CXCursorKind *Filter;
12937330f729Sjoerg const char *CommentSchemaFile;
12947330f729Sjoerg } VisitorData;
12957330f729Sjoerg
12967330f729Sjoerg
FilteredPrintingVisitor(CXCursor Cursor,CXCursor Parent,CXClientData ClientData)12977330f729Sjoerg enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
12987330f729Sjoerg CXCursor Parent,
12997330f729Sjoerg CXClientData ClientData) {
13007330f729Sjoerg VisitorData *Data = (VisitorData *)ClientData;
13017330f729Sjoerg if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
13027330f729Sjoerg CXSourceLocation Loc = clang_getCursorLocation(Cursor);
13037330f729Sjoerg unsigned line, column;
13047330f729Sjoerg clang_getSpellingLocation(Loc, 0, &line, &column, 0);
13057330f729Sjoerg printf("// %s: %s:%d:%d: ", FileCheckPrefix,
13067330f729Sjoerg GetCursorSource(Cursor), line, column);
13077330f729Sjoerg PrintCursor(Cursor, Data->CommentSchemaFile);
13087330f729Sjoerg PrintCursorExtent(Cursor);
13097330f729Sjoerg if (clang_isDeclaration(Cursor.kind)) {
13107330f729Sjoerg enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
13117330f729Sjoerg const char *accessStr = 0;
13127330f729Sjoerg
13137330f729Sjoerg switch (access) {
13147330f729Sjoerg case CX_CXXInvalidAccessSpecifier: break;
13157330f729Sjoerg case CX_CXXPublic:
13167330f729Sjoerg accessStr = "public"; break;
13177330f729Sjoerg case CX_CXXProtected:
13187330f729Sjoerg accessStr = "protected"; break;
13197330f729Sjoerg case CX_CXXPrivate:
13207330f729Sjoerg accessStr = "private"; break;
13217330f729Sjoerg }
13227330f729Sjoerg
13237330f729Sjoerg if (accessStr)
13247330f729Sjoerg printf(" [access=%s]", accessStr);
13257330f729Sjoerg }
13267330f729Sjoerg printf("\n");
13277330f729Sjoerg return CXChildVisit_Recurse;
13287330f729Sjoerg }
13297330f729Sjoerg
13307330f729Sjoerg return CXChildVisit_Continue;
13317330f729Sjoerg }
13327330f729Sjoerg
FunctionScanVisitor(CXCursor Cursor,CXCursor Parent,CXClientData ClientData)13337330f729Sjoerg static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
13347330f729Sjoerg CXCursor Parent,
13357330f729Sjoerg CXClientData ClientData) {
13367330f729Sjoerg const char *startBuf, *endBuf;
13377330f729Sjoerg unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn;
13387330f729Sjoerg CXCursor Ref;
13397330f729Sjoerg VisitorData *Data = (VisitorData *)ClientData;
13407330f729Sjoerg
13417330f729Sjoerg if (Cursor.kind != CXCursor_FunctionDecl ||
13427330f729Sjoerg !clang_isCursorDefinition(Cursor))
13437330f729Sjoerg return CXChildVisit_Continue;
13447330f729Sjoerg
13457330f729Sjoerg clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,
13467330f729Sjoerg &startLine, &startColumn,
13477330f729Sjoerg &endLine, &endColumn);
13487330f729Sjoerg /* Probe the entire body, looking for both decls and refs. */
13497330f729Sjoerg curLine = startLine;
13507330f729Sjoerg curColumn = startColumn;
13517330f729Sjoerg
13527330f729Sjoerg while (startBuf < endBuf) {
13537330f729Sjoerg CXSourceLocation Loc;
13547330f729Sjoerg CXFile file;
13557330f729Sjoerg CXString source;
13567330f729Sjoerg
13577330f729Sjoerg if (*startBuf == '\n') {
13587330f729Sjoerg startBuf++;
13597330f729Sjoerg curLine++;
13607330f729Sjoerg curColumn = 1;
13617330f729Sjoerg } else if (*startBuf != '\t')
13627330f729Sjoerg curColumn++;
13637330f729Sjoerg
13647330f729Sjoerg Loc = clang_getCursorLocation(Cursor);
13657330f729Sjoerg clang_getSpellingLocation(Loc, &file, 0, 0, 0);
13667330f729Sjoerg
13677330f729Sjoerg source = clang_getFileName(file);
13687330f729Sjoerg if (clang_getCString(source)) {
13697330f729Sjoerg CXSourceLocation RefLoc
13707330f729Sjoerg = clang_getLocation(Data->TU, file, curLine, curColumn);
13717330f729Sjoerg Ref = clang_getCursor(Data->TU, RefLoc);
13727330f729Sjoerg if (Ref.kind == CXCursor_NoDeclFound) {
13737330f729Sjoerg /* Nothing found here; that's fine. */
13747330f729Sjoerg } else if (Ref.kind != CXCursor_FunctionDecl) {
13757330f729Sjoerg printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
13767330f729Sjoerg curLine, curColumn);
13777330f729Sjoerg PrintCursor(Ref, Data->CommentSchemaFile);
13787330f729Sjoerg printf("\n");
13797330f729Sjoerg }
13807330f729Sjoerg }
13817330f729Sjoerg clang_disposeString(source);
13827330f729Sjoerg startBuf++;
13837330f729Sjoerg }
13847330f729Sjoerg
13857330f729Sjoerg return CXChildVisit_Continue;
13867330f729Sjoerg }
13877330f729Sjoerg
13887330f729Sjoerg /******************************************************************************/
13897330f729Sjoerg /* USR testing. */
13907330f729Sjoerg /******************************************************************************/
13917330f729Sjoerg
USRVisitor(CXCursor C,CXCursor parent,CXClientData ClientData)13927330f729Sjoerg enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
13937330f729Sjoerg CXClientData ClientData) {
13947330f729Sjoerg VisitorData *Data = (VisitorData *)ClientData;
13957330f729Sjoerg if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
13967330f729Sjoerg CXString USR = clang_getCursorUSR(C);
13977330f729Sjoerg const char *cstr = clang_getCString(USR);
13987330f729Sjoerg if (!cstr || cstr[0] == '\0') {
13997330f729Sjoerg clang_disposeString(USR);
14007330f729Sjoerg return CXChildVisit_Recurse;
14017330f729Sjoerg }
14027330f729Sjoerg printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr);
14037330f729Sjoerg
14047330f729Sjoerg PrintCursorExtent(C);
14057330f729Sjoerg printf("\n");
14067330f729Sjoerg clang_disposeString(USR);
14077330f729Sjoerg
14087330f729Sjoerg return CXChildVisit_Recurse;
14097330f729Sjoerg }
14107330f729Sjoerg
14117330f729Sjoerg return CXChildVisit_Continue;
14127330f729Sjoerg }
14137330f729Sjoerg
14147330f729Sjoerg /******************************************************************************/
14157330f729Sjoerg /* Inclusion stack testing. */
14167330f729Sjoerg /******************************************************************************/
14177330f729Sjoerg
InclusionVisitor(CXFile includedFile,CXSourceLocation * includeStack,unsigned includeStackLen,CXClientData data)14187330f729Sjoerg void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack,
14197330f729Sjoerg unsigned includeStackLen, CXClientData data) {
14207330f729Sjoerg
14217330f729Sjoerg unsigned i;
14227330f729Sjoerg CXString fname;
14237330f729Sjoerg
14247330f729Sjoerg fname = clang_getFileName(includedFile);
14257330f729Sjoerg printf("file: %s\nincluded by:\n", clang_getCString(fname));
14267330f729Sjoerg clang_disposeString(fname);
14277330f729Sjoerg
14287330f729Sjoerg for (i = 0; i < includeStackLen; ++i) {
14297330f729Sjoerg CXFile includingFile;
14307330f729Sjoerg unsigned line, column;
14317330f729Sjoerg clang_getSpellingLocation(includeStack[i], &includingFile, &line,
14327330f729Sjoerg &column, 0);
14337330f729Sjoerg fname = clang_getFileName(includingFile);
14347330f729Sjoerg printf(" %s:%d:%d\n", clang_getCString(fname), line, column);
14357330f729Sjoerg clang_disposeString(fname);
14367330f729Sjoerg }
14377330f729Sjoerg printf("\n");
14387330f729Sjoerg }
14397330f729Sjoerg
PrintInclusionStack(CXTranslationUnit TU)14407330f729Sjoerg void PrintInclusionStack(CXTranslationUnit TU) {
14417330f729Sjoerg clang_getInclusions(TU, InclusionVisitor, NULL);
14427330f729Sjoerg }
14437330f729Sjoerg
14447330f729Sjoerg /******************************************************************************/
14457330f729Sjoerg /* Linkage testing. */
14467330f729Sjoerg /******************************************************************************/
14477330f729Sjoerg
PrintLinkage(CXCursor cursor,CXCursor p,CXClientData d)14487330f729Sjoerg static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
14497330f729Sjoerg CXClientData d) {
14507330f729Sjoerg const char *linkage = 0;
14517330f729Sjoerg
14527330f729Sjoerg if (clang_isInvalid(clang_getCursorKind(cursor)))
14537330f729Sjoerg return CXChildVisit_Recurse;
14547330f729Sjoerg
14557330f729Sjoerg switch (clang_getCursorLinkage(cursor)) {
14567330f729Sjoerg case CXLinkage_Invalid: break;
14577330f729Sjoerg case CXLinkage_NoLinkage: linkage = "NoLinkage"; break;
14587330f729Sjoerg case CXLinkage_Internal: linkage = "Internal"; break;
14597330f729Sjoerg case CXLinkage_UniqueExternal: linkage = "UniqueExternal"; break;
14607330f729Sjoerg case CXLinkage_External: linkage = "External"; break;
14617330f729Sjoerg }
14627330f729Sjoerg
14637330f729Sjoerg if (linkage) {
14647330f729Sjoerg PrintCursor(cursor, NULL);
14657330f729Sjoerg printf("linkage=%s\n", linkage);
14667330f729Sjoerg }
14677330f729Sjoerg
14687330f729Sjoerg return CXChildVisit_Recurse;
14697330f729Sjoerg }
14707330f729Sjoerg
14717330f729Sjoerg /******************************************************************************/
14727330f729Sjoerg /* Visibility testing. */
14737330f729Sjoerg /******************************************************************************/
14747330f729Sjoerg
PrintVisibility(CXCursor cursor,CXCursor p,CXClientData d)14757330f729Sjoerg static enum CXChildVisitResult PrintVisibility(CXCursor cursor, CXCursor p,
14767330f729Sjoerg CXClientData d) {
14777330f729Sjoerg const char *visibility = 0;
14787330f729Sjoerg
14797330f729Sjoerg if (clang_isInvalid(clang_getCursorKind(cursor)))
14807330f729Sjoerg return CXChildVisit_Recurse;
14817330f729Sjoerg
14827330f729Sjoerg switch (clang_getCursorVisibility(cursor)) {
14837330f729Sjoerg case CXVisibility_Invalid: break;
14847330f729Sjoerg case CXVisibility_Hidden: visibility = "Hidden"; break;
14857330f729Sjoerg case CXVisibility_Protected: visibility = "Protected"; break;
14867330f729Sjoerg case CXVisibility_Default: visibility = "Default"; break;
14877330f729Sjoerg }
14887330f729Sjoerg
14897330f729Sjoerg if (visibility) {
14907330f729Sjoerg PrintCursor(cursor, NULL);
14917330f729Sjoerg printf("visibility=%s\n", visibility);
14927330f729Sjoerg }
14937330f729Sjoerg
14947330f729Sjoerg return CXChildVisit_Recurse;
14957330f729Sjoerg }
14967330f729Sjoerg
14977330f729Sjoerg /******************************************************************************/
14987330f729Sjoerg /* Typekind testing. */
14997330f729Sjoerg /******************************************************************************/
15007330f729Sjoerg
PrintTypeAndTypeKind(CXType T,const char * Format)15017330f729Sjoerg static void PrintTypeAndTypeKind(CXType T, const char *Format) {
15027330f729Sjoerg CXString TypeSpelling, TypeKindSpelling;
15037330f729Sjoerg
15047330f729Sjoerg TypeSpelling = clang_getTypeSpelling(T);
15057330f729Sjoerg TypeKindSpelling = clang_getTypeKindSpelling(T.kind);
15067330f729Sjoerg printf(Format,
15077330f729Sjoerg clang_getCString(TypeSpelling),
15087330f729Sjoerg clang_getCString(TypeKindSpelling));
15097330f729Sjoerg clang_disposeString(TypeSpelling);
15107330f729Sjoerg clang_disposeString(TypeKindSpelling);
15117330f729Sjoerg }
15127330f729Sjoerg
FieldVisitor(CXCursor C,CXClientData client_data)15137330f729Sjoerg static enum CXVisitorResult FieldVisitor(CXCursor C,
15147330f729Sjoerg CXClientData client_data) {
15157330f729Sjoerg (*(int *) client_data)+=1;
15167330f729Sjoerg return CXVisit_Continue;
15177330f729Sjoerg }
15187330f729Sjoerg
PrintTypeTemplateArgs(CXType T,const char * Format)15197330f729Sjoerg static void PrintTypeTemplateArgs(CXType T, const char *Format) {
15207330f729Sjoerg int NumTArgs = clang_Type_getNumTemplateArguments(T);
15217330f729Sjoerg if (NumTArgs != -1 && NumTArgs != 0) {
15227330f729Sjoerg int i;
15237330f729Sjoerg CXType TArg;
15247330f729Sjoerg printf(Format, NumTArgs);
15257330f729Sjoerg for (i = 0; i < NumTArgs; ++i) {
15267330f729Sjoerg TArg = clang_Type_getTemplateArgumentAsType(T, i);
15277330f729Sjoerg if (TArg.kind != CXType_Invalid) {
15287330f729Sjoerg PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]");
15297330f729Sjoerg }
15307330f729Sjoerg }
15317330f729Sjoerg /* Ensure that the returned type is invalid when indexing off-by-one. */
15327330f729Sjoerg TArg = clang_Type_getTemplateArgumentAsType(T, i);
15337330f729Sjoerg assert(TArg.kind == CXType_Invalid);
15347330f729Sjoerg printf("]");
15357330f729Sjoerg }
15367330f729Sjoerg }
15377330f729Sjoerg
PrintNullabilityKind(CXType T,const char * Format)15387330f729Sjoerg static void PrintNullabilityKind(CXType T, const char *Format) {
15397330f729Sjoerg enum CXTypeNullabilityKind N = clang_Type_getNullability(T);
15407330f729Sjoerg
15417330f729Sjoerg const char *nullability = 0;
15427330f729Sjoerg switch (N) {
1543*e038c9c4Sjoerg case CXTypeNullability_NonNull:
1544*e038c9c4Sjoerg nullability = "nonnull";
1545*e038c9c4Sjoerg break;
1546*e038c9c4Sjoerg case CXTypeNullability_Nullable:
1547*e038c9c4Sjoerg nullability = "nullable";
1548*e038c9c4Sjoerg break;
1549*e038c9c4Sjoerg case CXTypeNullability_NullableResult:
1550*e038c9c4Sjoerg nullability = "nullable_result";
1551*e038c9c4Sjoerg break;
1552*e038c9c4Sjoerg case CXTypeNullability_Unspecified:
1553*e038c9c4Sjoerg nullability = "unspecified";
1554*e038c9c4Sjoerg break;
1555*e038c9c4Sjoerg case CXTypeNullability_Invalid:
1556*e038c9c4Sjoerg break;
15577330f729Sjoerg }
15587330f729Sjoerg
15597330f729Sjoerg if (nullability) {
15607330f729Sjoerg printf(Format, nullability);
15617330f729Sjoerg }
15627330f729Sjoerg }
15637330f729Sjoerg
PrintType(CXCursor cursor,CXCursor p,CXClientData d)15647330f729Sjoerg static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
15657330f729Sjoerg CXClientData d) {
15667330f729Sjoerg if (!clang_isInvalid(clang_getCursorKind(cursor))) {
15677330f729Sjoerg CXType T = clang_getCursorType(cursor);
15687330f729Sjoerg CXType PT = clang_getPointeeType(T);
15697330f729Sjoerg enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T);
15707330f729Sjoerg PrintCursor(cursor, NULL);
15717330f729Sjoerg PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
15727330f729Sjoerg PrintNullabilityKind(T, " [nullability=%s]");
15737330f729Sjoerg if (clang_isConstQualifiedType(T))
15747330f729Sjoerg printf(" const");
15757330f729Sjoerg if (clang_isVolatileQualifiedType(T))
15767330f729Sjoerg printf(" volatile");
15777330f729Sjoerg if (clang_isRestrictQualifiedType(T))
15787330f729Sjoerg printf(" restrict");
15797330f729Sjoerg if (RQ == CXRefQualifier_LValue)
15807330f729Sjoerg printf(" lvalue-ref-qualifier");
15817330f729Sjoerg if (RQ == CXRefQualifier_RValue)
15827330f729Sjoerg printf(" rvalue-ref-qualifier");
15837330f729Sjoerg /* Print the template argument types if they exist. */
15847330f729Sjoerg PrintTypeTemplateArgs(T, " [templateargs/%d=");
15857330f729Sjoerg /* Print the canonical type if it is different. */
15867330f729Sjoerg {
15877330f729Sjoerg CXType CT = clang_getCanonicalType(T);
15887330f729Sjoerg if (!clang_equalTypes(T, CT)) {
15897330f729Sjoerg PrintTypeAndTypeKind(CT, " [canonicaltype=%s] [canonicaltypekind=%s]");
15907330f729Sjoerg PrintTypeTemplateArgs(CT, " [canonicaltemplateargs/%d=");
15917330f729Sjoerg }
15927330f729Sjoerg }
1593*e038c9c4Sjoerg /* Print the value type if it exists. */
1594*e038c9c4Sjoerg {
1595*e038c9c4Sjoerg CXType VT = clang_Type_getValueType(T);
1596*e038c9c4Sjoerg if (VT.kind != CXType_Invalid)
1597*e038c9c4Sjoerg PrintTypeAndTypeKind(VT, " [valuetype=%s] [valuetypekind=%s]");
1598*e038c9c4Sjoerg }
15997330f729Sjoerg /* Print the modified type if it exists. */
16007330f729Sjoerg {
16017330f729Sjoerg CXType MT = clang_Type_getModifiedType(T);
16027330f729Sjoerg if (MT.kind != CXType_Invalid) {
16037330f729Sjoerg PrintTypeAndTypeKind(MT, " [modifiedtype=%s] [modifiedtypekind=%s]");
16047330f729Sjoerg }
16057330f729Sjoerg }
16067330f729Sjoerg /* Print the return type if it exists. */
16077330f729Sjoerg {
16087330f729Sjoerg CXType RT = clang_getCursorResultType(cursor);
16097330f729Sjoerg if (RT.kind != CXType_Invalid) {
16107330f729Sjoerg PrintTypeAndTypeKind(RT, " [resulttype=%s] [resulttypekind=%s]");
16117330f729Sjoerg }
16127330f729Sjoerg PrintNullabilityKind(RT, " [resultnullability=%s]");
16137330f729Sjoerg }
16147330f729Sjoerg /* Print the argument types if they exist. */
16157330f729Sjoerg {
16167330f729Sjoerg int NumArgs = clang_Cursor_getNumArguments(cursor);
16177330f729Sjoerg if (NumArgs != -1 && NumArgs != 0) {
16187330f729Sjoerg int i;
16197330f729Sjoerg printf(" [args=");
16207330f729Sjoerg for (i = 0; i < NumArgs; ++i) {
16217330f729Sjoerg CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i));
16227330f729Sjoerg if (T.kind != CXType_Invalid) {
16237330f729Sjoerg PrintTypeAndTypeKind(T, " [%s] [%s]");
16247330f729Sjoerg PrintNullabilityKind(T, " [%s]");
16257330f729Sjoerg }
16267330f729Sjoerg }
16277330f729Sjoerg printf("]");
16287330f729Sjoerg }
16297330f729Sjoerg }
16307330f729Sjoerg /* Print ObjC base types, type arguments, and protocol list if available. */
16317330f729Sjoerg {
16327330f729Sjoerg CXType BT = clang_Type_getObjCObjectBaseType(PT);
16337330f729Sjoerg if (BT.kind != CXType_Invalid) {
16347330f729Sjoerg PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]");
16357330f729Sjoerg }
16367330f729Sjoerg }
16377330f729Sjoerg {
16387330f729Sjoerg unsigned NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT);
16397330f729Sjoerg if (NumTypeArgs > 0) {
16407330f729Sjoerg unsigned i;
16417330f729Sjoerg printf(" [typeargs=");
16427330f729Sjoerg for (i = 0; i < NumTypeArgs; ++i) {
16437330f729Sjoerg CXType TA = clang_Type_getObjCTypeArg(PT, i);
16447330f729Sjoerg if (TA.kind != CXType_Invalid) {
16457330f729Sjoerg PrintTypeAndTypeKind(TA, " [%s] [%s]");
16467330f729Sjoerg }
16477330f729Sjoerg }
16487330f729Sjoerg printf("]");
16497330f729Sjoerg }
16507330f729Sjoerg }
16517330f729Sjoerg {
16527330f729Sjoerg unsigned NumProtocols = clang_Type_getNumObjCProtocolRefs(PT);
16537330f729Sjoerg if (NumProtocols > 0) {
16547330f729Sjoerg unsigned i;
16557330f729Sjoerg printf(" [protocols=");
16567330f729Sjoerg for (i = 0; i < NumProtocols; ++i) {
16577330f729Sjoerg CXCursor P = clang_Type_getObjCProtocolDecl(PT, i);
16587330f729Sjoerg if (!clang_isInvalid(clang_getCursorKind(P))) {
16597330f729Sjoerg PrintCursor(P, NULL);
16607330f729Sjoerg }
16617330f729Sjoerg }
16627330f729Sjoerg printf("]");
16637330f729Sjoerg }
16647330f729Sjoerg }
16657330f729Sjoerg /* Print if this is a non-POD type. */
16667330f729Sjoerg printf(" [isPOD=%d]", clang_isPODType(T));
16677330f729Sjoerg /* Print the pointee type. */
16687330f729Sjoerg {
16697330f729Sjoerg if (PT.kind != CXType_Invalid) {
16707330f729Sjoerg PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]");
16717330f729Sjoerg }
16727330f729Sjoerg }
16737330f729Sjoerg /* Print the number of fields if they exist. */
16747330f729Sjoerg {
16757330f729Sjoerg int numFields = 0;
16767330f729Sjoerg if (clang_Type_visitFields(T, FieldVisitor, &numFields)){
16777330f729Sjoerg if (numFields != 0) {
16787330f729Sjoerg printf(" [nbFields=%d]", numFields);
16797330f729Sjoerg }
16807330f729Sjoerg }
16817330f729Sjoerg }
16827330f729Sjoerg
16837330f729Sjoerg /* Print if it is an anonymous record or namespace. */
16847330f729Sjoerg {
16857330f729Sjoerg unsigned isAnon = clang_Cursor_isAnonymous(cursor);
16867330f729Sjoerg if (isAnon != 0) {
16877330f729Sjoerg printf(" [isAnon=%d]", isAnon);
16887330f729Sjoerg }
16897330f729Sjoerg }
16907330f729Sjoerg
16917330f729Sjoerg /* Print if it is an anonymous record decl */
16927330f729Sjoerg {
16937330f729Sjoerg unsigned isAnonRecDecl = clang_Cursor_isAnonymousRecordDecl(cursor);
16947330f729Sjoerg printf(" [isAnonRecDecl=%d]", isAnonRecDecl);
16957330f729Sjoerg }
16967330f729Sjoerg
16977330f729Sjoerg /* Print if it is an inline namespace decl */
16987330f729Sjoerg {
16997330f729Sjoerg unsigned isInlineNamespace = clang_Cursor_isInlineNamespace(cursor);
17007330f729Sjoerg if (isInlineNamespace != 0)
17017330f729Sjoerg printf(" [isInlineNamespace=%d]", isInlineNamespace);
17027330f729Sjoerg }
17037330f729Sjoerg
17047330f729Sjoerg printf("\n");
17057330f729Sjoerg }
17067330f729Sjoerg return CXChildVisit_Recurse;
17077330f729Sjoerg }
17087330f729Sjoerg
PrintSingleTypeSize(CXType T,const char * TypeKindFormat,const char * SizeFormat,const char * AlignFormat)17097330f729Sjoerg static void PrintSingleTypeSize(CXType T, const char *TypeKindFormat,
17107330f729Sjoerg const char *SizeFormat,
17117330f729Sjoerg const char *AlignFormat) {
17127330f729Sjoerg PrintTypeAndTypeKind(T, TypeKindFormat);
17137330f729Sjoerg /* Print the type sizeof if applicable. */
17147330f729Sjoerg {
17157330f729Sjoerg long long Size = clang_Type_getSizeOf(T);
17167330f729Sjoerg if (Size >= 0 || Size < -1 ) {
17177330f729Sjoerg printf(SizeFormat, Size);
17187330f729Sjoerg }
17197330f729Sjoerg }
17207330f729Sjoerg /* Print the type alignof if applicable. */
17217330f729Sjoerg {
17227330f729Sjoerg long long Align = clang_Type_getAlignOf(T);
17237330f729Sjoerg if (Align >= 0 || Align < -1) {
17247330f729Sjoerg printf(AlignFormat, Align);
17257330f729Sjoerg }
17267330f729Sjoerg }
17277330f729Sjoerg
17287330f729Sjoerg /* Print the return type if it exists. */
17297330f729Sjoerg {
17307330f729Sjoerg CXType RT = clang_getResultType(T);
17317330f729Sjoerg if (RT.kind != CXType_Invalid)
17327330f729Sjoerg PrintSingleTypeSize(RT, " [resulttype=%s] [resulttypekind=%s]",
17337330f729Sjoerg " [resultsizeof=%lld]", " [resultalignof=%lld]");
17347330f729Sjoerg }
17357330f729Sjoerg }
17367330f729Sjoerg
PrintTypeSize(CXCursor cursor,CXCursor p,CXClientData d)17377330f729Sjoerg static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p,
17387330f729Sjoerg CXClientData d) {
17397330f729Sjoerg CXType T;
17407330f729Sjoerg enum CXCursorKind K = clang_getCursorKind(cursor);
17417330f729Sjoerg if (clang_isInvalid(K))
17427330f729Sjoerg return CXChildVisit_Recurse;
17437330f729Sjoerg T = clang_getCursorType(cursor);
17447330f729Sjoerg PrintCursor(cursor, NULL);
17457330f729Sjoerg PrintSingleTypeSize(T, " [type=%s] [typekind=%s]", " [sizeof=%lld]",
17467330f729Sjoerg " [alignof=%lld]");
17477330f729Sjoerg /* Print the record field offset if applicable. */
17487330f729Sjoerg {
17497330f729Sjoerg CXString FieldSpelling = clang_getCursorSpelling(cursor);
17507330f729Sjoerg const char *FieldName = clang_getCString(FieldSpelling);
17517330f729Sjoerg /* recurse to get the first parent record that is not anonymous. */
17527330f729Sjoerg unsigned RecordIsAnonymous = 0;
17537330f729Sjoerg if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) {
17547330f729Sjoerg CXCursor Record;
17557330f729Sjoerg CXCursor Parent = p;
17567330f729Sjoerg do {
17577330f729Sjoerg Record = Parent;
17587330f729Sjoerg Parent = clang_getCursorSemanticParent(Record);
17597330f729Sjoerg RecordIsAnonymous = clang_Cursor_isAnonymous(Record);
17607330f729Sjoerg /* Recurse as long as the parent is a CXType_Record and the Record
17617330f729Sjoerg is anonymous */
17627330f729Sjoerg } while ( clang_getCursorType(Parent).kind == CXType_Record &&
17637330f729Sjoerg RecordIsAnonymous > 0);
17647330f729Sjoerg {
17657330f729Sjoerg long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Record),
17667330f729Sjoerg FieldName);
17677330f729Sjoerg long long Offset2 = clang_Cursor_getOffsetOfField(cursor);
17687330f729Sjoerg if (Offset == Offset2){
17697330f729Sjoerg printf(" [offsetof=%lld]", Offset);
17707330f729Sjoerg } else {
17717330f729Sjoerg /* Offsets will be different in anonymous records. */
17727330f729Sjoerg printf(" [offsetof=%lld/%lld]", Offset, Offset2);
17737330f729Sjoerg }
17747330f729Sjoerg }
17757330f729Sjoerg }
17767330f729Sjoerg clang_disposeString(FieldSpelling);
17777330f729Sjoerg }
17787330f729Sjoerg /* Print if its a bitfield */
17797330f729Sjoerg {
17807330f729Sjoerg int IsBitfield = clang_Cursor_isBitField(cursor);
17817330f729Sjoerg if (IsBitfield)
17827330f729Sjoerg printf(" [BitFieldSize=%d]", clang_getFieldDeclBitWidth(cursor));
17837330f729Sjoerg }
17847330f729Sjoerg
17857330f729Sjoerg printf("\n");
17867330f729Sjoerg
17877330f729Sjoerg return CXChildVisit_Recurse;
17887330f729Sjoerg }
17897330f729Sjoerg
17907330f729Sjoerg /******************************************************************************/
17917330f729Sjoerg /* Mangling testing. */
17927330f729Sjoerg /******************************************************************************/
17937330f729Sjoerg
PrintMangledName(CXCursor cursor,CXCursor p,CXClientData d)17947330f729Sjoerg static enum CXChildVisitResult PrintMangledName(CXCursor cursor, CXCursor p,
17957330f729Sjoerg CXClientData d) {
17967330f729Sjoerg CXString MangledName;
17977330f729Sjoerg if (clang_isUnexposed(clang_getCursorKind(cursor)))
17987330f729Sjoerg return CXChildVisit_Recurse;
17997330f729Sjoerg PrintCursor(cursor, NULL);
18007330f729Sjoerg MangledName = clang_Cursor_getMangling(cursor);
18017330f729Sjoerg printf(" [mangled=%s]\n", clang_getCString(MangledName));
18027330f729Sjoerg clang_disposeString(MangledName);
18037330f729Sjoerg return CXChildVisit_Continue;
18047330f729Sjoerg }
18057330f729Sjoerg
PrintManglings(CXCursor cursor,CXCursor p,CXClientData d)18067330f729Sjoerg static enum CXChildVisitResult PrintManglings(CXCursor cursor, CXCursor p,
18077330f729Sjoerg CXClientData d) {
18087330f729Sjoerg unsigned I, E;
18097330f729Sjoerg CXStringSet *Manglings = NULL;
18107330f729Sjoerg if (clang_isUnexposed(clang_getCursorKind(cursor)))
18117330f729Sjoerg return CXChildVisit_Recurse;
18127330f729Sjoerg if (!clang_isDeclaration(clang_getCursorKind(cursor)))
18137330f729Sjoerg return CXChildVisit_Recurse;
18147330f729Sjoerg if (clang_getCursorKind(cursor) == CXCursor_ParmDecl)
18157330f729Sjoerg return CXChildVisit_Continue;
18167330f729Sjoerg PrintCursor(cursor, NULL);
18177330f729Sjoerg Manglings = clang_Cursor_getCXXManglings(cursor);
18187330f729Sjoerg if (Manglings) {
18197330f729Sjoerg for (I = 0, E = Manglings->Count; I < E; ++I)
18207330f729Sjoerg printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I]));
18217330f729Sjoerg clang_disposeStringSet(Manglings);
18227330f729Sjoerg printf("\n");
18237330f729Sjoerg }
18247330f729Sjoerg Manglings = clang_Cursor_getObjCManglings(cursor);
18257330f729Sjoerg if (Manglings) {
18267330f729Sjoerg for (I = 0, E = Manglings->Count; I < E; ++I)
18277330f729Sjoerg printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I]));
18287330f729Sjoerg clang_disposeStringSet(Manglings);
18297330f729Sjoerg printf("\n");
18307330f729Sjoerg }
18317330f729Sjoerg return CXChildVisit_Recurse;
18327330f729Sjoerg }
18337330f729Sjoerg
18347330f729Sjoerg /******************************************************************************/
18357330f729Sjoerg /* Bitwidth testing. */
18367330f729Sjoerg /******************************************************************************/
18377330f729Sjoerg
PrintBitWidth(CXCursor cursor,CXCursor p,CXClientData d)18387330f729Sjoerg static enum CXChildVisitResult PrintBitWidth(CXCursor cursor, CXCursor p,
18397330f729Sjoerg CXClientData d) {
18407330f729Sjoerg int Bitwidth;
18417330f729Sjoerg if (clang_getCursorKind(cursor) != CXCursor_FieldDecl)
18427330f729Sjoerg return CXChildVisit_Recurse;
18437330f729Sjoerg
18447330f729Sjoerg Bitwidth = clang_getFieldDeclBitWidth(cursor);
18457330f729Sjoerg if (Bitwidth >= 0) {
18467330f729Sjoerg PrintCursor(cursor, NULL);
18477330f729Sjoerg printf(" bitwidth=%d\n", Bitwidth);
18487330f729Sjoerg }
18497330f729Sjoerg
18507330f729Sjoerg return CXChildVisit_Recurse;
18517330f729Sjoerg }
18527330f729Sjoerg
18537330f729Sjoerg /******************************************************************************/
18547330f729Sjoerg /* Type declaration testing */
18557330f729Sjoerg /******************************************************************************/
18567330f729Sjoerg
PrintTypeDeclaration(CXCursor cursor,CXCursor p,CXClientData d)18577330f729Sjoerg static enum CXChildVisitResult PrintTypeDeclaration(CXCursor cursor, CXCursor p,
18587330f729Sjoerg CXClientData d) {
18597330f729Sjoerg CXCursor typeDeclaration = clang_getTypeDeclaration(clang_getCursorType(cursor));
18607330f729Sjoerg
18617330f729Sjoerg if (clang_isDeclaration(typeDeclaration.kind)) {
18627330f729Sjoerg PrintCursor(cursor, NULL);
18637330f729Sjoerg PrintTypeAndTypeKind(clang_getCursorType(typeDeclaration), " [typedeclaration=%s] [typekind=%s]\n");
18647330f729Sjoerg }
18657330f729Sjoerg
18667330f729Sjoerg return CXChildVisit_Recurse;
18677330f729Sjoerg }
18687330f729Sjoerg
18697330f729Sjoerg /******************************************************************************/
18707330f729Sjoerg /* Declaration attributes testing */
18717330f729Sjoerg /******************************************************************************/
18727330f729Sjoerg
PrintDeclAttributes(CXCursor cursor,CXCursor p,CXClientData d)18737330f729Sjoerg static enum CXChildVisitResult PrintDeclAttributes(CXCursor cursor, CXCursor p,
18747330f729Sjoerg CXClientData d) {
18757330f729Sjoerg if (clang_isDeclaration(cursor.kind)) {
18767330f729Sjoerg printf("\n");
18777330f729Sjoerg PrintCursor(cursor, NULL);
18787330f729Sjoerg return CXChildVisit_Recurse;
18797330f729Sjoerg } else if (clang_isAttribute(cursor.kind)) {
18807330f729Sjoerg printf(" ");
18817330f729Sjoerg PrintCursor(cursor, NULL);
18827330f729Sjoerg }
18837330f729Sjoerg return CXChildVisit_Continue;
18847330f729Sjoerg }
18857330f729Sjoerg
18867330f729Sjoerg /******************************************************************************/
18877330f729Sjoerg /* Target information testing. */
18887330f729Sjoerg /******************************************************************************/
18897330f729Sjoerg
print_target_info(int argc,const char ** argv)18907330f729Sjoerg static int print_target_info(int argc, const char **argv) {
18917330f729Sjoerg CXIndex Idx;
18927330f729Sjoerg CXTranslationUnit TU;
18937330f729Sjoerg CXTargetInfo TargetInfo;
18947330f729Sjoerg CXString Triple;
18957330f729Sjoerg const char *FileName;
18967330f729Sjoerg enum CXErrorCode Err;
18977330f729Sjoerg int PointerWidth;
18987330f729Sjoerg
18997330f729Sjoerg if (argc == 0) {
19007330f729Sjoerg fprintf(stderr, "No filename specified\n");
19017330f729Sjoerg return 1;
19027330f729Sjoerg }
19037330f729Sjoerg
19047330f729Sjoerg FileName = argv[1];
19057330f729Sjoerg
19067330f729Sjoerg Idx = clang_createIndex(0, 1);
19077330f729Sjoerg Err = clang_parseTranslationUnit2(Idx, FileName, argv, argc, NULL, 0,
19087330f729Sjoerg getDefaultParsingOptions(), &TU);
19097330f729Sjoerg if (Err != CXError_Success) {
19107330f729Sjoerg fprintf(stderr, "Couldn't parse translation unit!\n");
19117330f729Sjoerg describeLibclangFailure(Err);
19127330f729Sjoerg clang_disposeIndex(Idx);
19137330f729Sjoerg return 1;
19147330f729Sjoerg }
19157330f729Sjoerg
19167330f729Sjoerg TargetInfo = clang_getTranslationUnitTargetInfo(TU);
19177330f729Sjoerg
19187330f729Sjoerg Triple = clang_TargetInfo_getTriple(TargetInfo);
19197330f729Sjoerg printf("TargetTriple: %s\n", clang_getCString(Triple));
19207330f729Sjoerg clang_disposeString(Triple);
19217330f729Sjoerg
19227330f729Sjoerg PointerWidth = clang_TargetInfo_getPointerWidth(TargetInfo);
19237330f729Sjoerg printf("PointerWidth: %d\n", PointerWidth);
19247330f729Sjoerg
19257330f729Sjoerg clang_TargetInfo_dispose(TargetInfo);
19267330f729Sjoerg clang_disposeTranslationUnit(TU);
19277330f729Sjoerg clang_disposeIndex(Idx);
19287330f729Sjoerg return 0;
19297330f729Sjoerg }
19307330f729Sjoerg
19317330f729Sjoerg /******************************************************************************/
19327330f729Sjoerg /* Loading ASTs/source. */
19337330f729Sjoerg /******************************************************************************/
19347330f729Sjoerg
perform_test_load(CXIndex Idx,CXTranslationUnit TU,const char * filter,const char * prefix,CXCursorVisitor Visitor,PostVisitTU PV,const char * CommentSchemaFile)19357330f729Sjoerg static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
19367330f729Sjoerg const char *filter, const char *prefix,
19377330f729Sjoerg CXCursorVisitor Visitor,
19387330f729Sjoerg PostVisitTU PV,
19397330f729Sjoerg const char *CommentSchemaFile) {
19407330f729Sjoerg
19417330f729Sjoerg if (prefix)
19427330f729Sjoerg FileCheckPrefix = prefix;
19437330f729Sjoerg
19447330f729Sjoerg if (Visitor) {
19457330f729Sjoerg enum CXCursorKind K = CXCursor_NotImplemented;
19467330f729Sjoerg enum CXCursorKind *ck = &K;
19477330f729Sjoerg VisitorData Data;
19487330f729Sjoerg
19497330f729Sjoerg /* Perform some simple filtering. */
19507330f729Sjoerg if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
19517330f729Sjoerg else if (!strcmp(filter, "all-display") ||
19527330f729Sjoerg !strcmp(filter, "local-display")) {
19537330f729Sjoerg ck = NULL;
19547330f729Sjoerg wanted_display_type = DisplayType_DisplayName;
19557330f729Sjoerg }
19567330f729Sjoerg else if (!strcmp(filter, "all-pretty") ||
19577330f729Sjoerg !strcmp(filter, "local-pretty")) {
19587330f729Sjoerg ck = NULL;
19597330f729Sjoerg wanted_display_type = DisplayType_Pretty;
19607330f729Sjoerg }
19617330f729Sjoerg else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
19627330f729Sjoerg else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
19637330f729Sjoerg else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
19647330f729Sjoerg else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
19657330f729Sjoerg else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
19667330f729Sjoerg else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
19677330f729Sjoerg else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor;
19687330f729Sjoerg else {
19697330f729Sjoerg fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
19707330f729Sjoerg return 1;
19717330f729Sjoerg }
19727330f729Sjoerg
19737330f729Sjoerg Data.TU = TU;
19747330f729Sjoerg Data.Filter = ck;
19757330f729Sjoerg Data.CommentSchemaFile = CommentSchemaFile;
19767330f729Sjoerg clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data);
19777330f729Sjoerg }
19787330f729Sjoerg
19797330f729Sjoerg if (PV)
19807330f729Sjoerg PV(TU);
19817330f729Sjoerg
19827330f729Sjoerg PrintDiagnostics(TU);
19837330f729Sjoerg if (checkForErrors(TU) != 0) {
19847330f729Sjoerg clang_disposeTranslationUnit(TU);
19857330f729Sjoerg return -1;
19867330f729Sjoerg }
19877330f729Sjoerg
19887330f729Sjoerg clang_disposeTranslationUnit(TU);
19897330f729Sjoerg return 0;
19907330f729Sjoerg }
19917330f729Sjoerg
perform_test_load_tu(const char * file,const char * filter,const char * prefix,CXCursorVisitor Visitor,PostVisitTU PV)19927330f729Sjoerg int perform_test_load_tu(const char *file, const char *filter,
19937330f729Sjoerg const char *prefix, CXCursorVisitor Visitor,
19947330f729Sjoerg PostVisitTU PV) {
19957330f729Sjoerg CXIndex Idx;
19967330f729Sjoerg CXTranslationUnit TU;
19977330f729Sjoerg int result;
19987330f729Sjoerg Idx = clang_createIndex(/* excludeDeclsFromPCH */
19997330f729Sjoerg !strcmp(filter, "local") ? 1 : 0,
20007330f729Sjoerg /* displayDiagnostics=*/1);
20017330f729Sjoerg
20027330f729Sjoerg if (!CreateTranslationUnit(Idx, file, &TU)) {
20037330f729Sjoerg clang_disposeIndex(Idx);
20047330f729Sjoerg return 1;
20057330f729Sjoerg }
20067330f729Sjoerg
20077330f729Sjoerg result = perform_test_load(Idx, TU, filter, prefix, Visitor, PV, NULL);
20087330f729Sjoerg clang_disposeIndex(Idx);
20097330f729Sjoerg return result;
20107330f729Sjoerg }
20117330f729Sjoerg
perform_test_load_source(int argc,const char ** argv,const char * filter,CXCursorVisitor Visitor,PostVisitTU PV)20127330f729Sjoerg int perform_test_load_source(int argc, const char **argv,
20137330f729Sjoerg const char *filter, CXCursorVisitor Visitor,
20147330f729Sjoerg PostVisitTU PV) {
20157330f729Sjoerg CXIndex Idx;
20167330f729Sjoerg CXTranslationUnit TU;
20177330f729Sjoerg const char *CommentSchemaFile;
20187330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
20197330f729Sjoerg int num_unsaved_files = 0;
20207330f729Sjoerg enum CXErrorCode Err;
20217330f729Sjoerg int result;
20227330f729Sjoerg unsigned Repeats = 0;
20237330f729Sjoerg unsigned I;
20247330f729Sjoerg const char *InvocationPath;
20257330f729Sjoerg
20267330f729Sjoerg Idx = clang_createIndex(/* excludeDeclsFromPCH */
20277330f729Sjoerg (!strcmp(filter, "local") ||
20287330f729Sjoerg !strcmp(filter, "local-display") ||
20297330f729Sjoerg !strcmp(filter, "local-pretty"))
20307330f729Sjoerg ? 1
20317330f729Sjoerg : 0,
20327330f729Sjoerg /* displayDiagnostics=*/1);
20337330f729Sjoerg InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH");
20347330f729Sjoerg if (InvocationPath)
20357330f729Sjoerg clang_CXIndex_setInvocationEmissionPathOption(Idx, InvocationPath);
20367330f729Sjoerg
20377330f729Sjoerg if ((CommentSchemaFile = parse_comments_schema(argc, argv))) {
20387330f729Sjoerg argc--;
20397330f729Sjoerg argv++;
20407330f729Sjoerg }
20417330f729Sjoerg
20427330f729Sjoerg if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
20437330f729Sjoerg clang_disposeIndex(Idx);
20447330f729Sjoerg return -1;
20457330f729Sjoerg }
20467330f729Sjoerg
20477330f729Sjoerg if (getenv("CINDEXTEST_EDITING"))
20487330f729Sjoerg Repeats = 5;
20497330f729Sjoerg
20507330f729Sjoerg Err = clang_parseTranslationUnit2(Idx, 0,
20517330f729Sjoerg argv + num_unsaved_files,
20527330f729Sjoerg argc - num_unsaved_files,
20537330f729Sjoerg unsaved_files, num_unsaved_files,
20547330f729Sjoerg getDefaultParsingOptions(), &TU);
20557330f729Sjoerg if (Err != CXError_Success) {
20567330f729Sjoerg fprintf(stderr, "Unable to load translation unit!\n");
20577330f729Sjoerg describeLibclangFailure(Err);
20587330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
20597330f729Sjoerg clang_disposeIndex(Idx);
20607330f729Sjoerg return 1;
20617330f729Sjoerg }
20627330f729Sjoerg
20637330f729Sjoerg for (I = 0; I != Repeats; ++I) {
20647330f729Sjoerg if (checkForErrors(TU) != 0)
20657330f729Sjoerg return -1;
20667330f729Sjoerg
20677330f729Sjoerg if (Repeats > 1) {
20687330f729Sjoerg clang_suspendTranslationUnit(TU);
20697330f729Sjoerg
20707330f729Sjoerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
20717330f729Sjoerg clang_defaultReparseOptions(TU));
20727330f729Sjoerg if (Err != CXError_Success) {
20737330f729Sjoerg describeLibclangFailure(Err);
20747330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
20757330f729Sjoerg clang_disposeIndex(Idx);
20767330f729Sjoerg return 1;
20777330f729Sjoerg }
20787330f729Sjoerg }
20797330f729Sjoerg }
20807330f729Sjoerg
20817330f729Sjoerg result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV,
20827330f729Sjoerg CommentSchemaFile);
20837330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
20847330f729Sjoerg clang_disposeIndex(Idx);
20857330f729Sjoerg return result;
20867330f729Sjoerg }
20877330f729Sjoerg
perform_test_reparse_source(int argc,const char ** argv,int trials,const char * filter,CXCursorVisitor Visitor,PostVisitTU PV)20887330f729Sjoerg int perform_test_reparse_source(int argc, const char **argv, int trials,
20897330f729Sjoerg const char *filter, CXCursorVisitor Visitor,
20907330f729Sjoerg PostVisitTU PV) {
20917330f729Sjoerg CXIndex Idx;
20927330f729Sjoerg CXTranslationUnit TU;
20937330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
20947330f729Sjoerg int num_unsaved_files = 0;
20957330f729Sjoerg int compiler_arg_idx = 0;
20967330f729Sjoerg enum CXErrorCode Err;
20977330f729Sjoerg int result, i;
20987330f729Sjoerg int trial;
2099*e038c9c4Sjoerg int execute_after_trial = 0;
2100*e038c9c4Sjoerg const char *execute_command = NULL;
21017330f729Sjoerg int remap_after_trial = 0;
21027330f729Sjoerg char *endptr = 0;
21037330f729Sjoerg
21047330f729Sjoerg Idx = clang_createIndex(/* excludeDeclsFromPCH */
21057330f729Sjoerg !strcmp(filter, "local") ? 1 : 0,
21067330f729Sjoerg /* displayDiagnostics=*/1);
21077330f729Sjoerg
21087330f729Sjoerg if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
21097330f729Sjoerg clang_disposeIndex(Idx);
21107330f729Sjoerg return -1;
21117330f729Sjoerg }
21127330f729Sjoerg
21137330f729Sjoerg for (i = 0; i < argc; ++i) {
21147330f729Sjoerg if (strcmp(argv[i], "--") == 0)
21157330f729Sjoerg break;
21167330f729Sjoerg }
21177330f729Sjoerg if (i < argc)
21187330f729Sjoerg compiler_arg_idx = i+1;
21197330f729Sjoerg if (num_unsaved_files > compiler_arg_idx)
21207330f729Sjoerg compiler_arg_idx = num_unsaved_files;
21217330f729Sjoerg
21227330f729Sjoerg /* Load the initial translation unit -- we do this without honoring remapped
21237330f729Sjoerg * files, so that we have a way to test results after changing the source. */
21247330f729Sjoerg Err = clang_parseTranslationUnit2(Idx, 0,
21257330f729Sjoerg argv + compiler_arg_idx,
21267330f729Sjoerg argc - compiler_arg_idx,
21277330f729Sjoerg 0, 0, getDefaultParsingOptions(), &TU);
21287330f729Sjoerg if (Err != CXError_Success) {
21297330f729Sjoerg fprintf(stderr, "Unable to load translation unit!\n");
21307330f729Sjoerg describeLibclangFailure(Err);
21317330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
21327330f729Sjoerg clang_disposeIndex(Idx);
21337330f729Sjoerg return 1;
21347330f729Sjoerg }
21357330f729Sjoerg
21367330f729Sjoerg if (checkForErrors(TU) != 0)
21377330f729Sjoerg return -1;
21387330f729Sjoerg
2139*e038c9c4Sjoerg if (getenv("CINDEXTEST_EXECUTE_COMMAND")) {
2140*e038c9c4Sjoerg execute_command = getenv("CINDEXTEST_EXECUTE_COMMAND");
2141*e038c9c4Sjoerg }
2142*e038c9c4Sjoerg if (getenv("CINDEXTEST_EXECUTE_AFTER_TRIAL")) {
2143*e038c9c4Sjoerg execute_after_trial =
2144*e038c9c4Sjoerg strtol(getenv("CINDEXTEST_EXECUTE_AFTER_TRIAL"), &endptr, 10);
2145*e038c9c4Sjoerg }
2146*e038c9c4Sjoerg
21477330f729Sjoerg if (getenv("CINDEXTEST_REMAP_AFTER_TRIAL")) {
21487330f729Sjoerg remap_after_trial =
21497330f729Sjoerg strtol(getenv("CINDEXTEST_REMAP_AFTER_TRIAL"), &endptr, 10);
21507330f729Sjoerg }
21517330f729Sjoerg
21527330f729Sjoerg for (trial = 0; trial < trials; ++trial) {
2153*e038c9c4Sjoerg if (execute_command && trial == execute_after_trial) {
2154*e038c9c4Sjoerg result = indextest_perform_shell_execution(execute_command);
2155*e038c9c4Sjoerg if (result != 0)
2156*e038c9c4Sjoerg return result;
2157*e038c9c4Sjoerg }
2158*e038c9c4Sjoerg
21597330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
21607330f729Sjoerg if (parse_remapped_files_with_try(trial, argc, argv, 0,
21617330f729Sjoerg &unsaved_files, &num_unsaved_files)) {
21627330f729Sjoerg clang_disposeTranslationUnit(TU);
21637330f729Sjoerg clang_disposeIndex(Idx);
21647330f729Sjoerg return -1;
21657330f729Sjoerg }
21667330f729Sjoerg
21677330f729Sjoerg Err = clang_reparseTranslationUnit(
21687330f729Sjoerg TU,
21697330f729Sjoerg trial >= remap_after_trial ? num_unsaved_files : 0,
21707330f729Sjoerg trial >= remap_after_trial ? unsaved_files : 0,
21717330f729Sjoerg clang_defaultReparseOptions(TU));
21727330f729Sjoerg if (Err != CXError_Success) {
21737330f729Sjoerg fprintf(stderr, "Unable to reparse translation unit!\n");
21747330f729Sjoerg describeLibclangFailure(Err);
21757330f729Sjoerg clang_disposeTranslationUnit(TU);
21767330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
21777330f729Sjoerg clang_disposeIndex(Idx);
21787330f729Sjoerg return -1;
21797330f729Sjoerg }
21807330f729Sjoerg
21817330f729Sjoerg if (checkForErrors(TU) != 0)
21827330f729Sjoerg return -1;
21837330f729Sjoerg }
21847330f729Sjoerg
21857330f729Sjoerg result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, NULL);
21867330f729Sjoerg
21877330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
21887330f729Sjoerg clang_disposeIndex(Idx);
21897330f729Sjoerg return result;
21907330f729Sjoerg }
21917330f729Sjoerg
perform_single_file_parse(const char * filename)21927330f729Sjoerg static int perform_single_file_parse(const char *filename) {
21937330f729Sjoerg CXIndex Idx;
21947330f729Sjoerg CXTranslationUnit TU;
21957330f729Sjoerg enum CXErrorCode Err;
21967330f729Sjoerg int result;
21977330f729Sjoerg
21987330f729Sjoerg Idx = clang_createIndex(/* excludeDeclsFromPCH */1,
21997330f729Sjoerg /* displayDiagnostics=*/1);
22007330f729Sjoerg
22017330f729Sjoerg Err = clang_parseTranslationUnit2(Idx, filename,
22027330f729Sjoerg /*command_line_args=*/NULL,
22037330f729Sjoerg /*num_command_line_args=*/0,
22047330f729Sjoerg /*unsaved_files=*/NULL,
22057330f729Sjoerg /*num_unsaved_files=*/0,
22067330f729Sjoerg CXTranslationUnit_SingleFileParse, &TU);
22077330f729Sjoerg if (Err != CXError_Success) {
22087330f729Sjoerg fprintf(stderr, "Unable to load translation unit!\n");
22097330f729Sjoerg describeLibclangFailure(Err);
22107330f729Sjoerg clang_disposeIndex(Idx);
22117330f729Sjoerg return 1;
22127330f729Sjoerg }
22137330f729Sjoerg
22147330f729Sjoerg result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL,
22157330f729Sjoerg /*CommentSchemaFile=*/NULL);
22167330f729Sjoerg clang_disposeIndex(Idx);
22177330f729Sjoerg return result;
22187330f729Sjoerg }
22197330f729Sjoerg
perform_file_retain_excluded_cb(const char * filename)22207330f729Sjoerg static int perform_file_retain_excluded_cb(const char *filename) {
22217330f729Sjoerg CXIndex Idx;
22227330f729Sjoerg CXTranslationUnit TU;
22237330f729Sjoerg enum CXErrorCode Err;
22247330f729Sjoerg int result;
22257330f729Sjoerg
22267330f729Sjoerg Idx = clang_createIndex(/* excludeDeclsFromPCH */1,
22277330f729Sjoerg /* displayDiagnostics=*/1);
22287330f729Sjoerg
22297330f729Sjoerg Err = clang_parseTranslationUnit2(Idx, filename,
22307330f729Sjoerg /*command_line_args=*/NULL,
22317330f729Sjoerg /*num_command_line_args=*/0,
22327330f729Sjoerg /*unsaved_files=*/NULL,
22337330f729Sjoerg /*num_unsaved_files=*/0,
22347330f729Sjoerg CXTranslationUnit_RetainExcludedConditionalBlocks, &TU);
22357330f729Sjoerg if (Err != CXError_Success) {
22367330f729Sjoerg fprintf(stderr, "Unable to load translation unit!\n");
22377330f729Sjoerg describeLibclangFailure(Err);
22387330f729Sjoerg clang_disposeIndex(Idx);
22397330f729Sjoerg return 1;
22407330f729Sjoerg }
22417330f729Sjoerg
22427330f729Sjoerg result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL,
22437330f729Sjoerg /*CommentSchemaFile=*/NULL);
22447330f729Sjoerg clang_disposeIndex(Idx);
22457330f729Sjoerg return result;
22467330f729Sjoerg }
22477330f729Sjoerg
22487330f729Sjoerg /******************************************************************************/
22497330f729Sjoerg /* Logic for testing clang_getCursor(). */
22507330f729Sjoerg /******************************************************************************/
22517330f729Sjoerg
print_cursor_file_scan(CXTranslationUnit TU,CXCursor cursor,unsigned start_line,unsigned start_col,unsigned end_line,unsigned end_col,const char * prefix)22527330f729Sjoerg static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor,
22537330f729Sjoerg unsigned start_line, unsigned start_col,
22547330f729Sjoerg unsigned end_line, unsigned end_col,
22557330f729Sjoerg const char *prefix) {
22567330f729Sjoerg printf("// %s: ", FileCheckPrefix);
22577330f729Sjoerg if (prefix)
22587330f729Sjoerg printf("-%s", prefix);
22597330f729Sjoerg PrintExtent(stdout, start_line, start_col, end_line, end_col);
22607330f729Sjoerg printf(" ");
22617330f729Sjoerg PrintCursor(cursor, NULL);
22627330f729Sjoerg printf("\n");
22637330f729Sjoerg }
22647330f729Sjoerg
perform_file_scan(const char * ast_file,const char * source_file,const char * prefix)22657330f729Sjoerg static int perform_file_scan(const char *ast_file, const char *source_file,
22667330f729Sjoerg const char *prefix) {
22677330f729Sjoerg CXIndex Idx;
22687330f729Sjoerg CXTranslationUnit TU;
22697330f729Sjoerg FILE *fp;
22707330f729Sjoerg CXCursor prevCursor = clang_getNullCursor();
22717330f729Sjoerg CXFile file;
22727330f729Sjoerg unsigned line = 1, col = 1;
22737330f729Sjoerg unsigned start_line = 1, start_col = 1;
22747330f729Sjoerg
22757330f729Sjoerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
22767330f729Sjoerg /* displayDiagnostics=*/1))) {
22777330f729Sjoerg fprintf(stderr, "Could not create Index\n");
22787330f729Sjoerg return 1;
22797330f729Sjoerg }
22807330f729Sjoerg
22817330f729Sjoerg if (!CreateTranslationUnit(Idx, ast_file, &TU))
22827330f729Sjoerg return 1;
22837330f729Sjoerg
22847330f729Sjoerg if ((fp = fopen(source_file, "r")) == NULL) {
22857330f729Sjoerg fprintf(stderr, "Could not open '%s'\n", source_file);
22867330f729Sjoerg clang_disposeTranslationUnit(TU);
22877330f729Sjoerg return 1;
22887330f729Sjoerg }
22897330f729Sjoerg
22907330f729Sjoerg file = clang_getFile(TU, source_file);
22917330f729Sjoerg for (;;) {
22927330f729Sjoerg CXCursor cursor;
22937330f729Sjoerg int c = fgetc(fp);
22947330f729Sjoerg
22957330f729Sjoerg if (c == '\n') {
22967330f729Sjoerg ++line;
22977330f729Sjoerg col = 1;
22987330f729Sjoerg } else
22997330f729Sjoerg ++col;
23007330f729Sjoerg
23017330f729Sjoerg /* Check the cursor at this position, and dump the previous one if we have
23027330f729Sjoerg * found something new.
23037330f729Sjoerg */
23047330f729Sjoerg cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, col));
23057330f729Sjoerg if ((c == EOF || !clang_equalCursors(cursor, prevCursor)) &&
23067330f729Sjoerg prevCursor.kind != CXCursor_InvalidFile) {
23077330f729Sjoerg print_cursor_file_scan(TU, prevCursor, start_line, start_col,
23087330f729Sjoerg line, col, prefix);
23097330f729Sjoerg start_line = line;
23107330f729Sjoerg start_col = col;
23117330f729Sjoerg }
23127330f729Sjoerg if (c == EOF)
23137330f729Sjoerg break;
23147330f729Sjoerg
23157330f729Sjoerg prevCursor = cursor;
23167330f729Sjoerg }
23177330f729Sjoerg
23187330f729Sjoerg fclose(fp);
23197330f729Sjoerg clang_disposeTranslationUnit(TU);
23207330f729Sjoerg clang_disposeIndex(Idx);
23217330f729Sjoerg return 0;
23227330f729Sjoerg }
23237330f729Sjoerg
23247330f729Sjoerg /******************************************************************************/
23257330f729Sjoerg /* Logic for testing clang code completion. */
23267330f729Sjoerg /******************************************************************************/
23277330f729Sjoerg
23287330f729Sjoerg /* Parse file:line:column from the input string. Returns 0 on success, non-zero
23297330f729Sjoerg on failure. If successful, the pointer *filename will contain newly-allocated
23307330f729Sjoerg memory (that will be owned by the caller) to store the file name. */
parse_file_line_column(const char * input,char ** filename,unsigned * line,unsigned * column,unsigned * second_line,unsigned * second_column)23317330f729Sjoerg int parse_file_line_column(const char *input, char **filename, unsigned *line,
23327330f729Sjoerg unsigned *column, unsigned *second_line,
23337330f729Sjoerg unsigned *second_column) {
23347330f729Sjoerg /* Find the second colon. */
23357330f729Sjoerg const char *last_colon = strrchr(input, ':');
23367330f729Sjoerg unsigned values[4], i;
23377330f729Sjoerg unsigned num_values = (second_line && second_column)? 4 : 2;
23387330f729Sjoerg
23397330f729Sjoerg char *endptr = 0;
23407330f729Sjoerg if (!last_colon || last_colon == input) {
23417330f729Sjoerg if (num_values == 4)
23427330f729Sjoerg fprintf(stderr, "could not parse filename:line:column:line:column in "
23437330f729Sjoerg "'%s'\n", input);
23447330f729Sjoerg else
23457330f729Sjoerg fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
23467330f729Sjoerg return 1;
23477330f729Sjoerg }
23487330f729Sjoerg
23497330f729Sjoerg for (i = 0; i != num_values; ++i) {
23507330f729Sjoerg const char *prev_colon;
23517330f729Sjoerg
23527330f729Sjoerg /* Parse the next line or column. */
23537330f729Sjoerg values[num_values - i - 1] = strtol(last_colon + 1, &endptr, 10);
23547330f729Sjoerg if (*endptr != 0 && *endptr != ':') {
23557330f729Sjoerg fprintf(stderr, "could not parse %s in '%s'\n",
23567330f729Sjoerg (i % 2 ? "column" : "line"), input);
23577330f729Sjoerg return 1;
23587330f729Sjoerg }
23597330f729Sjoerg
23607330f729Sjoerg if (i + 1 == num_values)
23617330f729Sjoerg break;
23627330f729Sjoerg
23637330f729Sjoerg /* Find the previous colon. */
23647330f729Sjoerg prev_colon = last_colon - 1;
23657330f729Sjoerg while (prev_colon != input && *prev_colon != ':')
23667330f729Sjoerg --prev_colon;
23677330f729Sjoerg if (prev_colon == input) {
23687330f729Sjoerg fprintf(stderr, "could not parse %s in '%s'\n",
23697330f729Sjoerg (i % 2 == 0? "column" : "line"), input);
23707330f729Sjoerg return 1;
23717330f729Sjoerg }
23727330f729Sjoerg
23737330f729Sjoerg last_colon = prev_colon;
23747330f729Sjoerg }
23757330f729Sjoerg
23767330f729Sjoerg *line = values[0];
23777330f729Sjoerg *column = values[1];
23787330f729Sjoerg
23797330f729Sjoerg if (second_line && second_column) {
23807330f729Sjoerg *second_line = values[2];
23817330f729Sjoerg *second_column = values[3];
23827330f729Sjoerg }
23837330f729Sjoerg
23847330f729Sjoerg /* Copy the file name. */
23857330f729Sjoerg *filename = (char*)malloc(last_colon - input + 1);
23867330f729Sjoerg assert(*filename);
23877330f729Sjoerg memcpy(*filename, input, last_colon - input);
23887330f729Sjoerg (*filename)[last_colon - input] = 0;
23897330f729Sjoerg return 0;
23907330f729Sjoerg }
23917330f729Sjoerg
23927330f729Sjoerg const char *
clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind)23937330f729Sjoerg clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
23947330f729Sjoerg switch (Kind) {
23957330f729Sjoerg case CXCompletionChunk_Optional: return "Optional";
23967330f729Sjoerg case CXCompletionChunk_TypedText: return "TypedText";
23977330f729Sjoerg case CXCompletionChunk_Text: return "Text";
23987330f729Sjoerg case CXCompletionChunk_Placeholder: return "Placeholder";
23997330f729Sjoerg case CXCompletionChunk_Informative: return "Informative";
24007330f729Sjoerg case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
24017330f729Sjoerg case CXCompletionChunk_LeftParen: return "LeftParen";
24027330f729Sjoerg case CXCompletionChunk_RightParen: return "RightParen";
24037330f729Sjoerg case CXCompletionChunk_LeftBracket: return "LeftBracket";
24047330f729Sjoerg case CXCompletionChunk_RightBracket: return "RightBracket";
24057330f729Sjoerg case CXCompletionChunk_LeftBrace: return "LeftBrace";
24067330f729Sjoerg case CXCompletionChunk_RightBrace: return "RightBrace";
24077330f729Sjoerg case CXCompletionChunk_LeftAngle: return "LeftAngle";
24087330f729Sjoerg case CXCompletionChunk_RightAngle: return "RightAngle";
24097330f729Sjoerg case CXCompletionChunk_Comma: return "Comma";
24107330f729Sjoerg case CXCompletionChunk_ResultType: return "ResultType";
24117330f729Sjoerg case CXCompletionChunk_Colon: return "Colon";
24127330f729Sjoerg case CXCompletionChunk_SemiColon: return "SemiColon";
24137330f729Sjoerg case CXCompletionChunk_Equal: return "Equal";
24147330f729Sjoerg case CXCompletionChunk_HorizontalSpace: return "HorizontalSpace";
24157330f729Sjoerg case CXCompletionChunk_VerticalSpace: return "VerticalSpace";
24167330f729Sjoerg }
24177330f729Sjoerg
24187330f729Sjoerg return "Unknown";
24197330f729Sjoerg }
24207330f729Sjoerg
checkForErrors(CXTranslationUnit TU)24217330f729Sjoerg static int checkForErrors(CXTranslationUnit TU) {
24227330f729Sjoerg unsigned Num, i;
24237330f729Sjoerg CXDiagnostic Diag;
24247330f729Sjoerg CXString DiagStr;
24257330f729Sjoerg
24267330f729Sjoerg if (!getenv("CINDEXTEST_FAILONERROR"))
24277330f729Sjoerg return 0;
24287330f729Sjoerg
24297330f729Sjoerg Num = clang_getNumDiagnostics(TU);
24307330f729Sjoerg for (i = 0; i != Num; ++i) {
24317330f729Sjoerg Diag = clang_getDiagnostic(TU, i);
24327330f729Sjoerg if (clang_getDiagnosticSeverity(Diag) >= CXDiagnostic_Error) {
24337330f729Sjoerg DiagStr = clang_formatDiagnostic(Diag,
24347330f729Sjoerg clang_defaultDiagnosticDisplayOptions());
24357330f729Sjoerg fprintf(stderr, "%s\n", clang_getCString(DiagStr));
24367330f729Sjoerg clang_disposeString(DiagStr);
24377330f729Sjoerg clang_disposeDiagnostic(Diag);
24387330f729Sjoerg return -1;
24397330f729Sjoerg }
24407330f729Sjoerg clang_disposeDiagnostic(Diag);
24417330f729Sjoerg }
24427330f729Sjoerg
24437330f729Sjoerg return 0;
24447330f729Sjoerg }
24457330f729Sjoerg
print_completion_string(CXCompletionString completion_string,FILE * file)24467330f729Sjoerg static void print_completion_string(CXCompletionString completion_string,
24477330f729Sjoerg FILE *file) {
24487330f729Sjoerg int I, N;
24497330f729Sjoerg
24507330f729Sjoerg N = clang_getNumCompletionChunks(completion_string);
24517330f729Sjoerg for (I = 0; I != N; ++I) {
24527330f729Sjoerg CXString text;
24537330f729Sjoerg const char *cstr;
24547330f729Sjoerg enum CXCompletionChunkKind Kind
24557330f729Sjoerg = clang_getCompletionChunkKind(completion_string, I);
24567330f729Sjoerg
24577330f729Sjoerg if (Kind == CXCompletionChunk_Optional) {
24587330f729Sjoerg fprintf(file, "{Optional ");
24597330f729Sjoerg print_completion_string(
24607330f729Sjoerg clang_getCompletionChunkCompletionString(completion_string, I),
24617330f729Sjoerg file);
24627330f729Sjoerg fprintf(file, "}");
24637330f729Sjoerg continue;
24647330f729Sjoerg }
24657330f729Sjoerg
24667330f729Sjoerg if (Kind == CXCompletionChunk_VerticalSpace) {
24677330f729Sjoerg fprintf(file, "{VerticalSpace }");
24687330f729Sjoerg continue;
24697330f729Sjoerg }
24707330f729Sjoerg
24717330f729Sjoerg text = clang_getCompletionChunkText(completion_string, I);
24727330f729Sjoerg cstr = clang_getCString(text);
24737330f729Sjoerg fprintf(file, "{%s %s}",
24747330f729Sjoerg clang_getCompletionChunkKindSpelling(Kind),
24757330f729Sjoerg cstr ? cstr : "");
24767330f729Sjoerg clang_disposeString(text);
24777330f729Sjoerg }
24787330f729Sjoerg
24797330f729Sjoerg }
24807330f729Sjoerg
print_line_column(CXSourceLocation location,FILE * file)24817330f729Sjoerg static void print_line_column(CXSourceLocation location, FILE *file) {
24827330f729Sjoerg unsigned line, column;
24837330f729Sjoerg clang_getExpansionLocation(location, NULL, &line, &column, NULL);
24847330f729Sjoerg fprintf(file, "%d:%d", line, column);
24857330f729Sjoerg }
24867330f729Sjoerg
print_token_range(CXTranslationUnit translation_unit,CXSourceLocation start,FILE * file)24877330f729Sjoerg static void print_token_range(CXTranslationUnit translation_unit,
24887330f729Sjoerg CXSourceLocation start, FILE *file) {
24897330f729Sjoerg CXToken *token = clang_getToken(translation_unit, start);
24907330f729Sjoerg
24917330f729Sjoerg fprintf(file, "{");
24927330f729Sjoerg if (token != NULL) {
24937330f729Sjoerg CXSourceRange token_range = clang_getTokenExtent(translation_unit, *token);
24947330f729Sjoerg print_line_column(clang_getRangeStart(token_range), file);
24957330f729Sjoerg fprintf(file, "-");
24967330f729Sjoerg print_line_column(clang_getRangeEnd(token_range), file);
24977330f729Sjoerg clang_disposeTokens(translation_unit, token, 1);
24987330f729Sjoerg }
24997330f729Sjoerg
25007330f729Sjoerg fprintf(file, "}");
25017330f729Sjoerg }
25027330f729Sjoerg
print_completion_result(CXTranslationUnit translation_unit,CXCodeCompleteResults * completion_results,unsigned index,FILE * file)25037330f729Sjoerg static void print_completion_result(CXTranslationUnit translation_unit,
25047330f729Sjoerg CXCodeCompleteResults *completion_results,
25057330f729Sjoerg unsigned index,
25067330f729Sjoerg FILE *file) {
25077330f729Sjoerg CXCompletionResult *completion_result = completion_results->Results + index;
25087330f729Sjoerg CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
25097330f729Sjoerg unsigned annotationCount;
25107330f729Sjoerg enum CXCursorKind ParentKind;
25117330f729Sjoerg CXString ParentName;
25127330f729Sjoerg CXString BriefComment;
25137330f729Sjoerg CXString Annotation;
25147330f729Sjoerg const char *BriefCommentCString;
25157330f729Sjoerg unsigned i;
25167330f729Sjoerg
25177330f729Sjoerg fprintf(file, "%s:", clang_getCString(ks));
25187330f729Sjoerg clang_disposeString(ks);
25197330f729Sjoerg
25207330f729Sjoerg print_completion_string(completion_result->CompletionString, file);
25217330f729Sjoerg fprintf(file, " (%u)",
25227330f729Sjoerg clang_getCompletionPriority(completion_result->CompletionString));
25237330f729Sjoerg switch (clang_getCompletionAvailability(completion_result->CompletionString)){
25247330f729Sjoerg case CXAvailability_Available:
25257330f729Sjoerg break;
25267330f729Sjoerg
25277330f729Sjoerg case CXAvailability_Deprecated:
25287330f729Sjoerg fprintf(file, " (deprecated)");
25297330f729Sjoerg break;
25307330f729Sjoerg
25317330f729Sjoerg case CXAvailability_NotAvailable:
25327330f729Sjoerg fprintf(file, " (unavailable)");
25337330f729Sjoerg break;
25347330f729Sjoerg
25357330f729Sjoerg case CXAvailability_NotAccessible:
25367330f729Sjoerg fprintf(file, " (inaccessible)");
25377330f729Sjoerg break;
25387330f729Sjoerg }
25397330f729Sjoerg
25407330f729Sjoerg annotationCount = clang_getCompletionNumAnnotations(
25417330f729Sjoerg completion_result->CompletionString);
25427330f729Sjoerg if (annotationCount) {
25437330f729Sjoerg unsigned i;
25447330f729Sjoerg fprintf(file, " (");
25457330f729Sjoerg for (i = 0; i < annotationCount; ++i) {
25467330f729Sjoerg if (i != 0)
25477330f729Sjoerg fprintf(file, ", ");
25487330f729Sjoerg Annotation =
25497330f729Sjoerg clang_getCompletionAnnotation(completion_result->CompletionString, i);
25507330f729Sjoerg fprintf(file, "\"%s\"", clang_getCString(Annotation));
25517330f729Sjoerg clang_disposeString(Annotation);
25527330f729Sjoerg }
25537330f729Sjoerg fprintf(file, ")");
25547330f729Sjoerg }
25557330f729Sjoerg
25567330f729Sjoerg if (!getenv("CINDEXTEST_NO_COMPLETION_PARENTS")) {
25577330f729Sjoerg ParentName = clang_getCompletionParent(completion_result->CompletionString,
25587330f729Sjoerg &ParentKind);
25597330f729Sjoerg if (ParentKind != CXCursor_NotImplemented) {
25607330f729Sjoerg CXString KindSpelling = clang_getCursorKindSpelling(ParentKind);
25617330f729Sjoerg fprintf(file, " (parent: %s '%s')",
25627330f729Sjoerg clang_getCString(KindSpelling),
25637330f729Sjoerg clang_getCString(ParentName));
25647330f729Sjoerg clang_disposeString(KindSpelling);
25657330f729Sjoerg }
25667330f729Sjoerg clang_disposeString(ParentName);
25677330f729Sjoerg }
25687330f729Sjoerg
25697330f729Sjoerg BriefComment = clang_getCompletionBriefComment(
25707330f729Sjoerg completion_result->CompletionString);
25717330f729Sjoerg BriefCommentCString = clang_getCString(BriefComment);
25727330f729Sjoerg if (BriefCommentCString && *BriefCommentCString != '\0') {
25737330f729Sjoerg fprintf(file, "(brief comment: %s)", BriefCommentCString);
25747330f729Sjoerg }
25757330f729Sjoerg clang_disposeString(BriefComment);
25767330f729Sjoerg
25777330f729Sjoerg for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index);
25787330f729Sjoerg ++i) {
25797330f729Sjoerg CXSourceRange correction_range;
25807330f729Sjoerg CXString FixIt = clang_getCompletionFixIt(completion_results, index, i,
25817330f729Sjoerg &correction_range);
25827330f729Sjoerg fprintf(file, " (requires fix-it: ");
25837330f729Sjoerg print_token_range(translation_unit, clang_getRangeStart(correction_range),
25847330f729Sjoerg file);
25857330f729Sjoerg fprintf(file, " to \"%s\")", clang_getCString(FixIt));
25867330f729Sjoerg clang_disposeString(FixIt);
25877330f729Sjoerg }
25887330f729Sjoerg
25897330f729Sjoerg fprintf(file, "\n");
25907330f729Sjoerg }
25917330f729Sjoerg
print_completion_contexts(unsigned long long contexts,FILE * file)25927330f729Sjoerg void print_completion_contexts(unsigned long long contexts, FILE *file) {
25937330f729Sjoerg fprintf(file, "Completion contexts:\n");
25947330f729Sjoerg if (contexts == CXCompletionContext_Unknown) {
25957330f729Sjoerg fprintf(file, "Unknown\n");
25967330f729Sjoerg }
25977330f729Sjoerg if (contexts & CXCompletionContext_AnyType) {
25987330f729Sjoerg fprintf(file, "Any type\n");
25997330f729Sjoerg }
26007330f729Sjoerg if (contexts & CXCompletionContext_AnyValue) {
26017330f729Sjoerg fprintf(file, "Any value\n");
26027330f729Sjoerg }
26037330f729Sjoerg if (contexts & CXCompletionContext_ObjCObjectValue) {
26047330f729Sjoerg fprintf(file, "Objective-C object value\n");
26057330f729Sjoerg }
26067330f729Sjoerg if (contexts & CXCompletionContext_ObjCSelectorValue) {
26077330f729Sjoerg fprintf(file, "Objective-C selector value\n");
26087330f729Sjoerg }
26097330f729Sjoerg if (contexts & CXCompletionContext_CXXClassTypeValue) {
26107330f729Sjoerg fprintf(file, "C++ class type value\n");
26117330f729Sjoerg }
26127330f729Sjoerg if (contexts & CXCompletionContext_DotMemberAccess) {
26137330f729Sjoerg fprintf(file, "Dot member access\n");
26147330f729Sjoerg }
26157330f729Sjoerg if (contexts & CXCompletionContext_ArrowMemberAccess) {
26167330f729Sjoerg fprintf(file, "Arrow member access\n");
26177330f729Sjoerg }
26187330f729Sjoerg if (contexts & CXCompletionContext_ObjCPropertyAccess) {
26197330f729Sjoerg fprintf(file, "Objective-C property access\n");
26207330f729Sjoerg }
26217330f729Sjoerg if (contexts & CXCompletionContext_EnumTag) {
26227330f729Sjoerg fprintf(file, "Enum tag\n");
26237330f729Sjoerg }
26247330f729Sjoerg if (contexts & CXCompletionContext_UnionTag) {
26257330f729Sjoerg fprintf(file, "Union tag\n");
26267330f729Sjoerg }
26277330f729Sjoerg if (contexts & CXCompletionContext_StructTag) {
26287330f729Sjoerg fprintf(file, "Struct tag\n");
26297330f729Sjoerg }
26307330f729Sjoerg if (contexts & CXCompletionContext_ClassTag) {
26317330f729Sjoerg fprintf(file, "Class name\n");
26327330f729Sjoerg }
26337330f729Sjoerg if (contexts & CXCompletionContext_Namespace) {
26347330f729Sjoerg fprintf(file, "Namespace or namespace alias\n");
26357330f729Sjoerg }
26367330f729Sjoerg if (contexts & CXCompletionContext_NestedNameSpecifier) {
26377330f729Sjoerg fprintf(file, "Nested name specifier\n");
26387330f729Sjoerg }
26397330f729Sjoerg if (contexts & CXCompletionContext_ObjCInterface) {
26407330f729Sjoerg fprintf(file, "Objective-C interface\n");
26417330f729Sjoerg }
26427330f729Sjoerg if (contexts & CXCompletionContext_ObjCProtocol) {
26437330f729Sjoerg fprintf(file, "Objective-C protocol\n");
26447330f729Sjoerg }
26457330f729Sjoerg if (contexts & CXCompletionContext_ObjCCategory) {
26467330f729Sjoerg fprintf(file, "Objective-C category\n");
26477330f729Sjoerg }
26487330f729Sjoerg if (contexts & CXCompletionContext_ObjCInstanceMessage) {
26497330f729Sjoerg fprintf(file, "Objective-C instance method\n");
26507330f729Sjoerg }
26517330f729Sjoerg if (contexts & CXCompletionContext_ObjCClassMessage) {
26527330f729Sjoerg fprintf(file, "Objective-C class method\n");
26537330f729Sjoerg }
26547330f729Sjoerg if (contexts & CXCompletionContext_ObjCSelectorName) {
26557330f729Sjoerg fprintf(file, "Objective-C selector name\n");
26567330f729Sjoerg }
26577330f729Sjoerg if (contexts & CXCompletionContext_MacroName) {
26587330f729Sjoerg fprintf(file, "Macro name\n");
26597330f729Sjoerg }
26607330f729Sjoerg if (contexts & CXCompletionContext_NaturalLanguage) {
26617330f729Sjoerg fprintf(file, "Natural language\n");
26627330f729Sjoerg }
26637330f729Sjoerg }
26647330f729Sjoerg
perform_code_completion(int argc,const char ** argv,int timing_only)26657330f729Sjoerg int perform_code_completion(int argc, const char **argv, int timing_only) {
26667330f729Sjoerg const char *input = argv[1];
26677330f729Sjoerg char *filename = 0;
26687330f729Sjoerg unsigned line;
26697330f729Sjoerg unsigned column;
26707330f729Sjoerg CXIndex CIdx;
26717330f729Sjoerg int errorCode;
26727330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
26737330f729Sjoerg int num_unsaved_files = 0;
26747330f729Sjoerg CXCodeCompleteResults *results = 0;
26757330f729Sjoerg enum CXErrorCode Err;
26767330f729Sjoerg CXTranslationUnit TU;
26777330f729Sjoerg unsigned I, Repeats = 1;
26787330f729Sjoerg unsigned completionOptions = clang_defaultCodeCompleteOptions();
26797330f729Sjoerg const char *InvocationPath;
26807330f729Sjoerg
26817330f729Sjoerg if (getenv("CINDEXTEST_CODE_COMPLETE_PATTERNS"))
26827330f729Sjoerg completionOptions |= CXCodeComplete_IncludeCodePatterns;
26837330f729Sjoerg if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
26847330f729Sjoerg completionOptions |= CXCodeComplete_IncludeBriefComments;
26857330f729Sjoerg if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE"))
26867330f729Sjoerg completionOptions |= CXCodeComplete_SkipPreamble;
26877330f729Sjoerg if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS"))
26887330f729Sjoerg completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts;
26897330f729Sjoerg
26907330f729Sjoerg if (timing_only)
26917330f729Sjoerg input += strlen("-code-completion-timing=");
26927330f729Sjoerg else
26937330f729Sjoerg input += strlen("-code-completion-at=");
26947330f729Sjoerg
26957330f729Sjoerg if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
26967330f729Sjoerg 0, 0)))
26977330f729Sjoerg return errorCode;
26987330f729Sjoerg
26997330f729Sjoerg if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
27007330f729Sjoerg return -1;
27017330f729Sjoerg
27027330f729Sjoerg CIdx = clang_createIndex(0, 0);
27037330f729Sjoerg InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH");
27047330f729Sjoerg if (InvocationPath)
27057330f729Sjoerg clang_CXIndex_setInvocationEmissionPathOption(CIdx, InvocationPath);
27067330f729Sjoerg
27077330f729Sjoerg if (getenv("CINDEXTEST_EDITING"))
27087330f729Sjoerg Repeats = 5;
27097330f729Sjoerg
27107330f729Sjoerg Err = clang_parseTranslationUnit2(CIdx, 0,
27117330f729Sjoerg argv + num_unsaved_files + 2,
27127330f729Sjoerg argc - num_unsaved_files - 2,
27137330f729Sjoerg 0, 0, getDefaultParsingOptions(), &TU);
27147330f729Sjoerg if (Err != CXError_Success) {
27157330f729Sjoerg fprintf(stderr, "Unable to load translation unit!\n");
27167330f729Sjoerg describeLibclangFailure(Err);
27177330f729Sjoerg return 1;
27187330f729Sjoerg }
27197330f729Sjoerg
27207330f729Sjoerg Err = clang_reparseTranslationUnit(TU, 0, 0,
27217330f729Sjoerg clang_defaultReparseOptions(TU));
27227330f729Sjoerg
27237330f729Sjoerg if (Err != CXError_Success) {
27247330f729Sjoerg fprintf(stderr, "Unable to reparse translation unit!\n");
27257330f729Sjoerg describeLibclangFailure(Err);
27267330f729Sjoerg clang_disposeTranslationUnit(TU);
27277330f729Sjoerg return 1;
27287330f729Sjoerg }
27297330f729Sjoerg
27307330f729Sjoerg for (I = 0; I != Repeats; ++I) {
27317330f729Sjoerg results = clang_codeCompleteAt(TU, filename, line, column,
27327330f729Sjoerg unsaved_files, num_unsaved_files,
27337330f729Sjoerg completionOptions);
27347330f729Sjoerg if (!results) {
27357330f729Sjoerg fprintf(stderr, "Unable to perform code completion!\n");
27367330f729Sjoerg return 1;
27377330f729Sjoerg }
27387330f729Sjoerg if (I != Repeats-1)
27397330f729Sjoerg clang_disposeCodeCompleteResults(results);
27407330f729Sjoerg }
27417330f729Sjoerg
27427330f729Sjoerg if (results) {
27437330f729Sjoerg unsigned i, n = results->NumResults, containerIsIncomplete = 0;
27447330f729Sjoerg unsigned long long contexts;
27457330f729Sjoerg enum CXCursorKind containerKind;
27467330f729Sjoerg CXString objCSelector;
27477330f729Sjoerg const char *selectorString;
27487330f729Sjoerg if (!timing_only) {
27497330f729Sjoerg /* Sort the code-completion results based on the typed text. */
27507330f729Sjoerg clang_sortCodeCompletionResults(results->Results, results->NumResults);
27517330f729Sjoerg
27527330f729Sjoerg for (i = 0; i != n; ++i)
27537330f729Sjoerg print_completion_result(TU, results, i, stdout);
27547330f729Sjoerg }
27557330f729Sjoerg n = clang_codeCompleteGetNumDiagnostics(results);
27567330f729Sjoerg for (i = 0; i != n; ++i) {
27577330f729Sjoerg CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i);
27587330f729Sjoerg PrintDiagnostic(diag);
27597330f729Sjoerg clang_disposeDiagnostic(diag);
27607330f729Sjoerg }
27617330f729Sjoerg
27627330f729Sjoerg contexts = clang_codeCompleteGetContexts(results);
27637330f729Sjoerg print_completion_contexts(contexts, stdout);
27647330f729Sjoerg
27657330f729Sjoerg containerKind = clang_codeCompleteGetContainerKind(results,
27667330f729Sjoerg &containerIsIncomplete);
27677330f729Sjoerg
27687330f729Sjoerg if (containerKind != CXCursor_InvalidCode) {
27697330f729Sjoerg /* We have found a container */
27707330f729Sjoerg CXString containerUSR, containerKindSpelling;
27717330f729Sjoerg containerKindSpelling = clang_getCursorKindSpelling(containerKind);
27727330f729Sjoerg printf("Container Kind: %s\n", clang_getCString(containerKindSpelling));
27737330f729Sjoerg clang_disposeString(containerKindSpelling);
27747330f729Sjoerg
27757330f729Sjoerg if (containerIsIncomplete) {
27767330f729Sjoerg printf("Container is incomplete\n");
27777330f729Sjoerg }
27787330f729Sjoerg else {
27797330f729Sjoerg printf("Container is complete\n");
27807330f729Sjoerg }
27817330f729Sjoerg
27827330f729Sjoerg containerUSR = clang_codeCompleteGetContainerUSR(results);
27837330f729Sjoerg printf("Container USR: %s\n", clang_getCString(containerUSR));
27847330f729Sjoerg clang_disposeString(containerUSR);
27857330f729Sjoerg }
27867330f729Sjoerg
27877330f729Sjoerg objCSelector = clang_codeCompleteGetObjCSelector(results);
27887330f729Sjoerg selectorString = clang_getCString(objCSelector);
27897330f729Sjoerg if (selectorString && strlen(selectorString) > 0) {
27907330f729Sjoerg printf("Objective-C selector: %s\n", selectorString);
27917330f729Sjoerg }
27927330f729Sjoerg clang_disposeString(objCSelector);
27937330f729Sjoerg
27947330f729Sjoerg clang_disposeCodeCompleteResults(results);
27957330f729Sjoerg }
27967330f729Sjoerg clang_disposeTranslationUnit(TU);
27977330f729Sjoerg clang_disposeIndex(CIdx);
27987330f729Sjoerg free(filename);
27997330f729Sjoerg
28007330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
28017330f729Sjoerg
28027330f729Sjoerg return 0;
28037330f729Sjoerg }
28047330f729Sjoerg
28057330f729Sjoerg typedef struct {
28067330f729Sjoerg char *filename;
28077330f729Sjoerg unsigned line;
28087330f729Sjoerg unsigned column;
28097330f729Sjoerg } CursorSourceLocation;
28107330f729Sjoerg
28117330f729Sjoerg typedef void (*cursor_handler_t)(CXCursor cursor);
28127330f729Sjoerg
inspect_cursor_at(int argc,const char ** argv,const char * locations_flag,cursor_handler_t handler)28137330f729Sjoerg static int inspect_cursor_at(int argc, const char **argv,
28147330f729Sjoerg const char *locations_flag,
28157330f729Sjoerg cursor_handler_t handler) {
28167330f729Sjoerg CXIndex CIdx;
28177330f729Sjoerg int errorCode;
28187330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
28197330f729Sjoerg int num_unsaved_files = 0;
28207330f729Sjoerg enum CXErrorCode Err;
28217330f729Sjoerg CXTranslationUnit TU;
28227330f729Sjoerg CXCursor Cursor;
28237330f729Sjoerg CursorSourceLocation *Locations = 0;
28247330f729Sjoerg unsigned NumLocations = 0, Loc;
28257330f729Sjoerg unsigned Repeats = 1;
28267330f729Sjoerg unsigned I;
28277330f729Sjoerg
28287330f729Sjoerg /* Count the number of locations. */
28297330f729Sjoerg while (strstr(argv[NumLocations+1], locations_flag) == argv[NumLocations+1])
28307330f729Sjoerg ++NumLocations;
28317330f729Sjoerg
28327330f729Sjoerg /* Parse the locations. */
28337330f729Sjoerg assert(NumLocations > 0 && "Unable to count locations?");
28347330f729Sjoerg Locations = (CursorSourceLocation *)malloc(
28357330f729Sjoerg NumLocations * sizeof(CursorSourceLocation));
28367330f729Sjoerg assert(Locations);
28377330f729Sjoerg for (Loc = 0; Loc < NumLocations; ++Loc) {
28387330f729Sjoerg const char *input = argv[Loc + 1] + strlen(locations_flag);
28397330f729Sjoerg if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
28407330f729Sjoerg &Locations[Loc].line,
28417330f729Sjoerg &Locations[Loc].column, 0, 0)))
28427330f729Sjoerg return errorCode;
28437330f729Sjoerg }
28447330f729Sjoerg
28457330f729Sjoerg if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
28467330f729Sjoerg &num_unsaved_files))
28477330f729Sjoerg return -1;
28487330f729Sjoerg
28497330f729Sjoerg if (getenv("CINDEXTEST_EDITING"))
28507330f729Sjoerg Repeats = 5;
28517330f729Sjoerg
28527330f729Sjoerg /* Parse the translation unit. When we're testing clang_getCursor() after
28537330f729Sjoerg reparsing, don't remap unsaved files until the second parse. */
28547330f729Sjoerg CIdx = clang_createIndex(1, 1);
28557330f729Sjoerg Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
28567330f729Sjoerg argv + num_unsaved_files + 1 + NumLocations,
28577330f729Sjoerg argc - num_unsaved_files - 2 - NumLocations,
28587330f729Sjoerg unsaved_files,
28597330f729Sjoerg Repeats > 1? 0 : num_unsaved_files,
28607330f729Sjoerg getDefaultParsingOptions(), &TU);
28617330f729Sjoerg if (Err != CXError_Success) {
28627330f729Sjoerg fprintf(stderr, "unable to parse input\n");
28637330f729Sjoerg describeLibclangFailure(Err);
28647330f729Sjoerg return -1;
28657330f729Sjoerg }
28667330f729Sjoerg
28677330f729Sjoerg if (checkForErrors(TU) != 0)
28687330f729Sjoerg return -1;
28697330f729Sjoerg
28707330f729Sjoerg for (I = 0; I != Repeats; ++I) {
28717330f729Sjoerg if (Repeats > 1) {
28727330f729Sjoerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
28737330f729Sjoerg clang_defaultReparseOptions(TU));
28747330f729Sjoerg if (Err != CXError_Success) {
28757330f729Sjoerg describeLibclangFailure(Err);
28767330f729Sjoerg clang_disposeTranslationUnit(TU);
28777330f729Sjoerg return 1;
28787330f729Sjoerg }
28797330f729Sjoerg }
28807330f729Sjoerg
28817330f729Sjoerg if (checkForErrors(TU) != 0)
28827330f729Sjoerg return -1;
28837330f729Sjoerg
28847330f729Sjoerg for (Loc = 0; Loc < NumLocations; ++Loc) {
28857330f729Sjoerg CXFile file = clang_getFile(TU, Locations[Loc].filename);
28867330f729Sjoerg if (!file)
28877330f729Sjoerg continue;
28887330f729Sjoerg
28897330f729Sjoerg Cursor = clang_getCursor(TU,
28907330f729Sjoerg clang_getLocation(TU, file, Locations[Loc].line,
28917330f729Sjoerg Locations[Loc].column));
28927330f729Sjoerg
28937330f729Sjoerg if (checkForErrors(TU) != 0)
28947330f729Sjoerg return -1;
28957330f729Sjoerg
28967330f729Sjoerg if (I + 1 == Repeats) {
28977330f729Sjoerg handler(Cursor);
28987330f729Sjoerg free(Locations[Loc].filename);
28997330f729Sjoerg }
29007330f729Sjoerg }
29017330f729Sjoerg }
29027330f729Sjoerg
29037330f729Sjoerg PrintDiagnostics(TU);
29047330f729Sjoerg clang_disposeTranslationUnit(TU);
29057330f729Sjoerg clang_disposeIndex(CIdx);
29067330f729Sjoerg free(Locations);
29077330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
29087330f729Sjoerg return 0;
29097330f729Sjoerg }
29107330f729Sjoerg
inspect_print_cursor(CXCursor Cursor)29117330f729Sjoerg static void inspect_print_cursor(CXCursor Cursor) {
29127330f729Sjoerg CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
29137330f729Sjoerg CXCompletionString completionString = clang_getCursorCompletionString(
29147330f729Sjoerg Cursor);
29157330f729Sjoerg CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor);
29167330f729Sjoerg CXString Spelling;
29177330f729Sjoerg const char *cspell;
29187330f729Sjoerg unsigned line, column;
29197330f729Sjoerg clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
29207330f729Sjoerg printf("%d:%d ", line, column);
29217330f729Sjoerg PrintCursor(Cursor, NULL);
29227330f729Sjoerg PrintCursorExtent(Cursor);
29237330f729Sjoerg Spelling = clang_getCursorSpelling(Cursor);
29247330f729Sjoerg cspell = clang_getCString(Spelling);
29257330f729Sjoerg if (cspell && strlen(cspell) != 0) {
29267330f729Sjoerg unsigned pieceIndex;
29277330f729Sjoerg printf(" Spelling=%s (", cspell);
29287330f729Sjoerg for (pieceIndex = 0; ; ++pieceIndex) {
29297330f729Sjoerg CXSourceRange range =
29307330f729Sjoerg clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
29317330f729Sjoerg if (clang_Range_isNull(range))
29327330f729Sjoerg break;
29337330f729Sjoerg PrintRange(range, 0);
29347330f729Sjoerg }
29357330f729Sjoerg printf(")");
29367330f729Sjoerg }
29377330f729Sjoerg clang_disposeString(Spelling);
29387330f729Sjoerg if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1)
29397330f729Sjoerg printf(" Selector index=%d",
29407330f729Sjoerg clang_Cursor_getObjCSelectorIndex(Cursor));
29417330f729Sjoerg if (clang_Cursor_isDynamicCall(Cursor))
29427330f729Sjoerg printf(" Dynamic-call");
29437330f729Sjoerg if (Cursor.kind == CXCursor_ObjCMessageExpr ||
29447330f729Sjoerg Cursor.kind == CXCursor_MemberRefExpr) {
29457330f729Sjoerg CXType T = clang_Cursor_getReceiverType(Cursor);
29467330f729Sjoerg if (T.kind != CXType_Invalid) {
29477330f729Sjoerg CXString S = clang_getTypeKindSpelling(T.kind);
29487330f729Sjoerg printf(" Receiver-type=%s", clang_getCString(S));
29497330f729Sjoerg clang_disposeString(S);
29507330f729Sjoerg }
29517330f729Sjoerg }
29527330f729Sjoerg
29537330f729Sjoerg {
29547330f729Sjoerg CXModule mod = clang_Cursor_getModule(Cursor);
29557330f729Sjoerg CXFile astFile;
29567330f729Sjoerg CXString name, astFilename;
29577330f729Sjoerg unsigned i, numHeaders;
29587330f729Sjoerg if (mod) {
29597330f729Sjoerg astFile = clang_Module_getASTFile(mod);
29607330f729Sjoerg astFilename = clang_getFileName(astFile);
29617330f729Sjoerg name = clang_Module_getFullName(mod);
29627330f729Sjoerg numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod);
29637330f729Sjoerg printf(" ModuleName=%s (%s) system=%d Headers(%d):",
29647330f729Sjoerg clang_getCString(name), clang_getCString(astFilename),
29657330f729Sjoerg clang_Module_isSystem(mod), numHeaders);
29667330f729Sjoerg clang_disposeString(name);
29677330f729Sjoerg clang_disposeString(astFilename);
29687330f729Sjoerg for (i = 0; i < numHeaders; ++i) {
29697330f729Sjoerg CXFile file = clang_Module_getTopLevelHeader(TU, mod, i);
29707330f729Sjoerg CXString filename = clang_getFileName(file);
29717330f729Sjoerg printf("\n%s", clang_getCString(filename));
29727330f729Sjoerg clang_disposeString(filename);
29737330f729Sjoerg }
29747330f729Sjoerg }
29757330f729Sjoerg }
29767330f729Sjoerg
29777330f729Sjoerg if (completionString != NULL) {
29787330f729Sjoerg printf("\nCompletion string: ");
29797330f729Sjoerg print_completion_string(completionString, stdout);
29807330f729Sjoerg }
29817330f729Sjoerg printf("\n");
29827330f729Sjoerg }
29837330f729Sjoerg
display_evaluate_results(CXEvalResult result)29847330f729Sjoerg static void display_evaluate_results(CXEvalResult result) {
29857330f729Sjoerg switch (clang_EvalResult_getKind(result)) {
29867330f729Sjoerg case CXEval_Int:
29877330f729Sjoerg {
29887330f729Sjoerg printf("Kind: Int, ");
29897330f729Sjoerg if (clang_EvalResult_isUnsignedInt(result)) {
29907330f729Sjoerg unsigned long long val = clang_EvalResult_getAsUnsigned(result);
29917330f729Sjoerg printf("unsigned, Value: %llu", val);
29927330f729Sjoerg } else {
29937330f729Sjoerg long long val = clang_EvalResult_getAsLongLong(result);
29947330f729Sjoerg printf("Value: %lld", val);
29957330f729Sjoerg }
29967330f729Sjoerg break;
29977330f729Sjoerg }
29987330f729Sjoerg case CXEval_Float:
29997330f729Sjoerg {
30007330f729Sjoerg double val = clang_EvalResult_getAsDouble(result);
30017330f729Sjoerg printf("Kind: Float , Value: %f", val);
30027330f729Sjoerg break;
30037330f729Sjoerg }
30047330f729Sjoerg case CXEval_ObjCStrLiteral:
30057330f729Sjoerg {
30067330f729Sjoerg const char* str = clang_EvalResult_getAsStr(result);
30077330f729Sjoerg printf("Kind: ObjCString , Value: %s", str);
30087330f729Sjoerg break;
30097330f729Sjoerg }
30107330f729Sjoerg case CXEval_StrLiteral:
30117330f729Sjoerg {
30127330f729Sjoerg const char* str = clang_EvalResult_getAsStr(result);
30137330f729Sjoerg printf("Kind: CString , Value: %s", str);
30147330f729Sjoerg break;
30157330f729Sjoerg }
30167330f729Sjoerg case CXEval_CFStr:
30177330f729Sjoerg {
30187330f729Sjoerg const char* str = clang_EvalResult_getAsStr(result);
30197330f729Sjoerg printf("Kind: CFString , Value: %s", str);
30207330f729Sjoerg break;
30217330f729Sjoerg }
30227330f729Sjoerg default:
30237330f729Sjoerg printf("Unexposed");
30247330f729Sjoerg break;
30257330f729Sjoerg }
30267330f729Sjoerg }
30277330f729Sjoerg
inspect_evaluate_cursor(CXCursor Cursor)30287330f729Sjoerg static void inspect_evaluate_cursor(CXCursor Cursor) {
30297330f729Sjoerg CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor);
30307330f729Sjoerg CXString Spelling;
30317330f729Sjoerg const char *cspell;
30327330f729Sjoerg unsigned line, column;
30337330f729Sjoerg CXEvalResult ER;
30347330f729Sjoerg
30357330f729Sjoerg clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
30367330f729Sjoerg printf("%d:%d ", line, column);
30377330f729Sjoerg PrintCursor(Cursor, NULL);
30387330f729Sjoerg PrintCursorExtent(Cursor);
30397330f729Sjoerg Spelling = clang_getCursorSpelling(Cursor);
30407330f729Sjoerg cspell = clang_getCString(Spelling);
30417330f729Sjoerg if (cspell && strlen(cspell) != 0) {
30427330f729Sjoerg unsigned pieceIndex;
30437330f729Sjoerg printf(" Spelling=%s (", cspell);
30447330f729Sjoerg for (pieceIndex = 0; ; ++pieceIndex) {
30457330f729Sjoerg CXSourceRange range =
30467330f729Sjoerg clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
30477330f729Sjoerg if (clang_Range_isNull(range))
30487330f729Sjoerg break;
30497330f729Sjoerg PrintRange(range, 0);
30507330f729Sjoerg }
30517330f729Sjoerg printf(")");
30527330f729Sjoerg }
30537330f729Sjoerg clang_disposeString(Spelling);
30547330f729Sjoerg
30557330f729Sjoerg ER = clang_Cursor_Evaluate(Cursor);
30567330f729Sjoerg if (!ER) {
30577330f729Sjoerg printf("Not Evaluatable");
30587330f729Sjoerg } else {
30597330f729Sjoerg display_evaluate_results(ER);
30607330f729Sjoerg clang_EvalResult_dispose(ER);
30617330f729Sjoerg }
30627330f729Sjoerg printf("\n");
30637330f729Sjoerg }
30647330f729Sjoerg
inspect_macroinfo_cursor(CXCursor Cursor)30657330f729Sjoerg static void inspect_macroinfo_cursor(CXCursor Cursor) {
30667330f729Sjoerg CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor);
30677330f729Sjoerg CXString Spelling;
30687330f729Sjoerg const char *cspell;
30697330f729Sjoerg unsigned line, column;
30707330f729Sjoerg clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
30717330f729Sjoerg printf("%d:%d ", line, column);
30727330f729Sjoerg PrintCursor(Cursor, NULL);
30737330f729Sjoerg PrintCursorExtent(Cursor);
30747330f729Sjoerg Spelling = clang_getCursorSpelling(Cursor);
30757330f729Sjoerg cspell = clang_getCString(Spelling);
30767330f729Sjoerg if (cspell && strlen(cspell) != 0) {
30777330f729Sjoerg unsigned pieceIndex;
30787330f729Sjoerg printf(" Spelling=%s (", cspell);
30797330f729Sjoerg for (pieceIndex = 0; ; ++pieceIndex) {
30807330f729Sjoerg CXSourceRange range =
30817330f729Sjoerg clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
30827330f729Sjoerg if (clang_Range_isNull(range))
30837330f729Sjoerg break;
30847330f729Sjoerg PrintRange(range, 0);
30857330f729Sjoerg }
30867330f729Sjoerg printf(")");
30877330f729Sjoerg }
30887330f729Sjoerg clang_disposeString(Spelling);
30897330f729Sjoerg
30907330f729Sjoerg if (clang_Cursor_isMacroBuiltin(Cursor)) {
30917330f729Sjoerg printf("[builtin macro]");
30927330f729Sjoerg } else if (clang_Cursor_isMacroFunctionLike(Cursor)) {
30937330f729Sjoerg printf("[function macro]");
30947330f729Sjoerg }
30957330f729Sjoerg printf("\n");
30967330f729Sjoerg }
30977330f729Sjoerg
findFileRefsVisit(void * context,CXCursor cursor,CXSourceRange range)30987330f729Sjoerg static enum CXVisitorResult findFileRefsVisit(void *context,
30997330f729Sjoerg CXCursor cursor, CXSourceRange range) {
31007330f729Sjoerg if (clang_Range_isNull(range))
31017330f729Sjoerg return CXVisit_Continue;
31027330f729Sjoerg
31037330f729Sjoerg PrintCursor(cursor, NULL);
31047330f729Sjoerg PrintRange(range, "");
31057330f729Sjoerg printf("\n");
31067330f729Sjoerg return CXVisit_Continue;
31077330f729Sjoerg }
31087330f729Sjoerg
find_file_refs_at(int argc,const char ** argv)31097330f729Sjoerg static int find_file_refs_at(int argc, const char **argv) {
31107330f729Sjoerg CXIndex CIdx;
31117330f729Sjoerg int errorCode;
31127330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
31137330f729Sjoerg int num_unsaved_files = 0;
31147330f729Sjoerg enum CXErrorCode Err;
31157330f729Sjoerg CXTranslationUnit TU;
31167330f729Sjoerg CXCursor Cursor;
31177330f729Sjoerg CursorSourceLocation *Locations = 0;
31187330f729Sjoerg unsigned NumLocations = 0, Loc;
31197330f729Sjoerg unsigned Repeats = 1;
31207330f729Sjoerg unsigned I;
31217330f729Sjoerg
31227330f729Sjoerg /* Count the number of locations. */
31237330f729Sjoerg while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1])
31247330f729Sjoerg ++NumLocations;
31257330f729Sjoerg
31267330f729Sjoerg /* Parse the locations. */
31277330f729Sjoerg assert(NumLocations > 0 && "Unable to count locations?");
31287330f729Sjoerg Locations = (CursorSourceLocation *)malloc(
31297330f729Sjoerg NumLocations * sizeof(CursorSourceLocation));
31307330f729Sjoerg assert(Locations);
31317330f729Sjoerg for (Loc = 0; Loc < NumLocations; ++Loc) {
31327330f729Sjoerg const char *input = argv[Loc + 1] + strlen("-file-refs-at=");
31337330f729Sjoerg if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
31347330f729Sjoerg &Locations[Loc].line,
31357330f729Sjoerg &Locations[Loc].column, 0, 0)))
31367330f729Sjoerg return errorCode;
31377330f729Sjoerg }
31387330f729Sjoerg
31397330f729Sjoerg if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
31407330f729Sjoerg &num_unsaved_files))
31417330f729Sjoerg return -1;
31427330f729Sjoerg
31437330f729Sjoerg if (getenv("CINDEXTEST_EDITING"))
31447330f729Sjoerg Repeats = 5;
31457330f729Sjoerg
31467330f729Sjoerg /* Parse the translation unit. When we're testing clang_getCursor() after
31477330f729Sjoerg reparsing, don't remap unsaved files until the second parse. */
31487330f729Sjoerg CIdx = clang_createIndex(1, 1);
31497330f729Sjoerg Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
31507330f729Sjoerg argv + num_unsaved_files + 1 + NumLocations,
31517330f729Sjoerg argc - num_unsaved_files - 2 - NumLocations,
31527330f729Sjoerg unsaved_files,
31537330f729Sjoerg Repeats > 1? 0 : num_unsaved_files,
31547330f729Sjoerg getDefaultParsingOptions(), &TU);
31557330f729Sjoerg if (Err != CXError_Success) {
31567330f729Sjoerg fprintf(stderr, "unable to parse input\n");
31577330f729Sjoerg describeLibclangFailure(Err);
31587330f729Sjoerg clang_disposeTranslationUnit(TU);
31597330f729Sjoerg return -1;
31607330f729Sjoerg }
31617330f729Sjoerg
31627330f729Sjoerg if (checkForErrors(TU) != 0)
31637330f729Sjoerg return -1;
31647330f729Sjoerg
31657330f729Sjoerg for (I = 0; I != Repeats; ++I) {
31667330f729Sjoerg if (Repeats > 1) {
31677330f729Sjoerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
31687330f729Sjoerg clang_defaultReparseOptions(TU));
31697330f729Sjoerg if (Err != CXError_Success) {
31707330f729Sjoerg describeLibclangFailure(Err);
31717330f729Sjoerg clang_disposeTranslationUnit(TU);
31727330f729Sjoerg return 1;
31737330f729Sjoerg }
31747330f729Sjoerg }
31757330f729Sjoerg
31767330f729Sjoerg if (checkForErrors(TU) != 0)
31777330f729Sjoerg return -1;
31787330f729Sjoerg
31797330f729Sjoerg for (Loc = 0; Loc < NumLocations; ++Loc) {
31807330f729Sjoerg CXFile file = clang_getFile(TU, Locations[Loc].filename);
31817330f729Sjoerg if (!file)
31827330f729Sjoerg continue;
31837330f729Sjoerg
31847330f729Sjoerg Cursor = clang_getCursor(TU,
31857330f729Sjoerg clang_getLocation(TU, file, Locations[Loc].line,
31867330f729Sjoerg Locations[Loc].column));
31877330f729Sjoerg
31887330f729Sjoerg if (checkForErrors(TU) != 0)
31897330f729Sjoerg return -1;
31907330f729Sjoerg
31917330f729Sjoerg if (I + 1 == Repeats) {
31927330f729Sjoerg CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit };
31937330f729Sjoerg PrintCursor(Cursor, NULL);
31947330f729Sjoerg printf("\n");
31957330f729Sjoerg clang_findReferencesInFile(Cursor, file, visitor);
31967330f729Sjoerg free(Locations[Loc].filename);
31977330f729Sjoerg
31987330f729Sjoerg if (checkForErrors(TU) != 0)
31997330f729Sjoerg return -1;
32007330f729Sjoerg }
32017330f729Sjoerg }
32027330f729Sjoerg }
32037330f729Sjoerg
32047330f729Sjoerg PrintDiagnostics(TU);
32057330f729Sjoerg clang_disposeTranslationUnit(TU);
32067330f729Sjoerg clang_disposeIndex(CIdx);
32077330f729Sjoerg free(Locations);
32087330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
32097330f729Sjoerg return 0;
32107330f729Sjoerg }
32117330f729Sjoerg
findFileIncludesVisit(void * context,CXCursor cursor,CXSourceRange range)32127330f729Sjoerg static enum CXVisitorResult findFileIncludesVisit(void *context,
32137330f729Sjoerg CXCursor cursor, CXSourceRange range) {
32147330f729Sjoerg PrintCursor(cursor, NULL);
32157330f729Sjoerg PrintRange(range, "");
32167330f729Sjoerg printf("\n");
32177330f729Sjoerg return CXVisit_Continue;
32187330f729Sjoerg }
32197330f729Sjoerg
find_file_includes_in(int argc,const char ** argv)32207330f729Sjoerg static int find_file_includes_in(int argc, const char **argv) {
32217330f729Sjoerg CXIndex CIdx;
32227330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
32237330f729Sjoerg int num_unsaved_files = 0;
32247330f729Sjoerg enum CXErrorCode Err;
32257330f729Sjoerg CXTranslationUnit TU;
32267330f729Sjoerg const char **Filenames = 0;
32277330f729Sjoerg unsigned NumFilenames = 0;
32287330f729Sjoerg unsigned Repeats = 1;
32297330f729Sjoerg unsigned I, FI;
32307330f729Sjoerg
32317330f729Sjoerg /* Count the number of locations. */
32327330f729Sjoerg while (strstr(argv[NumFilenames+1], "-file-includes-in=") == argv[NumFilenames+1])
32337330f729Sjoerg ++NumFilenames;
32347330f729Sjoerg
32357330f729Sjoerg /* Parse the locations. */
32367330f729Sjoerg assert(NumFilenames > 0 && "Unable to count filenames?");
32377330f729Sjoerg Filenames = (const char **)malloc(NumFilenames * sizeof(const char *));
32387330f729Sjoerg assert(Filenames);
32397330f729Sjoerg for (I = 0; I < NumFilenames; ++I) {
32407330f729Sjoerg const char *input = argv[I + 1] + strlen("-file-includes-in=");
32417330f729Sjoerg /* Copy the file name. */
32427330f729Sjoerg Filenames[I] = input;
32437330f729Sjoerg }
32447330f729Sjoerg
32457330f729Sjoerg if (parse_remapped_files(argc, argv, NumFilenames + 1, &unsaved_files,
32467330f729Sjoerg &num_unsaved_files))
32477330f729Sjoerg return -1;
32487330f729Sjoerg
32497330f729Sjoerg if (getenv("CINDEXTEST_EDITING"))
32507330f729Sjoerg Repeats = 2;
32517330f729Sjoerg
32527330f729Sjoerg /* Parse the translation unit. When we're testing clang_getCursor() after
32537330f729Sjoerg reparsing, don't remap unsaved files until the second parse. */
32547330f729Sjoerg CIdx = clang_createIndex(1, 1);
32557330f729Sjoerg Err = clang_parseTranslationUnit2(
32567330f729Sjoerg CIdx, argv[argc - 1],
32577330f729Sjoerg argv + num_unsaved_files + 1 + NumFilenames,
32587330f729Sjoerg argc - num_unsaved_files - 2 - NumFilenames,
32597330f729Sjoerg unsaved_files,
32607330f729Sjoerg Repeats > 1 ? 0 : num_unsaved_files, getDefaultParsingOptions(), &TU);
32617330f729Sjoerg
32627330f729Sjoerg if (Err != CXError_Success) {
32637330f729Sjoerg fprintf(stderr, "unable to parse input\n");
32647330f729Sjoerg describeLibclangFailure(Err);
32657330f729Sjoerg clang_disposeTranslationUnit(TU);
32667330f729Sjoerg return -1;
32677330f729Sjoerg }
32687330f729Sjoerg
32697330f729Sjoerg if (checkForErrors(TU) != 0)
32707330f729Sjoerg return -1;
32717330f729Sjoerg
32727330f729Sjoerg for (I = 0; I != Repeats; ++I) {
32737330f729Sjoerg if (Repeats > 1) {
32747330f729Sjoerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
32757330f729Sjoerg clang_defaultReparseOptions(TU));
32767330f729Sjoerg if (Err != CXError_Success) {
32777330f729Sjoerg describeLibclangFailure(Err);
32787330f729Sjoerg clang_disposeTranslationUnit(TU);
32797330f729Sjoerg return 1;
32807330f729Sjoerg }
32817330f729Sjoerg }
32827330f729Sjoerg
32837330f729Sjoerg if (checkForErrors(TU) != 0)
32847330f729Sjoerg return -1;
32857330f729Sjoerg
32867330f729Sjoerg for (FI = 0; FI < NumFilenames; ++FI) {
32877330f729Sjoerg CXFile file = clang_getFile(TU, Filenames[FI]);
32887330f729Sjoerg if (!file)
32897330f729Sjoerg continue;
32907330f729Sjoerg
32917330f729Sjoerg if (checkForErrors(TU) != 0)
32927330f729Sjoerg return -1;
32937330f729Sjoerg
32947330f729Sjoerg if (I + 1 == Repeats) {
32957330f729Sjoerg CXCursorAndRangeVisitor visitor = { 0, findFileIncludesVisit };
32967330f729Sjoerg clang_findIncludesInFile(TU, file, visitor);
32977330f729Sjoerg
32987330f729Sjoerg if (checkForErrors(TU) != 0)
32997330f729Sjoerg return -1;
33007330f729Sjoerg }
33017330f729Sjoerg }
33027330f729Sjoerg }
33037330f729Sjoerg
33047330f729Sjoerg PrintDiagnostics(TU);
33057330f729Sjoerg clang_disposeTranslationUnit(TU);
33067330f729Sjoerg clang_disposeIndex(CIdx);
33077330f729Sjoerg free((void *)Filenames);
33087330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
33097330f729Sjoerg return 0;
33107330f729Sjoerg }
33117330f729Sjoerg
33127330f729Sjoerg #define MAX_IMPORTED_ASTFILES 200
33137330f729Sjoerg
33147330f729Sjoerg typedef struct {
33157330f729Sjoerg char **filenames;
33167330f729Sjoerg unsigned num_files;
33177330f729Sjoerg } ImportedASTFilesData;
33187330f729Sjoerg
importedASTs_create()33197330f729Sjoerg static ImportedASTFilesData *importedASTs_create() {
33207330f729Sjoerg ImportedASTFilesData *p;
33217330f729Sjoerg p = malloc(sizeof(ImportedASTFilesData));
33227330f729Sjoerg assert(p);
33237330f729Sjoerg p->filenames = malloc(MAX_IMPORTED_ASTFILES * sizeof(const char *));
33247330f729Sjoerg assert(p->filenames);
33257330f729Sjoerg p->num_files = 0;
33267330f729Sjoerg return p;
33277330f729Sjoerg }
33287330f729Sjoerg
importedASTs_dispose(ImportedASTFilesData * p)33297330f729Sjoerg static void importedASTs_dispose(ImportedASTFilesData *p) {
33307330f729Sjoerg unsigned i;
33317330f729Sjoerg if (!p)
33327330f729Sjoerg return;
33337330f729Sjoerg
33347330f729Sjoerg for (i = 0; i < p->num_files; ++i)
33357330f729Sjoerg free(p->filenames[i]);
33367330f729Sjoerg free(p->filenames);
33377330f729Sjoerg free(p);
33387330f729Sjoerg }
33397330f729Sjoerg
importedASTS_insert(ImportedASTFilesData * p,const char * file)33407330f729Sjoerg static void importedASTS_insert(ImportedASTFilesData *p, const char *file) {
33417330f729Sjoerg unsigned i;
33427330f729Sjoerg assert(p && file);
33437330f729Sjoerg for (i = 0; i < p->num_files; ++i)
33447330f729Sjoerg if (strcmp(file, p->filenames[i]) == 0)
33457330f729Sjoerg return;
33467330f729Sjoerg assert(p->num_files + 1 < MAX_IMPORTED_ASTFILES);
33477330f729Sjoerg p->filenames[p->num_files++] = strdup(file);
33487330f729Sjoerg }
33497330f729Sjoerg
33507330f729Sjoerg typedef struct IndexDataStringList_ {
33517330f729Sjoerg struct IndexDataStringList_ *next;
33527330f729Sjoerg char data[1]; /* Dynamically sized. */
33537330f729Sjoerg } IndexDataStringList;
33547330f729Sjoerg
33557330f729Sjoerg typedef struct {
33567330f729Sjoerg const char *check_prefix;
33577330f729Sjoerg int first_check_printed;
33587330f729Sjoerg int fail_for_error;
33597330f729Sjoerg int abort;
33607330f729Sjoerg CXString main_filename;
33617330f729Sjoerg ImportedASTFilesData *importedASTs;
33627330f729Sjoerg IndexDataStringList *strings;
33637330f729Sjoerg CXTranslationUnit TU;
33647330f729Sjoerg } IndexData;
33657330f729Sjoerg
free_client_data(IndexData * index_data)33667330f729Sjoerg static void free_client_data(IndexData *index_data) {
33677330f729Sjoerg IndexDataStringList *node = index_data->strings;
33687330f729Sjoerg while (node) {
33697330f729Sjoerg IndexDataStringList *next = node->next;
33707330f729Sjoerg free(node);
33717330f729Sjoerg node = next;
33727330f729Sjoerg }
33737330f729Sjoerg index_data->strings = NULL;
33747330f729Sjoerg }
33757330f729Sjoerg
printCheck(IndexData * data)33767330f729Sjoerg static void printCheck(IndexData *data) {
33777330f729Sjoerg if (data->check_prefix) {
33787330f729Sjoerg if (data->first_check_printed) {
33797330f729Sjoerg printf("// %s-NEXT: ", data->check_prefix);
33807330f729Sjoerg } else {
33817330f729Sjoerg printf("// %s : ", data->check_prefix);
33827330f729Sjoerg data->first_check_printed = 1;
33837330f729Sjoerg }
33847330f729Sjoerg }
33857330f729Sjoerg }
33867330f729Sjoerg
printCXIndexFile(CXIdxClientFile file)33877330f729Sjoerg static void printCXIndexFile(CXIdxClientFile file) {
33887330f729Sjoerg CXString filename = clang_getFileName((CXFile)file);
33897330f729Sjoerg printf("%s", clang_getCString(filename));
33907330f729Sjoerg clang_disposeString(filename);
33917330f729Sjoerg }
33927330f729Sjoerg
printCXIndexLoc(CXIdxLoc loc,CXClientData client_data)33937330f729Sjoerg static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) {
33947330f729Sjoerg IndexData *index_data;
33957330f729Sjoerg CXString filename;
33967330f729Sjoerg const char *cname;
33977330f729Sjoerg CXIdxClientFile file;
33987330f729Sjoerg unsigned line, column;
33997330f729Sjoerg const char *main_filename;
34007330f729Sjoerg int isMainFile;
34017330f729Sjoerg
34027330f729Sjoerg index_data = (IndexData *)client_data;
34037330f729Sjoerg clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
34047330f729Sjoerg if (line == 0) {
34057330f729Sjoerg printf("<invalid>");
34067330f729Sjoerg return;
34077330f729Sjoerg }
34087330f729Sjoerg if (!file) {
34097330f729Sjoerg printf("<no idxfile>");
34107330f729Sjoerg return;
34117330f729Sjoerg }
34127330f729Sjoerg filename = clang_getFileName((CXFile)file);
34137330f729Sjoerg cname = clang_getCString(filename);
34147330f729Sjoerg main_filename = clang_getCString(index_data->main_filename);
34157330f729Sjoerg if (strcmp(cname, main_filename) == 0)
34167330f729Sjoerg isMainFile = 1;
34177330f729Sjoerg else
34187330f729Sjoerg isMainFile = 0;
34197330f729Sjoerg clang_disposeString(filename);
34207330f729Sjoerg
34217330f729Sjoerg if (!isMainFile) {
34227330f729Sjoerg printCXIndexFile(file);
34237330f729Sjoerg printf(":");
34247330f729Sjoerg }
34257330f729Sjoerg printf("%d:%d", line, column);
34267330f729Sjoerg }
34277330f729Sjoerg
digitCount(unsigned val)34287330f729Sjoerg static unsigned digitCount(unsigned val) {
34297330f729Sjoerg unsigned c = 1;
34307330f729Sjoerg while (1) {
34317330f729Sjoerg if (val < 10)
34327330f729Sjoerg return c;
34337330f729Sjoerg ++c;
34347330f729Sjoerg val /= 10;
34357330f729Sjoerg }
34367330f729Sjoerg }
34377330f729Sjoerg
makeClientContainer(CXClientData * client_data,const CXIdxEntityInfo * info,CXIdxLoc loc)34387330f729Sjoerg static CXIdxClientContainer makeClientContainer(CXClientData *client_data,
34397330f729Sjoerg const CXIdxEntityInfo *info,
34407330f729Sjoerg CXIdxLoc loc) {
34417330f729Sjoerg IndexData *index_data;
34427330f729Sjoerg IndexDataStringList *node;
34437330f729Sjoerg const char *name;
34447330f729Sjoerg char *newStr;
34457330f729Sjoerg CXIdxClientFile file;
34467330f729Sjoerg unsigned line, column;
34477330f729Sjoerg
34487330f729Sjoerg name = info->name;
34497330f729Sjoerg if (!name)
34507330f729Sjoerg name = "<anon-tag>";
34517330f729Sjoerg
34527330f729Sjoerg clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
34537330f729Sjoerg
34547330f729Sjoerg node =
34557330f729Sjoerg (IndexDataStringList *)malloc(sizeof(IndexDataStringList) + strlen(name) +
34567330f729Sjoerg digitCount(line) + digitCount(column) + 2);
34577330f729Sjoerg assert(node);
34587330f729Sjoerg newStr = node->data;
34597330f729Sjoerg sprintf(newStr, "%s:%d:%d", name, line, column);
34607330f729Sjoerg
34617330f729Sjoerg /* Remember string so it can be freed later. */
34627330f729Sjoerg index_data = (IndexData *)client_data;
34637330f729Sjoerg node->next = index_data->strings;
34647330f729Sjoerg index_data->strings = node;
34657330f729Sjoerg
34667330f729Sjoerg return (CXIdxClientContainer)newStr;
34677330f729Sjoerg }
34687330f729Sjoerg
printCXIndexContainer(const CXIdxContainerInfo * info)34697330f729Sjoerg static void printCXIndexContainer(const CXIdxContainerInfo *info) {
34707330f729Sjoerg CXIdxClientContainer container;
34717330f729Sjoerg container = clang_index_getClientContainer(info);
34727330f729Sjoerg if (!container)
34737330f729Sjoerg printf("[<<NULL>>]");
34747330f729Sjoerg else
34757330f729Sjoerg printf("[%s]", (const char *)container);
34767330f729Sjoerg }
34777330f729Sjoerg
getEntityKindString(CXIdxEntityKind kind)34787330f729Sjoerg static const char *getEntityKindString(CXIdxEntityKind kind) {
34797330f729Sjoerg switch (kind) {
34807330f729Sjoerg case CXIdxEntity_Unexposed: return "<<UNEXPOSED>>";
34817330f729Sjoerg case CXIdxEntity_Typedef: return "typedef";
34827330f729Sjoerg case CXIdxEntity_Function: return "function";
34837330f729Sjoerg case CXIdxEntity_Variable: return "variable";
34847330f729Sjoerg case CXIdxEntity_Field: return "field";
34857330f729Sjoerg case CXIdxEntity_EnumConstant: return "enumerator";
34867330f729Sjoerg case CXIdxEntity_ObjCClass: return "objc-class";
34877330f729Sjoerg case CXIdxEntity_ObjCProtocol: return "objc-protocol";
34887330f729Sjoerg case CXIdxEntity_ObjCCategory: return "objc-category";
34897330f729Sjoerg case CXIdxEntity_ObjCInstanceMethod: return "objc-instance-method";
34907330f729Sjoerg case CXIdxEntity_ObjCClassMethod: return "objc-class-method";
34917330f729Sjoerg case CXIdxEntity_ObjCProperty: return "objc-property";
34927330f729Sjoerg case CXIdxEntity_ObjCIvar: return "objc-ivar";
34937330f729Sjoerg case CXIdxEntity_Enum: return "enum";
34947330f729Sjoerg case CXIdxEntity_Struct: return "struct";
34957330f729Sjoerg case CXIdxEntity_Union: return "union";
34967330f729Sjoerg case CXIdxEntity_CXXClass: return "c++-class";
34977330f729Sjoerg case CXIdxEntity_CXXNamespace: return "namespace";
34987330f729Sjoerg case CXIdxEntity_CXXNamespaceAlias: return "namespace-alias";
34997330f729Sjoerg case CXIdxEntity_CXXStaticVariable: return "c++-static-var";
35007330f729Sjoerg case CXIdxEntity_CXXStaticMethod: return "c++-static-method";
35017330f729Sjoerg case CXIdxEntity_CXXInstanceMethod: return "c++-instance-method";
35027330f729Sjoerg case CXIdxEntity_CXXConstructor: return "constructor";
35037330f729Sjoerg case CXIdxEntity_CXXDestructor: return "destructor";
35047330f729Sjoerg case CXIdxEntity_CXXConversionFunction: return "conversion-func";
35057330f729Sjoerg case CXIdxEntity_CXXTypeAlias: return "type-alias";
35067330f729Sjoerg case CXIdxEntity_CXXInterface: return "c++-__interface";
35077330f729Sjoerg }
35087330f729Sjoerg assert(0 && "Garbage entity kind");
35097330f729Sjoerg return 0;
35107330f729Sjoerg }
35117330f729Sjoerg
getEntityTemplateKindString(CXIdxEntityCXXTemplateKind kind)35127330f729Sjoerg static const char *getEntityTemplateKindString(CXIdxEntityCXXTemplateKind kind) {
35137330f729Sjoerg switch (kind) {
35147330f729Sjoerg case CXIdxEntity_NonTemplate: return "";
35157330f729Sjoerg case CXIdxEntity_Template: return "-template";
35167330f729Sjoerg case CXIdxEntity_TemplatePartialSpecialization:
35177330f729Sjoerg return "-template-partial-spec";
35187330f729Sjoerg case CXIdxEntity_TemplateSpecialization: return "-template-spec";
35197330f729Sjoerg }
35207330f729Sjoerg assert(0 && "Garbage entity kind");
35217330f729Sjoerg return 0;
35227330f729Sjoerg }
35237330f729Sjoerg
getEntityLanguageString(CXIdxEntityLanguage kind)35247330f729Sjoerg static const char *getEntityLanguageString(CXIdxEntityLanguage kind) {
35257330f729Sjoerg switch (kind) {
35267330f729Sjoerg case CXIdxEntityLang_None: return "<none>";
35277330f729Sjoerg case CXIdxEntityLang_C: return "C";
35287330f729Sjoerg case CXIdxEntityLang_ObjC: return "ObjC";
35297330f729Sjoerg case CXIdxEntityLang_CXX: return "C++";
35307330f729Sjoerg case CXIdxEntityLang_Swift: return "Swift";
35317330f729Sjoerg }
35327330f729Sjoerg assert(0 && "Garbage language kind");
35337330f729Sjoerg return 0;
35347330f729Sjoerg }
35357330f729Sjoerg
printEntityInfo(const char * cb,CXClientData client_data,const CXIdxEntityInfo * info)35367330f729Sjoerg static void printEntityInfo(const char *cb,
35377330f729Sjoerg CXClientData client_data,
35387330f729Sjoerg const CXIdxEntityInfo *info) {
35397330f729Sjoerg const char *name;
35407330f729Sjoerg IndexData *index_data;
35417330f729Sjoerg unsigned i;
35427330f729Sjoerg index_data = (IndexData *)client_data;
35437330f729Sjoerg printCheck(index_data);
35447330f729Sjoerg
35457330f729Sjoerg if (!info) {
35467330f729Sjoerg printf("%s: <<NULL>>", cb);
35477330f729Sjoerg return;
35487330f729Sjoerg }
35497330f729Sjoerg
35507330f729Sjoerg name = info->name;
35517330f729Sjoerg if (!name)
35527330f729Sjoerg name = "<anon-tag>";
35537330f729Sjoerg
35547330f729Sjoerg printf("%s: kind: %s%s", cb, getEntityKindString(info->kind),
35557330f729Sjoerg getEntityTemplateKindString(info->templateKind));
35567330f729Sjoerg printf(" | name: %s", name);
35577330f729Sjoerg printf(" | USR: %s", info->USR);
35587330f729Sjoerg printf(" | lang: %s", getEntityLanguageString(info->lang));
35597330f729Sjoerg
35607330f729Sjoerg for (i = 0; i != info->numAttributes; ++i) {
35617330f729Sjoerg const CXIdxAttrInfo *Attr = info->attributes[i];
35627330f729Sjoerg printf(" <attribute>: ");
35637330f729Sjoerg PrintCursor(Attr->cursor, NULL);
35647330f729Sjoerg }
35657330f729Sjoerg }
35667330f729Sjoerg
printBaseClassInfo(CXClientData client_data,const CXIdxBaseClassInfo * info)35677330f729Sjoerg static void printBaseClassInfo(CXClientData client_data,
35687330f729Sjoerg const CXIdxBaseClassInfo *info) {
35697330f729Sjoerg printEntityInfo(" <base>", client_data, info->base);
35707330f729Sjoerg printf(" | cursor: ");
35717330f729Sjoerg PrintCursor(info->cursor, NULL);
35727330f729Sjoerg printf(" | loc: ");
35737330f729Sjoerg printCXIndexLoc(info->loc, client_data);
35747330f729Sjoerg }
35757330f729Sjoerg
printProtocolList(const CXIdxObjCProtocolRefListInfo * ProtoInfo,CXClientData client_data)35767330f729Sjoerg static void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo,
35777330f729Sjoerg CXClientData client_data) {
35787330f729Sjoerg unsigned i;
35797330f729Sjoerg for (i = 0; i < ProtoInfo->numProtocols; ++i) {
35807330f729Sjoerg printEntityInfo(" <protocol>", client_data,
35817330f729Sjoerg ProtoInfo->protocols[i]->protocol);
35827330f729Sjoerg printf(" | cursor: ");
35837330f729Sjoerg PrintCursor(ProtoInfo->protocols[i]->cursor, NULL);
35847330f729Sjoerg printf(" | loc: ");
35857330f729Sjoerg printCXIndexLoc(ProtoInfo->protocols[i]->loc, client_data);
35867330f729Sjoerg printf("\n");
35877330f729Sjoerg }
35887330f729Sjoerg }
35897330f729Sjoerg
printSymbolRole(CXSymbolRole role)35907330f729Sjoerg static void printSymbolRole(CXSymbolRole role) {
35917330f729Sjoerg if (role & CXSymbolRole_Declaration)
35927330f729Sjoerg printf(" decl");
35937330f729Sjoerg if (role & CXSymbolRole_Definition)
35947330f729Sjoerg printf(" def");
35957330f729Sjoerg if (role & CXSymbolRole_Reference)
35967330f729Sjoerg printf(" ref");
35977330f729Sjoerg if (role & CXSymbolRole_Read)
35987330f729Sjoerg printf(" read");
35997330f729Sjoerg if (role & CXSymbolRole_Write)
36007330f729Sjoerg printf(" write");
36017330f729Sjoerg if (role & CXSymbolRole_Call)
36027330f729Sjoerg printf(" call");
36037330f729Sjoerg if (role & CXSymbolRole_Dynamic)
36047330f729Sjoerg printf(" dyn");
36057330f729Sjoerg if (role & CXSymbolRole_AddressOf)
36067330f729Sjoerg printf(" addr");
36077330f729Sjoerg if (role & CXSymbolRole_Implicit)
36087330f729Sjoerg printf(" implicit");
36097330f729Sjoerg }
36107330f729Sjoerg
index_diagnostic(CXClientData client_data,CXDiagnosticSet diagSet,void * reserved)36117330f729Sjoerg static void index_diagnostic(CXClientData client_data,
36127330f729Sjoerg CXDiagnosticSet diagSet, void *reserved) {
36137330f729Sjoerg CXString str;
36147330f729Sjoerg const char *cstr;
36157330f729Sjoerg unsigned numDiags, i;
36167330f729Sjoerg CXDiagnostic diag;
36177330f729Sjoerg IndexData *index_data;
36187330f729Sjoerg index_data = (IndexData *)client_data;
36197330f729Sjoerg printCheck(index_data);
36207330f729Sjoerg
36217330f729Sjoerg numDiags = clang_getNumDiagnosticsInSet(diagSet);
36227330f729Sjoerg for (i = 0; i != numDiags; ++i) {
36237330f729Sjoerg diag = clang_getDiagnosticInSet(diagSet, i);
36247330f729Sjoerg str = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
36257330f729Sjoerg cstr = clang_getCString(str);
36267330f729Sjoerg printf("[diagnostic]: %s\n", cstr);
36277330f729Sjoerg clang_disposeString(str);
36287330f729Sjoerg
36297330f729Sjoerg if (getenv("CINDEXTEST_FAILONERROR") &&
36307330f729Sjoerg clang_getDiagnosticSeverity(diag) >= CXDiagnostic_Error) {
36317330f729Sjoerg index_data->fail_for_error = 1;
36327330f729Sjoerg }
36337330f729Sjoerg }
36347330f729Sjoerg }
36357330f729Sjoerg
index_enteredMainFile(CXClientData client_data,CXFile file,void * reserved)36367330f729Sjoerg static CXIdxClientFile index_enteredMainFile(CXClientData client_data,
36377330f729Sjoerg CXFile file, void *reserved) {
36387330f729Sjoerg IndexData *index_data;
36397330f729Sjoerg
36407330f729Sjoerg index_data = (IndexData *)client_data;
36417330f729Sjoerg printCheck(index_data);
36427330f729Sjoerg
36437330f729Sjoerg index_data->main_filename = clang_getFileName(file);
36447330f729Sjoerg
36457330f729Sjoerg printf("[enteredMainFile]: ");
36467330f729Sjoerg printCXIndexFile((CXIdxClientFile)file);
36477330f729Sjoerg printf("\n");
36487330f729Sjoerg
36497330f729Sjoerg return (CXIdxClientFile)file;
36507330f729Sjoerg }
36517330f729Sjoerg
index_ppIncludedFile(CXClientData client_data,const CXIdxIncludedFileInfo * info)36527330f729Sjoerg static CXIdxClientFile index_ppIncludedFile(CXClientData client_data,
36537330f729Sjoerg const CXIdxIncludedFileInfo *info) {
36547330f729Sjoerg IndexData *index_data;
36557330f729Sjoerg CXModule Mod;
36567330f729Sjoerg index_data = (IndexData *)client_data;
36577330f729Sjoerg printCheck(index_data);
36587330f729Sjoerg
36597330f729Sjoerg printf("[ppIncludedFile]: ");
36607330f729Sjoerg printCXIndexFile((CXIdxClientFile)info->file);
36617330f729Sjoerg printf(" | name: \"%s\"", info->filename);
36627330f729Sjoerg printf(" | hash loc: ");
36637330f729Sjoerg printCXIndexLoc(info->hashLoc, client_data);
36647330f729Sjoerg printf(" | isImport: %d | isAngled: %d | isModule: %d",
36657330f729Sjoerg info->isImport, info->isAngled, info->isModuleImport);
36667330f729Sjoerg
36677330f729Sjoerg Mod = clang_getModuleForFile(index_data->TU, (CXFile)info->file);
36687330f729Sjoerg if (Mod) {
36697330f729Sjoerg CXString str = clang_Module_getFullName(Mod);
36707330f729Sjoerg const char *cstr = clang_getCString(str);
36717330f729Sjoerg printf(" | module: %s", cstr);
36727330f729Sjoerg clang_disposeString(str);
36737330f729Sjoerg }
36747330f729Sjoerg
36757330f729Sjoerg printf("\n");
36767330f729Sjoerg
36777330f729Sjoerg return (CXIdxClientFile)info->file;
36787330f729Sjoerg }
36797330f729Sjoerg
index_importedASTFile(CXClientData client_data,const CXIdxImportedASTFileInfo * info)36807330f729Sjoerg static CXIdxClientFile index_importedASTFile(CXClientData client_data,
36817330f729Sjoerg const CXIdxImportedASTFileInfo *info) {
36827330f729Sjoerg IndexData *index_data;
36837330f729Sjoerg index_data = (IndexData *)client_data;
36847330f729Sjoerg printCheck(index_data);
36857330f729Sjoerg
36867330f729Sjoerg if (index_data->importedASTs) {
36877330f729Sjoerg CXString filename = clang_getFileName(info->file);
36887330f729Sjoerg importedASTS_insert(index_data->importedASTs, clang_getCString(filename));
36897330f729Sjoerg clang_disposeString(filename);
36907330f729Sjoerg }
36917330f729Sjoerg
36927330f729Sjoerg printf("[importedASTFile]: ");
36937330f729Sjoerg printCXIndexFile((CXIdxClientFile)info->file);
36947330f729Sjoerg if (info->module) {
36957330f729Sjoerg CXString name = clang_Module_getFullName(info->module);
36967330f729Sjoerg printf(" | loc: ");
36977330f729Sjoerg printCXIndexLoc(info->loc, client_data);
36987330f729Sjoerg printf(" | name: \"%s\"", clang_getCString(name));
36997330f729Sjoerg printf(" | isImplicit: %d\n", info->isImplicit);
37007330f729Sjoerg clang_disposeString(name);
37017330f729Sjoerg } else {
37027330f729Sjoerg /* PCH file, the rest are not relevant. */
37037330f729Sjoerg printf("\n");
37047330f729Sjoerg }
37057330f729Sjoerg
37067330f729Sjoerg return (CXIdxClientFile)info->file;
37077330f729Sjoerg }
37087330f729Sjoerg
37097330f729Sjoerg static CXIdxClientContainer
index_startedTranslationUnit(CXClientData client_data,void * reserved)37107330f729Sjoerg index_startedTranslationUnit(CXClientData client_data, void *reserved) {
37117330f729Sjoerg IndexData *index_data;
37127330f729Sjoerg index_data = (IndexData *)client_data;
37137330f729Sjoerg printCheck(index_data);
37147330f729Sjoerg
37157330f729Sjoerg printf("[startedTranslationUnit]\n");
37167330f729Sjoerg return (CXIdxClientContainer)"TU";
37177330f729Sjoerg }
37187330f729Sjoerg
index_indexDeclaration(CXClientData client_data,const CXIdxDeclInfo * info)37197330f729Sjoerg static void index_indexDeclaration(CXClientData client_data,
37207330f729Sjoerg const CXIdxDeclInfo *info) {
37217330f729Sjoerg IndexData *index_data;
37227330f729Sjoerg const CXIdxObjCCategoryDeclInfo *CatInfo;
37237330f729Sjoerg const CXIdxObjCInterfaceDeclInfo *InterInfo;
37247330f729Sjoerg const CXIdxObjCProtocolRefListInfo *ProtoInfo;
37257330f729Sjoerg const CXIdxObjCPropertyDeclInfo *PropInfo;
37267330f729Sjoerg const CXIdxCXXClassDeclInfo *CXXClassInfo;
37277330f729Sjoerg unsigned i;
37287330f729Sjoerg index_data = (IndexData *)client_data;
37297330f729Sjoerg
37307330f729Sjoerg printEntityInfo("[indexDeclaration]", client_data, info->entityInfo);
37317330f729Sjoerg printf(" | cursor: ");
37327330f729Sjoerg PrintCursor(info->cursor, NULL);
37337330f729Sjoerg printf(" | loc: ");
37347330f729Sjoerg printCXIndexLoc(info->loc, client_data);
37357330f729Sjoerg printf(" | semantic-container: ");
37367330f729Sjoerg printCXIndexContainer(info->semanticContainer);
37377330f729Sjoerg printf(" | lexical-container: ");
37387330f729Sjoerg printCXIndexContainer(info->lexicalContainer);
37397330f729Sjoerg printf(" | isRedecl: %d", info->isRedeclaration);
37407330f729Sjoerg printf(" | isDef: %d", info->isDefinition);
37417330f729Sjoerg if (info->flags & CXIdxDeclFlag_Skipped) {
37427330f729Sjoerg assert(!info->isContainer);
37437330f729Sjoerg printf(" | isContainer: skipped");
37447330f729Sjoerg } else {
37457330f729Sjoerg printf(" | isContainer: %d", info->isContainer);
37467330f729Sjoerg }
37477330f729Sjoerg printf(" | isImplicit: %d\n", info->isImplicit);
37487330f729Sjoerg
37497330f729Sjoerg for (i = 0; i != info->numAttributes; ++i) {
37507330f729Sjoerg const CXIdxAttrInfo *Attr = info->attributes[i];
37517330f729Sjoerg printf(" <attribute>: ");
37527330f729Sjoerg PrintCursor(Attr->cursor, NULL);
37537330f729Sjoerg printf("\n");
37547330f729Sjoerg }
37557330f729Sjoerg
37567330f729Sjoerg if (clang_index_isEntityObjCContainerKind(info->entityInfo->kind)) {
37577330f729Sjoerg const char *kindName = 0;
37587330f729Sjoerg CXIdxObjCContainerKind K = clang_index_getObjCContainerDeclInfo(info)->kind;
37597330f729Sjoerg switch (K) {
37607330f729Sjoerg case CXIdxObjCContainer_ForwardRef:
37617330f729Sjoerg kindName = "forward-ref"; break;
37627330f729Sjoerg case CXIdxObjCContainer_Interface:
37637330f729Sjoerg kindName = "interface"; break;
37647330f729Sjoerg case CXIdxObjCContainer_Implementation:
37657330f729Sjoerg kindName = "implementation"; break;
37667330f729Sjoerg }
37677330f729Sjoerg printCheck(index_data);
37687330f729Sjoerg printf(" <ObjCContainerInfo>: kind: %s\n", kindName);
37697330f729Sjoerg }
37707330f729Sjoerg
37717330f729Sjoerg if ((CatInfo = clang_index_getObjCCategoryDeclInfo(info))) {
37727330f729Sjoerg printEntityInfo(" <ObjCCategoryInfo>: class", client_data,
37737330f729Sjoerg CatInfo->objcClass);
37747330f729Sjoerg printf(" | cursor: ");
37757330f729Sjoerg PrintCursor(CatInfo->classCursor, NULL);
37767330f729Sjoerg printf(" | loc: ");
37777330f729Sjoerg printCXIndexLoc(CatInfo->classLoc, client_data);
37787330f729Sjoerg printf("\n");
37797330f729Sjoerg }
37807330f729Sjoerg
37817330f729Sjoerg if ((InterInfo = clang_index_getObjCInterfaceDeclInfo(info))) {
37827330f729Sjoerg if (InterInfo->superInfo) {
37837330f729Sjoerg printBaseClassInfo(client_data, InterInfo->superInfo);
37847330f729Sjoerg printf("\n");
37857330f729Sjoerg }
37867330f729Sjoerg }
37877330f729Sjoerg
37887330f729Sjoerg if ((ProtoInfo = clang_index_getObjCProtocolRefListInfo(info))) {
37897330f729Sjoerg printProtocolList(ProtoInfo, client_data);
37907330f729Sjoerg }
37917330f729Sjoerg
37927330f729Sjoerg if ((PropInfo = clang_index_getObjCPropertyDeclInfo(info))) {
37937330f729Sjoerg if (PropInfo->getter) {
37947330f729Sjoerg printEntityInfo(" <getter>", client_data, PropInfo->getter);
37957330f729Sjoerg printf("\n");
37967330f729Sjoerg }
37977330f729Sjoerg if (PropInfo->setter) {
37987330f729Sjoerg printEntityInfo(" <setter>", client_data, PropInfo->setter);
37997330f729Sjoerg printf("\n");
38007330f729Sjoerg }
38017330f729Sjoerg }
38027330f729Sjoerg
38037330f729Sjoerg if ((CXXClassInfo = clang_index_getCXXClassDeclInfo(info))) {
38047330f729Sjoerg for (i = 0; i != CXXClassInfo->numBases; ++i) {
38057330f729Sjoerg printBaseClassInfo(client_data, CXXClassInfo->bases[i]);
38067330f729Sjoerg printf("\n");
38077330f729Sjoerg }
38087330f729Sjoerg }
38097330f729Sjoerg
38107330f729Sjoerg if (info->declAsContainer)
38117330f729Sjoerg clang_index_setClientContainer(
38127330f729Sjoerg info->declAsContainer,
38137330f729Sjoerg makeClientContainer(client_data, info->entityInfo, info->loc));
38147330f729Sjoerg }
38157330f729Sjoerg
index_indexEntityReference(CXClientData client_data,const CXIdxEntityRefInfo * info)38167330f729Sjoerg static void index_indexEntityReference(CXClientData client_data,
38177330f729Sjoerg const CXIdxEntityRefInfo *info) {
38187330f729Sjoerg printEntityInfo("[indexEntityReference]", client_data,
38197330f729Sjoerg info->referencedEntity);
38207330f729Sjoerg printf(" | cursor: ");
38217330f729Sjoerg PrintCursor(info->cursor, NULL);
38227330f729Sjoerg printf(" | loc: ");
38237330f729Sjoerg printCXIndexLoc(info->loc, client_data);
38247330f729Sjoerg printEntityInfo(" | <parent>:", client_data, info->parentEntity);
38257330f729Sjoerg printf(" | container: ");
38267330f729Sjoerg printCXIndexContainer(info->container);
38277330f729Sjoerg printf(" | refkind: ");
38287330f729Sjoerg switch (info->kind) {
38297330f729Sjoerg case CXIdxEntityRef_Direct: printf("direct"); break;
38307330f729Sjoerg case CXIdxEntityRef_Implicit: printf("implicit"); break;
38317330f729Sjoerg }
38327330f729Sjoerg printf(" | role:");
38337330f729Sjoerg printSymbolRole(info->role);
38347330f729Sjoerg printf("\n");
38357330f729Sjoerg }
38367330f729Sjoerg
index_abortQuery(CXClientData client_data,void * reserved)38377330f729Sjoerg static int index_abortQuery(CXClientData client_data, void *reserved) {
38387330f729Sjoerg IndexData *index_data;
38397330f729Sjoerg index_data = (IndexData *)client_data;
38407330f729Sjoerg return index_data->abort;
38417330f729Sjoerg }
38427330f729Sjoerg
38437330f729Sjoerg static IndexerCallbacks IndexCB = {
38447330f729Sjoerg index_abortQuery,
38457330f729Sjoerg index_diagnostic,
38467330f729Sjoerg index_enteredMainFile,
38477330f729Sjoerg index_ppIncludedFile,
38487330f729Sjoerg index_importedASTFile,
38497330f729Sjoerg index_startedTranslationUnit,
38507330f729Sjoerg index_indexDeclaration,
38517330f729Sjoerg index_indexEntityReference
38527330f729Sjoerg };
38537330f729Sjoerg
getIndexOptions(void)38547330f729Sjoerg static unsigned getIndexOptions(void) {
38557330f729Sjoerg unsigned index_opts;
38567330f729Sjoerg index_opts = 0;
38577330f729Sjoerg if (getenv("CINDEXTEST_SUPPRESSREFS"))
38587330f729Sjoerg index_opts |= CXIndexOpt_SuppressRedundantRefs;
38597330f729Sjoerg if (getenv("CINDEXTEST_INDEXLOCALSYMBOLS"))
38607330f729Sjoerg index_opts |= CXIndexOpt_IndexFunctionLocalSymbols;
38617330f729Sjoerg if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES"))
38627330f729Sjoerg index_opts |= CXIndexOpt_SkipParsedBodiesInSession;
38637330f729Sjoerg if (getenv("CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS"))
38647330f729Sjoerg index_opts |= CXIndexOpt_IndexImplicitTemplateInstantiations;
38657330f729Sjoerg
38667330f729Sjoerg return index_opts;
38677330f729Sjoerg }
38687330f729Sjoerg
index_compile_args(int num_args,const char ** args,CXIndexAction idxAction,ImportedASTFilesData * importedASTs,const char * check_prefix)38697330f729Sjoerg static int index_compile_args(int num_args, const char **args,
38707330f729Sjoerg CXIndexAction idxAction,
38717330f729Sjoerg ImportedASTFilesData *importedASTs,
38727330f729Sjoerg const char *check_prefix) {
38737330f729Sjoerg IndexData index_data;
38747330f729Sjoerg unsigned index_opts;
38757330f729Sjoerg int result;
38767330f729Sjoerg
38777330f729Sjoerg if (num_args == 0) {
38787330f729Sjoerg fprintf(stderr, "no compiler arguments\n");
38797330f729Sjoerg return -1;
38807330f729Sjoerg }
38817330f729Sjoerg
38827330f729Sjoerg index_data.check_prefix = check_prefix;
38837330f729Sjoerg index_data.first_check_printed = 0;
38847330f729Sjoerg index_data.fail_for_error = 0;
38857330f729Sjoerg index_data.abort = 0;
38867330f729Sjoerg index_data.main_filename = createCXString("");
38877330f729Sjoerg index_data.importedASTs = importedASTs;
38887330f729Sjoerg index_data.strings = NULL;
38897330f729Sjoerg index_data.TU = NULL;
38907330f729Sjoerg
38917330f729Sjoerg index_opts = getIndexOptions();
38927330f729Sjoerg result = clang_indexSourceFile(idxAction, &index_data,
38937330f729Sjoerg &IndexCB,sizeof(IndexCB), index_opts,
38947330f729Sjoerg 0, args, num_args, 0, 0, 0,
38957330f729Sjoerg getDefaultParsingOptions());
38967330f729Sjoerg if (result != CXError_Success)
38977330f729Sjoerg describeLibclangFailure(result);
38987330f729Sjoerg
38997330f729Sjoerg if (index_data.fail_for_error)
39007330f729Sjoerg result = -1;
39017330f729Sjoerg
39027330f729Sjoerg clang_disposeString(index_data.main_filename);
39037330f729Sjoerg free_client_data(&index_data);
39047330f729Sjoerg return result;
39057330f729Sjoerg }
39067330f729Sjoerg
index_ast_file(const char * ast_file,CXIndex Idx,CXIndexAction idxAction,ImportedASTFilesData * importedASTs,const char * check_prefix)39077330f729Sjoerg static int index_ast_file(const char *ast_file,
39087330f729Sjoerg CXIndex Idx,
39097330f729Sjoerg CXIndexAction idxAction,
39107330f729Sjoerg ImportedASTFilesData *importedASTs,
39117330f729Sjoerg const char *check_prefix) {
39127330f729Sjoerg CXTranslationUnit TU;
39137330f729Sjoerg IndexData index_data;
39147330f729Sjoerg unsigned index_opts;
39157330f729Sjoerg int result;
39167330f729Sjoerg
39177330f729Sjoerg if (!CreateTranslationUnit(Idx, ast_file, &TU))
39187330f729Sjoerg return -1;
39197330f729Sjoerg
39207330f729Sjoerg index_data.check_prefix = check_prefix;
39217330f729Sjoerg index_data.first_check_printed = 0;
39227330f729Sjoerg index_data.fail_for_error = 0;
39237330f729Sjoerg index_data.abort = 0;
39247330f729Sjoerg index_data.main_filename = createCXString("");
39257330f729Sjoerg index_data.importedASTs = importedASTs;
39267330f729Sjoerg index_data.strings = NULL;
39277330f729Sjoerg index_data.TU = TU;
39287330f729Sjoerg
39297330f729Sjoerg index_opts = getIndexOptions();
39307330f729Sjoerg result = clang_indexTranslationUnit(idxAction, &index_data,
39317330f729Sjoerg &IndexCB,sizeof(IndexCB),
39327330f729Sjoerg index_opts, TU);
39337330f729Sjoerg if (index_data.fail_for_error)
39347330f729Sjoerg result = -1;
39357330f729Sjoerg
39367330f729Sjoerg clang_disposeTranslationUnit(TU);
39377330f729Sjoerg clang_disposeString(index_data.main_filename);
39387330f729Sjoerg free_client_data(&index_data);
39397330f729Sjoerg return result;
39407330f729Sjoerg }
39417330f729Sjoerg
index_file(int argc,const char ** argv,int full)39427330f729Sjoerg static int index_file(int argc, const char **argv, int full) {
39437330f729Sjoerg const char *check_prefix;
39447330f729Sjoerg CXIndex Idx;
39457330f729Sjoerg CXIndexAction idxAction;
39467330f729Sjoerg ImportedASTFilesData *importedASTs;
39477330f729Sjoerg int result;
39487330f729Sjoerg
39497330f729Sjoerg check_prefix = 0;
39507330f729Sjoerg if (argc > 0) {
39517330f729Sjoerg if (strstr(argv[0], "-check-prefix=") == argv[0]) {
39527330f729Sjoerg check_prefix = argv[0] + strlen("-check-prefix=");
39537330f729Sjoerg ++argv;
39547330f729Sjoerg --argc;
39557330f729Sjoerg }
39567330f729Sjoerg }
39577330f729Sjoerg
39587330f729Sjoerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
39597330f729Sjoerg /* displayDiagnostics=*/1))) {
39607330f729Sjoerg fprintf(stderr, "Could not create Index\n");
39617330f729Sjoerg return 1;
39627330f729Sjoerg }
39637330f729Sjoerg idxAction = clang_IndexAction_create(Idx);
39647330f729Sjoerg importedASTs = 0;
39657330f729Sjoerg if (full)
39667330f729Sjoerg importedASTs = importedASTs_create();
39677330f729Sjoerg
39687330f729Sjoerg result = index_compile_args(argc, argv, idxAction, importedASTs, check_prefix);
39697330f729Sjoerg if (result != 0)
39707330f729Sjoerg goto finished;
39717330f729Sjoerg
39727330f729Sjoerg if (full) {
39737330f729Sjoerg unsigned i;
39747330f729Sjoerg for (i = 0; i < importedASTs->num_files && result == 0; ++i) {
39757330f729Sjoerg result = index_ast_file(importedASTs->filenames[i], Idx, idxAction,
39767330f729Sjoerg importedASTs, check_prefix);
39777330f729Sjoerg }
39787330f729Sjoerg }
39797330f729Sjoerg
39807330f729Sjoerg finished:
39817330f729Sjoerg importedASTs_dispose(importedASTs);
39827330f729Sjoerg clang_IndexAction_dispose(idxAction);
39837330f729Sjoerg clang_disposeIndex(Idx);
39847330f729Sjoerg return result;
39857330f729Sjoerg }
39867330f729Sjoerg
index_tu(int argc,const char ** argv)39877330f729Sjoerg static int index_tu(int argc, const char **argv) {
39887330f729Sjoerg const char *check_prefix;
39897330f729Sjoerg CXIndex Idx;
39907330f729Sjoerg CXIndexAction idxAction;
39917330f729Sjoerg int result;
39927330f729Sjoerg
39937330f729Sjoerg check_prefix = 0;
39947330f729Sjoerg if (argc > 0) {
39957330f729Sjoerg if (strstr(argv[0], "-check-prefix=") == argv[0]) {
39967330f729Sjoerg check_prefix = argv[0] + strlen("-check-prefix=");
39977330f729Sjoerg ++argv;
39987330f729Sjoerg --argc;
39997330f729Sjoerg }
40007330f729Sjoerg }
40017330f729Sjoerg
40027330f729Sjoerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
40037330f729Sjoerg /* displayDiagnostics=*/1))) {
40047330f729Sjoerg fprintf(stderr, "Could not create Index\n");
40057330f729Sjoerg return 1;
40067330f729Sjoerg }
40077330f729Sjoerg idxAction = clang_IndexAction_create(Idx);
40087330f729Sjoerg
40097330f729Sjoerg result = index_ast_file(argv[0], Idx, idxAction,
40107330f729Sjoerg /*importedASTs=*/0, check_prefix);
40117330f729Sjoerg
40127330f729Sjoerg clang_IndexAction_dispose(idxAction);
40137330f729Sjoerg clang_disposeIndex(Idx);
40147330f729Sjoerg return result;
40157330f729Sjoerg }
40167330f729Sjoerg
index_compile_db(int argc,const char ** argv)40177330f729Sjoerg static int index_compile_db(int argc, const char **argv) {
40187330f729Sjoerg const char *check_prefix;
40197330f729Sjoerg CXIndex Idx;
40207330f729Sjoerg CXIndexAction idxAction;
40217330f729Sjoerg int errorCode = 0;
40227330f729Sjoerg
40237330f729Sjoerg check_prefix = 0;
40247330f729Sjoerg if (argc > 0) {
40257330f729Sjoerg if (strstr(argv[0], "-check-prefix=") == argv[0]) {
40267330f729Sjoerg check_prefix = argv[0] + strlen("-check-prefix=");
40277330f729Sjoerg ++argv;
40287330f729Sjoerg --argc;
40297330f729Sjoerg }
40307330f729Sjoerg }
40317330f729Sjoerg
40327330f729Sjoerg if (argc == 0) {
40337330f729Sjoerg fprintf(stderr, "no compilation database\n");
40347330f729Sjoerg return -1;
40357330f729Sjoerg }
40367330f729Sjoerg
40377330f729Sjoerg if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
40387330f729Sjoerg /* displayDiagnostics=*/1))) {
40397330f729Sjoerg fprintf(stderr, "Could not create Index\n");
40407330f729Sjoerg return 1;
40417330f729Sjoerg }
40427330f729Sjoerg idxAction = clang_IndexAction_create(Idx);
40437330f729Sjoerg
40447330f729Sjoerg {
40457330f729Sjoerg const char *database = argv[0];
40467330f729Sjoerg CXCompilationDatabase db = 0;
40477330f729Sjoerg CXCompileCommands CCmds = 0;
40487330f729Sjoerg CXCompileCommand CCmd;
40497330f729Sjoerg CXCompilationDatabase_Error ec;
40507330f729Sjoerg CXString wd;
40517330f729Sjoerg #define MAX_COMPILE_ARGS 512
40527330f729Sjoerg CXString cxargs[MAX_COMPILE_ARGS];
40537330f729Sjoerg const char *args[MAX_COMPILE_ARGS];
40547330f729Sjoerg char *tmp;
40557330f729Sjoerg unsigned len;
40567330f729Sjoerg char *buildDir;
40577330f729Sjoerg int i, a, numCmds, numArgs;
40587330f729Sjoerg
40597330f729Sjoerg len = strlen(database);
40607330f729Sjoerg tmp = (char *) malloc(len+1);
40617330f729Sjoerg assert(tmp);
40627330f729Sjoerg memcpy(tmp, database, len+1);
40637330f729Sjoerg buildDir = dirname(tmp);
40647330f729Sjoerg
40657330f729Sjoerg db = clang_CompilationDatabase_fromDirectory(buildDir, &ec);
40667330f729Sjoerg
40677330f729Sjoerg if (db) {
40687330f729Sjoerg
40697330f729Sjoerg if (ec!=CXCompilationDatabase_NoError) {
40707330f729Sjoerg printf("unexpected error %d code while loading compilation database\n", ec);
40717330f729Sjoerg errorCode = -1;
40727330f729Sjoerg goto cdb_end;
40737330f729Sjoerg }
40747330f729Sjoerg
40757330f729Sjoerg if (chdir(buildDir) != 0) {
40767330f729Sjoerg printf("Could not chdir to %s\n", buildDir);
40777330f729Sjoerg errorCode = -1;
40787330f729Sjoerg goto cdb_end;
40797330f729Sjoerg }
40807330f729Sjoerg
40817330f729Sjoerg CCmds = clang_CompilationDatabase_getAllCompileCommands(db);
40827330f729Sjoerg if (!CCmds) {
40837330f729Sjoerg printf("compilation db is empty\n");
40847330f729Sjoerg errorCode = -1;
40857330f729Sjoerg goto cdb_end;
40867330f729Sjoerg }
40877330f729Sjoerg
40887330f729Sjoerg numCmds = clang_CompileCommands_getSize(CCmds);
40897330f729Sjoerg
40907330f729Sjoerg if (numCmds==0) {
40917330f729Sjoerg fprintf(stderr, "should not get an empty compileCommand set\n");
40927330f729Sjoerg errorCode = -1;
40937330f729Sjoerg goto cdb_end;
40947330f729Sjoerg }
40957330f729Sjoerg
40967330f729Sjoerg for (i=0; i<numCmds && errorCode == 0; ++i) {
40977330f729Sjoerg CCmd = clang_CompileCommands_getCommand(CCmds, i);
40987330f729Sjoerg
40997330f729Sjoerg wd = clang_CompileCommand_getDirectory(CCmd);
41007330f729Sjoerg if (chdir(clang_getCString(wd)) != 0) {
41017330f729Sjoerg printf("Could not chdir to %s\n", clang_getCString(wd));
41027330f729Sjoerg errorCode = -1;
41037330f729Sjoerg goto cdb_end;
41047330f729Sjoerg }
41057330f729Sjoerg clang_disposeString(wd);
41067330f729Sjoerg
41077330f729Sjoerg numArgs = clang_CompileCommand_getNumArgs(CCmd);
41087330f729Sjoerg if (numArgs > MAX_COMPILE_ARGS){
41097330f729Sjoerg fprintf(stderr, "got more compile arguments than maximum\n");
41107330f729Sjoerg errorCode = -1;
41117330f729Sjoerg goto cdb_end;
41127330f729Sjoerg }
41137330f729Sjoerg for (a=0; a<numArgs; ++a) {
41147330f729Sjoerg cxargs[a] = clang_CompileCommand_getArg(CCmd, a);
41157330f729Sjoerg args[a] = clang_getCString(cxargs[a]);
41167330f729Sjoerg }
41177330f729Sjoerg
41187330f729Sjoerg errorCode = index_compile_args(numArgs, args, idxAction,
41197330f729Sjoerg /*importedASTs=*/0, check_prefix);
41207330f729Sjoerg
41217330f729Sjoerg for (a=0; a<numArgs; ++a)
41227330f729Sjoerg clang_disposeString(cxargs[a]);
41237330f729Sjoerg }
41247330f729Sjoerg } else {
41257330f729Sjoerg printf("database loading failed with error code %d.\n", ec);
41267330f729Sjoerg errorCode = -1;
41277330f729Sjoerg }
41287330f729Sjoerg
41297330f729Sjoerg cdb_end:
41307330f729Sjoerg clang_CompileCommands_dispose(CCmds);
41317330f729Sjoerg clang_CompilationDatabase_dispose(db);
41327330f729Sjoerg free(tmp);
41337330f729Sjoerg
41347330f729Sjoerg }
41357330f729Sjoerg
41367330f729Sjoerg clang_IndexAction_dispose(idxAction);
41377330f729Sjoerg clang_disposeIndex(Idx);
41387330f729Sjoerg return errorCode;
41397330f729Sjoerg }
41407330f729Sjoerg
perform_token_annotation(int argc,const char ** argv)41417330f729Sjoerg int perform_token_annotation(int argc, const char **argv) {
41427330f729Sjoerg const char *input = argv[1];
41437330f729Sjoerg char *filename = 0;
41447330f729Sjoerg unsigned line, second_line;
41457330f729Sjoerg unsigned column, second_column;
41467330f729Sjoerg CXIndex CIdx;
41477330f729Sjoerg CXTranslationUnit TU = 0;
41487330f729Sjoerg int errorCode;
41497330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
41507330f729Sjoerg int num_unsaved_files = 0;
41517330f729Sjoerg CXToken *tokens;
41527330f729Sjoerg unsigned num_tokens;
41537330f729Sjoerg CXSourceRange range;
41547330f729Sjoerg CXSourceLocation startLoc, endLoc;
41557330f729Sjoerg CXFile file = 0;
41567330f729Sjoerg CXCursor *cursors = 0;
41577330f729Sjoerg CXSourceRangeList *skipped_ranges = 0;
41587330f729Sjoerg enum CXErrorCode Err;
41597330f729Sjoerg unsigned i;
41607330f729Sjoerg
41617330f729Sjoerg input += strlen("-test-annotate-tokens=");
41627330f729Sjoerg if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
41637330f729Sjoerg &second_line, &second_column)))
41647330f729Sjoerg return errorCode;
41657330f729Sjoerg
41667330f729Sjoerg if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) {
41677330f729Sjoerg free(filename);
41687330f729Sjoerg return -1;
41697330f729Sjoerg }
41707330f729Sjoerg
41717330f729Sjoerg CIdx = clang_createIndex(0, 1);
41727330f729Sjoerg Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
41737330f729Sjoerg argv + num_unsaved_files + 2,
41747330f729Sjoerg argc - num_unsaved_files - 3,
41757330f729Sjoerg unsaved_files,
41767330f729Sjoerg num_unsaved_files,
41777330f729Sjoerg getDefaultParsingOptions(), &TU);
41787330f729Sjoerg if (Err != CXError_Success) {
41797330f729Sjoerg fprintf(stderr, "unable to parse input\n");
41807330f729Sjoerg describeLibclangFailure(Err);
41817330f729Sjoerg clang_disposeIndex(CIdx);
41827330f729Sjoerg free(filename);
41837330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
41847330f729Sjoerg return -1;
41857330f729Sjoerg }
41867330f729Sjoerg errorCode = 0;
41877330f729Sjoerg
41887330f729Sjoerg if (checkForErrors(TU) != 0) {
41897330f729Sjoerg errorCode = -1;
41907330f729Sjoerg goto teardown;
41917330f729Sjoerg }
41927330f729Sjoerg
41937330f729Sjoerg if (getenv("CINDEXTEST_EDITING")) {
41947330f729Sjoerg for (i = 0; i < 5; ++i) {
41957330f729Sjoerg Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
41967330f729Sjoerg clang_defaultReparseOptions(TU));
41977330f729Sjoerg if (Err != CXError_Success) {
41987330f729Sjoerg fprintf(stderr, "Unable to reparse translation unit!\n");
41997330f729Sjoerg describeLibclangFailure(Err);
42007330f729Sjoerg errorCode = -1;
42017330f729Sjoerg goto teardown;
42027330f729Sjoerg }
42037330f729Sjoerg }
42047330f729Sjoerg }
42057330f729Sjoerg
42067330f729Sjoerg if (checkForErrors(TU) != 0) {
42077330f729Sjoerg errorCode = -1;
42087330f729Sjoerg goto teardown;
42097330f729Sjoerg }
42107330f729Sjoerg
42117330f729Sjoerg file = clang_getFile(TU, filename);
42127330f729Sjoerg if (!file) {
42137330f729Sjoerg fprintf(stderr, "file %s is not in this translation unit\n", filename);
42147330f729Sjoerg errorCode = -1;
42157330f729Sjoerg goto teardown;
42167330f729Sjoerg }
42177330f729Sjoerg
42187330f729Sjoerg startLoc = clang_getLocation(TU, file, line, column);
42197330f729Sjoerg if (clang_equalLocations(clang_getNullLocation(), startLoc)) {
42207330f729Sjoerg fprintf(stderr, "invalid source location %s:%d:%d\n", filename, line,
42217330f729Sjoerg column);
42227330f729Sjoerg errorCode = -1;
42237330f729Sjoerg goto teardown;
42247330f729Sjoerg }
42257330f729Sjoerg
42267330f729Sjoerg endLoc = clang_getLocation(TU, file, second_line, second_column);
42277330f729Sjoerg if (clang_equalLocations(clang_getNullLocation(), endLoc)) {
42287330f729Sjoerg fprintf(stderr, "invalid source location %s:%d:%d\n", filename,
42297330f729Sjoerg second_line, second_column);
42307330f729Sjoerg errorCode = -1;
42317330f729Sjoerg goto teardown;
42327330f729Sjoerg }
42337330f729Sjoerg
42347330f729Sjoerg range = clang_getRange(startLoc, endLoc);
42357330f729Sjoerg clang_tokenize(TU, range, &tokens, &num_tokens);
42367330f729Sjoerg
42377330f729Sjoerg if (checkForErrors(TU) != 0) {
42387330f729Sjoerg errorCode = -1;
42397330f729Sjoerg goto teardown;
42407330f729Sjoerg }
42417330f729Sjoerg
42427330f729Sjoerg cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor));
42437330f729Sjoerg assert(cursors);
42447330f729Sjoerg clang_annotateTokens(TU, tokens, num_tokens, cursors);
42457330f729Sjoerg
42467330f729Sjoerg if (checkForErrors(TU) != 0) {
42477330f729Sjoerg errorCode = -1;
42487330f729Sjoerg goto teardown;
42497330f729Sjoerg }
42507330f729Sjoerg
42517330f729Sjoerg skipped_ranges = clang_getSkippedRanges(TU, file);
42527330f729Sjoerg for (i = 0; i != skipped_ranges->count; ++i) {
42537330f729Sjoerg unsigned start_line, start_column, end_line, end_column;
42547330f729Sjoerg clang_getSpellingLocation(clang_getRangeStart(skipped_ranges->ranges[i]),
42557330f729Sjoerg 0, &start_line, &start_column, 0);
42567330f729Sjoerg clang_getSpellingLocation(clang_getRangeEnd(skipped_ranges->ranges[i]),
42577330f729Sjoerg 0, &end_line, &end_column, 0);
42587330f729Sjoerg printf("Skipping: ");
42597330f729Sjoerg PrintExtent(stdout, start_line, start_column, end_line, end_column);
42607330f729Sjoerg printf("\n");
42617330f729Sjoerg }
42627330f729Sjoerg clang_disposeSourceRangeList(skipped_ranges);
42637330f729Sjoerg
42647330f729Sjoerg for (i = 0; i != num_tokens; ++i) {
42657330f729Sjoerg const char *kind = "<unknown>";
42667330f729Sjoerg CXString spelling = clang_getTokenSpelling(TU, tokens[i]);
42677330f729Sjoerg CXSourceRange extent = clang_getTokenExtent(TU, tokens[i]);
42687330f729Sjoerg unsigned start_line, start_column, end_line, end_column;
42697330f729Sjoerg
42707330f729Sjoerg switch (clang_getTokenKind(tokens[i])) {
42717330f729Sjoerg case CXToken_Punctuation: kind = "Punctuation"; break;
42727330f729Sjoerg case CXToken_Keyword: kind = "Keyword"; break;
42737330f729Sjoerg case CXToken_Identifier: kind = "Identifier"; break;
42747330f729Sjoerg case CXToken_Literal: kind = "Literal"; break;
42757330f729Sjoerg case CXToken_Comment: kind = "Comment"; break;
42767330f729Sjoerg }
42777330f729Sjoerg clang_getSpellingLocation(clang_getRangeStart(extent),
42787330f729Sjoerg 0, &start_line, &start_column, 0);
42797330f729Sjoerg clang_getSpellingLocation(clang_getRangeEnd(extent),
42807330f729Sjoerg 0, &end_line, &end_column, 0);
42817330f729Sjoerg printf("%s: \"%s\" ", kind, clang_getCString(spelling));
42827330f729Sjoerg clang_disposeString(spelling);
42837330f729Sjoerg PrintExtent(stdout, start_line, start_column, end_line, end_column);
42847330f729Sjoerg if (!clang_isInvalid(cursors[i].kind)) {
42857330f729Sjoerg printf(" ");
42867330f729Sjoerg PrintCursor(cursors[i], NULL);
42877330f729Sjoerg }
42887330f729Sjoerg printf("\n");
42897330f729Sjoerg }
42907330f729Sjoerg free(cursors);
42917330f729Sjoerg clang_disposeTokens(TU, tokens, num_tokens);
42927330f729Sjoerg
42937330f729Sjoerg teardown:
42947330f729Sjoerg PrintDiagnostics(TU);
42957330f729Sjoerg clang_disposeTranslationUnit(TU);
42967330f729Sjoerg clang_disposeIndex(CIdx);
42977330f729Sjoerg free(filename);
42987330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
42997330f729Sjoerg return errorCode;
43007330f729Sjoerg }
43017330f729Sjoerg
43027330f729Sjoerg static int
perform_test_compilation_db(const char * database,int argc,const char ** argv)43037330f729Sjoerg perform_test_compilation_db(const char *database, int argc, const char **argv) {
43047330f729Sjoerg CXCompilationDatabase db;
43057330f729Sjoerg CXCompileCommands CCmds;
43067330f729Sjoerg CXCompileCommand CCmd;
43077330f729Sjoerg CXCompilationDatabase_Error ec;
43087330f729Sjoerg CXString wd;
43097330f729Sjoerg CXString arg;
43107330f729Sjoerg int errorCode = 0;
43117330f729Sjoerg char *tmp;
43127330f729Sjoerg unsigned len;
43137330f729Sjoerg char *buildDir;
43147330f729Sjoerg int i, j, a, numCmds, numArgs;
43157330f729Sjoerg
43167330f729Sjoerg len = strlen(database);
43177330f729Sjoerg tmp = (char *) malloc(len+1);
43187330f729Sjoerg assert(tmp);
43197330f729Sjoerg memcpy(tmp, database, len+1);
43207330f729Sjoerg buildDir = dirname(tmp);
43217330f729Sjoerg
43227330f729Sjoerg db = clang_CompilationDatabase_fromDirectory(buildDir, &ec);
43237330f729Sjoerg
43247330f729Sjoerg if (db) {
43257330f729Sjoerg
43267330f729Sjoerg if (ec!=CXCompilationDatabase_NoError) {
43277330f729Sjoerg printf("unexpected error %d code while loading compilation database\n", ec);
43287330f729Sjoerg errorCode = -1;
43297330f729Sjoerg goto cdb_end;
43307330f729Sjoerg }
43317330f729Sjoerg
43327330f729Sjoerg for (i=0; i<argc && errorCode==0; ) {
43337330f729Sjoerg if (strcmp(argv[i],"lookup")==0){
43347330f729Sjoerg CCmds = clang_CompilationDatabase_getCompileCommands(db, argv[i+1]);
43357330f729Sjoerg
43367330f729Sjoerg if (!CCmds) {
43377330f729Sjoerg printf("file %s not found in compilation db\n", argv[i+1]);
43387330f729Sjoerg errorCode = -1;
43397330f729Sjoerg break;
43407330f729Sjoerg }
43417330f729Sjoerg
43427330f729Sjoerg numCmds = clang_CompileCommands_getSize(CCmds);
43437330f729Sjoerg
43447330f729Sjoerg if (numCmds==0) {
43457330f729Sjoerg fprintf(stderr, "should not get an empty compileCommand set for file"
43467330f729Sjoerg " '%s'\n", argv[i+1]);
43477330f729Sjoerg errorCode = -1;
43487330f729Sjoerg break;
43497330f729Sjoerg }
43507330f729Sjoerg
43517330f729Sjoerg for (j=0; j<numCmds; ++j) {
43527330f729Sjoerg CCmd = clang_CompileCommands_getCommand(CCmds, j);
43537330f729Sjoerg
43547330f729Sjoerg wd = clang_CompileCommand_getDirectory(CCmd);
43557330f729Sjoerg printf("workdir:'%s'", clang_getCString(wd));
43567330f729Sjoerg clang_disposeString(wd);
43577330f729Sjoerg
43587330f729Sjoerg printf(" cmdline:'");
43597330f729Sjoerg numArgs = clang_CompileCommand_getNumArgs(CCmd);
43607330f729Sjoerg for (a=0; a<numArgs; ++a) {
43617330f729Sjoerg if (a) printf(" ");
43627330f729Sjoerg arg = clang_CompileCommand_getArg(CCmd, a);
43637330f729Sjoerg printf("%s", clang_getCString(arg));
43647330f729Sjoerg clang_disposeString(arg);
43657330f729Sjoerg }
43667330f729Sjoerg printf("'\n");
43677330f729Sjoerg }
43687330f729Sjoerg
43697330f729Sjoerg clang_CompileCommands_dispose(CCmds);
43707330f729Sjoerg
43717330f729Sjoerg i += 2;
43727330f729Sjoerg }
43737330f729Sjoerg }
43747330f729Sjoerg clang_CompilationDatabase_dispose(db);
43757330f729Sjoerg } else {
43767330f729Sjoerg printf("database loading failed with error code %d.\n", ec);
43777330f729Sjoerg errorCode = -1;
43787330f729Sjoerg }
43797330f729Sjoerg
43807330f729Sjoerg cdb_end:
43817330f729Sjoerg free(tmp);
43827330f729Sjoerg
43837330f729Sjoerg return errorCode;
43847330f729Sjoerg }
43857330f729Sjoerg
43867330f729Sjoerg /******************************************************************************/
43877330f729Sjoerg /* USR printing. */
43887330f729Sjoerg /******************************************************************************/
43897330f729Sjoerg
insufficient_usr(const char * kind,const char * usage)43907330f729Sjoerg static int insufficient_usr(const char *kind, const char *usage) {
43917330f729Sjoerg fprintf(stderr, "USR for '%s' requires: %s\n", kind, usage);
43927330f729Sjoerg return 1;
43937330f729Sjoerg }
43947330f729Sjoerg
isUSR(const char * s)43957330f729Sjoerg static unsigned isUSR(const char *s) {
43967330f729Sjoerg return s[0] == 'c' && s[1] == ':';
43977330f729Sjoerg }
43987330f729Sjoerg
not_usr(const char * s,const char * arg)43997330f729Sjoerg static int not_usr(const char *s, const char *arg) {
44007330f729Sjoerg fprintf(stderr, "'%s' argument ('%s') is not a USR\n", s, arg);
44017330f729Sjoerg return 1;
44027330f729Sjoerg }
44037330f729Sjoerg
print_usr(CXString usr)44047330f729Sjoerg static void print_usr(CXString usr) {
44057330f729Sjoerg const char *s = clang_getCString(usr);
44067330f729Sjoerg printf("%s\n", s);
44077330f729Sjoerg clang_disposeString(usr);
44087330f729Sjoerg }
44097330f729Sjoerg
display_usrs()44107330f729Sjoerg static void display_usrs() {
44117330f729Sjoerg fprintf(stderr, "-print-usrs options:\n"
44127330f729Sjoerg " ObjCCategory <class name> <category name>\n"
44137330f729Sjoerg " ObjCClass <class name>\n"
44147330f729Sjoerg " ObjCIvar <ivar name> <class USR>\n"
44157330f729Sjoerg " ObjCMethod <selector> [0=class method|1=instance method] "
44167330f729Sjoerg "<class USR>\n"
44177330f729Sjoerg " ObjCProperty <property name> <class USR>\n"
44187330f729Sjoerg " ObjCProtocol <protocol name>\n");
44197330f729Sjoerg }
44207330f729Sjoerg
print_usrs(const char ** I,const char ** E)44217330f729Sjoerg int print_usrs(const char **I, const char **E) {
44227330f729Sjoerg while (I != E) {
44237330f729Sjoerg const char *kind = *I;
44247330f729Sjoerg unsigned len = strlen(kind);
44257330f729Sjoerg switch (len) {
44267330f729Sjoerg case 8:
44277330f729Sjoerg if (memcmp(kind, "ObjCIvar", 8) == 0) {
44287330f729Sjoerg if (I + 2 >= E)
44297330f729Sjoerg return insufficient_usr(kind, "<ivar name> <class USR>");
44307330f729Sjoerg if (!isUSR(I[2]))
44317330f729Sjoerg return not_usr("<class USR>", I[2]);
44327330f729Sjoerg else {
44337330f729Sjoerg CXString x = createCXString(I[2]);
44347330f729Sjoerg print_usr(clang_constructUSR_ObjCIvar(I[1], x));
44357330f729Sjoerg }
44367330f729Sjoerg
44377330f729Sjoerg I += 3;
44387330f729Sjoerg continue;
44397330f729Sjoerg }
44407330f729Sjoerg break;
44417330f729Sjoerg case 9:
44427330f729Sjoerg if (memcmp(kind, "ObjCClass", 9) == 0) {
44437330f729Sjoerg if (I + 1 >= E)
44447330f729Sjoerg return insufficient_usr(kind, "<class name>");
44457330f729Sjoerg print_usr(clang_constructUSR_ObjCClass(I[1]));
44467330f729Sjoerg I += 2;
44477330f729Sjoerg continue;
44487330f729Sjoerg }
44497330f729Sjoerg break;
44507330f729Sjoerg case 10:
44517330f729Sjoerg if (memcmp(kind, "ObjCMethod", 10) == 0) {
44527330f729Sjoerg if (I + 3 >= E)
44537330f729Sjoerg return insufficient_usr(kind, "<method selector> "
44547330f729Sjoerg "[0=class method|1=instance method] <class USR>");
44557330f729Sjoerg if (!isUSR(I[3]))
44567330f729Sjoerg return not_usr("<class USR>", I[3]);
44577330f729Sjoerg else {
44587330f729Sjoerg CXString x = createCXString(I[3]);
44597330f729Sjoerg print_usr(clang_constructUSR_ObjCMethod(I[1], atoi(I[2]), x));
44607330f729Sjoerg }
44617330f729Sjoerg I += 4;
44627330f729Sjoerg continue;
44637330f729Sjoerg }
44647330f729Sjoerg break;
44657330f729Sjoerg case 12:
44667330f729Sjoerg if (memcmp(kind, "ObjCCategory", 12) == 0) {
44677330f729Sjoerg if (I + 2 >= E)
44687330f729Sjoerg return insufficient_usr(kind, "<class name> <category name>");
44697330f729Sjoerg print_usr(clang_constructUSR_ObjCCategory(I[1], I[2]));
44707330f729Sjoerg I += 3;
44717330f729Sjoerg continue;
44727330f729Sjoerg }
44737330f729Sjoerg if (memcmp(kind, "ObjCProtocol", 12) == 0) {
44747330f729Sjoerg if (I + 1 >= E)
44757330f729Sjoerg return insufficient_usr(kind, "<protocol name>");
44767330f729Sjoerg print_usr(clang_constructUSR_ObjCProtocol(I[1]));
44777330f729Sjoerg I += 2;
44787330f729Sjoerg continue;
44797330f729Sjoerg }
44807330f729Sjoerg if (memcmp(kind, "ObjCProperty", 12) == 0) {
44817330f729Sjoerg if (I + 2 >= E)
44827330f729Sjoerg return insufficient_usr(kind, "<property name> <class USR>");
44837330f729Sjoerg if (!isUSR(I[2]))
44847330f729Sjoerg return not_usr("<class USR>", I[2]);
44857330f729Sjoerg else {
44867330f729Sjoerg CXString x = createCXString(I[2]);
44877330f729Sjoerg print_usr(clang_constructUSR_ObjCProperty(I[1], x));
44887330f729Sjoerg }
44897330f729Sjoerg I += 3;
44907330f729Sjoerg continue;
44917330f729Sjoerg }
44927330f729Sjoerg break;
44937330f729Sjoerg default:
44947330f729Sjoerg break;
44957330f729Sjoerg }
44967330f729Sjoerg break;
44977330f729Sjoerg }
44987330f729Sjoerg
44997330f729Sjoerg if (I != E) {
45007330f729Sjoerg fprintf(stderr, "Invalid USR kind: %s\n", *I);
45017330f729Sjoerg display_usrs();
45027330f729Sjoerg return 1;
45037330f729Sjoerg }
45047330f729Sjoerg return 0;
45057330f729Sjoerg }
45067330f729Sjoerg
print_usrs_file(const char * file_name)45077330f729Sjoerg int print_usrs_file(const char *file_name) {
45087330f729Sjoerg char line[2048];
45097330f729Sjoerg const char *args[128];
45107330f729Sjoerg unsigned numChars = 0;
45117330f729Sjoerg
45127330f729Sjoerg FILE *fp = fopen(file_name, "r");
45137330f729Sjoerg if (!fp) {
45147330f729Sjoerg fprintf(stderr, "error: cannot open '%s'\n", file_name);
45157330f729Sjoerg return 1;
45167330f729Sjoerg }
45177330f729Sjoerg
45187330f729Sjoerg /* This code is not really all that safe, but it works fine for testing. */
45197330f729Sjoerg while (!feof(fp)) {
45207330f729Sjoerg char c = fgetc(fp);
45217330f729Sjoerg if (c == '\n') {
45227330f729Sjoerg unsigned i = 0;
45237330f729Sjoerg const char *s = 0;
45247330f729Sjoerg
45257330f729Sjoerg if (numChars == 0)
45267330f729Sjoerg continue;
45277330f729Sjoerg
45287330f729Sjoerg line[numChars] = '\0';
45297330f729Sjoerg numChars = 0;
45307330f729Sjoerg
45317330f729Sjoerg if (line[0] == '/' && line[1] == '/')
45327330f729Sjoerg continue;
45337330f729Sjoerg
45347330f729Sjoerg s = strtok(line, " ");
45357330f729Sjoerg while (s) {
45367330f729Sjoerg args[i] = s;
45377330f729Sjoerg ++i;
45387330f729Sjoerg s = strtok(0, " ");
45397330f729Sjoerg }
45407330f729Sjoerg if (print_usrs(&args[0], &args[i]))
45417330f729Sjoerg return 1;
45427330f729Sjoerg }
45437330f729Sjoerg else
45447330f729Sjoerg line[numChars++] = c;
45457330f729Sjoerg }
45467330f729Sjoerg
45477330f729Sjoerg fclose(fp);
45487330f729Sjoerg return 0;
45497330f729Sjoerg }
45507330f729Sjoerg
45517330f729Sjoerg /******************************************************************************/
45527330f729Sjoerg /* Command line processing. */
45537330f729Sjoerg /******************************************************************************/
write_pch_file(const char * filename,int argc,const char * argv[])45547330f729Sjoerg int write_pch_file(const char *filename, int argc, const char *argv[]) {
45557330f729Sjoerg CXIndex Idx;
45567330f729Sjoerg CXTranslationUnit TU;
45577330f729Sjoerg struct CXUnsavedFile *unsaved_files = 0;
45587330f729Sjoerg int num_unsaved_files = 0;
45597330f729Sjoerg enum CXErrorCode Err;
45607330f729Sjoerg int result = 0;
45617330f729Sjoerg
45627330f729Sjoerg Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1);
45637330f729Sjoerg
45647330f729Sjoerg if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
45657330f729Sjoerg clang_disposeIndex(Idx);
45667330f729Sjoerg return -1;
45677330f729Sjoerg }
45687330f729Sjoerg
45697330f729Sjoerg Err = clang_parseTranslationUnit2(
45707330f729Sjoerg Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files,
45717330f729Sjoerg unsaved_files, num_unsaved_files,
45727330f729Sjoerg CXTranslationUnit_Incomplete |
45737330f729Sjoerg CXTranslationUnit_DetailedPreprocessingRecord |
45747330f729Sjoerg CXTranslationUnit_ForSerialization,
45757330f729Sjoerg &TU);
45767330f729Sjoerg if (Err != CXError_Success) {
45777330f729Sjoerg fprintf(stderr, "Unable to load translation unit!\n");
45787330f729Sjoerg describeLibclangFailure(Err);
45797330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
45807330f729Sjoerg clang_disposeTranslationUnit(TU);
45817330f729Sjoerg clang_disposeIndex(Idx);
45827330f729Sjoerg return 1;
45837330f729Sjoerg }
45847330f729Sjoerg
45857330f729Sjoerg switch (clang_saveTranslationUnit(TU, filename,
45867330f729Sjoerg clang_defaultSaveOptions(TU))) {
45877330f729Sjoerg case CXSaveError_None:
45887330f729Sjoerg break;
45897330f729Sjoerg
45907330f729Sjoerg case CXSaveError_TranslationErrors:
45917330f729Sjoerg fprintf(stderr, "Unable to write PCH file %s: translation errors\n",
45927330f729Sjoerg filename);
45937330f729Sjoerg result = 2;
45947330f729Sjoerg break;
45957330f729Sjoerg
45967330f729Sjoerg case CXSaveError_InvalidTU:
45977330f729Sjoerg fprintf(stderr, "Unable to write PCH file %s: invalid translation unit\n",
45987330f729Sjoerg filename);
45997330f729Sjoerg result = 3;
46007330f729Sjoerg break;
46017330f729Sjoerg
46027330f729Sjoerg case CXSaveError_Unknown:
46037330f729Sjoerg default:
46047330f729Sjoerg fprintf(stderr, "Unable to write PCH file %s: unknown error \n", filename);
46057330f729Sjoerg result = 1;
46067330f729Sjoerg break;
46077330f729Sjoerg }
46087330f729Sjoerg
46097330f729Sjoerg clang_disposeTranslationUnit(TU);
46107330f729Sjoerg free_remapped_files(unsaved_files, num_unsaved_files);
46117330f729Sjoerg clang_disposeIndex(Idx);
46127330f729Sjoerg return result;
46137330f729Sjoerg }
46147330f729Sjoerg
46157330f729Sjoerg /******************************************************************************/
46167330f729Sjoerg /* Serialized diagnostics. */
46177330f729Sjoerg /******************************************************************************/
46187330f729Sjoerg
getDiagnosticCodeStr(enum CXLoadDiag_Error error)46197330f729Sjoerg static const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error) {
46207330f729Sjoerg switch (error) {
46217330f729Sjoerg case CXLoadDiag_CannotLoad: return "Cannot Load File";
46227330f729Sjoerg case CXLoadDiag_None: break;
46237330f729Sjoerg case CXLoadDiag_Unknown: return "Unknown";
46247330f729Sjoerg case CXLoadDiag_InvalidFile: return "Invalid File";
46257330f729Sjoerg }
46267330f729Sjoerg return "None";
46277330f729Sjoerg }
46287330f729Sjoerg
getSeverityString(enum CXDiagnosticSeverity severity)46297330f729Sjoerg static const char *getSeverityString(enum CXDiagnosticSeverity severity) {
46307330f729Sjoerg switch (severity) {
46317330f729Sjoerg case CXDiagnostic_Note: return "note";
46327330f729Sjoerg case CXDiagnostic_Error: return "error";
46337330f729Sjoerg case CXDiagnostic_Fatal: return "fatal";
46347330f729Sjoerg case CXDiagnostic_Ignored: return "ignored";
46357330f729Sjoerg case CXDiagnostic_Warning: return "warning";
46367330f729Sjoerg }
46377330f729Sjoerg return "unknown";
46387330f729Sjoerg }
46397330f729Sjoerg
printIndent(unsigned indent)46407330f729Sjoerg static void printIndent(unsigned indent) {
46417330f729Sjoerg if (indent == 0)
46427330f729Sjoerg return;
46437330f729Sjoerg fprintf(stderr, "+");
46447330f729Sjoerg --indent;
46457330f729Sjoerg while (indent > 0) {
46467330f729Sjoerg fprintf(stderr, "-");
46477330f729Sjoerg --indent;
46487330f729Sjoerg }
46497330f729Sjoerg }
46507330f729Sjoerg
printLocation(CXSourceLocation L)46517330f729Sjoerg static void printLocation(CXSourceLocation L) {
46527330f729Sjoerg CXFile File;
46537330f729Sjoerg CXString FileName;
46547330f729Sjoerg unsigned line, column, offset;
46557330f729Sjoerg
46567330f729Sjoerg clang_getExpansionLocation(L, &File, &line, &column, &offset);
46577330f729Sjoerg FileName = clang_getFileName(File);
46587330f729Sjoerg
46597330f729Sjoerg fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column);
46607330f729Sjoerg clang_disposeString(FileName);
46617330f729Sjoerg }
46627330f729Sjoerg
printRanges(CXDiagnostic D,unsigned indent)46637330f729Sjoerg static void printRanges(CXDiagnostic D, unsigned indent) {
46647330f729Sjoerg unsigned i, n = clang_getDiagnosticNumRanges(D);
46657330f729Sjoerg
46667330f729Sjoerg for (i = 0; i < n; ++i) {
46677330f729Sjoerg CXSourceLocation Start, End;
46687330f729Sjoerg CXSourceRange SR = clang_getDiagnosticRange(D, i);
46697330f729Sjoerg Start = clang_getRangeStart(SR);
46707330f729Sjoerg End = clang_getRangeEnd(SR);
46717330f729Sjoerg
46727330f729Sjoerg printIndent(indent);
46737330f729Sjoerg fprintf(stderr, "Range: ");
46747330f729Sjoerg printLocation(Start);
46757330f729Sjoerg fprintf(stderr, " ");
46767330f729Sjoerg printLocation(End);
46777330f729Sjoerg fprintf(stderr, "\n");
46787330f729Sjoerg }
46797330f729Sjoerg }
46807330f729Sjoerg
printFixIts(CXDiagnostic D,unsigned indent)46817330f729Sjoerg static void printFixIts(CXDiagnostic D, unsigned indent) {
46827330f729Sjoerg unsigned i, n = clang_getDiagnosticNumFixIts(D);
46837330f729Sjoerg fprintf(stderr, "Number FIXITs = %d\n", n);
46847330f729Sjoerg for (i = 0 ; i < n; ++i) {
46857330f729Sjoerg CXSourceRange ReplacementRange;
46867330f729Sjoerg CXString text;
46877330f729Sjoerg text = clang_getDiagnosticFixIt(D, i, &ReplacementRange);
46887330f729Sjoerg
46897330f729Sjoerg printIndent(indent);
46907330f729Sjoerg fprintf(stderr, "FIXIT: (");
46917330f729Sjoerg printLocation(clang_getRangeStart(ReplacementRange));
46927330f729Sjoerg fprintf(stderr, " - ");
46937330f729Sjoerg printLocation(clang_getRangeEnd(ReplacementRange));
46947330f729Sjoerg fprintf(stderr, "): \"%s\"\n", clang_getCString(text));
46957330f729Sjoerg clang_disposeString(text);
46967330f729Sjoerg }
46977330f729Sjoerg }
46987330f729Sjoerg
printDiagnosticSet(CXDiagnosticSet Diags,unsigned indent)46997330f729Sjoerg static void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) {
47007330f729Sjoerg unsigned i, n;
47017330f729Sjoerg
47027330f729Sjoerg if (!Diags)
47037330f729Sjoerg return;
47047330f729Sjoerg
47057330f729Sjoerg n = clang_getNumDiagnosticsInSet(Diags);
47067330f729Sjoerg for (i = 0; i < n; ++i) {
47077330f729Sjoerg CXSourceLocation DiagLoc;
47087330f729Sjoerg CXDiagnostic D;
47097330f729Sjoerg CXFile File;
47107330f729Sjoerg CXString FileName, DiagSpelling, DiagOption, DiagCat;
47117330f729Sjoerg unsigned line, column, offset;
47127330f729Sjoerg const char *FileNameStr = 0, *DiagOptionStr = 0, *DiagCatStr = 0;
47137330f729Sjoerg
47147330f729Sjoerg D = clang_getDiagnosticInSet(Diags, i);
47157330f729Sjoerg DiagLoc = clang_getDiagnosticLocation(D);
47167330f729Sjoerg clang_getExpansionLocation(DiagLoc, &File, &line, &column, &offset);
47177330f729Sjoerg FileName = clang_getFileName(File);
47187330f729Sjoerg FileNameStr = clang_getCString(FileName);
47197330f729Sjoerg DiagSpelling = clang_getDiagnosticSpelling(D);
47207330f729Sjoerg
47217330f729Sjoerg printIndent(indent);
47227330f729Sjoerg
47237330f729Sjoerg fprintf(stderr, "%s:%d:%d: %s: %s",
47247330f729Sjoerg FileNameStr ? FileNameStr : "(null)",
47257330f729Sjoerg line,
47267330f729Sjoerg column,
47277330f729Sjoerg getSeverityString(clang_getDiagnosticSeverity(D)),
47287330f729Sjoerg clang_getCString(DiagSpelling));
47297330f729Sjoerg
47307330f729Sjoerg DiagOption = clang_getDiagnosticOption(D, 0);
47317330f729Sjoerg DiagOptionStr = clang_getCString(DiagOption);
47327330f729Sjoerg if (DiagOptionStr) {
47337330f729Sjoerg fprintf(stderr, " [%s]", DiagOptionStr);
47347330f729Sjoerg }
47357330f729Sjoerg
47367330f729Sjoerg DiagCat = clang_getDiagnosticCategoryText(D);
47377330f729Sjoerg DiagCatStr = clang_getCString(DiagCat);
47387330f729Sjoerg if (DiagCatStr) {
47397330f729Sjoerg fprintf(stderr, " [%s]", DiagCatStr);
47407330f729Sjoerg }
47417330f729Sjoerg
47427330f729Sjoerg fprintf(stderr, "\n");
47437330f729Sjoerg
47447330f729Sjoerg printRanges(D, indent);
47457330f729Sjoerg printFixIts(D, indent);
47467330f729Sjoerg
47477330f729Sjoerg /* Print subdiagnostics. */
47487330f729Sjoerg printDiagnosticSet(clang_getChildDiagnostics(D), indent+2);
47497330f729Sjoerg
47507330f729Sjoerg clang_disposeString(FileName);
47517330f729Sjoerg clang_disposeString(DiagSpelling);
47527330f729Sjoerg clang_disposeString(DiagOption);
47537330f729Sjoerg clang_disposeString(DiagCat);
47547330f729Sjoerg }
47557330f729Sjoerg }
47567330f729Sjoerg
read_diagnostics(const char * filename)47577330f729Sjoerg static int read_diagnostics(const char *filename) {
47587330f729Sjoerg enum CXLoadDiag_Error error;
47597330f729Sjoerg CXString errorString;
47607330f729Sjoerg CXDiagnosticSet Diags = 0;
47617330f729Sjoerg
47627330f729Sjoerg Diags = clang_loadDiagnostics(filename, &error, &errorString);
47637330f729Sjoerg if (!Diags) {
47647330f729Sjoerg fprintf(stderr, "Trouble deserializing file (%s): %s\n",
47657330f729Sjoerg getDiagnosticCodeStr(error),
47667330f729Sjoerg clang_getCString(errorString));
47677330f729Sjoerg clang_disposeString(errorString);
47687330f729Sjoerg return 1;
47697330f729Sjoerg }
47707330f729Sjoerg
47717330f729Sjoerg printDiagnosticSet(Diags, 0);
47727330f729Sjoerg fprintf(stderr, "Number of diagnostics: %d\n",
47737330f729Sjoerg clang_getNumDiagnosticsInSet(Diags));
47747330f729Sjoerg clang_disposeDiagnosticSet(Diags);
47757330f729Sjoerg return 0;
47767330f729Sjoerg }
47777330f729Sjoerg
perform_print_build_session_timestamp(void)47787330f729Sjoerg static int perform_print_build_session_timestamp(void) {
47797330f729Sjoerg printf("%lld\n", clang_getBuildSessionTimestamp());
47807330f729Sjoerg return 0;
47817330f729Sjoerg }
47827330f729Sjoerg
47837330f729Sjoerg /******************************************************************************/
47847330f729Sjoerg /* Command line processing. */
47857330f729Sjoerg /******************************************************************************/
47867330f729Sjoerg
GetVisitor(const char * s)47877330f729Sjoerg static CXCursorVisitor GetVisitor(const char *s) {
47887330f729Sjoerg if (s[0] == '\0')
47897330f729Sjoerg return FilteredPrintingVisitor;
47907330f729Sjoerg if (strcmp(s, "-usrs") == 0)
47917330f729Sjoerg return USRVisitor;
47927330f729Sjoerg if (strncmp(s, "-memory-usage", 13) == 0)
47937330f729Sjoerg return GetVisitor(s + 13);
47947330f729Sjoerg return NULL;
47957330f729Sjoerg }
47967330f729Sjoerg
print_usage(void)47977330f729Sjoerg static void print_usage(void) {
47987330f729Sjoerg fprintf(stderr,
47997330f729Sjoerg "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
48007330f729Sjoerg " c-index-test -code-completion-timing=<site> <compiler arguments>\n"
48017330f729Sjoerg " c-index-test -cursor-at=<site> <compiler arguments>\n"
48027330f729Sjoerg " c-index-test -evaluate-cursor-at=<site> <compiler arguments>\n"
48037330f729Sjoerg " c-index-test -get-macro-info-cursor-at=<site> <compiler arguments>\n"
48047330f729Sjoerg " c-index-test -file-refs-at=<site> <compiler arguments>\n"
48057330f729Sjoerg " c-index-test -file-includes-in=<filename> <compiler arguments>\n");
48067330f729Sjoerg fprintf(stderr,
48077330f729Sjoerg " c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
48087330f729Sjoerg " c-index-test -index-file-full [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
48097330f729Sjoerg " c-index-test -index-tu [-check-prefix=<FileCheck prefix>] <AST file>\n"
48107330f729Sjoerg " c-index-test -index-compile-db [-check-prefix=<FileCheck prefix>] <compilation database>\n"
48117330f729Sjoerg " c-index-test -test-file-scan <AST file> <source file> "
48127330f729Sjoerg "[FileCheck prefix]\n");
48137330f729Sjoerg fprintf(stderr,
48147330f729Sjoerg " c-index-test -test-load-tu <AST file> <symbol filter> "
48157330f729Sjoerg "[FileCheck prefix]\n"
48167330f729Sjoerg " c-index-test -test-load-tu-usrs <AST file> <symbol filter> "
48177330f729Sjoerg "[FileCheck prefix]\n"
48187330f729Sjoerg " c-index-test -test-load-source <symbol filter> {<args>}*\n");
48197330f729Sjoerg fprintf(stderr,
48207330f729Sjoerg " c-index-test -test-load-source-memory-usage "
48217330f729Sjoerg "<symbol filter> {<args>}*\n"
48227330f729Sjoerg " c-index-test -test-load-source-reparse <trials> <symbol filter> "
48237330f729Sjoerg " {<args>}*\n"
48247330f729Sjoerg " c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
48257330f729Sjoerg " c-index-test -test-load-source-usrs-memory-usage "
48267330f729Sjoerg "<symbol filter> {<args>}*\n"
48277330f729Sjoerg " c-index-test -test-annotate-tokens=<range> {<args>}*\n"
48287330f729Sjoerg " c-index-test -test-inclusion-stack-source {<args>}*\n"
48297330f729Sjoerg " c-index-test -test-inclusion-stack-tu <AST file>\n");
48307330f729Sjoerg fprintf(stderr,
48317330f729Sjoerg " c-index-test -test-print-linkage-source {<args>}*\n"
48327330f729Sjoerg " c-index-test -test-print-visibility {<args>}*\n"
48337330f729Sjoerg " c-index-test -test-print-type {<args>}*\n"
48347330f729Sjoerg " c-index-test -test-print-type-size {<args>}*\n"
48357330f729Sjoerg " c-index-test -test-print-bitwidth {<args>}*\n"
48367330f729Sjoerg " c-index-test -test-print-target-info {<args>}*\n"
48377330f729Sjoerg " c-index-test -test-print-type-declaration {<args>}*\n"
48387330f729Sjoerg " c-index-test -print-usr [<CursorKind> {<args>}]*\n"
48397330f729Sjoerg " c-index-test -print-usr-file <file>\n");
48407330f729Sjoerg fprintf(stderr,
48417330f729Sjoerg " c-index-test -write-pch <file> <compiler arguments>\n"
48427330f729Sjoerg " c-index-test -compilation-db [lookup <filename>] database\n");
48437330f729Sjoerg fprintf(stderr,
48447330f729Sjoerg " c-index-test -print-build-session-timestamp\n");
48457330f729Sjoerg fprintf(stderr,
48467330f729Sjoerg " c-index-test -read-diagnostics <file>\n\n");
48477330f729Sjoerg fprintf(stderr,
48487330f729Sjoerg " <symbol filter> values:\n%s",
48497330f729Sjoerg " all - load all symbols, including those from PCH\n"
48507330f729Sjoerg " local - load all symbols except those in PCH\n"
48517330f729Sjoerg " category - only load ObjC categories (non-PCH)\n"
48527330f729Sjoerg " interface - only load ObjC interfaces (non-PCH)\n"
48537330f729Sjoerg " protocol - only load ObjC protocols (non-PCH)\n"
48547330f729Sjoerg " function - only load functions (non-PCH)\n"
48557330f729Sjoerg " typedef - only load typdefs (non-PCH)\n"
48567330f729Sjoerg " scan-function - scan function bodies (non-PCH)\n\n");
48577330f729Sjoerg }
48587330f729Sjoerg
48597330f729Sjoerg /***/
48607330f729Sjoerg
cindextest_main(int argc,const char ** argv)48617330f729Sjoerg int cindextest_main(int argc, const char **argv) {
48627330f729Sjoerg clang_enableStackTraces();
48637330f729Sjoerg if (argc > 2 && strcmp(argv[1], "-read-diagnostics") == 0)
48647330f729Sjoerg return read_diagnostics(argv[2]);
48657330f729Sjoerg if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
48667330f729Sjoerg return perform_code_completion(argc, argv, 0);
48677330f729Sjoerg if (argc > 2 && strstr(argv[1], "-code-completion-timing=") == argv[1])
48687330f729Sjoerg return perform_code_completion(argc, argv, 1);
48697330f729Sjoerg if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
48707330f729Sjoerg return inspect_cursor_at(argc, argv, "-cursor-at=", inspect_print_cursor);
48717330f729Sjoerg if (argc > 2 && strstr(argv[1], "-evaluate-cursor-at=") == argv[1])
48727330f729Sjoerg return inspect_cursor_at(argc, argv, "-evaluate-cursor-at=",
48737330f729Sjoerg inspect_evaluate_cursor);
48747330f729Sjoerg if (argc > 2 && strstr(argv[1], "-get-macro-info-cursor-at=") == argv[1])
48757330f729Sjoerg return inspect_cursor_at(argc, argv, "-get-macro-info-cursor-at=",
48767330f729Sjoerg inspect_macroinfo_cursor);
48777330f729Sjoerg if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1])
48787330f729Sjoerg return find_file_refs_at(argc, argv);
48797330f729Sjoerg if (argc > 2 && strstr(argv[1], "-file-includes-in=") == argv[1])
48807330f729Sjoerg return find_file_includes_in(argc, argv);
48817330f729Sjoerg if (argc > 2 && strcmp(argv[1], "-index-file") == 0)
48827330f729Sjoerg return index_file(argc - 2, argv + 2, /*full=*/0);
48837330f729Sjoerg if (argc > 2 && strcmp(argv[1], "-index-file-full") == 0)
48847330f729Sjoerg return index_file(argc - 2, argv + 2, /*full=*/1);
48857330f729Sjoerg if (argc > 2 && strcmp(argv[1], "-index-tu") == 0)
48867330f729Sjoerg return index_tu(argc - 2, argv + 2);
48877330f729Sjoerg if (argc > 2 && strcmp(argv[1], "-index-compile-db") == 0)
48887330f729Sjoerg return index_compile_db(argc - 2, argv + 2);
48897330f729Sjoerg else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
48907330f729Sjoerg CXCursorVisitor I = GetVisitor(argv[1] + 13);
48917330f729Sjoerg if (I)
48927330f729Sjoerg return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I,
48937330f729Sjoerg NULL);
48947330f729Sjoerg }
48957330f729Sjoerg else if (argc >= 5 && strncmp(argv[1], "-test-load-source-reparse", 25) == 0){
48967330f729Sjoerg CXCursorVisitor I = GetVisitor(argv[1] + 25);
48977330f729Sjoerg if (I) {
48987330f729Sjoerg int trials = atoi(argv[2]);
48997330f729Sjoerg return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I,
49007330f729Sjoerg NULL);
49017330f729Sjoerg }
49027330f729Sjoerg }
49037330f729Sjoerg else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
49047330f729Sjoerg CXCursorVisitor I = GetVisitor(argv[1] + 17);
49057330f729Sjoerg
49067330f729Sjoerg PostVisitTU postVisit = 0;
49077330f729Sjoerg if (strstr(argv[1], "-memory-usage"))
49087330f729Sjoerg postVisit = PrintMemoryUsage;
49097330f729Sjoerg
49107330f729Sjoerg if (I)
49117330f729Sjoerg return perform_test_load_source(argc - 3, argv + 3, argv[2], I,
49127330f729Sjoerg postVisit);
49137330f729Sjoerg }
49147330f729Sjoerg else if (argc >= 3 && strcmp(argv[1], "-single-file-parse") == 0)
49157330f729Sjoerg return perform_single_file_parse(argv[2]);
49167330f729Sjoerg else if (argc >= 3 && strcmp(argv[1], "-retain-excluded-conditional-blocks") == 0)
49177330f729Sjoerg return perform_file_retain_excluded_cb(argv[2]);
49187330f729Sjoerg else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
49197330f729Sjoerg return perform_file_scan(argv[2], argv[3],
49207330f729Sjoerg argc >= 5 ? argv[4] : 0);
49217330f729Sjoerg else if (argc > 2 && strstr(argv[1], "-test-annotate-tokens=") == argv[1])
49227330f729Sjoerg return perform_token_annotation(argc, argv);
49237330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-source") == 0)
49247330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all", NULL,
49257330f729Sjoerg PrintInclusionStack);
49267330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-tu") == 0)
49277330f729Sjoerg return perform_test_load_tu(argv[2], "all", NULL, NULL,
49287330f729Sjoerg PrintInclusionStack);
49297330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0)
49307330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage,
49317330f729Sjoerg NULL);
49327330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-visibility") == 0)
49337330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all", PrintVisibility,
49347330f729Sjoerg NULL);
49357330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0)
49367330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all",
49377330f729Sjoerg PrintType, 0);
49387330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-type-size") == 0)
49397330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all",
49407330f729Sjoerg PrintTypeSize, 0);
49417330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-type-declaration") == 0)
49427330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all",
49437330f729Sjoerg PrintTypeDeclaration, 0);
49447330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-decl-attributes") == 0)
49457330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all",
49467330f729Sjoerg PrintDeclAttributes, 0);
49477330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0)
49487330f729Sjoerg return perform_test_load_source(argc - 2, argv + 2, "all",
49497330f729Sjoerg PrintBitWidth, 0);
49507330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-mangle") == 0)
49517330f729Sjoerg return perform_test_load_tu(argv[2], "all", NULL, PrintMangledName, NULL);
49527330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-manglings") == 0)
49537330f729Sjoerg return perform_test_load_tu(argv[2], "all", NULL, PrintManglings, NULL);
49547330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-test-print-target-info") == 0)
49557330f729Sjoerg return print_target_info(argc - 2, argv + 2);
49567330f729Sjoerg else if (argc > 1 && strcmp(argv[1], "-print-usr") == 0) {
49577330f729Sjoerg if (argc > 2)
49587330f729Sjoerg return print_usrs(argv + 2, argv + argc);
49597330f729Sjoerg else {
49607330f729Sjoerg display_usrs();
49617330f729Sjoerg return 1;
49627330f729Sjoerg }
49637330f729Sjoerg }
49647330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-print-usr-file") == 0)
49657330f729Sjoerg return print_usrs_file(argv[2]);
49667330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0)
49677330f729Sjoerg return write_pch_file(argv[2], argc - 3, argv + 3);
49687330f729Sjoerg else if (argc > 2 && strcmp(argv[1], "-compilation-db") == 0)
49697330f729Sjoerg return perform_test_compilation_db(argv[argc-1], argc - 3, argv + 2);
49707330f729Sjoerg else if (argc == 2 && strcmp(argv[1], "-print-build-session-timestamp") == 0)
49717330f729Sjoerg return perform_print_build_session_timestamp();
49727330f729Sjoerg
49737330f729Sjoerg print_usage();
49747330f729Sjoerg return 1;
49757330f729Sjoerg }
49767330f729Sjoerg
49777330f729Sjoerg /***/
49787330f729Sjoerg
49797330f729Sjoerg /* We intentionally run in a separate thread to ensure we at least minimal
49807330f729Sjoerg * testing of a multithreaded environment (for example, having a reduced stack
49817330f729Sjoerg * size). */
49827330f729Sjoerg
49837330f729Sjoerg typedef struct thread_info {
49847330f729Sjoerg int (*main_func)(int argc, const char **argv);
49857330f729Sjoerg int argc;
49867330f729Sjoerg const char **argv;
49877330f729Sjoerg int result;
49887330f729Sjoerg } thread_info;
thread_runner(void * client_data_v)49897330f729Sjoerg void thread_runner(void *client_data_v) {
49907330f729Sjoerg thread_info *client_data = client_data_v;
49917330f729Sjoerg client_data->result = client_data->main_func(client_data->argc,
49927330f729Sjoerg client_data->argv);
49937330f729Sjoerg }
49947330f729Sjoerg
flush_atexit(void)49957330f729Sjoerg static void flush_atexit(void) {
49967330f729Sjoerg /* stdout, and surprisingly even stderr, are not always flushed on process
49977330f729Sjoerg * and thread exit, particularly when the system is under heavy load. */
49987330f729Sjoerg fflush(stdout);
49997330f729Sjoerg fflush(stderr);
50007330f729Sjoerg }
50017330f729Sjoerg
main(int argc,const char ** argv)50027330f729Sjoerg int main(int argc, const char **argv) {
50037330f729Sjoerg thread_info client_data;
50047330f729Sjoerg
50057330f729Sjoerg atexit(flush_atexit);
50067330f729Sjoerg
50077330f729Sjoerg #ifdef CLANG_HAVE_LIBXML
50087330f729Sjoerg LIBXML_TEST_VERSION
50097330f729Sjoerg #endif
50107330f729Sjoerg
50117330f729Sjoerg if (argc > 1 && strcmp(argv[1], "core") == 0)
50127330f729Sjoerg return indextest_core_main(argc, argv);
50137330f729Sjoerg
50147330f729Sjoerg client_data.main_func = cindextest_main;
50157330f729Sjoerg client_data.argc = argc;
50167330f729Sjoerg client_data.argv = argv;
50177330f729Sjoerg
50187330f729Sjoerg if (getenv("CINDEXTEST_NOTHREADS"))
50197330f729Sjoerg return client_data.main_func(client_data.argc, client_data.argv);
50207330f729Sjoerg
50217330f729Sjoerg clang_executeOnThread(thread_runner, &client_data, 0);
50227330f729Sjoerg return client_data.result;
50237330f729Sjoerg }
5024