Clang Project

clang_source_code/test/Sema/diagnose_if.c
1// RUN: %clang_cc1 %s -verify -fno-builtin
2
3#define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__)))
4
5void failure() _diagnose_if(); // expected-error{{exactly 3 arguments}}
6void failure() _diagnose_if(0); // expected-error{{exactly 3 arguments}}
7void failure() _diagnose_if(0, ""); // expected-error{{exactly 3 arguments}}
8void failure() _diagnose_if(0, "", "error", 1); // expected-error{{exactly 3 arguments}}
9void failure() _diagnose_if(0, 0, "error"); // expected-error{{requires a string}}
10void failure() _diagnose_if(0, "", "invalid"); // expected-error{{invalid diagnostic type for 'diagnose_if'; use "error" or "warning" instead}}
11void failure() _diagnose_if(0, "", "ERROR"); // expected-error{{invalid diagnostic type}}
12void failure(int a) _diagnose_if(a, "", ""); // expected-error{{invalid diagnostic type}}
13void failure() _diagnose_if(a, "", ""); // expected-error{{undeclared identifier 'a'}}
14
15int globalVar;
16void never_constant() _diagnose_if(globalVar, "", "error"); // expected-error{{'diagnose_if' attribute expression never produces a constant expression}} expected-note{{subexpression not valid}}
17void never_constant() _diagnose_if(globalVar, "", "warning"); // expected-error{{'diagnose_if' attribute expression never produces a constant expression}} expected-note{{subexpression not valid}}
18
19int alwaysok(int q) _diagnose_if(0, "", "error");
20int neverok(int q) _diagnose_if(1, "oh no", "error"); // expected-note 5{{from 'diagnose_if' attribute on 'neverok'}}
21int alwayswarn(int q) _diagnose_if(1, "oh no", "warning"); // expected-note 5{{from 'diagnose_if' attribute}}
22int neverwarn(int q) _diagnose_if(0, "", "warning");
23
24void 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
60int abs(int q) _diagnose_if(q >= 0, "redundant abs call", "error"); //expected-note{{from 'diagnose_if'}}
61void 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
73int ovl1(const char *n) _overloadable _diagnose_if(n, "oh no", "error"); // expected-note{{from 'diagnose_if'}}
74int ovl1(void *m) _overloadable;
75
76int ovl2(const char *n) _overloadable _diagnose_if(n, "oh no", "error"); // expected-note{{candidate function}}
77int ovl2(char *m) _overloadable; // expected-note{{candidate function}}
78void overloadsYay() {
79  ovl1((void *)0);
80  ovl1(""); // expected-error{{oh no}}
81
82  ovl2((void *)0); // expected-error{{ambiguous}}
83}
84
85void errorWarnDiagnose1() _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}}
86  _diagnose_if(1, "nop", "warning");
87void errorWarnDiagnose2() _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}}
88  _diagnose_if(1, "nop", "error");
89void errorWarnDiagnose3() _diagnose_if(1, "nop", "warning")
90  _diagnose_if(1, "oh no", "error"); // expected-note{{from 'diagnose_if'}}
91
92void errorWarnDiagnoseArg1(int a) _diagnose_if(a == 1, "oh no", "error") // expected-note{{from 'diagnose_if'}}
93  _diagnose_if(a == 1, "nop", "warning");
94void errorWarnDiagnoseArg2(int a) _diagnose_if(a == 1, "oh no", "error") // expected-note{{from 'diagnose_if'}}
95  _diagnose_if(a == 1, "nop", "error");
96void errorWarnDiagnoseArg3(int a) _diagnose_if(a == 1, "nop", "warning")
97  _diagnose_if(a == 1, "oh no", "error"); // expected-note{{from 'diagnose_if'}}
98
99void 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
109void warnWarnDiagnose() _diagnose_if(1, "oh no!", "warning") _diagnose_if(1, "foo", "warning"); // expected-note 2{{from 'diagnose_if'}}
110void runWarnWarnDiagnose() {
111  warnWarnDiagnose(); // expected-warning{{oh no!}} expected-warning{{foo}}
112}
113
114void declsStackErr1(int a) _diagnose_if(a & 1, "decl1", "error"); // expected-note 2{{from 'diagnose_if'}}
115void declsStackErr1(int a) _diagnose_if(a & 2, "decl2", "error"); // expected-note{{from 'diagnose_if'}}
116void declsStackErr2();
117void declsStackErr2() _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}}
118void declsStackErr3() _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}}
119void declsStackErr3();
120void 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
129void declsStackWarn1(int a) _diagnose_if(a & 1, "decl1", "warning"); // expected-note 2{{from 'diagnose_if'}}
130void declsStackWarn1(int a) _diagnose_if(a & 2, "decl2", "warning"); // expected-note 2{{from 'diagnose_if'}}
131void declsStackWarn2();
132void declsStackWarn2() _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}}
133void declsStackWarn3() _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}}
134void declsStackWarn3();
135void 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
144void noMsg(int n) _diagnose_if(n, "", "warning"); // expected-note{{from 'diagnose_if'}}
145void runNoMsg() {
146  noMsg(1); // expected-warning{{<no message provided>}}
147}
148
149void alwaysWarnWithArg(int a) _diagnose_if(1 || a, "alwaysWarn", "warning"); // expected-note{{from 'diagnose_if'}}
150void 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__.
159void underbarName(int a) __attribute__((__diagnose_if__(a, "", "warning")));
160
161// PR38095
162void constCharStar(const char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}}
163void charStar(char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}}
164void 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