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