[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
This commit is contained in:
Yitzhak Mandelbaum 2019-11-21 14:35:22 -05:00
parent 80cd6b6e04
commit 01e8dd2e7a
3 changed files with 89 additions and 4 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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;