1 | // RUN: %clang_cc1 %s -verify |
2 | // RUN: %clang_cc1 %s -DCODEGEN -emit-llvm -o - | FileCheck %s |
3 | |
4 | #define O_CREAT 0x100 |
5 | typedef int mode_t; |
6 | typedef unsigned long size_t; |
7 | |
8 | const int TRUE = 1; |
9 | |
10 | 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}} |
11 | 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}} |
12 | |
13 | void test1() { |
14 | #ifndef CODEGEN |
15 | open("path", O_CREAT); // expected-error{{no matching function for call to 'open'}} |
16 | #endif |
17 | open("path", O_CREAT, 0660); |
18 | open("path", 0); |
19 | open("path", 0, 0); |
20 | } |
21 | |
22 | size_t __strnlen_chk(const char *s, size_t requested_amount, size_t s_len); |
23 | |
24 | size_t strnlen(const char *s, size_t maxlen) |
25 | __attribute__((overloadable)) |
26 | __asm__("strnlen_real1"); |
27 | |
28 | __attribute__((always_inline)) |
29 | inline size_t strnlen(const char *s, size_t maxlen) |
30 | __attribute__((overloadable)) |
31 | __attribute__((enable_if(__builtin_object_size(s, 0) != -1, |
32 | "chosen when target buffer size is known"))) |
33 | { |
34 | return __strnlen_chk(s, maxlen, __builtin_object_size(s, 0)); |
35 | } |
36 | |
37 | size_t strnlen(const char *s, size_t maxlen) |
38 | __attribute__((overloadable)) |
39 | __attribute__((enable_if(__builtin_object_size(s, 0) != -1, |
40 | "chosen when target buffer size is known"))) |
41 | __attribute__((enable_if(maxlen <= __builtin_object_size(s, 0), |
42 | "chosen when 'maxlen' is known to be less than or equal to the buffer size"))) |
43 | __asm__("strnlen_real2"); |
44 | |
45 | size_t strnlen(const char *s, size_t maxlen) // expected-note {{'strnlen' has been explicitly marked unavailable here}} |
46 | __attribute__((overloadable)) |
47 | __attribute__((enable_if(__builtin_object_size(s, 0) != -1, |
48 | "chosen when target buffer size is known"))) |
49 | __attribute__((enable_if(maxlen > __builtin_object_size(s, 0), |
50 | "chosen when 'maxlen' is larger than the buffer size"))) |
51 | __attribute__((unavailable("'maxlen' is larger than the buffer size"))); |
52 | |
53 | void test2(const char *s, int i) { |
54 | // CHECK: define {{.*}}void @test2 |
55 | const char c[123]; |
56 | strnlen(s, i); |
57 | // CHECK: call {{.*}}strnlen_real1 |
58 | strnlen(s, 999); |
59 | // CHECK: call {{.*}}strnlen_real1 |
60 | strnlen(c, 1); |
61 | // CHECK: call {{.*}}strnlen_real2 |
62 | strnlen(c, i); |
63 | // CHECK: call {{.*}}strnlen_chk |
64 | #ifndef CODEGEN |
65 | strnlen(c, 999); // expected-error{{'strnlen' is unavailable: 'maxlen' is larger than the buffer size}} |
66 | #endif |
67 | } |
68 | |
69 | int isdigit(int c) __attribute__((overloadable)); |
70 | int isdigit(int c) __attribute__((overloadable)) // expected-note {{'isdigit' has been explicitly marked unavailable here}} |
71 | __attribute__((enable_if(c <= -1 || c > 255, "'c' must have the value of an unsigned char or EOF"))) |
72 | __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); |
73 | |
74 | void test3(int c) { |
75 | isdigit(c); // expected-warning{{ignoring return value of function declared with pure attribute}} |
76 | isdigit(10); // expected-warning{{ignoring return value of function declared with pure attribute}} |
77 | #ifndef CODEGEN |
78 | isdigit(-10); // expected-error{{'isdigit' is unavailable: 'c' must have the value of an unsigned char or EOF}} |
79 | #endif |
80 | } |
81 | |
82 | // Verify that the alternate spelling __enable_if__ works as well. |
83 | int isdigit2(int c) __attribute__((overloadable)); |
84 | int isdigit2(int c) __attribute__((overloadable)) // expected-note {{'isdigit2' has been explicitly marked unavailable here}} |
85 | __attribute__((__enable_if__(c <= -1 || c > 255, "'c' must have the value of an unsigned char or EOF"))) |
86 | __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); |
87 | |
88 | void test4(int c) { |
89 | isdigit2(c); |
90 | isdigit2(10); |
91 | #ifndef CODEGEN |
92 | isdigit2(-10); // expected-error{{'isdigit2' is unavailable: 'c' must have the value of an unsigned char or EOF}} |
93 | #endif |
94 | } |
95 | |
96 | void test5() { |
97 | int (*p1)(int) = &isdigit2; |
98 | int (*p2)(int) = isdigit2; |
99 | void *p3 = (void *)&isdigit2; |
100 | void *p4 = (void *)isdigit2; |
101 | } |
102 | |
103 | #ifndef CODEGEN |
104 | __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))) void f1(int n); // expected-error{{use of undeclared identifier 'n'}} |
105 | |
106 | int n __attribute__((enable_if(1, "always chosen"))); // expected-warning{{'enable_if' attribute only applies to functions}} |
107 | |
108 | void f(int n) __attribute__((enable_if("chosen when 'n' is zero", n == 0))); // expected-error{{'enable_if' attribute requires a string}} |
109 | |
110 | void f(int n) __attribute__((enable_if())); // expected-error{{'enable_if' attribute requires exactly 2 arguments}} |
111 | |
112 | void f(int n) __attribute__((enable_if(unresolvedid, "chosen when 'unresolvedid' is non-zero"))); // expected-error{{use of undeclared identifier 'unresolvedid'}} |
113 | |
114 | int global; |
115 | 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}} |
116 | |
117 | const int cst = 7; |
118 | void return_cst(void) __attribute__((overloadable)) __attribute__((enable_if(cst == 7, "chosen when 'cst' is 7"))); |
119 | void test_return_cst() { return_cst(); } |
120 | |
121 | void f2(void) __attribute__((overloadable)) __attribute__((enable_if(1, "always chosen"))); |
122 | void f2(void) __attribute__((overloadable)) __attribute__((enable_if(0, "never chosen"))); |
123 | void f2(void) __attribute__((overloadable)) __attribute__((enable_if(TRUE, "always chosen #2"))); |
124 | void test6() { |
125 | 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}} |
126 | 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}} |
127 | 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}} |
128 | 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}} |
129 | } |
130 | |
131 | void f3(int m) __attribute__((overloadable)) __attribute__((enable_if(m >= 0, "positive"))); |
132 | void f3(int m) __attribute__((overloadable)) __attribute__((enable_if(m < 0, "negative"))); |
133 | void test7() { |
134 | 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}} |
135 | 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}} |
136 | 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}} |
137 | 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}} |
138 | } |
139 | |
140 | void f4(int m) __attribute__((enable_if(0, ""))); |
141 | void test8() { |
142 | void (*p1)(int) = &f4; // expected-error{{cannot take address of function 'f4' because it has one or more non-tautological enable_if conditions}} |
143 | void (*p2)(int) = f4; // expected-error{{cannot take address of function 'f4' because it has one or more non-tautological enable_if conditions}} |
144 | } |
145 | |
146 | void regular_enable_if(int a) __attribute__((enable_if(a, ""))); // expected-note 3{{declared here}} |
147 | void PR27122_ext() { |
148 | regular_enable_if(0, 2); // expected-error{{too many arguments}} |
149 | regular_enable_if(1, 2); // expected-error{{too many arguments}} |
150 | regular_enable_if(); // expected-error{{too few arguments}} |
151 | } |
152 | |
153 | // We had a bug where we'd crash upon trying to evaluate varargs. |
154 | void variadic_enable_if(int a, ...) __attribute__((enable_if(a, ""))); // expected-note 6 {{disabled}} |
155 | void variadic_test() { |
156 | variadic_enable_if(1); |
157 | variadic_enable_if(1, 2); |
158 | variadic_enable_if(1, "c", 3); |
159 | |
160 | variadic_enable_if(0); // expected-error{{no matching}} |
161 | variadic_enable_if(0, 2); // expected-error{{no matching}} |
162 | variadic_enable_if(0, "c", 3); // expected-error{{no matching}} |
163 | |
164 | int m; |
165 | variadic_enable_if(1); |
166 | variadic_enable_if(1, m); |
167 | variadic_enable_if(1, m, "c"); |
168 | |
169 | variadic_enable_if(0); // expected-error{{no matching}} |
170 | variadic_enable_if(0, m); // expected-error{{no matching}} |
171 | variadic_enable_if(0, m, 3); // expected-error{{no matching}} |
172 | } |
173 | #endif |
174 | |