xref: /llvm-project/clang/test/Preprocessor/embed___has_embed_parsing_errors.c (revision 41c6e4379204ffc00948edd33d59ba5ebbceaba2)
1 // RUN: %clang_cc1 -std=c23 %s -E -verify
2 
3 // Test the parsing behavior for __has_embed and all of its parameters to ensure we
4 // recover from failures gracefully.
5 
6 // expected-error@+2 {{missing '(' after '__has_embed'}} \
7    expected-error@+2 {{expected value in expression}}
8 #if __has_embed
9 #endif
10 
11 // expected-error@+3 {{expected '>'}} \
12    expected-note@+3 {{to match this '<'}} \
13    expected-error@+3 {{expected value in expression}}
14 #if __has_embed(<)
15 #endif
16 
17 // expected-error@+3 {{expected "FILENAME" or <FILENAME>}} \
18    expected-warning@+3 {{missing terminating '"' character}} \
19    expected-error@+3 {{invalid token at start of a preprocessor expression}}
20 #if __has_embed(")
21 #endif
22 
23 // expected-error@+2 {{missing '(' after '__has_embed'}} \
24    expected-error@+2 {{token is not a valid binary operator in a preprocessor subexpression}}
25 #if __has_embed file.txt
26 #endif
27 
28 // OK, no diagnostic for an unknown embed parameter.
29 #if __has_embed("media/empty" xxx)
30 #endif
31 
32 // expected-error@+2 {{expected identifier}} \
33    expected-error@+2 {{expected value in expression}}
34 #if __has_embed("media/empty" xxx::)
35 #endif
36 
37 // OK, no diagnostic for an unknown embed parameter.
38 #if __has_embed("media/empty" xxx::xxx)
39 #endif
40 
41 // expected-error@+2 {{expected identifier}} \
42    expected-error@+2 {{expected value in expression}}
43 #if __has_embed("media/empty" xxx::42)
44 #endif
45 
46 // expected-error@+2 {{expected '('}} \
47    expected-error@+2 {{expected value in expression}}
48 #if __has_embed("media/empty" limit)
49 #endif
50 
51 // We get the same diagnostic twice intentionally. The first one is because of
52 // the missing value within limit() and the second one is because the #if does
53 // not resolve to a value due to the earlier error.
54 // expected-error@+1 2 {{expected value in expression}}
55 #if __has_embed("media/empty" limit()
56 #endif
57 
58 // expected-error@+3 {{missing ')' after '__has_embed'}} \
59    expected-error@+3 {{expected value in expression}} \
60    expected-note@+3 {{to match this '('}}
61 #if __has_embed("media/empty" limit(xxx)
62 #endif
63 
64 // expected-error@+3 {{missing ')' after '__has_embed'}} \
65    expected-error@+3 {{expected value in expression}} \
66    expected-note@+3 {{to match this '('}}
67 #if __has_embed("media/empty" limit(42)
68 #endif
69 
70 // expected-error@+2 {{invalid token at start of a preprocessor expression}} \
71    expected-error@+2 {{expected value in expression}}
72 #if __has_embed("media/empty" limit([)
73 #endif
74 
75 // expected-error@+2 {{invalid token at start of a preprocessor expression}} \
76    expected-error@+2 {{expected value in expression}}
77 #if __has_embed("media/empty" limit([))
78 #endif
79 
80 // expected-error@+2 {{division by zero in preprocessor expression}} \
81    expected-error@+2 {{expected value in expression}}
82 #if __has_embed("media/empty" limit(1/0))
83 #endif
84 
85 // expected-error@+2 {{expected '('}} \
86    expected-error@+2 {{expected value in expression}}
87 #if __has_embed("media/empty" clang::offset)
88 #endif
89 
90 // We get the same diagnostic twice intentionally. The first one is because of
91 // the missing value within clang::offset() and the second one is because the
92 // #if does not resolve to a value due to the earlier error.
93 // expected-error@+1 2 {{expected value in expression}}
94 #if __has_embed("media/empty" clang::offset()
95 #endif
96 
97 // expected-error@+3 {{missing ')' after '__has_embed'}} \
98    expected-error@+3 {{expected value in expression}} \
99    expected-note@+3 {{to match this '('}}
100 #if __has_embed("media/empty" clang::offset(xxx)
101 #endif
102 
103 // expected-error@+3 {{missing ')' after '__has_embed'}} \
104    expected-error@+3 {{expected value in expression}} \
105    expected-note@+3 {{to match this '('}}
106 #if __has_embed("media/empty" clang::offset(42)
107 #endif
108 
109 // expected-error@+2 {{invalid token at start of a preprocessor expression}} \
110    expected-error@+2 {{expected value in expression}}
111 #if __has_embed("media/empty" clang::offset([)
112 #endif
113 
114 // expected-error@+2 {{invalid token at start of a preprocessor expression}} \
115    expected-error@+2 {{expected value in expression}}
116 #if __has_embed("media/empty" clang::offset([))
117 #endif
118 
119 // expected-error@+2 {{division by zero in preprocessor expression}} \
120    expected-error@+2 {{expected value in expression}}
121 #if __has_embed("media/empty" clang::offset(1/0))
122 #endif
123 
124 // expected-error@+2 {{expected '('}} \
125    expected-error@+2 {{expected value in expression}}
126 #if __has_embed("media/empty" clang::offset 42)
127 #endif
128 
129 // expected-error@+2 {{expected '('}} \
130    expected-error@+2 {{expected value in expression}}
131 #if __has_embed("media/empty" prefix)
132 #endif
133 
134 // expected-error@+3 {{missing ')' after '__has_embed'}} \
135    expected-error@+3 {{expected value in expression}} \
136    expected-note@+3 {{to match this '('}}
137 #if __has_embed("media/empty" prefix()
138 #endif
139 
140 // expected-error@+3 {{missing ')' after '__has_embed'}} \
141    expected-error@+3 {{expected value in expression}} \
142    expected-note@+3 {{to match this '('}}
143 #if __has_embed("media/empty" prefix(xxx)
144 #endif
145 
146 #if __has_embed("media/empty" prefix(1/0)) // OK: emitted as tokens, not evaluated yet.
147 #endif
148 #if __has_embed("media/empty" prefix(([{}]))) // OK: delimiters balanced
149 #endif
150 // expected-error@+3 {{expected '}'}} \
151    expected-note@+3 {{to match this '{'}} \
152    expected-error@+3 {{expected value in expression}}
153 #if __has_embed("media/empty" prefix(([{)]}))
154 #endif
155 // expected-error@+3 {{expected ']'}} \
156    expected-note@+3 {{to match this '['}} \
157    expected-error@+3 {{expected value in expression}}
158 #if __has_embed("media/empty" prefix(([{})}))
159 #endif
160 // expected-error@+3 {{expected ')'}} \
161    expected-note@+3 {{to match this '('}} \
162    expected-error@+3 {{expected value in expression}}
163 #if __has_embed("media/empty" prefix(([{}]}))
164 #endif
165 #if __has_embed("media/empty" prefix()) // OK: tokens within parens are optional
166 #endif
167 // expected-error@+2 {{expected '('}} \
168    expected-error@+2 {{expected value in expression}}
169 #if __has_embed("media/empty" prefix))
170 #endif
171 
172 // expected-error@+2 {{expected '('}} \
173    expected-error@+2 {{expected value in expression}}
174 #if __has_embed("media/empty" suffix)
175 #endif
176 
177 // expected-error@+3 {{missing ')' after '__has_embed'}} \
178    expected-error@+3 {{expected value in expression}} \
179    expected-note@+3 {{to match this '('}}
180 #if __has_embed("media/empty" suffix()
181 #endif
182 
183 // expected-error@+3 {{missing ')' after '__has_embed'}} \
184    expected-error@+3 {{expected value in expression}} \
185    expected-note@+3 {{to match this '('}}
186 #if __has_embed("media/empty" suffix(xxx)
187 #endif
188 
189 #if __has_embed("media/empty" suffix(1/0)) // OK: emitted as tokens, not evaluated yet.
190 #endif
191 #if __has_embed("media/empty" suffix(([{}]))) // OK: delimiters balanced
192 #endif
193 // expected-error@+3 {{expected '}'}} \
194    expected-note@+3 {{to match this '{'}} \
195    expected-error@+3 {{expected value in expression}}
196 #if __has_embed("media/empty" suffix(([{)]}))
197 #endif
198 // expected-error@+3 {{expected ']'}} \
199    expected-note@+3 {{to match this '['}} \
200    expected-error@+3 {{expected value in expression}}
201 #if __has_embed("media/empty" suffix(([{})}))
202 #endif
203 // expected-error@+3 {{expected ')'}} \
204    expected-note@+3 {{to match this '('}} \
205    expected-error@+3 {{expected value in expression}}
206 #if __has_embed("media/empty" suffix(([{}]}))
207 #endif
208 #if __has_embed("media/empty" suffix()) // OK: tokens within parens are optional
209 #endif
210 // expected-error@+2 {{expected '('}} \
211    expected-error@+2 {{expected value in expression}}
212 #if __has_embed("media/empty" suffix))
213 #endif
214 
215 #if __has_embed("media/art.txt" if_empty(1/0)) // OK: emitted as tokens, not evaluated yet.
216 #endif
217 #if __has_embed("media/art.txt" if_empty(([{}]))) // OK: delimiters balanced
218 #endif
219 // expected-error@+3 {{expected '}'}} \
220    expected-note@+3 {{to match this '{'}} \
221    expected-error@+3 {{expected value in expression}}
222 #if __has_embed("media/art.txt" if_empty(([{)]}))
223 #endif
224 // expected-error@+3 {{expected ']'}} \
225    expected-note@+3 {{to match this '['}} \
226    expected-error@+3 {{expected value in expression}}
227 #if __has_embed("media/art.txt" if_empty(([{})}))
228 #endif
229 // expected-error@+3 {{expected ')'}} \
230    expected-note@+3 {{to match this '('}} \
231    expected-error@+3 {{expected value in expression}}
232 #if __has_embed("media/art.txt" if_empty(([{}]}))
233 #endif
234 #if __has_embed("media/art.txt" if_empty()) // OK: tokens within parens are optional
235 #endif
236 // expected-error@+2 {{expected '('}} \
237    expected-error@+2 {{expected value in expression}}
238 #if __has_embed("media/art.txt" if_empty))
239 #endif
240 
241