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 
runConstant()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'}}
runVariable()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}}
overloadsYay()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 
runErrorWarnDiagnose()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'}}
runWarnWarnDiagnose()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();
runDeclsStackErr()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();
runDeclsStackWarn()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'}}
runNoMsg()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'}}
runAlwaysWarnWithArg(int a)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}}
runConstCharStar()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