xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp (revision 84842f4b3ba175d744c03d40baa8e371522615e8)
1e8a3ddafSNathan James // RUN: %check_clang_tidy %s bugprone-assert-side-effect %t -- -config="{CheckOptions: {bugprone-assert-side-effect.CheckFunctionCalls: true, bugprone-assert-side-effect.AssertMacros: 'assert,assert2,my_assert,convoluted_assert,msvc_assert', bugprone-assert-side-effect.IgnoredFunctions: 'MyClass::badButIgnoredFunc'}}" -- -fexceptions -I %S/Inputs/assert-side-effect
20d6d8a85SCarlos Galvez #include <assert.h>
389a1d03eSRichard 
badButIgnoredFunc(int a,int b)489a1d03eSRichard bool badButIgnoredFunc(int a, int b) { return a * b > 0; }
589a1d03eSRichard 
689a1d03eSRichard class MyClass {
789a1d03eSRichard public:
badFunc(int a,int b)889a1d03eSRichard   bool badFunc(int a, int b) { return a * b > 0; }
badButIgnoredFunc(int a,int b)989a1d03eSRichard   bool badButIgnoredFunc(int a, int b) { return a * b > 0; }
goodFunc(int a,int b) const1089a1d03eSRichard   bool goodFunc(int a, int b) const { return a * b > 0; }
1189a1d03eSRichard 
operator =(const MyClass & rhs)1289a1d03eSRichard   MyClass &operator=(const MyClass &rhs) { return *this; }
1389a1d03eSRichard 
operator -()1489a1d03eSRichard   int operator-() { return 1; }
1589a1d03eSRichard 
operator bool() const1689a1d03eSRichard   operator bool() const { return true; }
1789a1d03eSRichard 
operator delete(void * p)1889a1d03eSRichard   void operator delete(void *p) {}
1989a1d03eSRichard };
2089a1d03eSRichard 
2189a1d03eSRichard class SomeoneElseClass {
2289a1d03eSRichard public:
badButIgnoredFunc(int a,int b)2389a1d03eSRichard   bool badButIgnoredFunc(int a, int b) { return a * b > 0; }
2489a1d03eSRichard };
2589a1d03eSRichard 
freeFunction()2689a1d03eSRichard bool freeFunction() {
2789a1d03eSRichard   return true;
2889a1d03eSRichard }
2989a1d03eSRichard 
main()3089a1d03eSRichard int main() {
3189a1d03eSRichard 
3289a1d03eSRichard   int X = 0;
3389a1d03eSRichard   bool B = false;
3489a1d03eSRichard   assert(X == 1);
3589a1d03eSRichard 
3689a1d03eSRichard   assert(X = 1);
3789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds [bugprone-assert-side-effect]
3889a1d03eSRichard   my_assert(X = 1);
3989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in my_assert() condition discarded in release builds
4089a1d03eSRichard   convoluted_assert(X = 1);
4189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in convoluted_assert() condition discarded in release builds
4289a1d03eSRichard   not_my_assert(X = 1);
4389a1d03eSRichard 
4489a1d03eSRichard   assert(++X);
4589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
4689a1d03eSRichard   assert(!B);
4789a1d03eSRichard 
4889a1d03eSRichard   assert(B || true);
4989a1d03eSRichard 
5089a1d03eSRichard   assert(freeFunction());
5189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
5289a1d03eSRichard 
5389a1d03eSRichard   MyClass mc;
5489a1d03eSRichard   SomeoneElseClass sec;
5589a1d03eSRichard   assert(mc.badFunc(0, 1));
5689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
5789a1d03eSRichard   assert(mc.badButIgnoredFunc(0, 1));
5889a1d03eSRichard   // badButIgnoredFunc is not ignored as only class members are ignored by the config
5989a1d03eSRichard   assert(badButIgnoredFunc(0, 1));
6089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
6189a1d03eSRichard   // sec.badButIgnoredFunc is not ignored as only MyClass members are ignored by the config
6289a1d03eSRichard   assert(sec.badButIgnoredFunc(0, 1));
6389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
6489a1d03eSRichard   assert(mc.goodFunc(0, 1));
6589a1d03eSRichard 
6689a1d03eSRichard   MyClass mc2;
6789a1d03eSRichard   assert(mc2 = mc);
6889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
6989a1d03eSRichard 
7089a1d03eSRichard   assert(-mc > 0);
7189a1d03eSRichard 
7289a1d03eSRichard   MyClass *mcp;
7389a1d03eSRichard   assert(mcp = new MyClass);
7489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
7589a1d03eSRichard 
7689a1d03eSRichard   assert((delete mcp, false));
7789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
7889a1d03eSRichard 
7989a1d03eSRichard   assert((throw 1, false));
8089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
8189a1d03eSRichard 
8289a1d03eSRichard   assert2(1 == 2 - 1);
8389a1d03eSRichard 
8489a1d03eSRichard   msvc_assert(mc2 = mc);
8589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in msvc_assert() condition discarded in release builds
8689a1d03eSRichard 
87c95d5813Sschenker   struct OperatorTest {
88c95d5813Sschenker     int operator<<(int i) const { return i; }
89c95d5813Sschenker     int operator<<(int i) { return i; }
90c95d5813Sschenker     int operator+=(int i) const { return i; }
91c95d5813Sschenker     int operator+=(int i) { return i; }
92c95d5813Sschenker   };
93c95d5813Sschenker 
94c95d5813Sschenker   const OperatorTest const_instance;
95c95d5813Sschenker   assert(const_instance << 1);
96c95d5813Sschenker   assert(const_instance += 1);
97c95d5813Sschenker 
98c95d5813Sschenker   OperatorTest non_const_instance;
99c95d5813Sschenker   assert(static_cast<const OperatorTest>(non_const_instance) << 1);
100c95d5813Sschenker   assert(static_cast<const OperatorTest>(non_const_instance) += 1);
101c95d5813Sschenker   assert(non_const_instance << 1);
102c95d5813Sschenker   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
103c95d5813Sschenker   assert(non_const_instance += 1);
104c95d5813Sschenker   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
105c95d5813Sschenker 
106c95d5813Sschenker   assert(5<<1);
107c95d5813Sschenker   assert(5>>1);
108c95d5813Sschenker 
10989a1d03eSRichard   return 0;
11089a1d03eSRichard }
111*84842f4bSCongcong Cai 
112*84842f4bSCongcong Cai namespace parameter_anaylysis {
113*84842f4bSCongcong Cai 
114*84842f4bSCongcong Cai struct S {
115*84842f4bSCongcong Cai   bool value(int) const;
116*84842f4bSCongcong Cai   bool leftValueRef(int &) const;
117*84842f4bSCongcong Cai   bool constRef(int const &) const;
118*84842f4bSCongcong Cai   bool rightValueRef(int &&) const;
119*84842f4bSCongcong Cai };
120*84842f4bSCongcong Cai 
foo()121*84842f4bSCongcong Cai void foo() {
122*84842f4bSCongcong Cai   S s{};
123*84842f4bSCongcong Cai   int i = 0;
124*84842f4bSCongcong Cai   assert(s.value(0));
125*84842f4bSCongcong Cai   assert(s.value(i));
126*84842f4bSCongcong Cai   assert(s.leftValueRef(i));
127*84842f4bSCongcong Cai   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
128*84842f4bSCongcong Cai   assert(s.constRef(0));
129*84842f4bSCongcong Cai   assert(s.constRef(i));
130*84842f4bSCongcong Cai   assert(s.rightValueRef(0));
131*84842f4bSCongcong Cai   assert(s.rightValueRef(static_cast<int &&>(i)));
132*84842f4bSCongcong Cai }
133*84842f4bSCongcong Cai 
134*84842f4bSCongcong Cai } // namespace parameter_anaylysis
135