[libTooling] Add smart pointer support to the `access` Stencil

This extends smart pointer support beyond the existing `maybeDeref` and
`maybeAddressOf`.

Differential Revision: https://reviews.llvm.org/D100450
This commit is contained in:
Shu-Chun Weng 2021-04-14 00:08:40 -07:00
parent af7925b4dd
commit 1c5717225e
2 changed files with 48 additions and 4 deletions

View File

@ -323,10 +323,23 @@ Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
return llvm::make_error<StringError>(errc::invalid_argument,
"Id not bound: " + Data.BaseId);
if (!E->isImplicitCXXThis()) {
if (llvm::Optional<std::string> S =
E->getType()->isAnyPointerType()
? tooling::buildArrow(*E, *Match.Context)
: tooling::buildDot(*E, *Match.Context))
llvm::Optional<std::string> S;
if (E->getType()->isAnyPointerType() ||
isSmartPointerType(E->getType(), *Match.Context)) {
// Strip off any operator->. This can only occur inside an actual arrow
// member access, so we treat it as equivalent to an actual object
// expression.
if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
if (OpCall->getOperator() == clang::OO_Arrow &&
OpCall->getNumArgs() == 1) {
E = OpCall->getArg(0);
}
}
S = tooling::buildArrow(*E, *Match.Context);
} else {
S = tooling::buildDot(*E, *Match.Context);
}
if (S.hasValue())
*Result += *S;
else
return llvm::make_error<StringError>(

View File

@ -392,6 +392,37 @@ TEST_F(StencilTest, AccessOpPointerDereference) {
testExpr(Id, Snippet, access(Id, "field"), "x->field");
}
TEST_F(StencilTest, AccessOpSmartPointer) {
StringRef Snippet = R"cc(
Smart x;
x;
)cc";
StringRef Id = "id";
testExpr(Id, Snippet, access(Id, "field"), "x->field");
}
TEST_F(StencilTest, AccessOpSmartPointerDereference) {
StringRef Snippet = R"cc(
Smart x;
*x;
)cc";
StringRef Id = "id";
testExpr(Id, Snippet, access(Id, "field"), "(*x).field");
}
TEST_F(StencilTest, AccessOpSmartPointerMemberCall) {
StringRef Snippet = R"cc(
Smart x;
x->Field;
)cc";
StringRef Id = "id";
auto StmtMatch =
matchStmt(Snippet, memberExpr(hasObjectExpression(expr().bind(Id))));
ASSERT_TRUE(StmtMatch);
EXPECT_THAT_EXPECTED(access(Id, "field")->eval(StmtMatch->Result),
HasValue("x->field"));
}
TEST_F(StencilTest, AccessOpExplicitThis) {
using clang::ast_matchers::hasObjectExpression;
using clang::ast_matchers::memberExpr;