aboutsummaryrefslogtreecommitdiff
path: root/test/Sema/diagnose_if.c
blob: 219e393bc0cc4bbd5d967781c6f58924f4a64d1d (plain) (blame)
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
// 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{{oh no}}
int ovl1(void *m) _overloadable; // expected-note{{candidate function}}

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{{call to unavailable function}}

  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}}
}