// RUN: %clang_cc1 -verify -fsyntax-only --embed-dir=%S/Inputs -std=c2x %s -Wno-constant-logical-operand // RUN: %clang_cc1 -verify -fsyntax-only --embed-dir=%S/Inputs -std=c2x %s -Wno-constant-logical-operand -fexperimental-new-constant-interpreter /* WG14 N3017: full * #embed - a scannable, tooling-friendly binary resource inclusion mechanism */ // C23 6.10p6 char b1[] = { #embed "boop.h" limit(5) , #embed "boop.h" __limit__(5) }; // C23 6.10.1p19 #if __has_embed(__FILE__ ext::token(0xB055)) #error "Supports an extension parameter Clang never claimed to support?" #endif #if !__has_embed(__FILE__ clang::offset(0)) #error "Doesn't support an extension Clang claims to support?" #endif // C23 6.10.1p20 void parse_into_s(short* ptr, unsigned char* ptr_bytes, unsigned long long size); int f() { #if __has_embed ("bits.bin" ds9000::element_type(short)) /* Implementation extension: create short integers from the */ /* translation environment resource into */ /* a sequence of integer constants */ short meow[] = { #embed "bits.bin" ds9000::element_type(short) }; #elif __has_embed ("bits.bin") /* no support for implementation-specific */ /* ds9000::element_type(short) parameter */ unsigned char meow_bytes[] = { #embed "bits.bin" }; short meow[sizeof(meow_bytes) / sizeof(short)] = {}; /* parse meow_bytes into short values by-hand! */ parse_into_s(meow, meow_bytes, sizeof(meow_bytes)); #else #error "cannot find bits.bin resource" #endif return (int)(meow[0] + meow[(sizeof(meow) / sizeof(*meow)) - 1]); } // NOTE: we don't have a good way to test infinite resources from within lit. int g() { #if __has_embed( limit(0)) == 2 // if exists, this // token sequence is always taken. return 0; #else // the ’infinite-resource’ resource does not exist #error "The resource does not exist" #endif // expected-error@-2 {{"The resource does not exist"}} } #include void have_you_any_wool(const unsigned char*, size_t); int h() { static const unsigned char baa_baa[] = { #embed __FILE__ }; have_you_any_wool(baa_baa, sizeof(baa_baa)); return 0; } // C23 6.10.3.1p17: not tested here because we do not currently support any // platforms where CHAR_BIT != 8. // C23 6.10.3.1p18 int i() { /* Braces may be kept or elided as per normal initialization rules */ int i = { #embed "i.dat" }; /* valid if i.dat produces 1 value, i value is [0, 2(embed element width)) */ int i2 = #embed "i.dat" ; /* valid if i.dat produces 1 value, i2 value is [0, 2(embed element width)) */ struct s { double a, b, c; struct { double e, f, g; }; double h, i, j; }; struct s x = { /* initializes each element in order according to initialization rules with comma-separated list of integer constant expressions inside of braces */ #embed "s.dat" }; return 0; } // C23 6.10.3.1p19: not tested here because it's a runtime test rather than one // which can be handled at compile time (it validates file contents via fread). // C23 6.10.3.2p5 int j() { static const char sound_signature[] = { #embed limit(2+2) }; static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) == 4, "There should only be 4 elements in this array."); // verify PCM WAV resource static_assert(sound_signature[0] == 'R'); static_assert(sound_signature[1] == 'I'); static_assert(sound_signature[2] == 'F'); static_assert(sound_signature[3] == 'F'); static_assert(sizeof(sound_signature) == 4); return 0; } // C23 6.10.3p6 int k() { #define TWO_PLUS_TWO 2+2 static const char sound_signature[] = { #embed limit(TWO_PLUS_TWO) }; static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) == 4, "There should only be 4 elements in this array."); // verify PCM WAV resource static_assert(sound_signature[0] == 'R'); static_assert(sound_signature[1] == 'I'); static_assert(sound_signature[2] == 'F'); static_assert(sound_signature[3] == 'F'); static_assert(sizeof(sound_signature) == 4); return 0; } // C23 6.10.3.2p7: not tested here because we do not currently support any // platforms where CHAR_BIT != 8. // C23 6.10.3.2p8: not tested here because it requires access to an infinite // resource like /dev/urandom. // C23 6.10.3.3p4 char *strcpy(char *, const char *); #ifndef SHADER_TARGET #define SHADER_TARGET "bits.bin" #endif extern char* null_term_shader_data; void fill_in_data () { const char internal_data[] = { #embed SHADER_TARGET \ suffix(,) 0 }; strcpy(null_term_shader_data, internal_data); } // C23 6.10.3.4p4 #ifndef SHADER_TARGET #define SHADER_TARGET "bits.bin" #endif extern char* merp; void init_data () { const char whl[] = { #embed SHADER_TARGET \ prefix(0xEF, 0xBB, 0xBF, ) /* UTF-8 BOM */ \ suffix(,) 0 }; // always null terminated, // contains BOM if not-empty const int is_good = (sizeof(whl) == 1 && whl[0] == '\0') || (whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF' && whl[sizeof(whl) - 1] == '\0'); static_assert(is_good); strcpy(merp, whl); } // C23 6.10.3.5p3 int l() { return #embed limit(0) prefix(1) if_empty(0) ; // becomes: // return 0; // Validating the assumption from the example in the standard. static_assert( #embed limit(0) prefix(1) if_empty(0) == 0); } // C23 6.10.3.5p4 void fill_in_data_again() { const char internal_data[] = { #embed SHADER_TARGET \ suffix(, 0) \ if_empty(0) }; strcpy(null_term_shader_data, internal_data); } // C23 6.10.3.5p5 int m() { return #embed __FILE__ limit(0) if_empty(45540) ; // Validating the assumption from the example in the standard. static_assert( #embed __FILE__ limit(0) if_empty(45540) == 45540); } // 6.10.9.1p1 static_assert(__STDC_EMBED_NOT_FOUND__ == 0); static_assert(__STDC_EMBED_FOUND__ == 1); static_assert(__STDC_EMBED_EMPTY__ == 2);