Skip to content

Commit

Permalink
[libclang] Compute the right spelling location (#72400)
Browse files Browse the repository at this point in the history
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.

Co-authored-by: Matthieu Eyraud <eyraud@adacore.com>
  • Loading branch information
sebastianpoeplau and Jugst3r committed Apr 24, 2024
1 parent b8f3024 commit 2e770ed
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 30 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,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
---------------

Expand Down
54 changes: 26 additions & 28 deletions clang/tools/c-index-test/c-index-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand All @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions clang/tools/libclang/CXSourceLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
31 changes: 31 additions & 0 deletions clang/unittests/libclang/LibclangTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 2e770ed

Please sign in to comment.