[PATCH] D20125: [libclang] Added clang_getRealSpellingLocation to compensate for clang_getSpellingLocation returning the expansion location

Cameron via cfe-commits cfe-commits at lists.llvm.org
Tue May 10 12:59:49 PDT 2016


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.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D20125.56782.patch
Type: text/x-patch
Size: 3379 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160510/7d2d6cf0/attachment-0001.bin>


More information about the cfe-commits mailing list