forked from OSchip/llvm-project
[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:
parent
80cd6b6e04
commit
01e8dd2e7a
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue