ymandel updated this revision to Diff 352453.
ymandel added a comment.

add comments and simplify.


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

Reply via email to