[cfe-commits] r86562 - in /cfe/trunk: include/clang-c/Index.h tools/CIndex/CIndex.cpp tools/CIndex/CIndex.exports tools/c-index-test/c-index-test.c

Steve Naroff snaroff at apple.com
Mon Nov 9 09:45:52 PST 2009


Author: snaroff
Date: Mon Nov  9 11:45:52 2009
New Revision: 86562

URL: http://llvm.org/viewvc/llvm-project?rev=86562&view=rev
Log:
Introduce CXString type and associated functions clang_getCString() and clang_disposeString().

This abstraction will help us manage string memory for complex names that cross the C++/C boundary (e.g. ObjC methods, selectors). This patch also uses it in clang_getTranslationUnitSpelling (which I'm not sure is necessary). Will investigate later...since the extra malloc() can't hurt (for now).

Patch by John Thompson.


Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/tools/CIndex/CIndex.cpp
    cfe/trunk/tools/CIndex/CIndex.exports
    cfe/trunk/tools/c-index-test/c-index-test.c

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=86562&r1=86561&r2=86562&view=diff

==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Mon Nov  9 11:45:52 2009
@@ -115,6 +115,26 @@
 /* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */
 typedef void *CXEntity;
 
+/**
+ * For functions returning a string that might or might not need
+ * to be internally allocated and freed.
+ * Use clang_getCString to access the C string value.
+ * Use clang_disposeString to free the value.
+ * Treat it as an opaque type.
+ */
+typedef struct {
+  const char *Spelling;
+  /* A 1 value indicates the clang_ indexing API needed to allocate the string
+     (and it must be freed by clang_disposeString()). */
+  int MustFreeString;
+} CXString;
+
+/* Get C string pointer from a CXString. */
+CINDEX_LINKAGE const char *clang_getCString(CXString string);
+
+/* Free CXString. */
+CINDEX_LINKAGE void clang_disposeString(CXString string);
+
 /**  
  * \brief clang_createIndex() provides a shared context for creating
  * translation units. It provides two options:
@@ -155,8 +175,7 @@
 CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
                           int displayDiagnostics);
 CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
-
-CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
+CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
 
 /* 
  * \brief Create a translation unit from an AST file (-emit-ast).
@@ -260,7 +279,7 @@
  */
 CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
 CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
-CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl);
+CINDEX_LINKAGE CXString clang_getDeclSpelling(CXDecl);
 CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
 CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
 CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
@@ -284,7 +303,7 @@
 
 CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
 CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
-CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor);
+CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
 CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
 CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
 

Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=86562&r1=86561&r2=86562&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Mon Nov  9 11:45:52 2009
@@ -541,11 +541,14 @@
   delete static_cast<ASTUnit *>(CTUnit);
 }
   
-const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
+CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
 {
   assert(CTUnit && "Passed null CXTranslationUnit");
   ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
-  return CXXUnit->getOriginalSourceFileName().c_str();
+  CXString string;
+  string.Spelling = strdup(CXXUnit->getOriginalSourceFileName().c_str());
+  string.MustFreeString = 1;
+  return string;
 }
 
 void clang_loadTranslationUnit(CXTranslationUnit CTUnit, 
@@ -610,25 +613,27 @@
 {
   return 0;
 }
-const char *clang_getDeclSpelling(CXDecl AnonDecl)
+CXString clang_getDeclSpelling(CXDecl AnonDecl)
 {
   assert(AnonDecl && "Passed null CXDecl");
   NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
-  
+  CXString string;
+
+  string.MustFreeString = 0;
   if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
-    // FIXME: Memory leak! We need to move to a CXString or other API.
-    return ::strdup(OMD->getSelector().getAsString().c_str());
+    string.Spelling = strdup(OMD->getSelector().getAsString().c_str());
+    string.MustFreeString = 1;
   }
-  if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
+  else if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
     // No, this isn't the same as the code below. getIdentifier() is non-virtual
     // and returns different names. NamedDecl returns the class name and
     // ObjCCategoryImplDecl returns the category name.
-    return CIMP->getIdentifier()->getNameStart();
-    
-  if (ND->getIdentifier())
-    return ND->getIdentifier()->getNameStart();
+    string.Spelling = CIMP->getIdentifier()->getNameStart(); 
+  else if (ND->getIdentifier())
+    string.Spelling = ND->getIdentifier()->getNameStart();
   else 
-    return "";
+    string.Spelling = "";
+  return string;
 }
 
 unsigned clang_getDeclLine(CXDecl AnonDecl)
@@ -686,37 +691,44 @@
   return FEnt->getModificationTime();
 }
 
