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 failure1(void) _diagnose_if(); // expected-error{{exactly 3 arguments}}
void failure2(void) _diagnose_if(0); // expected-error{{exactly 3 arguments}}
void failure3(void) _diagnose_if(0, ""); // expected-error{{exactly 3 arguments}}
void failure4(void) _diagnose_if(0, "", "error", 1); // expected-error{{exactly 3 arguments}}
void failure5(void) _diagnose_if(0, 0, "error"); // expected-error{{requires a string}}
void failure6(void) _diagnose_if(0, "", "invalid"); // expected-error{{invalid diagnostic type for 'diagnose_if'; use "error" or "warning" instead}}
void failure7(void) _diagnose_if(0, "", "ERROR"); // expected-error{{invalid diagnostic type}}
void failure8(int a) _diagnose_if(a, "", ""); // expected-error{{invalid diagnostic type}}
void failure9(void) _diagnose_if(a, "", ""); // expected-error{{undeclared identifier 'a'}}
int globalVar;
void never_constant(void) _diagnose_if(globalVar, "", "error"); // expected-error{{'diagnose_if' attribute expression never produces a constant expression}} expected-note{{subexpression not valid}}
void never_constant(void) _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(void) {
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(void) {
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(void) {
ovl1((void *)0);
ovl1(""); // expected-error{{oh no}}
ovl2((void *)0); // expected-error{{ambiguous}}
}
void errorWarnDiagnose1(void) _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}}
_diagnose_if(1, "nop", "warning");
void errorWarnDiagnose2(void) _diagnose_if(1, "oh no", "error") // expected-note{{from 'diagnose_if'}}
_diagnose_if(1, "nop", "error");
void errorWarnDiagnose3(void) _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(void) {
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(void) _diagnose_if(1, "oh no!", "warning") _diagnose_if(1, "foo", "warning"); // expected-note 2{{from 'diagnose_if'}}
void runWarnWarnDiagnose(void) {
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);
void declsStackErr2(void) _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}}
void declsStackErr3(void) _diagnose_if(1, "complaint", "error"); // expected-note{{from 'diagnose_if'}}
void declsStackErr3(void);
void runDeclsStackErr(void) {
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);
void declsStackWarn2(void) _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}}
void declsStackWarn3(void) _diagnose_if(1, "complaint", "warning"); // expected-note{{from 'diagnose_if'}}
void declsStackWarn3(void);
void runDeclsStackWarn(void) {
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(void) {
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(void) {
constCharStar("foo");
charStar("bar");
constCharStar(""); // expected-error {{empty string not allowed}}
charStar(""); // expected-error {{empty string not allowed}}
}
|