ymandel created this revision. ymandel added a reviewer: gribozavr2. Herald added a project: clang.
Currently, the `selection` stencil validates the selection before extracting the text. However, this means that any range inside a macro is rejected as an error. This patch changes the implementation to first try to map the range to something reasonable. This makes the behavior consistent with handling of ranges used for selecting portions of the source to edit. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D82126 Files: clang/lib/Tooling/Transformer/Stencil.cpp clang/unittests/Tooling/StencilTest.cpp Index: clang/unittests/Tooling/StencilTest.cpp =================================================================== --- clang/unittests/Tooling/StencilTest.cpp +++ clang/unittests/Tooling/StencilTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/Transformer/Stencil.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Tooling/FixIt.h" #include "clang/Tooling/Tooling.h" @@ -373,6 +374,48 @@ testExpr(Id, "3;", run(SimpleFn), "Bound"); } +TEST_F(StencilTest, CatOfMacroRangeSucceeds) { + StringRef Snippet = R"cpp( +#define MACRO 3.77 + double foo(double d); + foo(MACRO);)cpp"; + + auto StmtMatch = + matchStmt(Snippet, callExpr(callee(functionDecl(hasName("foo"))), + argumentCountIs(1), + hasArgument(0, expr().bind("arg")))); + ASSERT_TRUE(StmtMatch); + Stencil S = cat(node("arg")); + EXPECT_THAT_EXPECTED(S->eval(StmtMatch->Result), HasValue("MACRO")); +} + +TEST_F(StencilTest, CatOfMacroArgRangeSucceeds) { + StringRef Snippet = R"cpp( +#define MACRO(a, b) a + b + MACRO(2, 3);)cpp"; + + auto StmtMatch = + matchStmt(Snippet, binaryOperator(hasRHS(expr().bind("rhs")))); + ASSERT_TRUE(StmtMatch); + Stencil S = cat(node("rhs")); + EXPECT_THAT_EXPECTED(S->eval(StmtMatch->Result), HasValue("3")); +} + +TEST_F(StencilTest, CatOfMacroArgSubRangeSucceeds) { + StringRef Snippet = R"cpp( +#define MACRO(a, b) a + b + int foo(int); + MACRO(2, foo(3));)cpp"; + + auto StmtMatch = matchStmt( + Snippet, binaryOperator(hasRHS(callExpr( + callee(functionDecl(hasName("foo"))), argumentCountIs(1), + hasArgument(0, expr().bind("arg")))))); + ASSERT_TRUE(StmtMatch); + Stencil S = cat(node("arg")); + EXPECT_THAT_EXPECTED(S->eval(StmtMatch->Result), HasValue("3")); +} + TEST_F(StencilTest, CatOfInvalidRangeFails) { StringRef Snippet = R"cpp( #define MACRO (3.77) Index: clang/lib/Tooling/Transformer/Stencil.cpp =================================================================== --- clang/lib/Tooling/Transformer/Stencil.cpp +++ clang/lib/Tooling/Transformer/Stencil.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Expr.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Tooling/Transformer/SourceCode.h" #include "clang/Tooling/Transformer/SourceCodeBuilders.h" @@ -226,12 +227,14 @@ Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match, std::string *Result) { - auto Range = Data.Selector(Match); - if (!Range) - return Range.takeError(); - if (auto Err = tooling::validateEditRange(*Range, *Match.SourceManager)) + auto RawRange = Data.Selector(Match); + if (!RawRange) + return RawRange.takeError(); + CharSourceRange Range = Lexer::makeFileCharRange( + *RawRange, *Match.SourceManager, Match.Context->getLangOpts()); + if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager)) return Err; - *Result += tooling::getText(*Range, *Match.Context); + *Result += tooling::getText(Range, *Match.Context); return Error::success(); }
Index: clang/unittests/Tooling/StencilTest.cpp =================================================================== --- clang/unittests/Tooling/StencilTest.cpp +++ clang/unittests/Tooling/StencilTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/Transformer/Stencil.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Tooling/FixIt.h" #include "clang/Tooling/Tooling.h" @@ -373,6 +374,48 @@ testExpr(Id, "3;", run(SimpleFn), "Bound"); } +TEST_F(StencilTest, CatOfMacroRangeSucceeds) { + StringRef Snippet = R"cpp( +#define MACRO 3.77 + double foo(double d); + foo(MACRO);)cpp"; + + auto StmtMatch = + matchStmt(Snippet, callExpr(callee(functionDecl(hasName("foo"))), + argumentCountIs(1), + hasArgument(0, expr().bind("arg")))); + ASSERT_TRUE(StmtMatch); + Stencil S = cat(node("arg")); + EXPECT_THAT_EXPECTED(S->eval(StmtMatch->Result), HasValue("MACRO")); +} + +TEST_F(StencilTest, CatOfMacroArgRangeSucceeds) { + StringRef Snippet = R"cpp( +#define MACRO(a, b) a + b + MACRO(2, 3);)cpp"; + + auto StmtMatch = + matchStmt(Snippet, binaryOperator(hasRHS(expr().bind("rhs")))); + ASSERT_TRUE(StmtMatch); + Stencil S = cat(node("rhs")); + EXPECT_THAT_EXPECTED(S->eval(StmtMatch->Result), HasValue("3")); +} + +TEST_F(StencilTest, CatOfMacroArgSubRangeSucceeds) { + StringRef Snippet = R"cpp( +#define MACRO(a, b) a + b + int foo(int); + MACRO(2, foo(3));)cpp"; + + auto StmtMatch = matchStmt( + Snippet, binaryOperator(hasRHS(callExpr( + callee(functionDecl(hasName("foo"))), argumentCountIs(1), + hasArgument(0, expr().bind("arg")))))); + ASSERT_TRUE(StmtMatch); + Stencil S = cat(node("arg")); + EXPECT_THAT_EXPECTED(S->eval(StmtMatch->Result), HasValue("3")); +} + TEST_F(StencilTest, CatOfInvalidRangeFails) { StringRef Snippet = R"cpp( #define MACRO (3.77) Index: clang/lib/Tooling/Transformer/Stencil.cpp =================================================================== --- clang/lib/Tooling/Transformer/Stencil.cpp +++ clang/lib/Tooling/Transformer/Stencil.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Expr.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Tooling/Transformer/SourceCode.h" #include "clang/Tooling/Transformer/SourceCodeBuilders.h" @@ -226,12 +227,14 @@ Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match, std::string *Result) { - auto Range = Data.Selector(Match); - if (!Range) - return Range.takeError(); - if (auto Err = tooling::validateEditRange(*Range, *Match.SourceManager)) + auto RawRange = Data.Selector(Match); + if (!RawRange) + return RawRange.takeError(); + CharSourceRange Range = Lexer::makeFileCharRange( + *RawRange, *Match.SourceManager, Match.Context->getLangOpts()); + if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager)) return Err; - *Result += tooling::getText(*Range, *Match.Context); + *Result += tooling::getText(Range, *Match.Context); return Error::success(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits