This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGc7ed4fe56e0a: [libTooling] Change `access` stencil to recognize use of `operator*`. (authored by ymandel).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D104390/new/ https://reviews.llvm.org/D104390 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 @@ -407,7 +407,7 @@ *x; )cc"; StringRef Id = "id"; - testExpr(Id, Snippet, access(Id, "field"), "(*x).field"); + testExpr(Id, Snippet, access(Id, "field"), "x->field"); } TEST_F(StencilTest, AccessOpSmartPointerMemberCall) { Index: clang/lib/Tooling/Transformer/Stencil.cpp =================================================================== --- clang/lib/Tooling/Transformer/Stencil.cpp +++ clang/lib/Tooling/Transformer/Stencil.cpp @@ -73,6 +73,21 @@ return match(SmartPointer, Ty, Context).size() > 0; } +// Identifies use of `operator*` on smart pointers, and returns the underlying +// smart-pointer expression; otherwise, returns null. +static const Expr *isSmartDereference(const Expr &E, ASTContext &Context) { + using namespace ::clang::ast_matchers; + + const auto HasOverloadedArrow = cxxRecordDecl(hasMethod(cxxMethodDecl( + hasOverloadedOperatorName("->"), returns(qualType(pointsTo(type())))))); + // Verify it is a smart pointer by finding `operator->` in the class + // declaration. + auto Deref = cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), hasUnaryOperand(expr().bind("arg")), + callee(cxxMethodDecl(ofClass(HasOverloadedArrow)))); + return selectFirst<Expr>("arg", match(Deref, E, Context)); +} + namespace { // An arbitrary fragment of code within a stencil. class RawTextStencil : public StencilInterface { @@ -309,6 +324,10 @@ } } S = tooling::buildArrow(*E, *Match.Context); + } else if (const auto *Operand = isSmartDereference(*E, *Match.Context)) { + // `buildDot` already handles the built-in dereference operator, so we + // only need to catch overloaded `operator*`. + S = tooling::buildArrow(*Operand, *Match.Context); } else { S = tooling::buildDot(*E, *Match.Context); }
Index: clang/unittests/Tooling/StencilTest.cpp =================================================================== --- clang/unittests/Tooling/StencilTest.cpp +++ clang/unittests/Tooling/StencilTest.cpp @@ -407,7 +407,7 @@ *x; )cc"; StringRef Id = "id"; - testExpr(Id, Snippet, access(Id, "field"), "(*x).field"); + testExpr(Id, Snippet, access(Id, "field"), "x->field"); } TEST_F(StencilTest, AccessOpSmartPointerMemberCall) { Index: clang/lib/Tooling/Transformer/Stencil.cpp =================================================================== --- clang/lib/Tooling/Transformer/Stencil.cpp +++ clang/lib/Tooling/Transformer/Stencil.cpp @@ -73,6 +73,21 @@ return match(SmartPointer, Ty, Context).size() > 0; } +// Identifies use of `operator*` on smart pointers, and returns the underlying +// smart-pointer expression; otherwise, returns null. +static const Expr *isSmartDereference(const Expr &E, ASTContext &Context) { + using namespace ::clang::ast_matchers; + + const auto HasOverloadedArrow = cxxRecordDecl(hasMethod(cxxMethodDecl( + hasOverloadedOperatorName("->"), returns(qualType(pointsTo(type())))))); + // Verify it is a smart pointer by finding `operator->` in the class + // declaration. + auto Deref = cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), hasUnaryOperand(expr().bind("arg")), + callee(cxxMethodDecl(ofClass(HasOverloadedArrow)))); + return selectFirst<Expr>("arg", match(Deref, E, Context)); +} + namespace { // An arbitrary fragment of code within a stencil. class RawTextStencil : public StencilInterface { @@ -309,6 +324,10 @@ } } S = tooling::buildArrow(*E, *Match.Context); + } else if (const auto *Operand = isSmartDereference(*E, *Match.Context)) { + // `buildDot` already handles the built-in dereference operator, so we + // only need to catch overloaded `operator*`. + S = tooling::buildArrow(*Operand, *Match.Context); } else { S = tooling::buildDot(*E, *Match.Context); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits