1 #include "../clang-tidy/utils/DeclRefExprUtils.h"
2 #include "ClangTidyDiagnosticConsumer.h"
3 #include "ClangTidyTest.h"
4 #include "clang/ASTMatchers/ASTMatchFinder.h"
5 #include "clang/ASTMatchers/ASTMatchers.h"
6 #include "clang/Tooling/Tooling.h"
7 #include "gtest/gtest.h"
13 using namespace clang::ast_matchers
;
15 class ConstReferenceDeclRefExprsTransform
: public ClangTidyCheck
{
17 ConstReferenceDeclRefExprsTransform(StringRef CheckName
,
18 ClangTidyContext
*Context
)
19 : ClangTidyCheck(CheckName
, Context
) {}
21 void registerMatchers(MatchFinder
*Finder
) override
{
22 Finder
->addMatcher(varDecl(hasName("target")).bind("var"), this);
25 void check(const MatchFinder::MatchResult
&Result
) override
{
26 const auto *D
= Result
.Nodes
.getNodeAs
<VarDecl
>("var");
27 using utils::decl_ref_expr::constReferenceDeclRefExprs
;
28 const auto const_decrefexprs
= constReferenceDeclRefExprs(
29 *D
, *cast
<FunctionDecl
>(D
->getDeclContext())->getBody(),
32 for (const DeclRefExpr
*const Expr
: const_decrefexprs
) {
34 diag(Expr
->getBeginLoc(), "const usage")
35 << FixItHint::CreateInsertion(Expr
->getBeginLoc(), "/*const*/");
43 void RunTest(StringRef Snippet
) {
45 StringRef CommonCode
= R
"(
50 void constMethod() const;
51 void nonConstMethod();
53 void operator()(ConstTag) const;
54 void operator()(NonConstTag);
57 void operator[](int) const;
59 bool operator==(const S&) const;
66 struct Derived : public S {
74 void usePtrConstPtr(S* const*);
75 void useConstRef(const S&);
76 void useConstPtr(const S*);
77 void useConstPtrRef(const S*&);
78 void useConstPtrPtr(const S**);
79 void useConstPtrConstRef(const S* const&);
80 void useConstPtrConstPtr(const S* const*);
84 void useIntConstRef(const int&);
86 void useIntConstPtr(const int*);
90 std::string Code
= (CommonCode
+ Snippet
).str();
92 llvm::SmallVector
<StringRef
, 1> Parts
;
93 StringRef(Code
).split(Parts
, "/*const*/");
95 EXPECT_EQ(Code
, runCheckOnCode
<ConstReferenceDeclRefExprsTransform
>(
99 TEST(ConstReferenceDeclRefExprsTest
, ConstValueVar
) {
101 void f(const S target) {
102 useVal(/*const*/target);
103 useConstRef(/*const*/target);
104 useConstPtr(&target);
105 useConstPtrConstRef(&target);
106 /*const*/target.constMethod();
107 /*const*/target(ConstTag{});
109 useConstRef((/*const*/target));
110 (/*const*/target).constMethod();
111 (void)(/*const*/target == /*const*/target);
115 S copy1 = /*const*/target;
116 S copy2(/*const*/target);
117 useInt(/*const*/target.int_member);
118 useIntConstRef(/*const*/target.int_member);
119 useIntPtr(target.ptr_member);
120 useIntConstPtr(&target.int_member);
125 TEST(ConstReferenceDeclRefExprsTest
, ConstRefVar
) {
127 void f(const S& target) {
128 useVal(/*const*/target);
129 useConstRef(/*const*/target);
130 useConstPtr(&target);
131 useConstPtrConstRef(&target);
132 /*const*/target.constMethod();
133 /*const*/target(ConstTag{});
135 useConstRef((/*const*/target));
136 (/*const*/target).constMethod();
137 (void)(/*const*/target == /*const*/target);
141 S copy1 = /*const*/target;
142 S copy2(/*const*/target);
143 useInt(/*const*/target.int_member);
144 useIntConstRef(/*const*/target.int_member);
145 useIntPtr(target.ptr_member);
146 useIntConstPtr(&target.int_member);
151 TEST(ConstReferenceDeclRefExprsTest
, ValueVar
) {
153 void f(S target, const S& other) {
154 useConstRef(/*const*/target);
155 useVal(/*const*/target);
156 useConstPtr(&target);
157 useConstPtrConstRef(&target);
158 /*const*/target.constMethod();
159 target.nonConstMethod();
160 /*const*/target(ConstTag{});
162 /*const*/target(ConstTag{});
163 target(NonConstTag{});
166 useConstRef((/*const*/target));
167 (/*const*/target).constMethod();
168 (void)(/*const*/target == /*const*/target);
169 (void)(/*const*/target == other);
173 S copy1 = /*const*/target;
174 S copy2(/*const*/target);
175 useInt(/*const*/target.int_member);
176 useIntConstRef(/*const*/target.int_member);
177 useIntPtr(target.ptr_member);
178 useIntConstPtr(&target.int_member);
183 TEST(ConstReferenceDeclRefExprsTest
, RefVar
) {
186 useVal(/*const*/target);
187 useConstRef(/*const*/target);
188 useConstPtr(&target);
189 useConstPtrConstRef(&target);
190 /*const*/target.constMethod();
191 target.nonConstMethod();
192 /*const*/target(ConstTag{});
194 useConstRef((/*const*/target));
195 (/*const*/target).constMethod();
196 (void)(/*const*/target == /*const*/target);
200 S copy1 = /*const*/target;
201 S copy2(/*const*/target);
202 useInt(/*const*/target.int_member);
203 useIntConstRef(/*const*/target.int_member);
204 useIntPtr(target.ptr_member);
205 useIntConstPtr(&target.int_member);
210 TEST(ConstReferenceDeclRefExprsTest
, PtrVar
) {
214 useConstRef(*target);
216 useConstPtrConstRef(/*const*/target);
217 /*const*/target->constMethod();
218 target->nonConstMethod();
219 (*target)(ConstTag{});
221 target->operator[](42);
222 useConstRef((*target));
223 (/*const*/target)->constMethod();
224 (void)(*target == *target);
229 useInt(target->int_member);
230 useIntConstRef(target->int_member);
231 useIntPtr(target->ptr_member);
232 useIntConstPtr(&target->int_member);
237 TEST(ConstReferenceDeclRefExprsTest
, ConstPtrVar
) {
239 void f(const S* target) {
241 useConstRef(*target);
243 useConstPtrRef(target);
244 useConstPtrPtr(&target);
245 useConstPtrConstPtr(&target);
246 useConstPtrConstRef(/*const*/target);
247 /*const*/target->constMethod();
248 (*target)(ConstTag{});
250 /*const*/target->operator[](42);
251 (void)(*target == *target);
257 useInt(target->int_member);
258 useIntConstRef(target->int_member);
259 useIntPtr(target->ptr_member);
260 useIntConstPtr(&target->int_member);
265 TEST(ConstReferenceDeclRefExprsTest
, ConstPtrPtrVar
) {
267 void f(const S** target) {
269 useConstRef(**target);
270 useConstPtr(*target);
271 useConstPtrRef(*target);
272 useConstPtrPtr(target);
273 useConstPtrConstPtr(target);
274 useConstPtrConstRef(*target);
282 useInt((*target)->int_member);
283 useIntConstRef((*target)->int_member);
284 useIntPtr((*target)->ptr_member);
285 useIntConstPtr(&(*target)->int_member);
290 TEST(ConstReferenceDeclRefExprsTest
, ConstPtrConstPtrVar
) {
292 void f(const S* const* target) {
294 useConstRef(**target);
295 useConstPtr(*target);
296 useConstPtrConstPtr(target);
297 useConstPtrConstRef(*target);
305 useInt((*target)->int_member);
306 useIntConstRef((*target)->int_member);
307 useIntPtr((*target)->ptr_member);
308 useIntConstPtr(&(*target)->int_member);