elsteveogrande updated this revision to Diff 130557.
elsteveogrande added a comment.

remove unneeded changes


Repository:
  rC Clang

https://reviews.llvm.org/D42043

Files:
  include/clang-c/CXString.h
  tools/c-index-test/c-index-test.c
  tools/libclang/CXString.cpp

Index: tools/libclang/CXString.cpp
===================================================================
--- tools/libclang/CXString.cpp
+++ tools/libclang/CXString.cpp
@@ -15,99 +15,130 @@
 
 #include "CXString.h"
 #include "CXTranslationUnit.h"
+#include "clang-c/CXString.h"
 #include "clang-c/Index.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "llvm/Support/ErrorHandling.h"
+#include <cstring>
 
-using namespace clang;
-
-/// Describes the kind of underlying data in CXString.
-enum CXStringFlag {
-  /// CXString contains a 'const char *' that it doesn't own.
-  CXS_Unmanaged,
-
-  /// CXString contains a 'const char *' that it allocated with malloc().
-  CXS_Malloc,
+static_assert(sizeof(CXString) <= 16, "");
 
-  /// CXString contains a CXStringBuf that needs to be returned to the
-  /// CXStringPool.
-  CXS_StringBuf
-};
+using namespace clang;
 
 namespace clang {
 namespace cxstring {
 
+/**
+ * This is for \b CXString 's which are created with \b CreateRef(StringRef).
+ * We'll store the info from the input \b StringRef: char ptr and size.
+ *
+ * We don't know for sure whether this is null-terminated so, when and if
+ * \b clang_getCString is called for this \b CXString, we'll allocate C string
+ * storage and copy data into the storage.  We'll memo-ize that in the
+ * \b CString member.
+ *
+ * This is refcounted; the \b Count member is initially 1.  When a \b CXString
+ * instance using this object is disposed via \b clang_disposeString, \b Count
+ * is decremented.  When this string is duplicated the \b Count increases.
+ *
+ * When \b Count finally drops to zero, the ptr at \b CString, and this object,
+ * should be deleted.
+ */
+struct RefCountedCharRange {
+  const char *Data;
+  const char *CString;
+  unsigned Size;
+  unsigned Count;
+};
+
 //===----------------------------------------------------------------------===//
 // Basic generation of CXStrings.
 //===----------------------------------------------------------------------===//
 
-CXString createEmpty() {
+CXString createRef(const char *String) {
   CXString Str;
-  Str.data = "";
-  Str.private_flags = CXS_Unmanaged;
+  Str.Contents = (const void *) String;
+  if (String) {
+    Str.Size = strlen(String);
+    Str.IsNullTerminated = true;
+  } else {
+    Str.Size = 0;
+    Str.IsNullTerminated = false;
+  }
+  Str.IsOwned = false;
+  Str.IsPooled = false;
   return Str;
 }
 
-CXString createNull() {
-  CXString Str;
-  Str.data = nullptr;
-  Str.private_flags = CXS_Unmanaged;
-  return Str;
+CXString createEmpty() {
+  return createRef("");
 }
 
-CXString createRef(const char *String) {
-  if (String && String[0] == '\0')
-    return createEmpty();
+CXString createNull() {
+  return createRef(nullptr);
+}
 
-  CXString Str;
-  Str.data = String;
-  Str.private_flags = CXS_Unmanaged;
-  return Str;
+inline static const char *copyCharRange(const char *CS, unsigned Size) {
+  char *Spelling = (char *) malloc(Size + 1);
+  assert(Spelling);
+  if (CS) {
+    memcpy(Spelling, CS, Size);
+  }
+  Spelling[Size] = 0;
+  return Spelling;
 }
 
 CXString createDup(const char *String) {
-  if (!String)
+  if (!String) {
     return createNull();
-
-  if (String[0] == '\0')
+  }
+  if (String[0] == '\0') {
     return createEmpty();
+  }
 
   CXString Str;
-  Str.data = strdup(String);
-  Str.private_flags = CXS_Malloc;
+  Str.Size = strlen(String);
+  Str.Contents = (const void *) copyCharRange(String, Str.Size);
+  Str.IsNullTerminated = true;
+  Str.IsOwned = true;
+  Str.IsPooled = false;
   return Str;
 }
 
 CXString createRef(StringRef String) {
-  // If the string is not nul-terminated, we have to make a copy.
-
-  // FIXME: This is doing a one past end read, and should be removed! For memory
-  // we don't manage, the API string can become unterminated at any time outside
-  // our control.
-
-  if (!String.empty() && String.data()[String.size()] != 0)
-    return createDup(String);
-
-  CXString Result;
-  Result.data = String.data();
-  Result.private_flags = (unsigned) CXS_Unmanaged;
-  return Result;
+  assert (String.size() <= std::numeric_limits<unsigned>::max());
+  CXString Str;
+  Str.Size = unsigned(String.size());
+  Str.IsNullTerminated = false;
+  Str.IsOwned = false;
+  Str.IsPooled = false;
+  auto *RC = new RefCountedCharRange {
+    /* Data */ String.data(),
+    /* CString */ nullptr,
+    /* Size */ Str.Size,
+    /* Count */ 1,
+  };
+  Str.Contents = (const void *) RC;
+  return Str;
 }
 
 CXString createDup(StringRef String) {
-  CXString Result;
-  char *Spelling = static_cast<char *>(malloc(String.size() + 1));
-  memmove(Spelling, String.data(), String.size());
-  Spelling[String.size()] = 0;
-  Result.data = Spelling;
-  Result.private_flags = (unsigned) CXS_Malloc;
-  return Result;
+  CXString Str;
+  Str.Size = String.size();
+  Str.Contents = (const void *) copyCharRange(String.data(), Str.Size);
+  Str.IsNullTerminated = true;
+  Str.IsOwned = true;
+  Str.IsPooled = false;
+  return Str;
 }
 
 CXString createCXString(CXStringBuf *buf) {
   CXString Str;
-  Str.data = buf;
-  Str.private_flags = (unsigned) CXS_StringBuf;
+  Str.Contents = buf->Data.data();
+  Str.Size = buf->Data.size();
+  Str.IsNullTerminated = true;
+  Str.IsOwned = false;
+  Str.IsPooled = true;
   return Str;
 }
 
@@ -151,7 +182,7 @@
 }
 
 bool isManagedByPool(CXString str) {
-  return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
+  return str.IsPooled;
 }
 
 } // end namespace cxstring
@@ -161,25 +192,64 @@
 // libClang public APIs.
 //===----------------------------------------------------------------------===//
 
+using namespace clang::cxstring;
+
 const char *clang_getCString(CXString string) {
-  if (string.private_flags == (unsigned) CXS_StringBuf) {
-    return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
+  const char *CString = nullptr;
+
+  // If not null-terminated, then this is a reference to a range of characters
+  // owned elsewhere.  We'll need to copy this to a new C string to ensure it
+  // is null-terminated, if we haven't done so already.
+  if (string.IsNullTerminated) {
+    CString = (const char *) string.Contents;
+  } else {
+    auto *V = const_cast<void *>(string.Contents);
+    if (V) {
+      auto *R = (RefCountedCharRange *) V;
+      if (R) {
+        if (!R->CString) {
+          R->CString = copyCharRange(R->Data, R->Size);
+        }
+        CString = R->CString;
+      }
+    }
   }
-  return static_cast<const char *>(string.data);
+
+  return CString;
+}
+
+const char *clang_getStringData(CXString string) {
+  if (!(string.IsOwned || string.IsNullTerminated)) {
+    auto *R = (const RefCountedCharRange *) string.Contents;
+    return R ? R->Data : nullptr;
+  }
+  return (const char *) string.Contents;
+}
+
+unsigned clang_getStringSize(CXString string) {
+  return string.Size;
 }
 
 void clang_disposeString(CXString string) {
-  switch ((CXStringFlag) string.private_flags) {
-    case CXS_Unmanaged:
-      break;
-    case CXS_Malloc:
-      if (string.data)
-        free(const_cast<void *>(string.data));
-      break;
-    case CXS_StringBuf:
-      static_cast<cxstring::CXStringBuf *>(
-          const_cast<void *>(string.data))->dispose();
-      break;
+  if (string.IsOwned) {
+    // Is a C string that we own; need to free it.
+    const void *Chars = (const void *) string.Contents;
+    free(const_cast<void*>(Chars));
+  } else {
+    if (!string.IsNullTerminated) {
+      // Neither null-terminated nor owned.  Is a char range for which we might
+      // have created a C string.
+      auto *CR = (const RefCountedCharRange *) string.Contents;
+      auto *R = const_cast<RefCountedCharRange *>(CR);
+      if (R) {
+        -- R->Count;
+        if (!R->Count) {
+          const void *CStr = (const void *) R->CString;
+          free(const_cast<void*>(CStr));
+          delete R;
+        }
+      }
+    }
   }
 }
 
@@ -189,4 +259,3 @@
   delete[] set->Strings;
   delete set;
 }
-
Index: tools/c-index-test/c-index-test.c
===================================================================
--- tools/c-index-test/c-index-test.c
+++ tools/c-index-test/c-index-test.c
@@ -360,6 +360,33 @@
   return CommentSchemaFile;
 }
 
+static CXString createCXString(const char *CS) {
+  CXString Str;
+
+  Str.Contents = (const void *) CS;
+  if (CS) {
+    Str.Size = strlen(CS);
+    Str.IsNullTerminated = true;
+  } else {
+    Str.Size = 0;
+    Str.IsNullTerminated = false;
+  }
+  Str.IsOwned = false;
+  Str.IsPooled = false;
+  return Str;
+}
+
+static CXString copyToCXString(const char *OrigCS) {
+  CXString Str;
+  const char *CS;
+
+  CS = strdup(OrigCS);
+  assert(CS);
+  Str = createCXString(CS);
+  Str.IsOwned = true;
+  return Str;
+}
+
 /******************************************************************************/
 /* Pretty-printing.                                                           */
 /******************************************************************************/
@@ -429,7 +456,7 @@
   if (Version.Major < 0)
     return;
   printf("%s%d", Prefix, Version.Major);
-  
+
   if (Version.Minor < 0)
     return;
   printf(".%d", Version.Minor);
@@ -740,9 +767,7 @@
   }
   assert(0 && "unknown display type"); /* no llvm_unreachable in C. */
   /* Set to NULL to prevent uninitialized variable warnings. */
-  text.data = NULL;
-  text.private_flags = 0;
-  return text;
+  return createCXString(NULL);
 }
 
 static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
@@ -787,10 +812,10 @@
           CXSourceLocation Loc;
           if (I)
             printf(", ");
-          
+
           Loc = clang_getCursorLocation(Ovl);
           clang_getSpellingLocation(Loc, 0, &line, &column, 0);
-          printf("%d:%d", line, column);          
+          printf("%d:%d", line, column);
         }
         printf("]");
       } else {
@@ -812,24 +837,24 @@
 
     if (clang_isCursorDefinition(Cursor))
       printf(" (Definition)");
-    
+
     switch (clang_getCursorAvailability(Cursor)) {
       case CXAvailability_Available:
         break;
-        
+
       case CXAvailability_Deprecated:
         printf(" (deprecated)");
         break;
-        
+
       case CXAvailability_NotAvailable:
         printf(" (unavailable)");
         break;
 
       case CXAvailability_NotAccessible:
         printf(" (inaccessible)");
         break;
     }
-    
+
     NumPlatformAvailability
       = clang_getCursorPlatformAvailability(Cursor,
                                             &AlwaysDeprecated,
@@ -847,7 +872,7 @@
       for (I = 0; I != NumPlatformAvailability; ++I) {
         if (I >= 2)
           break;
-        
+
         printf("  (%s", clang_getCString(PlatformAvailability[I].Platform));
         if (PlatformAvailability[I].Unavailable)
           printf(", unavailable");
@@ -867,7 +892,7 @@
         break;
       clang_disposeCXPlatformAvailability(PlatformAvailability + I);
     }
-    
+
     clang_disposeString(DeprecatedMessage);
     clang_disposeString(UnavailableMessage);
 
@@ -954,7 +979,7 @@
       printf(" [IBOutletCollection=%s]", clang_getCString(S));
       clang_disposeString(S);
     }
-    
+
     if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
       enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
       unsigned isVirtual = clang_isVirtualBase(Cursor);
@@ -969,8 +994,8 @@
           accessStr = "protected"; break;
         case CX_CXXPrivate:
           accessStr = "private"; break;
-      }      
-      
+      }
+
       printf(" [access=%s isVirtual=%s]", accessStr,
              isVirtual ? "true" : "false");
     }
@@ -1016,7 +1041,7 @@
     }
 
     clang_getOverriddenCursors(Cursor, &overridden, &num_overridden);
-    if (num_overridden) {      
+    if (num_overridden) {
       unsigned I;
       LineCol lineCols[50];
       assert(num_overridden <= 50);
@@ -1037,28 +1062,28 @@
       printf("]");
       clang_disposeOverriddenCursors(overridden);
     }
-    
+
     if (Cursor.kind == CXCursor_InclusionDirective) {
       CXFile File = clang_getIncludedFile(Cursor);
       CXString Included = clang_getFileName(File);
       printf(" (%s)", clang_getCString(Included));
       clang_disposeString(Included);
-      
+
       if (clang_isFileMultipleIncludeGuarded(TU, File))
         printf("  [multi-include guarded]");
     }
-    
+
     CursorExtent = clang_getCursorExtent(Cursor);
-    RefNameRange = clang_getCursorReferenceNameRange(Cursor, 
+    RefNameRange = clang_getCursorReferenceNameRange(Cursor,
                                                    CXNameRange_WantQualifier
                                                  | CXNameRange_WantSinglePiece
                                                  | CXNameRange_WantTemplateArgs,
                                                      0);
     if (!clang_equalRanges(CursorExtent, RefNameRange))
       PrintRange(RefNameRange, "SingleRefName");
-    
+
     for (RefNameRangeNr = 0; 1; RefNameRangeNr++) {
-      RefNameRange = clang_getCursorReferenceNameRange(Cursor, 
+      RefNameRange = clang_getCursorReferenceNameRange(Cursor,
                                                    CXNameRange_WantQualifier
                                                  | CXNameRange_WantTemplateArgs,
                                                        RefNameRangeNr);
@@ -1111,28 +1136,24 @@
   }
 }
 
-static const char* GetCursorSource(CXCursor Cursor) {
+static CXString GetCursorSource(CXCursor Cursor) {
   CXSourceLocation Loc = clang_getCursorLocation(Cursor);
   CXString source;
   CXFile file;
+  const char *sourceCStr;
+  CXString result;
+
   clang_getExpansionLocation(Loc, &file, 0, 0, 0);
   source = clang_getFileName(file);
-  if (!clang_getCString(source)) {
-    clang_disposeString(source);
-    return "<invalid loc>";
-  }
-  else {
-    const char *b = basename(clang_getCString(source));
-    clang_disposeString(source);
-    return b;
+  sourceCStr = clang_getCString(source);
+  if (!sourceCStr) {
+    result = createCXString("<invalid loc>");
+  } else {
+    result = copyToCXString(basename(sourceCStr));
   }
-}
 
-static CXString createCXString(const char *CS) {
-  CXString Str;
-  Str.data = (const void *) CS;
-  Str.private_flags = 0;
-  return Str;
+  clang_disposeString(source);
+  return result;
 }
 
 /******************************************************************************/
@@ -1206,7 +1227,7 @@
     PrintDiagnostic(Diag);
     if (ChildDiags)
       PrintDiagnosticSet(ChildDiags);
-  }  
+  }
 }
 
 void PrintDiagnostics(CXTranslationUnit TU) {
@@ -1229,7 +1250,7 @@
   }
   fprintf(stderr, "  TOTAL = %ld bytes (%f MBytes)\n", total,
           ((double) total)/(1024*1024));
-  clang_disposeCXTUResourceUsage(usage);  
+  clang_disposeCXTUResourceUsage(usage);
 }
 
 /******************************************************************************/
