Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions clang/lib/Tooling/Transformer/SourceCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,39 @@ llvm::Error clang::tooling::validateEditRange(const CharSourceRange &Range,
return validateRange(Range, SM, /*AllowSystemHeaders=*/false);
}

static bool spelledInMacroDefinition(SourceLocation Loc,
const SourceManager &SM) {
// Returns the location of the top-level macro argument that is the spelling for
// the expansion `Loc` is from. If `Loc` is spelled in the macro definition,
// returns an invalid `SourceLocation`.
static SourceLocation getMacroArgumentSpellingLoc(SourceLocation Loc,
const SourceManager &SM) {
assert(Loc.isMacroID() && "Location must be in a macro");
while (Loc.isMacroID()) {
const auto &Expansion = SM.getSLocEntry(SM.getFileID(Loc)).getExpansion();
if (Expansion.isMacroArgExpansion()) {
// Check the spelling location of the macro arg, in case the arg itself is
// in a macro expansion.
Loc = Expansion.getSpellingLoc();
} else {
return true;
return {};
}
}
return Loc;
}

static bool spelledInMacroDefinition(CharSourceRange Range,
const SourceManager &SM) {
if (Range.getBegin().isMacroID() && Range.getEnd().isMacroID()) {
// Check whether the range is entirely within a single macro argument.
auto B = getMacroArgumentSpellingLoc(Range.getBegin(), SM);
auto E = getMacroArgumentSpellingLoc(Range.getEnd(), SM);
return B.isInvalid() || B != E;
}

if (Range.getBegin().isMacroID())
return getMacroArgumentSpellingLoc(Range.getBegin(), SM).isInvalid();
if (Range.getEnd().isMacroID())
return getMacroArgumentSpellingLoc(Range.getEnd(), SM).isInvalid();

return false;
}

Expand Down Expand Up @@ -158,8 +179,7 @@ static CharSourceRange getRange(const CharSourceRange &EditRange,
Range = Lexer::makeFileCharRange(EditRange, SM, LangOpts);
} else {
auto AdjustedRange = getRangeForSplitTokens(EditRange, SM, LangOpts);
if (spelledInMacroDefinition(AdjustedRange.getBegin(), SM) ||
spelledInMacroDefinition(AdjustedRange.getEnd(), SM))
if (spelledInMacroDefinition(AdjustedRange, SM))
return {};

auto B = SM.getSpellingLoc(AdjustedRange.getBegin());
Expand Down
2 changes: 2 additions & 0 deletions clang/unittests/Tooling/SourceCodeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,12 @@ TEST(SourceCodeTest, EditInvolvingExpansionIgnoringExpansionShouldFail) {
#define M1(x) x(1)
#define M2(x, y) x ## y
#define M3(x) foobar(x)
#define M4(x, y) x y
int foobar(int);
int a = M1(foobar);
int b = M2(foo, bar(2));
int c = M3(3);
int d = M4(foobar, (4));
)cpp");

CallsVisitor Visitor;
Expand Down
Loading