Skip to content

Commit 59a9a8f

Browse files
authored
[clang][dataflow] Fix smart pointer accessor caching to handle aliases (llvm#124964)
Check the canonical type in the matchers to handle aliases. For example std::optional uses add_pointer_t<...>.
1 parent d1033d1 commit 59a9a8f

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using ast_matchers::callee;
1414
using ast_matchers::cxxMemberCallExpr;
1515
using ast_matchers::cxxMethodDecl;
1616
using ast_matchers::cxxOperatorCallExpr;
17+
using ast_matchers::hasCanonicalType;
1718
using ast_matchers::hasName;
1819
using ast_matchers::hasOverloadedOperatorName;
1920
using ast_matchers::ofClass;
@@ -122,27 +123,29 @@ namespace clang::dataflow {
122123
ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar() {
123124
return cxxOperatorCallExpr(
124125
hasOverloadedOperatorName("*"),
125-
callee(cxxMethodDecl(parameterCountIs(0), returns(referenceType()),
126+
callee(cxxMethodDecl(parameterCountIs(0),
127+
returns(hasCanonicalType(referenceType())),
126128
ofClass(smartPointerClassWithGetOrValue()))));
127129
}
128130

129131
ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow() {
130132
return cxxOperatorCallExpr(
131133
hasOverloadedOperatorName("->"),
132-
callee(cxxMethodDecl(parameterCountIs(0), returns(pointerType()),
134+
callee(cxxMethodDecl(parameterCountIs(0),
135+
returns(hasCanonicalType(pointerType())),
133136
ofClass(smartPointerClassWithGetOrValue()))));
134137
}
135138

136139
ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall() {
137-
return cxxMemberCallExpr(callee(
138-
cxxMethodDecl(parameterCountIs(0), returns(referenceType()),
139-
hasName("value"), ofClass(smartPointerClassWithValue()))));
140+
return cxxMemberCallExpr(callee(cxxMethodDecl(
141+
parameterCountIs(0), returns(hasCanonicalType(referenceType())),
142+
hasName("value"), ofClass(smartPointerClassWithValue()))));
140143
}
141144

142145
ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall() {
143-
return cxxMemberCallExpr(callee(
144-
cxxMethodDecl(parameterCountIs(0), returns(pointerType()), hasName("get"),
145-
ofClass(smartPointerClassWithGet()))));
146+
return cxxMemberCallExpr(callee(cxxMethodDecl(
147+
parameterCountIs(0), returns(hasCanonicalType(pointerType())),
148+
hasName("get"), ofClass(smartPointerClassWithGet()))));
146149
}
147150

148151
const FunctionDecl *

clang/unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,57 @@ TEST(SmartPointerAccessorCachingTest, MatchesWithValueAndNonConstOverloads) {
190190
isSmartPointerLikeValueMethodCall()));
191191
}
192192

193+
TEST(SmartPointerAccessorCachingTest, MatchesWithTypeAliases) {
194+
llvm::StringRef Decls(R"cc(
195+
template <class T>
196+
struct HasGetAndValue {
197+
using pointer_t = T*;
198+
using reference_t = T&;
199+
200+
const pointer_t operator->() const;
201+
pointer_t operator->();
202+
const reference_t operator*() const;
203+
reference_t operator*();
204+
const reference_t value() const;
205+
reference_t value();
206+
const pointer_t get() const;
207+
pointer_t get();
208+
};
209+
210+
struct S { int i; };
211+
)cc");
212+
213+
EXPECT_TRUE(matches(
214+
Decls,
215+
"int target(HasGetAndValue<S> &NonConst) { return (*NonConst).i; }",
216+
isSmartPointerLikeOperatorStar()));
217+
EXPECT_TRUE(matches(
218+
Decls,
219+
"int target(const HasGetAndValue<S> &Const) { return (*Const).i; }",
220+
isSmartPointerLikeOperatorStar()));
221+
EXPECT_TRUE(matches(
222+
Decls, "int target(HasGetAndValue<S> &NonConst) { return NonConst->i; }",
223+
isSmartPointerLikeOperatorArrow()));
224+
EXPECT_TRUE(matches(
225+
Decls, "int target(const HasGetAndValue<S> &Const) { return Const->i; }",
226+
isSmartPointerLikeOperatorArrow()));
227+
EXPECT_TRUE(matches(
228+
Decls,
229+
"int target(HasGetAndValue<S> &NonConst) { return NonConst.value().i; }",
230+
isSmartPointerLikeValueMethodCall()));
231+
EXPECT_TRUE(matches(
232+
Decls,
233+
"int target(const HasGetAndValue<S> &Const) { return Const.value().i; }",
234+
isSmartPointerLikeValueMethodCall()));
235+
EXPECT_TRUE(matches(
236+
Decls,
237+
"int target(HasGetAndValue<S> &NonConst) { return NonConst.get()->i; }",
238+
isSmartPointerLikeGetMethodCall()));
239+
EXPECT_TRUE(matches(
240+
Decls,
241+
"int target(const HasGetAndValue<S> &Const) { return Const.get()->i; }",
242+
isSmartPointerLikeGetMethodCall()));
243+
}
244+
193245
} // namespace
194246
} // namespace clang::dataflow

0 commit comments

Comments
 (0)