@@ -1252,13 +1273,17 @@
 enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
                                                 CXCursor Parent,
                                                 CXClientData ClientData) {
+  CXString Source;
+  const char *SourceCStr;
   VisitorData *Data = (VisitorData *)ClientData;
   if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
     CXSourceLocation Loc = clang_getCursorLocation(Cursor);
     unsigned line, column;
     clang_getSpellingLocation(Loc, 0, &line, &column, 0);
-    printf("// %s: %s:%d:%d: ", FileCheckPrefix,
-           GetCursorSource(Cursor), line, column);
+    Source = GetCursorSource(Cursor);
+    SourceCStr = clang_getCString(Source);
+    printf("// %s: %s:%d:%d: ", FileCheckPrefix, SourceCStr, line, column);
+    clang_disposeString(Source);
     PrintCursor(Cursor, Data->CommentSchemaFile);
     PrintCursorExtent(Cursor);
     if (clang_isDeclaration(Cursor.kind)) {
@@ -1308,6 +1333,8 @@
     CXSourceLocation Loc;
     CXFile file;
     CXString source;
+    CXString curSource;
+    const char *curSourceCStr;
 
     if (*startBuf == '\n') {
       startBuf++;
@@ -1327,8 +1354,11 @@
       if (Ref.kind == CXCursor_NoDeclFound) {
         /* Nothing found here; that's fine. */
       } else if (Ref.kind != CXCursor_FunctionDecl) {
-        printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
+        curSource = GetCursorSource(Ref);
+        curSourceCStr = clang_getCString(curSource);
+        printf("// %s: %s:%d:%d: ", FileCheckPrefix, curSourceCStr,
                curLine, curColumn);
+        clang_disposeString(curSource);
         PrintCursor(Ref, Data->CommentSchemaFile);
         printf("\n");
       }
@@ -1346,15 +1376,21 @@
 
 enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
                                    CXClientData ClientData) {
+  CXString Source;
+  const char *SourceCStr;
   VisitorData *Data = (VisitorData *)ClientData;
+
   if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
     CXString USR = clang_getCursorUSR(C);
     const char *cstr = clang_getCString(USR);
     if (!cstr || cstr[0] == '\0') {
       clang_disposeString(USR);
       return CXChildVisit_Recurse;
     }
-    printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr);
+    Source = GetCursorSource(C);
+    SourceCStr = clang_getCString(Source);
+    printf("// %s: %s %s", FileCheckPrefix, SourceCStr, cstr);
+    clang_disposeString(Source);
 
     PrintCursorExtent(C);
     printf("\n");
@@ -1778,7 +1814,7 @@
 
     /* Perform some simple filtering. */
     if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
-    else if (!strcmp(filter, "all-display") || 
+    else if (!strcmp(filter, "all-display") ||
              !strcmp(filter, "local-display")) {
       ck = NULL;
       wanted_display_type = DisplayType_DisplayName;
@@ -1928,11 +1964,11 @@
   int trial;
   int remap_after_trial = 0;
   char *endptr = 0;
-  
+
   Idx = clang_createIndex(/* excludeDeclsFromPCH */
                           !strcmp(filter, "local") ? 1 : 0,
                           /* displayDiagnostics=*/1);
-  
+
   if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
     clang_disposeIndex(Idx);
     return -1;
@@ -1946,7 +1982,7 @@
     compiler_arg_idx = i+1;
   if (num_unsaved_files > compiler_arg_idx)
     compiler_arg_idx = num_unsaved_files;
-  
+
   /* Load the initial translation unit -- we do this without honoring remapped
    * files, so that we have a way to test results after changing the source. */
   Err = clang_parseTranslationUnit2(Idx, 0,
@@ -1960,7 +1996,7 @@
     clang_disposeIndex(Idx);
     return 1;
   }
-  
+
   if (checkForErrors(TU) != 0)
     return -1;
 
@@ -1989,13 +2025,13 @@
       clang_disposeTranslationUnit(TU);
       free_remapped_files(unsaved_files, num_unsaved_files);
       clang_disposeIndex(Idx);
-      return -1;      
+      return -1;
     }
 
     if (checkForErrors(TU) != 0)
       return -1;
   }
-  
+
   result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, NULL);
 
   free_remapped_files(unsaved_files, num_unsaved_files);
@@ -2246,7 +2282,7 @@
                               file);
       fprintf(file, "}");
       continue;
