brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · 064e04c Raw
425 lines · cpp
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"8 9namespace clang {10namespace tidy {11 12namespace {13using namespace clang::ast_matchers;14 15template <int Indirections>16class ConstReferenceDeclRefExprsTransform : public ClangTidyCheck {17public:18  ConstReferenceDeclRefExprsTransform(StringRef CheckName,19                                      ClangTidyContext *Context)20      : ClangTidyCheck(CheckName, Context) {}21 22  void registerMatchers(MatchFinder *Finder) override {23    Finder->addMatcher(varDecl(hasName("target")).bind("var"), this);24  }25 26  void check(const MatchFinder::MatchResult &Result) override {27    const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");28    using utils::decl_ref_expr::constReferenceDeclRefExprs;29    const auto const_decrefexprs = constReferenceDeclRefExprs(30        *D, *cast<FunctionDecl>(D->getDeclContext())->getBody(),31        *Result.Context, Indirections);32 33    for (const DeclRefExpr *const Expr : const_decrefexprs) {34      assert(Expr);35      diag(Expr->getBeginLoc(), "const usage")36          << FixItHint::CreateInsertion(Expr->getBeginLoc(), "/*const*/");37    }38  }39};40} // namespace41 42namespace test {43 44template <int Indirections> void RunTest(StringRef Snippet) {45 46  StringRef CommonCode = R"(47    struct ConstTag{};48    struct NonConstTag{};49    struct Tag1{};50 51    struct S {52      void constMethod() const;53      void nonConstMethod();54 55      static void staticMethod();56 57      void operator()(ConstTag) const;58      void operator()(NonConstTag);59 60      void operator[](int);61      void operator[](int) const;62 63      int& at(int);64      const int& at(int) const;65      const int& at(Tag1);66 67      int& weird_overload();68      const double& weird_overload() const;69 70      bool operator==(const S&) const;71 72      int int_member;73      // We consider a mutation of the `*ptr_member` to be a const use of74      // `*this`. This is consistent with the semantics of `const`-qualified75      // methods, which prevent modifying `ptr_member` but not `*ptr_member`.76      int* ptr_member;77 78    };79 80    struct Derived : public S {81 82    };83 84    void useVal(S);85    void useRef(S&);86    void usePtr(S*);87    void usePtrPtr(S**);88    void usePtrConstPtr(S* const*);89    void useConstRef(const S&);90    void useConstPtr(const S*);91    void useConstPtrRef(const S*&);92    void useConstPtrPtr(const S**);93    void useConstPtrConstRef(const S* const&);94    void useConstPtrConstPtr(const S* const*);95 96    void useInt(int);97    void useIntRef(int&);98    void useIntConstRef(const int&);99    void useIntPtr(int*);100    void useIntConstPtr(const int*);101 102    )";103 104  std::string Code = (CommonCode + Snippet).str();105 106  llvm::SmallVector<StringRef, 1> Parts;107  StringRef(Code).split(Parts, "/*const*/");108 109  EXPECT_EQ(Code,110            runCheckOnCode<ConstReferenceDeclRefExprsTransform<Indirections>>(111                join(Parts, "")));112}113 114TEST(ConstReferenceDeclRefExprsTest, ConstValueVar) {115  RunTest<0>(R"(116    void f(const S target) {117      useVal(/*const*/target);118      useConstRef(/*const*/target);119      useConstPtr(&/*const*/target);120      useConstPtrConstRef(&/*const*/target);121      /*const*/target.constMethod();122      /*const*/target.staticMethod();123      /*const*/target(ConstTag{});124      /*const*/target[42];125      useConstRef((/*const*/target));126      (/*const*/target).constMethod();127      /*const*/target.staticMethod();128      (void)(/*const*/target == /*const*/target);129      (void)/*const*/target;130      (void)&/*const*/target;131      (void)*&/*const*/target;132      /*const*/target;133      S copy1 = /*const*/target;134      S copy2(/*const*/target);135      /*const*/target.int_member;136      useInt(/*const*/target.int_member);137      useIntConstRef(/*const*/target.int_member);138      useIntPtr(/*const*/target.ptr_member);139      useIntConstPtr(&/*const*/target.int_member);140 141      const S& const_target_ref = /*const*/target;142      const S* const_target_ptr = &/*const*/target;143    }144)");145}146 147TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) {148  RunTest<0>(R"(149    void f(const S& target) {150      useVal(/*const*/target);151      useConstRef(/*const*/target);152      useConstPtr(&/*const*/target);153      useConstPtrConstRef(&/*const*/target);154      /*const*/target.constMethod();155      /*const*/target.staticMethod();156      /*const*/target(ConstTag{});157      /*const*/target[42];158      useConstRef((/*const*/target));159      (/*const*/target).constMethod();160      (void)(/*const*/target == /*const*/target);161      (void)/*const*/target;162      (void)&/*const*/target;163      (void)*&/*const*/target;164      /*const*/target;165      S copy1 = /*const*/target;166      S copy2(/*const*/target);167      /*const*/target.int_member;168      useInt(/*const*/target.int_member);169      useIntConstRef(/*const*/target.int_member);170      useIntPtr(/*const*/target.ptr_member);171      useIntConstPtr(&/*const*/target.int_member);172      (void)/*const*/target.at(3);173 174      const S& const_target_ref = /*const*/target;175      const S* const_target_ptr = &/*const*/target;176      (void)/*const*/target.at(3);177    }178)");179}180 181TEST(ConstReferenceDeclRefExprsTest, DEBUGREMOVEME) {182  RunTest<0>(R"(183    void f(S target, const S& other) {184      S* target_ptr = &target;185    }186)");187}188 189TEST(ConstReferenceDeclRefExprsTest, ValueVar) {190  RunTest<0>(R"(191    void f(S target, const S& other) {192      useConstRef(/*const*/target);193      useVal(/*const*/target);194      useConstPtr(&/*const*/target);195      useConstPtrConstRef(&/*const*/target);196      /*const*/target.constMethod();197      /*const*/target.staticMethod();198      target.nonConstMethod();199      /*const*/target(ConstTag{});200      /*const*/target[42];201      /*const*/target(ConstTag{});202      target(NonConstTag{});203      useRef(target);204      usePtr(&target);205      useConstRef((/*const*/target));206      (/*const*/target).constMethod();207      (void)(/*const*/target == /*const*/target);208      (void)(/*const*/target == other);209      (void)/*const*/target;210      (void)&/*const*/target;211      (void)*&/*const*/target;212      /*const*/target;213      S copy1 = /*const*/target;214      S copy2(/*const*/target);215      /*const*/target.int_member;216      useInt(/*const*/target.int_member);217      useIntConstRef(/*const*/target.int_member);218      useIntPtr(/*const*/target.ptr_member);219      useIntConstPtr(&/*const*/target.int_member);220 221      const S& const_target_ref = /*const*/target;222      const S* const_target_ptr = &/*const*/target;223      S* target_ptr = &target;224 225      (void)/*const*/target.at(3);226      ++target.at(3);227      const int civ = /*const*/target.at(3);228      const int& cir = /*const*/target.at(3);229      int& ir = target.at(3);230      target.at(Tag1{});231      target.weird_overload();232    }233)");234}235 236TEST(ConstReferenceDeclRefExprsTest, RefVar) {237  RunTest<0>(R"(238    void f(S& target) {239      useVal(/*const*/target);240      usePtr(&target);241      useConstRef(/*const*/target);242      useConstPtr(&/*const*/target);243      useConstPtrConstRef(&/*const*/target);244      /*const*/target.constMethod();245      /*const*/target.staticMethod();246      target.nonConstMethod();247      /*const*/target(ConstTag{});248      /*const*/target[42];249      useConstRef((/*const*/target));250      (/*const*/target).constMethod();251      (void)(/*const*/target == /*const*/target);252      (void)/*const*/target;253      (void)&/*const*/target;254      (void)*&/*const*/target;255      /*const*/target;256      S copy1 = /*const*/target;257      S copy2(/*const*/target);258      /*const*/target.int_member;259      useInt(/*const*/target.int_member);260      useIntConstRef(/*const*/target.int_member);261      useIntPtr(/*const*/target.ptr_member);262      useIntConstPtr(&/*const*/target.int_member);263 264      (void)(&/*const*/target)->int_member;265      useIntRef((&target)->int_member);266 267      const S& const_target_ref = /*const*/target;268      const S* const_target_ptr = &/*const*/target;269      S* target_ptr = &target;270 271      (void)/*const*/target.at(3);272      ++target.at(3);273      const int civ = /*const*/target.at(3);274      const int& cir = /*const*/target.at(3);275      int& ir = target.at(3);276      target.at(Tag1{});277      target.weird_overload();278    }279)");280}281 282TEST(ConstReferenceDeclRefExprsTest, PtrVar) {283  RunTest<1>(R"(284    void f(S* target) {285      useVal(*/*const*/target);286      usePtr(target);287      useConstRef(*/*const*/target);288      useConstPtr(/*const*/target);289      useConstPtrConstRef(/*const*/target);290      usePtrConstPtr(&target);291      /*const*/target->constMethod();292      /*const*/target->staticMethod();293      target->nonConstMethod();294      (*/*const*/target)(ConstTag{});295      (*/*const*/target)[42];296      /*const*/target->operator[](42);297      useConstRef((*/*const*/target));298      (/*const*/target)->constMethod();299      (void)(*/*const*/target == */*const*/target);300      (void)*/*const*/target;301      (void)/*const*/target;302      /*const*/target;303      S copy1 = */*const*/target;304      S copy2(*/*const*/target);305      /*const*/target->int_member;306      useInt(/*const*/target->int_member);307      useIntConstRef(/*const*/target->int_member);308      useIntPtr(/*const*/target->ptr_member);309      useIntConstPtr(&/*const*/target->int_member);310 311      const S& const_target_ref = */*const*/target;312      const S* const_target_ptr = /*const*/target;313      S* target_ptr = target;  // FIXME: we could chect const usage of `target_ptr`314 315      (void)/*const*/target->at(3);316      ++target->at(3);317      const int civ = /*const*/target->at(3);318      const int& cir = /*const*/target->at(3);319      int& ir = target->at(3);320      target->at(Tag1{});321      target->weird_overload();322    }323)");324}325 326TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) {327  RunTest<1>(R"(328    void f(const S* target) {329      useVal(*/*const*/target);330      useConstRef(*/*const*/target);331      useConstPtr(/*const*/target);332      useConstPtrRef(/*const*/target);333      useConstPtrPtr(&/*const*/target);334      useConstPtrConstPtr(&/*const*/target);335      useConstPtrConstRef(/*const*/target);336      /*const*/target->constMethod();337      /*const*/target->staticMethod();338      (*/*const*/target)(ConstTag{});339      (*/*const*/target)[42];340      /*const*/target->operator[](42);341      (void)(*/*const*/target == */*const*/target);342      (void)/*const*/target;343      (void)*/*const*/target;344      /*const*/target;345      if(/*const*/target) {}346      S copy1 = */*const*/target;347      S copy2(*/*const*/target);348      /*const*/target->int_member;349      useInt(/*const*/target->int_member);350      useIntConstRef(/*const*/target->int_member);351      useIntPtr(/*const*/target->ptr_member);352      useIntConstPtr(&/*const*/target->int_member);353 354      const S& const_target_ref = */*const*/target;355      const S* const_target_ptr = /*const*/target;356 357      (void)/*const*/target->at(3);358      const int civ = /*const*/target->at(3);359      const int& cir = /*const*/target->at(3);360    }361)");362}363 364TEST(ConstReferenceDeclRefExprsTest, ConstPtrPtrVar) {365  RunTest<2>(R"(366    void f(const S** target) {367      useVal(**/*const*/target);368      useConstRef(**/*const*/target);369      useConstPtr(*/*const*/target);370      useConstPtrRef(*/*const*/target);371      useConstPtrPtr(/*const*/target);372      useConstPtrConstPtr(/*const*/target);373      useConstPtrConstRef(*/*const*/target);374      (void)/*const*/target;375      (void)*/*const*/target;376      (void)**/*const*/target;377      /*const*/target;378      if(/*const*/target) {}379      if(*/*const*/target) {}380      S copy1 = **/*const*/target;381      S copy2(**/*const*/target);382      (*/*const*/target)->int_member;383      useInt((*/*const*/target)->int_member);384      useIntConstRef((*/*const*/target)->int_member);385      useIntPtr((*/*const*/target)->ptr_member);386      useIntConstPtr(&(*/*const*/target)->int_member);387 388      const S& const_target_ref = **/*const*/target;389      const S* const_target_ptr = */*const*/target;390    }391)");392}393 394TEST(ConstReferenceDeclRefExprsTest, ConstPtrConstPtrVar) {395  RunTest<2>(R"(396    void f(const S* const* target) {397      useVal(**/*const*/target);398      useConstRef(**/*const*/target);399      useConstPtr(*/*const*/target);400      useConstPtrConstPtr(/*const*/target);401      useConstPtrConstRef(*/*const*/target);402      (void)/*const*/target;403      (void)*/*const*/target;404      (void)**/*const*/target;405      /*const*/target;406      if(/*const*/target) {}407      if(*/*const*/target) {}408      S copy1 = **/*const*/target;409      S copy2(**/*const*/target);410      (*/*const*/target)->int_member;411      useInt((*/*const*/target)->int_member);412      useIntConstRef((*/*const*/target)->int_member);413      useIntPtr((*/*const*/target)->ptr_member);414      useIntConstPtr(&(*/*const*/target)->int_member);415 416      const S& const_target_ref = **/*const*/target;417      const S* const_target_ptr = */*const*/target;418    }419)");420}421 422} // namespace test423} // namespace tidy424} // namespace clang425