Skip to content

Commit 3ef9135

Browse files
committed
[clang-tidy] readability-redundant-smartptr-get: disable for smart pointers to arrays
1 parent 3833513 commit 3ef9135

File tree

3 files changed

+107
-9
lines changed

3 files changed

+107
-9
lines changed

clang-tools-extra/clang-tidy/readability/RedundantSmartptrGetCheck.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,18 @@ internal::Matcher<Expr> callToGet(const internal::Matcher<Decl> &OnClass) {
4343
.bind("redundant_get");
4444
}
4545

46-
internal::Matcher<Decl> knownSmartptr() {
46+
internal::Matcher<Decl> knownSmartptrAny() {
4747
return recordDecl(hasAnyName("::std::unique_ptr", "::std::shared_ptr"));
4848
}
4949

50+
internal::Matcher<Decl> knownSmartptrNonArray() {
51+
return recordDecl(hasAnyName("::std::unique_ptr", "::std::shared_ptr"),
52+
anyOf(has(cxxMethodDecl(hasName("operator*"))),
53+
has(functionTemplateDecl(hasName("operator*")))),
54+
anyOf(has(cxxMethodDecl(hasName("operator->"))),
55+
has(functionTemplateDecl(hasName("operator->")))));
56+
}
57+
5058
void registerMatchersForGetArrowStart(MatchFinder *Finder,
5159
MatchFinder::MatchCallback *Callback) {
5260
const auto QuacksLikeASmartptr = recordDecl(
@@ -57,21 +65,25 @@ void registerMatchersForGetArrowStart(MatchFinder *Finder,
5765
type().bind("op*Type")))))));
5866

5967
// Make sure we are not missing the known standard types.
60-
const auto Smartptr = anyOf(knownSmartptr(), QuacksLikeASmartptr);
68+
const auto SmartptrAny = anyOf(knownSmartptrAny(), QuacksLikeASmartptr);
69+
const auto SmartptrNonArray =
70+
anyOf(knownSmartptrNonArray(), QuacksLikeASmartptr);
6171

6272
// Catch 'ptr.get()->Foo()'
63-
Finder->addMatcher(memberExpr(expr().bind("memberExpr"), isArrow(),
64-
hasObjectExpression(callToGet(Smartptr))),
65-
Callback);
73+
Finder->addMatcher(
74+
memberExpr(expr().bind("memberExpr"), isArrow(),
75+
hasObjectExpression(callToGet(SmartptrNonArray))),
76+
Callback);
6677

6778
// Catch '*ptr.get()' or '*ptr->get()'
6879
Finder->addMatcher(
69-
unaryOperator(hasOperatorName("*"), hasUnaryOperand(callToGet(Smartptr))),
80+
unaryOperator(hasOperatorName("*"),
81+
hasUnaryOperand(callToGet(SmartptrNonArray))),
7082
Callback);
7183

7284
// Catch '!ptr.get()'
7385
const auto CallToGetAsBool = callToGet(
74-
recordDecl(Smartptr, has(cxxConversionDecl(returns(booleanType())))));
86+
recordDecl(SmartptrAny, has(cxxConversionDecl(returns(booleanType())))));
7587
Finder->addMatcher(
7688
unaryOperator(hasOperatorName("!"), hasUnaryOperand(CallToGetAsBool)),
7789
Callback);
@@ -84,7 +96,7 @@ void registerMatchersForGetArrowStart(MatchFinder *Finder,
8496
Callback);
8597

8698
Finder->addMatcher(cxxDependentScopeMemberExpr(hasObjectExpression(
87-
callExpr(has(callToGet(Smartptr))).bind("obj"))),
99+
callExpr(has(callToGet(SmartptrAny))))),
88100
Callback);
89101
}
90102

@@ -100,7 +112,7 @@ void registerMatchersForGetEquals(MatchFinder *Finder,
100112
binaryOperator(hasAnyOperatorName("==", "!="),
101113
hasOperands(anyOf(cxxNullPtrLiteralExpr(), gnuNullExpr(),
102114
integerLiteral(equals(0))),
103-
callToGet(knownSmartptr()))),
115+
callToGet(knownSmartptrAny()))),
104116
Callback);
105117

106118
// FIXME: Match and fix if (l.get() == r.get()).

clang-tools-extra/test/clang-tidy/checkers/readability/redundant-smartptr-get-msvc.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ struct unique_ptr {
1616
explicit operator bool() const noexcept;
1717
};
1818

19+
template <typename T>
20+
struct unique_ptr<T[]> {
21+
template <typename T2 = T>
22+
T2* operator[](unsigned) const;
23+
T* get() const;
24+
explicit operator bool() const noexcept;
25+
};
26+
1927
template <typename T>
2028
struct shared_ptr {
2129
template <typename T2 = T>
@@ -26,6 +34,14 @@ struct shared_ptr {
2634
explicit operator bool() const noexcept;
2735
};
2836

37+
template <typename T>
38+
struct shared_ptr<T[]> {
39+
template <typename T2 = T>
40+
T2* operator[](unsigned) const;
41+
T* get() const;
42+
explicit operator bool() const noexcept;
43+
};
44+
2945
} // namespace std
3046

3147
struct Bar {
@@ -92,3 +108,31 @@ void Positive() {
92108
// CHECK-MESSAGES: if (NULL == x.get());
93109
// CHECK-FIXES: if (NULL == x);
94110
}
111+
112+
void test_smart_ptr_to_array() {
113+
std::unique_ptr<int[]> i;
114+
// The array specialization does not have operator*(), so make sure
115+
// we do not incorrectly suggest sizeof(*i) here.
116+
// FIXME: alternatively, we could suggest sizeof(i[0])
117+
auto sz = sizeof(*i.get());
118+
119+
std::shared_ptr<Bar[]> s;
120+
// The array specialization does not have operator->() either
121+
s.get()->Do();
122+
123+
bool b1 = !s.get();
124+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call
125+
// CHECK-FIXES: bool b1 = !s;
126+
127+
if (s.get()) {}
128+
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
129+
// CHECK-FIXES: if (s) {}
130+
131+
int x = s.get() ? 1 : 2;
132+
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant get() call
133+
// CHECK-FIXES: int x = s ? 1 : 2;
134+
135+
bool b2 = s.get() == nullptr;
136+
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
137+
// CHECK-FIXES: bool b2 = s == nullptr;
138+
}

clang-tools-extra/test/clang-tidy/checkers/readability/redundant-smartptr-get.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ struct unique_ptr {
1212
explicit operator bool() const noexcept;
1313
};
1414

15+
template <typename T>
16+
struct unique_ptr<T[]> {
17+
T& operator[](unsigned) const;
18+
T* get() const;
19+
explicit operator bool() const noexcept;
20+
};
21+
1522
template <typename T>
1623
struct shared_ptr {
1724
T& operator*() const;
@@ -20,6 +27,13 @@ struct shared_ptr {
2027
explicit operator bool() const noexcept;
2128
};
2229

30+
template <typename T>
31+
struct shared_ptr<T[]> {
32+
T& operator[](unsigned) const;
33+
T* get() const;
34+
explicit operator bool() const noexcept;
35+
};
36+
2337
template <typename T>
2438
struct vector {
2539
vector();
@@ -283,3 +297,31 @@ void test_redundant_get_with_member() {
283297
// CHECK-FIXES: f(**i->get()->getValue());
284298
}
285299
}
300+
301+
void test_smart_ptr_to_array() {
302+
std::unique_ptr<int[]> i;
303+
// The array specialization does not have operator*(), so make sure
304+
// we do not incorrectly suggest sizeof(*i) here.
305+
// FIXME: alternatively, we could suggest sizeof(i[0])
306+
auto sz = sizeof(*i.get());
307+
308+
std::shared_ptr<Inner[]> s;
309+
// The array specialization does not have operator->() either
310+
s.get()->getValue();
311+
312+
bool b1 = !s.get();
313+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call
314+
// CHECK-FIXES: bool b1 = !s;
315+
316+
if (s.get()) {}
317+
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call
318+
// CHECK-FIXES: if (s) {}
319+
320+
int x = s.get() ? 1 : 2;
321+
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant get() call
322+
// CHECK-FIXES: int x = s ? 1 : 2;
323+
324+
bool b2 = s.get() == nullptr;
325+
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call
326+
// CHECK-FIXES: bool b2 = s == nullptr;
327+
}

0 commit comments

Comments
 (0)