-    } 
+    }
 
     if (Kind == CXCompletionChunk_VerticalSpace) {
       fprintf(file, "{VerticalSpace  }");
@@ -2272,21 +2308,21 @@
   CXString BriefComment;
   CXString Annotation;
   const char *BriefCommentCString;
-  
+
   fprintf(file, "%s:", clang_getCString(ks));
   clang_disposeString(ks);
 
   print_completion_string(completion_result->CompletionString, file);
-  fprintf(file, " (%u)", 
+  fprintf(file, " (%u)",
           clang_getCompletionPriority(completion_result->CompletionString));
   switch (clang_getCompletionAvailability(completion_result->CompletionString)){
   case CXAvailability_Available:
     break;
-    
+
   case CXAvailability_Deprecated:
     fprintf(file, " (deprecated)");
     break;
-    
+
   case CXAvailability_NotAvailable:
     fprintf(file, " (unavailable)");
     break;
@@ -2332,7 +2368,7 @@
     fprintf(file, "(brief comment: %s)", BriefCommentCString);
   }
   clang_disposeString(BriefComment);
-  
+
   fprintf(file, "\n");
 }
 
@@ -2431,7 +2467,7 @@
     completionOptions |= CXCodeComplete_IncludeBriefComments;
   if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE"))
     completionOptions |= CXCodeComplete_SkipPreamble;
-  
+
   if (timing_only)
     input += strlen("-code-completion-timing=");
   else
@@ -2490,7 +2526,7 @@
     enum CXCursorKind containerKind;
     CXString objCSelector;
     const char *selectorString;
-    if (!timing_only) {      
+    if (!timing_only) {
       /* Sort the code-completion results based on the typed text. */
       clang_sortCodeCompletionResults(results->Results, results->NumResults);
 
@@ -2503,39 +2539,39 @@
       PrintDiagnostic(diag);
       clang_disposeDiagnostic(diag);
     }
-    
+
     contexts = clang_codeCompleteGetContexts(results);
     print_completion_contexts(contexts, stdout);
-    
+
     containerKind = clang_codeCompleteGetContainerKind(results,
                                                        &containerIsIncomplete);
-    
+
     if (containerKind != CXCursor_InvalidCode) {
       /* We have found a container */
       CXString containerUSR, containerKindSpelling;
       containerKindSpelling = clang_getCursorKindSpelling(containerKind);
       printf("Container Kind: %s\n", clang_getCString(containerKindSpelling));
       clang_disposeString(containerKindSpelling);
-      
+
       if (containerIsIncomplete) {
         printf("Container is incomplete\n");
       }
       else {
         printf("Container is complete\n");
       }
-      
+
       containerUSR = clang_codeCompleteGetContainerUSR(results);
       printf("Container USR: %s\n", clang_getCString(containerUSR));
       clang_disposeString(containerUSR);
     }
-    
+
     objCSelector = clang_codeCompleteGetObjCSelector(results);
     selectorString = clang_getCString(objCSelector);
     if (selectorString && strlen(selectorString) > 0) {
       printf("Objective-C selector: %s\n", selectorString);
     }
     clang_disposeString(objCSelector);
-    
+
     clang_disposeCodeCompleteResults(results);
   }
   clang_disposeTranslationUnit(TU);
@@ -2569,7 +2605,7 @@
   unsigned NumLocations = 0, Loc;
   unsigned Repeats = 1;
   unsigned I;
-  
+
   /* Count the number of locations. */
   while (strstr(argv[NumLocations+1], locations_flag) == argv[NumLocations+1])
     ++NumLocations;
@@ -2624,7 +2660,7 @@
 
     if (checkForErrors(TU) != 0)
       return -1;
-    
+
     for (Loc = 0; Loc < NumLocations; ++Loc) {
       CXFile file = clang_getFile(TU, Locations[Loc].filename);
       if (!file)
@@ -2643,7 +2679,7 @@
       }
     }
   }
