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

Douglas Gregor dgregor at apple.com
Mon Jan 18 16:34:46 PST 2010


Author: dgregor
Date: Mon Jan 18 18:34:46 2010
New Revision: 93823

URL: http://llvm.org/viewvc/llvm-project?rev=93823&view=rev
Log:
Implement clang_getCursorExtent, which provides a source range for the
cursor itself. In particular, for references this returns the source
range of the reference rather than the source range of the thing it
refers to.

Switch c-index-test from clang_getDeclExtent (which will eventually be
deprecated and removed) over to clang_getCursorExtent. The source
ranges we print for references now make sense; fix up the tests
appropriately.

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/test/Index/c-index-api-loadTU-test.m
    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=93823&r1=93822&r2=93823&view=diff

==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Mon Jan 18 18:34:46 2010
@@ -407,6 +407,17 @@
  */
 CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
     
+/** \brief Retrieve the physical extent of the source construct referenced by
+ * the given cursor.
+ *
+ * The extent of a cursor starts with the file/line/column pointing at the
+ * first character within the source construct that the cursor refers to and
+ * ends with the last character withinin that source construct. For a 
+ * declaration, the extent covers the declaration itself. For a reference,
+ * the extent covers the location of the reference (e.g., where the referenced
+ * entity was actually used).
+ */
+CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
   
 /* for debug/testing */
 CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind); 

Modified: cfe/trunk/test/Index/c-index-api-loadTU-test.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-api-loadTU-test.m?rev=93823&r1=93822&r2=93823&view=diff

==============================================================================
--- cfe/trunk/test/Index/c-index-api-loadTU-test.m (original)
+++ cfe/trunk/test/Index/c-index-api-loadTU-test.m Mon Jan 18 18:34:46 2010
@@ -57,19 +57,19 @@
 // CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=foo:8:1 [Extent=8:1:8:6]
 // CHECK: c-index-api-loadTU-test.m:9:1: ObjCClassMethodDecl=fooC:9:1 [Extent=9:1:9:7]
 // CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:1 [Extent=13:1:17:4]
-// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:4:1 [Extent=4:1:11:4]
+// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:4:1 [Extent=13:18:13:20]
 // CHECK: c-index-api-loadTU-test.m:19:12: ObjCCategoryDecl=FooCat:19:12 [Extent=19:1:22:4]
-// CHECK: c-index-api-loadTU-test.m:19:12: ObjCClassRef=Foo:4:1 [Extent=4:1:11:4]
+// CHECK: c-index-api-loadTU-test.m:19:12: ObjCClassRef=Foo:4:1 [Extent=19:12:19:14]
 // CHECK: c-index-api-loadTU-test.m:20:1: ObjCInstanceMethodDecl=catMethodWithFloat::20:1 [Extent=20:1:20:40]
 // CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=floatMethod:21:1 [Extent=21:1:21:22]
 // CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 [Extent=24:1:26:4]
 // CHECK: c-index-api-loadTU-test.m:25:1: ObjCInstanceMethodDecl=pMethod:25:1 [Extent=25:1:25:10]
 // CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolDecl=SubP:28:1 [Extent=28:1:30:4]
-// CHECK: c-index-api-loadTU-test.m:28:17: ObjCProtocolRef=Proto:24:1 [Extent=24:1:26:4]
+// CHECK: c-index-api-loadTU-test.m:28:17: ObjCProtocolRef=Proto:24:1 [Extent=28:17:28:21]
 // CHECK: c-index-api-loadTU-test.m:29:1: ObjCInstanceMethodDecl=spMethod:29:1 [Extent=29:1:29:11]
 // CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:1 [Extent=32:1:39:4]
-// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:13:1 [Extent=13:1:17:4]
-// CHECK: c-index-api-loadTU-test.m:32:23: ObjCProtocolRef=SubP:28:1 [Extent=28:1:30:4]
+// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:13:1 [Extent=32:18:32:20]
+// CHECK: c-index-api-loadTU-test.m:32:23: ObjCProtocolRef=SubP:28:1 [Extent=32:23:32:26]
 // CHECK: c-index-api-loadTU-test.m:34:9: ObjCIvarDecl=_anIVar:34:9 [Extent=34:9:34:15]
 // CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 [Extent=37:1:37:20]
 // CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 [Extent=41:1:43:1]

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

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Mon Jan 18 18:34:46 2010
@@ -130,6 +130,55 @@
   return Result;
 }
 
