// 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 }} \ 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