[clang] c7ed4fe - [libTooling] Change `access` stencil to recognize use of `operator*`.
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 16 13:34:23 PDT 2021
Author: Yitzhak Mandelbaum
Date: 2021-06-16T20:34:00Z
New Revision: c7ed4fe56e0a6c664c5fb5dedaedb426abe7224d
URL: https://github.com/llvm/llvm-project/commit/c7ed4fe56e0a6c664c5fb5dedaedb426abe7224d
DIFF: https://github.com/llvm/llvm-project/commit/c7ed4fe56e0a6c664c5fb5dedaedb426abe7224d.diff
LOG: [libTooling] Change `access` stencil to recognize use of `operator*`.
Currently, `access` doesn't recognize a dereferenced smart pointer. So,
`access(e, "field")` where `e = *x`, yields:
* `x->field`, for normal-pointer x,
* `(*x).field`, for smart-pointer x.
This patch normalizes handling of smart pointer to match normal pointer, when
the smart pointer type supports `->`.
Differential Revision: https://reviews.llvm.org/D104390
Added:
Modified:
clang/lib/Tooling/Transformer/Stencil.cpp
clang/unittests/Tooling/StencilTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp
index 9223b4a290a08..4dc3544bb06db 100644
--- a/clang/lib/Tooling/Transformer/Stencil.cpp
+++ b/clang/lib/Tooling/Transformer/Stencil.cpp
@@ -73,6 +73,21 @@ static bool isSmartPointerType(QualType Ty, ASTContext &Context) {
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 @@ class AccessStencil : public StencilInterface {
}
}
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);
}
diff --git a/clang/unittests/Tooling/StencilTest.cpp b/clang/unittests/Tooling/StencilTest.cpp
index df05e6deeb577..0b5b9691dadc5 100644
--- a/clang/unittests/Tooling/StencilTest.cpp
+++ b/clang/unittests/Tooling/StencilTest.cpp
@@ -407,7 +407,7 @@ TEST_F(StencilTest, AccessOpSmartPointerDereference) {
*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) {
More information about the cfe-commits
mailing list