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 170 171 172 173
|
// RUN: %clang_cc1 %s -verify
// RUN: %clang_cc1 %s -DCODEGEN -emit-llvm -o - | FileCheck %s
#define O_CREAT 0x100
typedef int mode_t;
typedef unsigned long size_t;
enum { TRUE = 1 };
int open(const char *pathname, int flags) __attribute__((enable_if(!(flags & O_CREAT), "must specify mode when using O_CREAT"))) __attribute__((overloadable)); // expected-note{{candidate disabled: must specify mode when using O_CREAT}}
int open(const char *pathname, int flags, mode_t mode) __attribute__((overloadable)); // expected-note{{candidate function not viable: requires 3 arguments, but 2 were provided}}
void test1(void) {
#ifndef CODEGEN
open("path", O_CREAT); // expected-error{{no matching function for call to 'open'}}
#endif
open("path", O_CREAT, 0660);
open("path", 0);
open("path", 0, 0);
}
size_t __strnlen_chk(const char *s, size_t requested_amount, size_t s_len);
size_t strnlen(const char *s, size_t maxlen)
__attribute__((overloadable))
__asm__("strnlen_real1");
__attribute__((always_inline))
inline size_t strnlen(const char *s, size_t maxlen)
__attribute__((overloadable))
__attribute__((enable_if(__builtin_object_size(s, 0) != -1,
"chosen when target buffer size is known")))
{
return __strnlen_chk(s, maxlen, __builtin_object_size(s, 0));
}
size_t strnlen(const char *s, size_t maxlen)
__attribute__((overloadable))
__attribute__((enable_if(__builtin_object_size(s, 0) != -1,
"chosen when target buffer size is known")))
__attribute__((enable_if(maxlen <= __builtin_object_size(s, 0),
"chosen when 'maxlen' is known to be less than or equal to the buffer size")))
__asm__("strnlen_real2");
size_t strnlen(const char *s, size_t maxlen) // expected-note {{'strnlen' has been explicitly marked unavailable here}}
__attribute__((overloadable))
__attribute__((enable_if(__builtin_object_size(s, 0) != -1,
"chosen when target buffer size is known")))
__attribute__((enable_if(maxlen > __builtin_object_size(s, 0),
"chosen when 'maxlen' is larger than the buffer size")))
__attribute__((unavailable("'maxlen' is larger than the buffer size")));
void test2(const char *s, int i) {
// CHECK: define {{.*}}void @test2
const char c[123];
strnlen(s, i);
// CHECK: call {{.*}}strnlen_real1
strnlen(s, 999);
// CHECK: call {{.*}}strnlen_real1
strnlen(c, 1);
// CHECK: call {{.*}}strnlen_real2
strnlen(c, i);
// CHECK: call {{.*}}strnlen_chk
#ifndef CODEGEN
strnlen(c, 999); // expected-error{{'strnlen' is unavailable: 'maxlen' is larger than the buffer size}}
#endif
}
int isdigit(int c) __attribute__((overloadable));
int isdigit(int c) __attribute__((overloadable)) // expected-note {{'isdigit' has been explicitly marked unavailable here}}
__attribute__((enable_if(c <= -1 || c > 255, "'c' must have the value of an unsigned char or EOF")))
__attribute__((unavailable("'c' must have the value of an unsigned char or EOF")));
void test3(int c) {
isdigit(c); // expected-warning{{ignoring return value of function declared with pure attribute}}
isdigit(10); // expected-warning{{ignoring return value of function declared with pure attribute}}
#ifndef CODEGEN
isdigit(-10); // expected-error{{'isdigit' is unavailable: 'c' must have the value of an unsigned char or EOF}}
#endif
}
// Verify that the alternate spelling __enable_if__ works as well.
int isdigit2(int c) __attribute__((overloadable));
int isdigit2(int c) __attribute__((overloadable)) // expected-note {{'isdigit2' has been explicitly marked unavailable here}}
__attribute__((__enable_if__(c <= -1 || c > 255, "'c' must have the value of an unsigned char or EOF")))
__attribute__((unavailable("'c' must have the value of an unsigned char or EOF")));
void test4(int c) {
isdigit2(c);
isdigit2(10);
#ifndef CODEGEN
isdigit2(-10); // expected-error{{'isdigit2' is unavailable: 'c' must have the value of an unsigned char or EOF}}
#endif
}
void test5(void) {
int (*p1)(int) = &isdigit2;
int (*p2)(int) = isdigit2;
void *p3 = (void *)&isdigit2;
void *p4 = (void *)isdigit2;
}
#ifndef CODEGEN
__attribute__((enable_if(n == 0, "chosen when 'n' is zero"))) void f1(int n); // expected-error{{use of undeclared identifier 'n'}}
int n __attribute__((enable_if(1, "always chosen"))); // expected-warning{{'enable_if' attribute only applies to functions}}
void f(int n) __attribute__((enable_if("chosen when 'n' is zero", n == 0))); // expected-error{{'enable_if' attribute requires a string}}
void f(int n) __attribute__((enable_if())); // expected-error{{'enable_if' attribute requires exactly 2 arguments}}
void f(int n) __attribute__((enable_if(unresolvedid, "chosen when 'unresolvedid' is non-zero"))); // expected-error{{use of undeclared identifier 'unresolvedid'}}
int global;
void f(int n) __attribute__((enable_if(global == 0, "chosen when 'global' is zero"))); // expected-error{{'enable_if' attribute expression never produces a constant expression}} // expected-note{{subexpression not valid in a constant expression}}
enum { cst = 7 };
void return_cst(void) __attribute__((overloadable)) __attribute__((enable_if(cst == 7, "chosen when 'cst' is 7")));
void test_return_cst(void) { return_cst(); }
void f2(void) __attribute__((overloadable)) __attribute__((enable_if(1, "always chosen")));
void f2(void) __attribute__((overloadable)) __attribute__((enable_if(0, "never chosen")));
void f2(void) __attribute__((overloadable)) __attribute__((enable_if(TRUE, "always chosen #2")));
void test6(void) {
void (*p1)(void) = &f2; // expected-error{{initializing 'void (*)(void)' with an expression of incompatible type '<overloaded function type>'}} expected-note@121{{candidate function}} expected-note@122{{candidate function made ineligible by enable_if}} expected-note@123{{candidate function}}
void (*p2)(void) = f2; // expected-error{{initializing 'void (*)(void)' with an expression of incompatible type '<overloaded function type>'}} expected-note@121{{candidate function}} expected-note@122{{candidate function made ineligible by enable_if}} expected-note@123{{candidate function}}
void *p3 = (void*)&f2; // expected-error{{address of overloaded function 'f2' is ambiguous}} expected-note@121{{candidate function}} expected-note@122{{candidate function made ineligible by enable_if}} expected-note@123{{candidate function}}
void *p4 = (void*)f2; // expected-error{{address of overloaded function 'f2' is ambiguous}} expected-note@121{{candidate function}} expected-note@122{{candidate function made ineligible by enable_if}} expected-note@123{{candidate function}}
}
void f3(int m) __attribute__((overloadable)) __attribute__((enable_if(m >= 0, "positive")));
void f3(int m) __attribute__((overloadable)) __attribute__((enable_if(m < 0, "negative")));
void test7(void) {
void (*p1)(int) = &f3; // expected-error{{initializing 'void (*)(int)' with an expression of incompatible type '<overloaded function type>'}} expected-note@131{{candidate function made ineligible by enable_if}} expected-note@132{{candidate function made ineligible by enable_if}}
void (*p2)(int) = f3; // expected-error{{initializing 'void (*)(int)' with an expression of incompatible type '<overloaded function type>'}} expected-note@131{{candidate function made ineligible by enable_if}} expected-note@132{{candidate function made ineligible by enable_if}}
void *p3 = (void*)&f3; // expected-error{{address of overloaded function 'f3' does not match required type 'void'}} expected-note@131{{candidate function made ineligible by enable_if}} expected-note@132{{candidate function made ineligible by enable_if}}
void *p4 = (void*)f3; // expected-error{{address of overloaded function 'f3' does not match required type 'void'}} expected-note@131{{candidate function made ineligible by enable_if}} expected-note@132{{candidate function made ineligible by enable_if}}
}
void f4(int m) __attribute__((enable_if(0, "")));
void test8(void) {
void (*p1)(int) = &f4; // expected-error{{cannot take address of function 'f4' because it has one or more non-tautological enable_if conditions}}
void (*p2)(int) = f4; // expected-error{{cannot take address of function 'f4' because it has one or more non-tautological enable_if conditions}}
}
void regular_enable_if(int a) __attribute__((enable_if(a, ""))); // expected-note 3{{declared here}}
void PR27122_ext(void) {
regular_enable_if(0, 2); // expected-error{{too many arguments}}
regular_enable_if(1, 2); // expected-error{{too many arguments}}
regular_enable_if(); // expected-error{{too few arguments}}
}
// We had a bug where we'd crash upon trying to evaluate varargs.
void variadic_enable_if(int a, ...) __attribute__((enable_if(a, ""))); // expected-note 6 {{disabled}}
void variadic_test(void) {
variadic_enable_if(1);
variadic_enable_if(1, 2);
variadic_enable_if(1, "c", 3);
variadic_enable_if(0); // expected-error{{no matching}}
variadic_enable_if(0, 2); // expected-error{{no matching}}
variadic_enable_if(0, "c", 3); // expected-error{{no matching}}
int m;
variadic_enable_if(1);
variadic_enable_if(1, m);
variadic_enable_if(1, m, "c");
variadic_enable_if(0); // expected-error{{no matching}}
variadic_enable_if(0, m); // expected-error{{no matching}}
variadic_enable_if(0, m, 3); // expected-error{{no matching}}
}
#endif
|