From: Yitzhak Mandelbaum Date: Thu, 21 Nov 2019 19:35:22 +0000 (-0500) Subject: [libTooling] Add stencil combinators for nodes that may be pointers or values. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=01e8dd2e7a852794a60e50f356f171f893503598;p=platform%2Fupstream%2Fllvm.git [libTooling] Add stencil combinators for nodes that may be pointers or values. Summary: Adds combinators `maybeDeref` and `maybeAddressOf` 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. Reviewers: gribozavr Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70554 --- diff --git a/clang/include/clang/Tooling/Transformer/Stencil.h b/clang/include/clang/Tooling/Transformer/Stencil.h index dd65e68..0363b68 100644 --- a/clang/include/clang/Tooling/Transformer/Stencil.h +++ b/clang/include/clang/Tooling/Transformer/Stencil.h @@ -87,11 +87,24 @@ Stencil expression(llvm::StringRef Id); /// \p ExprId is wrapped in parentheses, if needed. Stencil deref(llvm::StringRef ExprId); +/// If \p ExprId is of pointer type, constructs an idiomatic dereferencing of +/// the expression bound to \p ExprId, including wrapping it in parentheses, if +/// needed. Otherwise, generates the original expression source. +/// FIXME: Identify smart-pointers as pointer types. +Stencil maybeDeref(llvm::StringRef ExprId); + /// Constructs an expression that idiomatically takes the address of the /// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if /// needed. Stencil addressOf(llvm::StringRef ExprId); +/// If \p ExprId is not a pointer type, constructs an expression that +/// idiomatically takes the address of the expression bound to \p ExprId, +/// including wrapping \p ExprId in parentheses, if needed. Otherwise, generates +/// the original expression source. +/// FIXME: Identify smart-pointers as pointer types. +Stencil maybeAddressOf(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 diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp index 486e18b..8710e3c 100644 --- a/clang/lib/Tooling/Transformer/Stencil.cpp +++ b/clang/lib/Tooling/Transformer/Stencil.cpp @@ -59,7 +59,9 @@ struct DebugPrintNodeData { enum class UnaryNodeOperator { Parens, Deref, - Address, + MaybeDeref, + AddressOf, + MaybeAddressOf, }; // Generic container for stencil operations with a (single) node-id argument. @@ -121,9 +123,15 @@ std::string toStringData(const UnaryOperationData &Data) { case UnaryNodeOperator::Deref: OpName = "deref"; break; - case UnaryNodeOperator::Address: + case UnaryNodeOperator::MaybeDeref: + OpName = "maybeDeref"; + break; + case UnaryNodeOperator::AddressOf: OpName = "addressOf"; break; + case UnaryNodeOperator::MaybeAddressOf: + OpName = "maybeAddressOf"; + break; } return (OpName + "(\"" + Data.Id + "\")").str(); } @@ -191,7 +199,21 @@ Error evalData(const UnaryOperationData &Data, case UnaryNodeOperator::Deref: Source = tooling::buildDereference(*E, *Match.Context); break; - case UnaryNodeOperator::Address: + case UnaryNodeOperator::MaybeDeref: + if (!E->getType()->isAnyPointerType()) { + *Result += tooling::getText(*E, *Match.Context); + return Error::success(); + } + Source = tooling::buildDereference(*E, *Match.Context); + break; + case UnaryNodeOperator::AddressOf: + Source = tooling::buildAddressOf(*E, *Match.Context); + break; + case UnaryNodeOperator::MaybeAddressOf: + if (E->getType()->isAnyPointerType()) { + *Result += tooling::getText(*E, *Match.Context); + return Error::success(); + } Source = tooling::buildAddressOf(*E, *Match.Context); break; } @@ -300,9 +322,19 @@ Stencil transformer::deref(llvm::StringRef ExprId) { UnaryNodeOperator::Deref, ExprId); } +Stencil transformer::maybeDeref(llvm::StringRef ExprId) { + return std::make_shared>( + UnaryNodeOperator::MaybeDeref, ExprId); +} + Stencil transformer::addressOf(llvm::StringRef ExprId) { return std::make_shared>( - UnaryNodeOperator::Address, ExprId); + UnaryNodeOperator::AddressOf, ExprId); +} + +Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) { + return std::make_shared>( + UnaryNodeOperator::MaybeAddressOf, ExprId); } Stencil transformer::access(StringRef BaseId, Stencil Member) { diff --git a/clang/unittests/Tooling/StencilTest.cpp b/clang/unittests/Tooling/StencilTest.cpp index 7f530fe..84a33e9 100644 --- a/clang/unittests/Tooling/StencilTest.cpp +++ b/clang/unittests/Tooling/StencilTest.cpp @@ -233,6 +233,46 @@ TEST_F(StencilTest, AddressOfDerefExpr) { testExpr(Id, "int *x; *x;", addressOf(Id), "x"); } +TEST_F(StencilTest, MaybeDerefValue) { + StringRef Id = "id"; + testExpr(Id, "int x; x;", maybeDeref(Id), "x"); +} + +TEST_F(StencilTest, MaybeDerefPointer) { + StringRef Id = "id"; + testExpr(Id, "int *x; x;", maybeDeref(Id), "*x"); +} + +TEST_F(StencilTest, MaybeDerefBinOp) { + StringRef Id = "id"; + testExpr(Id, "int *x; x + 1;", maybeDeref(Id), "*(x + 1)"); +} + +TEST_F(StencilTest, MaybeDerefAddressExpr) { + StringRef Id = "id"; + testExpr(Id, "int x; &x;", maybeDeref(Id), "x"); +} + +TEST_F(StencilTest, MaybeAddressOfPointer) { + StringRef Id = "id"; + testExpr(Id, "int *x; x;", maybeAddressOf(Id), "x"); +} + +TEST_F(StencilTest, MaybeAddressOfValue) { + StringRef Id = "id"; + testExpr(Id, "int x; x;", addressOf(Id), "&x"); +} + +TEST_F(StencilTest, MaybeAddressOfBinOp) { + StringRef Id = "id"; + testExpr(Id, "int x; x + 1;", maybeAddressOf(Id), "&(x + 1)"); +} + +TEST_F(StencilTest, MaybeAddressOfDerefExpr) { + StringRef Id = "id"; + testExpr(Id, "int *x; *x;", addressOf(Id), "x"); +} + TEST_F(StencilTest, AccessOpValue) { StringRef Snippet = R"cc( S x;