13b724480SClement Courbet #include "../clang-tidy/utils/DeclRefExprUtils.h"
23b724480SClement Courbet #include "ClangTidyDiagnosticConsumer.h"
33b724480SClement Courbet #include "ClangTidyTest.h"
43b724480SClement Courbet #include "clang/ASTMatchers/ASTMatchFinder.h"
53b724480SClement Courbet #include "clang/ASTMatchers/ASTMatchers.h"
63b724480SClement Courbet #include "clang/Tooling/Tooling.h"
73b724480SClement Courbet #include "gtest/gtest.h"
83b724480SClement Courbet
93b724480SClement Courbet namespace clang {
103b724480SClement Courbet namespace tidy {
113b724480SClement Courbet
123b724480SClement Courbet namespace {
133b724480SClement Courbet using namespace clang::ast_matchers;
143b724480SClement Courbet
1594ca854dSClement Courbet template <int Indirections>
163b724480SClement Courbet class ConstReferenceDeclRefExprsTransform : public ClangTidyCheck {
173b724480SClement Courbet public:
ConstReferenceDeclRefExprsTransform(StringRef CheckName,ClangTidyContext * Context)183b724480SClement Courbet ConstReferenceDeclRefExprsTransform(StringRef CheckName,
193b724480SClement Courbet ClangTidyContext *Context)
203b724480SClement Courbet : ClangTidyCheck(CheckName, Context) {}
213b724480SClement Courbet
registerMatchers(MatchFinder * Finder)223b724480SClement Courbet void registerMatchers(MatchFinder *Finder) override {
233b724480SClement Courbet Finder->addMatcher(varDecl(hasName("target")).bind("var"), this);
243b724480SClement Courbet }
253b724480SClement Courbet
check(const MatchFinder::MatchResult & Result)263b724480SClement Courbet void check(const MatchFinder::MatchResult &Result) override {
273b724480SClement Courbet const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");
283b724480SClement Courbet using utils::decl_ref_expr::constReferenceDeclRefExprs;
293b724480SClement Courbet const auto const_decrefexprs = constReferenceDeclRefExprs(
303b724480SClement Courbet *D, *cast<FunctionDecl>(D->getDeclContext())->getBody(),
3194ca854dSClement Courbet *Result.Context, Indirections);
323b724480SClement Courbet
333b724480SClement Courbet for (const DeclRefExpr *const Expr : const_decrefexprs) {
343b724480SClement Courbet assert(Expr);
353b724480SClement Courbet diag(Expr->getBeginLoc(), "const usage")
363b724480SClement Courbet << FixItHint::CreateInsertion(Expr->getBeginLoc(), "/*const*/");
373b724480SClement Courbet }
383b724480SClement Courbet }
393b724480SClement Courbet };
403b724480SClement Courbet } // namespace
413b724480SClement Courbet
423b724480SClement Courbet namespace test {
433b724480SClement Courbet
RunTest(StringRef Snippet)4494ca854dSClement Courbet template <int Indirections> void RunTest(StringRef Snippet) {
453b724480SClement Courbet
463b724480SClement Courbet StringRef CommonCode = R"(
473b724480SClement Courbet struct ConstTag{};
483b724480SClement Courbet struct NonConstTag{};
49*415a82c6SClement Courbet struct Tag1{};
503b724480SClement Courbet
513b724480SClement Courbet struct S {
523b724480SClement Courbet void constMethod() const;
533b724480SClement Courbet void nonConstMethod();
543b724480SClement Courbet
55308a2360SClement Courbet static void staticMethod();
56308a2360SClement Courbet
573b724480SClement Courbet void operator()(ConstTag) const;
583b724480SClement Courbet void operator()(NonConstTag);
593b724480SClement Courbet
603b724480SClement Courbet void operator[](int);
613b724480SClement Courbet void operator[](int) const;
623b724480SClement Courbet
63*415a82c6SClement Courbet int& at(int);
64*415a82c6SClement Courbet const int& at(int) const;
65*415a82c6SClement Courbet const int& at(Tag1);
66*415a82c6SClement Courbet
67*415a82c6SClement Courbet int& weird_overload();
68*415a82c6SClement Courbet const double& weird_overload() const;
69*415a82c6SClement Courbet
703b724480SClement Courbet bool operator==(const S&) const;
713b724480SClement Courbet
723b724480SClement Courbet int int_member;
7394ca854dSClement Courbet // We consider a mutation of the `*ptr_member` to be a const use of
7494ca854dSClement Courbet // `*this`. This is consistent with the semantics of `const`-qualified
7594ca854dSClement Courbet // methods, which prevent modifying `ptr_member` but not `*ptr_member`.
763b724480SClement Courbet int* ptr_member;
773b724480SClement Courbet
783b724480SClement Courbet };
793b724480SClement Courbet
803b724480SClement Courbet struct Derived : public S {
813b724480SClement Courbet
823b724480SClement Courbet };
833b724480SClement Courbet
843b724480SClement Courbet void useVal(S);
853b724480SClement Courbet void useRef(S&);
863b724480SClement Courbet void usePtr(S*);
873b724480SClement Courbet void usePtrPtr(S**);
883b724480SClement Courbet void usePtrConstPtr(S* const*);
893b724480SClement Courbet void useConstRef(const S&);
903b724480SClement Courbet void useConstPtr(const S*);
913b724480SClement Courbet void useConstPtrRef(const S*&);
923b724480SClement Courbet void useConstPtrPtr(const S**);
933b724480SClement Courbet void useConstPtrConstRef(const S* const&);
943b724480SClement Courbet void useConstPtrConstPtr(const S* const*);
953b724480SClement Courbet
963b724480SClement Courbet void useInt(int);
973b724480SClement Courbet void useIntRef(int&);
983b724480SClement Courbet void useIntConstRef(const int&);
993b724480SClement Courbet void useIntPtr(int*);
1003b724480SClement Courbet void useIntConstPtr(const int*);
1013b724480SClement Courbet
1023b724480SClement Courbet )";
1033b724480SClement Courbet
1043b724480SClement Courbet std::string Code = (CommonCode + Snippet).str();
1053b724480SClement Courbet
1063b724480SClement Courbet llvm::SmallVector<StringRef, 1> Parts;
1073b724480SClement Courbet StringRef(Code).split(Parts, "/*const*/");
1083b724480SClement Courbet
10994ca854dSClement Courbet EXPECT_EQ(Code,
11094ca854dSClement Courbet runCheckOnCode<ConstReferenceDeclRefExprsTransform<Indirections>>(
1113b724480SClement Courbet join(Parts, "")));
1123b724480SClement Courbet }
1133b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,ConstValueVar)1143b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, ConstValueVar) {
11594ca854dSClement Courbet RunTest<0>(R"(
1163b724480SClement Courbet void f(const S target) {
1173b724480SClement Courbet useVal(/*const*/target);
1183b724480SClement Courbet useConstRef(/*const*/target);
11994ca854dSClement Courbet useConstPtr(&/*const*/target);
12094ca854dSClement Courbet useConstPtrConstRef(&/*const*/target);
1213b724480SClement Courbet /*const*/target.constMethod();
122308a2360SClement Courbet /*const*/target.staticMethod();
1233b724480SClement Courbet /*const*/target(ConstTag{});
1243b724480SClement Courbet /*const*/target[42];
1253b724480SClement Courbet useConstRef((/*const*/target));
1263b724480SClement Courbet (/*const*/target).constMethod();
127308a2360SClement Courbet /*const*/target.staticMethod();
1283b724480SClement Courbet (void)(/*const*/target == /*const*/target);
12994ca854dSClement Courbet (void)/*const*/target;
13094ca854dSClement Courbet (void)&/*const*/target;
13194ca854dSClement Courbet (void)*&/*const*/target;
13294ca854dSClement Courbet /*const*/target;
1333b724480SClement Courbet S copy1 = /*const*/target;
1343b724480SClement Courbet S copy2(/*const*/target);
13594ca854dSClement Courbet /*const*/target.int_member;
1361e512688SShivam Gupta useInt(/*const*/target.int_member);
1371e512688SShivam Gupta useIntConstRef(/*const*/target.int_member);
13894ca854dSClement Courbet useIntPtr(/*const*/target.ptr_member);
13994ca854dSClement Courbet useIntConstPtr(&/*const*/target.int_member);
14094ca854dSClement Courbet
14194ca854dSClement Courbet const S& const_target_ref = /*const*/target;
14294ca854dSClement Courbet const S* const_target_ptr = &/*const*/target;
1433b724480SClement Courbet }
1443b724480SClement Courbet )");
1453b724480SClement Courbet }
1463b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,ConstRefVar)1473b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) {
14894ca854dSClement Courbet RunTest<0>(R"(
1493b724480SClement Courbet void f(const S& target) {
1503b724480SClement Courbet useVal(/*const*/target);
1513b724480SClement Courbet useConstRef(/*const*/target);
15294ca854dSClement Courbet useConstPtr(&/*const*/target);
15394ca854dSClement Courbet useConstPtrConstRef(&/*const*/target);
1543b724480SClement Courbet /*const*/target.constMethod();
155308a2360SClement Courbet /*const*/target.staticMethod();
1563b724480SClement Courbet /*const*/target(ConstTag{});
1573b724480SClement Courbet /*const*/target[42];
1583b724480SClement Courbet useConstRef((/*const*/target));
1593b724480SClement Courbet (/*const*/target).constMethod();
1603b724480SClement Courbet (void)(/*const*/target == /*const*/target);
16194ca854dSClement Courbet (void)/*const*/target;
16294ca854dSClement Courbet (void)&/*const*/target;
16394ca854dSClement Courbet (void)*&/*const*/target;
16494ca854dSClement Courbet /*const*/target;
1653b724480SClement Courbet S copy1 = /*const*/target;
1663b724480SClement Courbet S copy2(/*const*/target);
16794ca854dSClement Courbet /*const*/target.int_member;
1681e512688SShivam Gupta useInt(/*const*/target.int_member);
1691e512688SShivam Gupta useIntConstRef(/*const*/target.int_member);
17094ca854dSClement Courbet useIntPtr(/*const*/target.ptr_member);
17194ca854dSClement Courbet useIntConstPtr(&/*const*/target.int_member);
172*415a82c6SClement Courbet (void)/*const*/target.at(3);
17394ca854dSClement Courbet
17494ca854dSClement Courbet const S& const_target_ref = /*const*/target;
17594ca854dSClement Courbet const S* const_target_ptr = &/*const*/target;
176*415a82c6SClement Courbet (void)/*const*/target.at(3);
17794ca854dSClement Courbet }
17894ca854dSClement Courbet )");
17994ca854dSClement Courbet }
18094ca854dSClement Courbet
TEST(ConstReferenceDeclRefExprsTest,DEBUGREMOVEME)18194ca854dSClement Courbet TEST(ConstReferenceDeclRefExprsTest, DEBUGREMOVEME) {
18294ca854dSClement Courbet RunTest<0>(R"(
18394ca854dSClement Courbet void f(S target, const S& other) {
18494ca854dSClement Courbet S* target_ptr = ⌖
1853b724480SClement Courbet }
1863b724480SClement Courbet )");
1873b724480SClement Courbet }
1883b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,ValueVar)1893b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, ValueVar) {
19094ca854dSClement Courbet RunTest<0>(R"(
1913b724480SClement Courbet void f(S target, const S& other) {
1923b724480SClement Courbet useConstRef(/*const*/target);
1933b724480SClement Courbet useVal(/*const*/target);
19494ca854dSClement Courbet useConstPtr(&/*const*/target);
19594ca854dSClement Courbet useConstPtrConstRef(&/*const*/target);
1963b724480SClement Courbet /*const*/target.constMethod();
197308a2360SClement Courbet /*const*/target.staticMethod();
1983b724480SClement Courbet target.nonConstMethod();
1993b724480SClement Courbet /*const*/target(ConstTag{});
200*415a82c6SClement Courbet /*const*/target[42];
2013b724480SClement Courbet /*const*/target(ConstTag{});
2023b724480SClement Courbet target(NonConstTag{});
2033b724480SClement Courbet useRef(target);
2043b724480SClement Courbet usePtr(&target);
2053b724480SClement Courbet useConstRef((/*const*/target));
2063b724480SClement Courbet (/*const*/target).constMethod();
2073b724480SClement Courbet (void)(/*const*/target == /*const*/target);
2083b724480SClement Courbet (void)(/*const*/target == other);
20994ca854dSClement Courbet (void)/*const*/target;
21094ca854dSClement Courbet (void)&/*const*/target;
21194ca854dSClement Courbet (void)*&/*const*/target;
21294ca854dSClement Courbet /*const*/target;
2133b724480SClement Courbet S copy1 = /*const*/target;
2143b724480SClement Courbet S copy2(/*const*/target);
21594ca854dSClement Courbet /*const*/target.int_member;
2161e512688SShivam Gupta useInt(/*const*/target.int_member);
2171e512688SShivam Gupta useIntConstRef(/*const*/target.int_member);
21894ca854dSClement Courbet useIntPtr(/*const*/target.ptr_member);
21994ca854dSClement Courbet useIntConstPtr(&/*const*/target.int_member);
22094ca854dSClement Courbet
22194ca854dSClement Courbet const S& const_target_ref = /*const*/target;
22294ca854dSClement Courbet const S* const_target_ptr = &/*const*/target;
22394ca854dSClement Courbet S* target_ptr = ⌖
224*415a82c6SClement Courbet
225*415a82c6SClement Courbet (void)/*const*/target.at(3);
226*415a82c6SClement Courbet ++target.at(3);
227*415a82c6SClement Courbet const int civ = /*const*/target.at(3);
228*415a82c6SClement Courbet const int& cir = /*const*/target.at(3);
229*415a82c6SClement Courbet int& ir = target.at(3);
230*415a82c6SClement Courbet target.at(Tag1{});
231*415a82c6SClement Courbet target.weird_overload();
2323b724480SClement Courbet }
2333b724480SClement Courbet )");
2343b724480SClement Courbet }
2353b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,RefVar)2363b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, RefVar) {
23794ca854dSClement Courbet RunTest<0>(R"(
2383b724480SClement Courbet void f(S& target) {
2393b724480SClement Courbet useVal(/*const*/target);
24094ca854dSClement Courbet usePtr(&target);
2413b724480SClement Courbet useConstRef(/*const*/target);
24294ca854dSClement Courbet useConstPtr(&/*const*/target);
24394ca854dSClement Courbet useConstPtrConstRef(&/*const*/target);
2443b724480SClement Courbet /*const*/target.constMethod();
245308a2360SClement Courbet /*const*/target.staticMethod();
2463b724480SClement Courbet target.nonConstMethod();
2473b724480SClement Courbet /*const*/target(ConstTag{});
248*415a82c6SClement Courbet /*const*/target[42];
2493b724480SClement Courbet useConstRef((/*const*/target));
2503b724480SClement Courbet (/*const*/target).constMethod();
2513b724480SClement Courbet (void)(/*const*/target == /*const*/target);
25294ca854dSClement Courbet (void)/*const*/target;
25394ca854dSClement Courbet (void)&/*const*/target;
25494ca854dSClement Courbet (void)*&/*const*/target;
25594ca854dSClement Courbet /*const*/target;
2563b724480SClement Courbet S copy1 = /*const*/target;
2573b724480SClement Courbet S copy2(/*const*/target);
25894ca854dSClement Courbet /*const*/target.int_member;
2591e512688SShivam Gupta useInt(/*const*/target.int_member);
2601e512688SShivam Gupta useIntConstRef(/*const*/target.int_member);
26194ca854dSClement Courbet useIntPtr(/*const*/target.ptr_member);
26294ca854dSClement Courbet useIntConstPtr(&/*const*/target.int_member);
26394ca854dSClement Courbet
26494ca854dSClement Courbet (void)(&/*const*/target)->int_member;
26594ca854dSClement Courbet useIntRef((&target)->int_member);
26694ca854dSClement Courbet
26794ca854dSClement Courbet const S& const_target_ref = /*const*/target;
26894ca854dSClement Courbet const S* const_target_ptr = &/*const*/target;
26994ca854dSClement Courbet S* target_ptr = ⌖
270*415a82c6SClement Courbet
271*415a82c6SClement Courbet (void)/*const*/target.at(3);
272*415a82c6SClement Courbet ++target.at(3);
273*415a82c6SClement Courbet const int civ = /*const*/target.at(3);
274*415a82c6SClement Courbet const int& cir = /*const*/target.at(3);
275*415a82c6SClement Courbet int& ir = target.at(3);
276*415a82c6SClement Courbet target.at(Tag1{});
277*415a82c6SClement Courbet target.weird_overload();
2783b724480SClement Courbet }
2793b724480SClement Courbet )");
2803b724480SClement Courbet }
2813b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,PtrVar)2823b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, PtrVar) {
28394ca854dSClement Courbet RunTest<1>(R"(
2843b724480SClement Courbet void f(S* target) {
28594ca854dSClement Courbet useVal(*/*const*/target);
28694ca854dSClement Courbet usePtr(target);
28794ca854dSClement Courbet useConstRef(*/*const*/target);
28894ca854dSClement Courbet useConstPtr(/*const*/target);
2893b724480SClement Courbet useConstPtrConstRef(/*const*/target);
29094ca854dSClement Courbet usePtrConstPtr(&target);
2913b724480SClement Courbet /*const*/target->constMethod();
292308a2360SClement Courbet /*const*/target->staticMethod();
2933b724480SClement Courbet target->nonConstMethod();
29494ca854dSClement Courbet (*/*const*/target)(ConstTag{});
295*415a82c6SClement Courbet (*/*const*/target)[42];
296*415a82c6SClement Courbet /*const*/target->operator[](42);
29794ca854dSClement Courbet useConstRef((*/*const*/target));
2983b724480SClement Courbet (/*const*/target)->constMethod();
29994ca854dSClement Courbet (void)(*/*const*/target == */*const*/target);
30094ca854dSClement Courbet (void)*/*const*/target;
30194ca854dSClement Courbet (void)/*const*/target;
30294ca854dSClement Courbet /*const*/target;
30394ca854dSClement Courbet S copy1 = */*const*/target;
30494ca854dSClement Courbet S copy2(*/*const*/target);
30594ca854dSClement Courbet /*const*/target->int_member;
30694ca854dSClement Courbet useInt(/*const*/target->int_member);
30794ca854dSClement Courbet useIntConstRef(/*const*/target->int_member);
30894ca854dSClement Courbet useIntPtr(/*const*/target->ptr_member);
30994ca854dSClement Courbet useIntConstPtr(&/*const*/target->int_member);
31094ca854dSClement Courbet
31194ca854dSClement Courbet const S& const_target_ref = */*const*/target;
31294ca854dSClement Courbet const S* const_target_ptr = /*const*/target;
313*415a82c6SClement Courbet S* target_ptr = target; // FIXME: we could chect const usage of `target_ptr`
314*415a82c6SClement Courbet
315*415a82c6SClement Courbet (void)/*const*/target->at(3);
316*415a82c6SClement Courbet ++target->at(3);
317*415a82c6SClement Courbet const int civ = /*const*/target->at(3);
318*415a82c6SClement Courbet const int& cir = /*const*/target->at(3);
319*415a82c6SClement Courbet int& ir = target->at(3);
320*415a82c6SClement Courbet target->at(Tag1{});
321*415a82c6SClement Courbet target->weird_overload();
3223b724480SClement Courbet }
3233b724480SClement Courbet )");
3243b724480SClement Courbet }
3253b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,ConstPtrVar)3263b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) {
32794ca854dSClement Courbet RunTest<1>(R"(
3283b724480SClement Courbet void f(const S* target) {
32994ca854dSClement Courbet useVal(*/*const*/target);
33094ca854dSClement Courbet useConstRef(*/*const*/target);
33194ca854dSClement Courbet useConstPtr(/*const*/target);
33294ca854dSClement Courbet useConstPtrRef(/*const*/target);
33394ca854dSClement Courbet useConstPtrPtr(&/*const*/target);
33494ca854dSClement Courbet useConstPtrConstPtr(&/*const*/target);
3353b724480SClement Courbet useConstPtrConstRef(/*const*/target);
3363b724480SClement Courbet /*const*/target->constMethod();
337308a2360SClement Courbet /*const*/target->staticMethod();
33894ca854dSClement Courbet (*/*const*/target)(ConstTag{});
33994ca854dSClement Courbet (*/*const*/target)[42];
3403b724480SClement Courbet /*const*/target->operator[](42);
34194ca854dSClement Courbet (void)(*/*const*/target == */*const*/target);
34294ca854dSClement Courbet (void)/*const*/target;
34394ca854dSClement Courbet (void)*/*const*/target;
34494ca854dSClement Courbet /*const*/target;
34594ca854dSClement Courbet if(/*const*/target) {}
34694ca854dSClement Courbet S copy1 = */*const*/target;
34794ca854dSClement Courbet S copy2(*/*const*/target);
34894ca854dSClement Courbet /*const*/target->int_member;
34994ca854dSClement Courbet useInt(/*const*/target->int_member);
35094ca854dSClement Courbet useIntConstRef(/*const*/target->int_member);
35194ca854dSClement Courbet useIntPtr(/*const*/target->ptr_member);
35294ca854dSClement Courbet useIntConstPtr(&/*const*/target->int_member);
35394ca854dSClement Courbet
35494ca854dSClement Courbet const S& const_target_ref = */*const*/target;
35594ca854dSClement Courbet const S* const_target_ptr = /*const*/target;
356*415a82c6SClement Courbet
357*415a82c6SClement Courbet (void)/*const*/target->at(3);
358*415a82c6SClement Courbet const int civ = /*const*/target->at(3);
359*415a82c6SClement Courbet const int& cir = /*const*/target->at(3);
3603b724480SClement Courbet }
3613b724480SClement Courbet )");
3623b724480SClement Courbet }
3633b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,ConstPtrPtrVar)3643b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, ConstPtrPtrVar) {
36594ca854dSClement Courbet RunTest<2>(R"(
3663b724480SClement Courbet void f(const S** target) {
36794ca854dSClement Courbet useVal(**/*const*/target);
36894ca854dSClement Courbet useConstRef(**/*const*/target);
36994ca854dSClement Courbet useConstPtr(*/*const*/target);
37094ca854dSClement Courbet useConstPtrRef(*/*const*/target);
37194ca854dSClement Courbet useConstPtrPtr(/*const*/target);
37294ca854dSClement Courbet useConstPtrConstPtr(/*const*/target);
37394ca854dSClement Courbet useConstPtrConstRef(*/*const*/target);
37494ca854dSClement Courbet (void)/*const*/target;
37594ca854dSClement Courbet (void)*/*const*/target;
37694ca854dSClement Courbet (void)**/*const*/target;
37794ca854dSClement Courbet /*const*/target;
37894ca854dSClement Courbet if(/*const*/target) {}
37994ca854dSClement Courbet if(*/*const*/target) {}
38094ca854dSClement Courbet S copy1 = **/*const*/target;
38194ca854dSClement Courbet S copy2(**/*const*/target);
38294ca854dSClement Courbet (*/*const*/target)->int_member;
38394ca854dSClement Courbet useInt((*/*const*/target)->int_member);
38494ca854dSClement Courbet useIntConstRef((*/*const*/target)->int_member);
38594ca854dSClement Courbet useIntPtr((*/*const*/target)->ptr_member);
38694ca854dSClement Courbet useIntConstPtr(&(*/*const*/target)->int_member);
38794ca854dSClement Courbet
38894ca854dSClement Courbet const S& const_target_ref = **/*const*/target;
38994ca854dSClement Courbet const S* const_target_ptr = */*const*/target;
3903b724480SClement Courbet }
3913b724480SClement Courbet )");
3923b724480SClement Courbet }
3933b724480SClement Courbet
TEST(ConstReferenceDeclRefExprsTest,ConstPtrConstPtrVar)3943b724480SClement Courbet TEST(ConstReferenceDeclRefExprsTest, ConstPtrConstPtrVar) {
39594ca854dSClement Courbet RunTest<2>(R"(
3963b724480SClement Courbet void f(const S* const* target) {
39794ca854dSClement Courbet useVal(**/*const*/target);
39894ca854dSClement Courbet useConstRef(**/*const*/target);
39994ca854dSClement Courbet useConstPtr(*/*const*/target);
40094ca854dSClement Courbet useConstPtrConstPtr(/*const*/target);
40194ca854dSClement Courbet useConstPtrConstRef(*/*const*/target);
40294ca854dSClement Courbet (void)/*const*/target;
40394ca854dSClement Courbet (void)*/*const*/target;
40494ca854dSClement Courbet (void)**/*const*/target;
40594ca854dSClement Courbet /*const*/target;
40694ca854dSClement Courbet if(/*const*/target) {}
40794ca854dSClement Courbet if(*/*const*/target) {}
40894ca854dSClement Courbet S copy1 = **/*const*/target;
40994ca854dSClement Courbet S copy2(**/*const*/target);
41094ca854dSClement Courbet (*/*const*/target)->int_member;
41194ca854dSClement Courbet useInt((*/*const*/target)->int_member);
41294ca854dSClement Courbet useIntConstRef((*/*const*/target)->int_member);
41394ca854dSClement Courbet useIntPtr((*/*const*/target)->ptr_member);
41494ca854dSClement Courbet useIntConstPtr(&(*/*const*/target)->int_member);
41594ca854dSClement Courbet
41694ca854dSClement Courbet const S& const_target_ref = **/*const*/target;
41794ca854dSClement Courbet const S* const_target_ptr = */*const*/target;
4183b724480SClement Courbet }
4193b724480SClement Courbet )");
4203b724480SClement Courbet }
4213b724480SClement Courbet
4223b724480SClement Courbet } // namespace test
4233b724480SClement Courbet } // namespace tidy
4243b724480SClement Courbet } // namespace clang
425