[clang] 01e8dd2 - [libTooling] Add stencil combinators for nodes that may be pointers or values.
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 22 09:49:10 PST 2019
Author: Yitzhak Mandelbaum
Date: 2019-11-22T12:36:40-05:00
New Revision: 01e8dd2e7a852794a60e50f356f171f893503598
URL: https://github.com/llvm/llvm-project/commit/01e8dd2e7a852794a60e50f356f171f893503598
DIFF: https://github.com/llvm/llvm-project/commit/01e8dd2e7a852794a60e50f356f171f893503598.diff
LOG: [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
Added:
Modified:
clang/include/clang/Tooling/Transformer/Stencil.h
clang/lib/Tooling/Transformer/Stencil.cpp
clang/unittests/Tooling/StencilTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Transformer/Stencil.h b/clang/include/clang/Tooling/Transformer/Stencil.h
index dd65e68b7e8a..0363b689dc5b 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 486e18b341f7..8710e3cdf60f 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<StencilImpl<UnaryOperationData>>(
+ UnaryNodeOperator::MaybeDeref, ExprId);
+}
+
Stencil transformer::addressOf(llvm::StringRef ExprId) {
return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Address, ExprId);
+ UnaryNodeOperator::AddressOf, ExprId);
+}
+
+Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) {
+ return std::make_shared<StencilImpl<UnaryOperationData>>(
+ 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 7f530fe9fbf6..84a33e9cedee 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;
More information about the cfe-commits
mailing list