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

Douglas Gregor dgregor at apple.com
Tue Jan 19 13:36:56 PST 2010


Author: dgregor
Date: Tue Jan 19 15:36:55 2010
New Revision: 93915

URL: http://llvm.org/viewvc/llvm-project?rev=93915&view=rev
Log:
Rework the CXSourceLocation and CXSourceRange APIs. They are now
opaque data structures accessed through the new functions
clang_getInstantiationLocation(), clang_getRangeStart(), and
clang_getRangeEnd(). The new API permits later extensions to introduce
new functions to allow CIndex clients to walk macro instantiations, if
we ever care.


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=93915&r1=93914&r2=93915&view=diff

==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue Jan 19 15:36:55 2010
@@ -333,27 +333,62 @@
 CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl); /* deprecate */
 
 /**
- * \brief Identifies a specific source location given its file, line, and 
- * column.
+ * \brief Identifies a specific source location within a translation
+ * unit.
+ *
+ * Use clang_getInstantiationLocation() to map a source location to a
+ * particular file, line, and column.
  */
 typedef struct {
-  CXFile file;
-  unsigned line;
-  unsigned column;
+  void *ptr_data;
+  unsigned int_data;
 } CXSourceLocation;
 
 /**
- * \brief Identifies a range of source locations identified by the starting and
- * ending locations of that range.
+ * \brief Identifies a range of source locations in the source code.
  *
- * The \c begin location points to the first character in the range and the
- * \c end location points to the last character in the range.
+ * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
+ * starting and end locations from a source range, respectively.
  */
 typedef struct {
-  CXSourceLocation begin;
-  CXSourceLocation end;
+  void *ptr_data;
+  unsigned begin_int_data;
+  unsigned end_int_data;
 } CXSourceRange;
 
