342 lines · cpp
1// RUN: rm -rf %t && mkdir %t2// RUN: split-file %s %t3 4 5// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp \6// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- -- -I%t7 8// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp \9// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \10// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: at}}' -- -I%t11 12// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp \13// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \14// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \15// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t16 17 18// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-no-excl.cpp \19// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \20// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: ""}}' -- -I%t21 22// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-no-excl.cpp \23// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \24// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "", \25// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: at}}' -- -I%t26 27// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC-NO-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-no-excl.cpp \28// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \29// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "", \30// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \31// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t32 33 34// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=DEFAULT-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp \35// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \36// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "ExcludedClass1;ExcludedClass2"}}' -- -I%t37 38// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=AT-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp \39// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \40// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "ExcludedClass1;ExcludedClass2", \41// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: at}}' -- -I%t42 43// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 -check-suffix=FUNC-EXCL %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp \44// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \45// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.ExcludeClasses: "ExcludedClass1;ExcludedClass2", \46// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \47// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t48 49 50// RUN: %check_clang_tidy -std=c++23 -check-suffixes=DEFAULT-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \51// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- -- -I%t -DCXX_23=152 53// RUN: %check_clang_tidy -std=c++23 -check-suffixes=AT-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \54// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \55// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: at}}' -- -I%t -DCXX_23=1 56 57// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \58// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \59// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \60// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f"}}' -- -I%t -DCXX_23=1 61 62// RUN: %check_clang_tidy -std=c++23 -check-suffixes=FUNC-EMPTY-ARGS-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \63// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \64// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \65// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunction: "f", cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunctionEmptyArgs: "g", }}' -- -I%t -DCXX_23=166 67// RUN: %check_clang_tidy -std=c++23 -check-suffix=FUNC-EMPTY-ARGS-EMPTY-CXX-23 %t/cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp \68// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access %t -- \69// RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixMode: function, \70// RUN: cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.FixFunctionEmptyArgs: "", }}' -- -I%t -DCXX_23=171 72//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h73 74namespace std {75 template<typename T, unsigned size>76 struct array {77 T operator[](unsigned i) {78 return T{1};79 }80 T at(unsigned i) {81 return T{1};82 }83 T at() {84 return T{1};85 }86 };87 88 template<typename T, typename V>89 struct map {90 T operator[](unsigned i) {91 return T{1};92 }93 T at(unsigned i) {94 return T{1};95 }96 };97 98 template<typename T>99 struct unique_ptr {100 T operator[](unsigned i) {101 return T{1};102 }103 };104 105 template<typename T>106 struct span {107 T operator[](unsigned i) {108 return T{1};109 }110 };111} // namespace std112 113namespace json {114 template<typename T>115 struct node{116 T operator[](unsigned i) {117 return T{1};118 }119 };120} // namespace json121 122//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.cpp123 124#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h"125 126struct SubClass : std::array<int, 3> {};127 128template<class T> int f(T, unsigned){ return 0;}129template<class T> int f(T){ return 0;}130 131std::array<int, 3> a;132 133auto b = a[0];134// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]135// CHECK-FIXES-AT: auto b = a.at(0);136// CHECK-FIXES-FUNC: auto b = f(a, 0);137 138auto c = a[1+1];139// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]140// CHECK-FIXES-AT: auto c = a.at(1+1);141// CHECK-FIXES-FUNC: auto c = f(a, 1+1);142 143constexpr int Index = 1;144 145auto d = a[Index];146// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]147// CHECK-FIXES-AT: auto d = a.at(Index);148// CHECK-FIXES-FUNC: auto d = f(a, Index);149 150int e(int Ind) {151 return a[Ind];152 // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]153 // CHECK-FIXES-AT: return a.at(Ind);154 // CHECK-FIXES-FUNC: return f(a, Ind);155}156 157auto fa = (&a)->operator[](1);158// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]159// CHECK-FIXES-AT: auto fa = (&a)->at(1);160// CHECK-FIXES-FUNC: auto fa = f(*(&a), 1);161 162auto fd = a.operator[](1);163// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]164// CHECK-FIXES-AT: auto fd = a.at(1);165// CHECK-FIXES-FUNC: auto fd = f(a, 1);166 167 168 169auto g = a.at(0);170 171std::unique_ptr<int> p;172auto q = p[0];173// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]174// CHECK-FIXES-AT: auto q = p[0];175// CHECK-FIXES-FUNC: auto q = f(p, 0);176 177std::span<int> s;178auto t = s[0];179// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]180// CHECK-FIXES-AT: auto t = s[0];181// CHECK-FIXES-FUNC: auto t = f(s, 0);182 183json::node<int> n;184auto m = n[0];185// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]186// CHECK-FIXES-AT: auto m = n[0];187// CHECK-FIXES-FUNC: auto m = f(n, 0);188 189SubClass Sub;190auto r = Sub[0];191// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]192// CHECK-FIXES-AT: auto r = Sub.at(0);193// CHECK-FIXES-FUNC: auto r = f(Sub, 0);194 195typedef std::array<int, 3> ar;196ar BehindDef;197auto u = BehindDef[0];198// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:19: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]199// CHECK-FIXES-AT: auto u = BehindDef.at(0);200// CHECK-FIXES-FUNC: auto u = f(BehindDef, 0);201 202template<typename T> int TestTemplate(T t){203 return t[0];204 // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:10: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]205 206}207 208 209auto v = TestTemplate<>(a);210auto w = TestTemplate<>(p);211 212#define SUBSCRIPT_BEHIND_MACRO(x) a[x]213#define ARG_BEHIND_MACRO 0214#define OBJECT_BEHIND_MACRO a215 216auto m1 = SUBSCRIPT_BEHIND_MACRO(0);217// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]218 219auto m2 = a[ARG_BEHIND_MACRO];220// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]221// CHECK-FIXES-AT: auto m2 = a.at(ARG_BEHIND_MACRO);222// CHECK-FIXES-FUNC: auto m2 = f(a, ARG_BEHIND_MACRO);223 224auto m3 = OBJECT_BEHIND_MACRO[0];225// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:30: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]226// CHECK-FIXES-AT: auto m3 = OBJECT_BEHIND_MACRO.at(0);227// CHECK-FIXES-FUNC: auto m3 = f(OBJECT_BEHIND_MACRO, 0);228 229// Check that spacing does not invalidate the fixes 230std::array<int , 3> longname;231 232auto z1 = longname [ 0 ] ;233// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:22: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]234// CHECK-FIXES-AT: auto z1 = longname .at( 0 ) ;235// CHECK-FIXES-FUNC: auto z1 = f(longname , 0 ) ;236auto z2 = longname . operator[] ( 0 );237// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]238// CHECK-FIXES-AT: auto z2 = longname . at ( 0 );239// CHECK-FIXES-FUNC: auto z2 = f(longname , 0 );240auto z3 = (&longname) -> operator[] ( 0 );241// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:11: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]242// CHECK-FIXES-AT: auto z3 = (&longname) -> at ( 0 );243// CHECK-FIXES-FUNC: auto z3 = f(*(&longname) , 0 );244 245 246//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-no-excl.cpp247 248#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h"249 250class ExcludedClass1 {251 public:252 int operator[](unsigned i) {253 return 1;254 }255 int at(unsigned i) {256 return 1;257 }258};259 260class ExcludedClass2 {261 public:262 int operator[](unsigned i) {263 return 1;264 }265 int at(unsigned i) {266 return 1;267 }268};269 270ExcludedClass1 E1;271auto x1 = E1[0];272// CHECK-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]273// CHECK-FIXES-AT-NO-EXCL: auto x1 = E1.at(0);274// CHECK-FIXES-FUNC-NO-EXCL: auto x1 = f(E1, 0);275 276ExcludedClass2 E2;277auto x2 = E2[0];278// CHECK-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]279// CHECK-FIXES-AT-NO-EXCL: auto x2 = E2.at(0);280// CHECK-FIXES-FUNC-NO-EXCL: auto x2 = f(E2, 0);281 282std::map<int,int> TestMapNoExcl;283auto y = TestMapNoExcl[0];284// CHECK-MESSAGES-DEFAULT-NO-EXCL: :[[@LINE-1]]:23: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]285// CHECK-FIXES-AT-NO-EXCL: auto y = TestMapNoExcl.at(0);286// CHECK-FIXES-FUNC-NO-EXCL: auto y = f(TestMapNoExcl, 0);287 288 289//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-excl.cpp290 291#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h"292 293std::map<int,int> TestMapExcl;294auto y = TestMapExcl[0];295// CHECK-MESSAGES-DEFAULT-EXCL: :[[@LINE-1]]:21: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]296// CHECK-FIXES-AT-EXCL: auto y = TestMapExcl.at(0); 297// CHECK-FIXES-FUNC-EXCL: auto y = f(TestMapExcl, 0); 298 299 300//--- cppcoreguidelines-pro-bounds-avoid-unchecked-container-access-cxx-23.cpp301#ifdef CXX_23302#include "cppcoreguidelines-pro-bounds-avoid-unchecked-container-access.h"303 304namespace std {305 template<typename T, unsigned size>306 struct array_cxx_23 {307 T operator[]() {308 return T{1};309 }310 T at() {311 return T{1};312 }313 };314};315 316std::array_cxx_23<int, 3> a;317 318auto b23 = a[];319// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]320// CHECK-FIXES-AT-CXX-23: auto b23 = a.at();321// CHECK-FIXES-FUNC-CXX-23: auto b23 = f(a);322// CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto b23 = g(a);323// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] 324// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 325 326auto fa23 = (&a)->operator[]();327// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]328// CHECK-FIXES-AT-CXX-23: auto fa23 = (&a)->at();329// CHECK-FIXES-FUNC-CXX-23: auto fa23 = f(*(&a));330// CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fa23 = g(*(&a));331// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] 332// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 333 334auto fd23 = a.operator[]();335// CHECK-MESSAGES-DEFAULT-CXX-23: :[[@LINE-1]]:13: warning: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access]336// CHECK-FIXES-AT-CXX-23: auto fd23 = a.at();337// CHECK-FIXES-FUNC-CXX-23: auto fd23 = f(a);338// CHECK-FIXES-FUNC-EMPTY-ARGS-CXX-23: auto fd23 = g(a);339// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23: :[[@LINE-5]]:13: warning: possibly unsafe 'operator[]' [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access] 340// CHECK-MESSAGES-FUNC-EMPTY-ARGS-EMPTY-CXX-23-NOT: :[[@LINE-6]]:{{.*}}: note: FIX-IT applied suggested code changes 341#endif342