+/// \brief Translate a Clang source range into a CIndex source range.
+static CXSourceRange translateSourceRange(ASTContext &Context,
+                                          SourceRange R) {
+  if (R.isInvalid()) {
+    CXSourceRange extent = { { 0, 0, 0 }, { 0, 0, 0 } };
+    return extent;
+  }
+  
+  // FIXME: This is largely copy-paste from
+  ///TextDiagnosticPrinter::HighlightRange.  When it is clear that this is
+  // what we want the two routines should be refactored.
+  
+  SourceManager &SM = Context.getSourceManager();
+  SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
+  SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+        
+  // If the End location and the start location are the same and are a macro
+  // location, then the range was something that came from a macro expansion
+  // or _Pragma.  If this is an object-like macro, the best we can do is to
+  // get the range.  If this is a function-like macro, we'd also like to
+  // get the arguments.
+  if (Begin == End && R.getEnd().isMacroID())
+    End = SM.getInstantiationRange(R.getEnd()).second;
+  
+  unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);  
+  unsigned EndLineNo = SM.getInstantiationLineNumber(End);
+  
+  // Compute the column number of the start.  Keep the column based at 1.
+  unsigned StartColNo = SM.getInstantiationColumnNumber(Begin);
+  
+  // Compute the column number of the end.
+  unsigned EndColNo = SM.getInstantiationColumnNumber(End);
+  if (EndColNo) {
+    // Offset the end column by 1 so that we point to the last character
+    // in the last token.
+    --EndColNo;
+    
+    // Add in the length of the token, so that we cover multi-char tokens.
+    EndColNo += Lexer::MeasureTokenLength(End, SM, Context.getLangOptions());
+  }
+  
+  // Package up the line/column data and return to the caller.
+  const FileEntry *BeginFile = SM.getFileEntryForID(SM.getFileID(Begin));
+  const FileEntry *EndFile = SM.getFileEntryForID(SM.getFileID(End));
+  CXSourceRange extent = { { (void *)BeginFile, StartLineNo, StartColNo },
+                           { (void *)EndFile, EndLineNo, EndColNo } };
+  return extent;  
+}
+
 //===----------------------------------------------------------------------===//
 // Visitors.
 //===----------------------------------------------------------------------===//
