├── .github └── workflows │ └── linux_thirdparty.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── alloc.c ├── bitint.c ├── codegen.c ├── hashmap.c ├── main.c ├── parse.c ├── platform ├── freebsd.c ├── linux-alpine.c ├── linux-ci-debian13.c ├── linux-ci.c ├── linux-glibc-generic.c ├── linux-musl-bootstrap.c └── openbsd.c ├── preprocess.c ├── scripts ├── debian_asan.Dockerfile ├── debian_asan_interop.Dockerfile ├── debian_asan_musl_bootstrap.Dockerfile ├── linux_thirdparty.bash ├── test_driver.sh └── test_linker.sh ├── slimcc.h ├── slimcc_headers ├── include │ ├── alloca.h │ ├── bitint_builtins │ ├── float.h │ ├── stdalign.h │ ├── stdarg.h │ ├── stdatomic.h │ ├── stdbool.h │ ├── stdckdint.h │ ├── stdcountof.h │ ├── stddef.h │ └── stdnoreturn.h └── platform_fix │ ├── freebsd │ ├── ctype.h │ ├── stdlib.h │ └── sys │ │ └── cdefs.h │ └── openbsd │ └── sys │ └── cdefs.h ├── strings.c ├── test ├── alignas2.c ├── alignof.c ├── alignof2.c ├── alloca.c ├── arith.c ├── asm.c ├── asm_name.c ├── atomic.c ├── atomic2.c ├── attr_aligned.c ├── attr_cleanup.c ├── attr_section.c ├── attr_weak.c ├── attribute.c ├── attribute2.c ├── attribute_hiding.c ├── autotype.c ├── bitfield.c ├── bitfield2.c ├── bitint.c ├── builtin.c ├── builtin2.c ├── builtin_return_address.c ├── cast.c ├── commonsym.c ├── compat.c ├── complit.c ├── complit2.c ├── cond_decl.c ├── const.c ├── constexpr.c ├── constexpr2.c ├── constexpr_var.c ├── constexpr_var_ext.c ├── control.c ├── control2.c ├── countof.c ├── decl.c ├── decl2.c ├── defer.c ├── digit_separator.c ├── embed.c ├── embed_empty ├── embed_sudoku ├── enum.c ├── enum2.c ├── extern.c ├── float.c ├── float2.c ├── function.c ├── function2.c ├── generic.c ├── generic2.c ├── gibberish.c ├── host │ └── common.c ├── imm_arith_opt.c ├── include1.h ├── include2.h ├── include3.h ├── include4.h ├── initializer.c ├── initializer2.c ├── inline_asm.c ├── keywords_c23.c ├── labeled_loop_sw.c ├── line.c ├── literal.c ├── macro.c ├── macro2.c ├── macro_direcitve_in_fnlike.c ├── macro_has_include.c ├── macro_pmarks.c ├── macro_rescan.c ├── macro_spacing.c ├── macro_va_tail.c ├── nullptr.c ├── offsetof.c ├── pointer.c ├── postfix_inc_dec.c ├── qualifiers.c ├── setjmp.c ├── sizeof.c ├── stack_reuse.c ├── static_assertion.c ├── stdhdr.c ├── stmtexpr2.c ├── string.c ├── string2.c ├── struct.c ├── tag_compat.c ├── test.h ├── tls.c ├── tls2.c ├── typedef.c ├── typedef2.c ├── typeof.c ├── typeof_unqual.c ├── unicode.c ├── unicode2.c ├── union.c ├── union2.c ├── usualconv.c ├── varargs.c ├── variable.c ├── vla.c ├── vla2.c ├── vla_dealloc.c └── vla_params.c ├── tokenize.c ├── type.c └── unicode.c /.github/workflows/linux_thirdparty.yml: -------------------------------------------------------------------------------- 1 | name: build-test-thirdparty 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | build-docker-for-tests: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | include: 11 | - tag: debian_asan 12 | - tag: debian_asan_interop 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Set up Docker Buildx 18 | uses: docker/setup-buildx-action@v3 19 | 20 | - name: Build image 21 | uses: docker/build-push-action@v6 22 | with: 23 | platforms: linux/amd64 24 | context: . 25 | file: scripts/${{ matrix.tag }}.Dockerfile 26 | tags: ${{ matrix.tag }} 27 | outputs: type=docker,dest=/tmp/${{ matrix.tag }}.tar 28 | 29 | - name: Upload artifact 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: ${{ matrix.tag }} 33 | path: /tmp/${{ matrix.tag }}.tar 34 | 35 | interop-tests: 36 | runs-on: ubuntu-latest 37 | needs: build-docker-for-tests 38 | strategy: 39 | fail-fast: false 40 | matrix: 41 | include: 42 | - project: test_c3 43 | - project: test_muon 44 | steps: 45 | - name: Download artifact 46 | uses: actions/download-artifact@v4 47 | with: 48 | name: debian_asan_interop 49 | path: /tmp 50 | 51 | - name: Load image 52 | run: docker load --input /tmp/debian_asan_interop.tar 53 | 54 | - name: Run test 55 | run: > 56 | sudo docker run debian_asan_interop 57 | su non-root -c 58 | 'bash "$0" "$1"' linux_thirdparty.bash ${{ matrix.project }} 59 | 60 | build-tests: 61 | runs-on: ubuntu-latest 62 | needs: build-docker-for-tests 63 | strategy: 64 | fail-fast: false 65 | matrix: 66 | include: 67 | - project: test_bash 68 | - project: test_c23doku 69 | - project: test_cello 70 | - project: test_curl 71 | - project: test_doom 72 | - project: test_git 73 | - project: test_glib 74 | - project: test_gmake 75 | - project: test_go 76 | - project: test_gzip 77 | - project: test_imagemagick 78 | - project: test_janet 79 | - project: test_libpng 80 | - project: test_libressl 81 | - project: test_libuev 82 | - project: test_lua 83 | - project: test_metalang99 84 | - project: test_noplate 85 | - project: test_ocaml 86 | - project: test_oniguruma_jq 87 | - project: test_openssh 88 | - project: test_openssl 89 | - project: test_perl 90 | - project: test_php 91 | - project: test_postgres 92 | - project: test_python 93 | - project: test_qbe_hare 94 | - project: test_scrapscript 95 | - project: test_sqlite 96 | - project: test_tcl 97 | - project: test_tinycc 98 | - project: test_toxcore 99 | - project: test_toybox 100 | - project: test_vim 101 | - project: test_zlib 102 | - project: test_zsh 103 | - project: test_zstd 104 | - project: build_erlang 105 | - project: build_gcc 106 | - project: build_nano 107 | - project: build_sdl 108 | - project: build_zig 109 | steps: 110 | - name: Download artifact 111 | uses: actions/download-artifact@v4 112 | with: 113 | name: debian_asan 114 | path: /tmp 115 | 116 | - name: Load image 117 | run: docker load --input /tmp/debian_asan.tar 118 | 119 | - name: Run test 120 | run: > 121 | sudo docker run debian_asan 122 | su non-root -c 123 | 'bash "$0" "$1"' linux_thirdparty.bash ${{ matrix.project }} 124 | 125 | musl-bootstrap: 126 | runs-on: ubuntu-latest 127 | steps: 128 | - name: Checkout 129 | uses: actions/checkout@v4 130 | 131 | - name: Set up Docker Buildx 132 | uses: docker/setup-buildx-action@v3 133 | 134 | - name: Build image 135 | uses: docker/build-push-action@v6 136 | with: 137 | platforms: linux/amd64 138 | context: . 139 | file: scripts/debian_asan_musl_bootstrap.Dockerfile 140 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*~ 2 | **/\#* 3 | **/*.o 4 | **/*.s 5 | **/a.out 6 | /tmp* 7 | /thirdparty 8 | /slimcc 9 | /test/*.exe 10 | /test/c23/*.exe 11 | /stage2 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rui Ueyama 4 | Copyright (c) 2023 Hsiang-Ying Fu 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRCS=alloc.c bitint.c codegen.c hashmap.c main.c parse.c platform.c preprocess.c strings.c tokenize.c type.c unicode.c 2 | 3 | TEST_SRCS!=ls test/*.c 4 | 5 | TEST_FLAGS=-Itest -fenable-universal-char -std=c23 -fdefer-ts 6 | 7 | .SUFFIXES: .exe .stage2.o .stage2.exe .asan.o .asan.exe 8 | 9 | # Stage 1 10 | 11 | OBJS=$(SRCS:.c=.o) 12 | 13 | slimcc: $(OBJS) 14 | $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) 15 | 16 | $(OBJS): slimcc.h 17 | 18 | TESTS=$(TEST_SRCS:.c=.exe) 19 | 20 | test/host/common.o: test/host/common.c 21 | $(CC) -o $@ -c $< 22 | 23 | $(TESTS): slimcc test/host/common.o 24 | 25 | .c.exe: 26 | ./slimcc $(TEST_FLAGS) -o $@ $< test/host/common.o -pthread 27 | 28 | test: $(TESTS) 29 | for i in $(TESTS); do echo $$i; ./$$i >/dev/null || exit 1; echo; done 30 | $(SHELL) scripts/test_driver.sh $(PWD)/slimcc $(CC) 31 | ./slimcc -hashmap-test 32 | 33 | # Stage 2 34 | 35 | OBJS_S2=$(SRCS:.c=.stage2.o) 36 | 37 | $(OBJS_S2): slimcc 38 | 39 | .c.stage2.o: 40 | ./slimcc -o $@ -c $< 41 | 42 | slimcc-stage2: $(OBJS_S2) 43 | ./slimcc -o $@ $(OBJS_S2) $(LDFLAGS) 44 | 45 | TESTS_S2=$(TEST_SRCS:.c=.stage2.exe) 46 | 47 | $(TESTS_S2): slimcc-stage2 test/host/common.o 48 | 49 | .c.stage2.exe: 50 | ./slimcc-stage2 $(TEST_FLAGS) -o $@ $< test/host/common.o -pthread 51 | 52 | test-stage2: $(TESTS_S2) 53 | for i in $(TESTS_S2); do echo $$i; ./$$i >/dev/null || exit 1; echo; done 54 | $(SHELL) scripts/test_driver.sh $(PWD)/slimcc-stage2 $(CC) 55 | ./slimcc-stage2 -hashmap-test 56 | 57 | # Asan build 58 | 59 | OBJS_ASAN=$(SRCS:.c=.asan.o) 60 | 61 | $(OBJS_ASAN): slimcc.h 62 | 63 | .c.asan.o: 64 | $(CC) $(CFLAGS) -fsanitize=address -g -o $@ -c $< 65 | 66 | slimcc-asan: $(OBJS_ASAN) 67 | $(CC) $(CFLAGS) -fsanitize=address -g -o $@ $(OBJS_ASAN) $(LDFLAGS) 68 | 69 | TESTS_ASAN=$(TEST_SRCS:.c=.asan.exe) 70 | 71 | $(TESTS_ASAN): slimcc-asan test/host/common.o 72 | 73 | .c.asan.exe: 74 | ./slimcc-asan $(TEST_FLAGS) -o $@ $< test/host/common.o -pthread 75 | 76 | test-asan: $(TESTS_ASAN) 77 | for i in $(TESTS_ASAN); do echo $$i; ./$$i >/dev/null || exit 1; echo; done 78 | $(SHELL) scripts/test_driver.sh $(PWD)/slimcc-asan $(CC) 79 | $(MAKE) slimcc CC=./slimcc-asan -B 80 | ./slimcc-asan -hashmap-test 81 | 82 | # Misc. 83 | 84 | test-all: test test-stage2 85 | 86 | warn: $(SRCS) 87 | $(CC) -fsyntax-only -Wall -Wpedantic -Wno-switch $(CFLAGS) $(SRCS) 88 | 89 | lto: clean 90 | $(MAKE) CFLAGS="-O2 -flto=auto -Wno-switch" 91 | 92 | lto-je: clean 93 | $(MAKE) CFLAGS="-O2 -flto=auto -Wno-switch" LDFLAGS="-ljemalloc" 94 | 95 | lto-mi: clean 96 | $(MAKE) CFLAGS="-O2 -flto=auto -Wno-switch" LDFLAGS="-lmimalloc" 97 | 98 | clean: 99 | rm -f slimcc slimcc-stage2 slimcc-asan 100 | rm -f *.o test/*.o test/*.exe test/host/*.o 101 | 102 | .PHONY: test clean test-stage2 test-asan 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a fork of [Rui Ueyama's chibicc](https://github.com/rui314/chibicc) with [fixes](https://github.com/fuhsnn/slimcc/issues?q=is%3Aissue+is%3Aclosed+label%3Aupstream-chibicc) and improvements, including: 2 | - C99 features: VLA parameters, VLA de-allocation, K&R old-style functions. 3 | - C11 features: `_Static_assert()`, over-aligned locals, `_Generic` with qualifiers. 4 | - C23 features: `constexpr`, `enum:T{}`, `#embed`, `auto` type-inference, etc. 5 | - C2y features: labeled loop/switch, if/switch declaration 6 | - TS features: `defer`(enable with `-fdefer-ts`), `__VA_TAIL__` 7 | - GNU features: inline assembly, symbol attributes, `cleanup`, `cons/destructor` 8 | - Basic codegen optimizations: const folding, reg-alloc for temporaries, instruction selection. 9 | 10 | ## Project goals 11 | 12 | - Compile correct code correctly. 13 | - Code readability. 14 | - Build real world projects, test with their suites. 15 | - Implement GNU extensions and features from newer C standards if doable. 16 | - Match GCC/Clang's behavior even if non-standard for better compatibility with existing code in the wild. 17 | 18 | ## Building and Using 19 | - Recent GNU binutils is required. 20 | - Find a relevant preset in `platform/`, copy/symlink to `platform.c` or write one yourself, hit `make`. 21 | - For recent glibc-based Linux, this should just work: 22 | ``` 23 | ln -s platform/linux-glibc-generic.c platform.c 24 | make 25 | ``` 26 | - Default build finds builtin headers by relative path and is expected to be executed in source directory, so use it like: 27 | - - `~/slimcc/slimcc *.c`, or `CC=~/slimcc/slimcc ./configure` 28 | - For installing/symlinking/packaging, please update `platform.c` with absolute paths. 29 | - `make slimcc-asan/test-asan` build and run tests with address sanitizer, recommended if you are hacking the source. 30 | - Optimization flags and custom allocators are quite impactful on the compiler's performance; try `make lto/lto-mi/lto-je` for a quick taste. 31 | - For a fully bootstrapped musl environment, checkout [slimcc-musl-bootstrap](https://github.com/fuhsnn/slimcc-musl-bootstrap). 32 | 33 | ## What can it build? 34 | 35 | `slimcc` is compatible with posix `c99` and common GCC/Clang options, most C89 to C11 projects not requiring optional or compiler-specific features should work. 36 | 37 | For testing, a CI workflow is set up to not only build real C codebases in a container with `slimcc` as the sole C compiler (no `cc`/`gcc`/`cpp`), but also expect 100% pass rate from their test-suites. The lineup includes the likes of CPython, Curl, Git, jq, Ocaml, PHP, Perl, PostgreSQL, Sqlite, Toybox, and Zstd; please have a look at the [workflow](https://github.com/fuhsnn/slimcc/blob/main/.github/workflows/linux_thirdparty.yml), [dockerfile](https://github.com/fuhsnn/slimcc/blob/main/scripts/debian_asan.Dockerfile), and [build instructions](https://github.com/fuhsnn/slimcc/blob/main/scripts/linux_thirdparty.bash) to verify this claim. 38 | 39 | ## Compatibility with build systems 40 | - `autoconf` based builds sometimes miss out `-fPIC` or `-Wl,` options, causing failures, if there is a block in `./configure` that looks like below, append `-Wl,`, `-fPIC`, `-static` respectively and re-configure: 41 | ``` 42 | lt_prog_compiler_wl= 43 | lt_prog_compiler_pic= 44 | lt_prog_compiler_static= 45 | ``` 46 | - If it's just `-fPIC`, configure with `CFLAGS=-fPIC`, if cmake, `-DCMAKE_C_FLAGS=-fPIC`. 47 | - `cmake` `find_package()` might fail to find installed libraries for slimcc, help it with `-DCMAKE_PREFIX_PATH`. 48 | - `meson`: see https://github.com/mesonbuild/meson/issues/5406. Try `muon` or hope for slimcc to join the club. 49 | 50 | ## How optimized are the generated binaries? 51 | 52 | Binary size is roughly among TinyCC's and GCC/Clang at `-O0`, no claims about speed. 53 | 54 | ## How optimized is the compiler itself? 55 | 56 | The coding style is greatly influenced by `chibicc`, which means in the eyes of C veterans there might be all kinds of inefficiencies in the name of readability. While micro-optimizing is fun, I only commit changes that noticeably improve `-flto=auto -march=native -lmimalloc` builds. 57 | 58 | Previously all allocations were leaked, that led to pretty bad RAM usage for large translation units (Zig bootstrap) or macro expansion tricks (Metalang99). This was remedied with arena allocation and mark-and-sweep of linked lists. 59 | 60 | ## Can it be built with another small C compiler? 61 | 62 | - TinyCC, kefir, vanilla chibicc: can build with `cc *.c`, `make test` might fail at ABI tests. 63 | - pcc: has a bug parsing escaped sequence in a comment, otherwise can build. 64 | - cproc, simple-cc: lack long double support (it's a QBE limitation). 65 | - mir, xcc: missing header. 66 | -------------------------------------------------------------------------------- /alloc.c: -------------------------------------------------------------------------------- 1 | #include "slimcc.h" 2 | 3 | #if USE_ASAN 4 | #include 5 | 6 | const char *__asan_default_options(void) { 7 | return "detect_leaks=0"; 8 | } 9 | #endif 10 | 11 | #define FREE_THRESHOLD (100 * 1024) 12 | #define PAGE_SIZE 4064 13 | 14 | struct Page { 15 | char buf[PAGE_SIZE]; 16 | Page *next; 17 | }; 18 | 19 | Arena ast_arena; 20 | Arena node_arena; 21 | Arena pp_arena; 22 | bool free_alloc; 23 | 24 | bool check_mem_usage(void) { 25 | #if USE_ASAN 26 | return true; 27 | #else 28 | struct rusage stat; 29 | getrusage(RUSAGE_SELF, &stat); 30 | return stat.ru_maxrss > FREE_THRESHOLD; 31 | #endif 32 | } 33 | 34 | static Page *new_page(void) { 35 | Page *p = malloc(sizeof(Page)); 36 | p->next = NULL; 37 | #if USE_ASAN 38 | __asan_poison_memory_region(&p->buf, PAGE_SIZE); 39 | #endif 40 | return p; 41 | } 42 | 43 | static void *allocate(Arena *arena, size_t sz, bool clear) { 44 | size_t aligned_sz = (sz + 15) & -16LL; 45 | 46 | void *ptr; 47 | if ((arena->used + aligned_sz) <= PAGE_SIZE) { 48 | ptr = &arena->page->buf[arena->used]; 49 | arena->used += aligned_sz; 50 | } else { 51 | if (!arena->page->next) 52 | arena->page->next = new_page(); 53 | 54 | arena->page = arena->page->next; 55 | ptr = &arena->page->buf; 56 | arena->used = aligned_sz; 57 | } 58 | 59 | #if USE_ASAN 60 | __asan_unpoison_memory_region(ptr, sz); 61 | if (clear) 62 | memset(ptr, 0, sz); 63 | #else 64 | if (clear) 65 | for (int i = 0; i < (aligned_sz >> 3); i++) 66 | ((int64_t *)ptr)[i] = 0; 67 | #endif 68 | return ptr; 69 | } 70 | 71 | void arena_on(Arena *arena) { 72 | if (!arena->head_page) 73 | arena->head_page = new_page(); 74 | 75 | arena->page = arena->head_page; 76 | arena->on = true; 77 | arena->used = 0; 78 | } 79 | 80 | void arena_off(Arena *arena) { 81 | arena->on = false; 82 | 83 | if (free_alloc) { 84 | while (arena->head_page) { 85 | Page *nxt = arena->head_page->next; 86 | free(arena->head_page); 87 | arena->head_page = nxt; 88 | } 89 | } 90 | } 91 | 92 | void *arena_malloc(Arena *a, size_t sz) { 93 | return allocate(a, sz, false); 94 | } 95 | 96 | void *arena_calloc(Arena *a, size_t sz) { 97 | return allocate(a, sz, true); 98 | } 99 | 100 | void *ast_arena_malloc(size_t sz) { 101 | if (!ast_arena.on) 102 | return malloc(sz); 103 | return allocate(&ast_arena, sz, false); 104 | } 105 | 106 | void *ast_arena_calloc(size_t sz) { 107 | if (!ast_arena.on) 108 | return calloc(1, sz); 109 | return allocate(&ast_arena, sz, true); 110 | } 111 | -------------------------------------------------------------------------------- /hashmap.c: -------------------------------------------------------------------------------- 1 | // This is an implementation of the open-addressing hash table. 2 | 3 | #include "slimcc.h" 4 | 5 | // Initial hash bucket size 6 | #define INIT_SIZE 16 7 | 8 | // Rehash if the usage exceeds 70%. 9 | #define HIGH_WATERMARK 70 10 | 11 | // We'll keep the usage below 50% after rehashing. 12 | #define LOW_WATERMARK 50 13 | 14 | // Represents a deleted hash entry 15 | #define TOMBSTONE ((void *)-1) 16 | 17 | static uint64_t fnv_hash(char *s, int len) { 18 | uint64_t hash = 0xcbf29ce484222325; 19 | for (int i = 0; i < len; i++) { 20 | hash *= 0x100000001b3; 21 | hash ^= (unsigned char)s[i]; 22 | } 23 | return hash; 24 | } 25 | 26 | // Make room for new entires in a given hashmap by removing 27 | // tombstones and possibly extending the bucket size. 28 | static void rehash(HashMap *map) { 29 | // Compute the size of the new hashmap. 30 | int nkeys = 0; 31 | for (int i = 0; i < map->capacity; i++) 32 | if (map->buckets[i].key && map->buckets[i].key != TOMBSTONE) 33 | nkeys++; 34 | 35 | int cap = map->capacity; 36 | while ((nkeys * 100) / cap >= LOW_WATERMARK) 37 | cap = cap * 2; 38 | assert(cap > 0); 39 | 40 | // Create a new hashmap and copy all key-values. 41 | HashMap map2 = {0}; 42 | map2.buckets = calloc(cap, sizeof(HashEntry)); 43 | map2.capacity = cap; 44 | 45 | for (int i = 0; i < map->capacity; i++) { 46 | HashEntry *ent = &map->buckets[i]; 47 | if (ent->key && ent->key != TOMBSTONE) 48 | hashmap_put2(&map2, ent->key, ent->keylen, ent->val); 49 | } 50 | 51 | assert(map2.used == nkeys); 52 | free(map->buckets); 53 | *map = map2; 54 | } 55 | 56 | static bool match(HashEntry *ent, char *key, int keylen) { 57 | return ent->key && ent->key != TOMBSTONE && 58 | ent->keylen == keylen && memcmp(ent->key, key, keylen) == 0; 59 | } 60 | 61 | static HashEntry *get_entry(HashMap *map, char *key, int keylen) { 62 | if (!map->buckets) 63 | return NULL; 64 | 65 | uint64_t hash = fnv_hash(key, keylen); 66 | 67 | for (int i = 0; i < map->capacity; i++) { 68 | HashEntry *ent = &map->buckets[(hash + i) & (map->capacity - 1)]; 69 | if (match(ent, key, keylen)) 70 | return ent; 71 | if (ent->key == NULL) 72 | return NULL; 73 | } 74 | internal_error(); 75 | } 76 | 77 | static HashEntry *get_or_insert_entry(HashMap *map, char *key, int keylen) { 78 | if (!map->buckets) { 79 | map->buckets = calloc(INIT_SIZE, sizeof(HashEntry)); 80 | map->capacity = INIT_SIZE; 81 | } else if ((map->used * 100) / map->capacity >= HIGH_WATERMARK) { 82 | rehash(map); 83 | } 84 | 85 | uint64_t hash = fnv_hash(key, keylen); 86 | 87 | for (int i = 0; i < map->capacity; i++) { 88 | HashEntry *ent = &map->buckets[(hash + i) & (map->capacity - 1)]; 89 | 90 | if (match(ent, key, keylen)) 91 | return ent; 92 | 93 | if (ent->key == NULL) { 94 | ent->key = key; 95 | ent->keylen = keylen; 96 | map->used++; 97 | return ent; 98 | } 99 | } 100 | internal_error(); 101 | } 102 | 103 | void *hashmap_get(HashMap *map, char *key) { 104 | return hashmap_get2(map, key, strlen(key)); 105 | } 106 | 107 | void *hashmap_get2(HashMap *map, char *key, int keylen) { 108 | HashEntry *ent = get_entry(map, key, keylen); 109 | return ent ? ent->val : NULL; 110 | } 111 | 112 | void hashmap_put(HashMap *map, char *key, void *val) { 113 | hashmap_put2(map, key, strlen(key), val); 114 | } 115 | 116 | void hashmap_put2(HashMap *map, char *key, int keylen, void *val) { 117 | HashEntry *ent = get_or_insert_entry(map, key, keylen); 118 | ent->val = val; 119 | } 120 | 121 | void hashmap_delete(HashMap *map, char *key) { 122 | hashmap_delete2(map, key, strlen(key)); 123 | } 124 | 125 | void hashmap_delete2(HashMap *map, char *key, int keylen) { 126 | HashEntry *ent = get_entry(map, key, keylen); 127 | if (ent) 128 | ent->key = TOMBSTONE; 129 | } 130 | 131 | void hashmap_test(void) { 132 | HashMap *map = calloc(1, sizeof(HashMap)); 133 | 134 | for (int i = 0; i < 5000; i++) 135 | hashmap_put(map, format("key %d", i), (void *)(size_t)i); 136 | for (int i = 1000; i < 2000; i++) 137 | hashmap_delete(map, format("key %d", i)); 138 | for (int i = 1500; i < 1600; i++) 139 | hashmap_put(map, format("key %d", i), (void *)(size_t)i); 140 | for (int i = 6000; i < 7000; i++) 141 | hashmap_put(map, format("key %d", i), (void *)(size_t)i); 142 | 143 | for (int i = 0; i < 1000; i++) 144 | assert((size_t)hashmap_get(map, format("key %d", i)) == i); 145 | for (int i = 1000; i < 1500; i++) 146 | assert(hashmap_get(map, "no such key") == NULL); 147 | for (int i = 1500; i < 1600; i++) 148 | assert((size_t)hashmap_get(map, format("key %d", i)) == i); 149 | for (int i = 1600; i < 2000; i++) 150 | assert(hashmap_get(map, "no such key") == NULL); 151 | for (int i = 2000; i < 5000; i++) 152 | assert((size_t)hashmap_get(map, format("key %d", i)) == i); 153 | for (int i = 5000; i < 6000; i++) 154 | assert(hashmap_get(map, "no such key") == NULL); 155 | for (int i = 6000; i < 7000; i++) 156 | hashmap_put(map, format("key %d", i), (void *)(size_t)i); 157 | 158 | assert(hashmap_get(map, "no such key") == NULL); 159 | printf("OK\n"); 160 | } 161 | -------------------------------------------------------------------------------- /platform/freebsd.c: -------------------------------------------------------------------------------- 1 | #include "slimcc.h" 2 | 3 | void platform_init(void) { 4 | define_macro("__ELF__", "1"); 5 | 6 | define_macro("__FreeBSD__", "15"); 7 | define_macro("__extension__", ""); 8 | 9 | init_ty_lp64(); 10 | } 11 | 12 | void platform_stdinc_paths(StringArray *paths) { 13 | // Replace this block with absolute path if you intend to 14 | // execute the compiler outside of source directory. 15 | // If you are thinking of just removing the error while keeping 16 | // the relative search path, please read: 17 | // https://github.com/rui314/chibicc/issues/162 18 | { 19 | char *hdr_dir = format("%s/slimcc_headers", dirname(strdup(argv0))); 20 | if (!file_exists(hdr_dir)) 21 | error("can't find built-in headers"); 22 | 23 | add_include_path(paths, format("%s/platform_fix/freebsd", hdr_dir)); 24 | add_include_path(paths, format("%s/include", hdr_dir)); 25 | } 26 | 27 | add_include_path(paths, "/usr/local/include"); 28 | add_include_path(paths, "/usr/include"); 29 | } 30 | 31 | void run_assembler(StringArray *as_args, char *input, char *output) { 32 | run_assembler_gnustyle(as_args, input, output); 33 | } 34 | 35 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 36 | strarray_push(paths, "-L/usr/lib"); 37 | strarray_push(paths, "-L/lib"); 38 | 39 | run_linker_gnustyle(paths, inputs, output, 40 | "/libexec/ld-elf.so.1", 41 | "/usr/lib", 42 | "/usr/lib"); 43 | } 44 | -------------------------------------------------------------------------------- /platform/linux-alpine.c: -------------------------------------------------------------------------------- 1 | #include "slimcc.h" 2 | 3 | void platform_init(void) { 4 | define_macro("__ELF__", "1"); 5 | 6 | define_macro("linux", "1"); 7 | define_macro("__linux", "1"); 8 | define_macro("__linux__", "1"); 9 | 10 | init_ty_lp64(); 11 | 12 | set_fpie("2"); 13 | opt_pie = true; 14 | } 15 | 16 | void platform_stdinc_paths(StringArray *paths) { 17 | // Replace this block with absolute path if you intend to 18 | // execute the compiler outside of source directory. 19 | // If you are thinking of just removing the error while keeping 20 | // the relative search path, please read: 21 | // https://github.com/rui314/chibicc/issues/162 22 | { 23 | char *hdr_dir = format("%s/slimcc_headers", dirname(strdup(argv0))); 24 | if (!file_exists(hdr_dir)) 25 | error("can't find built-in headers"); 26 | 27 | add_include_path(paths, format("%s/include", hdr_dir)); 28 | } 29 | 30 | add_include_path(paths, "/usr/include"); 31 | } 32 | 33 | void run_assembler(StringArray *as_args, char *input, char *output) { 34 | run_assembler_gnustyle(as_args, input, output); 35 | } 36 | 37 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 38 | char *libgccpath = find_dir_w_file("/usr/lib/gcc/x86_64-alpine-linux-musl/*/crtbegin.o"); 39 | 40 | if (libgccpath) 41 | strarray_push(paths, format("-L%s", libgccpath)); 42 | strarray_push(paths, "-L/usr/lib"); 43 | strarray_push(paths, "-L/lib"); 44 | 45 | run_linker_gnustyle(paths, inputs, output, 46 | "/lib/ld-musl-x86_64.so.1", 47 | "/usr/lib", // ubuntu musl: /usr/lib/x86_64-linux-musl/ 48 | libgccpath); 49 | } 50 | -------------------------------------------------------------------------------- /platform/linux-ci-debian13.c: -------------------------------------------------------------------------------- 1 | // for scripts/debian_asan.Dockerfile 2 | 3 | #include "slimcc.h" 4 | 5 | void platform_init(void) { 6 | define_macro("__ELF__", "1"); 7 | 8 | define_macro("linux", "1"); 9 | define_macro("__linux", "1"); 10 | define_macro("__linux__", "1"); 11 | define_macro("__gnu_linux__", "1"); 12 | 13 | init_ty_lp64(); 14 | 15 | set_fpie("2"); 16 | opt_pie = true; 17 | } 18 | 19 | void platform_stdinc_paths(StringArray *paths) { 20 | add_include_path(paths, "/work/slimcc/slimcc_headers/include"); 21 | add_include_path(paths, "/usr/include/x86_64-linux-gnu"); 22 | add_include_path(paths, "/usr/include"); 23 | } 24 | 25 | void run_assembler(StringArray *as_args, char *input, char *output) { 26 | run_assembler_gnustyle(as_args, input, output); 27 | } 28 | 29 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 30 | strarray_push(paths, "-L/usr/lib/gcc/x86_64-linux-gnu/14"); 31 | strarray_push(paths, "-L/usr/lib/x86_64-linux-gnu"); 32 | 33 | run_linker_gnustyle(paths, inputs, output, 34 | "/usr/lib64/ld-linux-x86-64.so.2", 35 | "/usr/lib/x86_64-linux-gnu", 36 | "/usr/lib/gcc/x86_64-linux-gnu/14"); 37 | } 38 | -------------------------------------------------------------------------------- /platform/linux-ci.c: -------------------------------------------------------------------------------- 1 | // for scripts/debian_asan.Dockerfile 2 | 3 | #include "slimcc.h" 4 | 5 | void platform_init(void) { 6 | define_macro("__ELF__", "1"); 7 | 8 | define_macro("linux", "1"); 9 | define_macro("__linux", "1"); 10 | define_macro("__linux__", "1"); 11 | define_macro("__gnu_linux__", "1"); 12 | 13 | init_ty_lp64(); 14 | 15 | set_fpie("2"); 16 | opt_pie = true; 17 | } 18 | 19 | void platform_stdinc_paths(StringArray *paths) { 20 | add_include_path(paths, "/work/slimcc/slimcc_headers/include"); 21 | add_include_path(paths, "/usr/include/x86_64-linux-gnu"); 22 | add_include_path(paths, "/usr/include"); 23 | } 24 | 25 | void run_assembler(StringArray *as_args, char *input, char *output) { 26 | run_assembler_gnustyle(as_args, input, output); 27 | } 28 | 29 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 30 | strarray_push(paths, "-L/usr/lib/gcc/x86_64-linux-gnu/12"); 31 | strarray_push(paths, "-L/usr/lib/x86_64-linux-gnu"); 32 | 33 | run_linker_gnustyle(paths, inputs, output, 34 | "/usr/lib64/ld-linux-x86-64.so.2", 35 | "/usr/lib/x86_64-linux-gnu", 36 | "/usr/lib/gcc/x86_64-linux-gnu/12"); 37 | } 38 | -------------------------------------------------------------------------------- /platform/linux-glibc-generic.c: -------------------------------------------------------------------------------- 1 | #include "slimcc.h" 2 | 3 | void platform_init(void) { 4 | define_macro("__ELF__", "1"); 5 | 6 | define_macro("linux", "1"); 7 | define_macro("__linux", "1"); 8 | define_macro("__linux__", "1"); 9 | define_macro("__gnu_linux__", "1"); 10 | 11 | init_ty_lp64(); 12 | 13 | // Follow build compiler's PIE on/off status 14 | #ifdef __pie__ 15 | set_fpie("2"); 16 | opt_pie = true; 17 | #endif 18 | } 19 | 20 | void platform_stdinc_paths(StringArray *paths) { 21 | // Replace this block with absolute path if you intend to 22 | // execute the compiler outside of source directory. 23 | // If you are thinking of just removing the error while keeping 24 | // the relative search path, please read: 25 | // https://github.com/rui314/chibicc/issues/162 26 | { 27 | char *hdr_dir = format("%s/slimcc_headers", dirname(strdup(argv0))); 28 | if (!file_exists(hdr_dir)) 29 | error("can't find built-in headers"); 30 | 31 | add_include_path(paths, format("%s/include", hdr_dir)); 32 | } 33 | 34 | add_include_path(paths, "/usr/local/include"); 35 | add_include_path(paths, "/usr/include/x86_64-linux-gnu"); 36 | add_include_path(paths, "/usr/include"); 37 | } 38 | 39 | void run_assembler(StringArray *as_args, char *input, char *output) { 40 | run_assembler_gnustyle(as_args, input, output); 41 | } 42 | 43 | static char *libpath(void) { 44 | static char *path; 45 | if (!path) { 46 | if (file_exists("/usr/lib/x86_64-linux-gnu/crti.o")) 47 | path = "/usr/lib/x86_64-linux-gnu"; 48 | else if (file_exists("/usr/lib64/crti.o")) 49 | path = "/usr/lib64"; 50 | 51 | if (!path) 52 | error("library path is not found"); 53 | } 54 | return path; 55 | } 56 | 57 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 58 | char *gcclibpath = find_dir_w_file("/usr/lib*/gcc/x86_64*-linux*/*/crtbegin.o"); 59 | if (!gcclibpath) 60 | error("gcc library path not found"); 61 | 62 | strarray_push(paths, format("-L%s", gcclibpath)); 63 | strarray_push(paths, "-L/usr/lib/x86_64-linux-gnu"); 64 | strarray_push(paths, "-L/usr/lib/x86_64-pc-linux-gnu"); 65 | strarray_push(paths, "-L/usr/lib/x86_64-redhat-linux"); 66 | strarray_push(paths, "-L/usr/lib64"); 67 | strarray_push(paths, "-L/lib64"); 68 | strarray_push(paths, "-L/usr/lib"); 69 | strarray_push(paths, "-L/lib"); 70 | 71 | run_linker_gnustyle(paths, inputs, output, 72 | "/lib64/ld-linux-x86-64.so.2", 73 | libpath(), 74 | gcclibpath); 75 | } 76 | -------------------------------------------------------------------------------- /platform/linux-musl-bootstrap.c: -------------------------------------------------------------------------------- 1 | 2 | #include "slimcc.h" 3 | 4 | void platform_init(void) { 5 | define_macro("__ELF__", "1"); 6 | 7 | define_macro("linux", "1"); 8 | define_macro("__linux", "1"); 9 | define_macro("__linux__", "1"); 10 | 11 | init_ty_lp64(); 12 | 13 | opt_func_sections = opt_data_sections = true; 14 | } 15 | 16 | void platform_stdinc_paths(StringArray *paths) { 17 | add_include_path(paths, ROOT_DIR"/lib/slimcc/include"); 18 | add_include_path(paths, ROOT_DIR"/usr/include"); 19 | } 20 | 21 | void run_assembler(StringArray *as_args, char *input, char *output) { 22 | run_assembler_gnustyle(as_args, input, output); 23 | } 24 | 25 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 26 | strarray_push(paths, "-L"ROOT_DIR"/lib"); 27 | 28 | strarray_push(inputs, "--gc-sections"); 29 | 30 | run_linker_gnustyle(paths, inputs, output, 31 | ROOT_DIR"/lib/libc.so", 32 | ROOT_DIR"/lib", 33 | NULL); 34 | } 35 | -------------------------------------------------------------------------------- /platform/openbsd.c: -------------------------------------------------------------------------------- 1 | // Follows src/gnu/llvm/clang/lib/Driver/ToolChains/OpenBSD.cpp 2 | 3 | #include "slimcc.h" 4 | 5 | void platform_init(void) { 6 | define_macro("__ELF__", "1"); 7 | 8 | define_macro("__OpenBSD__", "1"); 9 | 10 | init_ty_lp64(); 11 | 12 | opt_use_as = "gas"; 13 | opt_use_ld = "ld"; 14 | 15 | opt_femulated_tls = true; 16 | set_fpie("1"); 17 | } 18 | 19 | void platform_stdinc_paths(StringArray *paths) { 20 | // Replace this block with absolute path if you intend to 21 | // execute the compiler outside of source directory. 22 | // If you are thinking of just removing the error while keeping 23 | // the relative search path, please read: 24 | // https://github.com/rui314/chibicc/issues/162 25 | { 26 | char *hdr_dir = format("%s/slimcc_headers", dirname(strdup(argv0))); 27 | if (!file_exists(hdr_dir)) 28 | error("can't find built-in headers"); 29 | 30 | add_include_path(paths, format("%s/platform_fix/openbsd", hdr_dir)); 31 | add_include_path(paths, format("%s/include", hdr_dir)); 32 | } 33 | 34 | add_include_path(paths, "/usr/include"); 35 | } 36 | 37 | void run_assembler(StringArray *as_args, char *input, char *output) { 38 | run_assembler_gnustyle(as_args, input, output); 39 | } 40 | 41 | void run_linker(StringArray *paths, StringArray *inputs, char *output) { 42 | StringArray arr = {0}; 43 | const bool opt_pg = false; 44 | 45 | strarray_push(&arr, "ld"); 46 | strarray_push(&arr, "-o"); 47 | strarray_push(&arr, output); 48 | strarray_push(&arr, "-m"); 49 | strarray_push(&arr, "elf_x86_64"); 50 | 51 | if (opt_s) 52 | strarray_push(&arr, "-s"); 53 | 54 | if (!(opt_nostartfiles || opt_shared)) { 55 | strarray_push(&arr, "-e"); 56 | strarray_push(&arr, "__start"); 57 | } 58 | 59 | strarray_push(&arr, "--eh-frame-hdr"); 60 | 61 | if (opt_static) { 62 | strarray_push(&arr, "-Bstatic"); 63 | strarray_push(&arr, "-static"); 64 | } else { 65 | if (opt_rdynamic) 66 | strarray_push(&arr, "-export-dynamic"); 67 | 68 | strarray_push(&arr, "-Bdynamic"); 69 | if (opt_shared) { 70 | strarray_push(&arr, "-shared"); 71 | } else if (!opt_r) { 72 | strarray_push(&arr, "-dynamic-linker"); 73 | strarray_push(&arr, "/usr/libexec/ld.so"); 74 | } 75 | } 76 | 77 | if (opt_pie) 78 | strarray_push(&arr, "-pie"); 79 | if (opt_nopie || opt_pg) 80 | strarray_push(&arr, "-nopie"); 81 | 82 | if (!(opt_nostartfiles || opt_r)) { 83 | if (!opt_shared) { 84 | if (opt_pg) 85 | strarray_push(&arr, format("/usr/lib/gcrt0.o")); 86 | else if (opt_static && !opt_nopie) 87 | strarray_push(&arr, format("/usr/lib/rcrt0.o")); 88 | else 89 | strarray_push(&arr, format("/usr/lib/crt0.o")); 90 | 91 | strarray_push(&arr, format("/usr/lib/crtbegin.o")); 92 | } else { 93 | strarray_push(&arr, format("/usr/lib/crtbeginS.o")); 94 | } 95 | } 96 | 97 | for (int i = 0; i < paths->len; i++) 98 | strarray_push(&arr, paths->data[i]); 99 | 100 | strarray_push(&arr, "-L/usr/lib"); 101 | 102 | for (int i = 0; i < inputs->len; i++) 103 | strarray_push(&arr, inputs->data[i]); 104 | 105 | if (opt_r) 106 | strarray_push(&arr, "-r"); 107 | 108 | if (!(opt_nodefaultlibs || opt_r)) { 109 | strarray_push(&arr, "-lcompiler_rt"); 110 | 111 | if (opt_pthread) { 112 | if (!opt_shared && opt_pg) 113 | strarray_push(&arr, "-lpthread_p"); 114 | else 115 | strarray_push(&arr, "-lpthread"); 116 | } 117 | 118 | if (!opt_shared && !opt_nolibc) { 119 | if (opt_pg) 120 | strarray_push(&arr, "-lc_p"); 121 | else 122 | strarray_push(&arr, "-lc"); 123 | } 124 | strarray_push(&arr, "-lcompiler_rt"); 125 | } 126 | 127 | if (!(opt_nostartfiles || opt_r)) { 128 | if (!opt_shared) 129 | strarray_push(&arr, format("/usr/lib/crtend.o")); 130 | else 131 | strarray_push(&arr, format("/usr/lib/crtendS.o")); 132 | } 133 | 134 | strarray_push(&arr, NULL); 135 | 136 | run_subprocess(arr.data); 137 | } 138 | -------------------------------------------------------------------------------- /scripts/debian_asan.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12-slim 2 | 3 | RUN apt-get update && apt-get install -y --no-install-recommends \ 4 | gcc-12 \ 5 | file binutils libc-dev libgcc-12-dev \ 6 | make cmake pkg-config \ 7 | autoconf autopoint automake gettext texinfo \ 8 | git curl ca-certificates \ 9 | tcl-dev bison flex re2c \ 10 | libcurl4-openssl-dev libssl-dev libexpat1-dev zlib1g-dev libicu-dev \ 11 | libncurses-dev libreadline-dev libpsl-dev libffi-dev libxml2-dev libsqlite3-dev \ 12 | # build_gcc 13 | libgmp-dev libmpfr-dev libmpc-dev \ 14 | # test_toxcore 15 | libsodium-dev \ 16 | # test_perl:cpan/Socket/t/getaddrinfo.t 17 | netbase \ 18 | # for ocaml testsuite 19 | parallel \ 20 | # glib 21 | libpcre3-dev libmount-dev desktop-file-utils shared-mime-info \ 22 | python3.11-minimal python3-distutils 23 | 24 | COPY . /work/slimcc 25 | WORKDIR /work/slimcc 26 | 27 | RUN ln -s platform/linux-ci.c platform.c 28 | RUN gcc-12 -O2 -flto=auto -march=native *.c -fsanitize=address -o slimcc 29 | RUN apt-get -y autoremove gcc-12 && apt-get clean 30 | 31 | RUN ! command -v cc 32 | RUN ! command -v cpp 33 | RUN ! command -v gcc 34 | RUN ! command -v gcc-12 35 | 36 | ENV CC=/work/slimcc/slimcc 37 | 38 | RUN bash scripts/linux_thirdparty.bash install_libtool 39 | 40 | RUN useradd -m non-root -s /bin/bash && \ 41 | su non-root -c "git config --global advice.detachedHead false" && \ 42 | su non-root -c "git config --global init.defaultBranch init" && \ 43 | mv scripts/linux_thirdparty.bash /home/non-root 44 | 45 | WORKDIR /home/non-root 46 | -------------------------------------------------------------------------------- /scripts/debian_asan_interop.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:trixie-slim 2 | 3 | RUN apt-get update && apt-get upgrade -y 4 | RUN apt-get install -y --no-install-recommends \ 5 | make cmake pkg-config \ 6 | autoconf autopoint automake gettext texinfo \ 7 | git curl ca-certificates \ 8 | clang libclang-rt-19-dev \ 9 | # C3 10 | zlib1g zlib1g-dev libllvm19 llvm llvm-dev llvm-runtime liblld-dev liblld-19 libpolly-19-dev 11 | 12 | COPY . /work/slimcc 13 | WORKDIR /work/slimcc 14 | 15 | RUN ln -s platform/linux-ci-debian13.c platform.c 16 | RUN clang -O2 -flto=auto -march=native *.c -fsanitize=address -o slimcc 17 | 18 | ENV CC=/work/slimcc/slimcc 19 | 20 | #RUN bash scripts/linux_thirdparty.bash install_libtool 21 | 22 | RUN useradd -m non-root -s /bin/bash && \ 23 | su non-root -c "git config --global advice.detachedHead false" && \ 24 | su non-root -c "git config --global init.defaultBranch init" && \ 25 | mv scripts/linux_thirdparty.bash /home/non-root 26 | 27 | WORKDIR /home/non-root 28 | -------------------------------------------------------------------------------- /scripts/debian_asan_musl_bootstrap.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12-slim 2 | 3 | RUN apt-get update && apt-get install -y --no-install-recommends \ 4 | gcc-12 libc6-dev binutils libgcc-12-dev make wget ca-certificates 5 | 6 | COPY . /work/slimcc 7 | WORKDIR /work/ 8 | 9 | RUN wget https://github.com/fuhsnn/slimcc-musl-bootstrap/archive/refs/heads/master.tar.gz 10 | RUN tar -xf master.tar.gz --strip-components=1 11 | RUN sed -i 's/$STAGE1_BUILD_CMD/gcc-12 -O2 -flto=auto -march=native *.c -fsanitize=address -o slimcc \&\& apt-get -y autoremove gcc-12 libc6-dev/g' slimcc-musl-bootstrap.sh 12 | RUN sh slimcc-musl-bootstrap.sh 13 | 14 | RUN mkdir ./rfs/dev ./rfs/tmp 15 | RUN make -C slimcc/ clean && cp -r slimcc/ ./rfs/ 16 | RUN chroot ./rfs /bin/sh -c 'cd /slimcc && make CC=cc test-stage2' 17 | -------------------------------------------------------------------------------- /scripts/test_linker.sh: -------------------------------------------------------------------------------- 1 | tmp=`mktemp -d /tmp/testcc-test-XXXXXX` 2 | trap 'rm -rf $tmp' INT TERM HUP EXIT 3 | 4 | "$FILE" --help | grep astron -q 5 | 6 | if [ ! $? -eq 0 ]; then 7 | echo 'please set FILE to Fine Free File Command from https://www.darwinsys.com/file' 8 | exit 1 9 | fi 10 | 11 | if [ -z "$CC" ]; then 12 | echo "please set CC" 13 | exit 1 14 | fi 15 | 16 | check() { 17 | if [ $? -eq 0 ]; then 18 | echo "testing $1 ... passed" 19 | else 20 | echo "testing $1 ... failed" 21 | exit 1 22 | fi 23 | } 24 | 25 | echo 'extern int bar; int foo() { return bar; }' > $tmp/foo.c 26 | echo 'int foo(); int bar=3; int main() { foo(); }' > $tmp/bar.c 27 | 28 | test_obj() { 29 | $CC $1 -o $tmp/foo $tmp/foo.c $tmp/bar.c 30 | check "$1 build" 31 | 32 | STR=`$FILE $tmp/foo` 33 | 34 | if [ -n "$2" ]; then 35 | echo "$STR" | grep -q "$2" 36 | check "$1 type" 37 | fi 38 | 39 | if [ -n "$3" ]; then 40 | echo "$STR" | grep -q "$3" 41 | check "$1 linkage" 42 | fi 43 | } 44 | 45 | if [ `uname` = 'OpenBSD' ]; then 46 | test_obj '-fPIE -static' 'pie executable,' 'static-pie linked' 47 | elif [ `uname` = 'Linux' ]; then 48 | test_obj '-fPIE -static-pie' 'pie executable,' 'static-pie linked' 49 | fi 50 | 51 | test_obj '-fPIE -pie' 'pie executable,' 'dynamically linked' 52 | 53 | test_obj '-fno-PIE -no-pie' 'LSB executable,' 'dynamically linked' 54 | 55 | test_obj '-fno-PIE -no-pie -static' 'LSB executable,' 'statically linked' 56 | 57 | test_obj '-fPIC -shared' 'shared object,' 'dynamically linked' 58 | 59 | test_obj '-r' 'relocatable' 60 | 61 | echo OK 62 | 63 | -------------------------------------------------------------------------------- /slimcc_headers/include/alloca.h: -------------------------------------------------------------------------------- 1 | #ifndef __ALLOCA_H 2 | #define __ALLOCA_H 3 | 4 | #include 5 | 6 | extern void *alloca (size_t); 7 | 8 | #define alloca(sz) __builtin_alloca(sz) 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /slimcc_headers/include/float.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDFLOAT_H 2 | #define __STDFLOAT_H 3 | 4 | #define DECIMAL_DIG 21 5 | #define FLT_EVAL_METHOD 0 // C11 5.2.4.2.2p9 6 | #define FLT_RADIX 2 7 | 8 | #if defined(__has_include) 9 | #if __has_include() 10 | #include 11 | #define FLT_ROUNDS \ 12 | ({ \ 13 | int val = -1; \ 14 | switch (fegetround()) { \ 15 | case FE_TOWARDZERO: val = 0; break; \ 16 | case FE_TONEAREST: val = 1; break; \ 17 | case FE_UPWARD: val = 2; break; \ 18 | case FE_DOWNWARD: val = 3; break; \ 19 | }; \ 20 | val; \ 21 | }) 22 | #endif 23 | #endif 24 | 25 | #ifndef FLT_ROUND 26 | #define FLT_ROUND 1 27 | #endif 28 | 29 | #define FLT_DIG 6 30 | #define FLT_EPSILON 0x1p-23 31 | #define FLT_MANT_DIG 24 32 | #define FLT_MAX 0x1.fffffep+127 33 | #define FLT_MAX_10_EXP 38 34 | #define FLT_MAX_EXP 128 35 | #define FLT_MIN 0x1p-126 36 | #define FLT_MIN_10_EXP -37 37 | #define FLT_MIN_EXP -125 38 | #define FLT_TRUE_MIN 0x1p-149 39 | 40 | #define DBL_DIG 15 41 | #define DBL_EPSILON 0x1p-52 42 | #define DBL_MANT_DIG 53 43 | #define DBL_MAX 0x1.fffffffffffffp+1023 44 | #define DBL_MAX_10_EXP 308 45 | #define DBL_MAX_EXP 1024 46 | #define DBL_MIN 0x1p-1022 47 | #define DBL_MIN_10_EXP -307 48 | #define DBL_MIN_EXP -1021 49 | #define DBL_TRUE_MIN 0x0.0000000000001p-1022 50 | 51 | #define LDBL_DIG 15 52 | #define LDBL_EPSILON 0x1p-52 53 | #define LDBL_MANT_DIG 53 54 | #define LDBL_MAX 0x1.fffffffffffffp+1023 55 | #define LDBL_MAX_10_EXP 308 56 | #define LDBL_MAX_EXP 1024 57 | #define LDBL_MIN 0x1p-1022 58 | #define LDBL_MIN_10_EXP -307 59 | #define LDBL_MIN_EXP -1021 60 | #define LDBL_TRUE_MIN 0x0.0000000000001p-1022 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdalign.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDALIGN_H 2 | #define __STDALIGN_H 3 | 4 | #define alignas _Alignas 5 | #define alignof _Alignof 6 | #define __alignas_is_defined 1 7 | #define __alignof_is_defined 1 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDARG_H 2 | #define __STDARG_H 3 | 4 | typedef __builtin_va_list va_list; 5 | 6 | #define va_start(ap, ...) __builtin_va_start(ap) 7 | 8 | #define va_end(ap) __builtin_va_end(ap) 9 | 10 | #define va_arg(ap, ty) __builtin_va_arg(ap, ty) 11 | 12 | #define va_copy(dest, src) __builtin_va_copy(dest, src) 13 | 14 | #define __GNUC_VA_LIST 1 15 | typedef va_list __gnuc_va_list; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdatomic.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDATOMIC_H 2 | #define __STDATOMIC_H 3 | 4 | #define ATOMIC_BOOL_LOCK_FREE 1 5 | #define ATOMIC_CHAR_LOCK_FREE 1 6 | #define ATOMIC_CHAR16_T_LOCK_FREE 1 7 | #define ATOMIC_CHAR32_T_LOCK_FREE 1 8 | #define ATOMIC_WCHAR_T_LOCK_FREE 1 9 | #define ATOMIC_SHORT_LOCK_FREE 1 10 | #define ATOMIC_INT_LOCK_FREE 1 11 | #define ATOMIC_LONG_LOCK_FREE 1 12 | #define ATOMIC_LLONG_LOCK_FREE 1 13 | #define ATOMIC_POINTER_LOCK_FREE 1 14 | 15 | typedef enum { 16 | memory_order_relaxed, 17 | memory_order_consume, 18 | memory_order_acquire, 19 | memory_order_release, 20 | memory_order_acq_rel, 21 | memory_order_seq_cst, 22 | } memory_order; 23 | 24 | #define ATOMIC_FLAG_INIT(x) (x) 25 | #define atomic_init(addr, val) (*(addr) = (val)) 26 | #define kill_dependency(x) (x) 27 | #define atomic_thread_fence(order) 28 | #define atomic_signal_fence(order) 29 | #define atomic_is_lock_free(x) 1 30 | 31 | #define atomic_load(addr) (*(addr)) 32 | #define atomic_store(addr, val) (*(addr) = (val)) 33 | 34 | #define atomic_load_explicit(addr, order) (*(addr)) 35 | #define atomic_store_explicit(addr, val, order) (*(addr) = (val)) 36 | 37 | #define atomic_fetch_add(addr, val) __builtin_atomic_fetch_add(addr, val) 38 | #define atomic_fetch_sub(addr, val) __builtin_atomic_fetch_sub(addr, val) 39 | #define atomic_fetch_or(addr, val) __builtin_atomic_fetch_or(addr, val) 40 | #define atomic_fetch_xor(addr, val) __builtin_atomic_fetch_xor(addr, val) 41 | #define atomic_fetch_and(addr, val) __builtin_atomic_fetch_and(addr, val) 42 | 43 | #define atomic_fetch_add_explicit(addr, val, order) __builtin_atomic_fetch_add(addr, val) 44 | #define atomic_fetch_sub_explicit(addr, val, order) __builtin_atomic_fetch_sub(addr, val) 45 | #define atomic_fetch_or_explicit(addr, val, order) __builtin_atomic_fetch_or(addr, val) 46 | #define atomic_fetch_xor_explicit(addr, val, order) __builtin_atomic_fetch_xor(addr, val) 47 | #define atomic_fetch_and_explicit(addr, val, order) __builtin_atomic_fetch_and(addr, val) 48 | 49 | #define atomic_compare_exchange_weak(p, old, new) \ 50 | __builtin_compare_and_swap((p), (old), (new)) 51 | 52 | #define atomic_compare_exchange_strong(p, old, new) \ 53 | __builtin_compare_and_swap((p), (old), (new)) 54 | 55 | #define atomic_compare_exchange_weak_explicit(p, old, new, succ, fail) \ 56 | __builtin_compare_and_swap((p), (old), (new)) 57 | 58 | #define atomic_compare_exchange_strong_explicit(p, old, new, succ, fail) \ 59 | __builtin_compare_and_swap((p), (old), (new)) 60 | 61 | #define atomic_exchange(obj, val) __builtin_atomic_exchange((obj), (val)) 62 | #define atomic_exchange_explicit(obj, val, order) __builtin_atomic_exchange((obj), (val)) 63 | 64 | #define atomic_flag_test_and_set(obj) atomic_exchange((obj), 1) 65 | #define atomic_flag_test_and_set_explicit(obj, order) atomic_exchange((obj), 1) 66 | #define atomic_flag_clear(obj) (*(obj) = 0) 67 | #define atomic_flag_clear_explicit(obj, order) (*(obj) = 0) 68 | 69 | typedef _Atomic _Bool atomic_flag; 70 | typedef _Atomic _Bool atomic_bool; 71 | typedef _Atomic char atomic_char; 72 | typedef _Atomic signed char atomic_schar; 73 | typedef _Atomic unsigned char atomic_uchar; 74 | typedef _Atomic short atomic_short; 75 | typedef _Atomic unsigned short atomic_ushort; 76 | typedef _Atomic int atomic_int; 77 | typedef _Atomic unsigned int atomic_uint; 78 | typedef _Atomic long atomic_long; 79 | typedef _Atomic unsigned long atomic_ulong; 80 | typedef _Atomic long long atomic_llong; 81 | typedef _Atomic unsigned long long atomic_ullong; 82 | typedef _Atomic unsigned short atomic_char16_t; 83 | typedef _Atomic unsigned atomic_char32_t; 84 | typedef _Atomic unsigned atomic_wchar_t; 85 | typedef _Atomic signed char atomic_int_least8_t; 86 | typedef _Atomic unsigned char atomic_uint_least8_t; 87 | typedef _Atomic short atomic_int_least16_t; 88 | typedef _Atomic unsigned short atomic_uint_least16_t; 89 | typedef _Atomic int atomic_int_least32_t; 90 | typedef _Atomic unsigned int atomic_uint_least32_t; 91 | typedef _Atomic long atomic_int_least64_t; 92 | typedef _Atomic unsigned long atomic_uint_least64_t; 93 | typedef _Atomic signed char atomic_int_fast8_t; 94 | typedef _Atomic unsigned char atomic_uint_fast8_t; 95 | typedef _Atomic short atomic_int_fast16_t; 96 | typedef _Atomic unsigned short atomic_uint_fast16_t; 97 | typedef _Atomic int atomic_int_fast32_t; 98 | typedef _Atomic unsigned int atomic_uint_fast32_t; 99 | typedef _Atomic long atomic_int_fast64_t; 100 | typedef _Atomic unsigned long atomic_uint_fast64_t; 101 | typedef _Atomic long atomic_intptr_t; 102 | typedef _Atomic unsigned long atomic_uintptr_t; 103 | typedef _Atomic unsigned long atomic_size_t; 104 | typedef _Atomic long atomic_ptrdiff_t; 105 | typedef _Atomic long atomic_intmax_t; 106 | typedef _Atomic unsigned long atomic_uintmax_t; 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDBOOL_H 2 | #define __STDBOOL_H 3 | 4 | #define bool _Bool 5 | #define true 1 6 | #define false 0 7 | #define __bool_true_false_are_defined 1 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdckdint.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDC_VERSION_STDCKDINT_H__ 2 | #define __STDC_VERSION_STDCKDINT_H__ 202311L 3 | 4 | #define ckd_add(_ptr, _lh, _rh) __builtin_add_overflow((_lh), (_rh), (_ptr)) 5 | #define ckd_sub(_ptr, _lh, _rh) __builtin_sub_overflow((_lh), (_rh), (_ptr)) 6 | #define ckd_mul(_ptr, _lh, _rh) __builtin_mul_overflow((_lh), (_rh), (_ptr)) 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdcountof.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDC_VERSION_STDCOUNTOF_H__ 2 | #define __STDC_VERSION_STDCOUNTOF_H__ 3 | 4 | #define countof _Countof 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /slimcc_headers/include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDDEF_H 2 | #define __STDDEF_H 3 | 4 | #define NULL ((void *)0) 5 | 6 | #if __STDC_VERSION__ >= 202311L 7 | typedef typeof(nullptr) nullptr_t; 8 | #endif 9 | 10 | typedef unsigned long size_t; 11 | typedef long ptrdiff_t; 12 | typedef int wchar_t; 13 | typedef struct { 14 | long long __ll; 15 | long double __ld; 16 | } max_align_t; 17 | 18 | #define offsetof(type, member) __builtin_offsetof(type, member) 19 | #endif 20 | -------------------------------------------------------------------------------- /slimcc_headers/include/stdnoreturn.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDNORETURN_H 2 | #define __STDNORETURN_H 3 | 4 | #define noreturn _Noreturn 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /slimcc_headers/platform_fix/freebsd/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLAT_CTYPE_H 2 | #define _PLAT_CTYPE_H 3 | 4 | #include 5 | 6 | #include_next 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /slimcc_headers/platform_fix/freebsd/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLAT_STDLIB_H 2 | #define _PLAT_STDLIB_H 3 | 4 | #include_next 5 | 6 | #define alloca(sz) __builtin_alloca(sz) 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /slimcc_headers/platform_fix/freebsd/sys/cdefs.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLAT_SYS_CDEFS_H 2 | #define _PLAT_SYS_CDEFS_H 3 | 4 | #define __compiler_membar() __asm __volatile(" " : : : "memory") 5 | 6 | #define __CC_SUPPORTS_SYMVER 1 7 | 8 | #include_next 9 | 10 | #define __inline inline 11 | 12 | #undef _Alignas 13 | #undef _Alignof 14 | #undef _Noreturn 15 | #undef _Thread_Local 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /slimcc_headers/platform_fix/openbsd/sys/cdefs.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLAT_SYS_CDEFS_H 2 | #define _PLAT_SYS_CDEFS_H 3 | 4 | #include_next 5 | 6 | #define __inline inline 7 | #define __returns_twice __attribute__((returns_twice)) 8 | #define __only_inline extern __inline __attribute__((__gnu_inline__)) 9 | #define __packed __attribute__((__packed__)) 10 | #define __aligned(x) __attribute__((__aligned__(x))) 11 | #define __dso_public __attribute__((__visibility__("default"))) 12 | #define __dso_hidden __attribute__((__visibility__("hidden"))) 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /strings.c: -------------------------------------------------------------------------------- 1 | #include "slimcc.h" 2 | 3 | void strarray_push(StringArray *arr, char *s) { 4 | if (!arr->data) { 5 | arr->data = calloc(8, sizeof(char *)); 6 | arr->capacity = 8; 7 | } 8 | 9 | if (arr->capacity == arr->len) { 10 | arr->data = realloc(arr->data, sizeof(char *) * arr->capacity * 2); 11 | arr->capacity *= 2; 12 | for (int i = arr->len; i < arr->capacity; i++) 13 | arr->data[i] = NULL; 14 | } 15 | 16 | arr->data[arr->len++] = s; 17 | } 18 | 19 | // Takes a printf-style format string and returns a formatted string. 20 | char *format(char *fmt, ...) { 21 | char *buf; 22 | size_t buflen; 23 | FILE *out = open_memstream(&buf, &buflen); 24 | 25 | va_list ap; 26 | va_start(ap, fmt); 27 | vfprintf(out, fmt, ap); 28 | va_end(ap); 29 | fclose(out); 30 | return buf; 31 | } 32 | -------------------------------------------------------------------------------- /test/alignas2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | struct S { 3 | _Alignas(2048) char i[127]; 4 | }; 5 | 6 | static void lvar(int cnt) { 7 | if (cnt > 3) 8 | return; 9 | ASSERT(0, ({ _Alignas(1024) int i; (unsigned long)&i % 1024; })); 10 | lvar(cnt + 1); 11 | } 12 | 13 | static void larray(int cnt) { 14 | if (cnt > 3) 15 | return; 16 | ASSERT(0, ({ _Alignas(512) char arr[17]; (unsigned long)&arr[0] % 512; })); 17 | larray(cnt + 1); 18 | } 19 | 20 | static void vla(int cnt) { 21 | if (cnt > 3) 22 | return; 23 | ASSERT(0, ({ _Alignas(256) char vla[cnt]; (unsigned long)&vla[0] % 256; })); 24 | vla(cnt + 1); 25 | } 26 | 27 | static void lstruct(int cnt) { 28 | if (cnt > 3) 29 | return; 30 | ASSERT(0, ({ struct S s; (unsigned long)&s.i % 2048; })); 31 | lstruct(cnt + 1); 32 | } 33 | 34 | static void pass_by_stack_struct(int cnt, struct S s) { 35 | if (cnt > 3) 36 | return; 37 | ASSERT(0, ({ (unsigned long)&s.i % 2048; })); 38 | pass_by_stack_struct(cnt + 1, s); 39 | } 40 | 41 | static void mix(int cnt, struct S s) { 42 | if (cnt > 3) 43 | return; 44 | 45 | ASSERT(0, ({ (unsigned long)&s.i % 2048; })); 46 | 47 | _Alignas(1024) int i; 48 | ASSERT(0, (unsigned long)&i % 1024 ); 49 | 50 | _Alignas(256) char arr[17]; 51 | ASSERT(0, (unsigned long)&arr[0] % 256 ); 52 | 53 | _Alignas(512) char vla[cnt]; 54 | ASSERT(0, ({ (unsigned long)&vla[0] % 512; })); 55 | 56 | struct S s2 = s; 57 | ASSERT(0, (unsigned long)&s2.i % 2048 ); 58 | 59 | mix(cnt + 1, s2); 60 | } 61 | 62 | int main(void) { 63 | struct S s; 64 | ASSERT(0, (unsigned long)&s.i % 2048 ); 65 | 66 | lvar(1); 67 | larray(1); 68 | vla(1); 69 | lstruct(1); 70 | pass_by_stack_struct(1,s); 71 | mix(1, s); 72 | 73 | printf("OK\n"); 74 | return 0; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /test/alignof.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int _Alignas(512) g1; 4 | int _Alignas(512) g2; 5 | char g3; 6 | int g4; 7 | long g5; 8 | char g6; 9 | 10 | int main() { 11 | EASSERT(1, _Alignof(char)); 12 | EASSERT(2, _Alignof(short)); 13 | EASSERT(4, _Alignof(int)); 14 | EASSERT(8, _Alignof(long)); 15 | EASSERT(8, _Alignof(long long)); 16 | EASSERT(1, _Alignof(char[3])); 17 | EASSERT(4, _Alignof(int[3])); 18 | EASSERT(1, _Alignof(struct {char a; char b;}[2])); 19 | EASSERT(8, _Alignof(struct {char a; long b;}[2])); 20 | 21 | // ASSERT(1, ({ _Alignas(char) char x, y; &y-&x; })); 22 | ASSERT(0, ({ _Alignas(long) char x, y; 7 & (intptr_t)&x; })); 23 | ASSERT(0, ({ _Alignas(32) char x, y; 31 & (intptr_t)&y; })); 24 | ASSERT(0, ({ _Alignas(32) int *x, *y; 31 & (intptr_t)&y; })); 25 | ASSERT(0, ({ struct { _Alignas(16) char x, y; } a; 15 & (intptr_t)&a.y; })); 26 | ASSERT(8, ({ struct T { _Alignas(8) char a; }; _Alignof(struct T); })); 27 | 28 | ASSERT(0, (long)(char *)&g1 % 512); 29 | ASSERT(0, (long)(char *)&g2 % 512); 30 | ASSERT(0, (long)(char *)&g4 % 4); 31 | ASSERT(0, (long)(char *)&g5 % 8); 32 | 33 | ASSERT(1, ({ char x; _Alignof(x); })); 34 | ASSERT(4, ({ int x; _Alignof(x); })); 35 | ASSERT(1, ({ char x; _Alignof x; })); 36 | ASSERT(4, ({ int x; _Alignof x; })); 37 | 38 | EASSERT(1, _Alignof(char) << 31 >> 31); 39 | EASSERT(1, _Alignof(char) << 63 >> 63); 40 | ASSERT(1, ({ char x; _Alignof(x) << 63 >> 63; })); 41 | 42 | ASSERT(0, ({ char x[16]; (unsigned long)&x % 16; })); 43 | ASSERT(0, ({ char x[17]; (unsigned long)&x % 16; })); 44 | ASSERT(0, ({ char x[100]; (unsigned long)&x % 16; })); 45 | ASSERT(0, ({ char x[101]; (unsigned long)&x % 16; })); 46 | 47 | printf("OK\n"); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/alignof2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main(int argc, char**argv) { 4 | 5 | EASSERT(1, _Alignof (char [argc])); 6 | 7 | char _Alignas(1024) arr1[11]; 8 | char _Alignas(1024) arr2[argc]; 9 | EASSERT(1024, _Alignof arr1); 10 | EASSERT(1, _Alignof arr1[0]); 11 | 12 | EASSERT(1024, _Alignof arr2); 13 | EASSERT(1, _Alignof arr2[0]); 14 | 15 | struct { 16 | char c; 17 | _Alignas(1024) int i; 18 | } s; 19 | EASSERT(1024, _Alignof s); 20 | EASSERT(1, _Alignof s.c); 21 | EASSERT(1024, _Alignof s.i); 22 | 23 | EASSERT(1, _Alignof (char){1}); 24 | 25 | printf("OK\n"); 26 | } 27 | -------------------------------------------------------------------------------- /test/alloca.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | void *fn(int x, void *p, int y) { return p; } 4 | 5 | int main() { 6 | int i = 0; 7 | 8 | char *p1 = alloca(16); 9 | char *p2 = alloca(16); 10 | char *p3 = 1 + (char *)alloca(3) + 1; 11 | p3 -= 2; 12 | char *p4 = fn(1, alloca(16), 3); 13 | 14 | ASSERT(16, p1 - p2); 15 | ASSERT(16, p2 - p3); 16 | ASSERT(16, p3 - p4); 17 | 18 | memcpy(p1, "0123456789abcdef", 16); 19 | memcpy(p2, "ghijklmnopqrstuv", 16); 20 | memcpy(p3, "wxy", 3); 21 | 22 | ASSERT(0, memcmp(p1, "0123456789abcdef", 16)); 23 | ASSERT(0, memcmp(p2, "ghijklmnopqrstuv", 16)); 24 | ASSERT(0, memcmp(p3, "wxy", 3)); 25 | 26 | printf("OK\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/arith.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | EASSERT(0, 0); 5 | EASSERT(42, 42); 6 | EASSERT(21, 5+20-4); 7 | EASSERT(41, 12 + 34 - 5 ); 8 | EASSERT(47, 5+6*7); 9 | EASSERT(15, 5*(9-6)); 10 | EASSERT(4, (3+5)/2); 11 | EASSERT(10, -10+20); 12 | EASSERT(10, - -10); 13 | EASSERT(10, - - +10); 14 | 15 | EASSERT(0, 0==1); 16 | EASSERT(1, 42==42); 17 | EASSERT(1, 0!=1); 18 | EASSERT(0, 42!=42); 19 | 20 | EASSERT(1, 0<1); 21 | EASSERT(0, 1<1); 22 | EASSERT(0, 2<1); 23 | EASSERT(1, 0<=1); 24 | EASSERT(1, 1<=1); 25 | EASSERT(0, 2<=1); 26 | 27 | EASSERT(1, 1>0); 28 | EASSERT(0, 1>1); 29 | EASSERT(0, 1>2); 30 | EASSERT(1, 1>=0); 31 | EASSERT(1, 1>=1); 32 | EASSERT(0, 1>=2); 33 | 34 | EASSERT(0, 1073741824 * 100 / 100); 35 | 36 | ASSERT(7, ({ int i=2; i+=5; i; })); 37 | ASSERT(7, ({ int i=2; i+=5; })); 38 | ASSERT(3, ({ int i=5; i-=2; i; })); 39 | ASSERT(3, ({ int i=5; i-=2; })); 40 | ASSERT(6, ({ int i=3; i*=2; i; })); 41 | ASSERT(6, ({ int i=3; i*=2; })); 42 | ASSERT(3, ({ int i=6; i/=2; i; })); 43 | ASSERT(3, ({ int i=6; i/=2; })); 44 | 45 | ASSERT(3, ({ int i=2; ++i; })); 46 | ASSERT(2, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; ++*p; })); 47 | ASSERT(0, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; --*p; })); 48 | 49 | ASSERT(2, ({ int i=2; i++; })); 50 | ASSERT(2, ({ int i=2; i--; })); 51 | ASSERT(3, ({ int i=2; i++; i; })); 52 | ASSERT(1, ({ int i=2; i--; i; })); 53 | ASSERT(1, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; *p++; })); 54 | ASSERT(1, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; *p--; })); 55 | 56 | ASSERT(0, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p++)--; a[0]; })); 57 | ASSERT(0, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*(p--))--; a[1]; })); 58 | ASSERT(2, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p)--; a[2]; })); 59 | ASSERT(2, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p)--; p++; *p; })); 60 | 61 | ASSERT(0, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p++)--; a[0]; })); 62 | ASSERT(0, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p++)--; a[1]; })); 63 | ASSERT(2, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p++)--; a[2]; })); 64 | ASSERT(2, ({ int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p=a+1; (*p++)--; *p; })); 65 | 66 | EASSERT(0, !1); 67 | EASSERT(0, !2); 68 | EASSERT(1, !0); 69 | EASSERT(1, !(char)0); 70 | EASSERT(0, !(long)3); 71 | EASSERT(4, sizeof(!(char)0)); 72 | EASSERT(4, sizeof(!(long)0)); 73 | 74 | EASSERT(-1, ~0); 75 | EASSERT(0, ~-1); 76 | 77 | EASSERT(5, 17%6); 78 | EASSERT(5, ((long)17)%6); 79 | ASSERT(2, ({ int i=10; i%=4; i; })); 80 | ASSERT(2, ({ long i=10; i%=4; i; })); 81 | 82 | EASSERT(0, 0&1); 83 | EASSERT(1, 3&1); 84 | EASSERT(3, 7&3); 85 | EASSERT(10, -1&10); 86 | 87 | EASSERT(1, 0|1); 88 | EASSERT(0b10011, 0b10000|0b00011); 89 | 90 | EASSERT(0, 0^0); 91 | EASSERT(0, 0b1111^0b1111); 92 | EASSERT(0b110100, 0b111000^0b001100); 93 | 94 | ASSERT(2, ({ int i=6; i&=3; i; })); 95 | ASSERT(7, ({ int i=6; i|=3; i; })); 96 | ASSERT(10, ({ int i=15; i^=5; i; })); 97 | 98 | EASSERT(1, 1<<0); 99 | EASSERT(8, 1<<3); 100 | EASSERT(10, 5<<1); 101 | EASSERT(2, 5>>1); 102 | EASSERT(-1, -1>>1); 103 | ASSERT(1, ({ int i=1; i<<=0; i; })); 104 | ASSERT(8, ({ int i=1; i<<=3; i; })); 105 | ASSERT(10, ({ int i=5; i<<=1; i; })); 106 | ASSERT(2, ({ int i=5; i>>=1; i; })); 107 | EASSERT(-1, -1); 108 | ASSERT(-1, ({ int i=-1; i; })); 109 | ASSERT(-1, ({ int i=-1; i>>=1; i; })); 110 | 111 | EASSERT(2, 0?1:2); 112 | EASSERT(1, 1?1:2); 113 | EASSERT(-1, 0?-2:-1); 114 | EASSERT(-2, 1?-2:-1); 115 | EASSERT(4, sizeof(0?1:2)); 116 | EASSERT(8, sizeof(0?(long)1:(long)2)); 117 | EASSERT(-1, 0?(long)-2:-1); 118 | EASSERT(-1, 0?-2:(long)-1); 119 | EASSERT(-2, 1?(long)-2:-1); 120 | EASSERT(-2, 1?-2:(long)-1); 121 | 122 | 1 ? -2 : (void)-1; 123 | 124 | ASSERT(20, ({ int x; int *p=&x; p+20-p; })); 125 | ASSERT(1, ({ int x; int *p=&x; p+20-p>0; })); 126 | ASSERT(-20, ({ int x; int *p=&x; p-20-p; })); 127 | ASSERT(1, ({ int x; int *p=&x; p-20-p<0; })); 128 | 129 | EASSERT(15, (char *)0xffffffffffffffff - (char *)0xfffffffffffffff0); 130 | EASSERT(-15, (char *)0xfffffffffffffff0 - (char *)0xffffffffffffffff); 131 | EASSERT(1, (void *)0xffffffffffffffff > (void *)0); 132 | 133 | ASSERT(3, 3?:5); 134 | ASSERT(5, 0?:5); 135 | ASSERT(4, ({ int i = 3; ++i?:10; })); 136 | 137 | EASSERT(3, (long double)3); 138 | EASSERT(5, (long double)3+2); 139 | EASSERT(6, (long double)3*2); 140 | EASSERT(5, (long double)3+2.0); 141 | 142 | printf("OK\n"); 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /test/asm.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | char *asm_fn1(void) { 4 | __asm__("mov $50, %rax\n\t" 5 | "mov %rbp, %rsp\n\t" 6 | "pop %rbp\n\t" 7 | "ret"); 8 | } 9 | 10 | char *asm_fn2(void) { 11 | __asm__ inline volatile("mov $55, %rax\n\t" 12 | "mov %rbp, %rsp\n\t" 13 | "pop %rbp\n\t" 14 | "ret"); 15 | } 16 | 17 | int main() { 18 | ASSERT(50, asm_fn1()); 19 | ASSERT(55, asm_fn2()); 20 | 21 | printf("OK\n"); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /test/asm_name.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int neg(int i) { 4 | return -i; 5 | } 6 | 7 | typeof(int(int)) g_proto __asm("neg") __attribute__((visibility("default"))); 8 | 9 | typeof(int(int)) *g_fp = &g_proto; 10 | 11 | extern typeof(int(int)) *ext_fp __asm("g_fp"); 12 | 13 | int main(void) { 14 | extern typeof(int(int)) l_proto __asm("neg"); 15 | 16 | ASSERT(-11, g_proto(11)); 17 | ASSERT(-22, l_proto(22)); 18 | ASSERT(-33, g_fp(33)); 19 | ASSERT(-44, ext_fp(44)); 20 | 21 | printf("OK\n"); 22 | } 23 | -------------------------------------------------------------------------------- /test/atomic.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | #include 4 | 5 | static int incr(_Atomic int *p) { 6 | int oldval = *p; 7 | int newval; 8 | do { 9 | newval = oldval + 1; 10 | } while (!atomic_compare_exchange_weak(p, &oldval, newval)); 11 | return newval; 12 | } 13 | 14 | static int add1(void *arg) { 15 | _Atomic int *x = arg; 16 | for (int i = 0; i < 1000*1000; i++) 17 | incr(x); 18 | return 0; 19 | } 20 | 21 | static int add2(void *arg) { 22 | _Atomic int *x = arg; 23 | for (int i = 0; i < 1000*1000; i++) 24 | (*x)++; 25 | return 0; 26 | } 27 | 28 | static int add3(void *arg) { 29 | _Atomic int *x = arg; 30 | for (int i = 0; i < 1000*1000; i++) 31 | *x += 5; 32 | return 0; 33 | } 34 | 35 | static int add_millions(void) { 36 | _Atomic int x = 0; 37 | 38 | pthread_t thr1; 39 | pthread_t thr2; 40 | pthread_t thr3; 41 | 42 | pthread_create(&thr1, NULL, add1, &x); 43 | pthread_create(&thr2, NULL, add2, &x); 44 | pthread_create(&thr3, NULL, add3, &x); 45 | 46 | for (int i = 0; i < 1000*1000; i++) 47 | x--; 48 | 49 | pthread_join(thr1, NULL); 50 | pthread_join(thr2, NULL); 51 | pthread_join(thr3, NULL); 52 | return x; 53 | } 54 | 55 | int main() { 56 | ASSERT(6*1000*1000, add_millions()); 57 | 58 | ASSERT(3, ({ int x=3; atomic_exchange(&x, 5); })); 59 | ASSERT(5, ({ int x=3; atomic_exchange(&x, 5); x; })); 60 | 61 | printf("OK\n"); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /test/atomic2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | int ptr_arith(void) { 5 | int32_t *_Atomic p = NULL; 6 | int32_t *p2 = atomic_fetch_add(&p, 1); 7 | #ifdef NOTGCC 8 | ASSERT(4, (long)p); 9 | #endif 10 | ASSERT(0, (long)p2); 11 | } 12 | 13 | int f32(void) { 14 | _Atomic float f = 5.0f; 15 | 16 | ASSERT(1, 8.0f == (f += 3.0f)); 17 | #ifdef NOTGCC 18 | ASSERT(1, 8.0f == atomic_fetch_sub(&f, 2.0f)); 19 | ASSERT(1, 6.0f == f); 20 | #endif 21 | } 22 | 23 | int f64(void) { 24 | _Atomic double d = 10.0; 25 | 26 | ASSERT(1, 7.0 == (d -= 3.0)); 27 | #ifdef NOTGCC 28 | ASSERT(1, 7.0 == atomic_fetch_add(&d, 2.0)); 29 | ASSERT(1, 9.0 == d); 30 | #endif 31 | } 32 | 33 | int main(void) { 34 | ptr_arith(); 35 | f32(); 36 | f64(); 37 | 38 | printf("OK\n"); 39 | } 40 | -------------------------------------------------------------------------------- /test/attr_cleanup.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int rec_idx = 0; 4 | int rec[20]; 5 | 6 | void cln1(void *num) { 7 | rec[rec_idx++] = (*(long long*)num)++; 8 | } 9 | 10 | void cln2(void *num) { 11 | rec[rec_idx++] = 10 * (*(long long*)num)++; 12 | } 13 | 14 | #define A __attribute__((cleanup(cln1))) 15 | #define B [[gnu::cleanup(cln2)]] 16 | void test_decl(void) { 17 | rec_idx = 0; 18 | 19 | A long long p1 = 11; 20 | long A long p2 = 22; 21 | long long A p3 = 33, p4 = 44; 22 | long long p5 A = 55, p6 = 66; 23 | long long p7 = 77, A p8 = 88, pz = 999; 24 | long long p9 = 99, p11 A = 111; 25 | 26 | B long long p22 = 222; 27 | long long p33 B = 333, p44 = 444; 28 | long long p55 = 555, p66 B = 666; 29 | 30 | A long long p77 = 777, p88 B = 888; 31 | } 32 | 33 | void test_decl2(void) { 34 | rec_idx = 0; 35 | 36 | A long long *p1[1]; 37 | long A long *p2[1]; 38 | long long A *p3[1]; 39 | long long *A p4[1]; 40 | long long *p5[1] A; 41 | 42 | B long long *p6[1]; 43 | long long *p7 B[1]; 44 | } 45 | 46 | void test_loop(void) { 47 | rec_idx = 0; 48 | 49 | for(B long long i = 0; i < 3; i++) { 50 | B long long j = 11; 51 | switch (i) { 52 | case 0: 53 | continue; 54 | case 1: 55 | B long long j = 22; 56 | continue; 57 | } 58 | } 59 | } 60 | 61 | void test_vla(int sz) { 62 | rec_idx = 0; 63 | 64 | long long i __attribute__((cleanup(cln1))) = 222; 65 | 66 | long long vla[sz * 2] __attribute__((cleanup(cln1))); 67 | vla[0] = 137; 68 | 69 | long long j __attribute__((cleanup(cln1))) = 444; 70 | 71 | long long vla2[sz * 3] __attribute__((cleanup(cln1))); 72 | vla2[0] = 248; 73 | 74 | long long k __attribute__((cleanup(cln1))) = 555; 75 | return; 76 | } 77 | 78 | 79 | void void_nortn(void) { 80 | long long j __attribute__((cleanup(cln1))) = 11; 81 | } 82 | void void_rtn(void) { 83 | long long j __attribute__((cleanup(cln1))) = 22; 84 | return; 85 | } 86 | int int_rtn(void) { 87 | long long j __attribute__((cleanup(cln1))) = 33; 88 | return j; 89 | } 90 | 91 | void float_cln(float* num) { 92 | rec[0] = (*num)++; 93 | } 94 | float float_rtn(void) { 95 | float f __attribute__((cleanup(float_cln))) = 44; 96 | return f; 97 | } 98 | 99 | void ldouble_cln(long double* num) { 100 | rec[0] = (*num)++; 101 | } 102 | long double ldouble_rtn(void) { 103 | long double f __attribute__((cleanup(ldouble_cln))) = 55; 104 | return f; 105 | } 106 | 107 | typedef struct { 108 | char c; 109 | } Small; 110 | void small_struct_cln(Small* s) { 111 | rec[0] = (s->c)++; 112 | } 113 | Small small_struct_rtn(void) { 114 | Small s __attribute__((cleanup(small_struct_cln))) = {66}; 115 | return s; 116 | } 117 | 118 | typedef struct { 119 | int i[33]; 120 | char c; 121 | } Large; 122 | void large_struct_cln(Large* s) { 123 | rec[0] = (s->c)++; 124 | } 125 | Large large_struct_rtn(void) { 126 | Large s __attribute__((cleanup(large_struct_cln))) = {.c = 77}; 127 | return s; 128 | } 129 | 130 | static void small_bitint_cln(_BitInt(100)* s) { 131 | rec[0] = ++(*s); 132 | } 133 | _BitInt(100) small_bitint_rtn(void) { 134 | _BitInt(100) s __attribute__((cleanup(small_bitint_cln))) = -88; 135 | return s; 136 | } 137 | 138 | static void large_bitint_cln(_BitInt(400)* s) { 139 | rec[0] = ++(*s); 140 | } 141 | _BitInt(400) large_bitint_rtn(void) { 142 | _BitInt(400) s __attribute__((cleanup(large_bitint_cln))) = 99; 143 | return s; 144 | } 145 | 146 | struct S { 147 | int j,i; 148 | }; 149 | void add(struct S* s) { 150 | ASSERT(11, s->i += 7); 151 | } 152 | void stmt_expr(void) { 153 | int i = ({ 154 | struct S s __attribute__((cleanup(add))) = {3,4}; 155 | s; 156 | }).i; 157 | ASSERT(4, i); 158 | } 159 | 160 | static inline void livefn(void*){} 161 | 162 | int main(void) { 163 | test_decl(); 164 | ASSERT(888, rec[0]); 165 | ASSERT(777, rec[1]); 166 | ASSERT(6660, rec[2]); 167 | ASSERT(3330, rec[3]); 168 | ASSERT(2220, rec[4]); 169 | ASSERT(111, rec[5]); 170 | ASSERT(88, rec[6]); 171 | ASSERT(55, rec[7]); 172 | ASSERT(44, rec[8]); 173 | ASSERT(33, rec[9]); 174 | ASSERT(22, rec[10]); 175 | ASSERT(11, rec[11]); 176 | 177 | test_decl2(); 178 | ASSERT(7, rec_idx); 179 | 180 | test_loop(); 181 | ASSERT(110, rec[0]); 182 | ASSERT(220, rec[1]); 183 | ASSERT(110, rec[2]); 184 | ASSERT(110, rec[3]); 185 | ASSERT(30, rec[4]); 186 | 187 | test_vla(100); 188 | ASSERT(555, rec[0]); 189 | ASSERT(248, rec[1]); 190 | ASSERT(444, rec[2]); 191 | ASSERT(137, rec[3]); 192 | ASSERT(222, rec[4]); 193 | 194 | rec_idx = 0; 195 | void_nortn(); 196 | ASSERT(11, rec[0]); 197 | void_rtn(); 198 | ASSERT(22, rec[1]); 199 | ASSERT(33, int_rtn()); 200 | ASSERT(33, rec[2]); 201 | 202 | ASSERT(44, (int)float_rtn()); 203 | ASSERT(44, rec[0]); 204 | ASSERT(55, (int)ldouble_rtn()); 205 | ASSERT(55, rec[0]); 206 | ASSERT(66, small_struct_rtn().c); 207 | ASSERT(66, rec[0]); 208 | ASSERT(77, large_struct_rtn().c); 209 | ASSERT(77, rec[0]); 210 | ASSERT(1, -88wb == small_bitint_rtn()); 211 | ASSERT(-87, rec[0]); 212 | ASSERT(1, 99wb == large_bitint_rtn()); 213 | ASSERT(100, rec[0]); 214 | 215 | stmt_expr(); 216 | 217 | int testlive [[gnu::cleanup(livefn)]]; 218 | 219 | printf("OK\n"); 220 | } 221 | -------------------------------------------------------------------------------- /test/attr_section.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | struct S { void *p; }; 4 | 5 | const __attribute__((section("sec1"))) struct S const_no_relo = {0}; 6 | const __attribute__((section("sec1"))) struct S const_with_relo = {.p = test_assert}; 7 | 8 | int main(void) { 9 | printf("OK\n"); 10 | } 11 | -------------------------------------------------------------------------------- /test/attr_weak.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | int no_def(void) __attribute__ ((weak)); 3 | int has_def(void) __attribute__ ((weak)); 4 | 5 | int main(int argc, const char **argv) 6 | { 7 | int res = 0; 8 | int no_def_test; 9 | if (no_def) { 10 | no_def_test = 1; 11 | res = no_def(); 12 | } else { 13 | no_def_test = 0; 14 | } 15 | int has_def_test; 16 | if (has_def) { 17 | has_def_test = 1; 18 | res = has_def(); 19 | } else { 20 | has_def_test = 0; 21 | } 22 | ASSERT(0, no_def_test); 23 | ASSERT(1, has_def_test); 24 | ASSERT(123, res); 25 | 26 | printf("OK\n"); 27 | } 28 | 29 | int has_def(void){ 30 | return 123; 31 | } 32 | -------------------------------------------------------------------------------- /test/attribute.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include "stddef.h" 3 | 4 | int main() { 5 | ASSERT(5, ({ struct { char a; int b; } __attribute__((packed)) x; sizeof(x); })); 6 | EASSERT(0, offsetof(struct __attribute__((packed)) { char a; int b; }, a)); 7 | EASSERT(1, offsetof(struct __attribute__((packed)) { char a; int b; }, b)); 8 | 9 | ASSERT(5, ({ struct __attribute__((packed)) { char a; int b; } x; sizeof(x); })); 10 | EASSERT(0, offsetof(struct { char a; int b; } __attribute__((packed)), a)); 11 | EASSERT(1, offsetof(struct { char a; int b; } __attribute__((packed)), b)); 12 | 13 | ASSERT(9, ({ typedef struct { char a; int b[2]; } __attribute__((packed)) T; sizeof(T); })); 14 | ASSERT(9, ({ typedef struct __attribute__((packed)) { char a; int b[2]; } T; sizeof(T); })); 15 | 16 | EASSERT(1, offsetof(struct __attribute__((packed)) T { char a; int b[2]; }, b)); 17 | EASSERT(1, _Alignof(struct __attribute__((packed)) { char a; int b[2]; })); 18 | 19 | ASSERT(8, ({ struct __attribute__((aligned(8))) { int a; } x; _Alignof(x); })); 20 | ASSERT(8, ({ struct { int a; } __attribute__((aligned(8))) x; _Alignof(x); })); 21 | 22 | ASSERT(8, ({ struct __attribute__((aligned(8), packed)) { char a; int b; } x; _Alignof(x); })); 23 | ASSERT(8, ({ struct { char a; int b; } __attribute__((aligned(8), packed)) x; _Alignof(x); })); 24 | ASSERT(1, offsetof(struct __attribute__((aligned(8), packed)) { char a; int b; }, b)); 25 | ASSERT(1, offsetof(struct { char a; int b; } __attribute__((aligned(8), packed)), b)); 26 | 27 | ASSERT(8, ({ struct __attribute__((aligned(8))) __attribute__((packed)) { char a; int b; } x; _Alignof(x); })); 28 | ASSERT(8, ({ struct { char a; int b; } __attribute__((aligned(8))) __attribute__((packed)) x; _Alignof(x); })); 29 | ASSERT(1, offsetof(struct __attribute__((aligned(8))) __attribute__((packed)) { char a; int b; }, b)); 30 | ASSERT(1, offsetof(struct { char a; int b; } __attribute__((aligned(8))) __attribute__((packed)), b)); 31 | 32 | ASSERT(8, ({ struct __attribute__((aligned(8))) { char a; int b; } __attribute__((packed)) x; _Alignof(x); })); 33 | ASSERT(1, offsetof(struct __attribute__((aligned(8))) { char a; int b; } __attribute__((packed)), b)); 34 | 35 | ASSERT(16, ({ struct __attribute__((aligned(8+8))) { char a; int b; } x; _Alignof(x); })); 36 | 37 | printf("OK\n"); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /test/attribute2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #if !defined(__has_attribute) || !defined(__has_c_attribute) 4 | #error 5 | #endif 6 | 7 | #if !__has_attribute(packed) 8 | #error 9 | #endif 10 | 11 | #if __has_c_attribute(packed) 12 | #error 13 | #endif 14 | 15 | #define CAT(x,y) x##y 16 | 17 | int has_attr(void) { 18 | DASSERT(__has_attribute(packed) == 1); 19 | DASSERT( CAT(__has,_attribute)(packed) == 1); 20 | DASSERT(__has_c_attribute(gnu::packed) == 1); 21 | DASSERT(__has_c_attribute(gnu::__packed__) == 1); 22 | DASSERT(__has_c_attribute(clang::packed) == 0); 23 | } 24 | 25 | 26 | [[_Noreturn]] 27 | int fallthrough(int i) { 28 | switch (i){ 29 | case 3: 30 | [[fallthrough]]; 31 | default: 32 | } 33 | exit(0); 34 | } 35 | 36 | void packed(void) { 37 | EASSERT(0, offsetof(struct [[gnu::packed]] { char a; int b; }, a)); 38 | EASSERT(1, offsetof(struct [[gnu::__packed__]] { char a; int b; }, b)); 39 | ASSERT(5, ({ struct [[gnu::packed]] { char a; int b; } x; sizeof(x); })); 40 | ASSERT(9, ({ typedef struct [[gnu::packed]] { char a; int b[2]; } T; sizeof(T); })); 41 | EASSERT(1, offsetof(struct [[gnu::packed]] T { char a; int b[2]; }, b)); 42 | 43 | // no-op 44 | #ifdef NOTCLANG 45 | ASSERT(8, ({ struct { char a; int b; } [[gnu::packed]] x; sizeof(x); })); 46 | EASSERT(0, offsetof(struct { char a; int b; } [[gnu::packed]], a)); 47 | EASSERT(4, offsetof(struct { char a; int b; } [[gnu::packed]], b)); 48 | #endif 49 | ASSERT(12, ({ typedef struct [[packed]] { char a; int b[2]; } T; sizeof(T); })); 50 | EASSERT(4, offsetof(struct [[packed]] { char a; int b[2]; }, b)); 51 | 52 | ASSERT(9, ({ struct { struct { char m2; long m5; } __attribute__((packed)); } T; sizeof(T); })); 53 | ASSERT(2, ({ typedef struct { struct { int :9, m16; } __attribute__((packed)); } T; offsetof(T, m16); })); 54 | ASSERT(12, ({ struct __attribute__((packed)) { long :48, :46; } a; sizeof(a); })); 55 | } 56 | 57 | int main() { 58 | has_attr(); 59 | packed(); 60 | 61 | printf("OK\n"); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /test/attribute_hiding.c: -------------------------------------------------------------------------------- 1 | typedef union { 2 | void *ptr; 3 | int fd; 4 | unsigned u32; 5 | unsigned u64; 6 | } Data_t; 7 | 8 | struct pre_inc { 9 | unsigned events; 10 | Data_t data; 11 | } __attribute__((packed)); 12 | 13 | #include "test.h" 14 | 15 | struct post_inc { 16 | unsigned events; 17 | Data_t data; 18 | } __attribute__((packed)); 19 | 20 | #ifdef __attribute__ 21 | #undef __attribute__ 22 | #endif 23 | 24 | #define __attribute__(x) 25 | 26 | struct re_def { 27 | unsigned events; 28 | Data_t data; 29 | } __attribute__((packed)); 30 | 31 | 32 | void pre_include(void) { 33 | DASSERT(sizeof(struct pre_inc) == 12); 34 | DASSERT(offsetof(struct pre_inc, data) == 4); 35 | } 36 | 37 | void post_include(void){ 38 | DASSERT(sizeof(struct post_inc) == 12); 39 | DASSERT(offsetof(struct post_inc, data) == 4); 40 | } 41 | 42 | void redefined(void) { 43 | DASSERT(sizeof(struct re_def) == 16); 44 | DASSERT(offsetof(struct re_def, data) == 8); 45 | } 46 | 47 | int main() { 48 | pre_include(); 49 | post_include(); 50 | redefined(); 51 | 52 | printf("OK\n"); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /test/autotype.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | static auto d = 3.5; 4 | __auto_type dp = &d; 5 | static_assert(_Generic(d, double:1)); 6 | static_assert(_Generic(dp, double *:1)); 7 | 8 | char arr[17]; 9 | auto p1 = arr; 10 | auto p2 = &arr; 11 | static_assert(8 == sizeof(p1)); 12 | static_assert(1 == sizeof(*p1)); 13 | static_assert(8 == sizeof(p2)); 14 | static_assert(17 == sizeof(*p2)); 15 | 16 | int main(void) { 17 | typedef struct S S; 18 | auto sp = (S*)NULL; 19 | struct S { int i[17]; }; 20 | S s = {.i[13] = 19}; 21 | sp = (void*)&s; 22 | ASSERT(19, sp->i[13]); 23 | 24 | typedef char foo; 25 | { 26 | __auto_type foo = 0L; 27 | static_assert(_Generic(foo, long:1)); 28 | 29 | for (auto foo = 17.9;;) { 30 | static_assert(_Generic(foo, double:1)); 31 | break; 32 | } 33 | } 34 | 35 | ASSERT(1, ({const int init = 0; auto i = init; _Generic(&i, int *:1);})); 36 | ASSERT(1, ({const int init = 0; const auto i = init; _Generic(&i, int const*:1);})); 37 | 38 | printf("OK\n"); 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /test/bitfield.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | struct { 4 | char a; 5 | int b : 5; 6 | int c : 10; 7 | } g45 = {1, 2, 3}, g46={}; 8 | 9 | int main() { 10 | ASSERT(4, sizeof(struct {int x:1; })); 11 | ASSERT(8, sizeof(struct {long x:1; })); 12 | 13 | struct bit1 { 14 | short a; 15 | char b; 16 | int c : 2; 17 | int d : 3; 18 | int e : 3; 19 | }; 20 | 21 | ASSERT(4, sizeof(struct bit1)); 22 | ASSERT(1, ({ struct bit1 x; x.a=1; x.b=2; x.c=3; x.d=4; x.e=5; x.a; })); 23 | ASSERT(1, ({ struct bit1 x={1,2,3,4,5}; x.a; })); 24 | ASSERT(2, ({ struct bit1 x={1,2,3,4,5}; x.b; })); 25 | ASSERT(-1, ({ struct bit1 x={1,2,3,4,5}; x.c; })); 26 | ASSERT(-4, ({ struct bit1 x={1,2,3,4,5}; x.d; })); 27 | ASSERT(-3, ({ struct bit1 x={1,2,3,4,5}; x.e; })); 28 | 29 | ASSERT(1, g45.a); 30 | ASSERT(2, g45.b); 31 | ASSERT(3, g45.c); 32 | 33 | ASSERT(0, g46.a); 34 | ASSERT(0, g46.b); 35 | ASSERT(0, g46.c); 36 | 37 | typedef struct { 38 | int a : 10; 39 | int b : 10; 40 | int c : 10; 41 | } T3; 42 | 43 | ASSERT(1, ({ T3 x={1,2,3}; x.a++; })); 44 | ASSERT(2, ({ T3 x={1,2,3}; x.b++; })); 45 | ASSERT(3, ({ T3 x={1,2,3}; x.c++; })); 46 | 47 | ASSERT(2, ({ T3 x={1,2,3}; ++x.a; })); 48 | ASSERT(3, ({ T3 x={1,2,3}; ++x.b; })); 49 | ASSERT(4, ({ T3 x={1,2,3}; ++x.c; })); 50 | 51 | ASSERT(4, sizeof(struct {int a:3; int c:1; int c:5;})); 52 | ASSERT(8, sizeof(struct {int a:3; int:0; int c:5;})); 53 | ASSERT(4, sizeof(struct {int a:3; int:0;})); 54 | 55 | printf("OK\n"); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /test/bitfield2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | struct M { int : 0; int f2 : 12; }; 3 | 4 | int bitextract(void){ 5 | struct Fields { 6 | _Bool a :1; 7 | long long :3; 8 | unsigned b :4; 9 | _Bool c :1; 10 | unsigned d :3; 11 | unsigned e :2; 12 | long :2; 13 | }; 14 | 15 | struct Fields s1 = {11,22,33,44,55,66,77}; 16 | struct Fields s2 = {77,66,55,44,33,22,11}; 17 | 18 | ASSERT(4, sizeof(struct Fields)); 19 | ASSERT(4, _Alignof(struct Fields)); 20 | ASSERT(0, memcmp(&(int){14689}, &s1, 2)); 21 | ASSERT(0, memcmp(&(int){6433}, &s2, 2)); 22 | ASSERT(1, s1.a); 23 | ASSERT(6, s1.b); 24 | ASSERT(1, s1.c); 25 | ASSERT(4, s1.d); 26 | ASSERT(3, s1.e); 27 | 28 | ASSERT(1, s2.a); 29 | ASSERT(2, s2.b); 30 | ASSERT(1, s2.c); 31 | ASSERT(4, s2.d); 32 | ASSERT(1, s2.e); 33 | } 34 | 35 | int struct_init(void) { 36 | struct M m = {11,22}; 37 | ASSERT(11, ({ m.f2; })); 38 | 39 | ASSERT(11, ({ struct { int :1,a,:1,b,:1,:1,c,:1; } s = {11,22,33}; s.a; })); 40 | ASSERT(22, ({ struct { int :1,a,:1,b,:1,:1,c,:1; } s = {11,22,33}; s.b; })); 41 | ASSERT(33, ({ struct { int :1,a,:1,b,:1,:1,c,:1; } s = {11,22,33}; s.c; })); 42 | 43 | ASSERT(11, ({ struct { int a,:1,b,:1,:1,c,:1; } s = {.a=11,22,33}; s.a; })); 44 | ASSERT(22, ({ struct { int a,:1,b,:1,:1,c,:1; } s = {.a=11,22,33}; s.b; })); 45 | ASSERT(33, ({ struct { int a,:1,b,:1,:1,c,:1; } s = {.a=11,22,33}; s.c; })); 46 | 47 | ASSERT(11, ({ struct { struct { int a,:1,b,:1,:1,c,:1; }; } s = {.a=11,22,33}; s.a; })); 48 | ASSERT(22, ({ struct { struct { int a,:1,b; int;int :1,c,:1; }; } s = {.a=11,22,33}; s.b; })); 49 | ASSERT(33, ({ struct { struct { int a,:1,b,:1,:1,c,:1; }; } s = {.a=11,22,33}; s.c; })); 50 | 51 | ASSERT(22, ({ struct { struct { int a; int; int b; int; int; int c; int; }; } s = {.a=11,22,33}; s.b; })); 52 | 53 | ASSERT(33, ({ struct { int a; struct {int:1,:1;}; int b; } s = {11,{},33}; s.b; })); 54 | ASSERT(33, ({ struct { int a; struct {int:1,:1;}; int b; } s = {.a=11,{},33}; s.b; })); 55 | ASSERT(22, ({ struct { struct { }; int a; } s = {{},22,33}; s.a; })); 56 | ASSERT(22, ({ struct { struct { int :1,:1; }; int a; } s = {{},22,33}; s.a; })); 57 | 58 | ASSERT(22, ({ struct { int :1; int a; int :1; struct { int :1; int b; int:1; int c; }; } s = {11,22,33}; s.b; })); 59 | ASSERT(33, ({ struct { int :1; int a; int :1; struct { int :1; int b; int:1; int c; }; } s = {11,22,33}; s.c; })); 60 | } 61 | 62 | void union_init(void) { 63 | 64 | ASSERT(33, ({ union { int :1,:1; int a; } s = {33}; s.a; })); 65 | ASSERT(33, ({ struct { union { int :1,:1; }; int a;} s = {{23},33}; s.a;})); 66 | ASSERT(33, ({ struct { union { int :1,:1; }; int a;} s = {{23},33}; s.a;})); 67 | 68 | ASSERT(11, ({ struct { int a; union { int :1,:7; }; int b; } s = {11,{},33}; s.a; })); 69 | ASSERT(33, ({ struct { int a; union { int :1,:7; }; int b; } s = {11,{},33}; s.b; })); 70 | 71 | ASSERT(11, ({ union { struct { int a,:1,b,:1,:1,c,:1; }; } s = {.a=11,22,33}; s.a; })); 72 | ASSERT(22, ({ union { struct { int a,:1,b,:1,:1,c,:1; }; } s = {.a=11,22,33}; s.b; })); 73 | ASSERT(33, ({ union { struct { int a,:1,b,:1,:1,c,:1; }; } s = {.a=11,22,33}; s.c; })); 74 | 75 | 76 | ASSERT(22, ({ union { struct { int a, :1; int b, :1, :1; int c, :1; }; } s = {.a=11,22,33}; s.b; })); 77 | 78 | ASSERT(0, ({ union { union { }; int a; } s = {{}}; s.a; })); 79 | 80 | ASSERT(0, ({ union { struct { int :1,:1; }; int a; } s = {{}}; s.a; })); 81 | 82 | ASSERT(22, ({ struct { int a; union { int:1; int b; }; } s = {11,22}; s.b; })); 83 | } 84 | 85 | int assign_expr(void) { 86 | struct { 87 | int i : 2; 88 | _Bool b : 1; 89 | unsigned j : 2; 90 | } s = {.b = 1}; 91 | int x = s.i = -5; 92 | int y = s.j = 5; 93 | ASSERT(-1, x); 94 | ASSERT(1, y); 95 | x = s.i += -5; 96 | y = s.j += 5; 97 | int z = s.b >>= 1; 98 | 99 | ASSERT(-2, x); 100 | ASSERT(2, y); 101 | ASSERT(0, (s.b >>= 1)); 102 | } 103 | 104 | int large_field(void) { 105 | ASSERT(1, ({ struct { unsigned long long i: 56; } s = {.i = 0xFFFFFFFFFFFFFFFF }; s.i == 0xFFFFFFFFFFFFFF; }) ); 106 | } 107 | 108 | void signed_large_field(void) { 109 | struct { 110 | long long i:4, j:33, k:27; 111 | } s; 112 | s.k = -1234; 113 | s.i = -1; 114 | char buf[32]; 115 | snprintf(buf, 32, "%d, %lld, %d", s.i, s.j = -54321, s.k); 116 | ASSERT(0, strcmp("-1, -54321, -1234", buf)); 117 | } 118 | 119 | struct { 120 | int b :3; 121 | int i, j; 122 | } s = {.i = 2, 3}; 123 | 124 | int uninit_global(void) { 125 | ASSERT(2, s.i); 126 | ASSERT(3, s.j); 127 | } 128 | 129 | static int operand_promotion(void) { 130 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; s.i > -1; }) ); 131 | ASSERT(0, ({ struct { unsigned i:8; } s = {0}; ((unsigned)s.i - 1) < 0; }) ); 132 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(0, s.i) < 0; }) ); 133 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~({s.i;}) < 0; }) ); 134 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(s.i = 0) < 0; }) ); 135 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(s.i += 0) < 0; }) ); 136 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(s.i++) < 0; }) ); 137 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(1 ? s.i : s.i) < 0; }) ); 138 | 139 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(0, (1 ? s.i : s.i)) < 0; }) ); 140 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~({(1 ? s.i : s.i);}) < 0; }) ); 141 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~({s.i = 0;}) < 0; }) ); 142 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(1 ? ({(0,s.i);}) : (0,({s.i;}))) < 0; }) ); 143 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(1 ? (s.i = 0) : (0,({s.i;}))) < 0; }) ); 144 | ASSERT(1, ({ struct { unsigned i:8; } s = {0}; ~(1 ? (s.i = 0) : ({(0,s.i);})) < 0; }) ); 145 | } 146 | 147 | static void aligned_store(void) { 148 | uint32_t v = 0x10100; 149 | struct { 150 | unsigned u : 16, u2 : 15; 151 | } s = {0}; 152 | ASSERT(1, ((s.u = v) == 0x100)); 153 | ASSERT(1, (s.u == 0x100)); 154 | ASSERT(1, (s.u2 == 0)); 155 | } 156 | 157 | int main(void) { 158 | bitextract(); 159 | struct_init(); 160 | union_init(); 161 | assign_expr(); 162 | large_field(); 163 | signed_large_field(); 164 | uninit_global(); 165 | operand_promotion(); 166 | aligned_store(); 167 | 168 | printf("OK\n"); 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /test/bitint.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | SASSERT(sizeof(_BitInt(7)) == 1); 4 | SASSERT(sizeof(_BitInt(15)) == 2); 5 | SASSERT(sizeof(_BitInt(31)) == 4); 6 | SASSERT(sizeof(_BitInt(63)) == 8); 7 | 8 | SASSERT(_Alignof(_BitInt(7)) == 1); 9 | SASSERT(_Alignof(_BitInt(15)) == 2); 10 | SASSERT(_Alignof(_BitInt(31)) == 4); 11 | SASSERT(_Alignof(_BitInt(63)) == 8); 12 | 13 | SASSERT(sizeof(_BitInt(7)[17]) == 17); 14 | SASSERT(sizeof(_BitInt(15)[17]) == 34); 15 | SASSERT(sizeof(_BitInt(31)[17]) == 68); 16 | SASSERT(sizeof(_BitInt(63)[17]) == 136); 17 | 18 | #define CHK_USUAL_CONV(A, B, C) \ 19 | SASSERT(_Generic((A)0+(B)0, C:1)) 20 | 21 | CHK_USUAL_CONV(_BitInt(2) signed, _BitInt(1) unsigned, _BitInt(2)); 22 | CHK_USUAL_CONV(_BitInt(2), unsigned _BitInt(2), unsigned _BitInt(2)); 23 | 24 | CHK_USUAL_CONV(_BitInt(2), _Bool, int); 25 | CHK_USUAL_CONV(unsigned _BitInt(1), _Bool, int); 26 | 27 | #define W (__SIZEOF_INT__ * 8) 28 | 29 | CHK_USUAL_CONV(signed _BitInt(W-1), signed, signed); 30 | CHK_USUAL_CONV(signed _BitInt(W-1), unsigned, unsigned); 31 | CHK_USUAL_CONV(unsigned _BitInt(W-1), signed, signed); 32 | CHK_USUAL_CONV(unsigned _BitInt(W-1), unsigned, unsigned); 33 | 34 | CHK_USUAL_CONV(signed _BitInt(W), signed, signed); 35 | CHK_USUAL_CONV(signed _BitInt(W), unsigned, unsigned); 36 | CHK_USUAL_CONV(unsigned _BitInt(W), signed, unsigned); 37 | CHK_USUAL_CONV(unsigned _BitInt(W), unsigned, unsigned); 38 | 39 | CHK_USUAL_CONV(signed _BitInt(W+1), signed, signed _BitInt(W+1)); 40 | CHK_USUAL_CONV(signed _BitInt(W+1), unsigned, signed _BitInt(W+1)); 41 | CHK_USUAL_CONV(unsigned _BitInt(W+1), signed, unsigned _BitInt(W+1)); 42 | CHK_USUAL_CONV(unsigned _BitInt(W+1), unsigned, unsigned _BitInt(W+1)); 43 | 44 | void bitint_bitfiled(void) { 45 | ASSERT(1, ({struct { _BitInt(W-1)i:W-1;} s; _Generic(-s.i, _BitInt(W-1):1);})); 46 | ASSERT(1, ({struct { _BitInt( W )i:W-1;} s; _Generic(-s.i, _BitInt( W ):1);})); 47 | ASSERT(1, ({struct { _BitInt(W+1)i:W-1;} s; _Generic(-s.i, _BitInt(W+1):1);})); 48 | 49 | ASSERT(1, ({struct { _BitInt(W-1)i:W-1;} s; _Generic(0+s.i, int:1);})); 50 | ASSERT(1, ({struct { _BitInt( W )i:W-1;} s; _Generic(0+s.i, int:1);})); 51 | ASSERT(1, ({struct { _BitInt(W+1)i:W-1;} s; _Generic(0+s.i, _BitInt(W+1):1);})); 52 | } 53 | 54 | SASSERT(_Generic(0wb, _BitInt(2):1)); 55 | SASSERT(_Generic(0uwb, _BitInt(1) unsigned:1)); 56 | SASSERT(_Generic(0b11wb, _BitInt(3):1)); 57 | SASSERT(_Generic(0b10wbu, _BitInt(2) unsigned:1)); 58 | SASSERT(_Generic(012WBu, _BitInt(4) unsigned:1)); 59 | SASSERT(_Generic(0x0B2fUwb, _BitInt(12) unsigned:1)); 60 | SASSERT(_Generic(0xFFFF'FFFF'FFFF'FFFFwb, _BitInt(65):1)); 61 | SASSERT(_Generic(8989898989898989898989898989898989898WB, _BitInt(124):1)); 62 | SASSERT(_Generic(077777777777776666666666666666666667777777777uwb, _BitInt(132)unsigned:1)); 63 | SASSERT(_Generic(0x7fffffffffffffffEEEEEEEEABCabcfeeeeeeeFFFFFFFFFF555555wb, _BitInt(216):1)); 64 | 65 | typedef struct { 66 | _BitInt(256) a : 3, b : 6, c : 7; 67 | } B; 68 | 69 | constexpr B b_c = {-1, 2, -3}; 70 | B b_s = {1, -2, 3}; 71 | 72 | void bitint_bitfiled_var(int i1, int i2, int i3) { 73 | B b_r = {i1, i2, i3}; 74 | ASSERT(1, b_c.a == b_r.c); 75 | ASSERT(1, b_c.b == b_r.b); 76 | ASSERT(1, b_c.c == b_r.a); 77 | 78 | ASSERT(1, b_s.a > b_r.c); 79 | ASSERT(1, b_s.b != b_r.b); 80 | ASSERT(0, b_s.c < b_r.a); 81 | 82 | ASSERT(-2, b_r.a *= b_s.b); 83 | ASSERT(1, b_s.a++); 84 | ASSERT(4, b_r.b *= b_s.a); 85 | ASSERT(-2, --b_r.c); 86 | ASSERT(-3, b_s.b += ({ b_c.c % b_r.c; })); 87 | ASSERT(-52, ({ b_r.b * b_s.b; }) - ( ({ b_s.c -= b_r.a; }) << 88 | ({ b_s.a *= -2; 89 | b_r.c ^ ~b_c.b; }) ) ); 90 | 91 | ASSERT(-2, b_r.a); 92 | ASSERT(4, b_r.b); 93 | ASSERT(-2, b_r.c); 94 | 95 | ASSERT(-4, b_s.a); 96 | ASSERT(-3, b_s.b); 97 | ASSERT(5, b_s.c); 98 | } 99 | 100 | int main() { 101 | bitint_bitfiled(); 102 | bitint_bitfiled_var(-3, 2, -1); 103 | 104 | printf("OK\n"); 105 | } 106 | -------------------------------------------------------------------------------- /test/builtin.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(1, __builtin_types_compatible_p(int, int)); 5 | ASSERT(1, __builtin_types_compatible_p(double, double)); 6 | ASSERT(0, __builtin_types_compatible_p(int, long)); 7 | ASSERT(0, __builtin_types_compatible_p(long, float)); 8 | ASSERT(1, __builtin_types_compatible_p(int *, int *)); 9 | ASSERT(0, __builtin_types_compatible_p(short *, int *)); 10 | ASSERT(0, __builtin_types_compatible_p(int **, int *)); 11 | ASSERT(1, __builtin_types_compatible_p(const int, int)); 12 | ASSERT(0, __builtin_types_compatible_p(unsigned, int)); 13 | ASSERT(1, __builtin_types_compatible_p(signed, int)); 14 | ASSERT(0, __builtin_types_compatible_p(struct {int a;}, struct {int a;})); 15 | 16 | ASSERT(1, __builtin_types_compatible_p(int (*)(void), int (*)(void))); 17 | ASSERT(1, __builtin_types_compatible_p(void (*)(int), void (*)(int))); 18 | ASSERT(1, __builtin_types_compatible_p(void (*)(int, double), void (*)(int, double))); 19 | ASSERT(1, __builtin_types_compatible_p(int (*)(float, double), int (*)(float, double))); 20 | ASSERT(0, __builtin_types_compatible_p(int (*)(float, double), int)); 21 | ASSERT(0, __builtin_types_compatible_p(int (*)(float, double), int (*)(float))); 22 | ASSERT(0, __builtin_types_compatible_p(int (*)(float, double), int (*)(float, double, int))); 23 | ASSERT(1, __builtin_types_compatible_p(double (*)(...), double (*)(...))); 24 | ASSERT(0, __builtin_types_compatible_p(double (*)(...), double (*)(void))); 25 | 26 | ASSERT(1, ({ typedef struct {int a;} T; __builtin_types_compatible_p(T, T); })); 27 | ASSERT(1, ({ typedef struct {int a;} T; __builtin_types_compatible_p(T, const T); })); 28 | 29 | ASSERT(1, ({ struct {int a; int b;} x; __builtin_types_compatible_p(typeof(x.a), typeof(x.b)); })); 30 | 31 | printf("OK\n"); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /test/builtin2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #ifndef __has_builtin 4 | #error 5 | #endif 6 | 7 | #if !__has_builtin(__builtin_offsetof) 8 | #error 9 | #endif 10 | 11 | struct ofs_S1 { 12 | char c; 13 | struct { 14 | struct { 15 | struct { 16 | struct { 17 | char k[7]; 18 | } n; 19 | char z; 20 | }; 21 | } m[7][7]; 22 | }; 23 | }; 24 | SASSERT(__builtin_offsetof(struct ofs_S1, m[1][2].n.k[3]) == 76); 25 | 26 | int va_expr_in_arg(int i, ...) { 27 | __builtin_va_list ap, ap2; 28 | __builtin_va_start(ap, (i += 7, i)); 29 | __builtin_va_copy(ap2, ap); 30 | ASSERT(1, !memcmp(ap,ap2,sizeof(__builtin_va_list))); 31 | #ifdef __slimcc__ 32 | __builtin_va_start(ap); 33 | #endif 34 | __builtin_va_end((i += 13, ap)); 35 | return i; 36 | } 37 | 38 | int va_in_comma(int i, ...) { 39 | __builtin_va_list ap, ap2; 40 | return __builtin_va_start(ap, i), 41 | __builtin_va_copy(ap2, ap), 42 | i = __builtin_va_arg(ap2, int), 43 | __builtin_va_end(ap2), 44 | i; 45 | } 46 | 47 | static int garr[2]; 48 | static void va_fn1(void) { garr[0] = 111; } 49 | static void va_fn2(void) { garr[1] = 222; } 50 | static void va_fn0(int cnt, ...) { 51 | va_list ap; 52 | va_start(ap, cnt); 53 | for(int i = 0; i < cnt; i++) 54 | va_arg(ap, void(*)(void))(); 55 | va_end(ap); 56 | } 57 | 58 | SASSERT(__builtin_constant_p(1 ? 0 : 0)); 59 | int g; 60 | SASSERT(!__builtin_constant_p(g)); 61 | 62 | static __auto_type builtin_constant_p_test = __builtin_constant_p(0); 63 | SASSERT(_Generic(&builtin_constant_p_test, int *:1)); 64 | 65 | static __auto_type builtin_expect_test = __builtin_expect(1.0f,1.0); 66 | SASSERT(_Generic(&builtin_expect_test, long *:1)); 67 | 68 | int main(void) { 69 | ASSERT(30, va_expr_in_arg(17)); 70 | ASSERT(33, va_in_comma(0,33)); 71 | 72 | va_fn0(2, &va_fn1, &va_fn2); 73 | ASSERT(111, garr[0]); 74 | ASSERT(222, garr[1]); 75 | 76 | #define runtime_ofs(x,y,z) __builtin_offsetof(struct ofs_S1, m[x][y].n.k[z]) 77 | ASSERT(324, ({int x = 5, y = 3; runtime_ofs(x,5,y); })); 78 | ASSERT(100, ({int x = 1, y = 5, z = 3; runtime_ofs(x,y,z); })); 79 | ASSERT(222, ({int y = 6; runtime_ofs(3,y,5); })); 80 | 81 | printf("OK\n"); 82 | } 83 | -------------------------------------------------------------------------------- /test/builtin_return_address.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | void *rtn_addr(int i) { 4 | switch (i) { 5 | case 2: 6 | return __builtin_return_address(2); 7 | case 1: 8 | ASSERT(1, rtn_addr(2) == __builtin_return_address(1)); 9 | return __builtin_return_address(1); 10 | } 11 | ASSERT(1, __builtin_return_address(0) == rtn_addr(1)); 12 | 13 | __auto_type builtin_return_address_test = __builtin_return_address(0); 14 | SASSERT(_Generic(&builtin_return_address_test, void **:1)); 15 | } 16 | 17 | int main(void) { 18 | rtn_addr(0); 19 | 20 | printf("OK\n"); 21 | } 22 | -------------------------------------------------------------------------------- /test/cast.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | EASSERT(131585, (int)8590066177); 5 | EASSERT(513, (short)8590066177); 6 | EASSERT(1, (char)8590066177); 7 | EASSERT(1, (long)1); 8 | ASSERT(0, (long)&*(int *)0); 9 | ASSERT(513, ({ int x=512; *(char *)&x=1; x; })); 10 | ASSERT(5, ({ int x=5; long y=(long)&x; *(int*)y; })); 11 | 12 | (void)1; 13 | 14 | EASSERT(-1, (char)255); 15 | EASSERT(-1, (signed char)255); 16 | EASSERT(255, (unsigned char)255); 17 | EASSERT(-1, (short)65535); 18 | EASSERT(65535, (unsigned short)65535); 19 | EASSERT(-1, (int)0xffffffff); 20 | EASSERT(0xffffffff, (unsigned)0xffffffff); 21 | 22 | EASSERT(1, -1<1); 23 | EASSERT(0, -1<(unsigned)1); 24 | EASSERT(254, (char)127+(char)127); 25 | EASSERT(65534, (short)32767+(short)32767); 26 | EASSERT(-1, -1>>1); 27 | EASSERT(-1, (unsigned long)-1); 28 | EASSERT(2147483647, ((unsigned)-1)>>1); 29 | EASSERT(-50, (-100)/2); 30 | EASSERT(2147483598, ((unsigned)-100)/2); 31 | EASSERT(9223372036854775758, ((unsigned long)-100)/2); 32 | EASSERT(0, ((long)-1)/(unsigned)100); 33 | EASSERT(-2, (-100)%7); 34 | EASSERT(2, ((unsigned)-100)%7); 35 | EASSERT(6, ((unsigned long)-100)%9); 36 | 37 | EASSERT(65535, (int)(unsigned short)65535); 38 | ASSERT(65535, ({ unsigned short x = 65535; x; })); 39 | ASSERT(65535, ({ unsigned short x = 65535; (int)x; })); 40 | 41 | ASSERT(-1, ({ typedef short T; T x = 65535; (int)x; })); 42 | ASSERT(65535, ({ typedef unsigned short T; T x = 65535; (int)x; })); 43 | 44 | EASSERT(0, (_Bool)0.0); 45 | EASSERT(1, (_Bool)0.1); 46 | EASSERT(3, (char)3.0); 47 | EASSERT(1000, (short)1000.3); 48 | EASSERT(3, (int)3.99); 49 | EASSERT(2000000000000000, (long)2e15); 50 | EASSERT(3, (float)3.5); 51 | EASSERT(5, (double)(float)5.5); 52 | EASSERT(3, (float)3); 53 | EASSERT(3, (double)3); 54 | EASSERT(3, (float)3L); 55 | EASSERT(3, (double)3L); 56 | 57 | printf("OK\n"); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /test/commonsym.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int x; 4 | int x = 5; 5 | int y = 7; 6 | int y; 7 | int common_ext1; 8 | static int common_local; 9 | 10 | int main() { 11 | ASSERT(5, x); 12 | ASSERT(7, y); 13 | ASSERT(0, common_ext1); 14 | 15 | printf("OK\n"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/compat.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | _Noreturn noreturn_fn(int restrict x) { 4 | exit(0); 5 | } 6 | 7 | void funcy_type(int arg[restrict static 3]) {} 8 | 9 | int main() { 10 | { volatile x; } 11 | { int volatile x; } 12 | { volatile int x; } 13 | { volatile int volatile volatile x; } 14 | { int volatile * volatile volatile x; } 15 | // { auto ** restrict __restrict __restrict__ const volatile *x; } 16 | 17 | printf("OK\n"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/complit.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | typedef struct Tree { 4 | int val; 5 | struct Tree *lhs; 6 | struct Tree *rhs; 7 | } Tree; 8 | 9 | Tree *tree = &(Tree){ 10 | 1, 11 | &(Tree){ 12 | 2, 13 | &(Tree){ 3, 0, 0 }, 14 | &(Tree){ 4, 0, 0 } 15 | }, 16 | 0 17 | }; 18 | 19 | int main() { 20 | ASSERT(1, (int){1}); 21 | ASSERT(2, ((int[]){0,1,2})[2]); 22 | ASSERT('a', ((struct {char a; int b;}){'a', 3}).a); 23 | ASSERT(3, ({ int x=3; (int){x}; })); 24 | (int){3} = 5; 25 | 26 | ASSERT(1, tree->val); 27 | ASSERT(2, tree->lhs->val); 28 | ASSERT(3, tree->lhs->lhs->val); 29 | ASSERT(4, tree->lhs->rhs->val); 30 | 31 | printf("OK\n"); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /test/complit2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | static int arr[4] = {1,2,3,4}; 4 | 5 | int sum(int a, int b){ 6 | return a + b; 7 | } 8 | int* getarr(int idx) { 9 | return &arr[idx]; 10 | } 11 | 12 | struct s { 13 | int i,j,k; 14 | } s0 = {1,2,3}; 15 | 16 | int static_local() { 17 | struct S { 18 | int i; 19 | int *p; 20 | }; 21 | static struct S s = {(int){}, (int*){&arr[1]}}; 22 | return (s.p++)[s.i++]; 23 | } 24 | 25 | int static_complit_counter(void) { 26 | int *p = &(static int){}; 27 | return (*p)++; 28 | } 29 | 30 | int static_complit_counter2(void) { 31 | static int *p = &(static int){3}; 32 | return (*p)++; 33 | } 34 | 35 | void constexpr_complit_adr(int recur, const int *local_p, const int *static_p) { 36 | if (recur >= 3) 37 | return; 38 | 39 | const int *local_vp = &(constexpr int){(int){55}}; 40 | const int *static_vp = &(static constexpr int){(int){66}}; 41 | 42 | ASSERT(55, *local_vp); 43 | ASSERT(66, *static_vp); 44 | 45 | if (recur) { 46 | ASSERT(55, *local_p); 47 | ASSERT(66, *static_p); 48 | 49 | ASSERT(1, local_vp != local_p ); 50 | ASSERT(1, static_vp == static_p ); 51 | } 52 | constexpr_complit_adr(recur + 1, local_vp, static_vp); 53 | } 54 | 55 | int main() { 56 | ASSERT(1, ({ (int[2]){1,2}[0]; })); 57 | ASSERT(2, ({ (int[2]){1,2}[1]; })); 58 | 59 | ASSERT(1, ({ (int*){(void*)&arr}[0]; })); 60 | ASSERT(3, ({ (int*){&arr[1]}[1]; })); 61 | 62 | ASSERT(4, ({ (int(*)[2]){(void*)&arr}[1][1]; })); 63 | 64 | ASSERT(0, ({ (struct s){.j=2}.i; })); 65 | ASSERT(2, ({ (struct s){.j=2}.j; })); 66 | ASSERT(0, ({ (struct s){.j=2}.k; })); 67 | 68 | ASSERT(3, ({ (struct s*){&s0}->k; })); 69 | 70 | ASSERT(3, ({ int a=(int){3}++; a; })); 71 | 72 | ASSERT(1, ({ int *p=(int*){&arr[0]}++; *p; })); 73 | 74 | ASSERT(10, ({ (int(*)(int,int)){sum}(7,3); })); 75 | 76 | ASSERT(3, ({ (int*(*)(int)){&getarr}(1)[1]; })); 77 | 78 | ASSERT(2, static_local()); 79 | ASSERT(4, static_local()); 80 | 81 | ASSERT(0, static_complit_counter()); 82 | ASSERT(3, static_complit_counter2()); 83 | 84 | ASSERT(1, static_complit_counter()); 85 | ASSERT(4, static_complit_counter2()); 86 | 87 | constexpr_complit_adr(0, NULL, NULL); 88 | 89 | printf("OK\n"); 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /test/cond_decl.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | static int buf[128]; 4 | static int idx; 5 | static void inc(void *p) { buf[idx++] = *(int *)p; } 6 | #define CLN [[gnu::cleanup(inc)]] 7 | 8 | static int if_cond(int i) { 9 | if (CLN int a = i + 1, b = a + 2; CLN int c = b - 10) 10 | return a + c; 11 | else if (int c CLN = -i, d CLN = c + 3; c += 7) 12 | ; 13 | else if (int d CLN = c) 14 | ; 15 | else 16 | return a + b + (c -= 11) + (d += 5); 17 | return 99; 18 | } 19 | 20 | static int sw_cond(int i, int j) { 21 | switch (int z = i * j) { 22 | case 0: 23 | return 99; 24 | case 24: 25 | return 24; 26 | } 27 | switch (char(*p)[i][j]; sizeof(*p)) { 28 | case 0: 29 | return 99; 30 | case 21: 31 | return 21; 32 | } 33 | switch (char arr[i][j]; int j = sizeof(arr)) { 34 | case 0: 35 | return 99; 36 | case 25: 37 | return 25; 38 | } 39 | return 99; 40 | } 41 | 42 | static void w_cond(int i) { 43 | while (CLN int a = i--) { 44 | CLN int b = -i; 45 | } 46 | int z = 9; 47 | inc(&z); 48 | } 49 | static void f_cond(int i) { 50 | int z = 9; 51 | for (int a CLN = i--; CLN int c = i--; inc(&z)) { 52 | CLN int d = i--; 53 | } 54 | inc(&z); 55 | } 56 | 57 | int main(void) { 58 | { 59 | idx = 0; 60 | ASSERT(-4, if_cond(1)); 61 | int ans[] = {-6, 4, 2}; 62 | ASSERT(0, memcmp(&buf, &ans, sizeof(ans))); 63 | } 64 | { 65 | idx = 0; 66 | ASSERT(12, if_cond(7)); 67 | int ans[] = {5, -4, -11, 0, 10, 8}; 68 | ASSERT(0, memcmp(&buf, &ans, sizeof(ans))); 69 | } 70 | 71 | ASSERT(24, sw_cond(4, 6)); 72 | ASSERT(21, sw_cond(7, 3)); 73 | ASSERT(25, sw_cond(5, 5)); 74 | { 75 | idx = 0; 76 | w_cond(2); 77 | int ans[] = {-1, 2, 0, 1, 0, 9}; 78 | ASSERT(0, memcmp(&buf, &ans, sizeof(ans))); 79 | } 80 | { 81 | idx = 0; 82 | f_cond(5); 83 | int ans[] = {3, 9, 4, 1, 9, 2, 0, 5, 9}; 84 | ASSERT(0, memcmp(&buf, &ans, sizeof(ans))); 85 | } 86 | 87 | printf("OK\n"); 88 | } 89 | -------------------------------------------------------------------------------- /test/const.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | { const x; } 5 | { int const x; } 6 | { const int x; } 7 | { const int const const x; } 8 | ASSERT(5, ({ const x = 5; x; })); 9 | ASSERT(8, ({ const x = 8; int *const y=&x; *y; })); 10 | ASSERT(6, ({ const x = 6; *(const * const)&x; })); 11 | 12 | printf("OK\n"); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/constexpr.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | float g40 = 1.5; 4 | double g41 = 0.0 ? 55 : (0, 1 + 1 * 5.0 / 2 * (double)2 * (int)2.0); 5 | 6 | int main() { 7 | ASSERT(10, ({ enum { ten=1+2+3+4 }; ten; })); 8 | ASSERT(1, ({ int i=0; switch(3) { case 5-2+0*3: i++; } i; })); 9 | EASSERT(8, sizeof(int[1+1])); 10 | EASSERT(6, 8-2); 11 | EASSERT(6, 2*3); 12 | EASSERT(3, 12/4); 13 | EASSERT(2, 12%10); 14 | EASSERT(0b100, 0b110&0b101); 15 | EASSERT(0b111, 0b110|0b101); 16 | EASSERT(0b110, 0b111^0b001); 17 | EASSERT(4, 1<<2); 18 | EASSERT(2, 4>>1); 19 | EASSERT(2, (1==1)+1); 20 | EASSERT(1, (1!=1)+1); 21 | EASSERT(1, (1<1)+1); 22 | EASSERT(2, (1<=1)+1); 23 | EASSERT(2, 1?2:3); 24 | EASSERT(3, 0?2:3); 25 | EASSERT(3, (1,3)); 26 | EASSERT(2, !0+1); 27 | EASSERT(1, !1+1); 28 | EASSERT(2, ~-3); 29 | EASSERT(2, (5||6)+1); 30 | EASSERT(1, (0||0)+1); 31 | EASSERT(2, (1&&1)+1); 32 | EASSERT(1, (1&&0)+1); 33 | EASSERT(3, (int)3); 34 | EASSERT(15, (char)0xffffff0f); 35 | EASSERT(0x10f, (short)0xffff010f); 36 | EASSERT(4, (int)0xfffffffffff+5); 37 | EASSERT(8, (int*)0+2); 38 | EASSERT(12, (int*)16-1); 39 | EASSERT(3, (int*)16-(int*)4); 40 | 41 | EASSERT(4, (-1>>31)+5); 42 | EASSERT(255, (unsigned char)0xffffffff); 43 | EASSERT(0x800f, (unsigned short)0xffff800f); 44 | EASSERT(1, (unsigned int)0xfffffffffff>>31); 45 | EASSERT(1, (long)-1/((long)1<<62)+1); 46 | EASSERT(4, (unsigned long)-1/((long)1<<62)+1); 47 | EASSERT(1, (unsigned)1<-1); 48 | EASSERT(1, (unsigned)1<=-1); 49 | 50 | ASSERT(1, g40==1.5); 51 | ASSERT(1, g41==11); 52 | 53 | printf("OK\n"); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /test/constexpr2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #if !1u - 1 > 0 4 | #error 5 | #endif 6 | 7 | extern int extarr[55]; 8 | int garr[11]; 9 | static int sgarr[33]; 10 | _Bool str_lit_bool_init = "abc" ? "foo" && "bar" : 0; 11 | 12 | void array_cast_to_bool(int j) { 13 | static int slarr[5]; 14 | int larr[7]; 15 | char vla[j]; 16 | 17 | DASSERT((_Bool)extarr && (_Bool)garr && (_Bool)sgarr && 18 | (_Bool)slarr && (_Bool)larr && (_Bool)vla); 19 | ASSERT(1, str_lit_bool_init); 20 | } 21 | int extarr[55]; 22 | 23 | extern int ext_var; 24 | extern void ext_fn(void); 25 | SASSERT(2 == ((_Bool)&ext_var + (_Bool)ext_fn)); 26 | #ifdef NOTGCC 27 | SASSERT(3 == ((_Bool)(long long)&ext_var + (_Bool)(_Bool)ext_fn + (_Bool)(long long)(_Bool)ext_fn)); 28 | #endif 29 | 30 | struct S2 { 31 | int i,j; 32 | }; 33 | struct S3 { 34 | char c; 35 | struct S2 arr[2]; 36 | }; 37 | struct S3 s3 = { .arr = {3, 7, 9, 11} }; 38 | struct S2 *s2p = {(struct S2 *)((struct S2 const *)&(((struct S3 const *)&s3))->arr + 1)}; 39 | 40 | int static_ref_excess_cast() { 41 | return s2p->j; 42 | } 43 | 44 | int main(void) { 45 | array_cast_to_bool(11); 46 | 47 | DASSERT((_Bool)0.1f == 1); 48 | DASSERT((_Bool)2 == 1); 49 | DASSERT((_Bool)(0.0f + 0.1f) == 1); 50 | DASSERT((_Bool)(2 * 3) == 1); 51 | 52 | DASSERT( -1 < 0 ); 53 | 54 | DASSERT( 3U << 31 >> 31 == 1); 55 | DASSERT( 1 << 31 >> 31 == -1); 56 | 57 | DASSERT(0.2 > 0.1); 58 | DASSERT(0.1 < 0.2); 59 | DASSERT(0.2 != 0.1); 60 | DASSERT(!(0.2 <= 0.1)); 61 | DASSERT(!(0.1 >= 0.2)); 62 | DASSERT(!(0.1 == 0.2)); 63 | DASSERT(!!0.1); 64 | 65 | DASSERT(0.1 ? 1 : 0); 66 | 67 | DASSERT((long)-0x1U == 4294967295); 68 | DASSERT((long)-0x1 == -1); 69 | DASSERT((long)-0xFFFFFFF0U == 16); 70 | DASSERT((long)-0xFFFFFFF0 == 16); 71 | 72 | DASSERT((long)~0x1U == 4294967294); 73 | DASSERT((long)~0x1 == -2); 74 | DASSERT((long)~0xFFFFFFF0U == 15); 75 | DASSERT((long)~0xFFFFFFF0 == 15); 76 | 77 | DASSERT((long)(0x80000000U << 1) == 0); 78 | DASSERT((long)(0xFFFFFFFFU + 1) == 0); 79 | DASSERT((long)(0U - 1) == 0xFFFFFFFFU); 80 | DASSERT((long)(25989 * 2972383464U) == 4287027336); 81 | 82 | static_assert(INT32_MIN / -1 == INT32_MIN); 83 | static_assert(INT64_MIN / -1 == INT64_MIN); 84 | static_assert(INT32_MIN % -1 == 0); 85 | static_assert(INT64_MIN % -1 == 0); 86 | 87 | DASSERT(13835058055282163712.0 == (double)13835058055282163712ULL); 88 | DASSERT(13835058055282163712.0f == (float) 13835058055282163712ULL); 89 | DASSERT(13835058055282163712ULL == (unsigned long long) 13835058055282163712.0f); 90 | DASSERT(13835058055282163712ULL == (unsigned long long) 13835058055282163712.0); 91 | 92 | DASSERT(13835058055282163711ULL == (unsigned long long) 13835058055282163711.0L); 93 | DASSERT(13835058055282163711.0L == (long double) 13835058055282163711ULL); 94 | 95 | DASSERT( 16777217.0 != (float)16777217.0 ); 96 | DASSERT( 9007199254740993.0L != (double)9007199254740993.0L || sizeof(double) == sizeof(long double) ); 97 | 98 | #ifdef NOTCLANG 99 | DASSERT( 127 == (unsigned char)511.0 >> 1 ); 100 | #endif 101 | DASSERT( (long long)(0.1f * 1e12f) == 99999997952LL ); 102 | 103 | ASSERT(1, ({ int i = 2; char arr[ (i++,3) ]; i == sizeof arr; }) ); 104 | 105 | { 106 | char (*arr_ptr)[UINT32_MAX + 1ULL]; 107 | DASSERT( sizeof(*arr_ptr) == (UINT32_MAX + 1ULL)); 108 | } 109 | 110 | { 111 | char arr[3]; 112 | DASSERT(8 == sizeof((0 ? arr:arr))); 113 | DASSERT(8 == sizeof((0 ? 0:arr))); 114 | DASSERT(8 == sizeof((0 ? arr:0))); 115 | DASSERT(8 == sizeof(({arr;}))); 116 | 117 | DASSERT(8 == sizeof((0,arr))); 118 | DASSERT(3 == sizeof( (typeof(arr)){0} )); 119 | } 120 | { 121 | struct S { struct { char c, c2; } s[13]; }; 122 | DASSERT(13 == (intptr_t)&((struct S*)0)->s[6].c2); 123 | } 124 | 125 | ASSERT(11, static_ref_excess_cast()); 126 | 127 | printf("OK\n"); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/constexpr_var.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | 4 | static constexpr float f = 11.0; 5 | constexpr long double ld = 22.0; 6 | 7 | constexpr long len = 17; 8 | long double arr0[len]; 9 | 10 | union U {int i; float f;}; 11 | constexpr union U u1 = {.i = 0x40490fda}; 12 | constexpr union U u2 = u1; 13 | 14 | constexpr int *np1 = 0; 15 | constexpr int *np2 = {}; 16 | constexpr int *np3 = {0}; 17 | 18 | SASSERT(!np1); 19 | SASSERT(np2 == 0); 20 | SASSERT(np3 == NULL); 21 | 22 | void local_adr(int recur, const int *local_p, const int *static_p) { 23 | if (recur >= 3) 24 | return; 25 | 26 | constexpr int local_v = 55; 27 | static constexpr int static_v = 66; 28 | 29 | DASSERT(55 == local_v); 30 | DASSERT(66 == static_v); 31 | 32 | if (recur) { 33 | ASSERT(55, *local_p); 34 | ASSERT(66, *static_p); 35 | 36 | ASSERT(1, &local_v != local_p ); 37 | ASSERT(1, &static_v == static_p ); 38 | } 39 | local_adr(recur + 1, &local_v, &static_v); 40 | } 41 | 42 | int main() { 43 | DASSERT(ld == f * 2); 44 | DASSERT(sizeof(arr0) == len * sizeof(typeof(arr0[0]))); 45 | 46 | DASSERT(u1.f == 3.1415926f); 47 | 48 | local_adr(0,NULL,NULL); 49 | 50 | union U1 { int i; union { int j; union { int k; int m; }; }; }; 51 | constexpr union U1 u1 = {.m =77 }; 52 | DASSERT( u1.m == 77 ); 53 | 54 | struct S { 55 | char c; 56 | struct { 57 | float f; 58 | }a; 59 | struct { 60 | unsigned short w :6; 61 | short x :7; 62 | struct { 63 | long double d; 64 | }; 65 | bool b : 1; 66 | }; 67 | }; 68 | constexpr struct S s = { 11,22,33,-44,55,6}; 69 | 70 | DASSERT(s.c == 11); 71 | DASSERT(s.a.f == 22); 72 | DASSERT(s.w == 33); 73 | DASSERT(s.x == -44); 74 | DASSERT(s.d == 55); 75 | DASSERT(s.b == true); 76 | 77 | { 78 | struct S { int i; }; 79 | constexpr _Bool b = (0 && (((struct S*)0)->i)); 80 | } 81 | { 82 | constexpr int32_t x = -6L; 83 | constexpr uint64_t y = (uint64_t)x; 84 | static_assert((uint64_t)-6L == y); 85 | } 86 | { 87 | constexpr struct { char c[23]; } s = {0}; 88 | static_assert((s,1)); 89 | } 90 | 91 | for (constexpr int i = 0; i;) { 92 | static_assert(i == 0); 93 | } 94 | 95 | printf("OK\n"); 96 | return 0; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /test/constexpr_var_ext.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | constexpr int i = 7; 4 | constexpr int arr[i] = { 1,2,3,4,5,6,7 }; 5 | 6 | int main(void){ 7 | constexpr int j = arr[(i - 1)]; 8 | DASSERT( arr[(i - 6)*6] == j); 9 | 10 | constexpr int arr2[] = { 5,6,7,8,9 }; 11 | DASSERT( sizeof(arr2) == 5 * sizeof(int) ); 12 | DASSERT( arr[arr2[arr[0]]] == 7); 13 | 14 | DASSERT( (0, arr)[5] == (i == j ? arr2 : arr)[1] ); 15 | 16 | constexpr int arr3[3][2] = {1,2,3,4,5,6}; 17 | DASSERT( (arr3[0] + 1)[0] == 2); 18 | DASSERT( (arr3[0] + 0)[1] == 2); 19 | DASSERT( (arr3 + 2)[-1][0] == 3); 20 | DASSERT( (arr3[1] + 2)[-1] == 4); 21 | 22 | struct S1 { int i; }; 23 | constexpr struct S1 sa[4] = { 1,2,3,4 }; 24 | DASSERT( sa[2].i == 3); 25 | 26 | struct S2 { int i[16]; }; 27 | constexpr struct S2 sa2 = { 1,2,3,4 }; 28 | DASSERT( sa2.i[1] == 2); 29 | 30 | printf("OK\n"); 31 | } 32 | -------------------------------------------------------------------------------- /test/control.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | /* 4 | * This is a block comment. 5 | */ 6 | 7 | int main() { 8 | ASSERT(3, ({ int x; if (0) x=2; else x=3; x; })); 9 | ASSERT(3, ({ int x; if (1-1) x=2; else x=3; x; })); 10 | ASSERT(2, ({ int x; if (1) x=2; else x=3; x; })); 11 | ASSERT(2, ({ int x; if (2-1) x=2; else x=3; x; })); 12 | 13 | ASSERT(55, ({ int i=0; int j=0; for (i=0; i<=10; i=i+1) j=i+j; j; })); 14 | 15 | ASSERT(10, ({ int i=0; while(i<10) i=i+1; i; })); 16 | 17 | ASSERT(3, ({ 1; {2;} 3; })); 18 | ASSERT(5, ({ ;;; 5; })); 19 | 20 | ASSERT(10, ({ int i=0; while(i<10) i=i+1; i; })); 21 | ASSERT(55, ({ int i=0; int j=0; while(i<=10) {j=i+j; i=i+1;} j; })); 22 | 23 | ASSERT(3, (1,2,3)); 24 | // ASSERT(5, ({ int i=2, j=3; (i=5,j)=6; i; })); 25 | // ASSERT(6, ({ int i=2, j=3; (i=5,j)=6; j; })); 26 | 27 | ASSERT(55, ({ int j=0; for (int i=0; i<=10; i=i+1) j=j+i; j; })); 28 | ASSERT(3, ({ int i=3; int j=0; for (int i=0; i<=10; i=i+1) j=j+i; i; })); 29 | 30 | EASSERT(1, 0||1); 31 | EASSERT(1, 0||(2-2)||5); 32 | EASSERT(0, 0||0); 33 | EASSERT(0, 0||(2-2)); 34 | 35 | EASSERT(0, 0&&1); 36 | EASSERT(0, (2-2)&&5); 37 | EASSERT(1, 1&&5); 38 | 39 | ASSERT(3, ({ int i=0; goto a; a: i++; b: i++; c: i++; i; })); 40 | ASSERT(2, ({ int i=0; goto e; d: i++; e: i++; f: i++; i; })); 41 | ASSERT(1, ({ int i=0; goto i; g: i++; h: i++; i: i++; i; })); 42 | 43 | ASSERT(1, ({ typedef int foo; goto foo; foo:; 1; })); 44 | 45 | ASSERT(3, ({ int i=0; for(;i<10;i++) { if (i == 3) break; } i; })); 46 | ASSERT(4, ({ int i=0; while (1) { if (i++ == 3) break; } i; })); 47 | ASSERT(3, ({ int i=0; for(;i<10;i++) { for (;;) break; if (i == 3) break; } i; })); 48 | ASSERT(4, ({ int i=0; while (1) { while(1) break; if (i++ == 3) break; } i; })); 49 | 50 | ASSERT(10, ({ int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } i; })); 51 | ASSERT(6, ({ int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } j; })); 52 | ASSERT(10, ({ int i=0; int j=0; for(;!i;) { for (;j!=10;j++) continue; break; } j; })); 53 | ASSERT(11, ({ int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } i; })); 54 | ASSERT(5, ({ int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } j; })); 55 | ASSERT(11, ({ int i=0; int j=0; while(!i) { while (j++!=10) continue; break; } j; })); 56 | 57 | ASSERT(5, ({ int i=0; switch(0) { case 0:i=5;break; case 1:i=6;break; case 2:i=7;break; } i; })); 58 | ASSERT(6, ({ int i=0; switch(1) { case 0:i=5;break; case 1:i=6;break; case 2:i=7;break; } i; })); 59 | ASSERT(7, ({ int i=0; switch(2) { case 0:i=5;break; case 1:i=6;break; case 2:i=7;break; } i; })); 60 | ASSERT(0, ({ int i=0; switch(3) { case 0:i=5;break; case 1:i=6;break; case 2:i=7;break; } i; })); 61 | ASSERT(5, ({ int i=0; switch(0) { case 0:i=5;break; default:i=7; } i; })); 62 | ASSERT(7, ({ int i=0; switch(1) { case 0:i=5;break; default:i=7; } i; })); 63 | ASSERT(2, ({ int i=0; switch(1) { case 0: 0; case 1: 0; case 2: 0; i=2; } i; })); 64 | ASSERT(0, ({ int i=0; switch(3) { case 0: 0; case 1: 0; case 2: 0; i=2; } i; })); 65 | 66 | ASSERT(3, ({ int i=0; switch(-1) { case 0xffffffff: i=3; break; } i; })); 67 | 68 | ASSERT(7, ({ int i=0; int j=0; do { j++; } while (i++ < 6); j; })); 69 | ASSERT(4, ({ int i=0; int j=0; int k=0; do { if (++j > 3) break; continue; k++; } while (1); j; })); 70 | 71 | EASSERT(0, 0.0 && 0.0); 72 | EASSERT(0, 0.0 && 0.1); 73 | EASSERT(0, 0.3 && 0.0); 74 | EASSERT(1, 0.3 && 0.5); 75 | EASSERT(0, 0.0 || 0.0); 76 | EASSERT(1, 0.0 || 0.1); 77 | EASSERT(1, 0.3 || 0.0); 78 | EASSERT(1, 0.3 || 0.5); 79 | ASSERT(5, ({ int x; if (0.0) x=3; else x=5; x; })); 80 | ASSERT(3, ({ int x; if (0.1) x=3; else x=5; x; })); 81 | ASSERT(5, ({ int x=5; if (0.0) x=3; x; })); 82 | ASSERT(3, ({ int x=5; if (0.1) x=3; x; })); 83 | ASSERT(10, ({ double i=10.0; int j=0; for (; i; i--, j++); j; })); 84 | ASSERT(10, ({ double i=10.0; int j=0; do j++; while(--i); j; })); 85 | 86 | ASSERT(2, ({ int i=0; switch(7) { case 0 ... 5: i=1; break; case 6 ... 20: i=2; break; } i; })); 87 | ASSERT(1, ({ int i=0; switch(7) { case 0 ... 7: i=1; break; case 8 ... 10: i=2; break; } i; })); 88 | ASSERT(1, ({ int i=0; switch(7) { case 0: i=1; break; case 7 ... 7: i=1; break; } i; })); 89 | 90 | ASSERT(3, ({ void *p = &&v11; int i=0; goto *p; v11:i++; v12:i++; v13:i++; i; })); 91 | ASSERT(2, ({ void *p = &&v22; int i=0; goto *p; v21:i++; v22:i++; v23:i++; i; })); 92 | ASSERT(1, ({ void *p = &&v33; int i=0; goto *p; v31:i++; v32:i++; v33:i++; i; })); 93 | 94 | ASSERT(3, ({ static void *p[]={&&v41,&&v42,&&v43}; int i=0; goto *p[0]; v41:i++; v42:i++; v43:i++; i; })); 95 | ASSERT(2, ({ static void *p[]={&&v52,&&v52,&&v53}; int i=0; goto *p[1]; v51:i++; v52:i++; v53:i++; i; })); 96 | ASSERT(1, ({ static void *p[]={&&v62,&&v62,&&v63}; int i=0; goto *p[2]; v61:i++; v62:i++; v63:i++; i; })); 97 | 98 | printf("OK\n"); 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /test/control2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | char c23_label(void) { 5 | 6 | { 7 | int i = 0; 8 | if (i != 0) 9 | lab3: 10 | i = 1; 11 | ASSERT(0, i); 12 | } 13 | 14 | switch (1) { 15 | default: 16 | case 2: 17 | } 18 | if (0) { 19 | { 20 | lab1: 21 | } 22 | { 23 | lab2: 24 | int j; 25 | } 26 | return 77; 27 | } 28 | goto lab1; 29 | } 30 | 31 | int label_in_secondary_block(int i) { 32 | if (i == 2) 33 | goto labl; 34 | if (i == 3) 35 | labl: 36 | return 1; 37 | return 0; 38 | } 39 | 40 | int main(void){ 41 | ASSERT(2, ({ uint32_t i=0; switch(i){case 0 ...0xFFFFFFFF: i=2;} i; })); 42 | ASSERT(2, ({ int32_t i=0; switch(i){case 0x80000000 ...0x7FFFFFFF: i=2;} i; })); 43 | ASSERT(2, ({ uint64_t i=0; switch(i){case 0 ...0xFFFFFFFFFFFFFFFF: i=2;} i; })); 44 | ASSERT(2, ({ int64_t i=0; switch(i){case 0x8000000000000000 ...0x7FFFFFFFFFFFFFFF: i=2;} i; })); 45 | 46 | ASSERT(2, ({ uint32_t i=0; switch(i){case 0 ...0x100000000: i=2;} i; })); 47 | ASSERT(2, ({ int32_t i=-1; switch(i){case -1 ...(int64_t)-1: i=2;} i; })); 48 | 49 | ASSERT(2, ({ int64_t i=0; switch(0x123456789){case 0x123456789: i=2;} i; })); 50 | 51 | ASSERT(0, label_in_secondary_block(1)); 52 | ASSERT(1, label_in_secondary_block(2)); 53 | ASSERT(1, label_in_secondary_block(3)); 54 | ASSERT(77, c23_label()); 55 | 56 | printf("OK\n"); 57 | } 58 | -------------------------------------------------------------------------------- /test/countof.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int vla(int i) { 4 | ASSERT(3, i); 5 | DASSERT(11 == _Countof(int[11][++i])); 6 | ASSERT(3, i); 7 | ASSERT(4, _Countof(int[++i][11])); 8 | ASSERT(4, i); 9 | 10 | int arr[11][i+20][33][i+40]; 11 | 12 | DASSERT(11 == _Countof arr); 13 | ASSERT(24, _Countof *arr); 14 | DASSERT(33 == _Countof **arr); 15 | ASSERT(44, _Countof ***arr); 16 | 17 | typedef int tarr[i++][33]; 18 | ASSERT(5, i); 19 | 20 | tarr A; 21 | ASSERT(4, _Countof A); 22 | DASSERT(33 == _Countof *A); 23 | 24 | ASSERT(4, _Countof(tarr)); 25 | 26 | extern int fn_not_to_be_called(int); 27 | DASSERT(30 == _Countof(int[30][fn_not_to_be_called(i = 90)])); 28 | 29 | return i; 30 | } 31 | 32 | int fn_to_be_called(int i) { 33 | return i * 7; 34 | } 35 | 36 | int main(void) { 37 | ASSERT(5, vla(3)); 38 | 39 | char str1[] = "foobar"; 40 | 41 | DASSERT(7 == _Countof str1); 42 | DASSERT(4 == _Countof "foo"); 43 | 44 | ASSERT(42, _Countof(int[fn_to_be_called(6)])); 45 | 46 | printf("OK\n"); 47 | } 48 | -------------------------------------------------------------------------------- /test/decl.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(1, ({ char x; sizeof(x); })); 5 | ASSERT(2, ({ short int x; sizeof(x); })); 6 | ASSERT(2, ({ int short x; sizeof(x); })); 7 | ASSERT(4, ({ int x; sizeof(x); })); 8 | ASSERT(8, ({ long int x; sizeof(x); })); 9 | ASSERT(8, ({ int long x; sizeof(x); })); 10 | 11 | ASSERT(8, ({ long long x; sizeof(x); })); 12 | 13 | ASSERT(0, ({ _Bool x=0; x; })); 14 | ASSERT(1, ({ _Bool x=1; x; })); 15 | ASSERT(1, ({ _Bool x=2; x; })); 16 | EASSERT(1, (_Bool)1); 17 | EASSERT(1, (_Bool)2); 18 | EASSERT(0, (_Bool)(char)256); 19 | 20 | printf("OK\n"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /test/decl2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define CAT(x) b##x 4 | int CAT(6_) = 7; 5 | int CAT(8µ) = 9; 6 | 7 | int fn(float), var1 = 7, fn2(void), var2 = 11; 8 | 9 | int tentative_var; 10 | int tentative_var; 11 | 12 | short incomplete_tentative_arr[]; 13 | 14 | extern int init_extern = 3; 15 | 16 | static inline int static_inline_fn(void); 17 | int (*static_inline_fn_ptr)(void) = static_inline_fn; 18 | 19 | int main(void) { 20 | { 21 | ASSERT(7, b6_); 22 | ASSERT(9, b8µ); 23 | } 24 | 25 | { 26 | ASSERT(7, var1); 27 | ASSERT(11, var2); 28 | ASSERT(13, fn(13.0f)); 29 | ASSERT(19, fn2()); 30 | } 31 | { 32 | char arr2[3] = {11, 22, 33}; 33 | ASSERT(33, (&arr2)[0][2]); 34 | ASSERT(22, (*&arr2)[1]); 35 | ASSERT(11, (**&arr2)); 36 | } 37 | 38 | ASSERT(0, tentative_var); 39 | 40 | ASSERT(0, incomplete_tentative_arr[0]); 41 | 42 | ASSERT(3, init_extern); 43 | 44 | ASSERT(127, static_inline_fn_ptr()); 45 | 46 | ASSERT(0, ({ struct S {}; sizeof(struct S);})); 47 | ASSERT(0, ({ union U {}; sizeof(union U);})); 48 | 49 | printf("OK\n"); 50 | } 51 | 52 | 53 | int fn(float f) { return f; } 54 | int fn2(void) { return 19; } 55 | static inline int static_inline_fn(void) { return 127; } 56 | -------------------------------------------------------------------------------- /test/defer.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | // Adapted from https://www.open-std.org/JTC1/SC22/WG14/www/docs/n3199.htm 4 | 5 | int n3199_ex2(void) { 6 | int r = 4; 7 | int* p = &r; 8 | defer { *p = 5; } 9 | return *p; 10 | } 11 | 12 | int n3199_ex5(void) { 13 | int r = 0; 14 | { 15 | defer { 16 | defer r *= 4; 17 | r *= 2; 18 | defer { 19 | r += 3; 20 | } 21 | } 22 | defer r += 1; 23 | } 24 | return r; 25 | } 26 | 27 | void n3199_ex4(void) { 28 | char buf[64] = "c"; 29 | { 30 | defer { 31 | snprintf(buf, 64, "%s meow", strdup(buf)); 32 | } 33 | if (1) 34 | defer snprintf(buf, 64, "%sat", strdup(buf)); 35 | snprintf(buf, 64, "%s says", strdup(buf)); 36 | } 37 | ASSERT(0, strcmp(buf, "cat says meow")); 38 | } 39 | 40 | int main () { 41 | ASSERT(4, n3199_ex2()); 42 | n3199_ex4(); 43 | ASSERT(20, n3199_ex5()); 44 | 45 | printf("OK\n"); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /test/digit_separator.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main(void) { 4 | 5 | #define CAT(A,B) A##B 6 | 7 | constexpr int i1 = CAT(0x3'5, 6); 8 | EASSERT(i1, 854); 9 | 10 | printf("OK\n"); 11 | } 12 | -------------------------------------------------------------------------------- /test/embed.c: -------------------------------------------------------------------------------- 1 | #ifndef __has_embed 2 | #error 3 | #endif 4 | 5 | #if !defined(__STDC_EMBED_NOT_FOUND__) || !defined(__STDC_EMBED_FOUND__) || !defined(__STDC_EMBED_EMPTY__) 6 | #error 7 | #endif 8 | 9 | #if __STDC_EMBED_NOT_FOUND__ != 0 || __STDC_EMBED_FOUND__ != 1 || __STDC_EMBED_EMPTY__ != 2 10 | #error 11 | #endif 12 | 13 | #if __has_embed("embed_???") != __STDC_EMBED_NOT_FOUND__ 14 | #error 15 | #endif 16 | 17 | #if __has_embed("embed_empty") != __STDC_EMBED_EMPTY__ 18 | #error 19 | #endif 20 | 21 | #if __has_embed("embed.c") != __STDC_EMBED_FOUND__ 22 | #error 23 | #endif 24 | 25 | #if __has_embed("embed.c" unsupported::directive(abc)) != __STDC_EMBED_NOT_FOUND__ 26 | #error 27 | #endif 28 | 29 | #if __has_embed("embed.c" limit(0)) != __STDC_EMBED_EMPTY__ 30 | #error 31 | #endif 32 | 33 | #include "test.h" 34 | 35 | 36 | const char sudoku_ref[] = { 37 | "1.3B.2.F.64EG5.." 38 | ".7A4.3E..C.B..68" 39 | ".9C2.1....75A..E" 40 | "E...9B....1DF74." 41 | "3C81...27.EG.6.." 42 | "...7.6.EA8......" 43 | "...F.93.B5..C.2." 44 | "....C4.8D.F19E5." 45 | "851..D9AFE.6BG7." 46 | ".....E5B.7.C.29." 47 | ".27...6....A.C.F" 48 | "6..DF.C.4.2...3." 49 | "..5.3G4...9...8." 50 | "9A.61.B.5GD.2FE3" 51 | "...8E..9..A.64G." 52 | "GD23.AF..4..51C." 53 | }; 54 | 55 | const char sudoku_full[] = { 56 | #embed "embed_sudoku" 57 | }; 58 | 59 | const char sudoku_limit[] = { 60 | #embed "embed_sudoku" limit(27) 61 | }; 62 | 63 | const char sudoku_lim_prepost[] = { 64 | #embed "embed_sudoku" suffix(, 'B', 'A', 'R', 0) limit(3) prefix('F', 'O', 'O',) 65 | }; 66 | 67 | const char sudoku_empty[] = { 68 | #embed "embed_empty" if_empty("empty") 69 | }; 70 | 71 | int main(void) { 72 | ASSERT(0, memcmp(sudoku_ref, sudoku_full, 256)); 73 | ASSERT(27, sizeof(sudoku_limit)); 74 | ASSERT(10, sizeof(sudoku_lim_prepost)); 75 | ASSERT(0, strcmp(sudoku_lim_prepost, "FOO1.3BAR")); 76 | ASSERT(0, strcmp(sudoku_empty, "empty")); 77 | 78 | printf("OK\n"); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /test/embed_empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuhsnn/slimcc/8a1d64256603696799beb76159e55ee26f77ec2c/test/embed_empty -------------------------------------------------------------------------------- /test/embed_sudoku: -------------------------------------------------------------------------------- 1 | 1.3B.2.F.64EG5...7A4.3E..C.B..68.9C2.1....75A..EE...9B....1DF74.3C81...27.EG.6.....7.6.EA8.........F.93.B5..C.2.....C4.8D.F19E5.851..D9AFE.6BG7......E5B.7.C.29..27...6....A.C.F6..DF.C.4.2...3...5.3G4...9...8.9A.61.B.5GD.2FE3...8E..9..A.64G.GD23.AF..4..51C. -------------------------------------------------------------------------------- /test/enum.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(0, ({ enum { zero, one, two }; zero; })); 5 | ASSERT(1, ({ enum { zero, one, two }; one; })); 6 | ASSERT(2, ({ enum { zero, one, two }; two; })); 7 | ASSERT(5, ({ enum { five=5, six, seven }; five; })); 8 | ASSERT(6, ({ enum { five=5, six, seven }; six; })); 9 | ASSERT(0, ({ enum { zero, five=5, three=3, four }; zero; })); 10 | ASSERT(5, ({ enum { zero, five=5, three=3, four }; five; })); 11 | ASSERT(3, ({ enum { zero, five=5, three=3, four }; three; })); 12 | ASSERT(4, ({ enum { zero, five=5, three=3, four }; four; })); 13 | ASSERT(4, ({ enum { zero, one, two } x; sizeof(x); })); 14 | ASSERT(4, ({ enum t { zero, one, two }; enum t y; sizeof(y); })); 15 | 16 | printf("OK\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /test/enum2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #if (__SIZEOF_INT__ != 4) 4 | #error 5 | #endif 6 | 7 | #if (__SIZEOF_LONG__ > 4) 8 | #define FIRST_64BIT_INT long 9 | #else 10 | #define FIRST_64BIT_INT long long 11 | #endif 12 | 13 | enum e0 { 14 | e0_i32max = 0x7FFFFFFF, 15 | }; 16 | _Static_assert(_Generic(e0_i32max, int32_t:1), ""); 17 | _Static_assert(_Generic((enum e0)0, uint32_t:1), ""); 18 | 19 | enum e1 { 20 | e1_i32max = 0x7FFFFFFF, 21 | e1_i32max_plus1, 22 | }; 23 | _Static_assert(_Generic(e1_i32max, uint32_t:1), ""); 24 | _Static_assert(_Generic((enum e1)0, uint32_t:1), ""); 25 | 26 | enum e2 { 27 | e2_neg = -1, 28 | e2_i32max = 0x7FFFFFFF, 29 | e2_i32max_plus1, 30 | }; 31 | _Static_assert(_Generic(e2_i32max, FIRST_64BIT_INT:1), ""); 32 | _Static_assert(_Generic((enum e2)0, FIRST_64BIT_INT:1), ""); 33 | 34 | enum e3 { 35 | e3_i32max = 0x7FFFFFFF, 36 | e3_neg = -1 37 | }; 38 | _Static_assert(_Generic(e3_i32max, int32_t:1), ""); 39 | _Static_assert(_Generic((enum e3)0, int32_t:1), ""); 40 | 41 | enum e4 { 42 | e4_u32max = 0xFFFFFFFF, 43 | }; 44 | _Static_assert(_Generic(e4_u32max, uint32_t:1), ""); 45 | _Static_assert(_Generic((enum e4)0, uint32_t:1), ""); 46 | 47 | enum e5 { 48 | e5_u32max = 0xFFFFFFFF, 49 | e5_neg = -1 50 | }; 51 | _Static_assert(_Generic(e5_u32max, FIRST_64BIT_INT:1), ""); 52 | _Static_assert(_Generic((enum e5)0, FIRST_64BIT_INT:1), ""); 53 | 54 | enum e6 { 55 | e6_u32max = 0xFFFFFFFF, 56 | e6_u32max_plus1, 57 | }; 58 | _Static_assert(_Generic(e6_u32max_plus1, unsigned FIRST_64BIT_INT:1), ""); 59 | _Static_assert(_Generic((enum e6)0, unsigned FIRST_64BIT_INT:1), ""); 60 | 61 | enum e7 { 62 | e7_u32max = 0xFFFFFFFF, 63 | e7_u32max_plus1, 64 | e7_neg = -1 65 | }; 66 | _Static_assert(_Generic(e7_u32max_plus1, FIRST_64BIT_INT:1), ""); 67 | _Static_assert(_Generic((enum e7)0, FIRST_64BIT_INT:1), ""); 68 | 69 | int main(void) { 70 | enum E1; 71 | typedef enum E1 const C2; 72 | typedef C2 *P; 73 | P p; 74 | 75 | enum E1 { 76 | E1A, 77 | E1B = 5000000000, 78 | }; 79 | 80 | DASSERT(sizeof(*p) == 8); 81 | DASSERT(5000000000 == E1B); 82 | 83 | enum E2 : short; 84 | enum E2 : short { E2A }; 85 | DASSERT(sizeof(E2A) == 2); 86 | 87 | enum : short unsigned { ANON_E }; 88 | DASSERT(sizeof(ANON_E) == 2); 89 | 90 | printf("OK\n"); 91 | } 92 | -------------------------------------------------------------------------------- /test/extern.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | extern int ext1; 4 | extern int *ext2; 5 | 6 | inline int inline_fn(void) { 7 | return 3; 8 | } 9 | 10 | int main() { 11 | ASSERT(5, ext1); 12 | ASSERT(5, *ext2); 13 | 14 | extern int ext3; 15 | ASSERT(7, ext3); 16 | 17 | int ext_fn1(int x); 18 | ASSERT(5, ext_fn1(5)); 19 | 20 | extern int ext_fn2(int x); 21 | ASSERT(8, ext_fn2(8)); 22 | 23 | printf("OK\n"); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test/float.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | EASSERT(35, (float)(char)35); 5 | EASSERT(35, (float)(short)35); 6 | EASSERT(35, (float)(int)35); 7 | EASSERT(35, (float)(long)35); 8 | EASSERT(35, (float)(unsigned char)35); 9 | EASSERT(35, (float)(unsigned short)35); 10 | EASSERT(35, (float)(unsigned int)35); 11 | EASSERT(35, (float)(unsigned long)35); 12 | 13 | EASSERT(35, (double)(char)35); 14 | EASSERT(35, (double)(short)35); 15 | EASSERT(35, (double)(int)35); 16 | EASSERT(35, (double)(long)35); 17 | EASSERT(35, (double)(unsigned char)35); 18 | EASSERT(35, (double)(unsigned short)35); 19 | EASSERT(35, (double)(unsigned int)35); 20 | EASSERT(35, (double)(unsigned long)35); 21 | 22 | EASSERT(35, (char)(float)35); 23 | EASSERT(35, (short)(float)35); 24 | EASSERT(35, (int)(float)35); 25 | EASSERT(35, (long)(float)35); 26 | EASSERT(35, (unsigned char)(float)35); 27 | EASSERT(35, (unsigned short)(float)35); 28 | EASSERT(35, (unsigned int)(float)35); 29 | EASSERT(35, (unsigned long)(float)35); 30 | 31 | EASSERT(35, (char)(double)35); 32 | EASSERT(35, (short)(double)35); 33 | EASSERT(35, (int)(double)35); 34 | EASSERT(35, (long)(double)35); 35 | EASSERT(35, (unsigned char)(double)35); 36 | EASSERT(35, (unsigned short)(double)35); 37 | EASSERT(35, (unsigned int)(double)35); 38 | EASSERT(35, (unsigned long)(double)35); 39 | 40 | // ASSERT(-2147483648, (double)(unsigned long)(long)-1); // impl-def 41 | 42 | EASSERT(1, 2e3==2e3); 43 | EASSERT(0, 2e3==2e5); 44 | EASSERT(1, 2.0==2); 45 | EASSERT(0, 5.1<5); 46 | EASSERT(0, 5.0<5); 47 | EASSERT(1, 4.9<5); 48 | EASSERT(0, 5.1<=5); 49 | EASSERT(1, 5.0<=5); 50 | EASSERT(1, 4.9<=5); 51 | 52 | EASSERT(1, 2e3f==2e3); 53 | EASSERT(0, 2e3f==2e5); 54 | EASSERT(1, 2.0f==2); 55 | EASSERT(0, 5.1f<5); 56 | EASSERT(0, 5.0f<5); 57 | EASSERT(1, 4.9f<5); 58 | EASSERT(0, 5.1f<=5); 59 | EASSERT(1, 5.0f<=5); 60 | EASSERT(1, 4.9f<=5); 61 | 62 | EASSERT(6, 2.3+3.8); 63 | EASSERT(-1, 2.3-3.8); 64 | EASSERT(-3, -3.8); 65 | EASSERT(13, 3.3*4); 66 | EASSERT(2, 5.0/2); 67 | 68 | EASSERT(6, 2.3f+3.8f); 69 | EASSERT(6, 2.3f+3.8); 70 | EASSERT(-1, 2.3f-3.8); 71 | EASSERT(-3, -3.8f); 72 | EASSERT(13, 3.3f*4); 73 | EASSERT(2, 5.0f/2); 74 | 75 | ASSERT(0, 0.0/0.0 == 0.0/0.0); 76 | ASSERT(1, 0.0/0.0 != 0.0/0.0); 77 | 78 | ASSERT(0, 0.0/0.0 < 0); 79 | ASSERT(0, 0.0/0.0 <= 0); 80 | ASSERT(0, 0.0/0.0 > 0); 81 | ASSERT(0, 0.0/0.0 >= 0); 82 | 83 | EASSERT(0, !3.); 84 | EASSERT(1, !0.); 85 | EASSERT(0, !3.f); 86 | EASSERT(1, !0.f); 87 | 88 | EASSERT(5, 0.0 ? 3 : 5); 89 | EASSERT(3, 1.2 ? 3 : 5); 90 | 91 | printf("OK\n"); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /test/float2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #if defined __GNUC__ && !defined __clang__ 4 | #define FASSERT ASSERT 5 | #else 6 | #define FASSERT EASSERT 7 | #endif 8 | 9 | long double g0 = 343.4314; 10 | 11 | int main(void) { 12 | long double l0 = 343.4314; 13 | long double l1 = 343.4314L; 14 | 15 | ASSERT(0, g0 == l1); 16 | ASSERT(0, l0 == l1); 17 | 18 | FASSERT(0, 0.0/0.0 == 0.0/0.0); 19 | FASSERT(1, 0.0/0.0 != 0.0/0.0); 20 | 21 | FASSERT(0, 0.0/0.0 < 0); 22 | FASSERT(0, 0.0/0.0 <= 0); 23 | FASSERT(0, 0.0/0.0 > 0); 24 | FASSERT(0, 0.0/0.0 >= 0); 25 | 26 | FASSERT(0, 0.0f/0.0f == 0.0f/0.0f); 27 | FASSERT(1, 0.0f/0.0f != 0.0f/0.0f); 28 | 29 | FASSERT(0, 0.0f/0.0f < 0); 30 | FASSERT(0, 0.0f/0.0f <= 0); 31 | FASSERT(0, 0.0f/0.0f > 0); 32 | FASSERT(0, 0.0f/0.0f >= 0); 33 | 34 | FASSERT(0, 0.0L/0.0L == 0.0L/0.0L); 35 | FASSERT(1, 0.0L/0.0L != 0.0L/0.0L); 36 | 37 | FASSERT(0, 0.0L/0.0L < 0); 38 | FASSERT(0, 0.0L/0.0L <= 0); 39 | FASSERT(0, 0.0L/0.0L > 0); 40 | FASSERT(0, 0.0L/0.0L >= 0); 41 | 42 | ASSERT(1, ({ float f = 0.0f; (_Bool)(f/f); })); 43 | ASSERT(1, ({ double d = -0.0; (d/d)?1:0; })); 44 | ASSERT(1, ({ long double ld = 0.0L; int i = 0; if(ld/ld) i = 1; i; })); 45 | 46 | { 47 | float pos_z; pos_z = +0.0f; 48 | float neg_z; neg_z = -0.0f; 49 | ASSERT(1, pos_z == neg_z && memcmp(&pos_z, &neg_z, sizeof(float))); 50 | pos_z = -pos_z; 51 | ASSERT(1, pos_z == neg_z && !memcmp(&pos_z, &neg_z, sizeof(float))); 52 | } 53 | { 54 | double pos_z; pos_z = +0.0; 55 | double neg_z; neg_z = -0.0; 56 | ASSERT(1, pos_z == neg_z && memcmp(&pos_z, &neg_z, sizeof(double))); 57 | neg_z = -neg_z; 58 | ASSERT(1, pos_z == neg_z && !memcmp(&pos_z, &neg_z, sizeof(double))); 59 | } 60 | { 61 | long double pos_z; pos_z = +0.0L; 62 | long double neg_z; neg_z = -0.0L; 63 | ASSERT(1, pos_z == neg_z && memcmp(&pos_z, &neg_z, 10)); 64 | } 65 | 66 | printf("OK\n"); 67 | } 68 | -------------------------------------------------------------------------------- /test/generic.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(1, _Generic(100.0, double: 1, int *: 2, int: 3, float: 4)); 5 | ASSERT(2, _Generic((int *)0, double: 1, int *: 2, int: 3, float: 4)); 6 | ASSERT(2, _Generic((int[3]){}, double: 1, int *: 2, int: 3, float: 4)); 7 | ASSERT(3, _Generic(100, double: 1, int *: 2, int: 3, float: 4)); 8 | ASSERT(4, _Generic(100f, double: 1, int *: 2, int: 3, float: 4)); 9 | 10 | printf("OK\n"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/generic2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | void paramty(int a[volatile], int sz, int b[const restrict static sz]) { 4 | ASSERT(1, _Generic(a, int *: 1, int volatile*: 0)); 5 | ASSERT(1, _Generic(a, int volatile*: 0, int *: 1)); 6 | 7 | ASSERT(1, _Generic(&a, int **: 0, int *volatile *: 1)); 8 | ASSERT(1, _Generic(&a, int *volatile *: 1, int **: 0)); 9 | 10 | ASSERT(1, _Generic(&b, int **: 0, int *restrict const *: 1)); 11 | ASSERT(1, _Generic(&b, int *restrict const *: 1, int **: 0)); 12 | } 13 | 14 | void param_arrptr_ty(int sz, int(*a)[13], int(*b)[]) { 15 | ASSERT(1, _Generic(a, default:0, int(*)[13]:1, int(*)[17]:2)); 16 | ASSERT(0, _Generic(a, default:0, int(*)[13][17]:1)); 17 | 18 | ASSERT(1, _Generic(b, default:0, typeof(a):1)); 19 | ASSERT(1, _Generic(a, default:0, typeof(b):1)); 20 | 21 | ASSERT(1, _Generic(b, default:0, int(*)[17]:1)); 22 | ASSERT(0, _Generic(b, default:0, int(*)[13][17]:1)); 23 | 24 | int vla1[sz]; 25 | int vla2[sz][13]; 26 | ASSERT(1, _Generic(&vla1, default :0, typeof(a):1)); 27 | ASSERT(1, _Generic(&vla1, default :0, typeof(b):1)); 28 | ASSERT(0, _Generic(&vla2, default :0, typeof(a):1)); 29 | ASSERT(1, _Generic(&vla2[1], default :0, typeof(a):1)); 30 | } 31 | 32 | 33 | void param_vlaptr_ty(int sz, int (*a)[sz]) { 34 | ASSERT(0, _Generic(a, default:0, int *:1)); 35 | ASSERT(1, _Generic(a, default:0, int(*)[13]:1)); 36 | ASSERT(0, _Generic(a, default:0, int(*)[13][17]:1)); 37 | } 38 | 39 | int main(int argc, char**argv) { 40 | 41 | ASSERT(1, ({ char c; _Generic(c << 1, int:1 ); }) ); 42 | ASSERT(1, ({ short s; _Generic(s >> 1, int:1 ); }) ); 43 | ASSERT(1, ({ struct { unsigned int c : 17; } s; _Generic(~s.c, int:1 ); }) ); 44 | ASSERT(1, ({ struct { unsigned long long c : 17; } s; _Generic(~s.c, int:1 ); }) ); 45 | 46 | ASSERT(1, ({ char c; _Generic(-c, int:1 ); }) ); 47 | ASSERT(1, ({ short s; _Generic(+s, int:1 ); }) ); 48 | 49 | ASSERT(1, _Generic((long){0}, long:1, long long:0) ); 50 | ASSERT(1, _Generic((long long){0}, long long:1, long:0) ); 51 | 52 | ASSERT(1, _Generic(1L, long:1, long long:0) ); 53 | ASSERT(1, _Generic(1LL, long long:1, long:0) ); 54 | 55 | ASSERT(1, _Generic(1UL, unsigned long:1, unsigned long long:0) ); 56 | ASSERT(1, _Generic(1lu, unsigned long:1, unsigned long long:0) ); 57 | 58 | ASSERT(1, _Generic(1ULL, unsigned long long:1, unsigned long:0) ); 59 | ASSERT(1, _Generic(1llu, unsigned long long:1, unsigned long:0) ); 60 | 61 | ASSERT(1, ({ unsigned long a; long long b; _Generic(a + b, unsigned long long:1, unsigned long:0); }) ); 62 | 63 | ASSERT(1, _Generic(argc ? 0 : "a", char*:1 ) ); 64 | ASSERT(1, _Generic(argc ? "a" : 0, char*:1 ) ); 65 | 66 | ASSERT(1, _Generic(argc ? (void*)0 : "a", char*:1 ) ); 67 | ASSERT(1, _Generic(argc ? "a" : (void*)0, char*:1 ) ); 68 | 69 | ASSERT(1, _Generic(argc ? "a" : (void*)(void*)0, void*:1 ) ); 70 | ASSERT(1, _Generic(argc ? (void*)(void*)0 : "a", void*:1 ) ); 71 | 72 | ASSERT(1, ({ void *p; _Generic(argc ? p : "a", void*:1, char*:2); }) ); 73 | ASSERT(1, ({ void *p; _Generic(argc ? "a" : p, void*:1, char*:2); }) ); 74 | 75 | ASSERT(1, ({ double *p; char *q; _Generic(argc ? p : q, void*:1 ); }) ); 76 | ASSERT(1, ({ double *p; char *q; _Generic(argc ? q : p, void*:1 ); }) ); 77 | 78 | ASSERT(1, _Generic(**argv, unsigned char:0, char:1, signed char:0) ); 79 | ASSERT(1, _Generic("a", unsigned char*:0, char*:1, signed char*:0) ); 80 | 81 | ASSERT(1, ({ int vla[argc]; _Generic(vla, int*:1 ); }) ); 82 | 83 | ASSERT(1, ({ const int *p; _Generic(p, int const *:1, int *:0);})); 84 | ASSERT(1, ({ volatile int *p; _Generic(p, int *:0, int volatile *:1);})); 85 | ASSERT(1, ({ _Atomic int *p; _Generic(p, int *:0, int _Atomic *:1);})); 86 | ASSERT(1, ({ int *_Atomic p; _Generic(p, int *:1);})); 87 | ASSERT(1, ({ int *_Atomic *p; _Generic(p, int *_Atomic *:1, int**:0);})); 88 | ASSERT(1, ({ int *_Atomic *p; _Generic(p, int**:0, int *_Atomic *:1);})); 89 | ASSERT(1, ({ int *restrict p; _Generic(p, int *:1);})); 90 | ASSERT(1, ({ int *restrict *p; _Generic(p, int *restrict *:1, int **:0);})); 91 | ASSERT(1, ({ int *restrict *p; _Generic(p, int **:0, int *restrict *:1);})); 92 | 93 | #ifdef NOTCLANG 94 | ASSERT(1, ({ const int (*fn)(void); _Generic(fn, int(*)(void): 1);})); 95 | #endif 96 | ASSERT(1, ({ const int(*fn)(void); typeof(fn()) i; _Generic(&i, int *:1);})); 97 | ASSERT(1, ({ void (*fn)(const int); _Generic(fn, void(*)(int): 1);})); 98 | 99 | ASSERT(1, ({ const int i; _Generic( i, int :1, const int: 2);})); 100 | ASSERT(2, ({ const int i; _Generic(typeof(i), int :1, const int: 2);})); 101 | 102 | DASSERT(2 == _Generic(const int, int :1, const int: 2) ); 103 | DASSERT(2 == _Generic(volatile int, volatile int: 2, int: 1) ); 104 | DASSERT(2 == _Generic(_Atomic int, _Atomic int: 2, int :1) ); 105 | 106 | paramty(0,0,0); 107 | param_arrptr_ty(0,0,0); 108 | param_vlaptr_ty(0,0); 109 | 110 | printf("OK\n"); 111 | } 112 | 113 | -------------------------------------------------------------------------------- /test/gibberish.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | void fn_param(void) { 4 | void (*A) (int (*pf)(char)); 5 | void (*B) (int *f(char)); 6 | _Static_assert(_Generic(A, typeof(&B):0, default: 1)); 7 | _Static_assert(_Generic(B, typeof(&A):0, default: 1)); 8 | 9 | 10 | _Static_assert(_Generic(A, void(*)(int (char) ):1)); 11 | _Static_assert(_Generic(A, void(*)(int ((char))):1)); 12 | _Static_assert(_Generic(A, void(*)(int p (char) ):1)); 13 | _Static_assert(_Generic(A, void(*)(int( p ) (char) ):1)); 14 | _Static_assert(_Generic(A, void(*)(int( ( p )) (char) ):1)); 15 | _Static_assert(_Generic(B, void(*)(int * (char) ):1)); 16 | _Static_assert(_Generic(B, void(*)(int * ((char))):1)); 17 | _Static_assert(_Generic(A, void(*)(int( * ) (char) ):1)); 18 | _Static_assert(_Generic(A, void(*)(int( (* )) (char) ):1)); 19 | 20 | _Static_assert(_Generic(B, void(*)(int* p (char) ):1)); 21 | _Static_assert(_Generic(B, void(*)(int*( p ) (char) ):1)); 22 | _Static_assert(_Generic(B, void(*)(int*(( p )) (char) ):1)); 23 | 24 | _Static_assert(_Generic(A, void(*)(int( *p ) (char) ):1)); 25 | _Static_assert(_Generic(A, void(*)(int( (*p )) (char) ):1)); 26 | _Static_assert(_Generic(A, void(*)(int(*( p )) (char) ):1)); 27 | _Static_assert(_Generic(A, void(*)(int(*((p))) (char) ):1)); 28 | 29 | _Static_assert(_Generic(A, void(*)(int( p (char) )):1)); 30 | _Static_assert(_Generic(A, void(*)(int( ( p ) (char) )):1)); 31 | _Static_assert(_Generic(A, void(*)(int( ((p)) (char) )):1)); 32 | _Static_assert(_Generic(B, void(*)(int( * (char) )):1)); 33 | _Static_assert(_Generic(B, void(*)(int( * ((char)))):1)); 34 | _Static_assert(_Generic(A, void(*)(int( (* ) (char) )):1)); 35 | _Static_assert(_Generic(A, void(*)(int(((* )) (char) )):1)); 36 | 37 | _Static_assert(_Generic(B, void(*)(int(* p (char))):1)); 38 | _Static_assert(_Generic(B, void(*)(int(*( p ) (char))):1)); 39 | _Static_assert(_Generic(A, void(*)(int( (*p ) (char))):1)); 40 | _Static_assert(_Generic(B, void(*)(int(*((p)) (char))):1)); 41 | _Static_assert(_Generic(A, void(*)(int((*(p)) (char))):1)); 42 | _Static_assert(_Generic(A, void(*)(int(((*p)) (char))):1)); 43 | } 44 | 45 | void fn_param_empty(void) { 46 | void (*A) (int (*pf)()); 47 | void (*B) (int *f()); 48 | _Static_assert(_Generic(A, typeof(&B):0, default: 1)); 49 | _Static_assert(_Generic(B, typeof(&A):0, default: 1)); 50 | 51 | 52 | _Static_assert(_Generic(A, void(*)(int () ):1)); 53 | _Static_assert(_Generic(A, void(*)(int (())):1)); 54 | _Static_assert(_Generic(A, void(*)(int p () ):1)); 55 | _Static_assert(_Generic(A, void(*)(int( p ) () ):1)); 56 | _Static_assert(_Generic(A, void(*)(int( ( p )) () ):1)); 57 | _Static_assert(_Generic(B, void(*)(int * () ):1)); 58 | _Static_assert(_Generic(B, void(*)(int * (())):1)); 59 | _Static_assert(_Generic(A, void(*)(int( * ) () ):1)); 60 | _Static_assert(_Generic(A, void(*)(int( (* )) () ):1)); 61 | 62 | _Static_assert(_Generic(B, void(*)(int* p () ):1)); 63 | _Static_assert(_Generic(B, void(*)(int*( p ) () ):1)); 64 | _Static_assert(_Generic(B, void(*)(int*(( p )) () ):1)); 65 | 66 | _Static_assert(_Generic(A, void(*)(int( *p ) () ):1)); 67 | _Static_assert(_Generic(A, void(*)(int( (*p )) () ):1)); 68 | _Static_assert(_Generic(A, void(*)(int(*( p )) () ):1)); 69 | _Static_assert(_Generic(A, void(*)(int(*((p))) () ):1)); 70 | 71 | _Static_assert(_Generic(A, void(*)(int( p () )):1)); 72 | _Static_assert(_Generic(A, void(*)(int( ( p ) () )):1)); 73 | _Static_assert(_Generic(A, void(*)(int( ((p)) () )):1)); 74 | _Static_assert(_Generic(B, void(*)(int( * () )):1)); 75 | _Static_assert(_Generic(B, void(*)(int( * (()))):1)); 76 | _Static_assert(_Generic(A, void(*)(int( (* ) () )):1)); 77 | _Static_assert(_Generic(A, void(*)(int(((* )) () )):1)); 78 | 79 | _Static_assert(_Generic(B, void(*)(int(* p ())):1)); 80 | _Static_assert(_Generic(B, void(*)(int(*( p ) ())):1)); 81 | _Static_assert(_Generic(A, void(*)(int( (*p ) ())):1)); 82 | _Static_assert(_Generic(B, void(*)(int(*((p)) ())):1)); 83 | _Static_assert(_Generic(A, void(*)(int((*(p)) ())):1)); 84 | _Static_assert(_Generic(A, void(*)(int(((*p)) ())):1)); 85 | } 86 | 87 | void fn_param_typedef(void) { 88 | typedef struct { 89 | int i; 90 | } S; 91 | 92 | void (*A) (int (*pf)(S)); 93 | void (*B) (int *f(S)); 94 | _Static_assert(_Generic(A, typeof(&B):0, default: 1)); 95 | _Static_assert(_Generic(B, typeof(&A):0, default: 1)); 96 | 97 | _Static_assert(_Generic(A, void(*)(int (S) ):1)); 98 | _Static_assert(_Generic(A, void(*)(int ((S))):1)); 99 | _Static_assert(_Generic(A, void(*)(int p (S) ):1)); 100 | _Static_assert(_Generic(A, void(*)(int( p ) (S) ):1)); 101 | _Static_assert(_Generic(A, void(*)(int( ( p )) (S) ):1)); 102 | _Static_assert(_Generic(B, void(*)(int * (S) ):1)); 103 | _Static_assert(_Generic(B, void(*)(int * ((S))):1)); 104 | _Static_assert(_Generic(A, void(*)(int( * ) (S) ):1)); 105 | _Static_assert(_Generic(A, void(*)(int( (* )) (S) ):1)); 106 | 107 | _Static_assert(_Generic(B, void(*)(int* p (S) ):1)); 108 | _Static_assert(_Generic(B, void(*)(int*( p ) (S) ):1)); 109 | _Static_assert(_Generic(B, void(*)(int*(( p )) (S) ):1)); 110 | 111 | _Static_assert(_Generic(A, void(*)(int( *p ) (S) ):1)); 112 | _Static_assert(_Generic(A, void(*)(int( (*p )) (S) ):1)); 113 | _Static_assert(_Generic(A, void(*)(int(*( p )) (S) ):1)); 114 | _Static_assert(_Generic(A, void(*)(int(*((p))) (S) ):1)); 115 | 116 | _Static_assert(_Generic(A, void(*)(int( p (S) )):1)); 117 | _Static_assert(_Generic(A, void(*)(int( ( p ) (S) )):1)); 118 | _Static_assert(_Generic(A, void(*)(int( ((p)) (S) )):1)); 119 | _Static_assert(_Generic(B, void(*)(int( * (S) )):1)); 120 | _Static_assert(_Generic(B, void(*)(int( * ((S)))):1)); 121 | _Static_assert(_Generic(A, void(*)(int( (* ) (S) )):1)); 122 | _Static_assert(_Generic(A, void(*)(int(((* )) (S) )):1)); 123 | 124 | _Static_assert(_Generic(B, void(*)(int(* p (S))):1)); 125 | _Static_assert(_Generic(B, void(*)(int(*( p ) (S))):1)); 126 | _Static_assert(_Generic(A, void(*)(int( (*p ) (S))):1)); 127 | _Static_assert(_Generic(B, void(*)(int(*((p)) (S))):1)); 128 | _Static_assert(_Generic(A, void(*)(int((*(p)) (S))):1)); 129 | _Static_assert(_Generic(A, void(*)(int(((*p)) (S))):1)); 130 | } 131 | 132 | int main(void) { 133 | printf("OK\n"); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /test/imm_arith_opt.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define TESTOPT2(Ty,x,Op,imm) \ 4 | ASSERT(1,((Ty)(x)Op(Ty)(imm)) == ({Ty a=x; a Op (Ty)(imm);}));\ 5 | 6 | #define TESTOPT(Ty,x,Op,imm) \ 7 | TESTOPT2(Ty,x,Op,imm) \ 8 | TESTOPT2(u##Ty,x,Op,imm) 9 | 10 | #define FILL32 0xF1234567 11 | #define FILL64 0xABCDEF0123456789 12 | 13 | int main(void) { 14 | TESTOPT(int32_t, FILL32, +, 0); 15 | TESTOPT(int64_t, FILL64, +, 0); 16 | TESTOPT(int32_t, FILL32, +, 1); 17 | TESTOPT(int64_t, FILL64, +, 1); 18 | TESTOPT(int32_t, FILL32, +, -1); 19 | TESTOPT(int64_t, FILL64, +, -1); 20 | 21 | TESTOPT(int32_t, FILL32, -, 0); 22 | TESTOPT(int64_t, FILL64, -, 0); 23 | TESTOPT(int32_t, FILL32, -, 1); 24 | TESTOPT(int64_t, FILL64, -, 1); 25 | TESTOPT(int32_t, FILL32, -, -1); 26 | TESTOPT(int64_t, FILL64, -, -1); 27 | 28 | TESTOPT(int32_t, FILL32, &, 0); 29 | TESTOPT(int64_t, FILL64, &, 0); 30 | TESTOPT(int32_t, FILL32, &, -1); 31 | TESTOPT(int64_t, FILL64, &, -1); 32 | 33 | TESTOPT(int32_t, FILL32, |, 0); 34 | TESTOPT(int64_t, FILL64, |, 0); 35 | TESTOPT(int32_t, FILL32, |, -1); 36 | TESTOPT(int64_t, FILL64, |, -1); 37 | 38 | TESTOPT(int32_t, FILL32, ^, 0); 39 | TESTOPT(int64_t, FILL64, ^, 0); 40 | TESTOPT(int32_t, FILL32, ^, -1); 41 | TESTOPT(int64_t, FILL64, ^, -1); 42 | 43 | TESTOPT(int32_t, FILL32, *, 0); 44 | TESTOPT(int64_t, FILL64, *, 0); 45 | TESTOPT(int32_t, FILL32, *, 1); 46 | TESTOPT(int64_t, FILL64, *, 1); 47 | TESTOPT(int32_t, FILL32, *, -1); 48 | TESTOPT(int64_t, FILL64, *, -1); 49 | 50 | TESTOPT(int32_t, FILL32, /, 1); 51 | TESTOPT(int64_t, FILL64, /, 1); 52 | TESTOPT(int32_t, FILL32, /, -1); 53 | TESTOPT(int64_t, FILL64, /, -1); 54 | TESTOPT(int32_t, -1, /, -1); 55 | TESTOPT(int64_t, -1, /, -1); 56 | 57 | TESTOPT(int32_t, FILL32, %, 1); 58 | TESTOPT(int64_t, FILL64, %, 1); 59 | TESTOPT(int32_t, FILL32, %, -1); 60 | TESTOPT(int64_t, FILL64, %, -1); 61 | TESTOPT(int32_t, -1, %, -1); 62 | TESTOPT(int64_t, -1, %, -1); 63 | 64 | TESTOPT(int32_t, FILL32, *, 1024); 65 | TESTOPT(int64_t, FILL64, *, 1024); 66 | 67 | TESTOPT2(uint32_t, FILL32, /, 1 << 5); 68 | TESTOPT2(uint64_t, FILL64, /, 1LL << 35); 69 | 70 | TESTOPT2(uint32_t, FILL32, %, 1U << 5); 71 | TESTOPT2(uint32_t, FILL32, %, 1U << 31); 72 | TESTOPT2(uint64_t, FILL64, %, 1ULL << 31); 73 | TESTOPT2(uint64_t, FILL64, %, 1ULL << 32); 74 | TESTOPT2(uint64_t, FILL64, %, 1ULL << 33); 75 | TESTOPT2(uint64_t, FILL64, %, 1ULL << 63); 76 | 77 | printf("OK\n"); 78 | } 79 | -------------------------------------------------------------------------------- /test/include1.h: -------------------------------------------------------------------------------- 1 | #include "include2.h" 2 | 3 | char *include1_filename = __FILE__; 4 | int include1_line = __LINE__; 5 | 6 | int include1 = 5; 7 | -------------------------------------------------------------------------------- /test/include2.h: -------------------------------------------------------------------------------- 1 | int include2 = 7; 2 | -------------------------------------------------------------------------------- /test/include3.h: -------------------------------------------------------------------------------- 1 | #define foo 3 2 | -------------------------------------------------------------------------------- /test/include4.h: -------------------------------------------------------------------------------- 1 | #define foo 4 2 | -------------------------------------------------------------------------------- /test/initializer2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | long double ld = 0.0L; 4 | 5 | const int arr[2][2] = {{1,2},{3,4}}; 6 | int *const p1 = arr[1]; 7 | 8 | int g1 = ((int){77}); 9 | int g2 = arr[1][1]; 10 | 11 | const struct { 12 | int *a, *b, *c; 13 | } relo = {.a = &g1, .c = &g2}; 14 | int *p2 = relo.c; 15 | int *p1p = p1; 16 | 17 | struct S { int i, j, k; }; 18 | struct S const s1 = {99, 88, 77}; 19 | struct S s2 = (struct S){33,44,55}; 20 | struct S s3 = s1; 21 | #ifdef NOTGCC 22 | int g3 = (struct S){55,66,77}.j; 23 | int g4 = (const int[]){11,22,33,44}[2]; 24 | #endif 25 | 26 | static long long obar = 2 + (long long)"foobar"; 27 | 28 | _Bool b = 2; 29 | _Bool ba[] = {3,3,3}; 30 | struct { 31 | _Bool b; 32 | } bs = {4}; 33 | 34 | long long z10 = {}; 35 | static long long z11 = {}; 36 | 37 | int c23_zinit(void) { 38 | long long z20 = {}; 39 | static long long z21 = {}; 40 | 41 | ASSERT(0, z10); 42 | ASSERT(0, z11); 43 | 44 | ASSERT(0, z20); 45 | ASSERT(0, z21); 46 | 47 | return 1; 48 | } 49 | 50 | int main(void) { 51 | ASSERT(3, *p1); 52 | 53 | ASSERT(77, g1); 54 | ASSERT(4, g2); 55 | ASSERT(1, p2 == &g2); 56 | ASSERT(1, p1p == p1); 57 | 58 | ASSERT(33, s2.i); 59 | ASSERT(44, s2.j); 60 | ASSERT(55, s2.k); 61 | 62 | ASSERT(99, s3.i); 63 | ASSERT(88, s3.j); 64 | ASSERT(77, s3.k); 65 | 66 | #ifdef NOTGCC 67 | ASSERT(66, g3); 68 | ASSERT(33, g4); 69 | #endif 70 | 71 | ASSERT(1, b); 72 | ASSERT(1, ba[2]); 73 | ASSERT(1, bs.b); 74 | 75 | ASSERT(0, strcmp("obar", (char *)obar)); 76 | 77 | { 78 | int i[2][4] = {[0][0 ... 1] = 4, 2, 3, 7, [1][1 ... 2] = 1, 9}; 79 | int ans[] = {4,4,2,3,7,1,1,9}; 80 | ASSERT(0, memcmp(&i, &ans, sizeof(ans))); 81 | } 82 | { 83 | struct Sub { 84 | int i; 85 | }; 86 | struct S { 87 | struct Sub b; 88 | int j; 89 | }; 90 | struct Sub b = {3}; 91 | struct S s[] = {b, 6, 7}; 92 | ASSERT(3, s[0].b.i); 93 | ASSERT(6, s[0].j); 94 | ASSERT(7, s[1].b.i); 95 | ASSERT(0, s[1].j); 96 | } 97 | 98 | ASSERT(1, c23_zinit()); 99 | 100 | printf("OK\n"); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /test/keywords_c23.c: -------------------------------------------------------------------------------- 1 | #define A 2 | 3 | #ifndef A 4 | #error 5 | #elifndef B 6 | #define B 7 | #else 8 | #error 9 | #endif 10 | 11 | #ifndef A 12 | #error 13 | #elifdef B 14 | #else 15 | #error 16 | #endif 17 | 18 | 19 | #if true 20 | #define true_is_1 21 | #endif 22 | 23 | #ifndef true_is_1 24 | #error 25 | #endif 26 | 27 | static_assert(true == (bool)123); 28 | 29 | bool fn() { 30 | alignas(1024) int var; 31 | return ((long long)(&var) & 1023) == false; 32 | } 33 | 34 | #include "test.h" 35 | 36 | int main() { 37 | ASSERT(true, fn()); 38 | printf("OK\n"); 39 | } 40 | -------------------------------------------------------------------------------- /test/labeled_loop_sw.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int fn(int i) { 4 | F: 5 | for (;; i += 1) { 6 | S1: 7 | S2: 8 | switch (i) 9 | F1: 10 | case 11: 11 | F2: 12 | for (;; i += 7) { 13 | switch (i) 14 | case 10: 15 | continue F; 16 | break S2; 17 | case 3: 18 | continue F1; 19 | default: 20 | break F; 21 | case 0: 22 | break S1; 23 | } 24 | i += 2; 25 | } 26 | return i; 27 | } 28 | 29 | int main(void) { 30 | ASSERT(14, fn(0)); 31 | printf("OK\n"); 32 | } 33 | -------------------------------------------------------------------------------- /test/line.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | #line 500 "foo" 5 | ASSERT(500, __LINE__); 6 | ASSERT(0, strcmp(__FILE__, "foo")); 7 | 8 | #line 800 "bar" 9 | ASSERT(800, __LINE__); 10 | ASSERT(0, strcmp(__FILE__, "bar")); 11 | 12 | #line 1 13 | ASSERT(1, __LINE__); 14 | 15 | # 200 "xyz" 2 3 16 | ASSERT(200, __LINE__); 17 | ASSERT(0, strcmp(__FILE__, "xyz")); 18 | 19 | printf("OK\n"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /test/literal.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | EASSERT(97, 'a'); 5 | EASSERT(10, '\n'); 6 | EASSERT(-128, '\x80'); 7 | 8 | EASSERT(511, 0777); 9 | EASSERT(0, 0x0); 10 | EASSERT(10, 0xa); 11 | EASSERT(10, 0XA); 12 | EASSERT(48879, 0xbeef); 13 | EASSERT(48879, 0xBEEF); 14 | EASSERT(48879, 0XBEEF); 15 | EASSERT(0, 0b0); 16 | EASSERT(1, 0b1); 17 | EASSERT(47, 0b101111); 18 | EASSERT(47, 0B101111); 19 | 20 | EASSERT(4, sizeof(0)); 21 | EASSERT(8, sizeof(0L)); 22 | EASSERT(8, sizeof(0LU)); 23 | EASSERT(8, sizeof(0UL)); 24 | EASSERT(8, sizeof(0LL)); 25 | EASSERT(8, sizeof(0LLU)); 26 | EASSERT(8, sizeof(0Ull)); 27 | EASSERT(8, sizeof(0l)); 28 | EASSERT(8, sizeof(0ll)); 29 | EASSERT(8, sizeof(0x0L)); 30 | EASSERT(8, sizeof(0b0L)); 31 | EASSERT(4, sizeof(2147483647)); 32 | EASSERT(8, sizeof(2147483648)); 33 | EASSERT(-1, 0xffffffffffffffff); 34 | EASSERT(8, sizeof(0xffffffffffffffff)); 35 | EASSERT(4, sizeof(4294967295U)); 36 | EASSERT(8, sizeof(4294967296U)); 37 | 38 | EASSERT(3, -1U>>30); 39 | EASSERT(3, -1Ul>>62); 40 | EASSERT(3, -1ull>>62); 41 | 42 | EASSERT(1, 0xffffffffffffffffl>>63); 43 | EASSERT(1, 0xffffffffffffffffll>>63); 44 | 45 | EASSERT(-1, 18446744073709551615); 46 | EASSERT(8, sizeof(18446744073709551615)); 47 | EASSERT(-1, 18446744073709551615>>63); 48 | 49 | EASSERT(-1, 0xffffffffffffffff); 50 | EASSERT(8, sizeof(0xffffffffffffffff)); 51 | EASSERT(1, 0xffffffffffffffff>>63); 52 | 53 | EASSERT(-1, 01777777777777777777777); 54 | EASSERT(8, sizeof(01777777777777777777777)); 55 | EASSERT(1, 01777777777777777777777>>63); 56 | 57 | EASSERT(-1, 0b1111111111111111111111111111111111111111111111111111111111111111); 58 | EASSERT(8, sizeof(0b1111111111111111111111111111111111111111111111111111111111111111)); 59 | EASSERT(1, 0b1111111111111111111111111111111111111111111111111111111111111111>>63); 60 | 61 | EASSERT(8, sizeof(2147483648)); 62 | EASSERT(4, sizeof(2147483647)); 63 | 64 | EASSERT(8, sizeof(0x1ffffffff)); 65 | EASSERT(4, sizeof(0xffffffff)); 66 | EASSERT(1, 0xffffffff>>31); 67 | 68 | EASSERT(8, sizeof(040000000000)); 69 | EASSERT(4, sizeof(037777777777)); 70 | EASSERT(1, 037777777777>>31); 71 | 72 | EASSERT(8, sizeof(0b111111111111111111111111111111111)); 73 | EASSERT(4, sizeof(0b11111111111111111111111111111111)); 74 | EASSERT(1, 0b11111111111111111111111111111111>>31); 75 | 76 | EASSERT(-1, 1 << 31 >> 31); 77 | EASSERT(-1, 01 << 31 >> 31); 78 | EASSERT(-1, 0x1 << 31 >> 31); 79 | EASSERT(-1, 0b1 << 31 >> 31); 80 | 81 | 0.0; 82 | 1.0; 83 | 3e+8; 84 | 0x10.1p0; 85 | .1E4f; 86 | 87 | EASSERT(4, sizeof(8f)); 88 | EASSERT(4, sizeof(0.3F)); 89 | EASSERT(8, sizeof(0.)); 90 | EASSERT(8, sizeof(.0)); 91 | EASSERT(16, sizeof(5.l)); 92 | EASSERT(16, sizeof(2.0L)); 93 | 94 | test_assert(1, size\ 95 | of(char), \ 96 | "sizeof(char)"); 97 | 98 | EASSERT(4, sizeof(L'\0')); 99 | EASSERT(97, L'a'); 100 | 101 | printf("OK\n"); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /test/macro2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #if 0 4 | 7 5 | #endif 6 | 7 | #define AAA 8 | #define MACRO_WITH_DEFINED_INSIDE (defined(AAA) && !defined(BBB)) 9 | 10 | #if MACRO_WITH_DEFINED_INSIDE 11 | #else 12 | #error 13 | #endif 14 | 15 | int main(void) { 16 | #define H(x) #x 17 | #define STR(x) H(x) 18 | 19 | #define M1(X) H(X) H(X) 20 | ASSERT(0, strcmp("00", M1(__COUNTER__)) ); 21 | 22 | #define M2(A,B,...) H(__VA_OPT__(A##B)) 23 | ASSERT(0, strcmp("XY", M2(X,Y,z)) ); 24 | 25 | #define M3(A,B,...) #__VA_OPT__(A##B) 26 | ASSERT(0, strcmp("XY", M3(X,Y,z)) ); 27 | 28 | #define EXPAND_PASTE(x,y) x + x##y 29 | #define i 5 30 | ASSERT(107, ({ int i3=100; EXPAND_PASTE(1+i,3); })); 31 | #undef i 32 | 33 | #define M4(A,...) H((A,##__VA_ARGS__)) 34 | ASSERT(0, strcmp("(X,)", M4(X,) )); 35 | 36 | #define M5(x,...) b ## __VA_OPT__(x) 37 | ASSERT(0, strcmp("bbz", STR(M5(M5(z,a),b)) )); 38 | 39 | #define hash_hash # ## # 40 | #define mkstr(a) # a 41 | #define in_between(a) mkstr(a) 42 | #define join(c, d) in_between(c hash_hash d) 43 | ASSERT(0, strcmp("x ## y", join(x,y) )); 44 | 45 | 46 | printf("OK\n"); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /test/macro_direcitve_in_fnlike.c: -------------------------------------------------------------------------------- 1 | 2 | #define G(...) 3 | G( 4 | #define M1 33 5 | #define M2 22 6 | #define F(x, y) x * y * x##y 7 | #define M3 11 8 | #define M23 5 9 | ) 10 | 11 | static int a = M1 + M2 + M3; 12 | static int b = F(M2, 3); 13 | 14 | #ifdef G 15 | 16 | #define H(x,y) y + x 17 | 18 | static int c = 19 | H( 20 | #endif 21 | M1 22 | , 23 | #ifdef F 24 | F(M2, 3) 25 | - 26 | #endif 27 | 28 | M3 29 | #ifdef H 30 | G(99) 31 | ) 32 | #endif 33 | ; 34 | 35 | #include "test.h" 36 | 37 | int main(void) { 38 | ASSERT(66, a); 39 | ASSERT(330, b); 40 | ASSERT(352, c); 41 | 42 | printf("OK\n"); 43 | } 44 | -------------------------------------------------------------------------------- /test/macro_has_include.c: -------------------------------------------------------------------------------- 1 | #ifndef __has_include 2 | #error 3 | #endif 4 | 5 | #if !__has_include("test.h") 6 | #error 7 | #endif 8 | 9 | #if !__has_include() 10 | #error 11 | #endif 12 | 13 | #define A B 14 | #define B C(test.h) 15 | #define C(x) STR(x) 16 | #define STR(x) #x 17 | 18 | #if !__has_include(A) 19 | #error 20 | #endif 21 | 22 | #include "test.h" 23 | 24 | int main(void) { 25 | printf("OK\n"); 26 | } 27 | -------------------------------------------------------------------------------- /test/macro_pmarks.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define HASH(x) #x 4 | #define STR(x) HASH(x) 5 | #define STR_STUFF(X,...) #__VA_OPT__(X X ## X __VA_ARGS__ X ## ## X X) 6 | 7 | int main(void) { 8 | 9 | #define M(x,y,z) x ## ## y ## ## z 10 | ASSERT(0, strcmp("3", STR(M(,,3)))); 11 | 12 | ASSERT(0, strcmp("3", STR_STUFF(,M(,,3)))); 13 | 14 | #define M1(X) a X ## X ## b 15 | ASSERT(0, strcmp("a b", STR(M1()))); 16 | 17 | #define M2(X, ...) __VA_OPT__(a X) ## b 18 | ASSERT(0, strcmp("a b", STR(M2(,.)))); 19 | 20 | #define M3(X, ...) a ## __VA_OPT__(X b) 21 | ASSERT(0, strcmp("a b", STR(M3(,.)))); 22 | 23 | #define M4(X, ...) __VA_OPT__(a X ## X) ## b 24 | ASSERT(0, strcmp("a b", STR(M4(,.)))); 25 | 26 | #define M5(X, ...) a ## __VA_OPT__(X ## X b) 27 | ASSERT(0, strcmp("a b", STR(M5(,.)))); 28 | 29 | printf("OK\n"); 30 | } 31 | -------------------------------------------------------------------------------- /test/macro_rescan.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | // adapted from David Mazières's "Recursive macros with C++20 __VA_OPT__" 4 | // https://www.scs.stanford.edu/~dm/blog/va-opt.html 5 | 6 | int E(int x) { 7 | return x * 17; 8 | } 9 | 10 | void rescan(void) { 11 | 12 | #define E(x) x 13 | int X = 3; 14 | 15 | ASSERT(51, E(E)(X) ); // E(X) 16 | 17 | #define T() E(X) 18 | #define PRNS () 19 | ASSERT(3, E(T()) ); // X 20 | ASSERT(51, E(T PRNS) ); // E(X) 21 | 22 | #define LPRN ( 23 | #define E2(arg) arg 24 | int x_0 = E(E2)(E)(X) ; // X 25 | int x_1 = E(E2 LPRN)E)(X) ; // X 26 | int x_2 = E(E2 LPRN E))(X) ; // E(X) 27 | int x_3 = E(E2 (E))(X) ; // E(X) 28 | ASSERT(3, x_0 ); 29 | ASSERT(3, x_1 ); 30 | ASSERT(51, x_2 ); 31 | ASSERT(51, x_3 ); 32 | 33 | #define F2() F 34 | #define F() __COUNTER__ F2 PRNS() 35 | #define H(x) #x 36 | #define STR(x) H(x) 37 | ASSERT(0, strcmp("0 F2 ()()", STR(F()) )); 38 | ASSERT(0, strcmp("1 2 F2 ()()", STR(E(F())) )); 39 | ASSERT(0, strcmp("3 4 5 F2 ()()", STR(E(E(F()))) )); 40 | } 41 | 42 | int arr[4]; 43 | 44 | void write_arr(int i) { 45 | static int idx = 0; 46 | if (idx >= 4) 47 | exit(1); 48 | 49 | arr[idx++] = i; 50 | } 51 | 52 | void foreach(void) { 53 | 54 | #define EXPAND(...) EXPAND2(EXPAND2(__VA_ARGS__)) 55 | #define EXPAND2(...) EXPAND1(EXPAND1(__VA_ARGS__)) 56 | #define EXPAND1(...) __VA_ARGS__ 57 | 58 | #define FOR_EACH(macro, ...) \ 59 | __VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, __VA_ARGS__))) 60 | #define FOR_EACH_HELPER(macro, a1, ...) \ 61 | macro(a1); \ 62 | __VA_OPT__(FOR_EACH_AGAIN PRNS (macro, __VA_ARGS__)) 63 | #define FOR_EACH_AGAIN() FOR_EACH_HELPER 64 | 65 | FOR_EACH(write_arr, 11, 22, 33, 44) 66 | 67 | ASSERT(11, arr[0] ); 68 | ASSERT(22, arr[1] ); 69 | ASSERT(33, arr[2] ); 70 | ASSERT(44, arr[3] ); 71 | } 72 | 73 | int main(void) { 74 | rescan(); 75 | foreach(); 76 | 77 | printf("OK\n"); 78 | } 79 | -------------------------------------------------------------------------------- /test/macro_spacing.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define EMPTY() 4 | #define H(x) #x 5 | #define STR(x) H(x) 6 | 7 | 8 | int main (void) { 9 | ASSERT(0, strcmp("+( )", STR(+EMPTY()( 10 | )) )); 11 | 12 | ASSERT(0, strcmp("a ( )", STR(a EMPTY()( 13 | )) )); 14 | 15 | ASSERT(0, strcmp("+ ()", STR(+EMPTY() 16 | ()) )); 17 | 18 | ASSERT(0, strcmp("a ()", STR(a EMPTY() 19 | ()) )); 20 | 21 | ASSERT(0, strcmp("+()", STR(+EMPTY( 22 | )()) )); 23 | 24 | ASSERT(0, strcmp("a ()", STR(a EMPTY( 25 | )()) )); 26 | 27 | ASSERT(0, strcmp("+()", STR(+EMPTY 28 | ()()) )); 29 | 30 | ASSERT(0, strcmp("a ()", STR(a EMPTY 31 | ()()) )); 32 | 33 | ASSERT(0, strcmp("+ ()", STR(+ 34 | EMPTY()()) )); 35 | 36 | ASSERT(0, strcmp("a ()", STR(a 37 | EMPTY()()) )); 38 | 39 | printf("OK\n"); 40 | } 41 | -------------------------------------------------------------------------------- /test/macro_va_tail.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | // Adapted from https://www.open-std.org/JTC1/SC22/WG14/www/docs/n3307.htm 4 | 5 | int main(void) { 6 | #define MAKE_SEMI(X, ...) X, __VA_TAIL__() 7 | char arr1[] = {MAKE_SEMI('A')}; 8 | char arr2[] = {MAKE_SEMI('A', 'B')}; 9 | char arr3[] = {MAKE_SEMI('A', 'B', 'C')}; 10 | ASSERT(0, strncmp(arr1, "A", 1)); 11 | ASSERT(0, strncmp(arr2, "AB", 2)); 12 | ASSERT(0, strncmp(arr3, "ABC", 3)); 13 | 14 | #define MAKE_SEMI2(X, ...) X, __VA_TAIL__(MAKE_SEMI2) 15 | char arr4[] = {MAKE_SEMI2('D')}; 16 | char arr5[] = {MAKE_SEMI2('D', 'E')}; 17 | char arr6[] = {MAKE_SEMI2('D', 'E', 'F')}; 18 | ASSERT(0, strncmp(arr4, "D", 1)); 19 | ASSERT(0, strncmp(arr5, "DE", 2)); 20 | ASSERT(0, strncmp(arr6, "DEF", 3)); 21 | 22 | #define AddUp(X, ...) (X __VA_OPT__(+__VA_TAIL__())) 23 | ASSERT(11, AddUp(11)); 24 | ASSERT(33, AddUp(11, 22)); 25 | ASSERT(66, AddUp(11, 22, 33)); 26 | 27 | #define REVERT(X, ...) __VA_TAIL__()__VA_OPT__(,) X 28 | char arr7[] = {REVERT('G')}; 29 | char arr8[] = {REVERT('G', 'H')}; 30 | char arr9[] = {REVERT('G', 'H', 'I')}; 31 | ASSERT(0, strncmp(arr7, "G", 1)); 32 | ASSERT(0, strncmp(arr8, "HG", 2)); 33 | ASSERT(0, strncmp(arr9, "IHG", 3)); 34 | 35 | #define LEFT(X, ...) X __VA_OPT__(,__VA_TAIL__(RIGHT)) 36 | #define RIGHT(X, ...) __VA_OPT__(__VA_TAIL__(LEFT),) X 37 | char arr10[] = {RIGHT('J', 'K', 'L', 'M', 'N', 'O')}; 38 | ASSERT(0, strncmp(arr10, "KMONLJ", 6)); 39 | 40 | #define A 35* 41 | #define B(Y) 3*(Y) 42 | #define C 7 43 | #define tailer(X, ...) (__VA_OPT__(+)X __VA_TAIL__()) 44 | ASSERT(735, tailer(A, B, C)); 45 | 46 | printf("OK\n"); 47 | } 48 | -------------------------------------------------------------------------------- /test/nullptr.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define COND_PTR_TYPE(_val, _arg1, _arg2) \ 4 | SASSERT(_val == _Generic(0 ? (_arg1) : (_arg2), nullptr_t:1, void*:2, int*:3)) 5 | 6 | COND_PTR_TYPE(2, (void*)0, (void*)0); 7 | COND_PTR_TYPE(1, nullptr, nullptr); 8 | COND_PTR_TYPE(2, nullptr, (void*)0); 9 | COND_PTR_TYPE(3, nullptr, (int*)0); 10 | 11 | COND_PTR_TYPE(2, (void*)nullptr, (void*)0); 12 | COND_PTR_TYPE(2, (void*)nullptr, 0); 13 | COND_PTR_TYPE(2, (void*)nullptr, (int*)0); 14 | 15 | COND_PTR_TYPE(3, (int*)nullptr, (int*)0); 16 | COND_PTR_TYPE(3, (int*)nullptr, (void*)0); 17 | COND_PTR_TYPE(3, (int*)nullptr, 0); 18 | COND_PTR_TYPE(3, (int*)nullptr, nullptr); 19 | COND_PTR_TYPE(2, (int*)nullptr, (void*)nullptr); 20 | 21 | COND_PTR_TYPE(1, nullptr, (nullptr_t)(void*)0); 22 | COND_PTR_TYPE(1, nullptr, (nullptr_t)0); 23 | COND_PTR_TYPE(1, nullptr, (nullptr_t)nullptr); 24 | 25 | nullptr_t p01; 26 | nullptr_t p02 = 0; 27 | nullptr_t p03 = {}; 28 | nullptr_t p04 = {0}; 29 | 30 | COND_PTR_TYPE(1, p02, nullptr); 31 | COND_PTR_TYPE(2, p02, (void*)0); 32 | COND_PTR_TYPE(3, p02, (int*)0); 33 | 34 | constexpr nullptr_t p12 = 0; 35 | constexpr nullptr_t p13 = {}; 36 | constexpr nullptr_t p14 = {0}; 37 | 38 | COND_PTR_TYPE(1, p12, nullptr); 39 | COND_PTR_TYPE(2, p12, (void*)0); 40 | COND_PTR_TYPE(3, p12, (int*)0); 41 | 42 | SASSERT(p12 == nullptr); 43 | SASSERT(p13 == 0); 44 | SASSERT(p14 == NULL); 45 | 46 | typedef nullptr_t n2; 47 | n2 np2 = 0; 48 | COND_PTR_TYPE(1, np2, nullptr); 49 | COND_PTR_TYPE(2, np2, (void*)0); 50 | COND_PTR_TYPE(3, np2, (int*)0); 51 | 52 | static nullptr_t val_test(void *vp, nullptr_t np, n2 np2) { 53 | { 54 | int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 55 | if (nullptr) 56 | b1 = 1; 57 | if (nullptr != vp) 58 | b2 = 1; 59 | if (!nullptr) 60 | b3 = 1; 61 | if ((bool)nullptr) 62 | b4 = 1; 63 | (void)nullptr; 64 | 65 | ASSERT(0, b1); 66 | ASSERT(0, b2); 67 | ASSERT(1, b3); 68 | ASSERT(0, b4); 69 | } 70 | 71 | { 72 | int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 73 | if (np) 74 | b1 = 1; 75 | if (np != vp) 76 | b2 = 1; 77 | if (!np) 78 | b3 = 1; 79 | if ((bool)np) 80 | b4 = 1; 81 | (void)np; 82 | 83 | ASSERT(0, b1); 84 | ASSERT(0, b2); 85 | ASSERT(1, b3); 86 | ASSERT(0, b4); 87 | } 88 | 89 | { 90 | int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 91 | if (np2) 92 | b1 = 1; 93 | if (np2 != vp) 94 | b2 = 1; 95 | if (!np2) 96 | b3 = 1; 97 | if ((bool)np2) 98 | b4 = 1; 99 | (void)np2; 100 | 101 | ASSERT(0, b1); 102 | ASSERT(0, b2); 103 | ASSERT(1, b3); 104 | ASSERT(0, b4); 105 | } 106 | 107 | return nullptr; 108 | } 109 | 110 | int main(void){ 111 | nullptr_t p21; 112 | nullptr_t p22 = 0; 113 | nullptr_t p23 = {}; 114 | nullptr_t p24 = {0}; 115 | 116 | ASSERT(1, p22 == 0); 117 | ASSERT(1, p23 == NULL); 118 | ASSERT(1, p24 == nullptr); 119 | 120 | static nullptr_t p31; 121 | static nullptr_t p32 = 0; 122 | static nullptr_t p33 = {}; 123 | static nullptr_t p34 = {0}; 124 | 125 | ASSERT(1, p32 == 0); 126 | ASSERT(1, p33 == NULL); 127 | ASSERT(1, p34 == nullptr); 128 | 129 | constexpr nullptr_t p42 = 0; 130 | constexpr nullptr_t p43 = {}; 131 | constexpr nullptr_t p44 = {0}; 132 | 133 | DASSERT(p42 == 0); 134 | DASSERT(p43 == NULL); 135 | DASSERT(p44 == nullptr); 136 | 137 | ASSERT(1, !val_test(NULL, nullptr, 0)); 138 | 139 | printf("OK\n"); 140 | } 141 | 142 | -------------------------------------------------------------------------------- /test/offsetof.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | typedef struct { 5 | int a; 6 | char b; 7 | int c; 8 | double d; 9 | } T; 10 | 11 | int main() { 12 | EASSERT(0, offsetof(T, a)); 13 | EASSERT(4, offsetof(T, b)); 14 | EASSERT(8, offsetof(T, c)); 15 | EASSERT(16, offsetof(T, d)); 16 | 17 | printf("OK\n"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/pointer.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(3, ({ int x=3; *&x; })); 5 | ASSERT(3, ({ int x=3; int *y=&x; int **z=&y; **z; })); 6 | ASSERT(5, ({ int x=3; int y=5; *(&x+1); })); 7 | ASSERT(3, ({ int x=3; int y=5; *(&y-1); })); 8 | ASSERT(5, ({ int x=3; int y=5; *(&x-(-1)); })); 9 | ASSERT(5, ({ int x=3; int *y=&x; *y=5; x; })); 10 | ASSERT(7, ({ int x=3; int y=5; *(&x+1)=7; y; })); 11 | ASSERT(7, ({ int x=3; int y=5; *(&y-2+1)=7; x; })); 12 | ASSERT(5, ({ int x=3; (&x+2)-&x+3; })); 13 | ASSERT(8, ({ int x, y; x=3; y=5; x+y; })); 14 | ASSERT(8, ({ int x=3, y=5; x+y; })); 15 | 16 | ASSERT(3, ({ int x[2]; int *y=&x; *y=3; *x; })); 17 | 18 | ASSERT(3, ({ int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *x; })); 19 | ASSERT(4, ({ int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+1); })); 20 | ASSERT(5, ({ int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+2); })); 21 | 22 | ASSERT(0, ({ int x[2][3]; int *y=x; *y=0; **x; })); 23 | ASSERT(1, ({ int x[2][3]; int *y=x; *(y+1)=1; *(*x+1); })); 24 | ASSERT(2, ({ int x[2][3]; int *y=x; *(y+2)=2; *(*x+2); })); 25 | ASSERT(3, ({ int x[2][3]; int *y=x; *(y+3)=3; **(x+1); })); 26 | ASSERT(4, ({ int x[2][3]; int *y=x; *(y+4)=4; *(*(x+1)+1); })); 27 | ASSERT(5, ({ int x[2][3]; int *y=x; *(y+5)=5; *(*(x+1)+2); })); 28 | 29 | ASSERT(3, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *x; })); 30 | ASSERT(4, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *(x+1); })); 31 | ASSERT(5, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2); })); 32 | ASSERT(5, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2); })); 33 | ASSERT(5, ({ int x[3]; *x=3; x[1]=4; 2[x]=5; *(x+2); })); 34 | 35 | ASSERT(0, ({ int x[2][3]; int *y=x; y[0]=0; x[0][0]; })); 36 | ASSERT(1, ({ int x[2][3]; int *y=x; y[1]=1; x[0][1]; })); 37 | ASSERT(2, ({ int x[2][3]; int *y=x; y[2]=2; x[0][2]; })); 38 | ASSERT(3, ({ int x[2][3]; int *y=x; y[3]=3; x[1][0]; })); 39 | ASSERT(4, ({ int x[2][3]; int *y=x; y[4]=4; x[1][1]; })); 40 | ASSERT(5, ({ int x[2][3]; int *y=x; y[5]=5; x[1][2]; })); 41 | 42 | printf("OK\n"); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test/postfix_inc_dec.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main(void) { 4 | _Bool b = 0; 5 | ASSERT(0, b--); 6 | ASSERT(1, b--); 7 | ASSERT(0, b--); 8 | ASSERT(1, b--); 9 | 10 | b = 0; 11 | ASSERT(0, b++); 12 | ASSERT(1, b++); 13 | ASSERT(1, b++); 14 | ASSERT(1, b++); 15 | 16 | float f; 17 | f = 16777216.0f; 18 | ASSERT(1, 16777216.0f == f++); 19 | 20 | f = -16777216.0f; 21 | ASSERT(1, -16777216.0f == f--); 22 | 23 | float f2; 24 | f = -0.0f; 25 | f2 = f++; 26 | f = -0.0f; 27 | ASSERT(1, !memcmp(&f, &f2, sizeof(float))); 28 | 29 | f = -0.0f; 30 | f2 = f--; 31 | f = -0.0f; 32 | ASSERT(1, !memcmp(&f, &f2, sizeof(float))); 33 | 34 | struct S { 35 | int pad :2; 36 | int i : 3; 37 | unsigned u : 3; 38 | _Bool b: 1; 39 | } s; 40 | 41 | ASSERT(-4, (s.i = -4, s.i--)); 42 | ASSERT(3, (s.i = 3, s.i++)); 43 | ASSERT(0, (s.u = 0, s.u--)); 44 | ASSERT(7, (s.u = 7, s.u++)); 45 | 46 | s.b = 0; 47 | ASSERT(0, s.b--); 48 | ASSERT(1, s.b--); 49 | ASSERT(0, s.b--); 50 | ASSERT(1, s.b--); 51 | 52 | s.b = 0; 53 | ASSERT(0, s.b++); 54 | ASSERT(1, s.b++); 55 | ASSERT(1, s.b++); 56 | ASSERT(1, s.b++); 57 | 58 | printf("OK\n"); 59 | } 60 | -------------------------------------------------------------------------------- /test/qualifiers.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | void cv_qualified_member(int i) { 4 | const int a1[4]; 5 | SASSERT(__builtin_types_compatible_p(typeof(&(*a1)), const int*)); 6 | SASSERT(!__builtin_types_compatible_p(typeof(&(*a1)), int*)); 7 | 8 | SASSERT(__builtin_types_compatible_p(typeof(&a1[0]), const int*)); 9 | SASSERT(!__builtin_types_compatible_p(typeof(&a1[0]), int*)); 10 | 11 | volatile int vla[i]; 12 | SASSERT(__builtin_types_compatible_p(typeof(&(*vla)), volatile int*)); 13 | SASSERT(!__builtin_types_compatible_p(typeof(&(*vla)), int*)); 14 | 15 | SASSERT(__builtin_types_compatible_p(typeof(&vla[0]), volatile int*)); 16 | SASSERT(!__builtin_types_compatible_p(typeof(&vla[0]), int*)); 17 | 18 | struct S1 { 19 | int i; 20 | }; 21 | 22 | struct S2 { 23 | int const i; 24 | }; 25 | 26 | struct S3 { 27 | const struct S1 s1; 28 | }; 29 | 30 | struct S4 { 31 | struct S1 s[4]; 32 | }; 33 | 34 | struct S1 const s1; 35 | SASSERT(__builtin_types_compatible_p(typeof(&s1.i), const int*)); 36 | SASSERT(!__builtin_types_compatible_p(typeof(&s1.i), int*)); 37 | 38 | struct S1 *p1; 39 | SASSERT(__builtin_types_compatible_p(typeof(&p1->i), int*)); 40 | SASSERT(!__builtin_types_compatible_p(typeof(&p1->i), int const*)); 41 | 42 | struct S1 const* p1c; 43 | SASSERT(!__builtin_types_compatible_p(typeof(&p1c->i), int*)); 44 | SASSERT(__builtin_types_compatible_p(typeof(&p1c->i), int const*)); 45 | 46 | struct S2 *p2; 47 | SASSERT(!__builtin_types_compatible_p(typeof(&p2->i), int*)); 48 | SASSERT(__builtin_types_compatible_p(typeof(&p2->i), int const*)); 49 | 50 | struct S3 *p3; 51 | SASSERT(!__builtin_types_compatible_p(typeof(&p3->s1.i), int*)); 52 | SASSERT(__builtin_types_compatible_p(typeof(&p3->s1.i), int const*)); 53 | 54 | struct S4 const *p4; 55 | SASSERT(!__builtin_types_compatible_p(typeof(&p4->s[3].i), int*)); 56 | SASSERT(__builtin_types_compatible_p(typeof(&p4->s[3].i), int const*)); 57 | 58 | SASSERT(!__builtin_types_compatible_p(typeof(&p4->s->i), int*)); 59 | SASSERT(__builtin_types_compatible_p(typeof(&p4->s->i), int const*)); 60 | 61 | SASSERT(!__builtin_types_compatible_p(typeof(&(*p4->s).i), int*)); 62 | SASSERT(__builtin_types_compatible_p(typeof(&(*p4->s).i), int const*)); 63 | } 64 | 65 | struct B { 66 | int i; 67 | }; 68 | typedef struct { 69 | struct B b1; 70 | struct B b2; 71 | } A; 72 | int regress1(const A* a, int i) { 73 | return (((i) ? &((a)->b1) : &((a)->b2)))->i; 74 | } 75 | 76 | int main(int argc, char** argv) { 77 | 78 | ASSERT(17, regress1(&(A){31,17}, 0)); 79 | ASSERT(31, regress1(&(A){31,17}, 1)); 80 | 81 | printf("OK\n"); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /test/setjmp.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | int acc; 5 | jmp_buf jbuf; 6 | 7 | void fn(int count) 8 | { 9 | acc += count; 10 | longjmp(jbuf, count+1); 11 | } 12 | 13 | int main(void) 14 | { 15 | volatile int count = 0; 16 | 17 | if (setjmp(jbuf) < 5) 18 | fn(++count); 19 | 20 | ASSERT(10, acc); 21 | 22 | count = 0; 23 | 24 | if (5 > setjmp(jbuf)) 25 | fn(++count); 26 | ASSERT(20, acc); 27 | 28 | printf("OK\n"); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /test/sizeof.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | EASSERT(1, sizeof(char)); 5 | EASSERT(2, sizeof(short)); 6 | EASSERT(2, sizeof(short int)); 7 | EASSERT(2, sizeof(int short)); 8 | EASSERT(4, sizeof(int)); 9 | EASSERT(8, sizeof(long)); 10 | EASSERT(8, sizeof(long int)); 11 | EASSERT(8, sizeof(long int)); 12 | EASSERT(8, sizeof(char *)); 13 | EASSERT(8, sizeof(int *)); 14 | EASSERT(8, sizeof(long *)); 15 | EASSERT(8, sizeof(int **)); 16 | EASSERT(8, sizeof(int(*)[4])); 17 | EASSERT(32, sizeof(int*[4])); 18 | EASSERT(16, sizeof(int[4])); 19 | EASSERT(48, sizeof(int[3][4])); 20 | EASSERT(8, sizeof(struct {int a; int b;})); 21 | 22 | EASSERT(8, sizeof(-10 + (long)5)); 23 | EASSERT(8, sizeof(-10 - (long)5)); 24 | EASSERT(8, sizeof(-10 * (long)5)); 25 | EASSERT(8, sizeof(-10 / (long)5)); 26 | EASSERT(8, sizeof((long)-10 + 5)); 27 | EASSERT(8, sizeof((long)-10 - 5)); 28 | EASSERT(8, sizeof((long)-10 * 5)); 29 | EASSERT(8, sizeof((long)-10 / 5)); 30 | 31 | ASSERT(1, ({ char i; sizeof(++i); })); 32 | ASSERT(1, ({ char i; sizeof(i++); })); 33 | 34 | EASSERT(8, sizeof(int(*)[10])); 35 | EASSERT(8, sizeof(int(*)[][10])); 36 | 37 | EASSERT(4, sizeof(struct { int x, y[]; })); 38 | 39 | EASSERT(1, sizeof(char)); 40 | EASSERT(1, sizeof(signed char)); 41 | EASSERT(1, sizeof(signed char signed)); 42 | EASSERT(1, sizeof(unsigned char)); 43 | EASSERT(1, sizeof(unsigned char unsigned)); 44 | 45 | EASSERT(2, sizeof(short)); 46 | EASSERT(2, sizeof(int short)); 47 | EASSERT(2, sizeof(short int)); 48 | EASSERT(2, sizeof(signed short)); 49 | EASSERT(2, sizeof(int short signed)); 50 | EASSERT(2, sizeof(unsigned short)); 51 | EASSERT(2, sizeof(int short unsigned)); 52 | 53 | EASSERT(4, sizeof(int)); 54 | EASSERT(4, sizeof(signed int)); 55 | EASSERT(4, sizeof(signed)); 56 | EASSERT(4, sizeof(signed signed)); 57 | EASSERT(4, sizeof(unsigned int)); 58 | EASSERT(4, sizeof(unsigned)); 59 | EASSERT(4, sizeof(unsigned unsigned)); 60 | 61 | EASSERT(8, sizeof(long)); 62 | EASSERT(8, sizeof(signed long)); 63 | EASSERT(8, sizeof(signed long int)); 64 | EASSERT(8, sizeof(unsigned long)); 65 | EASSERT(8, sizeof(unsigned long int)); 66 | 67 | EASSERT(8, sizeof(long long)); 68 | EASSERT(8, sizeof(signed long long)); 69 | EASSERT(8, sizeof(signed long long int)); 70 | EASSERT(8, sizeof(unsigned long long)); 71 | EASSERT(8, sizeof(unsigned long long int)); 72 | 73 | EASSERT(1, sizeof((char)1)); 74 | EASSERT(2, sizeof((short)1)); 75 | EASSERT(4, sizeof((int)1)); 76 | EASSERT(8, sizeof((long)1)); 77 | 78 | EASSERT(4, sizeof((char)1 + (char)1)); 79 | EASSERT(4, sizeof((short)1 + (short)1)); 80 | EASSERT(4, sizeof(1?2:3)); 81 | EASSERT(4, sizeof(1?(short)2:(char)3)); 82 | EASSERT(8, sizeof(1?(long)2:(char)3)); 83 | 84 | EASSERT(1, sizeof(char) << 31 >> 31); 85 | EASSERT(1, sizeof(char) << 63 >> 63); 86 | 87 | EASSERT(4, sizeof(float)); 88 | EASSERT(8, sizeof(double)); 89 | 90 | EASSERT(4, sizeof(1f+2)); 91 | EASSERT(8, sizeof(1.0+2)); 92 | EASSERT(4, sizeof(1f-2)); 93 | EASSERT(8, sizeof(1.0-2)); 94 | EASSERT(4, sizeof(1f*2)); 95 | EASSERT(8, sizeof(1.0*2)); 96 | EASSERT(4, sizeof(1f/2)); 97 | EASSERT(8, sizeof(1.0/2)); 98 | 99 | EASSERT(16, sizeof(long double)); 100 | 101 | EASSERT(1, sizeof(main)); 102 | 103 | printf("OK\n"); 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /test/stack_reuse.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | typedef struct { 4 | long i[4]; 5 | } S1; 6 | 7 | S1 gen_S1(int i) { S1 s = {i,i+1,i+2,i+3}; return s; } 8 | 9 | void *pass(void *ptr){ return ptr; } 10 | 11 | typedef struct { 12 | long i[1]; double d[1]; 13 | } M; 14 | 15 | void va_fn(int i, ...) { 16 | va_list ap; 17 | ASSERT(55, ( va_start(ap,i), va_arg(ap, M).i[ ({ S1 s = {}; 0; }) ] )); 18 | ASSERT(66, ( va_start(ap,i), va_arg(ap, M).d[ ({ S1 s = {}; 0; }) ] )); 19 | } 20 | 21 | 22 | int main(void) { 23 | ASSERT(1, ({ S1 s = {1,2,3,4}; s; }).i[ ({ S1 s = {}; 0;}) ] ); 24 | ASSERT(2, ({ S1 s = {1,2,3,4}; s; }).i[ ({ S1 s = {}; 1;}) ] ); 25 | ASSERT(3, ({ S1 s = {1,2,3,4}; s; }).i[ ({ S1 s = {}; 2;}) ] ); 26 | ASSERT(4, ({ S1 s = {1,2,3,4}; s; }).i[ ({ S1 s = {}; 3;}) ] ); 27 | 28 | ASSERT(1, gen_S1(1).i[ ({ S1 s = {}; 0;}) ] ); 29 | ASSERT(2, gen_S1(1).i[ ({ S1 s = {}; 1;}) ] ); 30 | ASSERT(3, gen_S1(1).i[ ({ S1 s = {}; 2;}) ] ); 31 | ASSERT(4, gen_S1(1).i[ ({ S1 s = {}; 3;}) ] ); 32 | 33 | ASSERT(5, gen_S1(5).i[ gen_S1(0).i[0] ] ); 34 | ASSERT(6, gen_S1(5).i[ gen_S1(0).i[1] ] ); 35 | ASSERT(7, gen_S1(5).i[ gen_S1(0).i[2] ] ); 36 | ASSERT(8, gen_S1(5).i[ gen_S1(0).i[3] ] ); 37 | 38 | ASSERT(5, ({ S1 s = {5,6,7,8}; s; }).i[ gen_S1(0).i[0] ] ); 39 | ASSERT(6, ({ S1 s = {5,6,7,8}; s; }).i[ gen_S1(0).i[1] ] ); 40 | ASSERT(7, ({ S1 s = {5,6,7,8}; s; }).i[ gen_S1(0).i[2] ] ); 41 | ASSERT(8, ({ S1 s = {5,6,7,8}; s; }).i[ gen_S1(0).i[3] ] ); 42 | 43 | unsigned long long complit_p1 = (unsigned long long) pass(&(S1[]){0}); 44 | unsigned long long complit_p2 = (unsigned long long) pass(&(S1[]){0}); 45 | unsigned long long complit_p3 = (unsigned long long) pass(pass(&(S1[]){0})); 46 | unsigned long long complit_p4 = (unsigned long long) pass(pass(&(S1[]){0})); 47 | 48 | ASSERT(1, complit_p1 != complit_p2); 49 | ASSERT(1, complit_p2 != complit_p3); 50 | ASSERT(1, complit_p3 != complit_p4); 51 | 52 | va_fn(0, (M){55,66}); 53 | 54 | printf("OK\n"); 55 | } 56 | -------------------------------------------------------------------------------- /test/static_assertion.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | struct S { 4 | int : 3; 5 | struct Inner{ 6 | int :3; 7 | } i; 8 | _Static_assert(sizeof(struct Inner) == 1); 9 | }; 10 | 11 | _Static_assert(offsetof(struct S, i) == 1); 12 | 13 | static_assert(sizeof (char[]){1,2,3} == 3); 14 | 15 | int main(void) { 16 | for (_Static_assert(1); 0;) { 17 | _Static_assert(1, "msg"); 18 | } 19 | printf("OK\n"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /test/stdhdr.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | printf("OK\n"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/stmtexpr2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | struct S { 4 | int a, b; 5 | }; 6 | 7 | int main() { 8 | struct S s1 = {11,-22 }; 9 | ASSERT(11, ({ ({ s1; }).a; })); 10 | ASSERT(-22, ({ ({ s1; }); }).b ); 11 | 12 | ASSERT(11, ({ ({ struct S s2 = s1; s2; }).a; })); 13 | ASSERT(-22, ({ ({ struct S s2 = s1; s2; }); }).b ); 14 | 15 | ASSERT(11, ({ ({(struct S){11,22}; }).a; })); 16 | ASSERT(22, ({ ({(struct S){11,22}; }); }).b ); 17 | 18 | ASSERT(sizeof(void*), sizeof ({ int arr[17]; arr; }) ); 19 | ASSERT(sizeof(void*), sizeof ({ int arr[s1.a]; arr; }) ); 20 | 21 | ({ 22 | if (s1.a == 11) { 23 | s1.a = 7; 24 | } else { 25 | s1.a = 13; 26 | } 27 | }); 28 | ASSERT(7, s1.a); 29 | 30 | printf("OK\n"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /test/string.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(0, ""[0]); 5 | ASSERT(1, sizeof("")); 6 | 7 | ASSERT(97, "abc"[0]); 8 | ASSERT(98, "abc"[1]); 9 | ASSERT(99, "abc"[2]); 10 | ASSERT(0, "abc"[3]); 11 | ASSERT(4, sizeof("abc")); 12 | 13 | ASSERT(7, "\a"[0]); 14 | ASSERT(8, "\b"[0]); 15 | ASSERT(9, "\t"[0]); 16 | ASSERT(10, "\n"[0]); 17 | ASSERT(11, "\v"[0]); 18 | ASSERT(12, "\f"[0]); 19 | ASSERT(13, "\r"[0]); 20 | ASSERT(27, "\e"[0]); 21 | 22 | ASSERT(106, "\j"[0]); 23 | ASSERT(107, "\k"[0]); 24 | ASSERT(108, "\l"[0]); 25 | 26 | ASSERT(7, "\ax\ny"[0]); 27 | ASSERT(120, "\ax\ny"[1]); 28 | ASSERT(10, "\ax\ny"[2]); 29 | ASSERT(121, "\ax\ny"[3]); 30 | 31 | ASSERT(0, "\0"[0]); 32 | ASSERT(16, "\20"[0]); 33 | ASSERT(65, "\101"[0]); 34 | ASSERT(104, "\1500"[0]); 35 | ASSERT(0, "\x00"[0]); 36 | ASSERT(119, "\x77"[0]); 37 | 38 | ASSERT(7, sizeof("abc" "def")); 39 | ASSERT(9, sizeof("abc" "d" "efgh")); 40 | ASSERT(0, strcmp("abc" "d" "\nefgh", "abcd\nefgh")); 41 | ASSERT(0, !strcmp("abc" "d", "abcd\nefgh")); 42 | ASSERT(0, strcmp("\x9" "0", "\t0")); 43 | 44 | ASSERT(16, sizeof(L"abc" "")); 45 | 46 | ASSERT(28, sizeof(L"abc" "def")); 47 | ASSERT(28, sizeof(L"abc" L"def")); 48 | ASSERT(14, sizeof(u"abc" "def")); 49 | ASSERT(14, sizeof(u"abc" u"def")); 50 | 51 | ASSERT(L'a', (L"abc" "def")[0]); 52 | ASSERT(L'd', (L"abc" "def")[3]); 53 | ASSERT(L'\0', (L"abc" "def")[6]); 54 | 55 | ASSERT(u'a', (u"abc" "def")[0]); 56 | ASSERT(u'd', (u"abc" "def")[3]); 57 | ASSERT(u'\0', (u"abc" "def")[6]); 58 | 59 | ASSERT(L'あ', ("あ" L"")[0]); 60 | ASSERT(0343, ("\343\201\202" L"")[0]); 61 | ASSERT(0201, ("\343\201\202" L"")[1]); 62 | ASSERT(0202, ("\343\201\202" L"")[2]); 63 | ASSERT(0, ("\343\201\202" L"")[3]); 64 | 65 | ASSERT(L'a', ("a" "b" L"c")[0]); 66 | ASSERT(L'b', ("a" "b" L"c")[1]); 67 | ASSERT(L'c', ("a" "b" L"c")[2]); 68 | ASSERT(0, ("a" "b" L"c")[3]); 69 | 70 | printf("OK\n"); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /test/string2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #include 4 | #include 5 | 6 | char str[] = {"foobar"}; 7 | char16_t str16[] = (u"foobar"); 8 | char32_t str32[] = ((U"foobar")); 9 | wchar_t strw[] = {((L"foobar"))}; 10 | 11 | int main(void){ 12 | ASSERT(1, _Generic( str, char *: 1)); 13 | ASSERT(1, _Generic( str16, char16_t *: 1)); 14 | ASSERT(1, _Generic( str32, char32_t *: 1)); 15 | ASSERT(1, _Generic( strw, wchar_t *: 1)); 16 | 17 | ASSERT(7 * sizeof(char), sizeof(str)); 18 | ASSERT(7 * sizeof(char16_t), sizeof(str16)); 19 | ASSERT(7 * sizeof(char32_t), sizeof(str32)); 20 | ASSERT(7 * sizeof(wchar_t), sizeof(strw)); 21 | 22 | char *arr[] = { "fo", {"oba"}, ("rfoob"), {(("ar"))} }; 23 | ASSERT(1, !strcmp("fo", arr[0]) ); 24 | ASSERT(1, !strcmp("oba", arr[1]) ); 25 | ASSERT(1, !strcmp("rfoob", arr[2]) ); 26 | ASSERT(1, !strcmp("ar", arr[3]) ); 27 | 28 | struct S { 29 | char *p; 30 | char a[4]; 31 | int i; 32 | }; 33 | struct S sarr[] = { 34 | "foobar", "baz", 11, 35 | ("xxx","foobaz"), (("bar")), 22, 36 | }; 37 | ASSERT(1, !strcmp("foobar", sarr[0].p) ); 38 | ASSERT(1, !strcmp("baz", sarr[0].a) ); 39 | ASSERT(1, !strcmp("foobaz", sarr[1].p) ); 40 | ASSERT(1, !strcmp("bar", sarr[1].a) ); 41 | 42 | printf("OK\n"); 43 | } 44 | -------------------------------------------------------------------------------- /test/struct.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(1, ({ struct {int a; int b;} x; x.a=1; x.b=2; x.a; })); 5 | ASSERT(2, ({ struct {int a; int b;} x; x.a=1; x.b=2; x.b; })); 6 | ASSERT(1, ({ struct {char a; int b; char c;} x; x.a=1; x.b=2; x.c=3; x.a; })); 7 | ASSERT(2, ({ struct {char a; int b; char c;} x; x.b=1; x.b=2; x.c=3; x.b; })); 8 | ASSERT(3, ({ struct {char a; int b; char c;} x; x.a=1; x.b=2; x.c=3; x.c; })); 9 | 10 | ASSERT(0, ({ struct {char a; char b;} x[3]; char *p=x; p[0]=0; x[0].a; })); 11 | ASSERT(1, ({ struct {char a; char b;} x[3]; char *p=x; p[1]=1; x[0].b; })); 12 | ASSERT(2, ({ struct {char a; char b;} x[3]; char *p=x; p[2]=2; x[1].a; })); 13 | ASSERT(3, ({ struct {char a; char b;} x[3]; char *p=x; p[3]=3; x[1].b; })); 14 | 15 | ASSERT(6, ({ struct {char a[3]; char b[5];} x; char *p=&x; x.a[0]=6; p[0]; })); 16 | ASSERT(7, ({ struct {char a[3]; char b[5];} x; char *p=&x; x.b[0]=7; p[3]; })); 17 | 18 | ASSERT(6, ({ struct { struct { char b; } a; } x; x.a.b=6; x.a.b; })); 19 | 20 | ASSERT(4, ({ struct {int a;} x; sizeof(x); })); 21 | ASSERT(8, ({ struct {int a; int b;} x; sizeof(x); })); 22 | ASSERT(8, ({ struct {int a, b;} x; sizeof(x); })); 23 | ASSERT(12, ({ struct {int a[3];} x; sizeof(x); })); 24 | ASSERT(16, ({ struct {int a;} x[4]; sizeof(x); })); 25 | ASSERT(24, ({ struct {int a[3];} x[2]; sizeof(x); })); 26 | ASSERT(2, ({ struct {char a; char b;} x; sizeof(x); })); 27 | ASSERT(0, ({ struct {} x; sizeof(x); })); 28 | ASSERT(8, ({ struct {char a; int b;} x; sizeof(x); })); 29 | ASSERT(8, ({ struct {int a; char b;} x; sizeof(x); })); 30 | 31 | ASSERT(8, ({ struct t {int a; int b;} x; struct t y; sizeof(y); })); 32 | ASSERT(8, ({ struct t {int a; int b;}; struct t y; sizeof(y); })); 33 | ASSERT(2, ({ struct t {char a[2];}; { struct t {char a[4];}; } struct t y; sizeof(y); })); 34 | ASSERT(3, ({ struct t {int x;}; int t=1; struct t y; y.x=2; t+y.x; })); 35 | 36 | ASSERT(3, ({ struct t {char a;} x; struct t *y = &x; x.a=3; y->a; })); 37 | ASSERT(3, ({ struct t {char a;} x; struct t *y = &x; y->a=3; x.a; })); 38 | 39 | ASSERT(3, ({ struct {int a,b;} x,y; x.a=3; y=x; y.a; })); 40 | ASSERT(7, ({ struct t {int a,b;}; struct t x; x.a=7; struct t y; struct t *z=&y; *z=x; y.a; })); 41 | ASSERT(7, ({ struct t {int a,b;}; struct t x; x.a=7; struct t y, *p=&x, *q=&y; *q=*p; y.a; })); 42 | ASSERT(5, ({ struct t {char a, b;} x, y; x.a=5; y=x; y.a; })); 43 | 44 | ASSERT(3, ({ struct {int a,b;} x,y; x.a=3; y=x; y.a; })); 45 | ASSERT(7, ({ struct t {int a,b;}; struct t x; x.a=7; struct t y; struct t *z=&y; *z=x; y.a; })); 46 | ASSERT(7, ({ struct t {int a,b;}; struct t x; x.a=7; struct t y, *p=&x, *q=&y; *q=*p; y.a; })); 47 | ASSERT(5, ({ struct t {char a, b;} x, y; x.a=5; y=x; y.a; })); 48 | 49 | ASSERT(8, ({ struct t {int a; int b;} x; struct t y; sizeof(y); })); 50 | ASSERT(8, ({ struct t {int a; int b;}; struct t y; sizeof(y); })); 51 | 52 | ASSERT(16, ({ struct {char a; long b;} x; sizeof(x); })); 53 | ASSERT(4, ({ struct {char a; short b;} x; sizeof(x); })); 54 | 55 | ASSERT(8, ({ struct foo *bar; sizeof(bar); })); 56 | ASSERT(4, ({ struct T *foo; struct T {int x;}; sizeof(struct T); })); 57 | ASSERT(1, ({ struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x; })); 58 | ASSERT(4, ({ typedef struct T T; struct T { int x; }; sizeof(T); })); 59 | 60 | ASSERT(2, ({ struct {int a;} x={1}, y={2}; (x=y).a; })); 61 | ASSERT(1, ({ struct {int a;} x={1}, y={2}; (1?x:y).a; })); 62 | ASSERT(2, ({ struct {int a;} x={1}, y={2}; (0?x:y).a; })); 63 | 64 | printf("OK\n"); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /test/tag_compat.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define TAG_COMPAT_CHK(_res, ...) \ 4 | static_assert(_res == _Generic( __VA_ARGS__ :1, default:0)) 5 | 6 | struct tag {int i;} tagged; 7 | struct {int i;} nontag; 8 | 9 | TAG_COMPAT_CHK(1, tagged, struct tag {int i;} ); 10 | TAG_COMPAT_CHK(0, tagged, struct {int i;} ); 11 | TAG_COMPAT_CHK(0, nontag, struct tag {int i;} ); 12 | TAG_COMPAT_CHK(0, nontag, struct {int i;} ); 13 | 14 | TAG_COMPAT_CHK(1, struct tag {int i;}, typeof(tagged) ); 15 | TAG_COMPAT_CHK(0, struct {int i;}, typeof(tagged) ); 16 | TAG_COMPAT_CHK(0, struct tag {int i;}, typeof(nontag) ); 17 | TAG_COMPAT_CHK(0, struct {int i;}, typeof(nontag) ); 18 | 19 | typedef 20 | struct tag {int i;} tagged_def; 21 | typedef 22 | struct {int i;} nontag_def; 23 | 24 | TAG_COMPAT_CHK(1, struct tag {int i;}, tagged_def ); 25 | TAG_COMPAT_CHK(0, struct {int i;}, tagged_def ); 26 | TAG_COMPAT_CHK(0, struct tag {int i;}, nontag_def ); 27 | TAG_COMPAT_CHK(0, struct {int i;}, nontag_def ); 28 | 29 | struct { struct tag {int i;} tagged; } inner_tagged; 30 | struct { struct {int i;} nontag; } inner_nontag; 31 | 32 | TAG_COMPAT_CHK(1, inner_tagged.tagged, struct tag {int i;} ); 33 | TAG_COMPAT_CHK(0, inner_tagged.tagged, struct {int i;} ); 34 | TAG_COMPAT_CHK(0, inner_nontag.nontag, struct tag {int i;} ); 35 | TAG_COMPAT_CHK(0, inner_nontag.nontag, struct {int i;} ); 36 | 37 | TAG_COMPAT_CHK(1, struct tag {int i;}, struct tag {int i;} ); 38 | 39 | TAG_COMPAT_CHK(1, struct t2 {int :3, i;}, struct t2 {int :3, i;} ); 40 | TAG_COMPAT_CHK(1, struct t3 {struct{int i;};}, struct t3 {struct{int i;};} ); 41 | TAG_COMPAT_CHK(1, struct t4 {struct t5{int i;} s;}, struct t4 {struct t5{int i;} s;} ); 42 | struct t6 {int i;} *p1; 43 | TAG_COMPAT_CHK(1, *p1, struct t6 {int i;} ); 44 | 45 | typedef struct t7 {int i;} t8; 46 | TAG_COMPAT_CHK(1, struct t7 {int i;}, struct t7 {int i;} ); 47 | typedef struct t7 {int i;} t8; 48 | TAG_COMPAT_CHK(1, t8, struct t7 {int i;} ); 49 | TAG_COMPAT_CHK(1, struct t7 {int i;}, t8 ); 50 | 51 | t8 s0; 52 | int assign(struct t7 {int i;} s1, t8 s2, struct t7 {int i;} s3) { 53 | s0 = s1; 54 | s1 = s2; 55 | s2 = s3; 56 | s3 = s0; 57 | return 1; 58 | } 59 | 60 | typedef const struct t7 {int i;} t9; 61 | TAG_COMPAT_CHK(0, struct t7 {int i;}, t9 ); 62 | TAG_COMPAT_CHK(1, const struct t7 {int i;}, t9 ); 63 | TAG_COMPAT_CHK(1, const t8, t9 ); 64 | TAG_COMPAT_CHK(1, t8, typeof_unqual(t9) ); 65 | 66 | int flexible(void) { 67 | typedef struct t10 {int i; int b[];} t11; 68 | t11 *flex = malloc(sizeof(t11) + 137 * sizeof(int)); 69 | struct t10 {int i; int b[];}* flex2 = malloc(sizeof(t11) + 321 * sizeof(int)); 70 | TAG_COMPAT_CHK(1, *flex, struct t10 {int i; int b[];} ); 71 | TAG_COMPAT_CHK(1, flex, typeof(flex2) ); 72 | free(flex), free(flex2); 73 | 74 | return 1; 75 | } 76 | 77 | struct list { struct list *next; }; 78 | TAG_COMPAT_CHK(1, struct lists { struct list lst; }, struct lists { struct list lst; } ); 79 | 80 | int main(void) { 81 | ASSERT(1, assign((t8){},(t8){},(t8){})); 82 | ASSERT(1, flexible()); 83 | 84 | printf("OK\n"); 85 | } 86 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define ASSERT(x, y) test_assert((int)(x), (int)(y), #y) 10 | #define SASSERT(x) static_assert(x,"") 11 | #define DASSERT(x) static_assert(x,""); ASSERT(1, x) 12 | #define EASSERT(x,y) do{static_assert((int)(x) == (int)(y),"");}while(0); ASSERT(x, y) 13 | 14 | #if defined(__slimcc__) || defined(__clang__) 15 | #define NOTGCC 16 | #endif 17 | #if defined(__slimcc__) || !defined(__clang__) 18 | #define NOTCLANG 19 | #endif 20 | 21 | extern 22 | #if defined __cplusplus 23 | "C" 24 | #endif 25 | void test_assert(int expected, int actual, char *code); 26 | -------------------------------------------------------------------------------- /test/tls.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | #include 4 | 5 | _Thread_local int v1; 6 | _Thread_local int v2 = 5; 7 | int v3 = 7; 8 | 9 | int thread_main(void *unused) { 10 | ASSERT(0, v1); 11 | ASSERT(5, v2); 12 | ASSERT(7, v3); 13 | 14 | v1 = 1; 15 | v2 = 2; 16 | v3 = 3; 17 | 18 | ASSERT(1, v1); 19 | ASSERT(2, v2); 20 | ASSERT(3, v3); 21 | 22 | return 0; 23 | } 24 | 25 | int main() { 26 | pthread_t thr; 27 | 28 | ASSERT(0, v1); 29 | ASSERT(5, v2); 30 | ASSERT(7, v3); 31 | 32 | ASSERT(0, pthread_create(&thr, NULL, thread_main, NULL)); 33 | ASSERT(0, pthread_join(thr, NULL)); 34 | 35 | ASSERT(0, v1); 36 | ASSERT(5, v2); 37 | ASSERT(3, v3); 38 | 39 | printf("OK\n"); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /test/tls2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | #include 4 | 5 | static _Thread_local int tentative_tls; 6 | static _Thread_local int tentative_tls = 3; 7 | 8 | extern _Thread_local int extern_tls; 9 | 10 | void *thread_main(void *unused) { 11 | 12 | static _Thread_local int v1; 13 | static _Thread_local int v2 = 5; 14 | int *p1 = &(static _Thread_local int){(int){11}}; 15 | 16 | ASSERT(0, v1); 17 | ASSERT(5, v2); 18 | ASSERT(11, *p1); 19 | 20 | ASSERT(3, tentative_tls); 21 | ASSERT(0, extern_tls); 22 | 23 | v1 = 1; 24 | v2 = 2; 25 | *p1 = 3; 26 | 27 | tentative_tls = 9; 28 | extern_tls = 7; 29 | 30 | ASSERT(1, v1); 31 | ASSERT(2, v2); 32 | ASSERT(3, *p1); 33 | 34 | ASSERT(9, tentative_tls); 35 | ASSERT(7, extern_tls); 36 | 37 | return NULL; 38 | } 39 | 40 | int main() { 41 | pthread_t thr1; 42 | pthread_t thr2; 43 | 44 | ASSERT(0, pthread_create(&thr1, NULL, thread_main, NULL)); 45 | 46 | thread_main(NULL); 47 | 48 | ASSERT(0, pthread_create(&thr2, NULL, thread_main, NULL)); 49 | 50 | ASSERT(0, pthread_join(thr1, NULL)); 51 | ASSERT(0, pthread_join(thr2, NULL)); 52 | 53 | printf("OK\n"); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /test/typedef.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | typedef int MyInt, MyInt2[4]; 4 | typedef int; 5 | 6 | int main() { 7 | ASSERT(1, ({ typedef int t; t x=1; x; })); 8 | ASSERT(1, ({ typedef struct {int a;} t; t x; x.a=1; x.a; })); 9 | ASSERT(1, ({ typedef int t; t t=1; t; })); 10 | ASSERT(2, ({ typedef struct {int a;} t; { typedef int t; } t x; x.a=2; x.a; })); 11 | ASSERT(4, ({ typedef t; t x; sizeof(x); })); 12 | ASSERT(3, ({ MyInt x=3; x; })); 13 | ASSERT(16, ({ MyInt2 x; sizeof(x); })); 14 | 15 | printf("OK\n"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/typedef2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main(void) { 4 | typedef struct S s0; 5 | typedef const struct S s1; 6 | typedef volatile struct S s2; 7 | typedef __attribute__((aligned(64))) struct S a0; 8 | 9 | SASSERT(__builtin_types_compatible_p(s0, s1)); 10 | SASSERT(__builtin_types_compatible_p(s0, s2)); 11 | SASSERT(__builtin_types_compatible_p(s1, s2)); 12 | SASSERT(__builtin_types_compatible_p(s0, a0)); 13 | 14 | typedef struct S *p0; 15 | typedef const struct S *p1; 16 | typedef s1 *p2; 17 | typedef const s0 *p3; 18 | 19 | SASSERT(!__builtin_types_compatible_p(p0, p1)); 20 | SASSERT(!__builtin_types_compatible_p(p0, p2)); 21 | SASSERT(!__builtin_types_compatible_p(p0, p3)); 22 | SASSERT(__builtin_types_compatible_p(p1, p2)); 23 | SASSERT(__builtin_types_compatible_p(p1, p3)); 24 | SASSERT(__builtin_types_compatible_p(p2, p3)); 25 | 26 | struct S { int i; }; 27 | 28 | SASSERT(__builtin_types_compatible_p(s0, s1)); 29 | SASSERT(__builtin_types_compatible_p(s0, s2)); 30 | SASSERT(__builtin_types_compatible_p(s1, s2)); 31 | SASSERT(__builtin_types_compatible_p(s0, a0)); 32 | SASSERT(_Alignof(s0) != _Alignof(a0)); 33 | 34 | SASSERT(!__builtin_types_compatible_p(p0, p1)); 35 | SASSERT(!__builtin_types_compatible_p(p0, p2)); 36 | SASSERT(!__builtin_types_compatible_p(p0, p3)); 37 | SASSERT(__builtin_types_compatible_p(p1, p2)); 38 | SASSERT(__builtin_types_compatible_p(p1, p3)); 39 | SASSERT(__builtin_types_compatible_p(p2, p3)); 40 | 41 | typedef struct S s3; 42 | typedef s0 s4; 43 | typedef __attribute__((aligned(64))) s0 a1; 44 | 45 | SASSERT(__builtin_types_compatible_p(s3, s4)); 46 | SASSERT(__builtin_types_compatible_p(s3, a1)); 47 | SASSERT(__builtin_types_compatible_p(a0, a1)); 48 | SASSERT(_Alignof(s0) != _Alignof(a1)); 49 | SASSERT(_Alignof(a0) == _Alignof(a1)); 50 | 51 | SASSERT(sizeof(s0) > 0); 52 | SASSERT(sizeof(s1) > 0); 53 | SASSERT(sizeof(s2) > 0); 54 | SASSERT(sizeof(s3) > 0); 55 | SASSERT(sizeof(s4) > 0); 56 | 57 | SASSERT(sizeof(*(p0){0}) > 0); 58 | SASSERT(sizeof(*(p1){0}) > 0); 59 | SASSERT(sizeof(*(p2){0}) > 0); 60 | SASSERT(sizeof(*(p3){0}) > 0); 61 | 62 | SASSERT(sizeof(a0) > 0); 63 | SASSERT(sizeof(a1) > 0); 64 | 65 | typedef struct FS fs0; 66 | struct FS { int i; char arr[]; }; 67 | typedef struct FS fs1; 68 | static fs0 fs00 = {1,2}; 69 | static fs0 fs01 = {1,2,3}; 70 | static fs1 fs10 = {1,2,3}; 71 | static fs1 fs11 = {1,2,3,4}; 72 | SASSERT(_Generic(fs00, struct FS: 1)); 73 | SASSERT(_Generic(fs01, struct FS: 1)); 74 | SASSERT(_Generic(fs10, struct FS: 1)); 75 | SASSERT(_Generic(fs11, struct FS: 1)); 76 | SASSERT(sizeof(fs00) > 0); 77 | SASSERT(sizeof(fs10) > 0); 78 | SASSERT(sizeof(fs01) > 0); 79 | SASSERT(sizeof(fs11) > 0); 80 | 81 | #define A __attribute__((aligned(1024))) 82 | ASSERT(1024, ({ A typedef struct s S; struct s { char c; }; _Alignof(S); })); 83 | ASSERT(1024, ({ typedef A struct s S; struct s { char c; }; _Alignof(S); })); 84 | ASSERT(1, ({ typedef struct A s S; struct s { char c; }; _Alignof(S); })); // clang: 1024 85 | ASSERT(1024, ({ typedef struct s A S; struct s { char c; }; _Alignof(S); })); 86 | ASSERT(1024, ({ typedef struct s S A; struct s { char c; }; _Alignof(S); })); 87 | ASSERT(1, ({ typedef struct s S; A struct s { char c; }; _Alignof(S); })); 88 | ASSERT(1024, ({ typedef struct s S; struct A s { char c; }; _Alignof(S); })); 89 | ASSERT(1024, ({ typedef struct s S; struct s { A char c; }; _Alignof(S); })); 90 | ASSERT(1024, ({ typedef struct s S; struct s { char A c; }; _Alignof(S); })); 91 | ASSERT(1024, ({ typedef struct s S; struct s { char c A; }; _Alignof(S); })); 92 | ASSERT(1024, ({ typedef struct s S; struct s { char c; } A; _Alignof(S); })); 93 | 94 | #define A2 __attribute__((aligned(2048))) 95 | ASSERT(2048, ({ typedef struct s S A; struct s { char c; } A2; _Alignof(S); })); // clang: 1024 96 | ASSERT(2048, ({ typedef struct s S A2; struct s { char c; } A; _Alignof(S); })); 97 | 98 | #define P __attribute__((packed)) 99 | ASSERT(8, ({ typedef struct P s S; struct s { char c; int i; }; sizeof(S); })); // clang: 5 100 | ASSERT(5, ({ typedef struct s S; struct P s { char c; int i; }; sizeof(S); })); 101 | ASSERT(5, ({ typedef struct s S; struct s { char c; int i; } P; sizeof(S); })); 102 | 103 | printf("OK\n"); 104 | return 0; 105 | } 106 | 107 | -------------------------------------------------------------------------------- /test/typeof.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(3, ({ typeof(int) x=3; x; })); 5 | ASSERT(3, ({ typeof(1) x=3; x; })); 6 | ASSERT(4, ({ int x; typeof(x) y; sizeof(y); })); 7 | ASSERT(8, ({ int x; typeof(&x) y; sizeof(y); })); 8 | ASSERT(4, ({ typeof("foo") x; sizeof(x); })); 9 | ASSERT(12, sizeof(typeof(struct { int a,b,c; }))); 10 | 11 | printf("OK\n"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /test/typeof_unqual.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) { 4 | const int i1; 5 | typeof_unqual(i1) i2; 6 | 7 | SASSERT(!__builtin_types_compatible_p(typeof(&i1), int *)); 8 | SASSERT(__builtin_types_compatible_p(typeof(&i1), int const*)); 9 | 10 | SASSERT(__builtin_types_compatible_p(typeof(&i2), int *)); 11 | SASSERT(!__builtin_types_compatible_p(typeof(&i2), int const*)); 12 | 13 | printf("OK\n"); 14 | } 15 | -------------------------------------------------------------------------------- /test/unicode.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #define STR(x) #x 4 | 5 | typedef unsigned short char16_t; 6 | typedef unsigned int char32_t; 7 | typedef int wchar_t; 8 | 9 | int π = 3; 10 | 11 | int main() { 12 | ASSERT(4, sizeof(L'\0')); 13 | ASSERT(97, L'a'); 14 | 15 | ASSERT(0, strcmp("αβγ", "\u03B1\u03B2\u03B3")); 16 | ASSERT(0, strcmp("日本語", "\u65E5\u672C\u8A9E")); 17 | ASSERT(0, strcmp("日本語", "\U000065E5\U0000672C\U00008A9E")); 18 | ASSERT(0, strcmp("🌮", "\U0001F32E")); 19 | 20 | ASSERT(-1, L'\xffffffff'>>31); 21 | ASSERT(946, L'β'); 22 | ASSERT(12354, L'あ'); 23 | ASSERT(127843, L'🍣'); 24 | 25 | ASSERT(2, sizeof(u'\0')); 26 | ASSERT(1, u'\xffff'>>15); 27 | ASSERT(97, u'a'); 28 | ASSERT(946, u'β'); 29 | ASSERT(12354, u'あ'); 30 | ASSERT(62307, u'🍣'); 31 | 32 | ASSERT(0, strcmp(STR(u'a'), "u'a'")); 33 | 34 | ASSERT(4, sizeof(U'\0')); 35 | ASSERT(1, U'\xffffffff'>>31); 36 | ASSERT(97, U'a'); 37 | ASSERT(946, U'β'); 38 | ASSERT(12354, U'あ'); 39 | ASSERT(127843, U'🍣'); 40 | 41 | ASSERT(0, strcmp(STR(U'a'), "U'a'")); 42 | 43 | ASSERT(4, sizeof(u8"abc")); 44 | ASSERT(0, strcmp(u8"abc", "abc")); 45 | 46 | ASSERT(0, strcmp(STR(u8"a"), "u8\"a\"")); 47 | 48 | ASSERT(2, sizeof(u"")); 49 | ASSERT(10, sizeof(u"\xffzzz")); 50 | ASSERT(0, memcmp(u"", "\0\0", 2)); 51 | ASSERT(0, memcmp(u"abc", "a\0b\0c\0\0\0", 8)); 52 | ASSERT(0, memcmp(u"日本語", "\345e,g\236\212\0\0", 8)); 53 | ASSERT(0, memcmp(u"🍣", "<\330c\337\0\0", 6)); 54 | ASSERT(u'β', u"βb"[0]); 55 | ASSERT(u'b', u"βb"[1]); 56 | ASSERT(0, u"βb"[2]); 57 | 58 | ASSERT(0, strcmp(STR(u"a"), "u\"a\"")); 59 | 60 | ASSERT(4, sizeof(U"")); 61 | ASSERT(20, sizeof(U"\xffzzz")); 62 | ASSERT(0, memcmp(U"", "\0\0\0\0", 4)); 63 | ASSERT(0, memcmp(U"abc", "a\0\0\0b\0\0\0c\0\0\0\0\0\0\0", 16)); 64 | ASSERT(0, memcmp(U"日本語", "\345e\0\0,g\0\0\236\212\0\0\0\0\0\0", 16)); 65 | ASSERT(0, memcmp(U"🍣", "c\363\001\0\0\0\0\0", 8)); 66 | ASSERT(u'β', U"βb"[0]); 67 | ASSERT(u'b', U"βb"[1]); 68 | ASSERT(0, U"βb"[2]); 69 | ASSERT(1, U"\xffffffff"[0] >> 31); 70 | 71 | ASSERT(0, strcmp(STR(U"a"), "U\"a\"")); 72 | 73 | ASSERT(4, sizeof(L"")); 74 | ASSERT(20, sizeof(L"\xffzzz")); 75 | ASSERT(0, memcmp(L"", "\0\0\0\0", 4)); 76 | ASSERT(0, memcmp(L"abc", "a\0\0\0b\0\0\0c\0\0\0\0\0\0\0", 16)); 77 | ASSERT(0, memcmp(L"日本語", "\345e\0\0,g\0\0\236\212\0\0\0\0\0\0", 16)); 78 | ASSERT(0, memcmp(L"🍣", "c\363\001\0\0\0\0\0", 8)); 79 | ASSERT(u'β', L"βb"[0]); 80 | ASSERT(u'b', L"βb"[1]); 81 | ASSERT(0, L"βb"[2]); 82 | ASSERT(-1, L"\xffffffff"[0] >> 31); 83 | 84 | ASSERT(0, strcmp(STR(L"a"), "L\"a\"")); 85 | 86 | ASSERT(u'α', ({ char16_t x[] = u"αβ"; x[0]; })); 87 | ASSERT(u'β', ({ char16_t x[] = u"αβ"; x[1]; })); 88 | ASSERT(6, ({ char16_t x[] = u"αβ"; sizeof(x); })); 89 | 90 | ASSERT(U'🤔', ({ char32_t x[] = U"🤔x"; x[0]; })); 91 | ASSERT(U'x', ({ char32_t x[] = U"🤔x"; x[1]; })); 92 | ASSERT(12, ({ char32_t x[] = U"🤔x"; sizeof(x); })); 93 | 94 | ASSERT(L'🤔', ({ wchar_t x[] = L"🤔x"; x[0]; })); 95 | ASSERT(L'x', ({ wchar_t x[] = L"🤔x"; x[1]; })); 96 | ASSERT(12, ({ wchar_t x[] = L"🤔x"; sizeof(x); })); 97 | 98 | ASSERT(3, π); 99 | ASSERT(3, ({ int あβ0µ=3; あβ0µ; })); 100 | ASSERT(5, ({ int $$$=5; $$$; })); 101 | 102 | printf("OK\n"); 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /test/unicode2.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | 4 | int main(void) { 5 | DASSERT(u8'a' == 'a'); 6 | SASSERT(_Generic(u8'b', unsigned char:1)); 7 | 8 | printf("OK\n"); 9 | } 10 | -------------------------------------------------------------------------------- /test/union.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(8, ({ union { int a; char b[6]; } x; sizeof(x); })); 5 | ASSERT(3, ({ union { int a; char b[4]; } x; x.a = 515; x.b[0]; })); 6 | ASSERT(2, ({ union { int a; char b[4]; } x; x.a = 515; x.b[1]; })); 7 | ASSERT(0, ({ union { int a; char b[4]; } x; x.a = 515; x.b[2]; })); 8 | ASSERT(0, ({ union { int a; char b[4]; } x; x.a = 515; x.b[3]; })); 9 | 10 | ASSERT(3, ({ union {int a,b;} x,y; x.a=3; y.a=5; y=x; y.a; })); 11 | ASSERT(3, ({ union {struct {int a,b;} c;} x,y; x.c.b=3; y.c.b=5; y=x; y.c.b; })); 12 | 13 | ASSERT(0xef, ({ union { struct { unsigned char a,b,c,d; }; long e; } x; x.e=0xdeadbeef; x.a; })); 14 | ASSERT(0xbe, ({ union { struct { unsigned char a,b,c,d; }; long e; } x; x.e=0xdeadbeef; x.b; })); 15 | ASSERT(0xad, ({ union { struct { unsigned char a,b,c,d; }; long e; } x; x.e=0xdeadbeef; x.c; })); 16 | ASSERT(0xde, ({ union { struct { unsigned char a,b,c,d; }; long e; } x; x.e=0xdeadbeef; x.d; })); 17 | 18 | ASSERT(3, ({struct { union { int a,b; }; union { int c,d; }; } x; x.a=3; x.b; })); 19 | ASSERT(5, ({struct { union { int a,b; }; union { int c,d; }; } x; x.d=5; x.c; })); 20 | 21 | printf("OK\n"); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /test/usualconv.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | static int ret10(void) { return 10; } 4 | 5 | int main() { 6 | EASSERT((long)-5, -10 + (long)5); 7 | EASSERT((long)-15, -10 - (long)5); 8 | EASSERT((long)-50, -10 * (long)5); 9 | EASSERT((long)-2, -10 / (long)5); 10 | 11 | EASSERT(1, -2 < (long)-1); 12 | EASSERT(1, -2 <= (long)-1); 13 | EASSERT(0, -2 > (long)-1); 14 | EASSERT(0, -2 >= (long)-1); 15 | 16 | EASSERT(1, (long)-2 < -1); 17 | EASSERT(1, (long)-2 <= -1); 18 | EASSERT(0, (long)-2 > -1); 19 | EASSERT(0, (long)-2 >= -1); 20 | 21 | EASSERT(0, 2147483647 + 2147483647 + 2); 22 | ASSERT((long)-1, ({ long x; x=-1; x; })); 23 | 24 | ASSERT(1, ({ char x[3]; x[0]=0; x[1]=1; x[2]=2; char *y=x+1; y[0]; })); 25 | ASSERT(0, ({ char x[3]; x[0]=0; x[1]=1; x[2]=2; char *y=x+1; y[-1]; })); 26 | ASSERT(5, ({ struct t {char a;} x, y; x.a=5; y=x; y.a; })); 27 | 28 | ASSERT(10, (1 ? ret10 : (void *)0)()); 29 | 30 | printf("OK\n"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /test/varargs.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | int sum1(int x, ...) { 5 | va_list ap; 6 | va_start(ap, x); 7 | 8 | for (;;) { 9 | int y = va_arg(ap, int); 10 | if (y == 0) 11 | return x; 12 | x += y; 13 | } 14 | } 15 | 16 | int sum2(int x, ...) { 17 | va_list ap; 18 | va_start(ap, x); 19 | 20 | for (;;) { 21 | double y = va_arg(ap, double); 22 | x += y; 23 | 24 | int z = va_arg(ap, int); 25 | if (z == 0) 26 | return x; 27 | x += z; 28 | } 29 | } 30 | 31 | void fmt(char *buf, char *fmt, ...) { 32 | va_list ap; 33 | va_start(ap, fmt); 34 | 35 | va_list ap2; 36 | va_copy(ap2, ap); 37 | vsprintf(buf, fmt, ap2); 38 | va_end(buf); 39 | } 40 | 41 | int main() { 42 | ASSERT(6, sum1(1, 2, 3, 0)); 43 | ASSERT(55, sum1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0)); 44 | ASSERT(21, sum2(1, 2.0, 3, 4.0, 5, 6.0, 0)); 45 | ASSERT(21, sum2(1, 2.0, 3, 4.0, 5, 6.0, 0)); 46 | ASSERT(210, sum2(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0, 15, 16.0, 17, 18.0, 19, 20.0, 0)); 47 | ASSERT(0, ({ char buf[100]; fmt(buf, "%d %d", 2, 3); strcmp(buf, "2 3"); })); 48 | 49 | printf("OK\n"); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /test/variable.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int g1, g2[4]; 4 | static int g3 = 3; 5 | 6 | int main() { 7 | ASSERT(3, ({ int a; a=3; a; })); 8 | ASSERT(3, ({ int a=3; a; })); 9 | ASSERT(8, ({ int a=3; int z=5; a+z; })); 10 | 11 | ASSERT(3, ({ int a=3; a; })); 12 | ASSERT(8, ({ int a=3; int z=5; a+z; })); 13 | ASSERT(6, ({ int a; int b; a=b=3; a+b; })); 14 | ASSERT(3, ({ int foo=3; foo; })); 15 | ASSERT(8, ({ int foo123=3; int bar=5; foo123+bar; })); 16 | 17 | ASSERT(4, ({ int x; sizeof(x); })); 18 | ASSERT(4, ({ int x; sizeof x; })); 19 | ASSERT(8, ({ int *x; sizeof(x); })); 20 | ASSERT(16, ({ int x[4]; sizeof(x); })); 21 | ASSERT(48, ({ int x[3][4]; sizeof(x); })); 22 | ASSERT(16, ({ int x[3][4]; sizeof(*x); })); 23 | ASSERT(4, ({ int x[3][4]; sizeof(**x); })); 24 | ASSERT(5, ({ int x[3][4]; sizeof(**x) + 1; })); 25 | ASSERT(5, ({ int x[3][4]; sizeof **x + 1; })); 26 | ASSERT(4, ({ int x[3][4]; sizeof(**x + 1); })); 27 | ASSERT(4, ({ int x=1; sizeof(x=2); })); 28 | ASSERT(1, ({ int x=1; sizeof(x=2); x; })); 29 | 30 | ASSERT(0, g1); 31 | ASSERT(3, ({ g1=3; g1; })); 32 | ASSERT(0, ({ g2[0]=0; g2[1]=1; g2[2]=2; g2[3]=3; g2[0]; })); 33 | ASSERT(1, ({ g2[0]=0; g2[1]=1; g2[2]=2; g2[3]=3; g2[1]; })); 34 | ASSERT(2, ({ g2[0]=0; g2[1]=1; g2[2]=2; g2[3]=3; g2[2]; })); 35 | ASSERT(3, ({ g2[0]=0; g2[1]=1; g2[2]=2; g2[3]=3; g2[3]; })); 36 | 37 | ASSERT(4, sizeof(g1)); 38 | ASSERT(16, sizeof(g2)); 39 | 40 | ASSERT(1, ({ char x=1; x; })); 41 | ASSERT(1, ({ char x=1; char y=2; x; })); 42 | ASSERT(2, ({ char x=1; char y=2; y; })); 43 | 44 | ASSERT(1, ({ char x; sizeof(x); })); 45 | ASSERT(10, ({ char x[10]; sizeof(x); })); 46 | 47 | ASSERT(2, ({ int x=2; { int x=3; } x; })); 48 | ASSERT(2, ({ int x=2; { int x=3; } int y=4; x; })); 49 | ASSERT(3, ({ int x=2; { x=3; } x; })); 50 | 51 | ASSERT(7, ({ int x; int y; char z; char *a=&y; char *b=&z; b-a; })); 52 | ASSERT(1, ({ int x; char y; int z; char *a=&y; char *b=&z; b-a; })); 53 | 54 | ASSERT(8, ({ long x; sizeof(x); })); 55 | ASSERT(2, ({ short x; sizeof(x); })); 56 | 57 | ASSERT(24, ({ char *x[3]; sizeof(x); })); 58 | ASSERT(8, ({ char (*x)[3]; sizeof(x); })); 59 | ASSERT(1, ({ char (x); sizeof(x); })); 60 | ASSERT(3, ({ char (x)[3]; sizeof(x); })); 61 | ASSERT(12, ({ char (x[3])[4]; sizeof(x); })); 62 | ASSERT(4, ({ char (x[3])[4]; sizeof(x[0]); })); 63 | ASSERT(3, ({ char *x[3]; char y; x[0]=&y; y=3; x[0][0]; })); 64 | ASSERT(4, ({ char x[3]; char (*y)[3]=x; y[0][0]=4; y[0][0]; })); 65 | 66 | { void *x; } 67 | 68 | ASSERT(3, g3); 69 | 70 | printf("OK\n"); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /test/vla.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int main() { 4 | ASSERT(20, ({ int n=5; int x[n]; sizeof(x); })); 5 | ASSERT((5+1)*(8*2)*4, ({ int m=5, n=8; int x[m+1][n*2]; sizeof(x); })); 6 | 7 | ASSERT(8, ({ char n=10; int (*x)[n][n+2]; sizeof(x); })); 8 | ASSERT(480, ({ char n=10; int (*x)[n][n+2]; sizeof(*x); })); 9 | ASSERT(48, ({ char n=10; int (*x)[n][n+2]; sizeof(**x); })); 10 | ASSERT(4, ({ char n=10; int (*x)[n][n+2]; sizeof(***x); })); 11 | 12 | ASSERT(60, ({ char n=3; int x[5][n]; sizeof(x); })); 13 | ASSERT(12, ({ char n=3; int x[5][n]; sizeof(*x); })); 14 | 15 | ASSERT(60, ({ char n=3; int x[n][5]; sizeof(x); })); 16 | ASSERT(20, ({ char n=3; int x[n][5]; sizeof(*x); })); 17 | 18 | ASSERT(0, ({ int n=10; int x[n+1][n+6]; int *p=x; for (int i = 0; i 3 | 4 | void fn(int32_t x){ 5 | typedef int32_t A[++x], B[++x]; 6 | A a1, *a2; 7 | ASSERT(24, sizeof(a1)); 8 | ASSERT(24, sizeof(*a2)); 9 | 10 | x = 17; 11 | B b1[x++], *b2; 12 | ASSERT(18, x); 13 | ASSERT(476, sizeof(b1)); 14 | ASSERT(28, sizeof(*b1)); 15 | ASSERT(28, sizeof(*b2)); 16 | 17 | typedef int32_t (*C)[++x]; 18 | ASSERT(19, x); 19 | C c1[++x], c2; 20 | ASSERT(20, x); 21 | ASSERT(160, sizeof(c1)); 22 | ASSERT(8, sizeof(*c1)); 23 | ASSERT(76, sizeof(**c1)); 24 | ASSERT(76, sizeof(*c2)); 25 | 26 | typedef int8_t D[x = 177]; 27 | D a; 28 | x = 7; 29 | D b; 30 | D c; 31 | 32 | ASSERT(192, (&a[0] - &b[0])); 33 | ASSERT(192, (&b[0] - &c[0])); 34 | } 35 | 36 | int fn2(int32_t i) { 37 | static int32_t (*p)[i]; 38 | return sizeof *p; 39 | } 40 | 41 | int fn3(int i) { 42 | typedef int32_t (*T)[i]; 43 | static T t; 44 | return sizeof *t; 45 | } 46 | 47 | int fn4(int i){ 48 | return sizeof(*(char(*)[i+7]){0}); 49 | } 50 | 51 | int zinit(int cnt) { 52 | { 53 | int a[cnt*100]; 54 | for (int i = 0; i < 100; i++) 55 | a[i] = -1; 56 | } 57 | { 58 | int a[cnt*100] = {}; 59 | int chk = 0; 60 | 61 | for (int i = 0; i < 100; i++) 62 | chk |= a[i]; 63 | 64 | ASSERT(0, chk); 65 | } 66 | return 1; 67 | } 68 | 69 | int main(void){ 70 | fn(5); 71 | 72 | ASSERT(12, fn2(3)); 73 | ASSERT(28, fn2(7)); 74 | 75 | ASSERT(44, fn3(11)); 76 | ASSERT(52, fn3(13)); 77 | 78 | ASSERT(14, fn4(7)); 79 | 80 | ASSERT(1, zinit(1)); 81 | 82 | printf("OK\n"); 83 | } 84 | -------------------------------------------------------------------------------- /test/vla_dealloc.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #define STRINGIFY2(x) #x 3 | #define STRINGIFY(x) STRINGIFY2(x) 4 | #define ASSERTL(x, y) test_assert(x, y, #y " line:" STRINGIFY(__LINE__)) 5 | 6 | int main(int argc, char** argv) { 7 | 8 | void *lv1, *lv2; 9 | { 10 | int vla[argc], vla2[argc]; 11 | lv1 = vla; 12 | lv2 = vla2; 13 | } 14 | { 15 | int vla[argc], vla2[argc]; 16 | ASSERTL(1, lv1 == vla); 17 | ASSERTL(1, lv2 == vla2); 18 | } 19 | 20 | { 21 | int i = 0; 22 | goto1:; 23 | int vla1[argc]; 24 | int vla2[argc]; 25 | ASSERTL(1, lv1 == vla1); 26 | ASSERTL(1, lv2 == vla2); 27 | if (i++ != argc) 28 | goto goto1; 29 | } 30 | 31 | { 32 | int i = 0; 33 | int vla1[argc]; 34 | ASSERTL(1, lv1 == vla1); 35 | { 36 | goto2:; 37 | int vla2[argc]; 38 | ASSERTL(1, lv2 == vla2); 39 | if (i++ != argc) 40 | goto goto2; 41 | else 42 | goto goto3; 43 | } 44 | goto3:; 45 | int vla2[argc]; 46 | ASSERTL(1, lv2 == vla2); 47 | } 48 | 49 | switch(argc) { 50 | default:; { 51 | int vla1[argc]; 52 | ASSERTL(1, lv1 == vla1); 53 | } 54 | int vla1[argc]; 55 | ASSERTL(1, lv1 == vla1); 56 | { 57 | int vla2[argc]; 58 | ASSERTL(1, lv2 == vla2); 59 | } 60 | int vla2[argc]; 61 | ASSERTL(1, lv2 == vla2); 62 | break; 63 | } 64 | 65 | int swctl = 0; 66 | goto4:; 67 | switch(swctl) { 68 | case 0: { 69 | int vla1[argc]; 70 | ASSERTL(1, lv1 == vla1); 71 | } 72 | case 1: { 73 | int vla1[argc]; 74 | ASSERTL(1, lv1 == vla1); 75 | swctl++; 76 | switch (swctl) { 77 | case 1: { 78 | int vla2[argc]; 79 | ASSERTL(1, lv2 == vla2); 80 | } 81 | case 2:; 82 | int vla2[argc]; 83 | ASSERTL(1, lv2 == vla2); 84 | if(swctl == 1) 85 | goto goto4; 86 | } 87 | int vla2[argc]; 88 | ASSERTL(1, lv2 == vla2); 89 | break; 90 | } 91 | default:; 92 | swctl++; 93 | int vla1[argc]; 94 | int vla2[argc]; 95 | ASSERTL(1, lv1 == vla1); 96 | ASSERTL(1, lv2 == vla2); 97 | } 98 | if (swctl == 2) 99 | goto goto4; 100 | 101 | switch(argc) { 102 | default: { 103 | int vla1[argc]; 104 | int vla2[argc]; 105 | ASSERTL(1, lv1 == vla1); 106 | ASSERTL(1, lv2 == vla2); 107 | break; 108 | } 109 | } 110 | 111 | 112 | int w0 = 0; 113 | while (w0++ != argc+1){ 114 | int vla1[argc]; 115 | int vla2[argc]; 116 | ASSERTL(1, lv1 == vla1); 117 | ASSERTL(1, lv2 == vla2); 118 | } 119 | 120 | int d0 = 0; 121 | do { 122 | int vla1[argc]; 123 | int vla2[argc]; 124 | ASSERTL(1, lv1 == vla1); 125 | ASSERTL(1, lv2 == vla2); 126 | } while (d0++ != argc+1); 127 | 128 | int i0 = 0; 129 | for (int vla1[argc]; i0 != argc+1; i0++){ 130 | ASSERTL(1, lv1 == vla1); 131 | int vla2[argc]; 132 | ASSERTL(1, lv2 == vla2); 133 | } 134 | 135 | int i1 = 0; 136 | for (int vla1[argc];; i1++){ 137 | ASSERTL(1, lv1 == vla1); 138 | int vla2[argc]; 139 | ASSERTL(1, lv2 == vla2); 140 | if (i1 != argc+1) 141 | continue; 142 | else 143 | break; 144 | } 145 | 146 | for (int i = 0;; i++){ 147 | int vla1[argc]; 148 | ASSERTL(1, lv1 == vla1); 149 | switch (i) { 150 | case 0: 151 | case 2: 152 | continue; 153 | case 1: 154 | case 3: 155 | int vla2[argc]; 156 | ASSERTL(1, lv2 == vla2); 157 | continue; 158 | } 159 | break; 160 | } 161 | 162 | ASSERTL(1, ({int vla1[argc]; vla1;}) == lv1); 163 | ASSERTL(1, ({int vla1[argc], vla2[argc]; vla2; }) == lv2); 164 | 165 | ASSERTL(1, ({int vla1[argc]; vla1;}) == ({int vla1[argc]; &vla1[0];}) ); 166 | 167 | int vla1[argc], vla2[argc]; 168 | ASSERTL(1, lv1 == vla1); 169 | ASSERTL(1, lv2 == vla2); 170 | 171 | printf("OK\n"); 172 | return 0; 173 | } 174 | -------------------------------------------------------------------------------- /test/vla_params.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | typedef int32_t i32; 4 | typedef uint8_t u8; 5 | 6 | void fn1(i32 z, i32 a[z], i32 b1[sizeof(a)], i32 (*b2)[sizeof(a)]){ 7 | ASSERT(8, sizeof(a)); 8 | ASSERT(8, sizeof(b1)); 9 | ASSERT(32, sizeof(*b2)); 10 | } 11 | 12 | void fn2(i32 z, i32 (*a)[z], i32 b1[sizeof(*a)], i32 (*b2)[sizeof(*a)]){ 13 | ASSERT(28, sizeof(*a)); 14 | ASSERT(8, sizeof(b1)); 15 | ASSERT(112, sizeof(*b2)); 16 | } 17 | 18 | void fn3(i32 x, i32 y, u8 arr[++y][(x+=2,x)]){ 19 | ASSERT(9, x); 20 | ASSERT(12, y); 21 | ASSERT(8, sizeof arr); 22 | ASSERT(9, sizeof *arr); 23 | } 24 | 25 | void fn4(i32 x,i32,i32 y,i32,i32,i32 z,i32 a[x+y][y+z][z+x]) { 26 | ASSERT(8, sizeof(a)); 27 | ASSERT(1008, sizeof(a[0])); 28 | ASSERT(56, sizeof(a[0][0])); 29 | } 30 | 31 | int max(i32 a, i32 b) { 32 | return a > b ? a : b; 33 | } 34 | int fn5(i32 x, i32 y, i32 (*z) [max(x, y)]) { 35 | return sizeof *z; 36 | } 37 | 38 | int g; 39 | void fn6(i32 x, i32 (*a)[g += x], i32 y, i32(*b)[sizeof(*a) + y], i32 (*c)[sizeof(*b) + g], i32 as, i32 bs, i32 cs){ 40 | ASSERT(as, sizeof(*a)); 41 | ASSERT(bs, sizeof(*b)); 42 | ASSERT(cs, sizeof(*c)); 43 | } 44 | 45 | void fn7(i32 *x, i32(*a)[*(++x)], i32(*b)[*(++x)] ) { 46 | ASSERT(88, sizeof(*a)); 47 | ASSERT(132, sizeof(*b)); 48 | } 49 | 50 | void fn8(i32 x, i32 (*a)[sizeof(u8[x])], i32 (*b)[sizeof(*a)+sizeof(u8[sizeof(*a)+sizeof(u8[x])])]) { 51 | ASSERT(468, sizeof(*b)); 52 | ASSERT(52, sizeof(*a)); 53 | } 54 | 55 | void fn9(char* str, int b, i32 (*arr)[b == strcmp(str, "FOOBAR")]) { 56 | ASSERT(4, sizeof *arr); 57 | } 58 | 59 | _Bool z = 1; 60 | 61 | void 62 | fn_oldstyle(a, b, c, d, z) 63 | float c; 64 | uint8_t b,d; 65 | int16_t (*a)[++b][(__typeof__(b))c][d++]; 66 | { 67 | ASSERT(720, sizeof(*a)); 68 | ASSERT(144, sizeof((*a)[0])); 69 | ASSERT(16, sizeof((*a)[1][2])); 70 | ASSERT(2, sizeof((*a)[1][2][3])); 71 | 72 | z = c; 73 | ASSERT(5, b); 74 | ASSERT(9, d); 75 | ASSERT(777, z); 76 | } 77 | 78 | int main(void){ 79 | fn1(7,0,0,0); 80 | fn2(7,0,0,0); 81 | fn3(7,11,0); 82 | fn4(3,0,7,0,0,11,0); 83 | ASSERT(28, fn5(3, 7, 0)); 84 | ASSERT(44, fn5(11, 5, 0)); 85 | g = 13; 86 | fn6(11,0,7,0,0,96,412,1744); 87 | g = 3; 88 | fn6(11,0,7,0,0,56,252,1064); 89 | i32 arr[3] = {11,22,33}; 90 | fn7((void*)&arr, 0, 0); 91 | fn8(13, 0, 0); 92 | fn9("FOOBAR", 0, 0); 93 | 94 | double f = 777.0; 95 | fn_oldstyle(0,260,f,264); 96 | 97 | printf("OK\n"); 98 | } 99 | --------------------------------------------------------------------------------