+/**
+ * \brief Retrieve the file, line, and column represented by the
+ * given source location.
+ *
+ * \param location the location within a source file that will be
+ * decomposed into its parts.
+ *
+ * \param file if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column if non-NULL, will be set to the column to which the
+ * given source location points.
+ */
+CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
+                                                   CXFile *file,
+                                                   unsigned *line,
+                                                   unsigned *column);
+
+/**
+ * \brief Retrieve a source location representing the first
+ * character within a source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
+
+/**
+ * \brief Retrieve a source location representing the last
+ * character within a source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
+
 /* clang_getDeclExtent() returns the physical extent of a declaration.  The
  * beginning line/column pair points to the start of the first token in the
  * declaration, and the ending line/column pair points to the last character in

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

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Tue Jan 19 15:36:55 2010
@@ -113,9 +113,17 @@
 #endif
 #endif
 
+typedef llvm::PointerIntPair<ASTContext *, 1, bool> CXSourceLocationPtr;
+
 /// \brief Translate a Clang source location into a CIndex source location.
-static CXSourceLocation translateSourceLocation(SourceManager &SourceMgr,
-                                                SourceLocation Loc) {
+static CXSourceLocation translateSourceLocation(ASTContext &Context,
+                                                SourceLocation Loc,
+                                                bool AtEnd = false) {
+  CXSourceLocationPtr Ptr(&Context, AtEnd);
+  CXSourceLocation Result = { Ptr.getOpaqueValue(), Loc.getRawEncoding() };
+  return Result;
+
+#if 0
   SourceLocation InstLoc = SourceMgr.getInstantiationLoc(Loc);
   if (InstLoc.isInvalid()) {
       CXSourceLocation Loc = { 0, 0, 0 };
@@ -128,11 +136,16 @@
   Result.line = SourceMgr.getInstantiationLineNumber(InstLoc);
   Result.column = SourceMgr.getInstantiationColumnNumber(InstLoc);
   return Result;
+#endif
 }
 
 /// \brief Translate a Clang source range into a CIndex source range.
-static CXSourceRange translateSourceRange(ASTContext &Context,
-                                          SourceRange R) {
+static CXSourceRange translateSourceRange(ASTContext &Context, SourceRange R) {
+  CXSourceRange Result = { &Context, 
+                           R.getBegin().getRawEncoding(),
+                           R.getEnd().getRawEncoding() };
+  return Result;
+#if 0
   if (R.isInvalid()) {
     CXSourceRange extent = { { 0, 0, 0 }, { 0, 0, 0 } };
     return extent;
@@ -177,8 +190,10 @@
   CXSourceRange extent = { { (void *)BeginFile, StartLineNo, StartColNo },
                            { (void *)EndFile, EndLineNo, EndColNo } };
   return extent;  
+#endif
 }
 
+
 //===----------------------------------------------------------------------===//
 // Visitors.
 //===----------------------------------------------------------------------===//
@@ -607,6 +622,80 @@
 } // end: extern "C"
 
 //===----------------------------------------------------------------------===//
+// CXSourceLocation and CXSourceRange Operations.
+//===----------------------------------------------------------------------===//
+
+void clang_getInstantiationLocation(CXSourceLocation location,
+                                    CXFile *file,
+                                    unsigned *line,
+                                    unsigned *column) {
+  CXSourceLocationPtr Ptr
+    = CXSourceLocationPtr::getFromOpaqueValue(location.ptr_data);
+  SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+  if (!Ptr.getPointer() || Loc.isInvalid()) {
+    if (file)
+      *file = 0;
+    if (line)
+      *line = 0;
+    if (column)
+      *column = 0;
+    return;
+  }
+
+  // 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.  
+  ASTContext &Context = *Ptr.getPointer();
+  SourceManager &SM = Context.getSourceManager();
+  SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
+  
+  if (Ptr.getInt()) {
+    // We want the last character in this location, so we will adjust
+    // the instantiation location accordingly.
+
+    // If the location is from a macro instantiation, get the end of
+    // the instantiation range.
+    if (Loc.isMacroID())
+      InstLoc = SM.getInstantiationRange(Loc).second;
+
+    // Measure the length token we're pointing at, so we can adjust
+    // the physical location in the file to point at the last
+    // character.
+    // FIXME: This won't cope with trigraphs or escaped newlines
+    // well. For that, we actually need a preprocessor, which isn't
+    // currently available here. Eventually, we'll switch the pointer
+    // data of CXSourceLocation/CXSourceRange to a translation unit
+    // (CXXUnit), so that the preprocessor will be available here. At
+    // that point, we can use Preprocessor::getLocForEndOfToken().
+    unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM, 
+                                                Context.getLangOptions());
+    if (Length > 0)
+      InstLoc = InstLoc.getFileLocWithOffset(Length - 1);
+  }
+
+  if (file)
+    *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc));
+  if (line)
+    *line = SM.getInstantiationLineNumber(InstLoc);
+  if (column)
+    *column = SM.getInstantiationColumnNumber(InstLoc);
+}
+
+CXSourceLocation clang_getRangeStart(CXSourceRange range) {
+  CXSourceLocation Result = { range.ptr_data, range.begin_int_data };
+  return Result;
+}
+
+CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
+  llvm::PointerIntPair<ASTContext *, 1, bool> Ptr;
+  Ptr.setPointer(static_cast<ASTContext *>(range.ptr_data));
+  Ptr.setInt(true);
+  CXSourceLocation Result = { Ptr.getOpaqueValue(), range.end_int_data };
+  return Result;
+}
+
+//===----------------------------------------------------------------------===//
 // CXDecl Operations.
 //===----------------------------------------------------------------------===//
 
@@ -896,22 +985,19 @@
     case CXCursor_ObjCSuperClassRef: {       
       std::pair<ObjCInterfaceDecl *, SourceLocation> P
         = getCursorObjCSuperClassRef(C);
-      SourceManager &SM = P.first->getASTContext().getSourceManager();
-      return translateSourceLocation(SM, P.second);
+      return translateSourceLocation(P.first->getASTContext(), P.second);
     }
 
     case CXCursor_ObjCProtocolRef: {       
       std::pair<ObjCProtocolDecl *, SourceLocation> P
         = getCursorObjCProtocolRef(C);
-      SourceManager &SM = P.first->getASTContext().getSourceManager();
-      return translateSourceLocation(SM, P.second);
+      return translateSourceLocation(P.first->getASTContext(), P.second);
     }
 
     case CXCursor_ObjCClassRef: {       
       std::pair<ObjCInterfaceDecl *, SourceLocation> P
         = getCursorObjCClassRef(C);
-      SourceManager &SM = P.first->getASTContext().getSourceManager();
-      return translateSourceLocation(SM, P.second);
+      return translateSourceLocation(P.first->getASTContext(), P.second);
     }
       
     case CXCursor_ObjCSelectorRef:
@@ -921,16 +1007,16 @@
     case CXCursor_EnumConstantRef:
     case CXCursor_MemberRef: {
       Expr *E = getCursorExpr(C);
-      SourceManager &SM = getCursorContext(C).getSourceManager();
+      ASTContext &Context = getCursorContext(C);
       if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
-        return translateSourceLocation(SM, /*FIXME:*/Msg->getLeftLoc());
+        return translateSourceLocation(Context, /*FIXME:*/Msg->getLeftLoc());
       if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
