1 // RUN: %clang_cc1 %s -verify -fno-builtin 2 3 #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__))) 4 5 void failure1(void) _diagnose_if(); // expected-error{{at least 3 arguments}} 6 void failure2(void) _diagnose_if(0); // expected-error{{at least 3 arguments}} 7 void failure3(void) _diagnose_if(0, ""); // expected-error{{at least 3 arguments}} 8 void failure4(void) _diagnose_if(0, "", "error", 1); // expected-error{{expected string literal as argument}} 9 void failure5(void) _diagnose_if(0, 0, "error"); // expected-error{{expected string literal as argument of 'diagnose_if' attribute}} 10 void failure6(void) _diagnose_if(0, "", "invalid"); // expected-error{{invalid diagnostic type for 'diagnose_if'; use "error" or "warning" instead}} 11 void failure7(void) _diagnose_if(0, "", "ERROR"); // expected-error{{invalid diagnostic type}} 12 void failure8(int a) _diagnose_if(a, "", ""); // expected-error{{invalid diagnostic type}} 13 void failure9(void) _diagnose_if(a, "", ""); // expected-error{{undeclared identifier 'a'}} 14 15 int globalVar; 16 void never_constant(void) _diagnose_if(globalVar, "", "error"); // expected-error{{'diagnose_if' attribute expression never produces a constant expression}} expected-note{{subexpression not valid}} 17 void never_constant(void) _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(void) { 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(void) { 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(void) { 79 ovl1((void *)0); 80 ovl1(""); // expected-error{{oh no}} 81 82 ovl2((void *)0); // expected-error{{ambiguous}} 83 } 84 85 void errorWarnDiagnose1(void) _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}} 86 _diagnose_if(1, "nop", "warning"); 87 void errorWarnDiagnose2(void) _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}} 88 _diagnose_if(1, "nop", "error"); 89 void errorWarnDiagnose3(void) _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(void) { 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(void) _diagnose_if(1, "oh no!", "warning") _diagnose_if(1, "foo", "warning"); // expected-note 2{{from 'diagnose_if'}} 110 void runWarnWarnDiagnose(void) { 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(void); 117 void declsStackErr2(void) _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}} 118 void declsStackErr3(void) _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}} 119 void declsStackErr3(void); 120 void runDeclsStackErr(void) { 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(void); 132 void declsStackWarn2(void) _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}} 133 void declsStackWarn3(void) _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}} 134 void declsStackWarn3(void); 135 void runDeclsStackWarn(void) { 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(void) { 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(void) { 165 constCharStar("foo"); 166 charStar("bar"); 167 constCharStar(""); // expected-error {{empty string not allowed}} 168 charStar(""); // expected-error {{empty string not allowed}} 169 } 170