[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