xref: /llvm-project/clang/test/Preprocessor/embed_weird.cpp (revision 6434dce85df21aabd5669dd9fbe8fa582e40c6ee)
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