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