1 // RUN: rm -rf %t && mkdir -p %t/media 2 // RUN: cp %S/Inputs/single_byte.txt %S/Inputs/jk.txt %S/Inputs/numbers.txt %t/ 3 // RUN: cp %S/Inputs/media/empty %t/media/ 4 // RUN: printf "\0" > %t/null_byte.bin 5 // RUN: %clang_cc1 %s -fsyntax-only --embed-dir=%t -verify=expected,cxx -Wno-c23-extensions 6 // RUN: %clang_cc1 -x c -std=c23 %s -fsyntax-only --embed-dir=%t -verify=expected,c 7 // RUN: %clang_cc1 %s -fsyntax-only -fexperimental-new-constant-interpreter --embed-dir=%t -verify=expected,cxx -Wno-c23-extensions 8 // RUN: %clang_cc1 -x c -std=c23 %s -fsyntax-only -fexperimental-new-constant-interpreter --embed-dir=%t -verify=expected,c 9 #embed <media/empty> 10 ; 11 12 void f (unsigned char x) { (void)x;} 13 void g () {} 14 void h (unsigned char x, int y) {(void)x; (void)y;} 15 int i () { 16 return 17 #embed <single_byte.txt> 18 ; 19 } 20 21 _Static_assert( 22 #embed <single_byte.txt> suffix(,) 23 "" 24 ); 25 _Static_assert( 26 #embed <single_byte.txt> 27 , "" 28 ); 29 _Static_assert(sizeof( 30 #embed <single_byte.txt> 31 ) == 32 sizeof(int) 33 , "" 34 ); 35 _Static_assert(sizeof 36 #embed <single_byte.txt> 37 , "" 38 ); 39 _Static_assert(sizeof( 40 #embed <jk.txt> 41 ) == 42 sizeof(int) 43 , "" 44 ); 45 46 #ifdef __cplusplus 47 template <int First, int Second> 48 void j() { 49 static_assert(First == 'j', ""); 50 static_assert(Second == 'k', ""); 51 } 52 #endif 53 54 void do_stuff() { 55 f( 56 #embed <single_byte.txt> 57 ); 58 g( 59 #embed <media/empty> 60 ); 61 h( 62 #embed <jk.txt> 63 ); 64 int r = i(); 65 (void)r; 66 #ifdef __cplusplus 67 j< 68 #embed <jk.txt> 69 >( 70 #embed <media/empty> 71 ); 72 #endif 73 } 74 75 // Ensure that we don't accidentally allow you to initialize an unsigned char * 76 // from embedded data; the data is modeled as a string literal internally, but 77 // is not actually a string literal. 78 const unsigned char *ptr = ( 79 #embed <jk.txt> // expected-warning {{left operand of comma operator has no effect}} 80 ); // c-error@-2 {{incompatible integer to pointer conversion initializing 'const unsigned char *' with an expression of type 'int'}} \ 81 cxx-error@-2 {{cannot initialize a variable of type 'const unsigned char *' with an rvalue of type 'int'}} 82 83 // However, there are some cases where this is fine and should work. 84 const unsigned char *null_ptr_1 = 85 #embed <media/empty> if_empty(0) 86 ; 87 88 const unsigned char *null_ptr_2 = 89 #embed <null_byte.bin> 90 ; 91 92 const unsigned char *null_ptr_3 = { 93 #embed <null_byte.bin> 94 }; 95 96 #define FILE_NAME <null_byte.bin> 97 #define LIMIT 1 98 #define OFFSET 0 99 #define EMPTY_SUFFIX suffix() 100 101 constexpr unsigned char ch = 102 #embed FILE_NAME limit(LIMIT) clang::offset(OFFSET) EMPTY_SUFFIX 103 ; 104 static_assert(ch == 0); 105 106 void foobar(float x, char y, char z); 107 void g1() { foobar((float) 108 #embed "numbers.txt" limit(3) 109 ); 110 } 111 112 #if __cplusplus 113 struct S { S(char x); ~S(); }; 114 void f1() { 115 S s[] = { 116 #embed "null_byte.bin" 117 }; 118 } 119 #endif 120 121 static_assert(_Generic( 122 #embed __FILE__ limit(1) 123 , int : 1, default : 0)); 124 125 static_assert(alignof(typeof( 126 #embed __FILE__ limit(1) 127 )) == alignof(int)); 128 129 struct HasChar { 130 signed char ch; 131 }; 132 133 constexpr struct HasChar c = { 134 #embed "Inputs/big_char.txt" // cxx-error {{constant expression evaluates to 255 which cannot be narrowed to type 'signed char'}} \ 135 cxx-note {{insert an explicit cast to silence this issue}} \ 136 c-error {{constexpr initializer evaluates to 255 which is not exactly representable in type 'signed char'}} 137 138 }; 139