cameron314 created this revision.
cameron314 added a reviewer: rsmith.
cameron314 added a subscriber: cfe-commits.

All the libclang functions for expanding a location, namely 
`clang_getExpansionLocation`, `clang_getPresumedLocation`, 
`clang_getInstantiationLocation`, and most surprisingly 
`clang_getSpellingLocation` return expansion locations, not spelling locations. 
As it turns out, there is no way to get a spelling location via libclang. This 
patch adds such a function.

Note that there's a FIXME in `clang_getSpellingLocation` about this, but 
changing `clang_getSpellingLocation` to actually return a spelling location 
would almost certainly break a large body of existing (third-party) code, 
mostly in subtle ways. I think it's better to introduce a new function, though 
I know it's ugly. But, this is what we've been using for the past year, and 
we've gotten quite comfortable with it.

http://reviews.llvm.org/D20125

Files:
  include/clang-c/Index.h
  tools/libclang/CXSourceLocation.cpp

Index: tools/libclang/CXSourceLocation.cpp
===================================================================
--- tools/libclang/CXSourceLocation.cpp
+++ tools/libclang/CXSourceLocation.cpp
@@ -346,6 +346,42 @@
     *offset = FileOffset;
 }
 
+void clang_getRealSpellingLocation(CXSourceLocation location,
+                                   CXFile *file,
+                                   unsigned *line,
+                                   unsigned *column,
+                                   unsigned *offset) {
+
+  if (!isASTUnitSourceLocation(location)) {
+    CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
+    return;
+  }
+
+  SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+  if (!location.ptr_data[0] || Loc.isInvalid())
+    return createNullLocation(file, line, column, offset);
+
+  const SourceManager &SM =
+  *static_cast<const SourceManager*>(location.ptr_data[0]);
+  SourceLocation SpellLoc = SM.getSpellingLoc(Loc);
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
+  FileID FID = LocInfo.first;
+  unsigned FileOffset = LocInfo.second;
+
+  if (FID.isInvalid())
+    return createNullLocation(file, line, column, offset);
+
+  if (file)
+    *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
+  if (line)
+    *line = SM.getLineNumber(FID, FileOffset);
+  if (column)
+    *column = SM.getColumnNumber(FID, FileOffset);
+  if (offset)
+    *offset = FileOffset;
+}
+
 void clang_getFileLocation(CXSourceLocation location,
                            CXFile *file,
                            unsigned *line,
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -568,6 +568,36 @@
  * \brief Retrieve the file, line, column, and offset represented by
  * the given source location.
  *
+ * If the location refers into a macro instantiation, return where the
+ * location was originally spelled in the source file (i.e. where the token
+ * text is located). clang_getSpellingLocation() is supposed to do this
+ * but doesn't, hence this function.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the 
given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+CINDEX_LINKAGE void clang_getRealSpellingLocation(CXSourceLocation location,
+                                                  CXFile *file,
+                                                  unsigned *line,
+                                                  unsigned *column,
+                                                  unsigned *offset);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
  * If the location refers into a macro expansion, return where the macro was
  * expanded or where the macro argument was written, if the location points at
  * a macro argument.


Index: tools/libclang/CXSourceLocation.cpp
===================================================================
--- tools/libclang/CXSourceLocation.cpp
+++ tools/libclang/CXSourceLocation.cpp
@@ -346,6 +346,42 @@
     *offset = FileOffset;
 }
 
+void clang_getRealSpellingLocation(CXSourceLocation location,
+                                   CXFile *file,
+                                   unsigned *line,
+                                   unsigned *column,
+                                   unsigned *offset) {
+
+  if (!isASTUnitSourceLocation(location)) {
+    CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
+    return;
+  }
+
+  SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+  if (!location.ptr_data[0] || Loc.isInvalid())
+    return createNullLocation(file, line, column, offset);
+
+  const SourceManager &SM =
+  *static_cast<const SourceManager*>(location.ptr_data[0]);
+  SourceLocation SpellLoc = SM.getSpellingLoc(Loc);
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
+  FileID FID = LocInfo.first;
+  unsigned FileOffset = LocInfo.second;
+
+  if (FID.isInvalid())
+    return createNullLocation(file, line, column, offset);
+
+  if (file)
+    *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
+  if (line)
+    *line = SM.getLineNumber(FID, FileOffset);
+  if (column)
+    *column = SM.getColumnNumber(FID, FileOffset);
+  if (offset)
+    *offset = FileOffset;
+}
+
 void clang_getFileLocation(CXSourceLocation location,
                            CXFile *file,
                            unsigned *line,
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -568,6 +568,36 @@
  * \brief Retrieve the file, line, column, and offset represented by
  * the given source location.
  *
+ * If the location refers into a macro instantiation, return where the
+ * location was originally spelled in the source file (i.e. where the token
+ * text is located). clang_getSpellingLocation() is supposed to do this
+ * but doesn't, hence this function.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+CINDEX_LINKAGE void clang_getRealSpellingLocation(CXSourceLocation location,
+                                                  CXFile *file,
+                                                  unsigned *line,
+                                                  unsigned *column,
+                                                  unsigned *offset);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
  * If the location refers into a macro expansion, return where the macro was
  * expanded or where the macro argument was written, if the location points at
  * a macro argument.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to