1 | // RUN: %clang_cc1 %s -verify -fno-builtin |
2 | |
3 | #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__))) |
4 | |
5 | void failure() _diagnose_if(); // expected-error{{exactly 3 arguments}} |
6 | void failure() _diagnose_if(0); // expected-error{{exactly 3 arguments}} |
7 | void failure() _diagnose_if(0, ""); // expected-error{{exactly 3 arguments}} |
8 | void failure() _diagnose_if(0, "", "error", 1); // expected-error{{exactly 3 arguments}} |
9 | void failure() _diagnose_if(0, 0, "error"); // expected-error{{requires a string}} |
10 | void failure() _diagnose_if(0, "", "invalid"); // expected-error{{invalid diagnostic type for 'diagnose_if'; use "error" or "warning" instead}} |
11 | void failure() _diagnose_if(0, "", "ERROR"); // expected-error{{invalid diagnostic type}} |
12 | void failure(int a) _diagnose_if(a, "", ""); // expected-error{{invalid diagnostic type}} |
13 | void failure() _diagnose_if(a, "", ""); // expected-error{{undeclared identifier 'a'}} |
14 | |
15 | int globalVar; |
16 | void never_constant() _diagnose_if(globalVar, "", "error"); // expected-error{{'diagnose_if' attribute expression never produces a constant expression}} expected-note{{subexpression not valid}} |
17 | void never_constant() _diagnose_if(globalVar, "", "warning"); // expected-error{{'diagnose_if' attribute expression never produces a constant expression}} expected-note{{subexpression not valid}} |
18 | |
19 | int alwaysok(int q) _diagnose_if(0, "", "error"); |
20 | int neverok(int q) _diagnose_if(1, "oh no", "error"); // expected-note 5{{from 'diagnose_if' attribute on 'neverok'}} |
21 | int alwayswarn(int q) _diagnose_if(1, "oh no", "warning"); // expected-note 5{{from 'diagnose_if' attribute}} |
22 | int neverwarn(int q) _diagnose_if(0, "", "warning"); |
23 | |
24 | void runConstant() { |
25 | int m; |
26 | alwaysok(0); |
27 | alwaysok(1); |
28 | alwaysok(m); |
29 | |
30 | { |
31 | int (*pok)(int) = alwaysok; |
32 | pok = &alwaysok; |
33 | } |
34 | |
35 | neverok(0); // expected-error{{oh no}} |
36 | neverok(1); // expected-error{{oh no}} |
37 | neverok(m); // expected-error{{oh no}} |
38 | { |
39 | int (*pok)(int) = neverok; // expected-error{{oh no}} |
40 | pok = &neverok; // expected-error{{oh no}} |
41 | } |
42 | |
43 | alwayswarn(0); // expected-warning{{oh no}} |
44 | alwayswarn(1); // expected-warning{{oh no}} |
45 | alwayswarn(m); // expected-warning{{oh no}} |
46 | { |
47 | int (*pok)(int) = alwayswarn; // expected-warning{{oh no}} |
48 | pok = &alwayswarn; // expected-warning{{oh no}} |
49 | } |
50 | |
51 | neverwarn(0); |
52 | neverwarn(1); |
53 | neverwarn(m); |
54 | { |
55 | int (*pok)(int) = neverwarn; |
56 | pok = &neverwarn; |
57 | } |
58 | } |
59 | |
60 | int abs(int q) _diagnose_if(q >= 0, "redundant abs call", "error"); //expected-note{{from 'diagnose_if'}} |
61 | void runVariable() { |
62 | int m; |
63 | abs(-1); |
64 | abs(1); // expected-error{{redundant abs call}} |
65 | abs(m); |
66 | |
67 | int (*pabs)(int) = abs; |
68 | pabs = &abs; |
69 | } |
70 | |
71 | #define _overloadable __attribute__((overloadable)) |
72 | |
73 | int ovl1(const char *n) _overloadable _diagnose_if(n, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
74 | int ovl1(void *m) _overloadable; |
75 | |
76 | int ovl2(const char *n) _overloadable _diagnose_if(n, "oh no", "error"); // expected-note{{candidate function}} |
77 | int ovl2(char *m) _overloadable; // expected-note{{candidate function}} |
78 | void overloadsYay() { |
79 | ovl1((void *)0); |
80 | ovl1(""); // expected-error{{oh no}} |
81 | |
82 | ovl2((void *)0); // expected-error{{ambiguous}} |
83 | } |
84 | |
85 | void errorWarnDiagnose1() _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}} |
86 | _diagnose_if(1, "nop", "warning"); |
87 | void errorWarnDiagnose2() _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}} |
88 | _diagnose_if(1, "nop", "error"); |
89 | void errorWarnDiagnose3() _diagnose_if(1, "nop", "warning") |
90 | _diagnose_if(1, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
91 | |
92 | void errorWarnDiagnoseArg1(int a) _diagnose_if(a == 1, "oh no", "error") // expected-note{{from 'diagnose_if'}} |
93 | _diagnose_if(a == 1, "nop", "warning"); |
94 | void errorWarnDiagnoseArg2(int a) _diagnose_if(a == 1, "oh no", "error") // expected-note{{from 'diagnose_if'}} |
95 | _diagnose_if(a == 1, "nop", "error"); |
96 | void errorWarnDiagnoseArg3(int a) _diagnose_if(a == 1, "nop", "warning") |
97 | _diagnose_if(a == 1, "oh no", "error"); // expected-note{{from 'diagnose_if'}} |
98 | |
99 | void runErrorWarnDiagnose() { |
100 | errorWarnDiagnose1(); // expected-error{{oh no}} |
101 | errorWarnDiagnose2(); // expected-error{{oh no}} |
102 | errorWarnDiagnose3(); // expected-error{{oh no}} |
103 | |
104 | errorWarnDiagnoseArg1(1); // expected-error{{oh no}} |
105 | errorWarnDiagnoseArg2(1); // expected-error{{oh no}} |
106 | errorWarnDiagnoseArg3(1); // expected-error{{oh no}} |
107 | } |
108 | |
109 | void warnWarnDiagnose() _diagnose_if(1, "oh no!", "warning") _diagnose_if(1, "foo", "warning"); // expected-note 2{{from 'diagnose_if'}} |
110 | void runWarnWarnDiagnose() { |
111 | warnWarnDiagnose(); // expected-warning{{oh no!}} expected-warning{{foo}} |
112 | } |
113 | |
114 | void declsStackErr1(int a) _diagnose_if(a & 1, "decl1", "error"); // expected-note 2{{from 'diagnose_if'}} |
115 | void declsStackErr1(int a) _diagnose_if(a & 2, "decl2", "error"); // expected-note{{from 'diagnose_if'}} |
116 | void declsStackErr2(); |
117 | void declsStackErr2() _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}} |
118 | void declsStackErr3() _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}} |
119 | void declsStackErr3(); |
120 | void runDeclsStackErr() { |
121 | declsStackErr1(0); |
122 | declsStackErr1(1); // expected-error{{decl1}} |
123 | declsStackErr1(2); // expected-error{{decl2}} |
124 | declsStackErr1(3); // expected-error{{decl1}} |
125 | declsStackErr2(); // expected-error{{complaint}} |
126 | declsStackErr3(); // expected-error{{complaint}} |
127 | } |
128 | |
129 | void declsStackWarn1(int a) _diagnose_if(a & 1, "decl1", "warning"); // expected-note 2{{from 'diagnose_if'}} |
130 | void declsStackWarn1(int a) _diagnose_if(a & 2, "decl2", "warning"); // expected-note 2{{from 'diagnose_if'}} |
131 | void declsStackWarn2(); |
132 | void declsStackWarn2() _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}} |
133 | void declsStackWarn3() _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}} |
134 | void declsStackWarn3(); |
135 | void runDeclsStackWarn() { |
136 | declsStackWarn1(0); |
137 | declsStackWarn1(1); // expected-warning{{decl1}} |
138 | declsStackWarn1(2); // expected-warning{{decl2}} |
139 | declsStackWarn1(3); // expected-warning{{decl1}} expected-warning{{decl2}} |
140 | declsStackWarn2(); // expected-warning{{complaint}} |
141 | declsStackWarn3(); // expected-warning{{complaint}} |
142 | } |
143 | |
144 | void noMsg(int n) _diagnose_if(n, "", "warning"); // expected-note{{from 'diagnose_if'}} |
145 | void runNoMsg() { |
146 | noMsg(1); // expected-warning{{<no message provided>}} |
147 | } |
148 | |
149 | void alwaysWarnWithArg(int a) _diagnose_if(1 || a, "alwaysWarn", "warning"); // expected-note{{from 'diagnose_if'}} |
150 | void runAlwaysWarnWithArg(int a) { |
151 | alwaysWarnWithArg(a); // expected-warning{{alwaysWarn}} |
152 | } |
153 | |
154 | // Test that diagnose_if warnings generated in system headers are not ignored. |
155 | #include "Inputs/diagnose-if-warn-system-header.h" |
156 | |
157 | // Bug: we would complain about `a` being undeclared if this was spelled |
158 | // __diagnose_if__. |
159 | void underbarName(int a) __attribute__((__diagnose_if__(a, "", "warning"))); |
160 | |
161 | // PR38095 |
162 | void constCharStar(const char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}} |
163 | void charStar(char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}} |
164 | void runConstCharStar() { |
165 | constCharStar("foo"); |
166 | charStar("bar"); |
167 | constCharStar(""); // expected-error {{empty string not allowed}} |
168 | charStar(""); // expected-error {{empty string not allowed}} |
169 | } |
170 | |