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