357 lines · cpp
1// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-const-or-ref-data-members %t2namespace std {3template <typename T>4struct unique_ptr {};5 6template <typename T>7struct shared_ptr {};8} // namespace std9 10namespace gsl {11template <typename T>12struct not_null {};13} // namespace gsl14 15struct Ok {16 int i;17 int *p;18 const int *pc;19 std::unique_ptr<int> up;20 std::shared_ptr<int> sp;21 gsl::not_null<int*> n;22};23 24struct ConstMember {25 const int c;26 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const int' is const qualified [cppcoreguidelines-avoid-const-or-ref-data-members]27};28 29struct LvalueRefMember {30 int &lr;31 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'int &' is a reference32};33 34struct ConstRefMember {35 const int &cr;36 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const int &' is a reference37};38 39struct RvalueRefMember {40 int &&rr;41 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'int &&' is a reference42};43 44struct ConstAndRefMembers {45 const int c;46 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const int' is const qualified47 int &lr;48 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'int &' is a reference49 const int &cr;50 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const int &' is a reference51 int &&rr;52 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'int &&' is a reference53};54 55struct Foo {};56 57struct Ok2 {58 Foo i;59 Foo *p;60 const Foo *pc;61 std::unique_ptr<Foo> up;62 std::shared_ptr<Foo> sp;63 gsl::not_null<Foo*> n;64};65 66struct ConstMember2 {67 const Foo c;68 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const Foo' is const qualified69};70 71struct LvalueRefMember2 {72 Foo &lr;73 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'Foo &' is a reference74};75 76struct ConstRefMember2 {77 const Foo &cr;78 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const Foo &' is a reference79};80 81struct RvalueRefMember2 {82 Foo &&rr;83 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'Foo &&' is a reference84};85 86struct ConstAndRefMembers2 {87 const Foo c;88 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const Foo' is const qualified89 Foo &lr;90 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'Foo &' is a reference91 const Foo &cr;92 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const Foo &' is a reference93 Foo &&rr;94 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'Foo &&' is a reference95};96 97using ConstType = const int;98using RefType = int &;99using ConstRefType = const int &;100using RefRefType = int &&;101 102struct WithAlias {103 ConstType c;104 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'ConstType' (aka 'const int') is const qualified105 RefType lr;106 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: member 'lr' of type 'RefType' (aka 'int &') is a reference107 ConstRefType cr;108 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: member 'cr' of type 'ConstRefType' (aka 'const int &') is a reference109 RefRefType rr;110 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'rr' of type 'RefRefType' (aka 'int &&') is a reference111};112 113template <int N>114using Array = int[N];115 116struct ConstArrayMember {117 const Array<1> c;118 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: member 'c' of type 'const Array<1>' (aka 'const int[1]') is const qualified119};120 121struct LvalueRefArrayMember {122 Array<2> &lr;123 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'lr' of type 'Array<2> &' (aka 'int (&)[2]') is a reference124};125 126struct ConstLvalueRefArrayMember {127 const Array<3> &cr;128 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: member 'cr' of type 'const Array<3> &' (aka 'const int (&)[3]') is a reference129};130 131struct RvalueRefArrayMember {132 Array<4> &&rr;133 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'rr' of type 'Array<4> &&' (aka 'int (&&)[4]') is a reference134};135 136template <typename T>137struct TemplatedOk {138 T t;139};140 141template <typename T>142struct TemplatedConst {143 T t;144 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'const int' is const qualified145};146 147template <typename T>148struct TemplatedConstRef {149 T t;150 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'const int &' is a reference151};152 153template <typename T>154struct TemplatedRefRef {155 T t;156 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'int &&' is a reference157};158 159template <typename T>160struct TemplatedRef {161 T t;162 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'int &' is a reference163};164 165TemplatedOk<int> t1{};166TemplatedConst<const int> t2{123};167TemplatedConstRef<const int &> t3{123};168TemplatedRefRef<int &&> t4{123};169TemplatedRef<int &> t5{t1.t};170 171// Lambdas capturing const or ref members should not trigger warnings172void lambdas()173{174 int x1{123};175 const int x2{123};176 const int& x3{123};177 int&& x4{123};178 int& x5{x1};179 180 auto v1 = [x1]{};181 auto v2 = [x2]{};182 auto v3 = [x3]{};183 auto v4 = [x4]{};184 auto v5 = [x5]{};185 186 auto r1 = [&x1]{};187 auto r2 = [&x2]{};188 auto r3 = [&x3]{};189 auto r4 = [&x4]{};190 auto r5 = [&x5]{};191 192 auto iv = [=]{193 auto c1 = x1;194 auto c2 = x2;195 auto c3 = x3;196 auto c4 = x4;197 auto c5 = x5;198 };199 200 auto ir = [&]{201 auto c1 = x1;202 auto c2 = x2;203 auto c3 = x3;204 auto c4 = x4;205 auto c5 = x5;206 };207}208 209struct NonCopyableWithRef210{211 NonCopyableWithRef(NonCopyableWithRef const&) = delete;212 NonCopyableWithRef& operator=(NonCopyableWithRef const&) = delete;213 NonCopyableWithRef(NonCopyableWithRef&&) = default;214 NonCopyableWithRef& operator=(NonCopyableWithRef&&) = default;215 216 int& x;217 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference218};219 220struct NonMovableWithRef221{222 NonMovableWithRef(NonMovableWithRef const&) = default;223 NonMovableWithRef& operator=(NonMovableWithRef const&) = default;224 NonMovableWithRef(NonMovableWithRef&&) = delete;225 NonMovableWithRef& operator=(NonMovableWithRef&&) = delete;226 227 int& x;228 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference229};230 231struct NonCopyableNonMovableWithRef232{233 NonCopyableNonMovableWithRef(NonCopyableNonMovableWithRef const&) = delete;234 NonCopyableNonMovableWithRef(NonCopyableNonMovableWithRef&&) = delete;235 NonCopyableNonMovableWithRef& operator=(NonCopyableNonMovableWithRef const&) = delete;236 NonCopyableNonMovableWithRef& operator=(NonCopyableNonMovableWithRef&&) = delete;237 238 int& x; // OK, non copyable nor movable239};240 241struct NonCopyable242{243 NonCopyable(NonCopyable const&) = delete;244 NonCopyable& operator=(NonCopyable const&) = delete;245 NonCopyable(NonCopyable&&) = default;246 NonCopyable& operator=(NonCopyable&&) = default;247};248 249struct NonMovable250{251 NonMovable(NonMovable const&) = default;252 NonMovable& operator=(NonMovable const&) = default;253 NonMovable(NonMovable&&) = delete;254 NonMovable& operator=(NonMovable&&) = delete;255};256 257struct NonCopyableNonMovable258{259 NonCopyableNonMovable(NonCopyableNonMovable const&) = delete;260 NonCopyableNonMovable(NonCopyableNonMovable&&) = delete;261 NonCopyableNonMovable& operator=(NonCopyableNonMovable const&) = delete;262 NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;263};264 265// Test inheritance266struct InheritFromNonCopyable : NonCopyable267{268 int& x;269 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference270};271 272struct InheritFromNonMovable : NonMovable273{274 int& x;275 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference276};277 278struct InheritFromNonCopyableNonMovable : NonCopyableNonMovable279{280 int& x; // OK, non copyable nor movable281};282 283struct InheritBothFromNonCopyableAndNonMovable : NonCopyable, NonMovable284{285 int& x; // OK, non copyable nor movable286};287 288template<class T> struct TemplateInheritFromNonCopyable : NonCopyable289{290 int& x;291 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference292};293 294template<class T> struct TemplateInheritFromNonMovable : NonMovable295{296 int& x;297 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference298};299 300template<class T> struct TemplateInheritFromNonCopyableNonMovable : NonCopyableNonMovable301{302 int& x; // OK, non copyable nor movable303};304 305template<class T> struct TemplateInheritBothFromNonCopyableAndNonMovable : NonCopyable, NonMovable306{307 int& x; // OK, non copyable nor movable308};309 310// Test composition311struct ContainsNonCopyable312{313 NonCopyable x;314 int& y;315 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'y' of type 'int &' is a reference316};317 318struct ContainsNonMovable319{320 NonMovable x;321 int& y;322 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'y' of type 'int &' is a reference323};324 325struct ContainsNonCopyableNonMovable326{327 NonCopyableNonMovable x;328 int& y; // OK, non copyable nor movable329};330 331struct ContainsBothNonCopyableAndNonMovable332{333 NonCopyable x;334 NonMovable y;335 int& z; // OK, non copyable nor movable336};337 338// If copies are deleted and moves are not declared, moves are not implicitly declared,339// so the class is also not movable and we should not warn340struct NonCopyableMovesNotDeclared341{342 NonCopyableMovesNotDeclared(NonCopyableMovesNotDeclared const&) = delete;343 NonCopyableMovesNotDeclared& operator=(NonCopyableMovesNotDeclared const&) = delete;344 345 int& x; // OK, non copyable nor movable346};347 348// If moves are deleted but copies are not declared, copies are implicitly deleted,349// so the class is also not copyable and we should not warn350struct NonMovableCopiesNotDeclared351{352 NonMovableCopiesNotDeclared(NonMovableCopiesNotDeclared&&) = delete;353 NonMovableCopiesNotDeclared& operator=(NonMovableCopiesNotDeclared&&) = delete;354 355 int& x; // OK, non copyable nor movable356};357