-const char *clang_getCursorSpelling(CXCursor C)
+CXString clang_getCursorSpelling(CXCursor C)
 {
   assert(C.decl && "CXCursor has null decl");
   NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
-  
+
   if (clang_isReference(C.kind)) {
+    CXString string;
+    string.MustFreeString = 0;
     switch (C.kind) {
       case CXCursor_ObjCSuperClassRef: {
         ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
         assert(OID && "clang_getCursorLine(): Missing interface decl");
-        return OID->getSuperClass()->getIdentifier()->getNameStart();
+        string.Spelling = OID->getSuperClass()->getIdentifier()->getNameStart();
+        break;
       }
       case CXCursor_ObjCClassRef: {
         if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND)) {
-          return OID->getIdentifier()->getNameStart();
+          string.Spelling = OID->getIdentifier()->getNameStart();
+        } else {
+          ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(ND);
+          assert(OCD && "clang_getCursorLine(): Missing category decl");
+          string.Spelling = OCD->getClassInterface()->getIdentifier()->getNameStart();
         }
-        ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
-        assert(OID && "clang_getCursorLine(): Missing category decl");
-        return OID->getClassInterface()->getIdentifier()->getNameStart();
+        break;
       }
       case CXCursor_ObjCProtocolRef: {
         ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
         assert(OID && "clang_getCursorLine(): Missing protocol decl");
-        return OID->getIdentifier()->getNameStart();
+        string.Spelling = OID->getIdentifier()->getNameStart();
+        break;
       }
       case CXCursor_ObjCSelectorRef: {
         ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
                                  static_cast<Stmt *>(C.stmt));
         assert(OME && "clang_getCursorLine(): Missing message expr");
-        // FIXME: Memory leak! We need to move to a CXString or other API.
-        return ::strdup(OME->getSelector().getAsString().c_str());
+        string.Spelling = strdup(OME->getSelector().getAsString().c_str());
+        string.MustFreeString = 1;
+        break;
       }
       case CXCursor_VarRef:
       case CXCursor_FunctionRef:
@@ -724,11 +736,14 @@
         DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
                                  static_cast<Stmt *>(C.stmt));
         assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
-        return DRE->getDecl()->getIdentifier()->getNameStart();
+        string.Spelling = DRE->getDecl()->getIdentifier()->getNameStart();
+        break;
       }
       default:
-        return "<not implemented>";
+        string.Spelling = "<not implemented>";
+        break;
     }
+    return string;
   }
   return clang_getDeclSpelling(C.decl);
 }
@@ -936,6 +951,22 @@
   return SourceMgr.getSpellingLineNumber(SLoc);
 }
 
+// Access string.
+const char *clang_getCString(CXString string) {
+  return string.Spelling;
+}
+ 
+// Free CXString.
+void clang_disposeString(CXString string) {
+  if (string.MustFreeString) {
+    if (string.Spelling) {
+      free((void *)string.Spelling);
+      string.Spelling = NULL;
+    }
+    string.MustFreeString = 0;
+  }
+}
+
 unsigned clang_getCursorColumn(CXCursor C)
 {
   assert(C.decl && "CXCursor has null decl");

Modified: cfe/trunk/tools/CIndex/CIndex.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.exports?rev=86562&r1=86561&r2=86562&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.exports (original)
+++ cfe/trunk/tools/CIndex/CIndex.exports Mon Nov  9 11:45:52 2009
@@ -3,6 +3,7 @@
 _clang_createTranslationUnit
 _clang_createTranslationUnitFromSourceFile
 _clang_disposeIndex
+_clang_disposeString
 _clang_disposeTranslationUnit
 _clang_getCompletionChunkCompletionString
 _clang_getCompletionChunkKind
@@ -17,6 +18,7 @@
 _clang_getCursorSource
 _clang_getCursorSourceFile
 _clang_getCursorSpelling
+_clang_getCString
 _clang_getDeclColumn
 _clang_getDeclLine
 _clang_getDeclSource

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=86562&r1=86561&r2=86562&view=diff

==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Mon Nov  9 11:45:52 2009
@@ -28,8 +28,11 @@
     printf("Invalid Cursor => %s\n", clang_getCursorKindSpelling(Cursor.kind));
   else {
     CXDecl DeclReferenced;
+    CXString string;
+    string = clang_getCursorSpelling(Cursor);
     printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
-                      clang_getCursorSpelling(Cursor));
+                      clang_getCString(string));
+    clang_disposeString(string);
     DeclReferenced = clang_getCursorDecl(Cursor);
     if (DeclReferenced)
       printf(":%d:%d", clang_getDeclLine(DeclReferenced),
@@ -40,22 +43,29 @@
 static void DeclVisitor(CXDecl Dcl, CXCursor Cursor, CXClientData Filter)
 {
   if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
+    CXString string;
     printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
                                  clang_getCursorLine(Cursor),
                                  clang_getCursorColumn(Cursor));
     PrintCursor(Cursor);
-    printf(" [Context=%s]\n", clang_getDeclSpelling(Dcl));
+    string = clang_getDeclSpelling(Dcl);
+    printf(" [Context=%s]\n", clang_getCString(string));
+    clang_disposeString(string);
   }
 }
 static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
                                    CXClientData Filter)
 {
   if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
+    CXString string;
     printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Cursor)),
                                  clang_getCursorLine(Cursor),
                                  clang_getCursorColumn(Cursor));
     PrintCursor(Cursor);
-    printf(" [Context=%s]\n", basename(clang_getTranslationUnitSpelling(Unit)));
+    string = clang_getTranslationUnitSpelling(Unit);
+    printf(" [Context=%s]\n",
+          basename(clang_getCString(string)));
+    clang_disposeString(string);
 
     clang_loadDeclaration(Cursor.decl, DeclVisitor, 0);
 
@@ -83,10 +93,13 @@
           if (Ref.kind == CXCursor_NoDeclFound) {
             /* Nothing found here; that's fine. */
           } else if (Ref.kind != CXCursor_FunctionDecl) {
+            CXString string;
             printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Ref)),
                                              curLine, curColumn);
             PrintCursor(Ref);
-            printf(" [Context:%s]\n", clang_getDeclSpelling(Ref.decl));
+            string = clang_getDeclSpelling(Ref.decl);
+            printf(" [Context:%s]\n", clang_getCString(string));
+            clang_disposeString(string);
           }
           startBuf++;
         }





More information about the cfe-commits mailing list