[clang] [libclang] Compute the right spelling location (PR #72400)
Sebastian Poeplau via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 22 01:25:33 PDT 2024
https://github.com/sebastianpoeplau updated https://github.com/llvm/llvm-project/pull/72400
>From cc15f9bb8b37fb1b68bd33241ab37e98d57d274c Mon Sep 17 00:00:00 2001
From: Matthieu Eyraud <eyraud at adacore.com>
Date: Mon, 11 Apr 2022 16:53:24 +0200
Subject: [PATCH] [libclang] Compute the right spelling location
Locations inside macro expansions have different spelling/expansion
locations. Apply a FIXME to make the libclang function
clang_getSpellingLocation return the right spelling location, and adapt
the testsuite driver code to use the file location rather than the
spelling location to compute source ranges.
---
clang/docs/ReleaseNotes.rst | 3 ++
clang/tools/c-index-test/c-index-test.c | 54 +++++++++++------------
clang/tools/libclang/CXSourceLocation.cpp | 3 +-
clang/unittests/libclang/LibclangTest.cpp | 31 +++++++++++++
4 files changed, 61 insertions(+), 30 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3fe15934323c53..6fdc285da6ecd3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -678,6 +678,9 @@ clang-format
libclang
--------
+- ``clang_getSpellingLocation`` now correctly resolves macro expansions; that
+ is, it returns the spelling location instead of the expansion location.
+
Static Analyzer
---------------
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 21619888cfa5f3..e078e9bdce027a 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -464,10 +464,10 @@ static void PrintRange(CXSourceRange R, const char *str) {
CXFile begin_file, end_file;
unsigned begin_line, begin_column, end_line, end_column;
- clang_getSpellingLocation(clang_getRangeStart(R),
- &begin_file, &begin_line, &begin_column, 0);
- clang_getSpellingLocation(clang_getRangeEnd(R),
- &end_file, &end_line, &end_column, 0);
+ clang_getFileLocation(clang_getRangeStart(R), &begin_file, &begin_line,
+ &begin_column, 0);
+ clang_getFileLocation(clang_getRangeEnd(R), &end_file, &end_line, &end_column,
+ 0);
if (!begin_file || !end_file)
return;
@@ -849,13 +849,13 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
printf(", ");
Loc = clang_getCursorLocation(Ovl);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
+ clang_getFileLocation(Loc, 0, &line, &column, 0);
printf("%d:%d", line, column);
}
printf("]");
} else {
CXSourceLocation Loc = clang_getCursorLocation(Referenced);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
+ clang_getFileLocation(Loc, 0, &line, &column, 0);
printf(":%d:%d", line, column);
}
@@ -1047,7 +1047,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {
CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);
CXString Name = clang_getCursorSpelling(SpecializationOf);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
+ clang_getFileLocation(Loc, 0, &line, &column, 0);
printf(" [Specialization of %s:%d:%d]",
clang_getCString(Name), line, column);
clang_disposeString(Name);
@@ -1094,7 +1094,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
printf(" [Overrides ");
for (I = 0; I != num_overridden; ++I) {
CXSourceLocation Loc = clang_getCursorLocation(overridden[I]);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
+ clang_getFileLocation(Loc, 0, &line, &column, 0);
lineCols[I].line = line;
lineCols[I].col = column;
}
@@ -1257,8 +1257,8 @@ void PrintDiagnostic(CXDiagnostic Diagnostic) {
fprintf(stderr, "%s\n", clang_getCString(Msg));
clang_disposeString(Msg);
- clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
- &file, 0, 0, 0);
+ clang_getFileLocation(clang_getDiagnosticLocation(Diagnostic), &file, 0, 0,
+ 0);
if (!file)
return;
@@ -1271,9 +1271,8 @@ void PrintDiagnostic(CXDiagnostic Diagnostic) {
CXSourceLocation end = clang_getRangeEnd(range);
unsigned start_line, start_column, end_line, end_column;
CXFile start_file, end_file;
- clang_getSpellingLocation(start, &start_file, &start_line,
- &start_column, 0);
- clang_getSpellingLocation(end, &end_file, &end_line, &end_column, 0);
+ clang_getFileLocation(start, &start_file, &start_line, &start_column, 0);
+ clang_getFileLocation(end, &end_file, &end_line, &end_column, 0);
if (clang_equalLocations(start, end)) {
/* Insertion. */
if (start_file == file)
@@ -1356,7 +1355,7 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
CXSourceLocation Loc = clang_getCursorLocation(Cursor);
unsigned line, column;
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
+ clang_getFileLocation(Loc, 0, &line, &column, 0);
printf("// %s: %s:%d:%d: ", FileCheckPrefix,
GetCursorSource(Cursor), line, column);
PrintCursor(Cursor, Data->CommentSchemaFile);
@@ -1417,7 +1416,7 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
curColumn++;
Loc = clang_getCursorLocation(Cursor);
- clang_getSpellingLocation(Loc, &file, 0, 0, 0);
+ clang_getFileLocation(Loc, &file, 0, 0, 0);
source = clang_getFileName(file);
if (clang_getCString(source)) {
@@ -1483,8 +1482,7 @@ void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack,
for (i = 0; i < includeStackLen; ++i) {
CXFile includingFile;
unsigned line, column;
- clang_getSpellingLocation(includeStack[i], &includingFile, &line,
- &column, 0);
+ clang_getFileLocation(includeStack[i], &includingFile, &line, &column, 0);
fname = clang_getFileName(includingFile);
printf(" %s:%d:%d\n", clang_getCString(fname), line, column);
clang_disposeString(fname);
@@ -2984,7 +2982,7 @@ static void inspect_print_cursor(CXCursor Cursor) {
CXString Spelling;
const char *cspell;
unsigned line, column;
- clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
+ clang_getFileLocation(CursorLoc, 0, &line, &column, 0);
printf("%d:%d ", line, column);
PrintCursor(Cursor, NULL);
PrintCursorExtent(Cursor);
@@ -3100,7 +3098,7 @@ static void inspect_evaluate_cursor(CXCursor Cursor) {
unsigned line, column;
CXEvalResult ER;
- clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
+ clang_getFileLocation(CursorLoc, 0, &line, &column, 0);
printf("%d:%d ", line, column);
PrintCursor(Cursor, NULL);
PrintCursorExtent(Cursor);
@@ -3135,7 +3133,7 @@ static void inspect_macroinfo_cursor(CXCursor Cursor) {
CXString Spelling;
const char *cspell;
unsigned line, column;
- clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
+ clang_getFileLocation(CursorLoc, 0, &line, &column, 0);
printf("%d:%d ", line, column);
PrintCursor(Cursor, NULL);
PrintCursorExtent(Cursor);
@@ -4328,10 +4326,10 @@ int perform_token_annotation(int argc, const char **argv) {
skipped_ranges = clang_getSkippedRanges(TU, file);
for (i = 0; i != skipped_ranges->count; ++i) {
unsigned start_line, start_column, end_line, end_column;
- clang_getSpellingLocation(clang_getRangeStart(skipped_ranges->ranges[i]),
- 0, &start_line, &start_column, 0);
- clang_getSpellingLocation(clang_getRangeEnd(skipped_ranges->ranges[i]),
- 0, &end_line, &end_column, 0);
+ clang_getFileLocation(clang_getRangeStart(skipped_ranges->ranges[i]), 0,
+ &start_line, &start_column, 0);
+ clang_getFileLocation(clang_getRangeEnd(skipped_ranges->ranges[i]), 0,
+ &end_line, &end_column, 0);
printf("Skipping: ");
PrintExtent(stdout, start_line, start_column, end_line, end_column);
printf("\n");
@@ -4351,10 +4349,10 @@ int perform_token_annotation(int argc, const char **argv) {
case CXToken_Literal: kind = "Literal"; break;
case CXToken_Comment: kind = "Comment"; break;
}
- clang_getSpellingLocation(clang_getRangeStart(extent),
- 0, &start_line, &start_column, 0);
- clang_getSpellingLocation(clang_getRangeEnd(extent),
- 0, &end_line, &end_column, 0);
+ clang_getFileLocation(clang_getRangeStart(extent), 0, &start_line,
+ &start_column, 0);
+ clang_getFileLocation(clang_getRangeEnd(extent), 0, &end_line, &end_column,
+ 0);
printf("%s: \"%s\" ", kind, clang_getCString(spelling));
clang_disposeString(spelling);
PrintExtent(stdout, start_line, start_column, end_line, end_column);
diff --git a/clang/tools/libclang/CXSourceLocation.cpp b/clang/tools/libclang/CXSourceLocation.cpp
index ba70cbfee8995f..53cb71f7276f29 100644
--- a/clang/tools/libclang/CXSourceLocation.cpp
+++ b/clang/tools/libclang/CXSourceLocation.cpp
@@ -319,8 +319,7 @@ void clang_getSpellingLocation(CXSourceLocation location,
const SourceManager &SM =
*static_cast<const SourceManager*>(location.ptr_data[0]);
- // FIXME: This should call SourceManager::getSpellingLoc().
- SourceLocation SpellLoc = SM.getFileLoc(Loc);
+ SourceLocation SpellLoc = SM.getSpellingLoc(Loc);
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second;
diff --git a/clang/unittests/libclang/LibclangTest.cpp b/clang/unittests/libclang/LibclangTest.cpp
index 87075a46d75187..6de4d02bf74f4f 100644
--- a/clang/unittests/libclang/LibclangTest.cpp
+++ b/clang/unittests/libclang/LibclangTest.cpp
@@ -1292,6 +1292,37 @@ void func() {}
EXPECT_EQ(attrCount, 1);
}
+TEST_F(LibclangParseTest, clang_getSpellingLocation) {
+ std::string fileName = "main.c";
+ WriteFile(fileName, "#define X(value) int x = value;\nX(42)\n");
+
+ ClangTU = clang_parseTranslationUnit(Index, fileName.c_str(), nullptr, 0,
+ nullptr, 0, TUFlags);
+
+ int declarationCount = 0;
+ Traverse([&declarationCount](CXCursor cursor,
+ CXCursor parent) -> CXChildVisitResult {
+ if (cursor.kind == CXCursor_VarDecl) {
+ declarationCount++;
+
+ CXSourceLocation cxl = clang_getCursorLocation(cursor);
+ unsigned line;
+
+ // We expect clang_getFileLocation to return the expansion location,
+ // whereas clang_getSpellingLocation should resolve the macro expansion
+ // and return the location of the macro definition.
+ clang_getFileLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(line, 2U);
+ clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+ EXPECT_EQ(line, 1U);
+ }
+
+ return CXChildVisit_Recurse;
+ });
+
+ EXPECT_EQ(declarationCount, 1);
+}
+
class LibclangRewriteTest : public LibclangParseTest {
public:
CXRewriter Rew = nullptr;
More information about the cfe-commits
mailing list