| 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 | |
| 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'}} |
| 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}} |
| 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 | |
| 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'}} |
| 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(); |
| 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(); |
| 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'}} |
| 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'}} |
| 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}} |
| 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 | |