-        return translateSourceLocation(SM, DRE->getLocation());
+        return translateSourceLocation(Context, DRE->getLocation());
       if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
-        return translateSourceLocation(SM, Member->getMemberLoc());
+        return translateSourceLocation(Context, Member->getMemberLoc());
       if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
-        return translateSourceLocation(SM, Ivar->getLocation());
-      return translateSourceLocation(SM, E->getLocStart());
+        return translateSourceLocation(Context, Ivar->getLocation());
+      return translateSourceLocation(Context, E->getLocStart());
     }
         
     default:
@@ -940,16 +1026,15 @@
   }
   
   if (!getCursorDecl(C)) {
-    CXSourceLocation empty = { 0, 0, 0 };
+    CXSourceLocation empty = { 0, 0 };
     return empty;
   }
 
   Decl *D = getCursorDecl(C);
-  SourceManager &SM = D->getASTContext().getSourceManager();
   SourceLocation Loc = D->getLocation();
   if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
     Loc = Class->getClassLoc();
-  return translateSourceLocation(SM, Loc);
+  return translateSourceLocation(D->getASTContext(), Loc);
 }
 
 CXSourceRange clang_getCursorExtent(CXCursor C) {
@@ -990,7 +1075,7 @@
   }
   
   if (!getCursorDecl(C)) {
-    CXSourceRange empty = { { 0, 0, 0 }, { 0, 0, 0 } };
+    CXSourceRange empty = { 0, 0, 0 };
     return empty;
   }
   

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

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.exports (original)
+++ cfe/trunk/tools/CIndex/CIndex.exports Tue Jan 19 15:36:55 2010
@@ -34,8 +34,11 @@
 _clang_getEntityFromDecl
 _clang_getFileName
 _clang_getFileTime
+_clang_getInstantiationLocation
 _clang_getNullCursor
 _clang_getNumCompletionChunks
+_clang_getRangeEnd
+_clang_getRangeStart
 _clang_getTranslationUnitSpelling
 _clang_isCursorDefinition
 _clang_isDeclaration

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=93915&r1=93914&r2=93915&view=diff

==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Tue Jan 19 15:36:55 2010
@@ -49,6 +49,7 @@
   else {
     CXString string;
     CXCursor Referenced;
+    unsigned line, column;
     string = clang_getCursorSpelling(Cursor);
     printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind),
                       clang_getCString(string));
