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(location.ptr_data[0]); + SourceLocation SpellLoc = SM.getSpellingLoc(Loc); + std::pair 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(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,