ymandel created this revision.
ymandel added a reviewer: gribozavr.
Herald added a project: clang.

Adds combinators `asValue` and `asPointer` to provide a uniform way to handle
nodes which may be bound to either a pointer or a value (most often in the
context of member expressions). Such polymorphism is already supported by
`access`; these combinators extend it to more general uses.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70554

Files:
  clang/include/clang/Tooling/Transformer/Stencil.h
  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
@@ -233,6 +233,46 @@
   testExpr(Id, "int *x; *x;", addressOf(Id), "x");
 }
 
+TEST_F(StencilTest, AsValueValue) {
+  StringRef Id = "id";
+  testExpr(Id, "int x; x;", asValue(Id), "x");
+}
+
+TEST_F(StencilTest, AsValuePointer) {
+  StringRef Id = "id";
+  testExpr(Id, "int *x; x;", asValue(Id), "*x");
+}
+
+TEST_F(StencilTest, AsValueBinOp) {
+  StringRef Id = "id";
+  testExpr(Id, "int *x; x + 1;", asValue(Id), "*(x + 1)");
+}
+
+TEST_F(StencilTest, AsValueAddressExpr) {
+  StringRef Id = "id";
+  testExpr(Id, "int x; &x;", asValue(Id), "x");
+}
+
+TEST_F(StencilTest, AsPointerPointer) {
+  StringRef Id = "id";
+  testExpr(Id, "int *x; x;", asPointer(Id), "x");
+}
+
+TEST_F(StencilTest, AsPointerValue) {
+  StringRef Id = "id";
+  testExpr(Id, "int x; x;", addressOf(Id), "&x");
+}
+
+TEST_F(StencilTest, AsPointerBinOp) {
+  StringRef Id = "id";
+  testExpr(Id, "int x; x + 1;", asPointer(Id), "&(x + 1)");
+}
+
+TEST_F(StencilTest, AsPointerDerefExpr) {
+  StringRef Id = "id";
+  testExpr(Id, "int *x; *x;", addressOf(Id), "x");
+}
+
 TEST_F(StencilTest, AccessOpValue) {
   StringRef Snippet = R"cc(
     S x;
Index: clang/lib/Tooling/Transformer/Stencil.cpp
===================================================================
--- clang/lib/Tooling/Transformer/Stencil.cpp
+++ clang/lib/Tooling/Transformer/Stencil.cpp
@@ -60,6 +60,8 @@
   Parens,
   Deref,
   Address,
+  AsValue,
+  AsPointer,
 };
 
 // Generic container for stencil operations with a (single) node-id argument.
@@ -124,6 +126,12 @@
   case UnaryNodeOperator::Address:
     OpName = "addressOf";
     break;
+  case UnaryNodeOperator::AsValue:
+    OpName = "asValue";
+    break;
+  case UnaryNodeOperator::AsPointer:
+    OpName = "asPointer";
+    break;
   }
   return (OpName + "(\"" + Data.Id + "\")").str();
 }
@@ -194,6 +202,21 @@
   case UnaryNodeOperator::Address:
     Source = tooling::buildAddressOf(*E, *Match.Context);
     break;
+  case UnaryNodeOperator::AsValue:
+    if (!E->getType()->isAnyPointerType()) {
+      *Result += tooling::getText(*E, *Match.Context);
+      return Error::success();
+    }
+    Source = tooling::buildDereference(*E, *Match.Context);
+    break;
+
+  case UnaryNodeOperator::AsPointer:
+    if (E->getType()->isAnyPointerType()) {
+      *Result += tooling::getText(*E, *Match.Context);
+      return Error::success();
+    }
+    Source = tooling::buildAddressOf(*E, *Match.Context);
+    break;
   }
   if (!Source)
     return llvm::make_error<StringError>(
@@ -305,6 +328,16 @@
       UnaryNodeOperator::Address, ExprId);
 }
 
+Stencil transformer::asValue(llvm::StringRef ExprId) {
+  return std::make_shared<StencilImpl<UnaryOperationData>>(
+      UnaryNodeOperator::AsValue, ExprId);
+}
+
+Stencil transformer::asPointer(llvm::StringRef ExprId) {
+  return std::make_shared<StencilImpl<UnaryOperationData>>(
+      UnaryNodeOperator::AsPointer, ExprId);
+}
+
 Stencil transformer::access(StringRef BaseId, Stencil Member) {
   return std::make_shared<StencilImpl<AccessData>>(BaseId, std::move(Member));
 }
Index: clang/include/clang/Tooling/Transformer/Stencil.h
===================================================================
--- clang/include/clang/Tooling/Transformer/Stencil.h
+++ clang/include/clang/Tooling/Transformer/Stencil.h
@@ -92,6 +92,14 @@
 /// needed.
 Stencil addressOf(llvm::StringRef ExprId);
 
+// Constructs an expression that idiomatically represents a value, taking into
+// account whether `ExprId` is a pointer or already a value.
+Stencil asValue(llvm::StringRef ExprId);
+
+// Constructs an expression that idiomatically represents a pointer, taking into
+// account whether `ExprId` is a value or already a pointer.
+Stencil asPointer(llvm::StringRef ExprId);
+
 /// Constructs a `MemberExpr` that accesses the named member (\p Member) of the
 /// object bound to \p BaseId. The access is constructed idiomatically: if \p
 /// BaseId is bound to `e` and \p Member identifies member `m`, then returns
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to