zcov: / tools/c-index-test/c-index-test.c


Files: 1 Branches Taken: 59.6% 180 / 302
Generated: 2010-02-10 01:31 Branches Executed: 83.4% 252 / 302
Line Coverage: 74.9% 388 / 518


Programs: 1 Runs 69


       1                 : /* c-index-test.c */
       2                 : 
       3                 : #include "clang-c/Index.h"
       4                 : #include <stdlib.h>
       5                 : #include <stdio.h>
       6                 : #include <string.h>
       7                 : #include <assert.h>
       8                 : 
       9                 : /******************************************************************************/
      10                 : /* Utility functions.                                                         */
      11                 : /******************************************************************************/
      12                 : 
      13                 : #ifdef _MSC_VER
      14                 : char *basename(const char* path)
      15                 : {
      16                 :     char* base1 = (char*)strrchr(path, '/');
      17                 :     char* base2 = (char*)strrchr(path, '\\');
      18                 :     if (base1 && base2)
      19                 :         return((base1 > base2) ? base1 + 1 : base2 + 1);
      20                 :     else if (base1)
      21                 :         return(base1 + 1);
      22                 :     else if (base2)
      23                 :         return(base2 + 1);
      24                 : 
      25                 :     return((char*)path);
      26                 : }
      27                 : #else
      28                 : extern char *basename(const char *);
      29                 : #endif
      30                 : 
      31                 : static void PrintDiagnosticCallback(CXDiagnostic Diagnostic, 
      32                 :                                     CXClientData ClientData);
      33                 : 
      34                 : static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
      35                8:                                       CXTranslationUnit *TU) {
      36                 :   
      37                8:   *TU = clang_createTranslationUnit(Idx, file, PrintDiagnosticCallback, 0);
                        0: branch 0 not taken
                        8: branch 1 taken
      38                8:   if (!TU) {
      39                0:     fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
      40                0:     return 0;
      41                 :   }  
      42                8:   return 1;
      43                 : }
      44                 : 
      45                 : void free_remapped_files(struct CXUnsavedFile *unsaved_files,
      46               60:                          int num_unsaved_files) {
      47                 :   int i;
                        5: branch 0 taken
                       60: branch 1 taken
      48               65:   for (i = 0; i != num_unsaved_files; ++i) {
      49                5:     free((char *)unsaved_files[i].Filename);
      50                5:     free((char *)unsaved_files[i].Contents);
      51                 :   }
      52               60: }
      53                 : 
      54                 : int parse_remapped_files(int argc, const char **argv, int start_arg,
      55                 :                          struct CXUnsavedFile **unsaved_files,
      56               61:                          int *num_unsaved_files) {
      57                 :   int i;
      58                 :   int arg;
      59               61:   int prefix_len = strlen("-remap-file=");
      60               61:   *unsaved_files = 0;
      61               61:   *num_unsaved_files = 0;
      62                 :   
      63                 :   /* Count the number of remapped files. */
                       66: branch 0 taken
                        0: branch 1 not taken
      64               66:   for (arg = start_arg; arg < argc; ++arg) {
                       61: branch 1 taken
                        5: branch 2 taken
      65               66:     if (strncmp(argv[arg], "-remap-file=", prefix_len))
      66               61:       break;
      67                 :     
      68                5:     ++*num_unsaved_files;
      69                 :   }
      70                 :   
                       56: branch 0 taken
                        5: branch 1 taken
      71               61:   if (*num_unsaved_files == 0)
      72               56:     return 0;
      73                 :   
      74                5:   *unsaved_files
      75                 :   = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) * 
      76                 :                                    *num_unsaved_files);
                        5: branch 0 taken
                        5: branch 1 taken
      77               10:   for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
      78                5:     struct CXUnsavedFile *unsaved = *unsaved_files + i;
      79                5:     const char *arg_string = argv[arg] + prefix_len;
      80                 :     int filename_len;
      81                 :     char *filename;
      82                 :     char *contents;
      83                 :     FILE *to_file;
      84                5:     const char *semi = strchr(arg_string, ';');
                        0: branch 0 not taken
                        5: branch 1 taken
      85                5:     if (!semi) {
      86                0:       fprintf(stderr, 
      87                 :               "error: -remap-file=from;to argument is missing semicolon\n");
      88                0:       free_remapped_files(*unsaved_files, i);
      89                0:       *unsaved_files = 0;
      90                0:       *num_unsaved_files = 0;
      91                0:       return -1;
      92                 :     }
      93                 :     
      94                 :     /* Open the file that we're remapping to. */
      95                5:     to_file = fopen(semi + 1, "r");
                        0: branch 0 not taken
                        5: branch 1 taken
      96                5:     if (!to_file) {
      97                0:       fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
      98                 :               semi + 1);
      99                0:       free_remapped_files(*unsaved_files, i);
     100                0:       *unsaved_files = 0;
     101                0:       *num_unsaved_files = 0;
     102                0:       return -1;
     103                 :     }
     104                 :     
     105                 :     /* Determine the length of the file we're remapping to. */
     106                5:     fseek(to_file, 0, SEEK_END);
     107                5:     unsaved->Length = ftell(to_file);
     108                5:     fseek(to_file, 0, SEEK_SET);
     109                 :     
     110                 :     /* Read the contents of the file we're remapping to. */
     111                5:     contents = (char *)malloc(unsaved->Length + 1);
                        0: branch 1 not taken
                        5: branch 2 taken
     112                5:     if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     113                0:       fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
     114                 :               (feof(to_file) ? "EOF" : "error"), semi + 1);
     115                0:       fclose(to_file);
     116                0:       free_remapped_files(*unsaved_files, i);
     117                0:       *unsaved_files = 0;
     118                0:       *num_unsaved_files = 0;
     119                0:       return -1;
     120                 :     }
     121                5:     contents[unsaved->Length] = 0;
     122                5:     unsaved->Contents = contents;
     123                 :     
     124                 :     /* Close the file. */
     125                5:     fclose(to_file);
     126                 :     
     127                 :     /* Copy the file name that we're remapping from. */
     128                5:     filename_len = semi - arg_string;
     129                5:     filename = (char *)malloc(filename_len + 1);
     130                5:     memcpy(filename, arg_string, filename_len);
     131                5:     filename[filename_len] = 0;
     132                5:     unsaved->Filename = filename;
     133                 :   }
     134                 :   
     135                5:   return 0;
     136                 : }
     137                 : 
     138                 : /******************************************************************************/
     139                 : /* Pretty-printing.                                                           */
     140                 : /******************************************************************************/
     141                 : 
     142              375: static void PrintCursor(CXCursor Cursor) {
                       16: branch 1 taken
                      359: branch 2 taken
     143              375:   if (clang_isInvalid(Cursor.kind))
     144               16:     printf("Invalid Cursor => %s", clang_getCursorKindSpelling(Cursor.kind));
     145                 :   else {
     146                 :     CXString string;
     147                 :     CXCursor Referenced;
     148                 :     unsigned line, column;
     149              359:     string = clang_getCursorSpelling(Cursor);
     150              359:     printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
     151                 :                       clang_getCString(string));
     152              359:     clang_disposeString(string);
     153                 :     
     154              359:     Referenced = clang_getCursorReferenced(Cursor);
                      295: branch 2 taken
                       64: branch 3 taken
     155              359:     if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
     156              295:       CXSourceLocation Loc = clang_getCursorLocation(Referenced);
     157              295:       clang_getInstantiationLocation(Loc, 0, &line, &column, 0);
     158              295:       printf(":%d:%d", line, column);
     159                 :     }
     160                 : 
                      124: branch 1 taken
                      235: branch 2 taken
     161              359:     if (clang_isCursorDefinition(Cursor))
     162              124:       printf(" (Definition)");
     163                 :   }
     164              375: }
     165                 : 
     166              237: static const char* GetCursorSource(CXCursor Cursor) {  
     167              237:   CXSourceLocation Loc = clang_getCursorLocation(Cursor);
     168                 :   const char *source;
     169                 :   CXFile file;
     170              237:   clang_getInstantiationLocation(Loc, &file, 0, 0, 0);
     171              237:   source = clang_getFileName(file);
                       53: branch 0 taken
                      184: branch 1 taken
     172              237:   if (!source)
     173               53:     return "<invalid loc>";  
     174              184:   return basename(source);
     175                 : }
     176                 : 
     177                 : /******************************************************************************/
     178                 : /* Callbacks.                                                                 */
     179                 : /******************************************************************************/
     180                 : 
     181                 : typedef void (*PostVisitTU)(CXTranslationUnit);
     182                 : 
     183                 : static void PrintDiagnosticCallback(CXDiagnostic Diagnostic, 
     184               55:                                     CXClientData ClientData) {
     185               55:   FILE *out = (FILE *)ClientData;
     186                 :   CXFile file;
     187                 :   unsigned line, column;
     188                 :   CXString text;
     189               55:   enum CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(Diagnostic);
     190                 :   
     191                 :   /* Ignore diagnostics that should be ignored. */
                        0: branch 0 not taken
                       55: branch 1 taken
     192               55:   if (severity == CXDiagnostic_Ignored)
     193                0:     return;
     194                 :   
     195                 :   /* Print file:line:column. */
     196               55:   clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
     197                 :                                  &file, &line, &column, 0);
                       55: branch 0 taken
                        0: branch 1 not taken
     198               55:   if (file) {
     199                 :     unsigned i, n;
     200               55:     unsigned printed_any_ranges = 0;
     201                 :     
     202               55:     fprintf(out, "%s:%d:%d:", clang_getFileName(file), line, column);
     203                 :   
     204               55:     n = clang_getDiagnosticNumRanges(Diagnostic);
                       11: branch 0 taken
                       55: branch 1 taken
     205               66:     for (i = 0; i != n; ++i) {
     206                 :       CXFile start_file, end_file;
     207               11:       CXSourceRange range = clang_getDiagnosticRange(Diagnostic, i);
     208                 :       
     209                 :       unsigned start_line, start_column, end_line, end_column;
     210               11:       clang_getInstantiationLocation(clang_getRangeStart(range),
     211                 :                                      &start_file, &start_line, &start_column,0);
     212               11:       clang_getInstantiationLocation(clang_getRangeEnd(range),
     213                 :                                      &end_file, &end_line, &end_column, 0);
     214                 :       
                       11: branch 0 taken
                        0: branch 1 not taken
                       11: branch 2 taken
                        0: branch 3 not taken
     215               11:       if (start_file != end_file || start_file != file)
     216                 :         continue;
     217                 :       
     218               11:       fprintf(out, "{%d:%d-%d:%d}", start_line, start_column, end_line, 
     219                 :               end_column+1);
     220               11:       printed_any_ranges = 1;
     221                 :     }
                       10: branch 0 taken
                       45: branch 1 taken
     222               55:     if (printed_any_ranges)
     223               10:       fprintf(out, ":");
     224                 :     
     225               55:     fprintf(out, " ");
     226                 :   }
     227                 :   
     228                 :   /* Print warning/error/etc. */
                        0: branch 0 not taken
                        3: branch 1 taken
                       44: branch 2 taken
                        6: branch 3 taken
                        2: branch 4 taken
                        0: branch 5 not taken
     229               55:   switch (severity) {
     230                0:   case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
     231                3:   case CXDiagnostic_Note: fprintf(out, "note: "); break;
     232               44:   case CXDiagnostic_Warning: fprintf(out, "warning: "); break;
     233                6:   case CXDiagnostic_Error: fprintf(out, "error: "); break;
     234                2:   case CXDiagnostic_Fatal: fprintf(out, "fatal error: "); break;
     235                 :   }
     236                 :   
     237               55:   text = clang_getDiagnosticSpelling(Diagnostic);
                       55: branch 1 taken
                        0: branch 2 not taken
     238               55:   if (clang_getCString(text))
     239               55:     fprintf(out, "%s\n", clang_getCString(text));
     240                 :   else
     241                0:     fprintf(out, "<no diagnostic text>\n");
     242               55:   clang_disposeString(text);
     243                 :   
                       55: branch 0 taken
                        0: branch 1 not taken
     244               55:   if (file) {
     245               55:     unsigned i, num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
                        3: branch 0 taken
                       55: branch 1 taken
     246               58:     for (i = 0; i != num_fixits; ++i) {
                        1: branch 1 taken
                        1: branch 2 taken
                        1: branch 3 taken
                        0: branch 4 not taken
     247                3:       switch (clang_getDiagnosticFixItKind(Diagnostic, i)) {
     248                 :       case CXFixIt_Insertion: {
     249                 :         CXSourceLocation insertion_loc;
     250                 :         CXFile insertion_file;
     251                 :         unsigned insertion_line, insertion_column;
     252                1:         text = clang_getDiagnosticFixItInsertion(Diagnostic, i, &insertion_loc);
     253                1:         clang_getInstantiationLocation(insertion_loc, &insertion_file, 
     254                 :                                        &insertion_line, &insertion_column, 0);
                        1: branch 0 taken
                        0: branch 1 not taken
     255                1:         if (insertion_file == file)
     256                1:           fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
     257                 :                   clang_getCString(text), insertion_line, insertion_column);
     258                1:         clang_disposeString(text);
     259                1:         break;
     260                 :       }
     261                 : 
     262                 :       case CXFixIt_Removal: {
     263                 :         CXFile start_file, end_file;
     264                 :         unsigned start_line, start_column, end_line, end_column;
     265                 :         CXSourceRange remove_range
     266                1:           = clang_getDiagnosticFixItRemoval(Diagnostic, i);
     267                1:         clang_getInstantiationLocation(clang_getRangeStart(remove_range),
     268                 :                                        &start_file, &start_line, &start_column,
     269                 :                                        0);
     270                1:         clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
     271                 :                                        &end_file, &end_line, &end_column, 0);
                        1: branch 0 taken
                        0: branch 1 not taken
                        1: branch 2 taken
                        0: branch 3 not taken
     272                1:         if (start_file == file && end_file == file)
     273                1:           fprintf(out, "FIX-IT: Remove %d:%d-%d:%d\n",
     274                 :                   start_line, start_column, end_line, end_column+1);
     275                1:         break;
     276                 :       }
     277                 :           
     278                 :       case CXFixIt_Replacement: {
     279                 :         CXFile start_file, end_file;
     280                 :         unsigned start_line, start_column, end_line, end_column;
     281                 :         CXSourceRange remove_range;
     282                1:         text = clang_getDiagnosticFixItReplacement(Diagnostic, i,&remove_range);
     283                1:         clang_getInstantiationLocation(clang_getRangeStart(remove_range),
     284                 :                                        &start_file, &start_line, &start_column,
     285                 :                                        0);
     286                1:         clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
     287                 :                                        &end_file, &end_line, &end_column, 0);
                        1: branch 0 taken
                        0: branch 1 not taken
     288                1:         if (start_file == end_file)
     289                1:           fprintf(out, "FIX-IT: Replace %d:%d-%d:%d with \"%s\"\n",
     290                 :                   start_line, start_column, end_line, end_column+1,
     291                 :                   clang_getCString(text));
     292                1:         clang_disposeString(text);
     293                 :         break;
     294                 :       }
     295                 :       }
     296                 :     }
     297                 :   }
     298                 : }
     299                 : 
     300                 : /******************************************************************************/
     301                 : /* Logic for testing traversal.                                               */
     302                 : /******************************************************************************/
     303                 : 
     304                 : static const char *FileCheckPrefix = "CHECK";
     305                 : 
     306              237: static void PrintCursorExtent(CXCursor C) {
     307              237:   CXSourceRange extent = clang_getCursorExtent(C);
     308                 :   CXFile begin_file, end_file;
     309                 :   unsigned begin_line, begin_column, end_line, end_column;
     310                 :   
     311              237:   clang_getInstantiationLocation(clang_getRangeStart(extent),
     312                 :                                  &begin_file, &begin_line, &begin_column, 0);
     313              237:   clang_getInstantiationLocation(clang_getRangeEnd(extent),
     314                 :                                  &end_file, &end_line, &end_column, 0);
                      184: branch 0 taken
                       53: branch 1 taken
                        0: branch 2 not taken
                      184: branch 3 taken
     315              237:   if (!begin_file || !end_file)
     316               53:     return;
     317                 : 
     318              184:   printf(" [Extent=%d:%d:%d:%d]", begin_line, begin_column,
     319                 :          end_line, end_column);
     320                 : }
     321                 : 
     322                 : /* Data used by all of the visitors. */
     323                 : typedef struct  {
     324                 :   CXTranslationUnit TU;
     325                 :   enum CXCursorKind *Filter;
     326                 : } VisitorData;
     327                 : 
     328                 : 
     329                 : enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor, 
     330                 :                                                 CXCursor Parent,
     331              237:                                                 CXClientData ClientData) {
     332              237:   VisitorData *Data = (VisitorData *)ClientData;
                        0: branch 0 not taken
                      237: branch 1 taken
                      237: branch 2 taken
                      237: branch 3 taken
     333              237:   if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
     334              237:     CXSourceLocation Loc = clang_getCursorLocation(Cursor);
     335                 :     unsigned line, column;
     336              237:     clang_getInstantiationLocation(Loc, 0, &line, &column, 0);
     337              237:     printf("// %s: %s:%d:%d: ", FileCheckPrefix,
     338                 :            GetCursorSource(Cursor), line, column);
     339              237:     PrintCursor(Cursor);
     340              237:     PrintCursorExtent(Cursor);
     341              237:     printf("\n");    
     342              237:     return CXChildVisit_Recurse;
     343                 :   }
     344                 :   
     345                0:   return CXChildVisit_Continue;
     346                 : }
     347                 : 
     348                 : static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor, 
     349                 :                                                    CXCursor Parent,
     350                0:                                                    CXClientData ClientData) {
     351                 :   const char *startBuf, *endBuf;
     352                 :   unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn;
     353                 :   CXCursor Ref;
     354                0:   VisitorData *Data = (VisitorData *)ClientData;
     355                 : 
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     356                0:   if (Cursor.kind != CXCursor_FunctionDecl ||
     357                 :       !clang_isCursorDefinition(Cursor))
     358                0:     return CXChildVisit_Continue;
     359                 : 
     360                0:   clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,
     361                 :                                        &startLine, &startColumn,
     362                 :                                        &endLine, &endColumn);
     363                 :   /* Probe the entire body, looking for both decls and refs. */
     364                0:   curLine = startLine;
     365                0:   curColumn = startColumn;
     366                 : 
                        0: branch 0 not taken
                        0: branch 1 not taken
     367                0:   while (startBuf < endBuf) {
     368                 :     CXSourceLocation Loc;
     369                 :     CXFile file;
     370                0:     const char *source = 0;
     371                 :     
                        0: branch 0 not taken
                        0: branch 1 not taken
     372                0:     if (*startBuf == '\n') {
     373                0:       startBuf++;
     374                0:       curLine++;
     375                0:       curColumn = 1;
                        0: branch 0 not taken
                        0: branch 1 not taken
     376                0:     } else if (*startBuf != '\t')
     377                0:       curColumn++;
     378                 :           
     379                0:     Loc = clang_getCursorLocation(Cursor);
     380                0:     clang_getInstantiationLocation(Loc, &file, 0, 0, 0);
     381                0:     source = clang_getFileName(file);
                        0: branch 0 not taken
                        0: branch 1 not taken
     382                0:     if (source) {
     383                 :       CXSourceLocation RefLoc
     384                0:         = clang_getLocation(Data->TU, file, curLine, curColumn);
     385                0:       Ref = clang_getCursor(Data->TU, RefLoc);
                        0: branch 0 not taken
                        0: branch 1 not taken
     386                0:       if (Ref.kind == CXCursor_NoDeclFound) {
     387                 :         /* Nothing found here; that's fine. */
                        0: branch 0 not taken
                        0: branch 1 not taken
     388                0:       } else if (Ref.kind != CXCursor_FunctionDecl) {
     389                0:         printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
     390                 :                curLine, curColumn);
     391                0:         PrintCursor(Ref);
     392                0:         printf("\n");
     393                 :       }
     394                 :     }
     395                0:     startBuf++;
     396                 :   }
     397                 :   
     398                0:   return CXChildVisit_Continue;
     399                 : }
     400                 : 
     401                 : /******************************************************************************/
     402                 : /* USR testing.                                                               */
     403                 : /******************************************************************************/
     404                 : 
     405                 : enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
     406                0:                                    CXClientData ClientData) {
     407                0:   VisitorData *Data = (VisitorData *)ClientData;
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
     408                0:   if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
     409                0:     CXString USR = clang_getCursorUSR(C);
                        0: branch 0 not taken
                        0: branch 1 not taken
     410                0:     if (!USR.Spelling) {
     411                0:       clang_disposeString(USR);
     412                0:       return CXChildVisit_Continue;
     413                 :     }
     414                0:     printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), USR.Spelling);
     415                0:     PrintCursorExtent(C);
     416                0:     printf("\n");
     417                0:     clang_disposeString(USR);
     418                 :     
     419                0:     return CXChildVisit_Recurse;
     420                 :   }  
     421                 :   
     422                0:   return CXChildVisit_Continue;
     423                 : }
     424                 : 
     425                 : /******************************************************************************/
     426                 : /* Inclusion stack testing.                                                   */
     427                 : /******************************************************************************/
     428                 : 
     429                 : void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack,
     430                3:                       unsigned includeStackLen, CXClientData data) {
     431                 :   
     432                 :   unsigned i;
     433                3:   printf("file: %s\nincluded by:\n", clang_getFileName(includedFile));
                        3: branch 0 taken
                        3: branch 1 taken
     434                6:   for (i = 0; i < includeStackLen; ++i) {
     435                 :     CXFile includingFile;
     436                 :     unsigned line, column;
     437                3:     clang_getInstantiationLocation(includeStack[i], &includingFile, &line,
     438                 :                                    &column, 0);
     439                3:     printf("  %s:%d:%d\n", clang_getFileName(includingFile), line, column);
     440                 :   }
     441                3:   printf("\n");
     442                3: }
     443                 : 
     444                1: void PrintInclusionStack(CXTranslationUnit TU) {
     445                1:   clang_getInclusions(TU, InclusionVisitor, NULL);  
     446                1: }
     447                 : 
     448                 : /******************************************************************************/
     449                 : /* Loading ASTs/source.                                                       */
     450                 : /******************************************************************************/
     451                 : 
     452                 : static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
     453                 :                              const char *filter, const char *prefix,
     454                 :                              CXCursorVisitor Visitor,
     455               11:                              PostVisitTU PV) {
     456                 :   
                        0: branch 0 not taken
                       11: branch 1 taken
     457               11:   if (prefix)
     458                0:     FileCheckPrefix = prefix;  
     459                 : 
                       10: branch 0 taken
                        1: branch 1 taken
     460               11:   if (Visitor) {
     461               10:     enum CXCursorKind K = CXCursor_NotImplemented;
     462               10:     enum CXCursorKind *ck = &K;
     463                 :     VisitorData Data;
     464                 :   
     465                 :     /* Perform some simple filtering. */
                        4: branch 1 taken
                        6: branch 2 taken
                        4: branch 4 taken
                        0: branch 5 not taken
     466               10:     if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
                        0: branch 1 not taken
                        0: branch 2 not taken
     467                0:     else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
                        0: branch 1 not taken
                        0: branch 2 not taken
     468                0:     else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
                        0: branch 1 not taken
                        0: branch 2 not taken
     469                0:     else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
                        0: branch 1 not taken
                        0: branch 2 not taken
     470                0:     else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
                        0: branch 1 not taken
                        0: branch 2 not taken
     471                0:     else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
                        0: branch 1 not taken
                        0: branch 2 not taken
     472                0:     else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor;
     473                 :     else {
     474                0:       fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
     475                0:       return 1;
     476                 :     }
     477                 :   
     478               10:     Data.TU = TU;
     479               10:     Data.Filter = ck;
     480               10:     clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data);
     481                 :   }
     482                 :   
                        1: branch 0 taken
                       10: branch 1 taken
     483               11:   if (PV)
     484                1:     PV(TU);
     485                 : 
     486               11:   clang_disposeTranslationUnit(TU);
     487               11:   return 0;
     488                 : }
     489                 : 
     490                 : int perform_test_load_tu(const char *file, const char *filter,
     491                 :                          const char *prefix, CXCursorVisitor Visitor,
     492                5:                          PostVisitTU PV) {
     493                 :   CXIndex Idx;
     494                 :   CXTranslationUnit TU;
     495                5:   Idx = clang_createIndex(/* excludeDeclsFromPCH */ 
     496                 :                           !strcmp(filter, "local") ? 1 : 0);
     497                 :   
                        0: branch 1 not taken
                        5: branch 2 taken
     498                5:   if (!CreateTranslationUnit(Idx, file, &TU))
     499                0:     return 1;
     500                 : 
     501                5:   return perform_test_load(Idx, TU, filter, prefix, Visitor, PV);
     502                 : }
     503                 : 
     504                 : int perform_test_load_source(int argc, const char **argv,
     505                 :                              const char *filter, CXCursorVisitor Visitor,
     506                7:                              PostVisitTU PV) {
     507                 :   const char *UseExternalASTs =
     508                7:     getenv("CINDEXTEST_USE_EXTERNAL_AST_GENERATION");
     509                 :   CXIndex Idx;
     510                 :   CXTranslationUnit TU;
     511                7:   struct CXUnsavedFile *unsaved_files = 0;
     512                7:   int num_unsaved_files = 0;
     513                 :   int result;
     514                 :   
     515                7:   Idx = clang_createIndex(/* excludeDeclsFromPCH */
     516                 :                           !strcmp(filter, "local") ? 1 : 0);
     517                 : 
                        1: branch 0 taken
                        6: branch 1 taken
                        1: branch 2 taken
                        0: branch 3 not taken
     518                7:   if (UseExternalASTs && strlen(UseExternalASTs))
     519                1:     clang_setUseExternalASTGeneration(Idx, 1);
     520                 : 
                        0: branch 1 not taken
                        7: branch 2 taken
     521                7:   if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files))
     522                0:     return -1;
     523                 : 
     524                7:   TU = clang_createTranslationUnitFromSourceFile(Idx, 0, 
     525                 :                                                  argc - num_unsaved_files, 
     526                 :                                                  argv + num_unsaved_files,
     527                 :                                                  num_unsaved_files,
     528                 :                                                  unsaved_files,
     529                 :                                                  PrintDiagnosticCallback,
     530                 :                                                  stderr);
                        1: branch 0 taken
                        6: branch 1 taken
     531                7:   if (!TU) {
     532                1:     fprintf(stderr, "Unable to load translation unit!\n");
     533                1:     return 1;
     534                 :   }
     535                 : 
     536                6:   result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV);
     537                6:   free_remapped_files(unsaved_files, num_unsaved_files);
     538                6:   return result;
     539                 : }
     540                 : 
     541                 : /******************************************************************************/
     542                 : /* Logic for testing clang_getCursor().                                       */
     543                 : /******************************************************************************/
     544                 : 
     545                 : static void print_cursor_file_scan(CXCursor cursor,
     546                 :                                    unsigned start_line, unsigned start_col,
     547                 :                                    unsigned end_line, unsigned end_col,
     548              122:                                    const char *prefix) {
     549              122:   printf("// %s: ", FileCheckPrefix);
                        0: branch 0 not taken
                      122: branch 1 taken
     550              122:   if (prefix)
     551                0:     printf("-%s", prefix);
     552              122:   printf("{start_line=%d start_col=%d end_line=%d end_col=%d} ",
     553                 :           start_line, start_col, end_line, end_col);
     554              122:   PrintCursor(cursor);
     555              122:   printf("\n");
     556              122: }
     557                 : 
     558                 : static int perform_file_scan(const char *ast_file, const char *source_file,
     559                3:                              const char *prefix) {
     560                 :   CXIndex Idx;
     561                 :   CXTranslationUnit TU;
     562                 :   FILE *fp;
     563                 :   unsigned line;
     564                 :   CXCursor prevCursor;
     565                 :   CXFile file;
     566                 :   unsigned printed;
     567                 :   unsigned start_line, start_col, last_line, last_col;
     568                 :   size_t i;
     569                 :   
                        0: branch 1 not taken
                        3: branch 2 taken
     570                3:   if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1))) {
     571                0:     fprintf(stderr, "Could not create Index\n");
     572                0:     return 1;
     573                 :   }
     574                 :   
                        0: branch 1 not taken
                        3: branch 2 taken
     575                3:   if (!CreateTranslationUnit(Idx, ast_file, &TU))
     576                0:     return 1;
     577                 :   
                        0: branch 1 not taken
                        3: branch 2 taken
     578                3:   if ((fp = fopen(source_file, "r")) == NULL) {
     579                0:     fprintf(stderr, "Could not open '%s'\n", source_file);
     580                0:     return 1;
     581                 :   }
     582                 :   
     583                3:   line = 0;
     584                3:   prevCursor = clang_getNullCursor();
     585                3:   printed = 0;
     586                3:   start_line = last_line = 1;
     587                3:   start_col = last_col = 1;
     588                 :   
     589                3:   file = clang_getFile(TU, source_file);
                      230: branch 1 taken
                        3: branch 2 taken
     590              236:   while (!feof(fp)) {
     591              230:     size_t len = 0;
     592                 :     int c;
     593                 : 
                    12821: branch 1 taken
                        3: branch 2 taken
     594            13054:     while ((c = fgetc(fp)) != EOF) {
     595            12821:       len++;
                      227: branch 0 taken
                    12594: branch 1 taken
     596            12821:       if (c == '\n')
     597              227:         break;
     598                 :     }
     599                 : 
     600              230:     ++line;
     601                 :     
                    12821: branch 0 taken
                      230: branch 1 taken
     602            13051:     for (i = 0; i < len ; ++i) {
     603                 :       CXCursor cursor;
     604            12821:       cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, i+1));
     605                 : 
                      122: branch 1 taken
                    12699: branch 2 taken
                      119: branch 3 taken
                        3: branch 4 taken
     606            12940:       if (!clang_equalCursors(cursor, prevCursor) &&
     607                 :           prevCursor.kind != CXCursor_InvalidFile) {
     608              119:         print_cursor_file_scan(prevCursor, start_line, start_col,
     609                 :                                last_line, last_col, prefix);
     610              119:         printed = 1;
     611              119:         start_line = line;
     612              119:         start_col = (unsigned) i+1;
     613                 :       }
     614                 :       else {
     615            12702:         printed = 0;
     616                 :       }
     617                 :       
     618            12821:       prevCursor = cursor;
     619            12821:       last_line = line;
     620            12821:       last_col = (unsigned) i+1;
     621                 :     }    
     622                 :   }
     623                 :   
                        3: branch 0 taken
                        0: branch 1 not taken
                        3: branch 2 taken
                        0: branch 3 not taken
     624                3:   if (!printed && prevCursor.kind != CXCursor_InvalidFile) {
     625                3:     print_cursor_file_scan(prevCursor, start_line, start_col,
     626                 :                            last_line, last_col, prefix);
     627                 :   }  
     628                 :   
     629                3:   fclose(fp);
     630                3:   return 0;
     631                 : }
     632                 : 
     633                 : /******************************************************************************/
     634                 : /* Logic for testing clang_codeComplete().                                    */
     635                 : /******************************************************************************/
     636                 : 
     637                 : /* Parse file:line:column from the input string. Returns 0 on success, non-zero
     638                 :    on failure. If successful, the pointer *filename will contain newly-allocated
     639                 :    memory (that will be owned by the caller) to store the file name. */
     640                 : int parse_file_line_column(const char *input, char **filename, unsigned *line, 
     641                 :                            unsigned *column, unsigned *second_line,
     642               56:                            unsigned *second_column) {
     643                 :   /* Find the second colon. */
     644               56:   const char *last_colon = strrchr(input, ':');
     645                 :   unsigned values[4], i;
                        1: branch 0 taken
                       55: branch 1 taken
                        1: branch 2 taken
                        0: branch 3 not taken
     646               56:   unsigned num_values = (second_line && second_column)? 4 : 2;
     647                 : 
     648               56:   char *endptr = 0;
                       56: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                       56: branch 3 taken
     649               56:   if (!last_colon || last_colon == input) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     650                0:     if (num_values == 4)
     651                0:       fprintf(stderr, "could not parse filename:line:column:line:column in "
     652                 :               "'%s'\n", input);
     653                 :     else
     654                0:       fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
     655                0:     return 1;
     656                 :   }
     657                 : 
                      114: branch 0 taken
                        0: branch 1 not taken
     658              114:   for (i = 0; i != num_values; ++i) {
     659                 :     const char *prev_colon;
     660                 : 
     661                 :     /* Parse the next line or column. */
     662              114:     values[num_values - i - 1] = strtol(last_colon + 1, &endptr, 10);
                       58: branch 0 taken
                       56: branch 1 taken
                        0: branch 2 not taken
                       58: branch 3 taken
     663              114:     if (*endptr != 0 && *endptr != ':') {
                        0: branch 0 not taken
                        0: branch 1 not taken
     664                0:       fprintf(stderr, "could not parse %s in '%s'\n", 
     665                 :               (i % 2 ? "column" : "line"), input);
     666                0:       return 1;
     667                 :     }
     668                 :     
                       56: branch 0 taken
                       58: branch 1 taken
     669              114:     if (i + 1 == num_values)
     670               56:       break;
     671                 : 
     672                 :     /* Find the previous colon. */
     673               58:     prev_colon = last_colon - 1;
                      151: branch 0 taken
                        0: branch 1 not taken
                       93: branch 2 taken
                       58: branch 3 taken
     674              209:     while (prev_colon != input && *prev_colon != ':')
     675               93:       --prev_colon;
                        0: branch 0 not taken
                       58: branch 1 taken
     676               58:     if (prev_colon == input) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     677                0:       fprintf(stderr, "could not parse %s in '%s'\n", 
     678                 :               (i % 2 == 0? "column" : "line"), input);
     679                0:       return 1;    
     680                 :     }
     681                 : 
     682               58:     last_colon = prev_colon;
     683                 :   }
     684                 : 
     685               56:   *line = values[0];
     686               56:   *column = values[1];
     687                 :   
                        1: branch 0 taken
                       55: branch 1 taken
                        1: branch 2 taken
                        0: branch 3 not taken
     688               56:   if (second_line && second_column) {
     689                1:     *second_line = values[2];
     690                1:     *second_column = values[3];
     691                 :   }
     692                 : 
     693                 :   /* Copy the file name. */
     694               56:   *filename = (char*)malloc(last_colon - input + 1);
     695               56:   memcpy(*filename, input, last_colon - input);
     696               56:   (*filename)[last_colon - input] = 0;
     697               56:   return 0;
     698                 : }
     699                 : 
     700                 : const char *
     701             2262: clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
                        0: branch 0 not taken
                     1728: branch 1 taken
                       42: branch 2 taken
                      136: branch 3 taken
                       20: branch 4 taken
                        3: branch 5 taken
                       57: branch 6 taken
                       57: branch 7 taken
                        0: branch 8 not taken
                        0: branch 9 not taken
                       23: branch 10 taken
                       23: branch 11 taken
                        0: branch 12 not taken
                        0: branch 13 not taken
                        4: branch 14 taken
                       90: branch 15 taken
                        0: branch 16 not taken
                       22: branch 17 taken
                        0: branch 18 not taken
                       42: branch 19 taken
                       15: branch 20 taken
                        0: branch 21 not taken
     702             2262:   switch (Kind) {
     703                0:   case CXCompletionChunk_Optional: return "Optional";
     704             1728:   case CXCompletionChunk_TypedText: return "TypedText";
     705               42:   case CXCompletionChunk_Text: return "Text";
     706              136:   case CXCompletionChunk_Placeholder: return "Placeholder";
     707               20:   case CXCompletionChunk_Informative: return "Informative";
     708                3:   case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
     709               57:   case CXCompletionChunk_LeftParen: return "LeftParen";
     710               57:   case CXCompletionChunk_RightParen: return "RightParen";
     711                0:   case CXCompletionChunk_LeftBracket: return "LeftBracket";
     712                0:   case CXCompletionChunk_RightBracket: return "RightBracket";
     713               23:   case CXCompletionChunk_LeftBrace: return "LeftBrace";
     714               23:   case CXCompletionChunk_RightBrace: return "RightBrace";
     715                0:   case CXCompletionChunk_LeftAngle: return "LeftAngle";
     716                0:   case CXCompletionChunk_RightAngle: return "RightAngle";
     717                4:   case CXCompletionChunk_Comma: return "Comma";
     718               90:   case CXCompletionChunk_ResultType: return "ResultType";
     719                0:   case CXCompletionChunk_Colon: return "Colon";
     720               22:   case CXCompletionChunk_SemiColon: return "SemiColon";
     721                0:   case CXCompletionChunk_Equal: return "Equal";
     722               42:   case CXCompletionChunk_HorizontalSpace: return "HorizontalSpace";
     723               15:   case CXCompletionChunk_VerticalSpace: return "VerticalSpace";
     724                 :   }
     725                 :   
     726                0:   return "Unknown";
     727                 : }
     728                 : 
     729             1732: void print_completion_string(CXCompletionString completion_string, FILE *file) {
     730                 :   int I, N;
     731                 :   
     732             1732:   N = clang_getNumCompletionChunks(completion_string);
                     2263: branch 0 taken
                     1732: branch 1 taken
     733             3995:   for (I = 0; I != N; ++I) {
     734             2263:     const char *text = 0;
     735                 :     enum CXCompletionChunkKind Kind
     736             2263:       = clang_getCompletionChunkKind(completion_string, I);
     737                 :     
                        1: branch 0 taken
                     2262: branch 1 taken
     738             2263:     if (Kind == CXCompletionChunk_Optional) {
     739                1:       fprintf(file, "{Optional ");
     740                1:       print_completion_string(
     741                 :                 clang_getCompletionChunkCompletionString(completion_string, I), 
     742                 :                               file);
     743                1:       fprintf(file, "}");
     744                1:       continue;
     745                 :     }
     746                 :     
     747             2262:     text = clang_getCompletionChunkText(completion_string, I);
                     2262: branch 0 taken
                        0: branch 1 not taken
     748             2262:     fprintf(file, "{%s %s}", 
     749                 :             clang_getCompletionChunkKindSpelling(Kind),
     750                 :             text? text : "");
     751                 :   }
     752             1732: }
     753                 : 
     754                 : void print_completion_result(CXCompletionResult *completion_result,
     755             1731:                              CXClientData client_data) {
     756             1731:   FILE *file = (FILE *)client_data;
     757             1731:   fprintf(file, "%s:", 
     758                 :           clang_getCursorKindSpelling(completion_result->CursorKind));
     759             1731:   print_completion_string(completion_result->CompletionString, file);
     760             1731:   fprintf(file, "\n");
     761             1731: }
     762                 : 
     763               51: int perform_code_completion(int argc, const char **argv) {
     764               51:   const char *input = argv[1];
     765               51:   char *filename = 0;
     766                 :   unsigned line;
     767                 :   unsigned column;
     768                 :   CXIndex CIdx;
     769                 :   int errorCode;
     770               51:   struct CXUnsavedFile *unsaved_files = 0;
     771               51:   int num_unsaved_files = 0;
     772               51:   CXCodeCompleteResults *results = 0;
     773                 : 
     774               51:   input += strlen("-code-completion-at=");
                        0: branch 1 not taken
                       51: branch 2 taken
     775               51:   if ((errorCode = parse_file_line_column(input, &filename, &line, &column, 
     776                 :                                           0, 0)))
     777                0:     return errorCode;
     778                 : 
                        0: branch 1 not taken
                       51: branch 2 taken
     779               51:   if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
     780                0:     return -1;
     781                 : 
     782               51:   CIdx = clang_createIndex(0);
     783               51:   results = clang_codeComplete(CIdx, 
     784                 :                                argv[argc - 1], argc - num_unsaved_files - 3, 
     785                 :                                argv + num_unsaved_files + 2, 
     786                 :                                num_unsaved_files, unsaved_files,
     787                 :                                filename, line, column,
     788                 :                                PrintDiagnosticCallback, stderr);
     789                 : 
                       51: branch 0 taken
                        0: branch 1 not taken
     790               51:   if (results) {
     791               51:     unsigned i, n = results->NumResults;
                     1731: branch 0 taken
                       51: branch 1 taken
     792             1782:     for (i = 0; i != n; ++i)
     793             1731:       print_completion_result(results->Results + i, stdout);
     794               51:     clang_disposeCodeCompleteResults(results);
     795                 :   }
     796                 : 
     797               51:   clang_disposeIndex(CIdx);
     798               51:   free(filename);
     799                 :   
     800               51:   free_remapped_files(unsaved_files, num_unsaved_files);
     801                 : 
     802               51:   return 0;
     803                 : }
     804                 : 
     805                 : typedef struct {
     806                 :   char *filename;
     807                 :   unsigned line;
     808                 :   unsigned column;
     809                 : } CursorSourceLocation;
     810                 : 
     811                2: int inspect_cursor_at(int argc, const char **argv) {
     812                 :   CXIndex CIdx;
     813                 :   int errorCode;
     814                2:   struct CXUnsavedFile *unsaved_files = 0;
     815                2:   int num_unsaved_files = 0;
     816                 :   CXTranslationUnit TU;
     817                 :   CXCursor Cursor;
     818                2:   CursorSourceLocation *Locations = 0;
     819                2:   unsigned NumLocations = 0, Loc;
     820                 : 
     821                 :   /* Count the number of locations. */ 
                        4: branch 1 taken
                        2: branch 2 taken
     822                8:   while (strstr(argv[NumLocations+1], "-cursor-at=") == argv[NumLocations+1])
     823                4:     ++NumLocations;
     824                 :   
     825                 :   /* Parse the locations. */
                        0: branch 0 not taken
                        2: branch 1 taken
     826                2:   assert(NumLocations > 0 && "Unable to count locations?");
     827                2:   Locations = (CursorSourceLocation *)malloc(
     828                 :                                   NumLocations * sizeof(CursorSourceLocation));
                        4: branch 0 taken
                        2: branch 1 taken
     829                6:   for (Loc = 0; Loc < NumLocations; ++Loc) {
     830                4:     const char *input = argv[Loc + 1] + strlen("-cursor-at=");
                        0: branch 1 not taken
                        4: branch 2 taken
     831                4:     if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename, 
     832                 :                                             &Locations[Loc].line, 
     833                 :                                             &Locations[Loc].column, 0, 0)))
     834                0:       return errorCode;
     835                 :   }
     836                 :   
                        0: branch 1 not taken
                        2: branch 2 taken
     837                2:   if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files, 
     838                 :                            &num_unsaved_files))
     839                0:     return -1;
     840                 :   
     841                2:   CIdx = clang_createIndex(0);
     842                2:   TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1],
     843                 :                                   argc - num_unsaved_files - 2 - NumLocations,
     844                 :                                    argv + num_unsaved_files + 1 + NumLocations,
     845                 :                                                  num_unsaved_files,
     846                 :                                                  unsaved_files,
     847                 :                                                  PrintDiagnosticCallback,
     848                 :                                                  stderr);
                        0: branch 0 not taken
                        2: branch 1 taken
     849                2:   if (!TU) {
     850                0:     fprintf(stderr, "unable to parse input\n");
     851                0:     return -1;
     852                 :   }
     853                 :   
                        4: branch 0 taken
                        2: branch 1 taken
     854                6:   for (Loc = 0; Loc < NumLocations; ++Loc) {
     855                4:     CXFile file = clang_getFile(TU, Locations[Loc].filename);
                        0: branch 0 not taken
                        4: branch 1 taken
     856                4:     if (!file)
     857                0:       continue;
     858                 :     
     859                4:     Cursor = clang_getCursor(TU, 
     860                 :                              clang_getLocation(TU, file, Locations[Loc].line, 
     861                 :                                                Locations[Loc].column)); 
     862                4:     PrintCursor(Cursor);
     863                4:     printf("\n");
     864                4:     free(Locations[Loc].filename);
     865                 :   }
     866                 :   
     867                2:   clang_disposeTranslationUnit(TU);
     868                2:   clang_disposeIndex(CIdx);
     869                2:   free(Locations);
     870                2:   free_remapped_files(unsaved_files, num_unsaved_files);
     871                2:   return 0;
     872                 : }
     873                 : 
     874                1: int perform_token_annotation(int argc, const char **argv) {
     875                1:   const char *input = argv[1];
     876                1:   char *filename = 0;
     877                 :   unsigned line, second_line;
     878                 :   unsigned column, second_column;
     879                 :   CXIndex CIdx;
     880                1:   CXTranslationUnit TU = 0;
     881                 :   int errorCode;
     882                1:   struct CXUnsavedFile *unsaved_files = 0;
     883                1:   int num_unsaved_files = 0;
     884                 :   CXToken *tokens;
     885                 :   unsigned num_tokens;
     886                 :   CXSourceRange range;
     887                 :   CXSourceLocation startLoc, endLoc;
     888                1:   CXFile file = 0;
     889                1:   CXCursor *cursors = 0;
     890                 :   unsigned i;
     891                 : 
     892                1:   input += strlen("-test-annotate-tokens=");
                        0: branch 1 not taken
                        1: branch 2 taken
     893                1:   if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
     894                 :                                           &second_line, &second_column)))
     895                0:     return errorCode;
     896                 : 
                        0: branch 1 not taken
                        1: branch 2 taken
     897                1:   if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
     898                0:     return -1;
     899                 : 
     900                1:   CIdx = clang_createIndex(0);
     901                1:   TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1],
     902                 :                                                  argc - num_unsaved_files - 3,
     903                 :                                                  argv + num_unsaved_files + 2,
     904                 :                                                  num_unsaved_files,
     905                 :                                                  unsaved_files,
     906                 :                                                  PrintDiagnosticCallback,
     907                 :                                                  stderr);
                        0: branch 0 not taken
                        1: branch 1 taken
     908                1:   if (!TU) {
     909                0:     fprintf(stderr, "unable to parse input\n");
     910                0:     clang_disposeIndex(CIdx);
     911                0:     free(filename);
     912                0:     free_remapped_files(unsaved_files, num_unsaved_files);
     913                0:     return -1;
     914                 :   }  
     915                1:   errorCode = 0;
     916                 : 
     917                1:   file = clang_getFile(TU, filename);
                        0: branch 0 not taken
                        1: branch 1 taken
     918                1:   if (!file) {
     919                0:     fprintf(stderr, "file %s is not in this translation unit\n", filename);
     920                0:     errorCode = -1;
     921                0:     goto teardown;
     922                 :   }
     923                 : 
     924                1:   startLoc = clang_getLocation(TU, file, line, column);
                        0: branch 2 not taken
                        1: branch 3 taken
     925                1:   if (clang_equalLocations(clang_getNullLocation(), startLoc)) {
     926                0:     fprintf(stderr, "invalid source location %s:%d:%d\n", filename, line, 
     927                 :             column);
     928                0:     errorCode = -1;
     929                0:     goto teardown;    
     930                 :   }
     931                 : 
     932                1:   endLoc = clang_getLocation(TU, file, second_line, second_column);
                        0: branch 2 not taken
                        1: branch 3 taken
     933                1:   if (clang_equalLocations(clang_getNullLocation(), endLoc)) {
     934                0:     fprintf(stderr, "invalid source location %s:%d:%d\n", filename, 
     935                 :             second_line, second_column);
     936                0:     errorCode = -1;
     937                0:     goto teardown;    
     938                 :   }
     939                 : 
     940                1:   range = clang_getRange(startLoc, endLoc);
     941                1:   clang_tokenize(TU, range, &tokens, &num_tokens);
     942                1:   cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor));
     943                1:   clang_annotateTokens(TU, tokens, num_tokens, cursors);
                       51: branch 0 taken
                        1: branch 1 taken
     944               52:   for (i = 0; i != num_tokens; ++i) {
     945               51:     const char *kind = "<unknown>";
     946               51:     CXString spelling = clang_getTokenSpelling(TU, tokens[i]);
     947               51:     CXSourceRange extent = clang_getTokenExtent(TU, tokens[i]);
     948                 :     unsigned start_line, start_column, end_line, end_column;
     949                 : 
                       28: branch 1 taken
                        7: branch 2 taken
                       12: branch 3 taken
                        3: branch 4 taken
                        1: branch 5 taken
                        0: branch 6 not taken
     950               51:     switch (clang_getTokenKind(tokens[i])) {
     951               28:     case CXToken_Punctuation: kind = "Punctuation"; break;
     952                7:     case CXToken_Keyword: kind = "Keyword"; break;
     953               12:     case CXToken_Identifier: kind = "Identifier"; break;
     954                3:     case CXToken_Literal: kind = "Literal"; break;
     955                1:     case CXToken_Comment: kind = "Comment"; break;
     956                 :     }
     957               51:     clang_getInstantiationLocation(clang_getRangeStart(extent), 
     958                 :                                    0, &start_line, &start_column, 0);
     959               51:     clang_getInstantiationLocation(clang_getRangeEnd(extent),
     960                 :                                    0, &end_line, &end_column, 0);
     961               51:     printf("%s: \"%s\" [%d:%d - %d:%d]", kind, clang_getCString(spelling),
     962                 :            start_line, start_column, end_line, end_column);
                       12: branch 1 taken
                       39: branch 2 taken
     963               51:     if (!clang_isInvalid(cursors[i].kind)) {
     964               12:       printf(" ");
     965               12:       PrintCursor(cursors[i]);
     966                 :     }
     967               51:     printf("\n");
     968                 :   }
     969                1:   free(cursors);
     970                 : 
     971                1:  teardown:
     972                1:   clang_disposeTranslationUnit(TU);
     973                1:   clang_disposeIndex(CIdx);
     974                1:   free(filename);
     975                1:   free_remapped_files(unsaved_files, num_unsaved_files);
     976                1:   return errorCode;
     977                 : }
     978                 : 
     979                 : /******************************************************************************/
     980                 : /* Command line processing.                                                   */
     981                 : /******************************************************************************/
     982                 : 
     983               11: static CXCursorVisitor GetVisitor(const char *s) {
                       11: branch 0 taken
                        0: branch 1 not taken
     984               11:   if (s[0] == '\0')
     985               11:     return FilteredPrintingVisitor;
                        0: branch 1 not taken
                        0: branch 2 not taken
     986                0:   if (strcmp(s, "-usrs") == 0)
     987                0:     return USRVisitor;
     988                0:   return NULL;
     989                 : }
     990                 : 
     991                0: static void print_usage(void) {
     992                0:   fprintf(stderr,
     993                 :     "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
     994                 :     "       c-index-test -cursor-at=<site> <compiler arguments>\n"
     995                 :     "       c-index-test -test-file-scan <AST file> <source file> "
     996                 :           "[FileCheck prefix]\n"
     997                 :     "       c-index-test -test-load-tu <AST file> <symbol filter> "
     998                 :           "[FileCheck prefix]\n"
     999                 :     "       c-index-test -test-load-tu-usrs <AST file> <symbol filter> "
    1000                 :            "[FileCheck prefix]\n"
    1001                 :     "       c-index-test -test-load-source <symbol filter> {<args>}*\n"
    1002                 :     "       c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n");
    1003                0:   fprintf(stderr,
    1004                 :     "       c-index-test -test-annotate-tokens=<range> {<args>}*\n"
    1005                 :     "       c-index-test -test-inclusion-stack-source {<args>}*\n"
    1006                 :     "       c-index-test -test-inclusion-stack-tu <AST file>\n\n"
    1007                 :     " <symbol filter> values:\n%s",
    1008                 :     "   all - load all symbols, including those from PCH\n"
    1009                 :     "   local - load all symbols except those in PCH\n"
    1010                 :     "   category - only load ObjC categories (non-PCH)\n"
    1011                 :     "   interface - only load ObjC interfaces (non-PCH)\n"
    1012                 :     "   protocol - only load ObjC protocols (non-PCH)\n"
    1013                 :     "   function - only load functions (non-PCH)\n"
    1014                 :     "   typedef - only load typdefs (non-PCH)\n"
    1015                 :     "   scan-function - scan function bodies (non-PCH)\n\n");
    1016                0: }
    1017                 : 
    1018               69: int main(int argc, const char **argv) {
                       69: branch 0 taken
                        0: branch 1 not taken
                       51: branch 3 taken
                       18: branch 4 taken
    1019               69:   if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
    1020               51:     return perform_code_completion(argc, argv);
                       18: branch 0 taken
                        0: branch 1 not taken
                        2: branch 3 taken
                       16: branch 4 taken
    1021               18:   if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
    1022                2:     return inspect_cursor_at(argc, argv);
                       14: branch 0 taken
                        2: branch 1 taken
                        5: branch 3 taken
                        9: branch 4 taken
    1023               16:   else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
    1024                5:     CXCursorVisitor I = GetVisitor(argv[1] + 13);
                        5: branch 0 taken
                        0: branch 1 not taken
    1025                5:     if (I)
                        0: branch 0 not taken
                        5: branch 1 taken
    1026                5:       return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I,
    1027                 :                                   NULL);
    1028                 :   }
                        9: branch 0 taken
                        2: branch 1 taken
                        6: branch 3 taken
                        3: branch 4 taken
    1029               11:   else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
    1030                6:     CXCursorVisitor I = GetVisitor(argv[1] + 17);
                        6: branch 0 taken
                        0: branch 1 not taken
    1031                6:     if (I)
    1032                6:       return perform_test_load_source(argc - 3, argv + 3, argv[2], I, NULL);
    1033                 :   }
                        3: branch 0 taken
                        2: branch 1 taken
                        3: branch 3 taken
                        0: branch 4 not taken
    1034                5:   else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
                        0: branch 0 not taken
                        3: branch 1 taken
    1035                3:     return perform_file_scan(argv[2], argv[3],
    1036                 :                              argc >= 5 ? argv[4] : 0);
                        2: branch 0 taken
                        0: branch 1 not taken
                        1: branch 3 taken
                        1: branch 4 taken
    1037                2:   else if (argc > 2 && strstr(argv[1], "-test-annotate-tokens=") == argv[1])
    1038                1:     return perform_token_annotation(argc, argv);
                        1: branch 0 taken
                        0: branch 1 not taken
                        1: branch 3 taken
                        0: branch 4 not taken
    1039                1:   else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-source") == 0)
    1040                1:     return perform_test_load_source(argc - 2, argv + 2, "all", NULL,
    1041                 :                                     PrintInclusionStack);
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
    1042                0:   else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-tu") == 0)
    1043                0:     return perform_test_load_tu(argv[2], "all", NULL, NULL,
    1044                 :                                 PrintInclusionStack);
    1045                 :     
    1046                0:   print_usage();
    1047                0:   return 1;
    1048                 : }

Generated: 2010-02-10 01:31 by zcov