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