-  
+
   PrintDiagnostics(TU);
   clang_disposeTranslationUnit(TU);
   clang_disposeIndex(CIdx);
@@ -2862,7 +2898,7 @@
   unsigned NumLocations = 0, Loc;
   unsigned Repeats = 1;
   unsigned I;
-  
+
   /* Count the number of locations. */
   while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1])
     ++NumLocations;
@@ -2918,7 +2954,7 @@
 
     if (checkForErrors(TU) != 0)
       return -1;
-    
+
     for (Loc = 0; Loc < NumLocations; ++Loc) {
       CXFile file = clang_getFile(TU, Locations[Loc].filename);
       if (!file)
@@ -2943,7 +2979,7 @@
       }
     }
   }
-  
+
   PrintDiagnostics(TU);
   clang_disposeTranslationUnit(TU);
   clang_disposeIndex(CIdx);
@@ -3138,7 +3174,7 @@
   unsigned line, column;
   const char *main_filename;
   int isMainFile;
-  
+
   index_data = (IndexData *)client_data;
   clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
   if (line == 0) {
@@ -3184,7 +3220,7 @@
   char *newStr;
   CXIdxClientFile file;
   unsigned line, column;
-  
+
   name = info->name;
   if (!name)
     name = "<anon-tag>";
@@ -3342,8 +3378,8 @@
     str = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
     cstr = clang_getCString(str);
     printf("[diagnostic]: %s\n", cstr);
-    clang_disposeString(str);  
-  
+    clang_disposeString(str);
+
     if (getenv("CINDEXTEST_FAILONERROR") &&
         clang_getDiagnosticSeverity(diag) >= CXDiagnostic_Error) {
       index_data->fail_for_error = 1;
@@ -3381,7 +3417,7 @@
   printCXIndexLoc(info->hashLoc, client_data);
   printf(" | isImport: %d | isAngled: %d | isModule: %d",
          info->isImport, info->isAngled, info->isModuleImport);
-  
+
   Mod = clang_getModuleForFile(index_data->TU, (CXFile)info->file);
   if (Mod) {
     CXString str = clang_Module_getFullName(Mod);
@@ -3406,7 +3442,7 @@
     importedASTS_insert(index_data->importedASTs, clang_getCString(filename));
     clang_disposeString(filename);
   }
-  
+
   printf("[importedASTFile]: ");
   printCXIndexFile((CXIdxClientFile)info->file);
   if (info->module) {
@@ -4269,9 +4305,9 @@
   int num_unsaved_files = 0;
   enum CXErrorCode Err;
   int result = 0;
-  
+
   Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1);
-  
+
   if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
     clang_disposeIndex(Idx);
     return -1;
@@ -4293,30 +4329,30 @@
     return 1;
   }
 
-  switch (clang_saveTranslationUnit(TU, filename, 
+  switch (clang_saveTranslationUnit(TU, filename,
                                     clang_defaultSaveOptions(TU))) {
   case CXSaveError_None:
     break;
 
   case CXSaveError_TranslationErrors:
-    fprintf(stderr, "Unable to write PCH file %s: translation errors\n", 
+    fprintf(stderr, "Unable to write PCH file %s: translation errors\n",
             filename);
-    result = 2;    
+    result = 2;
     break;
 
   case CXSaveError_InvalidTU:
-    fprintf(stderr, "Unable to write PCH file %s: invalid translation unit\n", 
+    fprintf(stderr, "Unable to write PCH file %s: invalid translation unit\n",
             filename);
-    result = 3;    
+    result = 3;
     break;
 
   case CXSaveError_Unknown:
   default:
     fprintf(stderr, "Unable to write PCH file %s: unknown error \n", filename);
     result = 1;
     break;
   }
-  
+
   clang_disposeTranslationUnit(TU);
   free_remapped_files(unsaved_files, num_unsaved_files);
   clang_disposeIndex(Idx);
@@ -4363,23 +4399,23 @@
   CXFile File;
   CXString FileName;
   unsigned line, column, offset;
-  
+
   clang_getExpansionLocation(L, &File, &line, &column, &offset);
   FileName = clang_getFileName(File);
-  
+
   fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column);
   clang_disposeString(FileName);
 }
 
 static void printRanges(CXDiagnostic D, unsigned indent) {
   unsigned i, n = clang_getDiagnosticNumRanges(D);
-  
+
   for (i = 0; i < n; ++i) {
     CXSourceLocation Start, End;
     CXSourceRange SR = clang_getDiagnosticRange(D, i);
     Start = clang_getRangeStart(SR);
     End = clang_getRangeEnd(SR);
-    
+
     printIndent(indent);
     fprintf(stderr, "Range: ");
     printLocation(Start);
@@ -4396,40 +4432,40 @@
     CXSourceRange ReplacementRange;
     CXString text;
     text = clang_getDiagnosticFixIt(D, i, &ReplacementRange);
-    
+
     printIndent(indent);
     fprintf(stderr, "FIXIT: (");
     printLocation(clang_getRangeStart(ReplacementRange));
     fprintf(stderr, " - ");
     printLocation(clang_getRangeEnd(ReplacementRange));
     fprintf(stderr, "): \"%s\"\n", clang_getCString(text));
     clang_disposeString(text);
-  }  
+  }
 }
 
 static void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) {
   unsigned i, n;
 
   if (!Diags)
     return;
-  
+
   n = clang_getNumDiagnosticsInSet(Diags);
   for (i = 0; i < n; ++i) {
     CXSourceLocation DiagLoc;
     CXDiagnostic D;
     CXFile File;
     CXString FileName, DiagSpelling, DiagOption, DiagCat;
     unsigned line, column, offset;
     const char *DiagOptionStr = 0, *DiagCatStr = 0;
-    
+
     D = clang_getDiagnosticInSet(Diags, i);
     DiagLoc = clang_getDiagnosticLocation(D);
     clang_getExpansionLocation(DiagLoc, &File, &line, &column, &offset);
     FileName = clang_getFileName(File);
     DiagSpelling = clang_getDiagnosticSpelling(D);
-    
+
     printIndent(indent);
-    
+
     fprintf(stderr, "%s:%d:%d: %s: %s",
             clang_getCString(FileName),
             line,
@@ -4442,42 +4478,42 @@
     if (DiagOptionStr) {
       fprintf(stderr, " [%s]", DiagOptionStr);
     }
-    
+
     DiagCat = clang_getDiagnosticCategoryText(D);
     DiagCatStr = clang_getCString(DiagCat);
     if (DiagCatStr) {
       fprintf(stderr, " [%s]", DiagCatStr);
     }
-    
+
     fprintf(stderr, "\n");
-    
+
     printRanges(D, indent);
     printFixIts(D, indent);
-    
+
     /* Print subdiagnostics. */
     printDiagnosticSet(clang_getChildDiagnostics(D), indent+2);
 
     clang_disposeString(FileName);
     clang_disposeString(DiagSpelling);
     clang_disposeString(DiagOption);
     clang_disposeString(DiagCat);
-  }  
+  }
 }
 
 static int read_diagnostics(const char *filename) {
   enum CXLoadDiag_Error error;
   CXString errorString;
   CXDiagnosticSet Diags = 0;
-  
+
   Diags = clang_loadDiagnostics(filename, &error, &errorString);
   if (!Diags) {
     fprintf(stderr, "Trouble deserializing file (%s): %s\n",
             getDiagnosticCodeStr(error),
             clang_getCString(errorString));
     clang_disposeString(errorString);
     return 1;
   }
-  
+
   printDiagnosticSet(Diags, 0);
   fprintf(stderr, "Number of diagnostics: %d\n",
           clang_getNumDiagnosticsInSet(Diags));
@@ -4606,17 +4642,17 @@
     CXCursorVisitor I = GetVisitor(argv[1] + 25);
     if (I) {
       int trials = atoi(argv[2]);
-      return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I, 
+      return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I,
                                          NULL);
     }
   }
   else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
     CXCursorVisitor I = GetVisitor(argv[1] + 17);