@@ -57,7 +58,8 @@
     Referenced = clang_getCursorReferenced(Cursor);
     if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
       CXSourceLocation Loc = clang_getCursorLocation(Referenced);
-      printf(":%d:%d", Loc.line, Loc.column);
+      clang_getInstantiationLocation(Loc, 0, &line, &column);
+      printf(":%d:%d", line, column);
     }
 
     if (clang_isCursorDefinition(Cursor))
@@ -66,7 +68,11 @@
 }
 
 static const char* GetCursorSource(CXCursor Cursor) {  
-  const char *source = clang_getFileName(clang_getCursorLocation(Cursor).file);
+  CXSourceLocation Loc = clang_getCursorLocation(Cursor);
+  const char *source;
+  CXFile file;
+  clang_getInstantiationLocation(Loc, &file, 0, 0);
+  source = clang_getFileName(file);
   if (!source)
     return "<invalid loc>";  
   return basename(source);
@@ -80,20 +86,31 @@
 
 static void PrintCursorExtent(CXCursor C) {
   CXSourceRange extent = clang_getCursorExtent(C);
-  /* FIXME: Better way to check for empty extents? */
-  if (!extent.begin.file)
+  CXFile begin_file, end_file;
+  unsigned begin_line, begin_column, end_line, end_column;
+  
+  clang_getInstantiationLocation(clang_getRangeStart(extent),
+                                 &begin_file, &begin_line, &begin_column);
+  clang_getInstantiationLocation(clang_getRangeEnd(extent),
+                                 &end_file, &end_line, &end_column);
+  if (!begin_file || !end_file)
     return;
-  printf(" [Extent=%d:%d:%d:%d]", extent.begin.line, extent.begin.column,
-         extent.end.line, extent.end.column);
+
+  printf(" [Extent=%d:%d:%d:%d]", begin_line, begin_column,
+         end_line, end_column);
 }
 
 static void DeclVisitor(CXDecl Dcl, CXCursor Cursor, CXClientData Filter) {
   if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
     CXSourceLocation Loc = clang_getCursorLocation(Cursor);
-    const char *source = clang_getFileName(Loc.file);
+    CXFile file;
+    unsigned line, column;
+    const char *source;
+    clang_getInstantiationLocation(Loc, &file, &line, &column);
+    source = clang_getFileName(file);
     if (!source)
       source = "<invalid loc>";  
-    printf("// %s: %s:%d:%d: ", FileCheckPrefix, source, Loc.line, Loc.column);
+    printf("// %s: %s:%d:%d: ", FileCheckPrefix, source, line, column);
     PrintCursor(Cursor);
     PrintCursorExtent(Cursor);
 
@@ -106,8 +123,10 @@
   if (!Filter || (Cursor.kind == *(enum CXCursorKind *)Filter)) {
     CXDecl D;
     CXSourceLocation Loc = clang_getCursorLocation(Cursor);
+    unsigned line, column;
+    clang_getInstantiationLocation(Loc, 0, &line, &column);
     printf("// %s: %s:%d:%d: ", FileCheckPrefix,
-           GetCursorSource(Cursor), Loc.line, Loc.column);
+           GetCursorSource(Cursor), line, column);
     PrintCursor(Cursor);
     
     D = clang_getCursorDecl(Cursor);
@@ -141,6 +160,7 @@
 
   while (startBuf < endBuf) {
     CXSourceLocation Loc;
+    CXFile file;
     const char *source = 0;
     
     if (*startBuf == '\n') {
@@ -151,7 +171,8 @@
       curColumn++;
           
     Loc = clang_getCursorLocation(Cursor);
-    source = clang_getFileName(Loc.file);
+    clang_getInstantiationLocation(Loc, &file, 0, 0);
+    source = clang_getFileName(file);
     if (source) {
       Ref = clang_getCursor(Unit, source, curLine, curColumn);
       if (Ref.kind == CXCursor_NoDeclFound) {





More information about the cfe-commits mailing list