ymandel updated this revision to Diff 298392.
ymandel added a comment.
cleaned up test code
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D89468/new/
https://reviews.llvm.org/D89468
Files:
clang/lib/Tooling/Transformer/RangeSelector.cpp
clang/unittests/Tooling/RangeSelectorTest.cpp
Index: clang/unittests/Tooling/RangeSelectorTest.cpp
===================================================================
--- clang/unittests/Tooling/RangeSelectorTest.cpp
+++ clang/unittests/Tooling/RangeSelectorTest.cpp
@@ -193,6 +193,65 @@
HasValue(EqualsCharSourceRange(ExpectedAfter)));
}
+// Gets the spelling location `Length` characters after the start of AST node
+// `Id`.
+static SourceLocation getSpellingLocAfter(const MatchResult &Result,
+ StringRef Id, int Length) {
+ const auto *E = Result.Nodes.getNodeAs<Expr>(Id);
+ assert(E != nullptr);
+ return Result.SourceManager->getSpellingLoc(E->getBeginLoc())
+ .getLocWithOffset(Length);
+}
+
+// Test with a range that is the entire macro arg, but does not end the
+// expansion itself.
+TEST(RangeSelectorTest, AfterOpInMacroArg) {
+ StringRef Code = R"cc(
+#define ISNULL(x) x == nullptr
+ bool g() { int* y; return ISNULL(y); }
+ )cc";
+
+ TestMatch Match =
+ matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
+ int YVarLen = 1;
+ SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);
+ CharSourceRange Expected = CharSourceRange::getCharRange(After, After);
+ EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),
+ HasValue(EqualsCharSourceRange(Expected)));
+}
+
+// Test with a range that is the entire macro arg and ends the expansion itself.
+TEST(RangeSelectorTest, AfterOpInMacroArgEndsExpansion) {
+ StringRef Code = R"cc(
+#define ISNULL(x) nullptr == x
+ bool g() { int* y; return ISNULL(y); }
+ )cc";
+
+ TestMatch Match =
+ matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
+ int YVarLen = 1;
+ SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);
+ CharSourceRange Expected = CharSourceRange::getCharRange(After, After);
+ EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),
+ HasValue(EqualsCharSourceRange(Expected)));
+}
+
+TEST(RangeSelectorTest, AfterOpInPartOfMacroArg) {
+ StringRef Code = R"cc(
+#define ISNULL(x) x == nullptr
+ int* f(int*);
+ bool g() { int* y; return ISNULL(f(y)); }
+ )cc";
+
+ TestMatch Match =
+ matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
+ int YVarLen = 1;
+ SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);
+ CharSourceRange Expected = CharSourceRange::getCharRange(After, After);
+ EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),
+ HasValue(EqualsCharSourceRange(Expected)));
+}
+
TEST(RangeSelectorTest, BetweenOp) {
StringRef Code = R"cc(
int f(int x, int y, int z) { return 3; }
Index: clang/lib/Tooling/Transformer/RangeSelector.cpp
===================================================================
--- clang/lib/Tooling/Transformer/RangeSelector.cpp
+++ clang/lib/Tooling/Transformer/RangeSelector.cpp
@@ -116,11 +116,24 @@
Expected<CharSourceRange> SelectedRange = Selector(Result);
if (!SelectedRange)
return SelectedRange.takeError();
- if (SelectedRange->isCharRange())
- return CharSourceRange::getCharRange(SelectedRange->getEnd());
- return CharSourceRange::getCharRange(Lexer::getLocForEndOfToken(
- SelectedRange->getEnd(), 0, Result.Context->getSourceManager(),
- Result.Context->getLangOpts()));
+ SourceLocation End = SelectedRange->getEnd();
+ if (SelectedRange->isTokenRange()) {
+ // We need to find the actual (exclusive) end location from which to
+ // create a new source range. However, that's not guaranteed to be valid,
+ // even if the token location itself is valid. So, we create a token range
+ // consisting only of the last token, then map that range back to the
+ // source file. If that succeeds, we have a valid location for the end of
+ // the generated range.
+ CharSourceRange Range = Lexer::makeFileCharRange(
+ CharSourceRange::getTokenRange(SelectedRange->getEnd()),
+ *Result.SourceManager, Result.Context->getLangOpts());
+ if (Range.isInvalid())
+ return invalidArgumentError(
+ "after: can't resolve sub-range to valid source range");
+ End = Range.getEnd();
+ }
+
+ return CharSourceRange::getCharRange(End);
};
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits