xref: /llvm-project/clang-tools-extra/unittests/clang-tidy/DeclRefExprUtilsTest.cpp (revision 415a82c64afa0047383caf471aa872fdb0e2658d)
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 = &target;
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 = &target;
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 = &target;
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