blob: 995d872dce76a0e1f509218ba8827b5507541c75 [file] [log] [blame]
Alexander Kornienkoa1a29332018-02-28 14:47:20 +00001// RUN: %check_clang_tidy %s bugprone-macro-repeated-side-effects %t
Daniel Marjamaki71c92572015-06-17 14:19:35 +00002
3#define badA(x,y) ((x)+((x)+(y))+(y))
4void bad(int ret, int a, int b) {
5 ret = badA(a++, b);
Jonas Toth0ec31852018-09-25 18:15:52 +00006 // CHECK-NOTES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
7 // CHECK-NOTES: :[[@LINE-4]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +00008 ret = badA(++a, b);
Jonas Toth0ec31852018-09-25 18:15:52 +00009 // CHECK-NOTES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
10 // CHECK-NOTES: :[[@LINE-7]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000011 ret = badA(a--, b);
Jonas Toth0ec31852018-09-25 18:15:52 +000012 // CHECK-NOTES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
13 // CHECK-NOTES: :[[@LINE-10]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000014 ret = badA(--a, b);
Jonas Toth0ec31852018-09-25 18:15:52 +000015 // CHECK-NOTES: :[[@LINE-1]]:14: warning: side effects in the 1st macro argument 'x'
16 // CHECK-NOTES: :[[@LINE-13]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000017 ret = badA(a, b++);
Jonas Toth0ec31852018-09-25 18:15:52 +000018 // CHECK-NOTES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
19 // CHECK-NOTES: :[[@LINE-16]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000020 ret = badA(a, ++b);
Jonas Toth0ec31852018-09-25 18:15:52 +000021 // CHECK-NOTES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
22 // CHECK-NOTES: :[[@LINE-19]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000023 ret = badA(a, b--);
Jonas Toth0ec31852018-09-25 18:15:52 +000024 // CHECK-NOTES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
25 // CHECK-NOTES: :[[@LINE-22]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000026 ret = badA(a, --b);
Jonas Toth0ec31852018-09-25 18:15:52 +000027 // CHECK-NOTES: :[[@LINE-1]]:17: warning: side effects in the 2nd macro argument 'y'
28 // CHECK-NOTES: :[[@LINE-25]]:9: note: macro 'badA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000029}
30
31
Daniel Marjamakie0384e52015-07-02 07:49:55 +000032#define MIN(A,B) ((A) < (B) ? (A) : (B)) // single ?:
33#define LIMIT(X,A,B) ((X) < (A) ? (A) : ((X) > (B) ? (B) : (X))) // two ?:
34void question(int x) {
35 MIN(x++, 12);
Jonas Toth0ec31852018-09-25 18:15:52 +000036 // CHECK-NOTES: :[[@LINE-1]]:7: warning: side effects in the 1st macro argument 'A'
37 // CHECK-NOTES: :[[@LINE-5]]:9: note: macro 'MIN' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +000038 MIN(34, x++);
Jonas Toth0ec31852018-09-25 18:15:52 +000039 // CHECK-NOTES: :[[@LINE-1]]:11: warning: side effects in the 2nd macro argument 'B'
40 // CHECK-NOTES: :[[@LINE-8]]:9: note: macro 'MIN' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +000041 LIMIT(x++, 0, 100);
Jonas Toth0ec31852018-09-25 18:15:52 +000042 // CHECK-NOTES: :[[@LINE-1]]:9: warning: side effects in the 1st macro argument 'X'
43 // CHECK-NOTES: :[[@LINE-10]]:9: note: macro 'LIMIT' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +000044 LIMIT(20, x++, 100);
Jonas Toth0ec31852018-09-25 18:15:52 +000045 // CHECK-NOTES: :[[@LINE-1]]:13: warning: side effects in the 2nd macro argument 'A'
46 // CHECK-NOTES: :[[@LINE-13]]:9: note: macro 'LIMIT' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +000047 LIMIT(20, 0, x++);
Jonas Toth0ec31852018-09-25 18:15:52 +000048 // CHECK-NOTES: :[[@LINE-1]]:16: warning: side effects in the 3rd macro argument 'B'
49 // CHECK-NOTES: :[[@LINE-16]]:9: note: macro 'LIMIT' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +000050}
51
Daniel Marjamaki71c92572015-06-17 14:19:35 +000052// False positive: Repeated side effects is intentional.
53// It is hard to know when it's done by intention so right now we warn.
54#define UNROLL(A) {A A}
55void fp1(int i) {
56 UNROLL({ i++; });
Jonas Toth0ec31852018-09-25 18:15:52 +000057 // CHECK-NOTES: :[[@LINE-1]]:10: warning: side effects in the 1st macro argument 'A'
58 // CHECK-NOTES: :[[@LINE-4]]:9: note: macro 'UNROLL' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000059}
60
61// Do not produce a false positive on a strchr() macro. Explanation; Currently the '?'
62// triggers the test to bail out, because it cannot evaluate __builtin_constant_p(c).
63# define strchrs(s, c) \
64 (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s) \
65 && (c) == '\0' \
66 ? (char *) __rawmemchr (s, c) \
67 : __builtin_strchr (s, c)))
68char* __rawmemchr(char* a, char b) {
69 return a;
70}
71void pass(char* pstr, char ch) {
72 strchrs(pstr, ch++); // No error.
73}
74
75// Check large arguments (t=20, u=21).
76#define largeA(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, x, y, z) \
77 ((a) + (a) + (b) + (b) + (c) + (c) + (d) + (d) + (e) + (e) + (f) + (f) + (g) + (g) + \
78 (h) + (h) + (i) + (i) + (j) + (j) + (k) + (k) + (l) + (l) + (m) + (m) + (n) + (n) + \
79 (o) + (o) + (p) + (p) + (q) + (q) + (r) + (r) + (s) + (s) + (t) + (t) + (u) + (u) + \
80 (v) + (v) + (x) + (x) + (y) + (y) + (z) + (z))
81void large(int a) {
82 largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0, 0, 0);
Jonas Toth0ec31852018-09-25 18:15:52 +000083 // CHECK-NOTES: :[[@LINE-1]]:64: warning: side effects in the 19th macro argument 's'
84 // CHECK-NOTES: :[[@LINE-8]]:9: note: macro 'largeA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000085 largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0, 0);
Jonas Toth0ec31852018-09-25 18:15:52 +000086 // CHECK-NOTES: :[[@LINE-1]]:67: warning: side effects in the 20th macro argument 't'
87 // CHECK-NOTES: :[[@LINE-11]]:9: note: macro 'largeA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000088 largeA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a++, 0, 0, 0, 0);
Jonas Toth0ec31852018-09-25 18:15:52 +000089 // CHECK-NOTES: :[[@LINE-1]]:70: warning: side effects in the 21st macro argument 'u'
90 // CHECK-NOTES: :[[@LINE-14]]:9: note: macro 'largeA' defined here
Daniel Marjamaki71c92572015-06-17 14:19:35 +000091}
92
Daniel Marjamakie0384e52015-07-02 07:49:55 +000093// Passing macro argument as argument to __builtin_constant_p and macros.
94#define builtinbad(x) (__builtin_constant_p(x) + (x) + (x))
95#define builtingood1(x) (__builtin_constant_p(x) + (x))
96#define builtingood2(x) ((__builtin_constant_p(x) && (x)) || (x))
97#define macrobad(x) (builtingood1(x) + (x) + (x))
98#define macrogood(x) (builtingood1(x) + (x))
Daniel Marjamaki71c92572015-06-17 14:19:35 +000099void builtins(int ret, int a) {
Daniel Marjamakie0384e52015-07-02 07:49:55 +0000100 ret += builtinbad(a++);
Jonas Toth0ec31852018-09-25 18:15:52 +0000101 // CHECK-NOTES: :[[@LINE-1]]:21: warning: side effects in the 1st macro argument 'x'
102 // CHECK-NOTES: :[[@LINE-8]]:9: note: macro 'builtinbad' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +0000103
104 ret += builtingood1(a++);
105 ret += builtingood2(a++);
106
107 ret += macrobad(a++);
Jonas Toth0ec31852018-09-25 18:15:52 +0000108 // CHECK-NOTES: :[[@LINE-1]]:19: warning: side effects in the 1st macro argument 'x'
109 // CHECK-NOTES: :[[@LINE-12]]:9: note: macro 'macrobad' defined here
Daniel Marjamakie0384e52015-07-02 07:49:55 +0000110
111 ret += macrogood(a++);
Daniel Marjamaki71c92572015-06-17 14:19:35 +0000112}
113
114// Bail out for conditionals.
Daniel Marjamaki71c92572015-06-17 14:19:35 +0000115#define condB(x,y) if(x) {x=y;} else {x=y + 1;}
Daniel Marjamakie0384e52015-07-02 07:49:55 +0000116void conditionals(int a, int b)
Daniel Marjamaki71c92572015-06-17 14:19:35 +0000117{
Daniel Marjamaki71c92572015-06-17 14:19:35 +0000118 condB(a, b++);
119}
120
Alexander Kornienko5142c0d2016-04-23 00:00:08 +0000121void log(const char *s, int v);
122#define LOG(val) log(#val, (val))
123void test_log(int a) {
124 LOG(a++);
125}