@@ -609,57 +658,7 @@
 }
   
 CXSourceRange clang_getDeclExtent(CXDecl AnonDecl) {
-  assert(AnonDecl && "Passed null CXDecl");
-  NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
-  SourceManager &SM = ND->getASTContext().getSourceManager();
-  SourceRange R = ND->getSourceRange();
-
-  SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
-  SourceLocation End = SM.getInstantiationLoc(R.getEnd());
-
-  if (!Begin.isValid()) {
-    CXSourceRange extent = { { 0, 0, 0 }, { 0, 0, 0 } };
-    return extent;
-  }
-  
-  // FIXME: This is largely copy-paste from
-  ///TextDiagnosticPrinter::HighlightRange.  When it is clear that this is
-  // what we want the two routines should be refactored.
-  
-  // If the End location and the start location are the same and are a macro
-  // location, then the range was something that came from a macro expansion
-  // or _Pragma.  If this is an object-like macro, the best we can do is to
-  // get the range.  If this is a function-like macro, we'd also like to
-  // get the arguments.
-  if (Begin == End && R.getEnd().isMacroID())
-    End = SM.getInstantiationRange(R.getEnd()).second;
-
-  assert(SM.getFileID(Begin) == SM.getFileID(End));
-  unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);  
-  unsigned EndLineNo = SM.getInstantiationLineNumber(End);
-  
-  // Compute the column number of the start.  Keep the column based at 1.
-  unsigned StartColNo = SM.getInstantiationColumnNumber(Begin);
-  
-  // Compute the column number of the end.
-  unsigned EndColNo = SM.getInstantiationColumnNumber(End);
-  if (EndColNo) {
-    // Offset the end column by 1 so that we point to the last character
-    // in the last token.
-    --EndColNo;
-    
-    // Add in the length of the token, so that we cover multi-char tokens.
-    ASTContext &Ctx = ND->getTranslationUnitDecl()->getASTContext();
-    const LangOptions &LOpts = Ctx.getLangOptions();
-
-    EndColNo += Lexer::MeasureTokenLength(End, SM, LOpts);
-  }
-
-  // Package up the line/column data and return to the caller.
-  const FileEntry *FEntry = SM.getFileEntryForID(SM.getFileID(Begin));
-  CXSourceRange extent = { { (void *)FEntry, StartLineNo, StartColNo },
-                           { (void *)FEntry, EndLineNo, EndColNo } };
-  return extent;  
+  return clang_getCursorExtent(clang_getCursorFromDecl(AnonDecl));
 }
 
 const char *clang_getDeclSource(CXDecl AnonDecl) {
@@ -961,6 +960,52 @@
     Loc = Class->getClassLoc();
   return translateSourceLocation(SM, Loc);
 }
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+  if (clang_isReference(C.kind)) {
+    switch (C.kind) {
+      case CXCursor_ObjCSuperClassRef: {       
+        std::pair<ObjCInterfaceDecl *, SourceLocation> P
+          = getCursorObjCSuperClassRef(C);
+        return translateSourceRange(P.first->getASTContext(), P.second);
+      }
+        
+      case CXCursor_ObjCProtocolRef: {       
+        std::pair<ObjCProtocolDecl *, SourceLocation> P
+          = getCursorObjCProtocolRef(C);
+        return translateSourceRange(P.first->getASTContext(), P.second);
+      }
+        
+      case CXCursor_ObjCClassRef: {       
+        std::pair<ObjCInterfaceDecl *, SourceLocation> P
+          = getCursorObjCClassRef(C);
+        
+        return translateSourceRange(P.first->getASTContext(), P.second);
+      }
+        
+      case CXCursor_ObjCSelectorRef:
+      case CXCursor_ObjCIvarRef:
+      case CXCursor_VarRef:
+      case CXCursor_FunctionRef:
+      case CXCursor_EnumConstantRef:
+      case CXCursor_MemberRef:
+        return translateSourceRange(getCursorContext(C), 
+                                    getCursorExpr(C)->getSourceRange());
+        
+      default:
+        // FIXME: Need a way to enumerate all non-reference cases.
+        llvm_unreachable("Missed a reference kind");
+    }
+  }
+  
+  if (!getCursorDecl(C)) {
+    CXSourceRange empty = { { 0, 0, 0 }, { 0, 0, 0 } };
+    return empty;
+  }
+  
+  Decl *D = getCursorDecl(C);
+  return translateSourceRange(D->getASTContext(), D->getSourceRange());
+}
   
 void clang_getDefinitionSpellingAndExtent(CXCursor C,
                                           const char **startBuf,

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

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.exports (original)
+++ cfe/trunk/tools/CIndex/CIndex.exports Mon Jan 18 18:34:46 2010
@@ -13,6 +13,7 @@
 _clang_getCompletionChunkText
 _clang_getCursor
 _clang_getCursorDecl
+_clang_getCursorExtent
 _clang_getCursorFromDecl
 _clang_getCursorKind
 _clang_getCursorKindSpelling

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=93823&r1=93822&r2=93823&view=diff

==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Mon Jan 18 18:34:46 2010
@@ -73,11 +73,11 @@
 
 static const char *FileCheckPrefix = "CHECK";
 
-static void PrintDeclExtent(CXDecl Dcl) {
-  CXSourceRange extent; 
-  if (!Dcl)
+static void PrintCursorExtent(CXCursor C) {
+  CXSourceRange extent = clang_getCursorExtent(C);
+  /* FIXME: Better way to check for empty extents? */
+  if (!extent.begin.file)
     return;
-  extent = clang_getDeclExtent(Dcl);
   printf(" [Extent=%d:%d:%d:%d]", extent.begin.line, extent.begin.column,
          extent.end.line, extent.end.column);
 }
@@ -89,8 +89,8 @@
     if (!source)
       source = "<invalid loc>";  
     printf("// %s: %s:%d:%d: ", FileCheckPrefix, source, Loc.line, Loc.column);
-    PrintCursor(Cursor);    
-    PrintDeclExtent(clang_getCursorDecl(Cursor));
+    PrintCursor(Cursor);
+    PrintCursorExtent(Cursor);
 
     printf("\n");
   }
@@ -111,7 +111,7 @@
       return;
     }
     
-    PrintDeclExtent(D);
+    PrintCursorExtent(Cursor);
     printf("\n");    
     clang_loadDeclaration(D, DeclVisitor, 0);
   }
@@ -173,7 +173,7 @@
       return;
     }
     printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), USR.Spelling);
-    PrintDeclExtent(clang_getCursorDecl(C));
+    PrintCursorExtent(C);
     printf("\n");
     clang_disposeString(USR);
   }





More information about the cfe-commits mailing list