Home | History | Annotate | Download | only in Sema
      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)  // expected-note{{candidate function}}
     25   __attribute__((overloadable))
     26   __asm__("strnlen_real1");
     27 
     28 __attribute__((always_inline))
     29 inline size_t strnlen(const char *s, size_t maxlen)  // expected-note{{candidate function}}
     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)  // expected-note{{candidate disabled: chosen when 'maxlen' is known to be less than or equal to the buffer size}}
     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{{candidate function has been explicitly made unavailable}}
     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{{call to unavailable function 'strnlen': 'maxlen' is larger than the buffer size}}
     66 #endif
     67 }
     68 
     69 int isdigit(int c) __attribute__((overloadable));  // expected-note{{candidate function}}
     70 int isdigit(int c) __attribute__((overloadable))  // expected-note{{candidate function has been explicitly made unavailable}}
     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{{call to unavailable function 'isdigit': '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));  // expected-note{{candidate function}}
     84 int isdigit2(int c) __attribute__((overloadable))  // expected-note{{candidate function has been explicitly made unavailable}}
     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{{call to unavailable function 'isdigit2': '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' becuase it has one or more non-tautological enable_if conditions}}
    143   void (*p2)(int) = f4; // expected-error{{cannot take address of function 'f4' becuase 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 #endif
    153