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