-    
+
     PostVisitTU postVisit = 0;
     if (strstr(argv[1], "-memory-usage"))
       postVisit = PrintMemoryUsage;
-    
+
     if (I)
       return perform_test_load_source(argc - 3, argv + 3, argv[2], I,
                                       postVisit);
Index: include/clang-c/CXString.h
===================================================================
--- include/clang-c/CXString.h
+++ include/clang-c/CXString.h
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_C_CXSTRING_H
 
 #include "clang-c/Platform.h"
+#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -36,8 +37,11 @@
  * with the string data, call \c clang_disposeString() to free the string.
  */
 typedef struct {
-  const void *data;
-  unsigned private_flags;
+  const void *Contents;
+  unsigned Size;
+  bool IsNullTerminated;
+  bool IsOwned;
+  bool IsPooled;
 } CXString;
 
 typedef struct {
@@ -47,10 +51,33 @@
 
 /**
  * \brief Retrieve the character data associated with the given string.
+ *
+ * This returns a pointer to a C string even if this \b CXString was built
+ * from e.g. a StringRef reference (which is not null-terminated).  In those
+ * cases a string copy is performed on-demand.
+ *
+ * See also \b clang_getStringData and \b clang_getStringSize which could
+ * provide a range or "window" of data, if needed, and a C string is not
+ * strictly needed; this could save a C string allocation, deallocation, and
+ * string copy.
  */
 CINDEX_LINKAGE const char *clang_getCString(CXString string);
 
 /**
+ * \brief Retrieve a pointer to the start of the character data for this string.
+ *
+ * Note that the string is not necessarily null-terminated, so it might not be
+ * suitable for use as a C string.  See \b clang_getCString which guarantees
+ * a C string result.
+ */
+CINDEX_LINKAGE const char *clang_getStringData(CXString string);
+
+/**
+ * \brief Retrieve the string length (not including null-terminator, if any).
+ */
+CINDEX_LINKAGE unsigned clang_getStringSize(CXString string);
+
+/**
  * \brief Free the given string.
  */
 CINDEX_LINKAGE void clang_disposeString(CXString string);
@@ -68,4 +95,3 @@
 }
 #endif
 #endif
-
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to