// RUN: %clang_cc1 -std=c23 %s -E -verify
// Test the parsing behavior for __has_embed and all of its parameters to ensure we
// recover from failures gracefully.
// expected-error@+2 {{missing '(' after '__has_embed'}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed
#endif
// expected-error@+3 {{expected '>'}} \
expected-note@+3 {{to match this '<'}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed(<)
#endif
// expected-error@+3 {{expected "FILENAME" or <FILENAME>}} \
expected-warning@+3 {{missing terminating '"' character}} \
expected-error@+3 {{invalid token at start of a preprocessor expression}}
#if __has_embed(")
#endif
// expected-error@+2 {{missing '(' after '__has_embed'}} \
expected-error@+2 {{token is not a valid binary operator in a preprocessor subexpression}}
#if __has_embed file.txt
#endif
// OK, no diagnostic for an unknown embed parameter.
#if __has_embed("media/empty" xxx)
#endif
// expected-error@+2 {{expected identifier}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" xxx::)
#endif
// OK, no diagnostic for an unknown embed parameter.
#if __has_embed("media/empty" xxx::xxx)
#endif
// expected-error@+2 {{expected identifier}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" xxx::42)
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" limit)
#endif
// We get the same diagnostic twice intentionally. The first one is because of
// the missing value within limit() and the second one is because the #if does
// not resolve to a value due to the earlier error.
// expected-error@+1 2 {{expected value in expression}}
#if __has_embed("media/empty" limit()
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" limit(xxx)
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" limit(42)
#endif
// expected-error@+2 {{invalid token at start of a preprocessor expression}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" limit([)
#endif
// expected-error@+2 {{invalid token at start of a preprocessor expression}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" limit([))
#endif
// expected-error@+2 {{division by zero in preprocessor expression}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" limit(1/0))
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" clang::offset)
#endif
// We get the same diagnostic twice intentionally. The first one is because of
// the missing value within clang::offset() and the second one is because the
// #if does not resolve to a value due to the earlier error.
// expected-error@+1 2 {{expected value in expression}}
#if __has_embed("media/empty" clang::offset()
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" clang::offset(xxx)
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" clang::offset(42)
#endif
// expected-error@+2 {{invalid token at start of a preprocessor expression}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" clang::offset([)
#endif
// expected-error@+2 {{invalid token at start of a preprocessor expression}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" clang::offset([))
#endif
// expected-error@+2 {{division by zero in preprocessor expression}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" clang::offset(1/0))
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" clang::offset 42)
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" prefix)
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" prefix()
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" prefix(xxx)
#endif
#if __has_embed("media/empty" prefix(1/0)) // OK: emitted as tokens, not evaluated yet.
#endif
#if __has_embed("media/empty" prefix(([{}]))) // OK: delimiters balanced
#endif
// expected-error@+3 {{expected '}'}} \
expected-note@+3 {{to match this '{'}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/empty" prefix(([{)]}))
#endif
// expected-error@+3 {{expected ']'}} \
expected-note@+3 {{to match this '['}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/empty" prefix(([{})}))
#endif
// expected-error@+3 {{expected ')'}} \
expected-note@+3 {{to match this '('}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/empty" prefix(([{}]}))
#endif
#if __has_embed("media/empty" prefix()) // OK: tokens within parens are optional
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" prefix))
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" suffix)
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" suffix()
#endif
// expected-error@+3 {{missing ')' after '__has_embed'}} \
expected-error@+3 {{expected value in expression}} \
expected-note@+3 {{to match this '('}}
#if __has_embed("media/empty" suffix(xxx)
#endif
#if __has_embed("media/empty" suffix(1/0)) // OK: emitted as tokens, not evaluated yet.
#endif
#if __has_embed("media/empty" suffix(([{}]))) // OK: delimiters balanced
#endif
// expected-error@+3 {{expected '}'}} \
expected-note@+3 {{to match this '{'}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/empty" suffix(([{)]}))
#endif
// expected-error@+3 {{expected ']'}} \
expected-note@+3 {{to match this '['}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/empty" suffix(([{})}))
#endif
// expected-error@+3 {{expected ')'}} \
expected-note@+3 {{to match this '('}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/empty" suffix(([{}]}))
#endif
#if __has_embed("media/empty" suffix()) // OK: tokens within parens are optional
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/empty" suffix))
#endif
#if __has_embed("media/art.txt" if_empty(1/0)) // OK: emitted as tokens, not evaluated yet.
#endif
#if __has_embed("media/art.txt" if_empty(([{}]))) // OK: delimiters balanced
#endif
// expected-error@+3 {{expected '}'}} \
expected-note@+3 {{to match this '{'}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/art.txt" if_empty(([{)]}))
#endif
// expected-error@+3 {{expected ']'}} \
expected-note@+3 {{to match this '['}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/art.txt" if_empty(([{})}))
#endif
// expected-error@+3 {{expected ')'}} \
expected-note@+3 {{to match this '('}} \
expected-error@+3 {{expected value in expression}}
#if __has_embed("media/art.txt" if_empty(([{}]}))
#endif
#if __has_embed("media/art.txt" if_empty()) // OK: tokens within parens are optional
#endif
// expected-error@+2 {{expected '('}} \
expected-error@+2 {{expected value in expression}}
#if __has_embed("media/art.txt" if_empty))
#endif