├── test ├── cases │ ├── embed │ │ ├── empty │ │ ├── embed byte │ │ └── embed data │ ├── expanded │ │ ├── #elifdef.c │ │ ├── nested #ifs.c │ │ ├── #elifndef.c │ │ ├── #ifdef.c │ │ ├── lazy macro.c │ │ ├── nested macro call.c │ │ ├── recursive func macro.c │ │ ├── unspecified expansion.c │ │ ├── #if constant expression.c │ │ ├── debug dump macros.c │ │ ├── line counter.c │ │ ├── paste operator whitespace.c │ │ ├── recursive object macro.c │ │ ├── stringify invalid escape.c │ │ ├── macro expansion exhaustion.c │ │ ├── object macro token pasting.c │ │ ├── deferred macro expansion.c │ │ ├── digraph pretty print.c │ │ ├── empty variadic paste.c │ │ ├── macro self definition.c │ │ ├── macro unbalanced parens call.c │ │ ├── object macro expansion.c │ │ ├── recursive call non-expanded parens.c │ │ ├── __has_attribute with define.c │ │ ├── empty macro block expansion.c │ │ ├── empty va args comma delete c99.c │ │ ├── gnu variadic macros.c │ │ ├── var args macro functions.c │ │ ├── macro expansion disabled.c │ │ ├── macro token pasting order.c │ │ ├── placeholder tokens pasting.c │ │ ├── source epoch.c │ │ ├── whitespace macro arguments.c │ │ ├── function macro expansion.c │ │ ├── multiline comment.c │ │ ├── standard-placeholder-example.c │ │ ├── debug dump macro names.c │ │ ├── X macro.c │ │ ├── macro whitespace.c │ │ ├── macro expands to self after pasting.c │ │ ├── debug dump macros and results.c │ │ ├── preserve comments.c │ │ ├── macro re-expansion.c │ │ ├── token paste delete comma gnu.c │ │ ├── standard-redefinition-reexamination-example.c │ │ ├── standard-concatenation-strings-example.c │ │ ├── __line__.c │ │ ├── float header netbsd 6.99.26.c │ │ ├── float header x86-64-linux.c │ │ └── float header aarch64-linux-gnu.c │ ├── include │ │ ├── global_var.h │ │ ├── iquote │ │ │ └── iquote_test.h │ │ ├── next │ │ │ ├── my_include.h │ │ │ ├── same_name.h │ │ │ └── other.h │ │ ├── other.h │ │ ├── right │ │ │ └── target.h │ │ ├── same_name.h │ │ ├── wrong │ │ │ └── target.h │ │ ├── global_var_once.h │ │ ├── ms-ext │ │ │ └── include other.h │ │ ├── other_mixed.h │ │ ├── two spaces │ │ │ └── three spaces.h │ │ ├── system │ │ │ ├── same_name_system.h │ │ │ └── next │ │ │ │ └── same_name_system.h │ │ ├── global_var_once_pragma_operator.h │ │ ├── correct_guard.h │ │ ├── __line__.h │ │ ├── incorrect_guard.h │ │ ├── extra_tokens.h │ │ ├── mixed │ │ │ └── other_mixed.h │ │ ├── test_helpers.h │ │ └── my_include.h │ ├── latin1.c │ ├── digraph pretty print.c │ ├── frameworks │ │ └── SimpleFramework.framework │ │ │ └── Headers │ │ │ └── Foo.h │ ├── double long.c │ ├── implicit main return zero.c │ ├── paste operator whitespace.c │ ├── pragma without terminating newline.c │ ├── array subscript with string.c │ ├── basic math.c │ ├── hide warnings.c │ ├── invalid continuation byte at eof.c │ ├── extern variables.c │ ├── invalid _BitInt pointer.c │ ├── labeled return.c │ ├── line counter.c │ ├── typeof invalid pointer.c │ ├── #pragma push then pop.c │ ├── object macro token pasting.c │ ├── recursive func macro.c │ ├── c23 defines.c │ ├── c99 standard.c │ ├── concat improperly encoded strings.c │ ├── gnu89 standard.c │ ├── macro keyword normalization.c │ ├── source epoch.c │ ├── c23 static_assert.c │ ├── forever stmt.c │ ├── _BitInt min max.c │ ├── colon after #embed.c │ ├── include flag.c │ ├── nested macro call.c │ ├── deref void.c │ ├── macro expansion exhaustion.c │ ├── nested #ifs.c │ ├── fp16 parameter aarch64.c │ ├── recursive call non-expanded parens.c │ ├── self_include.c │ ├── c23 digit separators.c │ ├── for decl stmt.c │ ├── nl in macro param.c │ ├── unreachable.c │ ├── X macro.c │ ├── typeof incomplete array.c │ ├── typeof_unqual.c │ ├── zero length multidimensional array.c │ ├── gnu alignof.c │ ├── macro unbalanced parens call.c │ ├── array of zero size type.c │ ├── attributed anonymous record.c │ ├── #if expression error.c │ ├── __is_target_darwin.c │ ├── __is_target_vendor.c │ ├── macro self definition.c │ ├── recursive object macro.c │ ├── c89 standard.c │ ├── comment after define.c │ ├── stringify backslashes.c │ ├── allow fp16 parameter.c │ ├── debug dump macros.c │ ├── empty computed include.c │ ├── debug dump macro names.c │ ├── empty va args comma delete c99.c │ ├── guard defined outside header.c │ ├── anonymous attributed field.c │ ├── debug dump macros and results.c │ ├── stringify invalid escape.c │ ├── c23 missing type specifier.c │ ├── darwin __float128.c │ ├── global register.c │ ├── unmatched macro paren.c │ ├── assembly invalid token.c │ ├── hash_hash at func macro start.c │ ├── imacros flag.c │ ├── object macro expands to function macro.c │ ├── spliced newline in char literal.c │ ├── #ifdef.c │ ├── digraphs disabled.c │ ├── generated location.c │ ├── invalid epoch.c │ ├── no inline asm.c │ ├── spliced newline in string literal.c │ ├── unterminated comment.c │ ├── date expansion.c │ ├── digraphs not supported.c │ ├── native half type.c │ ├── placeholder tokens pasting.c │ ├── pointer subtraction.c │ ├── include framework.c │ ├── lazy macro.c │ ├── macro expansion to defined parsed.c │ ├── object macro expansion.c │ ├── gnuc version default gcc.c │ ├── idirafter shadows include.c │ ├── gnuc version default clang.c │ ├── gnuc version override.c │ ├── empty macro block expansion.c │ ├── gnuc version empty.c │ ├── multiline comment.c │ ├── unexpected_type_name.c │ ├── __float80.c │ ├── __is_target_arch.c │ ├── binary literal.c │ ├── gnuc version default msvc.c │ ├── var args macro functions.c │ ├── float values.c │ ├── redefine invalid typedef.c │ ├── pie1.c │ ├── pie2.c │ ├── predefined macros.c │ ├── missing type specifier.c │ ├── nested invalid struct layout.c │ ├── c23 true false ast.c │ ├── enum attributes gcc.c │ ├── float eval method.c │ ├── integer conversions 32bit.c │ ├── no declarations.c │ ├── unterminated macro function at eof gcc.c │ ├── c23 stdarg.c │ ├── msvc flexible array in union.c │ ├── optimize define.c │ ├── unterminated macro function at eof clang.c │ ├── macro token pasting order.c │ ├── no optimizations.c │ ├── standard-placeholder-example.c │ ├── #elifdef.c │ ├── builtin headers.c │ ├── decayed attributed array.c │ ├── gnu variadic macros.c │ ├── incorrect guard.c │ ├── zero argument macro.c │ ├── optimize size flags.c │ ├── unspecified expansion.c │ ├── array of invalid.c │ ├── ignored attributes.c │ ├── pic1.c │ ├── pic2.c │ ├── duplicate typedef.c │ ├── guard undef.c │ ├── msvc boolean bitfield.c │ ├── #elifndef.c │ ├── missing newline before eof.c │ ├── #if expression macro ws.c │ ├── comma operator.c │ ├── complex numbers gcc.c │ ├── complex float16.c │ ├── float array size.c │ ├── switch unsigned int.c │ ├── whitespace macro arguments.c │ ├── __has_attribute with define.c │ ├── attributed typeof.c │ ├── generic ast.c │ ├── main wrong return type.c │ ├── __is_target_os.c │ ├── array designator too large.c │ ├── macro expansion disabled.c │ ├── preserve comments.c │ ├── hello world.c │ ├── cast to same type.c │ ├── __has_feature.c │ ├── pragma changes warning to error in parser.c │ ├── __has_extension.c │ ├── iquote.c │ ├── fp16 parameter.c │ ├── non string attribute.c │ ├── macro backtrace limit.c │ ├── typeof pointer wrong size.c │ ├── enum pointer.c │ ├── packed member address.c │ ├── pragma during parsing.c │ ├── deferred macro expansion.c │ ├── include pragma.c │ ├── macro argument evaluation.c │ ├── stdckdint_ast.c │ ├── typeof quals.c │ ├── stringify invalid.c │ ├── compound stmt fallthrough.c │ ├── indirect macro invocation wrong arg count.c │ ├── macro expands to self after pasting.c │ ├── integer literal promotion warning clang.c │ ├── void star.c │ ├── function macro expansion.c │ ├── gnu designated init extension.c │ ├── integer literal promotion warning gcc 64.c │ ├── linux __float128.c │ ├── unavailable results.c │ ├── array argument too small.c │ ├── integer literal promotion warning gcc 32.c │ ├── #elifndef error.c │ ├── ms-extensions.c │ ├── no dollars in identifiers.c │ ├── tentative array.c │ ├── vla.c │ ├── __float80 clang.c │ ├── char literal sign extension.c │ ├── unterminated comment in preprocessor expression.c │ ├── visibility.c │ ├── _BitInt change size.c │ ├── unexpected pragmas.c │ ├── __has_attribute.c │ ├── unterminated string literal.c │ ├── __is_target_variant.c │ ├── intptr_t.c │ ├── zero length array.c │ ├── c23 attributes.c │ ├── undef.c │ ├── builtin choose expr.c │ ├── calling convention.c │ ├── unsigned char.c │ ├── anonymous_struct_ms.c │ ├── arithmetic conversion floats.c │ ├── incorrect macro arg count.c │ ├── anonymous_struct_no-ms.c │ ├── keyword hidden by macro.c │ ├── macro whitespace.c │ ├── tentative decls defined.c │ ├── designated_init.c │ ├── include_next_mixed.c │ ├── macro backtrace.c │ ├── call undeclared function with invalid type.c │ ├── __VA_OPT__.c │ ├── bitfields.c │ ├── incorrect typeof usage.c │ ├── #if constant expression.c │ ├── pragma poison.c │ ├── dollars in identifiers.c │ ├── redefine typedef.c │ ├── unaligned u16 string literal.c │ ├── complex init.c │ ├── nested unterminated macro gcc.c │ ├── pragma once.c │ ├── nested unterminated macro clang.c │ ├── empty records.c │ ├── no declspec.c │ ├── nameless param.c │ ├── signed char.c │ ├── intmax_t.c │ ├── promotion edge cases.c │ ├── __line__.c │ ├── asm.c │ ├── digraphs.c │ ├── integer conversions.c │ ├── unknown pragmas.c │ ├── sizeof variably modified types.c │ ├── negative and too big shift count.c │ ├── signed remainder.c │ ├── __has_builtin.c │ ├── empty variadic paste.c │ ├── macro re-expansion.c │ ├── msvc macros.c │ ├── #pragma pack clang.c │ ├── digraphs enabled.c │ ├── standard-redefinition-reexamination-example.c │ ├── subscript.c │ ├── float header x86-64-linux.c │ ├── layout overflow.c │ ├── __auto_type self init.c │ ├── arithmetic overflow.c │ ├── ast │ │ ├── forever stmt.c │ │ ├── typeof_unqual.c │ │ ├── msvc attribute keywords.c │ │ ├── for decl stmt.c │ │ └── nullability.c │ ├── implicitly unsigned literal.c │ ├── invalid k&r functions.c │ ├── float header netbsd 6.99.26.c │ ├── standard-concatenation-strings-example.c │ ├── builtin functions.c │ ├── float header aarch64-linux-gnu.c │ ├── types.c │ ├── _Float16.c │ ├── undefined macro.c │ ├── misplaced attribute.c │ ├── c17 char8_t.c │ ├── msvc attribute keywords.c │ ├── newline splicing.c │ ├── #pragma pack gcc.c │ ├── alternate spellings for signed.c │ ├── kr_def_deprecated.c │ ├── int128.c │ ├── __has_warning.c │ ├── c23 char8_t disabled.c │ ├── #pragma pack msvc.c │ ├── extended identifiers c99.c │ ├── repeated preprocessor tokens.c │ ├── builtin macro errors.c │ ├── nested attributes.c │ ├── gnuc version default.c │ ├── macro redefinition.c │ ├── cast to union.c │ ├── c23 auto.c │ ├── standard attributes.c │ ├── extension.c │ ├── c23 char8_t.c │ ├── preserve comments in macros.c │ ├── c17 char8_t enabled.c │ ├── alloc_align attribute.c │ ├── unreachable code.c │ ├── float types.c │ ├── u8 character constant.c │ ├── array argument is null.c │ ├── imaginary constants.c │ ├── msvc zero size array.c │ ├── __func__.c │ ├── address of label.c │ ├── typedef extra specifiers disallowed.c │ ├── static assert messages.c │ ├── c23 identifiers.c │ ├── enumerator constants.c │ ├── ucn identifiers.c │ ├── unterminated char literal.c │ ├── gnu pointer arith.c │ ├── float builtins.c │ ├── avr sizeof long.c │ ├── nullability.c │ ├── divide by zero.c │ ├── adjust diagnostic levels.c │ ├── __is_identifier.c │ ├── expand #pragma args.c │ ├── enum overflow linux.c │ ├── declspec.c │ ├── attributed record fields.c │ ├── warn unused result.c │ ├── invalid attributes.c │ ├── token paste delete comma gnu.c │ ├── stdarg.c │ ├── enum sizes windows.c │ ├── limits header.c │ ├── enum overflow msvc.c │ ├── msp430 builtin types.c │ ├── shufflevector.c │ ├── numbers.c │ └── c23 keywords.c └── fuzz │ └── main.c ├── .gitignore ├── include ├── varargs.h ├── stdnoreturn.h ├── stdbool.h ├── stdalign.h ├── iso646.h ├── stdckdint.h ├── stddef.h └── stdarg.h ├── .gitattributes ├── deps └── zig │ └── lib.zig ├── src ├── aro │ ├── Builtins │ │ ├── xcore.def │ │ └── bpf.def │ └── StringInterner.zig ├── assembly_backend.zig ├── backend │ └── Assembly.zig └── backend.zig ├── .github └── workflows │ └── ci.yml └── LICENSE /test/cases/embed/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/cases/embed/embed byte: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /test/cases/expanded/#elifdef.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/cases/expanded/nested #ifs.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/cases/embed/embed data: -------------------------------------------------------------------------------- 1 | Hello, World! -------------------------------------------------------------------------------- /test/cases/expanded/#elifndef.c: -------------------------------------------------------------------------------- 1 | int 2 | long 3 | -------------------------------------------------------------------------------- /test/cases/expanded/#ifdef.c: -------------------------------------------------------------------------------- 1 | long 2 | int 3 | -------------------------------------------------------------------------------- /test/cases/expanded/lazy macro.c: -------------------------------------------------------------------------------- 1 | REC_0_HOOK () 2 | -------------------------------------------------------------------------------- /test/cases/expanded/nested macro call.c: -------------------------------------------------------------------------------- 1 | x 2 | x 3 | -------------------------------------------------------------------------------- /test/cases/expanded/recursive func macro.c: -------------------------------------------------------------------------------- 1 | F(1) 2 | -------------------------------------------------------------------------------- /test/cases/expanded/unspecified expansion.c: -------------------------------------------------------------------------------- 1 | 2*9*g 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .zig-cache/ 2 | zig-out/ 3 | test/fuzz-output/ -------------------------------------------------------------------------------- /test/cases/expanded/#if constant expression.c: -------------------------------------------------------------------------------- 1 | long 2 | -------------------------------------------------------------------------------- /test/cases/expanded/debug dump macros.c: -------------------------------------------------------------------------------- 1 | #define BAR 43 2 | -------------------------------------------------------------------------------- /test/cases/expanded/line counter.c: -------------------------------------------------------------------------------- 1 | 2 0 2 | 3 1 3 2 3 | -------------------------------------------------------------------------------- /test/cases/expanded/paste operator whitespace.c: -------------------------------------------------------------------------------- 1 | (AY) 2 | -------------------------------------------------------------------------------- /test/cases/expanded/recursive object macro.c: -------------------------------------------------------------------------------- 1 | x 2 | x 3 | -------------------------------------------------------------------------------- /test/cases/expanded/stringify invalid escape.c: -------------------------------------------------------------------------------- 1 | x["" 2 | -------------------------------------------------------------------------------- /test/cases/include/global_var.h: -------------------------------------------------------------------------------- 1 | int multiple = 10; 2 | -------------------------------------------------------------------------------- /test/cases/include/iquote/iquote_test.h: -------------------------------------------------------------------------------- 1 | #define FOO 42 2 | -------------------------------------------------------------------------------- /test/cases/include/next/my_include.h: -------------------------------------------------------------------------------- 1 | #define BAR 2 2 | -------------------------------------------------------------------------------- /test/cases/include/other.h: -------------------------------------------------------------------------------- 1 | #define OTHER_INCLUDED 1 2 | -------------------------------------------------------------------------------- /test/cases/expanded/macro expansion exhaustion.c: -------------------------------------------------------------------------------- 1 | (2 + 2) 2 | -------------------------------------------------------------------------------- /test/cases/expanded/object macro token pasting.c: -------------------------------------------------------------------------------- 1 | a1 2 | a1 3 | -------------------------------------------------------------------------------- /test/cases/include/right/target.h: -------------------------------------------------------------------------------- 1 | #warning wrong included 2 | -------------------------------------------------------------------------------- /test/cases/include/same_name.h: -------------------------------------------------------------------------------- 1 | #include_next "same_name.h" 2 | -------------------------------------------------------------------------------- /test/cases/include/wrong/target.h: -------------------------------------------------------------------------------- 1 | #error wrong included 2 | -------------------------------------------------------------------------------- /test/cases/expanded/deferred macro expansion.c: -------------------------------------------------------------------------------- 1 | F_HOOK ()(XXX) 2 | -------------------------------------------------------------------------------- /test/cases/expanded/digraph pretty print.c: -------------------------------------------------------------------------------- 1 | %:%: %: <%<%> > <::> 2 | -------------------------------------------------------------------------------- /test/cases/expanded/empty variadic paste.c: -------------------------------------------------------------------------------- 1 | ASM_SEL(btsl, btsq) 2 | -------------------------------------------------------------------------------- /test/cases/expanded/macro self definition.c: -------------------------------------------------------------------------------- 1 | FOO 2 | BAR 3 | BAZ 4 | -------------------------------------------------------------------------------- /test/cases/expanded/macro unbalanced parens call.c: -------------------------------------------------------------------------------- 1 | FIRST 42 2 | -------------------------------------------------------------------------------- /test/cases/expanded/object macro expansion.c: -------------------------------------------------------------------------------- 1 | a 2 | 1 3 | define 4 | -------------------------------------------------------------------------------- /test/cases/expanded/recursive call non-expanded parens.c: -------------------------------------------------------------------------------- 1 | 1 2 1 bar 2 | -------------------------------------------------------------------------------- /test/cases/include/global_var_once.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | int once = 10; 3 | -------------------------------------------------------------------------------- /test/cases/include/ms-ext/include other.h: -------------------------------------------------------------------------------- 1 | #include "include/other.h" 2 | -------------------------------------------------------------------------------- /test/cases/include/next/same_name.h: -------------------------------------------------------------------------------- 1 | #define NEXT_SAME_NAME_INCLUDED 1 2 | -------------------------------------------------------------------------------- /test/cases/include/other_mixed.h: -------------------------------------------------------------------------------- 1 | #define NEXT_OTHER_MIXED_INCLUDED 1 2 | -------------------------------------------------------------------------------- /test/cases/expanded/__has_attribute with define.c: -------------------------------------------------------------------------------- 1 | 1 2 | 1 + 0 3 | 1 4 | 1 5 | -------------------------------------------------------------------------------- /test/cases/expanded/empty macro block expansion.c: -------------------------------------------------------------------------------- 1 | F_HOOK () 2 | F_HOOK () 3 | -------------------------------------------------------------------------------- /test/cases/expanded/empty va args comma delete c99.c: -------------------------------------------------------------------------------- 1 | foo(a,) 2 | foo(a,b) 3 | -------------------------------------------------------------------------------- /test/cases/expanded/gnu variadic macros.c: -------------------------------------------------------------------------------- 1 | "2,3,4", 1 __VA_ARGS__ 2,3,4 2 | -------------------------------------------------------------------------------- /test/cases/expanded/var args macro functions.c: -------------------------------------------------------------------------------- 1 | "2,3,4,5,6" 2 | baz bar 3,4 3 | -------------------------------------------------------------------------------- /test/cases/include/two spaces/three spaces.h: -------------------------------------------------------------------------------- 1 | #define THREE_SPACES_H 1 2 | -------------------------------------------------------------------------------- /test/cases/include/system/same_name_system.h: -------------------------------------------------------------------------------- 1 | #include_next 2 | -------------------------------------------------------------------------------- /test/cases/expanded/macro expansion disabled.c: -------------------------------------------------------------------------------- 1 | 1 LOOP_INDIRECTION () (1) 2 | 123 3 | -------------------------------------------------------------------------------- /test/cases/expanded/macro token pasting order.c: -------------------------------------------------------------------------------- 1 | TEST_0 2 | TEST_M(0) 3 | 1 4 | a bc 5 | -------------------------------------------------------------------------------- /test/cases/expanded/placeholder tokens pasting.c: -------------------------------------------------------------------------------- 1 | x x 2 | y 3 | x ()x 4 | (y) 5 | (x) 6 | -------------------------------------------------------------------------------- /test/cases/latin1.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vexu/arocc/HEAD/test/cases/latin1.c -------------------------------------------------------------------------------- /test/cases/include/global_var_once_pragma_operator.h: -------------------------------------------------------------------------------- 1 | _Pragma("once") 2 | int once = 10; 3 | -------------------------------------------------------------------------------- /test/cases/expanded/source epoch.c: -------------------------------------------------------------------------------- 1 | "Jan 1 1970" 2 | "00:00:00" 3 | "Thu Jan 1 00:00:00 1970" 4 | -------------------------------------------------------------------------------- /test/cases/include/system/next/same_name_system.h: -------------------------------------------------------------------------------- 1 | #define SYSTEM_NEXT_SAME_NAME_INCLUDED 1 2 | -------------------------------------------------------------------------------- /test/cases/digraph pretty print.c: -------------------------------------------------------------------------------- 1 | %:%: %: <%<%> > <::> 2 | 3 | /** manifest: 4 | expand 5 | */ 6 | -------------------------------------------------------------------------------- /test/cases/expanded/whitespace macro arguments.c: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | q 1 4 | 5 | 1 6 | 2 3 7 | 3 8 | -------------------------------------------------------------------------------- /test/cases/frameworks/SimpleFramework.framework/Headers/Foo.h: -------------------------------------------------------------------------------- 1 | #define SIMPLE_FRAMEWORK_FOO 123 2 | -------------------------------------------------------------------------------- /test/cases/double long.c: -------------------------------------------------------------------------------- 1 | _Complex double long x; 2 | double long y; 3 | 4 | /** manifest: 5 | syntax 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/expanded/function macro expansion.c: -------------------------------------------------------------------------------- 1 | "HI THERE" 2 | HI_THERE 3 | "HI THERE" 4 | 1, (2, 3) 5 | S() 6 | -------------------------------------------------------------------------------- /test/cases/expanded/multiline comment.c: -------------------------------------------------------------------------------- 1 | int I_exist; 2 | int x; 3 | int y; 4 | int foo ; int bar; 5 | -------------------------------------------------------------------------------- /test/cases/implicit main return zero.c: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | */ 8 | -------------------------------------------------------------------------------- /test/cases/paste operator whitespace.c: -------------------------------------------------------------------------------- 1 | #define F(X) (X##Y) 2 | F(A) 3 | 4 | /** manifest: 5 | expand 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/pragma without terminating newline.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | */ 4 | 5 | #pragma GCC poison foo -------------------------------------------------------------------------------- /test/cases/array subscript with string.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax_ignore_errors 3 | */ 4 | 5 | int x[2]; 6 | x[""[""] -------------------------------------------------------------------------------- /test/cases/basic math.c: -------------------------------------------------------------------------------- 1 | _Static_assert(1 + 1u == 2, "unexpected result"); 2 | 3 | /** manifest: 4 | syntax 5 | */ 6 | -------------------------------------------------------------------------------- /test/cases/expanded/standard-placeholder-example.c: -------------------------------------------------------------------------------- 1 | int j[] = { 123, 45, 67, 89, 2 | 10, 11, 12, }; 3 | -------------------------------------------------------------------------------- /test/cases/hide warnings.c: -------------------------------------------------------------------------------- 1 | int arr[2] = { 0, [0] = 10 }; 2 | 3 | /** manifest: 4 | syntax 5 | args = -w 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/invalid continuation byte at eof.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax_ignore_errors 3 | */ 4 | 5 | foo() {� 6 | -------------------------------------------------------------------------------- /test/cases/expanded/debug dump macro names.c: -------------------------------------------------------------------------------- 1 | #define FOO 2 | #define BAR 3 | int x = 42; 4 | #undef FOO 5 | #define FOO 6 | -------------------------------------------------------------------------------- /test/cases/extern variables.c: -------------------------------------------------------------------------------- 1 | extern int foo[]; 2 | extern struct Bar bar; 3 | 4 | /** manifest: 5 | syntax 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/invalid _BitInt pointer.c: -------------------------------------------------------------------------------- 1 | _BitInt(1) *e= __real__ e; 2 | 3 | /** manifest: 4 | syntax_ignore_errors 5 | */ 6 | -------------------------------------------------------------------------------- /test/cases/labeled return.c: -------------------------------------------------------------------------------- 1 | int foo(int x) { 2 | bar: 3 | return x; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/line counter.c: -------------------------------------------------------------------------------- 1 | #define FOO __LINE__ __COUNTER__ 2 | FOO 3 | FOO FOO 4 | 5 | /** manifest: 6 | expand 7 | */ 8 | -------------------------------------------------------------------------------- /test/cases/typeof invalid pointer.c: -------------------------------------------------------------------------------- 1 | typeof((void)0 + 0) *a = 2; 2 | 3 | /** manifest: 4 | syntax_ignore_errors 5 | */ 6 | -------------------------------------------------------------------------------- /test/cases/#pragma push then pop.c: -------------------------------------------------------------------------------- 1 | #pragma pack(push, 16) 2 | #pragma pack(pop) 3 | 4 | /** manifest: 5 | syntax 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/expanded/X macro.c: -------------------------------------------------------------------------------- 1 | enum Foo { 2 | Foo_1 = 1, 3 | Foo_2 = 2, 4 | Foo_3 = 3, 5 | Foo_4 = 4, 6 | Foo_5 = 5, 7 | }; 8 | -------------------------------------------------------------------------------- /test/cases/object macro token pasting.c: -------------------------------------------------------------------------------- 1 | #define x a##1 2 | x 3 | #define a 1 4 | x 5 | 6 | /** manifest: 7 | expand 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/expanded/macro whitespace.c: -------------------------------------------------------------------------------- 1 | "1 2" 2 | "+ /" 3 | "1" 4 | "1 2" 5 | "2" 6 | "3" 7 | "5" 8 | "6" 9 | foo bar 10 | -------------------------------------------------------------------------------- /test/cases/recursive func macro.c: -------------------------------------------------------------------------------- 1 | #define F(x) G(x) 2 | #define G(x) F(x) 3 | 4 | F(1) 5 | 6 | /** manifest: 7 | expand 8 | */ 9 | -------------------------------------------------------------------------------- /include/varargs.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | #pragma once 3 | #error please use instead of 4 | -------------------------------------------------------------------------------- /test/cases/c23 defines.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__STDC_VERSION__ == 202311L, ""); 2 | 3 | /** manifest: 4 | syntax 5 | args = -std=c23 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/c99 standard.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int typeof = 5; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = -std=c99 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/concat improperly encoded strings.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vexu/arocc/HEAD/test/cases/concat improperly encoded strings.c -------------------------------------------------------------------------------- /test/cases/expanded/macro expands to self after pasting.c: -------------------------------------------------------------------------------- 1 | void speex_resampler_init(void); 2 | void speex_resampler_init_frac(void); 3 | -------------------------------------------------------------------------------- /test/cases/gnu89 standard.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | typeof(int) x = 5; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = -std=gnu89 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/include/correct_guard.h: -------------------------------------------------------------------------------- 1 | #ifndef CORRECT_GUARD_H 2 | #define CORRECT_GUARD_H 3 | int x = 42; 4 | #endif // CORRECT_GUARD_H 5 | -------------------------------------------------------------------------------- /test/cases/macro keyword normalization.c: -------------------------------------------------------------------------------- 1 | #define p(x) int x; 2 | p(elif) 3 | 4 | int endif; 5 | 6 | /** manifest: 7 | syntax 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/expanded/debug dump macros and results.c: -------------------------------------------------------------------------------- 1 | #define FOO 42 2 | #define BAR FOO 3 | int x = 42; 4 | #undef FOO 5 | #define FOO 43 6 | -------------------------------------------------------------------------------- /test/cases/source epoch.c: -------------------------------------------------------------------------------- 1 | __DATE__ 2 | __TIME__ 3 | __TIMESTAMP__ 4 | 5 | /** manifest: 6 | expand 7 | env = SOURCE_DATE_EPOCH=0 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/c23 static_assert.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | _Static_assert(1); 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = -std=c23 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/expanded/preserve comments.c: -------------------------------------------------------------------------------- 1 | 12 2 | 12 3 | 1 4 | 1 5 | hello1 6 | /** manifest: 7 | expand_partial 8 | args = -C 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/forever stmt.c: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | for (;;); 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = --target=x86_64-linux-gnu 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/_BitInt min max.c: -------------------------------------------------------------------------------- 1 | _Static_assert(-10 % -444444444444444442051616WB != 0, ""); 2 | 3 | /** manifest: 4 | syntax 5 | args = -std=c23 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/colon after #embed.c: -------------------------------------------------------------------------------- 1 | #embed "embed byte"n: 2 | 3 | /** manifest: 4 | syntax_ignore_errors 5 | args = --embed-dir=test/cases/embed 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/include flag.c: -------------------------------------------------------------------------------- 1 | _Static_assert(FOO == 42, ""); 2 | 3 | /** manifest: 4 | syntax 5 | args = -include include/iquote/iquote_test.h 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/include/__line__.h: -------------------------------------------------------------------------------- 1 | static int line3 = __LINE__; 2 | #line 200 "bar.c" 3 | static int line4 = __LINE__; 4 | static char *file2 = __FILE__; 5 | -------------------------------------------------------------------------------- /test/cases/include/next/other.h: -------------------------------------------------------------------------------- 1 | #if defined(OTHER_INCLUDED) 2 | #error should not have been included yet 3 | #endif 4 | #define NEXT_OTHER_INCLUDED 1 5 | -------------------------------------------------------------------------------- /test/cases/nested macro call.c: -------------------------------------------------------------------------------- 1 | #define A(x) x 2 | #define B(x) A(x) 3 | 4 | B(B(x)) 5 | A(B(x)) 6 | 7 | /** manifest: 8 | expand 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/deref void.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | void *p = 0; 3 | (void)*p; 4 | p = &*p; 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/include/incorrect_guard.h: -------------------------------------------------------------------------------- 1 | #ifndef INCORRECT_GUARD_H 2 | // missing #define INCORRECT_GUARD_H 3 | int x = 42; 4 | #endif // INCORRECT_GUARD_H 5 | -------------------------------------------------------------------------------- /test/cases/macro expansion exhaustion.c: -------------------------------------------------------------------------------- 1 | #define CREATE_CALL F 2 | #define F(x) (x + 2) 3 | 4 | CREATE_CALL(2) 5 | 6 | /** manifest: 7 | expand 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/nested #ifs.c: -------------------------------------------------------------------------------- 1 | #define FOO 2 | #ifdef FOO 3 | #ifdef FOO 4 | #else 5 | #endif 6 | #endif 7 | 8 | /** manifest: 9 | expand 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/fp16 parameter aarch64.c: -------------------------------------------------------------------------------- 1 | __fp16 foo(__fp16 x) { 2 | return 0; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = --target=aarch64-linux-gnu 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/recursive call non-expanded parens.c: -------------------------------------------------------------------------------- 1 | #define foo(X) 1 bar 2 | #define bar(X) 2 foo 3 | 4 | foo(X)(Y)(Z) 5 | 6 | /** manifest: 7 | expand 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/self_include.c: -------------------------------------------------------------------------------- 1 | #include "self_include.c" 2 | 3 | /** manifest: 4 | syntax 5 | 6 | self_include.c:1:10: error: #include nested too deeply 7 | */ 8 | -------------------------------------------------------------------------------- /include/stdnoreturn.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | 5 | #define noreturn _Noreturn 6 | #define __noreturn_is_defined 1 7 | -------------------------------------------------------------------------------- /test/cases/c23 digit separators.c: -------------------------------------------------------------------------------- 1 | _Static_assert(0b1001'0110 == 150); 2 | _Static_assert(1'2wb == 12); 3 | 4 | /** manifest: 5 | syntax 6 | args = -std=c23 7 | */ 8 | -------------------------------------------------------------------------------- /test/cases/for decl stmt.c: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | for (int x=0, y=1; ; x++); 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = --target=x86_64-linux-gnu 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/nl in macro param.c: -------------------------------------------------------------------------------- 1 | #define F(x) x 2 | 3 | int foo(void) { 4 | return F(1 + 5 | 2); 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/unreachable.c: -------------------------------------------------------------------------------- 1 | #include 2 | void foo(void) { 3 | unreachable(); 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | args = -std=c23 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/X macro.c: -------------------------------------------------------------------------------- 1 | #define X(a) Foo_ ## a = a, 2 | enum Foo { 3 | X(1) 4 | X(2) 5 | X(3) 6 | X(4) 7 | X(5) 8 | }; 9 | 10 | /** manifest: 11 | expand 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/expanded/macro re-expansion.c: -------------------------------------------------------------------------------- 1 | z[0] 2 | z[0] 3 | z[0] 4 | z[0] 5 | z[0] 6 | h (s) 7 | 1 8 | 13 9 | z[0] z[0] Z1 10 | 1 TAU(2) 11 | 1 TAU(1) 1 z[0] 12 | -------------------------------------------------------------------------------- /test/cases/typeof incomplete array.c: -------------------------------------------------------------------------------- 1 | typeof(const int[]) arr1 = {1,2}; 2 | _Static_assert(sizeof(arr1) == sizeof(int[2]), ""); 3 | 4 | /** manifest: 5 | syntax 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/typeof_unqual.c: -------------------------------------------------------------------------------- 1 | const int a; 2 | typeof(a) b; 3 | typeof_unqual(a) c; 4 | 5 | /** manifest: 6 | syntax 7 | args = -std=c23 --target=x86_64-linux-gnu 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/zero length multidimensional array.c: -------------------------------------------------------------------------------- 1 | int foo[1][0]; 2 | int bar[0][0]; 3 | int baz[1][0][0]; 4 | int qux[1][1][0]; 5 | 6 | /** manifest: 7 | syntax 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/expanded/token paste delete comma gnu.c: -------------------------------------------------------------------------------- 1 | fprintf (stderr, "foo"); 2 | fprintf (stderr, "foo",); 3 | fprintf (stderr, "foo", "bar"); 4 | foo(a) 5 | foo(a,b) 6 | 1, 7 | -------------------------------------------------------------------------------- /test/cases/gnu alignof.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | (void) _Alignof 2; 3 | (void) _Alignof(2); 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | args = --emulate=gcc 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/macro unbalanced parens call.c: -------------------------------------------------------------------------------- 1 | #define FIRST(x) x 2 | #define SECOND FIRST 3 | #define THIRD SECOND( FIRST 4 | THIRD 42) 5 | 6 | /** manifest: 7 | expand 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/array of zero size type.c: -------------------------------------------------------------------------------- 1 | struct { 2 | int:0; 3 | 4 | } c [] = {}; 5 | 6 | _Static_assert(sizeof(c) == 0, ""); 7 | 8 | /** manifest: 9 | syntax 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/attributed anonymous record.c: -------------------------------------------------------------------------------- 1 | struct A{ 2 | union { 3 | char a; 4 | } __attribute__((packed)); 5 | }; 6 | 7 | /** manifest: 8 | syntax 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/#if expression error.c: -------------------------------------------------------------------------------- 1 | #if 1/q 2 | #endif 3 | 4 | /** manifest: 5 | syntax 6 | 7 | #if expression error.c:1:6: error: division by zero in preprocessor expression 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/__is_target_darwin.c: -------------------------------------------------------------------------------- 1 | #if !__is_target_os(iOS) 2 | #error macos should match ios 3 | #endif 4 | 5 | /** manifest: 6 | expand_error 7 | args = --target=aarch64-macos 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/__is_target_vendor.c: -------------------------------------------------------------------------------- 1 | #if !__is_target_vendor(pc) 2 | #error 3 | #endif 4 | 5 | /** manifest: 6 | expand_error 7 | args = --target=x86_64-pc-linux-gnu --emulate=clang 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/macro self definition.c: -------------------------------------------------------------------------------- 1 | #define FOO FOO 2 | 3 | FOO 4 | 5 | #define BAR BAZ 6 | #define BAZ BAR 7 | 8 | BAR 9 | BAZ 10 | 11 | /** manifest: 12 | expand 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/recursive object macro.c: -------------------------------------------------------------------------------- 1 | #define y x 2 | #define x y 3 | x 4 | 5 | #undef y 6 | #undef x 7 | 8 | #define x x 9 | x 10 | 11 | /** manifest: 12 | expand 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/c89 standard.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int inline = 5; 3 | int restrict = 10; 4 | int typeof = 20; 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | args = -std=c89 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/comment after define.c: -------------------------------------------------------------------------------- 1 | #define FOO /* comment */ 2 | #if 0 3 | #endif 4 | 5 | #define BAR // comment 6 | #if 0 7 | #endif 8 | 9 | /** manifest: 10 | syntax 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/stringify backslashes.c: -------------------------------------------------------------------------------- 1 | #define str(s) #s 2 | x[str() 3 | x[str(\) 4 | x[str(\\) 5 | x[str(\\\) 6 | x[str(\\\\) 7 | 8 | /** manifest: 9 | syntax_ignore_errors 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/allow fp16 parameter.c: -------------------------------------------------------------------------------- 1 | __fp16 foo(__fp16 x) { 2 | return 0; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = --target=x86_64-linux-gnu -fnative-half-arguments-and-returns 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/debug dump macros.c: -------------------------------------------------------------------------------- 1 | #define FOO 42 2 | #define BAR FOO 3 | int x = FOO; 4 | #undef BAR 5 | #define BAR 43 6 | 7 | /** manifest: 8 | expand_partial 9 | args = -dM 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/empty computed include.c: -------------------------------------------------------------------------------- 1 | #define FOO 2 | #include FOO 3 | 4 | /** manifest: 5 | expand_error 6 | 7 | empty computed include.c:2:10: error: expected "FILENAME" or 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/debug dump macro names.c: -------------------------------------------------------------------------------- 1 | #define FOO 42 2 | #define BAR FOO 3 | int x = BAR; 4 | #undef FOO 5 | #define FOO 43 6 | 7 | /** manifest: 8 | expand_partial 9 | args = -dN 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/empty va args comma delete c99.c: -------------------------------------------------------------------------------- 1 | #define ZERO_ARGS(...) foo(a, ##__VA_ARGS__) 2 | 3 | ZERO_ARGS() 4 | ZERO_ARGS(b) 5 | 6 | /** manifest: 7 | expand 8 | args = -std=c99 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/guard defined outside header.c: -------------------------------------------------------------------------------- 1 | #include "incorrect_guard.h" 2 | #define INCORRECT_GUARD_H 3 | #include "incorrect_guard.h" 4 | 5 | /** manifest: 6 | syntax 7 | args = -I include 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/anonymous attributed field.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax_ignore_errors 3 | */ 4 | 5 | struct A { 6 | union { 7 | char a 8 | } __attribute__((packed))} b = __builtin_offsetof(struct A,a -------------------------------------------------------------------------------- /test/cases/debug dump macros and results.c: -------------------------------------------------------------------------------- 1 | #define FOO 42 2 | #define BAR FOO 3 | int x = BAR; 4 | #undef FOO 5 | #define FOO 43 6 | 7 | /** manifest: 8 | expand_partial 9 | args = -dD 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/stringify invalid escape.c: -------------------------------------------------------------------------------- 1 | #define str(s) # s 2 | x[str(\) 3 | 4 | /** manifest: 5 | expand 6 | 7 | stringify invalid escape.c:2:7: warning: invalid string literal, ignoring final '\' 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/c23 missing type specifier.c: -------------------------------------------------------------------------------- 1 | static x = 5; 2 | 3 | /** manifest: 4 | syntax 5 | args = -std=c23 6 | 7 | c23 missing type specifier.c:1:8: error: a type specifier is required for all declarations*/ 8 | -------------------------------------------------------------------------------- /test/cases/darwin __float128.c: -------------------------------------------------------------------------------- 1 | __float128 q = 0.0; 2 | 3 | /** manifest: 4 | syntax 5 | args = --target=x86_64-macos 6 | 7 | darwin __float128.c:1:1: error: __float128 is not supported on this target 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/global register.c: -------------------------------------------------------------------------------- 1 | register int a; 2 | register int b __asm__("ebp"); 3 | 4 | /** manifest: 5 | syntax 6 | 7 | global register.c:1:15: error: register name not specified for global variable 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/include/extra_tokens.h: -------------------------------------------------------------------------------- 1 | extra leading tokens that will be ignored 2 | 3 | #define FOO BAR 4 | #define BAR BAZ 5 | #define BAZ 42 6 | 7 | FOO BAR BAZ 8 | extra trailing tokens that will be ignored 9 | -------------------------------------------------------------------------------- /test/cases/unmatched macro paren.c: -------------------------------------------------------------------------------- 1 | #define f(x) x 2 | 3 | f(1 4 | 5 | /** manifest: 6 | expand_error 7 | 8 | unmatched macro paren.c:3:1: error: unterminated function macro argument list 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/assembly invalid token.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __asm__("") 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | 8 | assembly invalid token.c:2:15: error: expected ')', found 'invalid bytes' 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/hash_hash at func macro start.c: -------------------------------------------------------------------------------- 1 | #define foo(X) ## x 2 | 3 | /** manifest: 4 | syntax 5 | 6 | hash_hash at func macro start.c:1:16: error: '##' cannot appear at the start of a macro expansion 7 | */ 8 | -------------------------------------------------------------------------------- /test/cases/imacros flag.c: -------------------------------------------------------------------------------- 1 | _Static_assert(FOO == 42, ""); 2 | _Static_assert(BAR == 42, ""); 3 | _Static_assert(BAZ == 42, ""); 4 | 5 | /** manifest: 6 | syntax 7 | args = -imacros include/extra_tokens.h 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/object macro expands to function macro.c: -------------------------------------------------------------------------------- 1 | #define FOO(X) X##OK 2 | #define BAR FOO 3 | #define BAZ BAR 4 | 5 | #define A 1 6 | #if BAZ (A) 7 | #endif 8 | 9 | /** manifest: 10 | syntax 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/spliced newline in char literal.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | expand_error 3 | 4 | spliced newline in char literal.c:7:1: warning: missing terminating ' character [-Winvalid-pp-token] 5 | */ 6 | 7 | '\\ 8 | 9 | -------------------------------------------------------------------------------- /test/cases/#ifdef.c: -------------------------------------------------------------------------------- 1 | #define FOO 2 | #ifdef FOO 3 | long 4 | #else 5 | int 6 | #endif 7 | 8 | #define BAR 9 | #ifdef BAZ 10 | long 11 | #else 12 | int 13 | #endif 14 | 15 | /** manifest: 16 | expand 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/digraphs disabled.c: -------------------------------------------------------------------------------- 1 | void baz(void) { 2 | int x<:5:>; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = -fno-digraphs 8 | 9 | digraphs disabled.c:2:10: error: expected ';', found '<' 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/generated location.c: -------------------------------------------------------------------------------- 1 | __has_attribute(foo) 2 | 3 | /** manifest: 4 | syntax 5 | 6 | generated location.c:1:1: error: expected external declaration 7 | :1:1: note: expanded from here 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/invalid epoch.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | env = SOURCE_DATE_EPOCH=abc 4 | 5 | error: environment variable SOURCE_DATE_EPOCH must expand to a non-negative integer less than or equal to 253402300799 6 | */ 7 | -------------------------------------------------------------------------------- /test/cases/no inline asm.c: -------------------------------------------------------------------------------- 1 | __asm__("foo"); 2 | __asm__(""); 3 | 4 | /** manifest: 5 | syntax 6 | args = -fno-gnu-inline-asm 7 | 8 | no inline asm.c:1:8: error: GNU-style inline assembly is disabled 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/spliced newline in string literal.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | expand_error 3 | 4 | spliced newline in string literal.c:7:1: warning: missing terminating '"' character [-Winvalid-pp-token] 5 | */ 6 | 7 | "\\ 8 | 9 | -------------------------------------------------------------------------------- /test/cases/unterminated comment.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | 4 | unterminated comment.c:8:7: error: unterminated comment 5 | unterminated comment.c:8:6: error: expected ';' before end of file 6 | */ 7 | 8 | int x /** -------------------------------------------------------------------------------- /test/cases/date expansion.c: -------------------------------------------------------------------------------- 1 | char *foo = __DATE__; 2 | 3 | /** manifest: 4 | syntax 5 | args = -Wdate-time 6 | 7 | date expansion.c:1:13: warning: expansion of date or time macro is not reproducible [-Wdate-time] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/digraphs not supported.c: -------------------------------------------------------------------------------- 1 | void baz(void) { 2 | int x<:5:>; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = -std=c89 8 | 9 | digraphs not supported.c:2:10: error: expected ';', found '<' 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/native half type.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __fp16 x = 1.0f; 3 | __fp16 y = 2.0f; 4 | x = x + y; 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | args = -fnative-half-type --target=x86_64-linux-gnu 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/placeholder tokens pasting.c: -------------------------------------------------------------------------------- 1 | #define CAT(a, b) a##b 2 | #define CAT2(a, b) (a##b) 3 | 4 | x CAT(,)x 5 | CAT(,y) 6 | 7 | x CAT2(,)x 8 | CAT2(,y) 9 | CAT2(x,) 10 | 11 | /** manifest: 12 | expand 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/pointer subtraction.c: -------------------------------------------------------------------------------- 1 | #include 2 | ptrdiff_t foo(int x) { 3 | char c[2] = {0, 0}; 4 | const char *p = &c[1]; 5 | return p - &c[0]; 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/include framework.c: -------------------------------------------------------------------------------- 1 | #include 2 | _Static_assert(SIMPLE_FRAMEWORK_FOO == 123, "macro from framework not accessible"); 3 | 4 | /** manifest: 5 | syntax 6 | args = -iframework frameworks 7 | */ 8 | -------------------------------------------------------------------------------- /test/cases/include/mixed/other_mixed.h: -------------------------------------------------------------------------------- 1 | #if defined(NEXT_OTHER_MIXED_INCLUDED) 2 | #error should not have been included yet 3 | #endif 4 | #define OTHER_MIXED_INCLUDED 1 5 | #include_next // include/other_mixed.h 6 | -------------------------------------------------------------------------------- /test/cases/lazy macro.c: -------------------------------------------------------------------------------- 1 | #define REC_EMPTY 2 | #define REC_DEFER(op) op REC_EMPTY 3 | 4 | #define REC_0_HOOK() REC_0 5 | #define REC_1 REC_DEFER(REC_0_HOOK)() 6 | 7 | REC_1 8 | 9 | /** manifest: 10 | expand 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/macro expansion to defined parsed.c: -------------------------------------------------------------------------------- 1 | #define DEFINED defined 2 | 3 | void foo(void) { 4 | int DEFINED = 0; 5 | defined = 1; 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | args = -Wexpansion-to-defined 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/object macro expansion.c: -------------------------------------------------------------------------------- 1 | #define x a 2 | x 3 | #define a 1 4 | x 5 | #define y define 6 | y 7 | 8 | #define __restrict restrict 9 | 10 | #define empty 11 | empty 12 | 13 | /** manifest: 14 | expand 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/gnuc version default gcc.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__GNUC__ == 7, ""); 2 | _Static_assert(__GNUC_MINOR__ == 1, ""); 3 | _Static_assert(__GNUC_PATCHLEVEL__ == 0, ""); 4 | 5 | /** manifest: 6 | syntax 7 | args = --emulate=gcc 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/idirafter shadows include.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** manifest: 4 | syntax 5 | args = -I include/wrong -I include/right -idirafter include/wrong 6 | 7 | target.h:1:2: warning: wrong included [-W#warnings] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/gnuc version default clang.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__GNUC__ == 4, ""); 2 | _Static_assert(__GNUC_MINOR__ == 2, ""); 3 | _Static_assert(__GNUC_PATCHLEVEL__ == 1, ""); 4 | 5 | /** manifest: 6 | syntax 7 | args = --emulate=clang 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/gnuc version override.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__GNUC__ == 5, ""); 2 | _Static_assert(__GNUC_MINOR__ == 3, ""); 3 | _Static_assert(__GNUC_PATCHLEVEL__ == 42, ""); 4 | 5 | /** manifest: 6 | syntax 7 | args = -fgnuc-version=5.3.42 8 | */ 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.zig text eol=lf 2 | test/cases/expanded/* text eol=lf 3 | test/cases/ast/* text eol=lf 4 | 5 | deps/** linguist-vendored 6 | test/records/** linguist-generated=true 7 | src/builtins/BuiltinFunction.zig linguist-generated=true 8 | -------------------------------------------------------------------------------- /test/cases/empty macro block expansion.c: -------------------------------------------------------------------------------- 1 | #define CONTINUE(k) DEFER(k##_HOOK)() 2 | #define DEFER(op) op EMPTY 3 | #define EMPTY 4 | #define F_HOOK() F 5 | 6 | CONTINUE( F) 7 | CONTINUE(F) 8 | 9 | /** manifest: 10 | expand 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/gnuc version empty.c: -------------------------------------------------------------------------------- 1 | #if defined(__GNUC__) || defined(__GNUC_MINOR__) || defined(__GNUC_PATCHLEVEL__) 2 | #error "__GNUC__ macros should not be defined" 3 | #endif 4 | 5 | /** manifest: 6 | syntax 7 | args = -fgnuc-version= 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/multiline comment.c: -------------------------------------------------------------------------------- 1 | /* comment **/ 2 | 3 | int I_exist; 4 | 5 | /* 6 | int I_dont; 7 | */ 8 | 9 | /* */int x; 10 | /* 11 | */int y; 12 | 13 | int foo/**/; int/* 14 | */bar; 15 | 16 | /** manifest: 17 | expand 18 | */ 19 | -------------------------------------------------------------------------------- /test/cases/unexpected_type_name.c: -------------------------------------------------------------------------------- 1 | typedef int foo; 2 | void bar(void) { 3 | int a = foo; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | 9 | unexpected_type_name.c:3:13: error: unexpected type name 'foo': expected expression 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/__float80.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __float80 x = 1.0w; 3 | x = 1.0W; 4 | _Complex long double z; 5 | z = 1.0wI; 6 | z = 1.0iW; 7 | } 8 | 9 | /** manifest: 10 | syntax 11 | args = --target=x86_64-linux 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/__is_target_arch.c: -------------------------------------------------------------------------------- 1 | #if !__is_target_arch(x86) 2 | #error 3 | #endif 4 | 5 | #if __is_target_arch(x86_64) 6 | #error 7 | #endif 8 | 9 | /** manifest: 10 | expand_error 11 | args = -target x86-linux-gnu --emulate=clang 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/binary literal.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | 0b11; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = -Wpedantic -std=c17 8 | 9 | binary literal.c:2:3: warning: binary integer literals are a C23 extension [-Wc23-extensions] 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/gnuc version default msvc.c: -------------------------------------------------------------------------------- 1 | #if defined(__GNUC__) || defined(__GNUC_MINOR__) || defined(__GNUC_PATCHLEVEL__) 2 | #error "__GNUC__ macros should not be defined" 3 | #endif 4 | 5 | /** manifest: 6 | syntax 7 | args = --emulate=msvc 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/var args macro functions.c: -------------------------------------------------------------------------------- 1 | #define foo(a,...) #__VA_ARGS__ 2 | foo(1,2,3,4,5,6) 3 | 4 | #define bar(a,...) bar __VA_ARGS__ 5 | #define baz(a,...) baz bar(__VA_ARGS__) 6 | baz(1,2,3,4) 7 | 8 | /** manifest: 9 | expand 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/float values.c: -------------------------------------------------------------------------------- 1 | _Static_assert(-1.0 - 1.0 == -2.0, ""); 2 | _Static_assert(-2.0f == -2.0, ""); 3 | _Static_assert(1.0 == (2.0||0), ""); 4 | void foo(void) { 5 | float f = 2.0 || 0; 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/redefine invalid typedef.c: -------------------------------------------------------------------------------- 1 | typedef float *invalid1 __attribute__((vector_size(8))); 2 | typedef float invalid1; 3 | 4 | /** manifest: 5 | syntax 6 | 7 | redefine invalid typedef.c:1:40: error: invalid vector element type 'float *' 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/pie1.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__pic__ == 1, ""); 2 | _Static_assert(__PIC__ == 1, ""); 3 | _Static_assert(__pie__ == 1, ""); 4 | _Static_assert(__PIE__ == 1, ""); 5 | 6 | /** manifest: 7 | syntax 8 | args = --target=x86_64-linux-gnu -fpie 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/pie2.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__pic__ == 2, ""); 2 | _Static_assert(__PIC__ == 2, ""); 3 | _Static_assert(__pie__ == 2, ""); 4 | _Static_assert(__PIE__ == 2, ""); 5 | 6 | /** manifest: 7 | syntax 8 | args = --target=x86_64-linux-gnu -fPIE 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/predefined macros.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | _Static_assert(__STDC_VERSION__ == 199901, "__STDC_VERSION__ is incorrect"); 3 | (void)__DATE__; 4 | (void)__TIME__; 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | args = -std=c99 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/missing type specifier.c: -------------------------------------------------------------------------------- 1 | static x = 5; 2 | 3 | /** manifest: 4 | syntax 5 | args = -std=c17 6 | 7 | missing type specifier.c:1:8: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/nested invalid struct layout.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | Bar bar; 3 | }; 4 | 5 | struct Baz { 6 | struct Foo foo; 7 | }; 8 | 9 | /** manifest: 10 | syntax 11 | 12 | nested invalid struct layout.c:2:5: error: unknown type name 'Bar' 13 | */ 14 | -------------------------------------------------------------------------------- /include/stdbool.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | 5 | #if __STDC_VERSION__ < 202311L 6 | #define bool _Bool 7 | 8 | #define true 1 9 | #define false 0 10 | 11 | #define __bool_true_false_are_defined 1 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /test/cases/c23 true false ast.c: -------------------------------------------------------------------------------- 1 | bool a = true; 2 | bool b = false; 3 | bool c = 0; 4 | bool d = 1; 5 | 6 | int e = true; 7 | int f = false; 8 | 9 | int g = true + 1; 10 | 11 | /** manifest: 12 | syntax 13 | args = -std=c23 --target=x86_64-linux-gnu 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/enum attributes gcc.c: -------------------------------------------------------------------------------- 1 | enum __attribute__((vector_size(32))) VectorSize2 { 2 | A 3 | }; 4 | 5 | /** manifest: 6 | syntax 7 | args = --emulate=gcc 8 | 9 | enum attributes gcc.c:1:21: error: invalid vector element type 'enum VectorSize2' 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/expanded/standard-redefinition-reexamination-example.c: -------------------------------------------------------------------------------- 1 | f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); 2 | f(2 * (2+(3,4)-0,1)) | f(2 * (\~{ } 5)) & f(2 * (0,1)) 3 | ^m(0,1); 4 | int i[] = { 1, 23, 4, 5, }; 5 | char c[2][6] = { "hello", "" }; 6 | -------------------------------------------------------------------------------- /test/cases/float eval method.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | float a = 1.0f, b = 2.0f; 3 | float c = a + b; 4 | _Complex float ca = 0.0f; 5 | ca = ca + a; 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | args = -ffp-eval-method=double --target=x86_64-linux-gnu 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/integer conversions 32bit.c: -------------------------------------------------------------------------------- 1 | #include "include/test_helpers.h" 2 | 3 | void foo(void) { 4 | EXPECT_TYPE(1U + 1L, unsigned long); 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | args = --target=x86-linux-gnu -Wno-c23-extensions -I include 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/no declarations.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic warning "-Wempty-translation-unit" 2 | 3 | /** manifest: 4 | syntax 5 | 6 | no declarations.c:2:58: warning: ISO C requires a translation unit to contain at least one declaration [-Wempty-translation-unit] 7 | */ 8 | -------------------------------------------------------------------------------- /test/cases/unterminated macro function at eof gcc.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | expand_error 3 | args = --emulate=gcc 4 | 5 | unterminated macro function at eof gcc.c:9:1: error: unterminated function macro argument list 6 | */ 7 | 8 | #define foo(X) X 9 | foo(1, 10 | -------------------------------------------------------------------------------- /test/cases/c23 stdarg.c: -------------------------------------------------------------------------------- 1 | #include 2 | void foo(...) { 3 | va_list va, new; 4 | va_start(va); 5 | int arg = va_arg(va, int); 6 | va_copy(va, new); 7 | va_end(va); 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | args = -std=c23 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/msvc flexible array in union.c: -------------------------------------------------------------------------------- 1 | union Foo { 2 | int x; 3 | float y[]; 4 | long z; 5 | }; 6 | 7 | union Bar { 8 | int x[]; 9 | float y[]; 10 | }; 11 | 12 | /** manifest: 13 | syntax 14 | args = --target=x86_64-windows-msvc 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/optimize define.c: -------------------------------------------------------------------------------- 1 | #if !defined(__OPTIMIZE__) 2 | #error Optimize flag not defined 3 | #endif 4 | 5 | #if defined(__OPTIMIZE_SIZE__) 6 | #error Optimize size flag should not be defined 7 | #endif 8 | 9 | /** manifest: 10 | syntax 11 | args = -O 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/unterminated macro function at eof clang.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | expand_error 3 | args = --emulate=clang 4 | 5 | unterminated macro function at eof clang.c:9:1: error: unterminated function macro argument list 6 | */ 7 | 8 | #define foo(X) X 9 | foo(1, 10 | -------------------------------------------------------------------------------- /include/stdalign.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | #if __STDC_VERSION__ < 202311L 5 | 6 | #define alignas _Alignas 7 | #define alignof _Alignof 8 | 9 | #define __alignas_is_defined 1 10 | #define __alignof_is_defined 1 11 | #endif 12 | -------------------------------------------------------------------------------- /test/cases/macro token pasting order.c: -------------------------------------------------------------------------------- 1 | #define CAT(a, ...) a ## __VA_ARGS__ 2 | #define M(val) val 3 | #define TEST(c) CAT(TEST_, c) 4 | #define abc 1 5 | 6 | TEST(M(0)) 7 | CAT(TEST_, M(0)) 8 | CAT(ab, c) 9 | CAT(a b, c) 10 | 11 | /** manifest: 12 | expand 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/no optimizations.c: -------------------------------------------------------------------------------- 1 | #if defined(__OPTIMIZE__) 2 | #error Optimize flag should not be defined 3 | #endif 4 | 5 | 6 | #if defined(__OPTIMIZE_SIZE__) 7 | #error Optimize size flag should not be defined 8 | #endif 9 | 10 | /** manifest: 11 | syntax 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/standard-placeholder-example.c: -------------------------------------------------------------------------------- 1 | // example from the C18 standard draft, 6.10.3.5, example 5 2 | #define t(x,y,z) x ## y ## z 3 | int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), 4 | t(10,,), t(,11,), t(,,12), t(,,) }; 5 | 6 | /** manifest: 7 | expand 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/#elifdef.c: -------------------------------------------------------------------------------- 1 | #ifdef FOO 2 | long long 3 | #elifdef FOO 4 | long 5 | #elifndef FOO 6 | int 7 | #endif 8 | 9 | #define BAR 10 | #ifdef FOO 11 | long long 12 | #elifdef BAR 13 | long 14 | #elifndef FOO 15 | int 16 | #endif 17 | 18 | /** manifest: 19 | expand 20 | */ 21 | -------------------------------------------------------------------------------- /test/cases/builtin headers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | /* a */ # /* b */ include /* c */ 6 | 7 | #define HEADER 8 | #include HEADER 9 | 10 | /** manifest: 11 | syntax 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/decayed attributed array.c: -------------------------------------------------------------------------------- 1 | __attribute__((aligned)) int arr[1] = {0}; 2 | int *ptr = arr; 3 | 4 | void foo(void) { 5 | _Alignas(8) char x[64]; 6 | char *y = &(x)[0]; 7 | } 8 | 9 | /** manifest: 10 | syntax 11 | args = --target=x86_64-linux-gnu 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/gnu variadic macros.c: -------------------------------------------------------------------------------- 1 | #define a(foo, args...) #args, foo __VA_ARGS__ args 2 | a(1,2,3,4) 3 | 4 | /** manifest: 5 | expand 6 | args = -Wpedantic 7 | 8 | gnu variadic macros.c:1:20: warning: named variadic macros are a GNU extension [-Wvariadic-macros] 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/incorrect guard.c: -------------------------------------------------------------------------------- 1 | #include "incorrect_guard.h" 2 | #include "incorrect_guard.h" 3 | 4 | /** manifest: 5 | syntax 6 | args = -I include 7 | 8 | incorrect_guard.h:3:5: error: redefinition of 'x' 9 | incorrect_guard.h:3:5: note: previous definition is here 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/zero argument macro.c: -------------------------------------------------------------------------------- 1 | #define NO_ARGUMENTS() 2 | 3 | NO_ARGUMENTS() 4 | NO_ARGUMENTS( ) 5 | NO_ARGUMENTS( 6 | 7 | ) 8 | NO_ARGUMENTS(1) 9 | 10 | /** manifest: 11 | expand_error 12 | 13 | zero argument macro.c:8:1: error: expected 0 argument(s) got 1 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/optimize size flags.c: -------------------------------------------------------------------------------- 1 | #if !defined(__OPTIMIZE__) 2 | #error Optimize flag should be defined 3 | #endif 4 | 5 | 6 | #if !defined(__OPTIMIZE_SIZE__) 7 | #error Optimize size flag should be defined 8 | #endif 9 | 10 | /** manifest: 11 | syntax 12 | args = -Os 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/unspecified expansion.c: -------------------------------------------------------------------------------- 1 | // This can either expand as 2*f(9) or as 2*9*g (see 6.10.3.4 in the standard) 2 | // We follow gcc and clang in expanding it to 2*9*g 3 | 4 | #define f(a) a*g 5 | #define g(a) f(a) 6 | 7 | f(2)(9) 8 | 9 | /** manifest: 10 | expand 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/array of invalid.c: -------------------------------------------------------------------------------- 1 | _BitInt(0) a[]; 2 | _BitInt(0) b[10]; 3 | 4 | /** manifest: 5 | syntax 6 | 7 | array of invalid.c:1:1: error: signed _BitInt must have a bit size of at least 2 8 | array of invalid.c:2:1: error: signed _BitInt must have a bit size of at least 2 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/expanded/standard-concatenation-strings-example.c: -------------------------------------------------------------------------------- 1 | printf("x" "1" "= %d, x" "2" "= %s", x1, x2); 2 | fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" 3 | ": @\n", s); 4 | "vers2.h" 5 | "vers2 . h" 6 | "INCFILE(2).h" 7 | "INCFILE(2) . h" 8 | "hello"; 9 | "hello" ", world" 10 | -------------------------------------------------------------------------------- /test/cases/ignored attributes.c: -------------------------------------------------------------------------------- 1 | __attribute__((malloc)) int foo(void); 2 | __attribute__((malloc)) int *bar(void); 3 | 4 | /** manifest: 5 | syntax 6 | 7 | ignored attributes.c:1:16: warning: attribute 'malloc' ignored on functions that do not return pointers [-Wignored-attributes] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/include/test_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define EXPECT_TYPE(EXPR, TYPE) _Static_assert(__builtin_types_compatible_p(__typeof__(EXPR), TYPE), "") 4 | 5 | #define CAT(X, Y) XCAT(X, Y) 6 | #define XCAT(X, Y) X ## Y 7 | 8 | #define STR(X) XSTR(X) 9 | #define XSTR(X) #X 10 | -------------------------------------------------------------------------------- /test/cases/pic1.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__pic__ == 1, ""); 2 | _Static_assert(__PIC__ == 1, ""); 3 | #if defined __pie__ || defined __PIE__ 4 | #error __pie__ and __PIE__ should not be defined 5 | #endif 6 | 7 | /** manifest: 8 | syntax 9 | args = --target=x86_64-linux-gnu -fpic 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/pic2.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__pic__ == 2, ""); 2 | _Static_assert(__PIC__ == 2, ""); 3 | #if defined __pie__ || defined __PIE__ 4 | #error __pie__ and __PIE__ should not be defined 5 | #endif 6 | 7 | /** manifest: 8 | syntax 9 | args = --target=x86_64-linux-gnu -fPIC 10 | */ 11 | -------------------------------------------------------------------------------- /deps/zig/lib.zig: -------------------------------------------------------------------------------- 1 | pub const arch = struct { 2 | pub const x86_64 = struct { 3 | pub const abi = @import("arch/x86_64/abi.zig"); 4 | pub const bits = @import("arch/x86_64/bits.zig"); 5 | }; 6 | }; 7 | pub const RegisterManager = @import("register_manager.zig").RegisterManager; 8 | -------------------------------------------------------------------------------- /test/cases/duplicate typedef.c: -------------------------------------------------------------------------------- 1 | typedef long foo; 2 | typedef long foo; 3 | _Static_assert(__builtin_types_compatible_p(long, foo), ""); 4 | 5 | typedef foo bar; 6 | typedef foo bar; 7 | _Static_assert(__builtin_types_compatible_p(bar, foo), ""); 8 | 9 | /** manifest: 10 | syntax 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/guard undef.c: -------------------------------------------------------------------------------- 1 | #include "correct_guard.h" 2 | #undef CORRECT_GUARD_H 3 | #include "correct_guard.h" 4 | 5 | /** manifest: 6 | syntax 7 | args = -I include 8 | 9 | correct_guard.h:3:5: error: redefinition of 'x' 10 | correct_guard.h:3:5: note: previous definition is here 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/msvc boolean bitfield.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | _Bool a: 4; 3 | _Bool : 2; 4 | _Bool c: 2; 5 | } S; 6 | 7 | _Static_assert(sizeof(S) == 1, ""); 8 | _Static_assert(_Alignof(S) == 1, ""); 9 | 10 | /** manifest: 11 | syntax 12 | args = --target=x86_64-windows-msvc 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/#elifndef.c: -------------------------------------------------------------------------------- 1 | #ifdef FOO 2 | long long 3 | #elifdef FOO 4 | long 5 | #elifndef FOO 6 | int 7 | #endif 8 | 9 | #define BAR 10 | #ifdef FOO 11 | long long 12 | #elifdef BAR 13 | long 14 | #elifndef FOO 15 | int 16 | #endif 17 | 18 | /** manifest: 19 | expand 20 | args = -std=c23 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/missing newline before eof.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | 4 | missing newline before eof.c:9:8: warning: no newline at end of file [-Wnewline-eof] 5 | missing newline before eof.c:9:8: error: expected ';' before end of file 6 | */ 7 | #pragma GCC diagnostic warning "-Wnewline-eof" 8 | 9 | int foo -------------------------------------------------------------------------------- /test/cases/#if expression macro ws.c: -------------------------------------------------------------------------------- 1 | #define FOO(X) X 2 | 3 | #if FOO( X ) 4 | #error Should not error 5 | #endif 6 | 7 | #define Y 1 8 | 9 | #if FOO ( Y ) 10 | #error Should error 11 | #endif 12 | 13 | /** manifest: 14 | syntax 15 | 16 | #if expression macro ws.c:10:2: error: Should error 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/comma operator.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | char a[1]; 3 | _Static_assert(sizeof(((void)0, a)) == sizeof(char *), ""); 4 | const int x = 0; 5 | __typeof__(((void) 0, x)) y = 5; 6 | y = 2; 7 | } 8 | 9 | /** manifest: 10 | syntax 11 | args = -Wno-sizeof-array-argument 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/complex numbers gcc.c: -------------------------------------------------------------------------------- 1 | void foo(int x, float y) { 2 | _Static_assert(__imag(42) == 0); 3 | _Static_assert(__imag(42.0) == 0.0); 4 | _Static_assert(__imag(x) == 0); 5 | _Static_assert(__imag(y) == 0); 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | args = -std=c23 --emulate=gcc 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/complex float16.c: -------------------------------------------------------------------------------- 1 | _Static_assert(3.0f16 + 4.0if16 == 2.0f16 + 1.0f16 + 2.0if16 + 2.0if16); 2 | constexpr _Complex _Float16 f = 2.0f16 + 4.0if16; 3 | constexpr _Complex _Float16 f2 = (2.0f16 - 4.0if16); 4 | _Static_assert(f * f2 == 20.f16); 5 | 6 | /** manifest: 7 | syntax 8 | args = -std=c23 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/float array size.c: -------------------------------------------------------------------------------- 1 | void foo(float f) { 2 | int bar[2.0] = {0}; 3 | int baz[f]; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | 9 | float array size.c:2:13: error: size of array has non-integer type 'double' 10 | float array size.c:3:13: error: size of array has non-integer type 'float' 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/switch unsigned int.c: -------------------------------------------------------------------------------- 1 | int lottery(unsigned int x) { 2 | switch (x) { 3 | case 3: return 0; 4 | case -1: return 3; 5 | case 8 ... 10: return x; 6 | default: return -1; 7 | } 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | args = --target=x86_64-linux-gnu 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/whitespace macro arguments.c: -------------------------------------------------------------------------------- 1 | #define h() 1 2 | #define g(x) x 3 | #define f(x, y) g(y) x 4 | 5 | #define p(...) h(__VA_ARGS__) 6 | #define q(e, ...) f(e, __VA_ARGS__) 7 | 8 | h() 9 | g() 10 | f(1,) 11 | f(1,q) 12 | f(,) 13 | p() 14 | q(3, 2) 15 | q(, 3) 16 | 17 | /** manifest: 18 | expand 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/__has_attribute with define.c: -------------------------------------------------------------------------------- 1 | #define foo __has_attribute(used) 2 | #define bar 1 + __has_attribute(does_not_exist) 3 | #define HASATTR(X) __has_attribute(X) 4 | #define HASATTR2(X, Y) __has_attribute(X ## Y) 5 | foo 6 | bar 7 | HASATTR(used) 8 | HASATTR2(us, ed) 9 | 10 | /** manifest: 11 | expand 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/attributed typeof.c: -------------------------------------------------------------------------------- 1 | typedef __attribute__((aligned(16))) int aligned_int; 2 | 3 | void foo(void) { 4 | aligned_int a; 5 | __attribute__((aligned(16))) int b; 6 | typeof(a) c; 7 | typeof(aligned_int) d; 8 | typeof(b) e; 9 | } 10 | 11 | /** manifest: 12 | syntax 13 | args = -target x86_64-linux 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/generic ast.c: -------------------------------------------------------------------------------- 1 | int x = _Generic(5, 2 | int: 42, 3 | double: 32.5 4 | ); 5 | 6 | int y = _Generic(5, 7 | int: 42, 8 | double: 32.5, 9 | default: "string" 10 | ); 11 | 12 | double z = _Generic(5, 13 | default: 32 14 | ); 15 | 16 | /** manifest: 17 | syntax 18 | args = --target=x86_64-linux-gnu 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/main wrong return type.c: -------------------------------------------------------------------------------- 1 | float main(void) { 2 | 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | 8 | main wrong return type.c:1:7: warning: return type of 'main' is not 'int' [-Wmain-return-type] 9 | main wrong return type.c:3:1: warning: non-void function 'main' does not return a value [-Wreturn-type] 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/__is_target_os.c: -------------------------------------------------------------------------------- 1 | #if !__is_target_os(linux) 2 | #error Target should be linux! 3 | #endif 4 | 5 | #if __is_target_os(windows) || __is_target_os(macos) 6 | #error Target should not be windows or macos! 7 | #endif 8 | 9 | /** manifest: 10 | expand_error 11 | args = --target=x86_64-linux --emulate=clang 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/array designator too large.c: -------------------------------------------------------------------------------- 1 | int arr1[] = { [0x800000000000000 - 1] = 0 }; 2 | int arr2[] = { [0x800000000000000 - 2] = 0 }; 3 | _Static_assert(sizeof(arr1), ""); 4 | _Static_assert(sizeof(arr2), ""); 5 | 6 | /** manifest: 7 | syntax 8 | 9 | array designator too large.c:1:14: error: array is too large 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/expanded/__line__.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int x = 6; 3 | int y = 10; 4 | int z = 12; 5 | } 6 | static int line1 = 20; 7 | static int line2 = 100; 8 | static char *file1 = "foo.c"; 9 | static int line3 = 1; 10 | static int line4 = 200; 11 | static char *file2 = "bar.c"; 12 | static int line5 = 105; 13 | -------------------------------------------------------------------------------- /test/cases/macro expansion disabled.c: -------------------------------------------------------------------------------- 1 | #define EMPTY() 2 | #define LOOP_INDIRECTION() LOOP 3 | #define LOOP(x) x LOOP_INDIRECTION EMPTY()() (x) 4 | LOOP(1) 5 | 6 | #define DEFER(id) id EMPTY() 7 | #define EXPAND(...) __VA_ARGS__ 8 | 9 | #define A() 123 10 | EXPAND(DEFER(A)()) 11 | 12 | /** manifest: 13 | expand 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/preserve comments.c: -------------------------------------------------------------------------------- 1 | #define a() 1 /*foo*/ ## /*bar*/ 2 2 | a() 3 | 4 | #define b 1 /*foo*/ ## /*bar*/ 2 5 | b 6 | 7 | #define c() 1 /*foo*/ 8 | c() 9 | 10 | #define d 1 /*foo*/ 11 | d 12 | 13 | #define e(p) p ## 1 14 | 15 | e(hello/*foo*/) 16 | 17 | /** manifest: 18 | expand_partial 19 | args = -C 20 | */ 21 | -------------------------------------------------------------------------------- /include/iso646.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | 5 | #define and && 6 | #define and_eq &= 7 | #define bitand & 8 | #define bitor | 9 | #define compl ~ 10 | #define not ! 11 | #define not_eq != 12 | #define or || 13 | #define or_eq |= 14 | #define xor ^ 15 | #define xor_eq ^= 16 | -------------------------------------------------------------------------------- /test/cases/hello world.c: -------------------------------------------------------------------------------- 1 | extern int printf(const char*, ...); 2 | static int foo(void); 3 | 4 | int main(int argc, char **argv) { 5 | return foo(); 6 | } 7 | 8 | static int foo(void) { 9 | printf("Hello, world!\n"); 10 | return 0; 11 | } 12 | 13 | /** manifest: 14 | compare_output 15 | 16 | Hello, world! 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/cast to same type.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | int x; 3 | }; 4 | 5 | void foo(void) { 6 | struct S s = {.x = 5 }; 7 | s = (struct S)s; 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | args = -pedantic 13 | 14 | cast to same type.c:7:9: warning: C99 forbids casting nonscalar type 'struct S' to the same type [-Wpedantic] 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/__has_feature.c: -------------------------------------------------------------------------------- 1 | #if defined __has_feature 2 | # if __has_feature(enumerator_attributes) 3 | #error feature exists 4 | # endif 5 | # if __has_feature(does_not_exist) 6 | #error feature exists 7 | # endif 8 | #endif 9 | 10 | /** manifest: 11 | expand_error 12 | 13 | __has_feature.c:3:8: error: feature exists 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/pragma changes warning to error in parser.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic error "-Wint-conversion" 2 | void foo(void) { 3 | int *x = 5; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | 9 | pragma changes warning to error in parser.c:3:11: error: implicit integer to pointer conversion from 'int' to 'int *' [-Werror,-Wint-conversion] 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/__has_extension.c: -------------------------------------------------------------------------------- 1 | #if defined __has_extension 2 | # if __has_extension(c_alignas) 3 | #error extension exists 4 | # endif 5 | # if __has_extension(does_not_exist) 6 | #error extension exists 7 | # endif 8 | #endif 9 | 10 | /** manifest: 11 | expand_error 12 | 13 | __has_extension.c:3:8: error: extension exists 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/iquote.c: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #error Should not find this 3 | #endif 4 | 5 | #if !__has_include("iquote_test.h") 6 | #error Should find this 7 | #endif 8 | 9 | #include "iquote_test.h" 10 | _Static_assert(FOO == 42, "FOO is incorrect"); 11 | 12 | /** manifest: 13 | syntax 14 | args = -iquote include/iquote 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/fp16 parameter.c: -------------------------------------------------------------------------------- 1 | __fp16 foo(__fp16 param) { 2 | return 0; 3 | } 4 | 5 | /** manifest: 6 | syntax 7 | args = --target=x86_64-linux-gnu 8 | 9 | fp16 parameter.c:1:19: error: parameters cannot have __fp16 type; did you forget * ? 10 | fp16 parameter.c:1:11: error: function return value cannot have __fp16 type; did you forget * ? 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/non string attribute.c: -------------------------------------------------------------------------------- 1 | enum E { 2 | is_deprecated_with_msg __attribute__((deprecated("I am deprecated" = 5 ))), 3 | }; 4 | 5 | /** manifest: 6 | syntax 7 | 8 | non string attribute.c:2:71: error: array type 'char [16]' is not assignable 9 | non string attribute.c:2:53: error: attribute 'deprecated' requires an ordinary string 10 | */ 11 | -------------------------------------------------------------------------------- /include/stdckdint.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | 5 | #define __STDC_VERSION_STDCKDINT_H__ 202311L 6 | 7 | #define ckd_add(result, a, b) __builtin_add_overflow(a, b, result) 8 | #define ckd_sub(result, a, b) __builtin_sub_overflow(a, b, result) 9 | #define ckd_mul(result, a, b) __builtin_mul_overflow(a, b, result) 10 | -------------------------------------------------------------------------------- /test/cases/macro backtrace limit.c: -------------------------------------------------------------------------------- 1 | #define FOO(X) X 2 | FOO(2) 3 | 4 | /** manifest: 5 | syntax 6 | args = -fmacro-backtrace-limit=1 7 | 8 | macro backtrace limit.c:2:1: error: expected external declaration 9 | note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) 10 | macro backtrace limit.c:2:5: note: expanded from here 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/typeof pointer wrong size.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | char arr[10]; 3 | typeof(const int) *p = arr; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | 9 | typeof pointer wrong size.c:3:28: warning: incompatible pointer types initializing 'typeof(const int) *' (aka 'const int *') from incompatible type 'char [10]' [-Wincompatible-pointer-types] 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/enum pointer.c: -------------------------------------------------------------------------------- 1 | enum E { 2 | A, 3 | }; 4 | 5 | void foo(void) { 6 | int x; 7 | unsigned y; 8 | enum E *p1 = &x; 9 | enum E *p2 = &y; 10 | } 11 | 12 | /** manifest: 13 | syntax 14 | 15 | enum pointer.c:8:18: warning: incompatible pointer types initializing 'enum E *' from incompatible type 'int *' [-Wincompatible-pointer-types] 16 | */ 17 | -------------------------------------------------------------------------------- /test/cases/packed member address.c: -------------------------------------------------------------------------------- 1 | struct __attribute__((packed)) Foo { 2 | int x; 3 | }; 4 | struct Foo foo; 5 | int *p = &foo.x; 6 | 7 | 8 | /** manifest: 9 | syntax 10 | 11 | packed member address.c:5:10: warning: taking address of packed member 'x' of class or structure 'Foo' may result in an unaligned pointer value [-Waddress-of-packed-member] 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/pragma during parsing.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | #pragma GCC diagnostic error "-Wint-conversion" 3 | int *x = 5; 4 | #pragma GCC diagnostic ignored "-Wint-conversion" 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | 10 | pragma during parsing.c:3:14: error: implicit integer to pointer conversion from 'int' to 'int *' [-Werror,-Wint-conversion] 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/deferred macro expansion.c: -------------------------------------------------------------------------------- 1 | #define F(acc) F_PROGRESS(acc) 2 | #define F_PROGRESS(acc) CONTINUE(F)(acc##X) 3 | #define F_HOOK() F 4 | #define UNROLL(...) __VA_ARGS__ 5 | #define DEFER(op) op EMPTY 6 | #define EMPTY 7 | #define CONTINUE(k) DEFER(k##_HOOK)() 8 | 9 | UNROLL(F_PROGRESS(X)) 10 | 11 | /** manifest: 12 | expand 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/include pragma.c: -------------------------------------------------------------------------------- 1 | #include _Pragma("once") 2 | #include __pragma(once) 3 | 4 | /** manifest: 5 | syntax 6 | args = -fms-extensions 7 | 8 | include pragma.c:1:10: error: expected "FILENAME" or 9 | include pragma.c:2:19: warning: #pragma once in main file [-Wpragma-once-outside-header] 10 | include pragma.c:2:10: error: expected "FILENAME" or 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/macro argument evaluation.c: -------------------------------------------------------------------------------- 1 | #define FOO(X) X##OK 2 | #define BAR FOO 3 | 4 | #define A 1 5 | 6 | #if BAR(A) 7 | #error Should not error 8 | #endif 9 | 10 | BAR(A) 11 | 12 | #define AOK 1 13 | #if BAR(A) 14 | #error Should error 15 | #endif 16 | 17 | BAR(A) 18 | 19 | /** manifest: 20 | expand_error 21 | 22 | macro argument evaluation.c:14:2: error: Should error 23 | */ 24 | -------------------------------------------------------------------------------- /test/cases/stdckdint_ast.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void foo(void) { 4 | char x = 0; 5 | unsigned y = 2; 6 | _Bool overflowed; 7 | long res; 8 | 9 | overflowed = ckd_add(&res, x, y); 10 | overflowed = ckd_sub(&res, x, y); 11 | overflowed = ckd_mul(&res, x, y); 12 | } 13 | 14 | /** manifest: 15 | syntax 16 | args = --target=x86_64-linux-gnu 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/typeof quals.c: -------------------------------------------------------------------------------- 1 | void test_typeof_quals(void) { 2 | const int a; 3 | typeof(a) b; 4 | volatile int c; 5 | typeof(c) d; 6 | register int e; 7 | typeof(e) f; 8 | (void)&f; 9 | _Atomic int g; 10 | typeof(g) h; 11 | int *restrict i = 0; 12 | typeof(i) j; 13 | } 14 | 15 | /** manifest: 16 | syntax 17 | args = -target x86_64-linux 18 | */ 19 | -------------------------------------------------------------------------------- /src/aro/Builtins/xcore.def: -------------------------------------------------------------------------------- 1 | # Generated from clang/include/clang/Basic/BuiltinsXCore.def 2 | 3 | __builtin_bitrev 4 | .param_str = "UiUi" 5 | .attributes = .{ .@"const" = true } 6 | 7 | __builtin_getid 8 | .param_str = "Si" 9 | .attributes = .{ .@"const" = true } 10 | 11 | __builtin_getps 12 | .param_str = "UiUi" 13 | 14 | __builtin_setps 15 | .param_str = "vUiUi" 16 | -------------------------------------------------------------------------------- /test/cases/stringify invalid.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | 3 | #define str(s) # s 4 | #define xstr(s) str(s) 5 | 6 | #define INCFILE(n) "ok\ 7 | vers ## n 8 | 9 | xstr(INCFILE(a)) 10 | } 11 | 12 | /** manifest: 13 | syntax 14 | 15 | stringify invalid.c:6:20: warning: missing terminating '"' character [-Winvalid-pp-token] 16 | stringify invalid.c:10:1: error: expected ';', found '}' 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/compound stmt fallthrough.c: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int x = 5; 3 | switch (x) { 4 | case 1: { 5 | __attribute__((fallthrough)); 6 | } 7 | case 2: { 8 | __attribute__((fallthrough));; 9 | } 10 | default: { 11 | 12 | } 13 | } 14 | return 0; 15 | } 16 | 17 | /** manifest: 18 | syntax 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/indirect macro invocation wrong arg count.c: -------------------------------------------------------------------------------- 1 | #define h(x) x(0) 2 | #define s() 3 | h(s) 4 | 5 | /** manifest: 6 | expand_error 7 | 8 | indirect macro invocation wrong arg count.c:3:1: error: expected 0 argument(s) got 1 9 | indirect macro invocation wrong arg count.c:1:14: note: expanded from here 10 | indirect macro invocation wrong arg count.c:3:3: note: expanded from here 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/macro expands to self after pasting.c: -------------------------------------------------------------------------------- 1 | #define CAT_PREFIX2(a,b) a ## b 2 | #define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) 3 | 4 | #define speex_resampler_init CAT_PREFIX(speex,_resampler_init) 5 | #define speex_resampler_init_frac CAT_PREFIX(speex,_resampler_init_frac) 6 | 7 | void speex_resampler_init(void); 8 | void speex_resampler_init_frac(void); 9 | 10 | /** manifest: 11 | expand 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/integer literal promotion warning clang.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__builtin_types_compatible_p(typeof(18446744073709550592), unsigned long long), ""); 2 | 3 | /** manifest: 4 | syntax 5 | args = --emulate=clang 6 | 7 | integer literal promotion warning clang.c:1:52: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/void star.c: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | extern int func(int *); 3 | extern int func1(void *); 4 | int * foo(void) { 5 | int *a = NULL; 6 | func(NULL); 7 | return NULL; 8 | } 9 | int *bar(void *a) { 10 | int *b = a; 11 | func(a); 12 | return a; 13 | } 14 | void *baz(int *a) { 15 | void *b = a; 16 | func(a); 17 | return a; 18 | } 19 | 20 | /** manifest: 21 | syntax 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/function macro expansion.c: -------------------------------------------------------------------------------- 1 | #define HE HI 2 | #define LLO _THERE 3 | #define HELLO "HI THERE" 4 | #define CAT(a,b) a##b 5 | #define XCAT(a,b) CAT(a,b) 6 | #define CALL(fn) fn(HE,LLO) 7 | CAT(HE, LLO) 8 | XCAT(HE, LLO) 9 | CALL(CAT) 10 | 11 | #define FOO(a, b) BAR(a, b) 12 | #define BAR(a, b) a, b 13 | 14 | FOO(1, (2, 3)) 15 | 16 | #define S(...) S() 17 | S() 18 | 19 | /** manifest: 20 | expand 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/gnu designated init extension.c: -------------------------------------------------------------------------------- 1 | int x[] = {[1] 2, [3] 4}; 2 | _Static_assert(sizeof(x) == sizeof(int[4]), "Incorrect array size"); 3 | 4 | /** manifest: 5 | syntax 6 | 7 | gnu designated init extension.c:1:16: warning: use of GNU 'missing =' extension in designator [-Wgnu-designator] 8 | gnu designated init extension.c:1:23: warning: use of GNU 'missing =' extension in designator [-Wgnu-designator] 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/integer literal promotion warning gcc 64.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__builtin_types_compatible_p(typeof(18446744073709550592), __int128), ""); 2 | 3 | /** manifest: 4 | syntax 5 | args = --emulate=gcc --target=x86_64-linux-gnu 6 | 7 | integer literal promotion warning gcc 64.c:1:52: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/linux __float128.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __float128 q = 0.0; 3 | _Float128 q2 = 0.0; 4 | 5 | q = 1.0q; 6 | q = 1.0f128; 7 | 8 | _Complex __float128 q3; 9 | q3 = 1.0Qi; 10 | q3 = 1.0iQ; 11 | q3 = 1.0f128i; 12 | q3 = 1.0IF128; 13 | } 14 | 15 | _Static_assert(1.F128 + 2.F128 == 3.F128, ""); 16 | 17 | /** manifest: 18 | syntax 19 | args = --target=x86_64-linux-gnu 20 | */ 21 | -------------------------------------------------------------------------------- /test/cases/unavailable results.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic push 2 | #pragma GCC diagnostic ignored "-Wunused-value" 3 | void foo(void) { 4 | 1.0f == 1.0f; 5 | (double)1 + 1U == 2.0; 6 | (_Complex float)1 + 2U; 7 | 1U + (int *)1; 8 | 1U + &2; 9 | } 10 | #pragma GCC diagnostic pop 11 | 12 | /** manifest: 13 | syntax 14 | 15 | unavailable results.c:8:10: error: cannot take the address of an rvalue 16 | */ 17 | -------------------------------------------------------------------------------- /test/cases/array argument too small.c: -------------------------------------------------------------------------------- 1 | void foo(int x[static 10]) { 2 | 3 | } 4 | 5 | void bar(void) { 6 | int x[5]; 7 | foo(x); 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | 13 | array argument too small.c:7:9: warning: array argument is too small; contains 5 elements, callee requires at least 10 [-Warray-bounds] 14 | array argument too small.c:1:14: note: callee declares array parameter as static here 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/integer literal promotion warning gcc 32.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__builtin_types_compatible_p(typeof(18446744073709550592), long long int), ""); 2 | 3 | /** manifest: 4 | syntax 5 | args = --emulate=gcc --target=riscv32-linux-gnu 6 | 7 | integer literal promotion warning gcc 32.c:1:52: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal] 8 | */ 9 | -------------------------------------------------------------------------------- /test/cases/#elifndef error.c: -------------------------------------------------------------------------------- 1 | #ifdef FOO 2 | #error invalid 3 | #elifdef 4 | #error invalid 5 | #else 6 | int 7 | #endif 8 | 9 | #define BAR 10 | #ifdef FOO 11 | #error invalid 12 | #elifndef 13 | #error invalid 14 | #else 15 | int 16 | #endif 17 | 18 | /** manifest: 19 | expand_error 20 | args = -std=c23 21 | 22 | #elifndef error.c:4:9: error: macro name missing 23 | #elifndef error.c:13:10: error: macro name missing 24 | */ 25 | -------------------------------------------------------------------------------- /test/cases/ms-extensions.c: -------------------------------------------------------------------------------- 1 | #include "include\other.h" 2 | 3 | #ifndef OTHER_INCLUDED 4 | #error backslash in include should work 5 | #endif 6 | 7 | #undef OTHER_INCLUDED 8 | #include "include/ms-ext/include other.h" 9 | 10 | #ifndef OTHER_INCLUDED 11 | #error Microsoft search rule should work 12 | #endif 13 |  14 | don't mind me ;) 15 | 16 | /** manifest: 17 | syntax 18 | args = -fms-extensions -Wno-microsoft-include 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/no dollars in identifiers.c: -------------------------------------------------------------------------------- 1 | #define foo$ bar 2 | void fib() { 3 | int foo$; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | args = -fno-dollars-in-identifiers 9 | 10 | no dollars in identifiers.c:1:12: warning: ISO C99 requires whitespace after the macro name [-Wc99-extensions] 11 | no dollars in identifiers.c:3:7: error: expected identifier or '(' 12 | no dollars in identifiers.c:1:12: note: expanded from here 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/tentative array.c: -------------------------------------------------------------------------------- 1 | int arr[]; 2 | 3 | _Static_assert(sizeof arr,""); 4 | 5 | int arr[3]; // TODO should make the warning go away 6 | 7 | /** manifest: 8 | syntax 9 | skip = TODO tentative array warning not removed 10 | 11 | tentative array.c:1:5: warning: tentative array definition assumed to have one element 12 | tentative array.c:3:16: error: invalid application of 'sizeof' to an incomplete type 'int []' 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/vla.c: -------------------------------------------------------------------------------- 1 | void foo(int x) { 2 | int arr[x]; 3 | } 4 | 5 | struct S { 6 | int x; 7 | int y[x]; 8 | }; 9 | 10 | void bar(int x) { 11 | int arr[2][3][x]; 12 | } 13 | 14 | /** manifest: 15 | syntax 16 | args = -Wvla 17 | 18 | vla.c:2:13: warning: variable length array used [-Wvla] 19 | vla.c:7:11: error: use of undeclared identifier 'x' 20 | vla.c:11:19: warning: variable length array used [-Wvla] 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/__float80 clang.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __float80 x; 3 | double y = 1.0w; 4 | _Complex double z = 2.0iw; 5 | } 6 | 7 | /** manifest: 8 | syntax 9 | args = --emulate=clang 10 | 11 | __float80 clang.c:2:5: error: use of undeclared identifier '__float80' 12 | __float80 clang.c:3:16: error: invalid suffix 'w' on floating constant 13 | __float80 clang.c:4:25: error: invalid suffix 'iw' on floating constant 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/char literal sign extension.c: -------------------------------------------------------------------------------- 1 | _Static_assert('\xFF' == -1, ""); 2 | _Static_assert(u8'\xFF' == 0xFF, ""); 3 | 4 | #if '\xFF' != -1 5 | #error comparison failed 6 | #endif 7 | 8 | #if u8'\xFF' != 0xFF 9 | #error comparison failed 10 | #endif 11 | 12 | _Static_assert('\x00\xFF' == 255, ""); 13 | _Static_assert('\xFF\xFF' == 65535, ""); 14 | 15 | /** manifest: 16 | syntax 17 | args = -std=c23 -fsigned-char -Wno-multichar 18 | */ 19 | -------------------------------------------------------------------------------- /test/cases/unterminated comment in preprocessor expression.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | 4 | unterminated comment in preprocessor expression.c:11:5: error: invalid token at start of a preprocessor expression 5 | unterminated comment in preprocessor expression.c:11:1: error: unterminated conditional directive 6 | unterminated comment in preprocessor expression.c:11:1: error: unterminated conditional directive 7 | */ 8 | 9 | #if /* 10 | 11 | -------------------------------------------------------------------------------- /test/cases/visibility.c: -------------------------------------------------------------------------------- 1 | int __attribute__((visibility("default"))) default_func(void) { 2 | return 0; 3 | } 4 | 5 | int __attribute__((visibility("hidden"))) hidden_global; 6 | 7 | int __attribute__((visibility("none"))) bad_visibility; 8 | 9 | /** manifest: 10 | syntax 11 | 12 | visibility.c:7:31: warning: unknown `visibility` argument. Possible values are: "default", "hidden", "internal", "protected" [-Wignored-attributes] 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/_BitInt change size.c: -------------------------------------------------------------------------------- 1 | _BitInt(10) x = 1.2; 2 | _Complex unsigned _BitInt(10) y = 1.2; 3 | 4 | /** manifest: 5 | syntax 6 | 7 | _BitInt change size.c:1:17: warning: implicit conversion from 'double' to 'signed _BitInt(10)' changes value from 1.2 to 1 [-Wfloat-conversion] 8 | _BitInt change size.c:2:35: warning: implicit conversion from 'double' to '_Complex unsigned _BitInt(10)' changes value from 1.2 to 1 [-Wfloat-conversion] 9 | */ 10 | -------------------------------------------------------------------------------- /test/cases/unexpected pragmas.c: -------------------------------------------------------------------------------- 1 | // This tests that pragmas in locations where the parser does not check for them 2 | // do not cause undefined behavior. See https://github.com/Vexu/arocc/issues/82 3 | // Parser improvements may reduce or eliminate the errors reported. 4 | 5 | int foo, 6 | #pragma bar bar 7 | int baz; 8 | #pragma qux 9 | 10 | /** manifest: 11 | syntax 12 | 13 | unexpected pragmas.c:6:2: error: expected identifier or '(' 14 | */ 15 | -------------------------------------------------------------------------------- /src/assembly_backend.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const aro = @import("aro"); 4 | 5 | pub const x86_64 = @import("assembly_backend/x86_64.zig"); 6 | 7 | pub fn genAsm(target: std.Target, tree: *const aro.Tree) aro.Compilation.Error!aro.Assembly { 8 | return switch (target.cpu.arch) { 9 | .x86_64 => x86_64.genAsm(tree), 10 | else => std.debug.panic("genAsm not implemented: {s}", .{@tagName(target.cpu.arch)}), 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /test/cases/__has_attribute.c: -------------------------------------------------------------------------------- 1 | #if defined __has_attribute 2 | # if __has_attribute(aligned) 3 | #error attribute exists 4 | # endif 5 | # if __has_attribute(does_not_exist) 6 | #error attribute exists 7 | # endif 8 | #endif 9 | 10 | #define FOO aligned 11 | #if !__has_attribute(FOO) 12 | # error should have attribute aligned 13 | #endif 14 | 15 | /** manifest: 16 | expand_error 17 | 18 | __has_attribute.c:3:8: error: attribute exists 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/unterminated string literal.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | 4 | unterminated string literal.c:9:12: warning: missing terminating '"' character [-Winvalid-pp-token] 5 | unterminated string literal.c:10:20: warning: missing terminating '"' character [-Winvalid-pp-token] 6 | unterminated string literal.c:11:12: warning: missing terminating '"' character [-Winvalid-pp-token] 7 | */ 8 | 9 | char A[] = "hello 10 | char B[] = "hello" "world 11 | char C[] = " -------------------------------------------------------------------------------- /test/cases/__is_target_variant.c: -------------------------------------------------------------------------------- 1 | #if !__is_target_variant_os(ios) 2 | #error 3 | #endif 4 | 5 | #if !__is_target_variant_os(macos) 6 | #error 7 | #endif 8 | 9 | #if !__is_target_variant_environment(macABI) 10 | #error 11 | #endif 12 | 13 | #if __is_target_variant_environment(none) 14 | #error 15 | #endif 16 | 17 | /** manifest: 18 | expand_error 19 | args = -target aarch64-macos-none --emulate=clang -darwin-target-variant-triple x86_64-ios.13.1-macabi 20 | */ 21 | -------------------------------------------------------------------------------- /test/cases/include/my_include.h: -------------------------------------------------------------------------------- 1 | #define FOO 1 2 | 3 | #include_next // include/next/my_include.h 4 | #include_next // include/next/other.h 5 | 6 | #if __has_include_next() 7 | #error "Should not exist" 8 | #endif 9 | 10 | #if __has_include_next() 11 | #define HAS_INCLUDE_NEXT_WORKED 1 12 | #endif 13 | 14 | #if __has_include_next("global_var.h") 15 | #error "Should not find this with include_next" 16 | #endif 17 | -------------------------------------------------------------------------------- /test/cases/intptr_t.c: -------------------------------------------------------------------------------- 1 | #include "test_helpers.h" 2 | 3 | _Static_assert(__INTPTR_MAX__ == 9223372036854775807L, ""); 4 | _Static_assert(__INTPTR_WIDTH__ == 64, ""); 5 | EXPECT_TYPE(__INTPTR_TYPE__, long); 6 | 7 | _Static_assert(__UINTPTR_MAX__ == 18446744073709551615UL, ""); 8 | _Static_assert(__UINTPTR_WIDTH__ == 64, ""); 9 | EXPECT_TYPE(__UINTPTR_TYPE__, unsigned long); 10 | 11 | /** manifest: 12 | syntax 13 | args = --target=x86_64-linux-gnu -I include 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/zero length array.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | int x; 3 | int y[0]; 4 | }; 5 | 6 | void foo(void) { 7 | struct S s; 8 | s.y[2] = 5; 9 | int z[0]; 10 | z[5] = 2; 11 | } 12 | 13 | /** manifest: 14 | syntax 15 | args = -Wzero-length-array 16 | 17 | zero length array.c:3:10: warning: zero size arrays are an extension [-Wzero-length-array] 18 | zero length array.c:9:10: warning: zero size arrays are an extension [-Wzero-length-array] 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/c23 attributes.c: -------------------------------------------------------------------------------- 1 | // Example adapted from N2956 - unsequenced functions 2 | 3 | extern double sqrt(double); 4 | 5 | inline double distance(double const x[static 2]) [[reproducible]] { 6 | extern double sqrt(double) [[unsequenced]]; 7 | return sqrt(x[0]*x[0] + x[1]*x[1]); 8 | } 9 | 10 | int main(void) { 11 | (void) sqrt(2.); 12 | (void) distance((double[]) {1., 2.}); 13 | } 14 | 15 | /** manifest: 16 | syntax 17 | args = -std=c23 18 | */ 19 | -------------------------------------------------------------------------------- /test/cases/undef.c: -------------------------------------------------------------------------------- 1 | #if defined(linux) || defined(__linux) || defined(__linux__) 2 | #error Should not be defined 3 | #endif 4 | 5 | int foo = __CHAR_BIT__; 6 | int bar = 100; 7 | 8 | int *someFunc(int x, int y) { return &bar; } 9 | 10 | struct Foo { 11 | int x: 3; 12 | int y; 13 | int z; 14 | }; 15 | 16 | /** manifest: 17 | syntax 18 | args = -undef --target=x86_64-linux-gnu 19 | 20 | undef.c:5:11: error: use of undeclared identifier '__CHAR_BIT__' 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/builtin choose expr.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int x, y; 3 | __builtin_choose_expr(1, x, 0/0) = 10; 4 | __builtin_choose_expr(0, x/0, y) = 32; 5 | __builtin_choose_expr(x, 1, 2); 6 | int z = __builtin_choose_expr(1>0, 1, (char *)5); 7 | float f = __builtin_choose_expr(0!=0, (char *)10, 1.0f); 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | 13 | builtin choose expr.c:5:27: error: '__builtin_choose_expr' requires a constant expression 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/calling convention.c: -------------------------------------------------------------------------------- 1 | __attribute__((sysv_abi)) void sysv_func(void); 2 | 3 | __attribute__((sysv_abi)) int x; 4 | 5 | 6 | typedef __attribute__((sysv_abi)) void (*fn_ptr_t)(void); 7 | void foo(__attribute__((sysv_abi)) void (*p)(void)) { 8 | __attribute__((sysv_abi)) void (*fn_ptr)(void); 9 | } 10 | 11 | /** manifest: 12 | syntax 13 | 14 | calling convention.c:3:16: warning: 'sysv_abi' only applies to function types; type here is 'int' [-Wignored-attributes] 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/unsigned char.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__CHAR_UNSIGNED__ == 1, ""); 2 | _Static_assert((char)-1 == 0xFF, "char should be unsigned"); 3 | 4 | #if '\0' - 1 < 0 5 | #error "preprocessor char literal is signed when it should be unsigned" 6 | #endif 7 | 8 | #if u'\0' - 1 < 0 9 | #error "preprocessor u8 char literal is signed when it should be unsigned" 10 | #endif 11 | 12 | /** manifest: 13 | syntax 14 | args = --target=x86_64-linux-gnu -funsigned-char -Wno-integer-overflow 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/anonymous_struct_ms.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | int a; 3 | } unnamed; 4 | typedef struct named { 5 | int b; 6 | } named; 7 | 8 | struct S { 9 | unnamed; 10 | named; 11 | }; 12 | 13 | /** manifest: 14 | syntax 15 | args = -fms-extensions 16 | 17 | anonymous_struct_ms.c:9:12: warning: anonymous structs are a Microsoft extension [-Wmicrosoft-anon-tag] 18 | anonymous_struct_ms.c:10:10: warning: anonymous structs are a Microsoft extension [-Wmicrosoft-anon-tag] 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/arithmetic conversion floats.c: -------------------------------------------------------------------------------- 1 | #include "include/test_helpers.h" 2 | 3 | void foo(void) { 4 | EXPECT_TYPE((long double)1 + 1.fi, _Complex long double); 5 | EXPECT_TYPE(1.i + 1.f, _Complex double); 6 | EXPECT_TYPE((long double)1 + 1., long double); 7 | EXPECT_TYPE(1.fi + 1.f, _Complex float); 8 | EXPECT_TYPE(1.f + 1.f, float); 9 | EXPECT_TYPE((long double)1.f + 1.f, long double); 10 | } 11 | 12 | /** manifest: 13 | syntax 14 | args = -I include 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/expanded/float header netbsd 6.99.26.c: -------------------------------------------------------------------------------- 1 | 2 | 15 3 | 2.2204460492503131e-16 4 | 53 5 | 308 6 | 1024 7 | 1.7976931348623157e+308 8 | (-307) 9 | (-1021) 10 | 2.2250738585072014e-308 11 | 21 12 | 6 13 | 1.19209290e-7F 14 | 24 15 | 38 16 | 128 17 | 3.40282347e+38F 18 | (-37) 19 | (-125) 20 | 1.17549435e-38F 21 | 2 22 | 18 23 | 1.08420217248550443401e-19L 24 | 64 25 | 4932 26 | 16384 27 | 1.18973149535723176502e+4932L 28 | (-4931) 29 | (-16381) 30 | 3.36210314311209350626e-4932L 31 | 1 32 | -------------------------------------------------------------------------------- /test/cases/expanded/float header x86-64-linux.c: -------------------------------------------------------------------------------- 1 | 2 | 15 3 | 2.2204460492503131e-16 4 | 53 5 | 308 6 | 1024 7 | 1.7976931348623157e+308 8 | (-307) 9 | (-1021) 10 | 2.2250738585072014e-308 11 | 21 12 | 6 13 | 1.19209290e-7F 14 | 24 15 | 38 16 | 128 17 | 3.40282347e+38F 18 | (-37) 19 | (-125) 20 | 1.17549435e-38F 21 | 2 22 | 18 23 | 1.08420217248550443401e-19L 24 | 64 25 | 4932 26 | 16384 27 | 1.18973149535723176502e+4932L 28 | (-4931) 29 | (-16381) 30 | 3.36210314311209350626e-4932L 31 | 0 32 | -------------------------------------------------------------------------------- /test/cases/incorrect macro arg count.c: -------------------------------------------------------------------------------- 1 | #define TWO_ARGS(A, B) A B 2 | 3 | TWO_ARGS() 4 | TWO_ARGS(A) 5 | TWO_ARGS(A, B, C) 6 | TWO_ARGS(,,,) 7 | 8 | /** manifest: 9 | expand_error 10 | 11 | incorrect macro arg count.c:3:1: error: expected 2 argument(s) got 1 12 | incorrect macro arg count.c:4:1: error: expected 2 argument(s) got 1 13 | incorrect macro arg count.c:5:1: error: expected 2 argument(s) got 3 14 | incorrect macro arg count.c:6:1: error: expected 2 argument(s) got 4 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/anonymous_struct_no-ms.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | int a; 3 | } unnamed; 4 | typedef struct named { 5 | int b; 6 | } named; 7 | 8 | struct S { 9 | unnamed; 10 | named; 11 | }; 12 | 13 | /** manifest: 14 | syntax 15 | args = -fno-ms-extensions 16 | 17 | anonymous_struct_no-ms.c:9:12: warning: declaration does not declare anything [-Wmissing-declaration] 18 | anonymous_struct_no-ms.c:10:10: warning: declaration does not declare anything [-Wmissing-declaration] 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/keyword hidden by macro.c: -------------------------------------------------------------------------------- 1 | #define int foo 2 | #define include hello 3 | #include 4 | #define if then 5 | #define alignof _Alignof 6 | 7 | unsigned x; // only here to suppress -Wempty-translation-unit 8 | 9 | /** manifest: 10 | syntax 11 | args = -pedantic 12 | 13 | keyword hidden by macro.c:1:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 14 | keyword hidden by macro.c:4:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/macro whitespace.c: -------------------------------------------------------------------------------- 1 | #define FOO 1 /* fjfao */ /* fjfao */ 2 2 | 3 | #define BAR + /* fjfao */ /* fjfao */ / 4 | 5 | #define BAZ 1 /* FJDLKS */ 6 | 7 | #define QUX /**/2 8 | 9 | #define MULTI /* 10 | */3 11 | 12 | #define XSTR(s) #s 13 | #define STR(s) XSTR(s) 14 | STR(FOO) 15 | STR(BAR) 16 | STR(BAZ) 17 | STR(1 18 | 2) 19 | STR(QUX) 20 | STR(MULTI) 21 | STR(/* 22 | */5) 23 | STR(/**/6) 24 | 25 | #define x foo bar 26 | x 27 | 28 | /** manifest: 29 | expand 30 | */ 31 | -------------------------------------------------------------------------------- /test/cases/tentative decls defined.c: -------------------------------------------------------------------------------- 1 | int foo(int); 2 | extern int foo(int); 3 | int foo(int); 4 | int foo(int a) { return a; } 5 | int foo(int); 6 | extern int foo(int); 7 | int foo(int); 8 | 9 | extern int a; 10 | int a; 11 | int a = 1; 12 | extern int a; 13 | int a; 14 | 15 | int bar(void) { 16 | int baz(void); 17 | int baz(void); 18 | extern int b; 19 | extern int b; 20 | return b; 21 | } 22 | 23 | /** manifest: 24 | syntax 25 | args = --target=x86_64-linux-gnu 26 | */ 27 | -------------------------------------------------------------------------------- /test/cases/designated_init.c: -------------------------------------------------------------------------------- 1 | union U { 2 | int a; 3 | float b; 4 | } __attribute__((designated_init)); 5 | struct S { 6 | int a; 7 | float b; 8 | } __attribute__((designated_init)) a = { 1 }; 9 | 10 | /** manifest: 11 | syntax 12 | 13 | designated_init.c:4:18: error: 'designated_init' attribute is only valid on 'struct' type' 14 | designated_init.c:8:42: warning: positional initialization of field in 'struct' declared with 'designated_init' attribute [-Wdesignated-init] 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/include_next_mixed.c: -------------------------------------------------------------------------------- 1 | #include // mixed//other_mixed.h or mixed\\other_mixed.h on windows 2 | _Static_assert(OTHER_MIXED_INCLUDED == 1, "OTHER_MIXED_INCLUDED"); 3 | _Static_assert(NEXT_OTHER_MIXED_INCLUDED == 1, "NEXT_OTHER_MIXED_INCLUDED"); 4 | 5 | /** manifest: 6 | syntax 7 | args = -fms-extensions -Wgnu-include-next -Wno-gnu-alignof-expression -I include//mixed -I include 8 | 9 | other_mixed.h:5:2: warning: #include_next is a language extension [-Wgnu-include-next] 10 | */ 11 | -------------------------------------------------------------------------------- /test/cases/macro backtrace.c: -------------------------------------------------------------------------------- 1 | #define a 1 ## 2 2 | #define b a 3 | #define c b 4 | #define d c 5 | #define e d 6 | #define f e 7 | #define g f 8 | #define h g 9 | #define i h 10 | #define j i 11 | #define k j 12 | a 13 | b 14 | c 15 | d 16 | e 17 | f 18 | g 19 | h 20 | i 21 | j 22 | k 23 | 24 | /** manifest: 25 | syntax 26 | 27 | macro backtrace.c:12:1: error: expected external declaration 28 | macro backtrace.c:1:11: note: expanded from here 29 | :1:1: note: expanded from here 30 | */ 31 | -------------------------------------------------------------------------------- /test/cases/call undeclared function with invalid type.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | does_not_exist x; 3 | }; 4 | 5 | void foo(void) { 6 | struct S s = {0}; 7 | bar(s.x); 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | 13 | call undeclared function with invalid type.c:2:5: error: unknown type name 'does_not_exist' 14 | call undeclared function with invalid type.c:7:5: error: call to undeclared function 'bar'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/__VA_OPT__.c: -------------------------------------------------------------------------------- 1 | #define foo(...) __VA_OPT__(1, 2, ) __VA_OPT__(3, 4) 2 | foo(1) 3 | 4 | #define bar(...) a ## __VA_OPT__(3, 4) + 5 | bar() 6 | 7 | #define baz() __VA_OPT__(1) 8 | baz() 9 | 10 | #define invalid1(...) __VA_OPT__ 1 11 | #define invalid2(...) __VA_OPT__(1 12 | 13 | /** manifest: 14 | expand_error 15 | 16 | __VA_OPT__.c:10:33: error: missing '(' following __VA_OPT__ 17 | __VA_OPT__.c:12:35: error: unterminated __VA_OPT__ argument list 18 | __VA_OPT__.c:11:33: note: to match this '(' 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/bitfields.c: -------------------------------------------------------------------------------- 1 | int b; 2 | 3 | struct Foo { 4 | float a: 1; 5 | int c: b, d: -1; 6 | int e: 64, f:0; 7 | }; 8 | 9 | /** manifest: 10 | syntax 11 | 12 | bitfields.c:4:10: error: bit-field has non-integer type 'float' 13 | bitfields.c:5:11: error: expression is not an integer constant expression 14 | bitfields.c:5:14: error: bit-field has negative width (-1) 15 | bitfields.c:6:8: error: width of bit-field exceeds width of its type 16 | bitfields.c:6:15: error: named bit-field has zero width 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/incorrect typeof usage.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | unsigned typeof(int) x; 3 | typeof(int) typeof(int) y; 4 | typeof() z; 5 | typeof(int) unsigned w; 6 | } 7 | 8 | /** manifest: 9 | syntax 10 | 11 | incorrect typeof usage.c:2:5: error: 'unsigned typeof' is invalid 12 | incorrect typeof usage.c:3:5: error: cannot combine with previous 'typeof' specifier 13 | incorrect typeof usage.c:4:12: error: expected expression 14 | incorrect typeof usage.c:5:17: error: 'unsigned typeof' is invalid 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/#if constant expression.c: -------------------------------------------------------------------------------- 1 | #if defined FOO & !defined(BAZ) 2 | void 3 | #elif !defined(BAR) 4 | long 5 | #endif 6 | 7 | #if 1 - 1 8 | #error "foo" 9 | #endif 10 | 11 | #if defined BAR ? 1 : 0 12 | #error foo 13 | #endif 14 | 15 | #if 0 && 0 16 | # error foo 17 | #endif 18 | 19 | #if 0 || 0 20 | # error foo 21 | #endif 22 | #if 0U - 1 != 18446744073709551615ULL 23 | #error incorrect unsigned subtraction in preprocessor 24 | #endif 25 | 26 | /** manifest: 27 | expand 28 | args = -Wno-integer-overflow 29 | */ 30 | -------------------------------------------------------------------------------- /test/cases/pragma poison.c: -------------------------------------------------------------------------------- 1 | #define foo bar 2 | #pragma GCC poison "bar" foo 3 | #pragma GCC poison bar 4 | 5 | int foo; 6 | int bar; 7 | 8 | #define baz(x) 9 | 10 | baz(bar) 11 | 12 | #pragma GCC poison baz 13 | 14 | /** manifest: 15 | syntax 16 | 17 | pragma poison.c:2:20: error: can only poison identifier tokens 18 | pragma poison.c:6:5: error: attempt to use a poisoned identifier 19 | pragma poison.c:10:5: error: attempt to use a poisoned identifier 20 | pragma poison.c:12:20: warning: poisoning existing macro 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/dollars in identifiers.c: -------------------------------------------------------------------------------- 1 | void foo$() { } 2 | 3 | void fib() { 4 | int $test; 5 | } 6 | 7 | void ano$ther() {} 8 | 9 | #pragma GCC diagnostic warning "-Wdollar-in-identifier-extension" 10 | 11 | void identi$fier() {} 12 | 13 | void inside() { 14 | int vari$able; 15 | } 16 | 17 | /** manifest: 18 | syntax 19 | 20 | dollars in identifiers.c:11:12: warning: '$' in identifier [-Wdollar-in-identifier-extension] 21 | dollars in identifiers.c:14:11: warning: '$' in identifier [-Wdollar-in-identifier-extension] 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/redefine typedef.c: -------------------------------------------------------------------------------- 1 | typedef int MyInt; 2 | int foo(MyInt MyInt) { 3 | return MyInt; 4 | } 5 | 6 | int MyInt; 7 | 8 | enum E { 9 | Foo, 10 | }; 11 | 12 | typedef int Foo; 13 | 14 | /** manifest: 15 | syntax 16 | 17 | redefine typedef.c:6:5: error: redefinition of 'MyInt' as different kind of symbol 18 | redefine typedef.c:1:13: note: previous definition is here 19 | redefine typedef.c:12:13: error: redefinition of 'Foo' as different kind of symbol 20 | redefine typedef.c:9:2: note: previous definition is here 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/expanded/float header aarch64-linux-gnu.c: -------------------------------------------------------------------------------- 1 | 2 | 15 3 | 2.2204460492503131e-16 4 | 53 5 | 308 6 | 1024 7 | 1.7976931348623157e+308 8 | (-307) 9 | (-1021) 10 | 2.2250738585072014e-308 11 | 36 12 | 6 13 | 1.19209290e-7F 14 | 24 15 | 38 16 | 128 17 | 3.40282347e+38F 18 | (-37) 19 | (-125) 20 | 1.17549435e-38F 21 | 2 22 | 33 23 | 1.92592994438723585305597794258492732e-34L 24 | 113 25 | 4932 26 | 16384 27 | 1.18973149535723176508575932662800702e+4932L 28 | (-4931) 29 | (-16381) 30 | 3.36210314311209350626267781732175260e-4932L 31 | 2 32 | -------------------------------------------------------------------------------- /test/cases/unaligned u16 string literal.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | int x; 3 | }; 4 | 5 | void foo(void) { 6 | struct S s; 7 | s.y; 8 | } 9 | 10 | _Static_assert(u"A"); 11 | 12 | /** manifest: 13 | syntax 14 | 15 | unaligned u16 string literal.c:7:7: error: no member named 'y' in 'struct S' 16 | unaligned u16 string literal.c:10:1: warning: '_Static_assert' with no message is a C23 extension [-Wc23-extensions] 17 | unaligned u16 string literal.c:10:16: error: static assertion expression is not an integral constant expression 18 | */ 19 | -------------------------------------------------------------------------------- /test/cases/complex init.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | _Complex double cd = { 1.0, 2.0 }; 3 | _Complex float cf = { 1.0f, 2.0f }; 4 | // _Complex int ci = {1, 2}; // TODO: complx integer initializer 5 | 6 | cd = __builtin_complex(1.0, 2.0); 7 | cf = __builtin_complex(1.0f, 2.0f); 8 | 9 | cd = (_Complex double) { 1.0f, 2.0f}; // convert float literals to double 10 | cf = (_Complex float) { 1.0, 2.0 }; // convert double literals to float 11 | } 12 | 13 | /** manifest: 14 | syntax 15 | args = --target=aarch64-macos-musl 16 | */ 17 | -------------------------------------------------------------------------------- /test/cases/nested unterminated macro gcc.c: -------------------------------------------------------------------------------- 1 | #define str(s) # s 2 | #define xstr(s) str(s) 3 | #define INCFILE(n) str(strcmp( 4 | xstr(INCFILE(2)) INCFILE(2)) 5 | 6 | /** manifest: 7 | expand_error 8 | args = --emulate=gcc 9 | 10 | nested unterminated macro gcc.c:4:6: error: unterminated function macro argument list 11 | nested unterminated macro gcc.c:3:20: note: expanded from here 12 | nested unterminated macro gcc.c:4:18: error: unterminated function macro argument list 13 | nested unterminated macro gcc.c:3:20: note: expanded from here 14 | */ 15 | -------------------------------------------------------------------------------- /src/aro/Builtins/bpf.def: -------------------------------------------------------------------------------- 1 | # Generated from clang/include/clang/Basic/BuiltinsBPF.td 2 | 3 | __builtin_btf_type_id 4 | .param_str = "LUi." 5 | .attributes = .{ .custom_typecheck = true } 6 | 7 | __builtin_preserve_enum_value 8 | .param_str = "Li." 9 | .attributes = .{ .custom_typecheck = true } 10 | 11 | __builtin_preserve_field_info 12 | .param_str = "Ui." 13 | .attributes = .{ .custom_typecheck = true } 14 | 15 | __builtin_preserve_type_info 16 | .param_str = "LUi." 17 | .attributes = .{ .custom_typecheck = true } 18 | -------------------------------------------------------------------------------- /test/cases/pragma once.c: -------------------------------------------------------------------------------- 1 | #include "include/global_var.h" 2 | #include "include/global_var.h" 3 | 4 | #include "include/global_var_once.h" 5 | #include "include/global_var_once.h" 6 | 7 | #pragma once 8 | #pragma once 9 | 10 | /** manifest: 11 | syntax 12 | 13 | pragma once.c:7:9: warning: #pragma once in main file [-Wpragma-once-outside-header] 14 | pragma once.c:8:9: warning: #pragma once in main file [-Wpragma-once-outside-header] 15 | global_var.h:1:5: error: redefinition of 'multiple' 16 | global_var.h:1:5: note: previous definition is here 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/nested unterminated macro clang.c: -------------------------------------------------------------------------------- 1 | #define str(s) # s 2 | #define xstr(s) str(s) 3 | #define INCFILE(n) str(strcmp( 4 | xstr(INCFILE(2)) INCFILE(2)) 5 | 6 | /** manifest: 7 | expand_error 8 | args = --emulate=clang 9 | 10 | nested unterminated macro clang.c:4:6: error: unterminated function macro argument list 11 | nested unterminated macro clang.c:3:20: note: expanded from here 12 | nested unterminated macro clang.c:4:18: error: unterminated function macro argument list 13 | nested unterminated macro clang.c:3:20: note: expanded from here 14 | */ 15 | -------------------------------------------------------------------------------- /src/backend/Assembly.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Allocator = std.mem.Allocator; 3 | 4 | data: []const u8, 5 | text: []const u8, 6 | 7 | const Assembly = @This(); 8 | 9 | pub fn deinit(self: *const Assembly, gpa: Allocator) void { 10 | gpa.free(self.data); 11 | gpa.free(self.text); 12 | } 13 | 14 | pub fn writeToFile(self: Assembly, file: std.fs.File) !void { 15 | var file_writer = file.writer(&.{}); 16 | 17 | var buffers = [_][]const u8{ self.data, self.text }; 18 | try file_writer.interface.writeSplatAll(&buffers, 1); 19 | } 20 | -------------------------------------------------------------------------------- /test/cases/empty records.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic warning "-Wgnu-empty-struct" 2 | #pragma GCC diagnostic warning "-Wc++-compat" 3 | 4 | struct {}s; 5 | union {}u; 6 | 7 | /** manifest: 8 | syntax 9 | 10 | empty records.c:4:1: warning: empty struct is a GNU extension [-Wgnu-empty-struct] 11 | empty records.c:4:1: warning: empty struct has size 0 in C, size 1 in C++ [-Wc++-compat] 12 | empty records.c:5:1: warning: empty union is a GNU extension [-Wgnu-empty-struct] 13 | empty records.c:5:1: warning: empty union has size 0 in C, size 1 in C++ [-Wc++-compat] 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/no declspec.c: -------------------------------------------------------------------------------- 1 | __declspec(align(4)) int foo; 2 | 3 | #if __has_declspec_attribute(noreturn) 4 | #error "__has_declspec_attribute macro should not work without -fdeclspec" 5 | #endif 6 | 7 | #if __has_declspec_attribute(x) 8 | #error "__has_declspec_attribute macro should not work without -fdeclspec" 9 | #endif 10 | 11 | /** manifest: 12 | syntax 13 | args = -fno-declspec --target=x86_64-linux 14 | 15 | no declspec.c:1:1: error: '__declspec' attributes are not enabled; use '-fdeclspec' or '-fms-extensions' to enable support for __declspec attributes 16 | */ 17 | -------------------------------------------------------------------------------- /test/cases/nameless param.c: -------------------------------------------------------------------------------- 1 | int xyz(float); 2 | 3 | void foo(int) { 4 | return; 5 | } 6 | 7 | void bar(float, char) { 8 | return; 9 | } 10 | 11 | /** manifest: 12 | syntax 13 | 14 | nameless param.c:3:13: warning: omitting the parameter name in a function definition is a C23 extension [-Wc23-extensions] 15 | nameless param.c:7:15: warning: omitting the parameter name in a function definition is a C23 extension [-Wc23-extensions] 16 | nameless param.c:7:21: warning: omitting the parameter name in a function definition is a C23 extension [-Wc23-extensions] 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/signed char.c: -------------------------------------------------------------------------------- 1 | #if defined __CHAR_UNSIGNED__ 2 | #error char should be signed 3 | #endif 4 | 5 | _Static_assert((char)-1 == -1, "char should be signed"); 6 | _Static_assert((char)0xFF == -1, "char should be signed"); 7 | 8 | #if '\0' - 1 > 0 9 | #error "preprocessor char literal is unsigned when it should be signed" 10 | #endif 11 | 12 | #if u'\0' - 1 < 0 13 | #error "preprocessor u8 char literal is signed when it should be unsigned" 14 | #endif 15 | 16 | /** manifest: 17 | syntax 18 | args = --target=aarch64-linux-gnu -fsigned-char -Wno-integer-overflow 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/intmax_t.c: -------------------------------------------------------------------------------- 1 | #include "test_helpers.h" 2 | 3 | _Static_assert(__INTMAX_MAX__ == 9223372036854775807L, ""); 4 | _Static_assert(__INTMAX_WIDTH__ == 64, ""); 5 | EXPECT_TYPE(__INTMAX_TYPE__, long); 6 | EXPECT_TYPE(CAT(0, __INTMAX_C_SUFFIX__), long); 7 | 8 | _Static_assert(__UINTMAX_MAX__ == 18446744073709551615UL, ""); 9 | _Static_assert(__UINTMAX_WIDTH__ == 64, ""); 10 | EXPECT_TYPE(__UINTMAX_TYPE__, unsigned long); 11 | EXPECT_TYPE(CAT(0, __UINTMAX_C_SUFFIX__), unsigned long); 12 | 13 | /** manifest: 14 | syntax 15 | args = --target=x86_64-linux-gnu -I include 16 | */ 17 | -------------------------------------------------------------------------------- /test/cases/promotion edge cases.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | unsigned x: 3; 3 | long y: 5; 4 | }; 5 | void foo(void) { 6 | char c = 0; 7 | double d = 2.0; 8 | d = d + c; // promote char to int then to double 9 | struct S s = { .x = 1U, .y = 1L}; 10 | int x = s.x + 1; // unsigned bitfield promotes to int if it fits 11 | int y = s.y + 1; // long bitfield promotes to int if it fits 12 | __fp16 fp16 = 0.0f; 13 | fp16 = fp16 + fp16; // __fp16 casts to float for arithmetic 14 | } 15 | 16 | /** manifest: 17 | syntax 18 | args = --target=x86_64-linux-gnu 19 | */ 20 | -------------------------------------------------------------------------------- /test/cases/__line__.c: -------------------------------------------------------------------------------- 1 | #define LINE __LINE__ 2 | 3 | void foo(void) { 4 | \ 5 | i\ 6 | nt x = __LI\ 7 | NE__; 8 | \ 9 | \ 10 | int y = __LINE__; 11 | 12 | int z = LINE; 13 | \ 14 | \ 15 | 16 | } 17 | 18 | #define FOO __LINE__ 19 | 20 | static int line1 = __LINE__; 21 | #line 100 "foo.c" 22 | static int line2 = __LINE__; 23 | static char *file1 = __FILE__; 24 | 25 | #include <__line__.h> 26 | 27 | static int line5 = FOO; 28 | 29 | # 1 "a.c" 1 3 30 | # 2 "b.c" 1 3 31 | # 3 "c.c" 1 3 4 32 | # 3 "c.c" 2 33 | 34 | /** manifest: 35 | expand 36 | args = -I include 37 | */ 38 | -------------------------------------------------------------------------------- /test/cases/asm.c: -------------------------------------------------------------------------------- 1 | void foo(void) __asm__("foo"); 2 | __asm__ volatile volatile("foo"); 3 | __asm__(u8"nop"); 4 | __asm__(L"nop"); 5 | __asm__(5); 6 | 7 | /** manifest: 8 | syntax 9 | 10 | asm.c:2:9: error: meaningless 'volatile' on assembly outside function 11 | asm.c:2:18: error: meaningless 'volatile' on assembly outside function 12 | asm.c:2:18: error: duplicate asm qualifier 'volatile' 13 | asm.c:3:9: error: cannot use unicode string literal in assembly 14 | asm.c:4:9: error: cannot use wide string literal in assembly 15 | asm.c:5:9: error: expected string literal in 'asm' 16 | */ 17 | -------------------------------------------------------------------------------- /test/cases/digraphs.c: -------------------------------------------------------------------------------- 1 | #define PASTE(X, Y) (X %:%: Y) 2 | 3 | void baz(void) <% 4 | int int_arr<::> = <%1%>; 5 | char char_arr<::> = STRINGIZE(HELLO); 6 | char no_digraph[] = "<::>"; 7 | 8 | _Static_assert(sizeof(int_arr) == sizeof(int), "wrong size"); 9 | _Static_assert(PASTE(1,2) == 12, "bad token pasting"); 10 | _Static_assert(sizeof(char_arr) == sizeof("HELLO"), "bad stringify"); 11 | _Static_assert(sizeof(no_digraph) == 5, "string literals should not produce digraph tokens"); 12 | %> 13 | 14 | /** manifest: 15 | syntax 16 | args = -DSTRINGIZE(X)=%:X 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/integer conversions.c: -------------------------------------------------------------------------------- 1 | #include "include/test_helpers.h" 2 | 3 | void foo(void) { 4 | _BitInt(8) x = 0; 5 | EXPECT_TYPE(x + 1, int); 6 | 7 | _BitInt(32) y = 0; 8 | EXPECT_TYPE(y + 1, int); 9 | 10 | _BitInt(33) z = 0; 11 | EXPECT_TYPE(z + 1, _BitInt(33)); 12 | 13 | _Complex unsigned cx = 0; 14 | EXPECT_TYPE(cx + 1L, _Complex long); 15 | 16 | _Complex int cy = 0; 17 | EXPECT_TYPE(cy + 4294967296wb, _Complex _BitInt(34)); 18 | } 19 | 20 | /** manifest: 21 | syntax 22 | args = --target=x86_64-linux-gnu -Wno-c23-extensions -I include 23 | */ 24 | -------------------------------------------------------------------------------- /test/cases/unknown pragmas.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic warning "-Wunknown-pragmas" 2 | 3 | #pragma unknown_option 4 | 5 | #pragma GCC unknown_option 6 | 7 | #pragma GCC diagnostic unknown_option_again 8 | 9 | /** manifest: 10 | expand_error 11 | 12 | unknown pragmas.c:3:9: warning: unknown pragma ignored [-Wunknown-pragmas] 13 | unknown pragmas.c:5:13: warning: pragma GCC expected 'error', 'warning', 'diagnostic', 'poison' [-Wunknown-pragmas] 14 | unknown pragmas.c:7:24: warning: pragma GCC diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop' [-Wunknown-pragmas] 15 | */ 16 | -------------------------------------------------------------------------------- /test/cases/sizeof variably modified types.c: -------------------------------------------------------------------------------- 1 | void foo(int x) { 2 | int arr[x]; 3 | _Static_assert(sizeof(arr) > 0, "sizeof VLA"); 4 | int (*pointer)[x] = &arr; 5 | _Static_assert(sizeof(pointer) == sizeof(int *), "pointer size"); 6 | _Static_assert(sizeof(*pointer) > 0, "sizeof variably-modified type"); 7 | } 8 | 9 | /** manifest: 10 | syntax 11 | 12 | sizeof variably modified types.c:3:20: error: static assertion expression is not an integral constant expression 13 | sizeof variably modified types.c:6:20: error: static assertion expression is not an integral constant expression 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/negative and too big shift count.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int a = 0b11 << -32; 3 | int b = 0b11 << 32; 4 | } 5 | 6 | /** manifest: 7 | syntax 8 | 9 | negative and too big shift count.c:2:16: warning: shift count is negative [-Wshift-count-negative] 10 | negative and too big shift count.c:2:16: warning: overflow in expression; result is '2147483647' [-Winteger-overflow] 11 | negative and too big shift count.c:3:16: warning: shift count >= width of type [-Wshift-count-overflow] 12 | negative and too big shift count.c:3:16: warning: overflow in expression; result is '0' [-Winteger-overflow] 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/signed remainder.c: -------------------------------------------------------------------------------- 1 | _Static_assert(5 % -2 == 1, "failed"); 2 | _Static_assert(-10 % -4 == -2, "failed"); 3 | _Static_assert(10 % -1 == 0, "failed"); 4 | _Static_assert(-10 % -1 == 0, "failed"); 5 | _Static_assert(10U % -1 == 10, "failed"); 6 | _Static_assert(10U % -1 == 10, "failed"); 7 | _Static_assert((-9223372036854775807LL - 1LL) % -1 != 0, "failed"); 8 | 9 | #if (-9223372036854775807LL - 1LL) % -1 != 0 10 | #error Should not get here 11 | #endif 12 | 13 | /** manifest: 14 | syntax 15 | 16 | signed remainder.c:7:16: error: static assertion expression is not an integral constant expression 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/__has_builtin.c: -------------------------------------------------------------------------------- 1 | #if defined __has_builtin 2 | # if __has_builtin(__builtin_va_start) && __has_builtin(__builtin_va_arg) 3 | #error builtin exists 4 | # endif 5 | # if __has_builtin(__builtin_foobar) 6 | #error builtin exists 7 | # endif 8 | #endif 9 | 10 | #if __has_builtin(__has_builtin) 11 | # error should not have builtin __has_builtin 12 | #endif 13 | 14 | #if !__has_builtin(__is_target_arch) 15 | # error should have builtin __is_target_arch 16 | #endif 17 | 18 | /** manifest: 19 | expand_error 20 | args = --emulate=clang 21 | 22 | __has_builtin.c:3:8: error: builtin exists 23 | */ 24 | -------------------------------------------------------------------------------- /test/cases/empty variadic paste.c: -------------------------------------------------------------------------------- 1 | #define ASM_SIZE(inst, ...) ASM_SEL(inst##l##__VA_ARGS__, \ 2 | inst##q##__VA_ARGS__) 3 | 4 | ASM_SIZE(bts) 5 | 6 | /** manifest: 7 | expand 8 | args = -pedantic 9 | 10 | empty variadic paste.c:1:48: warning: passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23 [-Wvariadic-macro-arguments-omitted] 11 | empty variadic paste.c:2:52: warning: passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23 [-Wvariadic-macro-arguments-omitted] 12 | */ 13 | -------------------------------------------------------------------------------- /test/cases/macro re-expansion.c: -------------------------------------------------------------------------------- 1 | #define f(a) a 2 | #define z z[0] 3 | 4 | #define h(x) f(x(1)) 5 | #define s(x) z 6 | 7 | #define K h(s) 8 | 9 | #define H h 10 | 11 | #define L H 12 | 13 | #define SS (s) 14 | 15 | #define INCOMPLETE f(1 16 | #define g(a, b) a##b 17 | #define INCOMPLETE2 g(1 18 | 19 | #define Z1 z Z2 20 | #define Z2 z Z1 21 | 22 | #define THETA(x) x f 23 | #define TAU(x) x TAU 24 | #define OMEGA(x) TAU(x)(1) THETA(x) 25 | 26 | f(f(z)) 27 | h(s) 28 | K 29 | H(s) 30 | L(s) 31 | H SS 32 | INCOMPLETE) 33 | INCOMPLETE2,3) 34 | Z1 35 | TAU(1)(2) 36 | OMEGA(1)(z) 37 | 38 | /** manifest: 39 | expand 40 | */ 41 | -------------------------------------------------------------------------------- /test/cases/msvc macros.c: -------------------------------------------------------------------------------- 1 | __pragma(once) 2 | #define PRAGMA(x) __pragma(x) 3 | 4 | PRAGMA(message "foo") 5 | 6 | int __identifier(int); 7 | 8 | __identifier() 9 | __identifier(1) 10 | __identifier(a b) 11 | 12 | /** manifest: 13 | syntax 14 | args = --target=x86_64-windows-msvc 15 | 16 | msvc macros.c:1:10: warning: #pragma once in main file [-Wpragma-once-outside-header] 17 | msvc macros.c:4:1: note: #pragma message: foo 18 | msvc macros.c:8:1: error: expected identifier argument 19 | msvc macros.c:9:14: error: cannot convert a number to an identifier 20 | msvc macros.c:10:16: error: missing ')', after identifier 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/#pragma pack clang.c: -------------------------------------------------------------------------------- 1 | struct A { 2 | char c; 3 | int x; 4 | }; 5 | 6 | struct B { 7 | #pragma pack(1) 8 | char c; 9 | int x; 10 | }; 11 | 12 | #pragma pack() 13 | struct C { 14 | char c; 15 | #pragma pack(1) 16 | int x; 17 | }; 18 | 19 | #pragma pack() 20 | struct D { 21 | char c; 22 | int x; 23 | #pragma pack(1) 24 | }; 25 | 26 | _Static_assert(sizeof(struct A) == sizeof(struct B), ""); 27 | _Static_assert(sizeof(struct A) == sizeof(struct C), ""); 28 | _Static_assert(sizeof(struct A) == sizeof(struct D), ""); 29 | 30 | /** manifest: 31 | syntax 32 | args = --emulate=clang 33 | */ 34 | -------------------------------------------------------------------------------- /test/cases/digraphs enabled.c: -------------------------------------------------------------------------------- 1 | #define STRINGIZE(X) %:X 2 | #define PASTE(X, Y) (X %:%: Y) 3 | 4 | void baz(void) <% 5 | int int_arr<::> = <%1%>; 6 | char char_arr<::> = STRINGIZE(HELLO); 7 | char no_digraph[] = "<::>"; 8 | 9 | _Static_assert(sizeof(int_arr) == sizeof(int), "wrong size"); 10 | _Static_assert(PASTE(1,2) == 12, "bad token pasting"); 11 | _Static_assert(sizeof(char_arr) == sizeof("HELLO"), "bad stringize"); 12 | _Static_assert(sizeof(no_digraph) == 5, "string literals should not produce digraph tokens"); 13 | %> 14 | 15 | /** manifest: 16 | syntax 17 | args = -std=c89 -fdigraphs 18 | */ 19 | -------------------------------------------------------------------------------- /test/cases/standard-redefinition-reexamination-example.c: -------------------------------------------------------------------------------- 1 | // example from the C18 standard draft, 6.10.3.5, example 3 2 | #define x 3 3 | #define f(a) f(x * (a)) 4 | #undef x 5 | #define x 2 6 | #define g f 7 | #define z z[0] 8 | #define h g(\~{ } 9 | #define m(a) a(w) 10 | #define w 0,1 11 | #define t(a) a 12 | #define p() int 13 | #define q(x) x 14 | #define r(x,y) x ## y 15 | #define str(x) # x 16 | f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); 17 | g(x+(3,4)-w) | h 5) & m 18 | (f)^m(m); 19 | p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; 20 | char c[2][6] = { str(hello), str() }; 21 | 22 | /** manifest: 23 | expand 24 | */ 25 | -------------------------------------------------------------------------------- /test/cases/subscript.c: -------------------------------------------------------------------------------- 1 | int foo(int foo[2]) { 2 | int arr[4]; 3 | arr[-4] = 4[arr]; 4 | 1[1] = 2; 5 | arr[arr] = 2; 6 | return foo[2]; 7 | } 8 | 9 | /** manifest: 10 | syntax 11 | 12 | subscript.c:3:8: warning: array index -4 is before the beginning of the array [-Warray-bounds] 13 | subscript.c:3:16: warning: array index 4 is past the end of the array [-Warray-bounds] 14 | subscript.c:4:6: error: subscripted value is not an array, pointer or vector 15 | subscript.c:5:8: error: array subscript is not an integer 16 | subscript.c:6:15: warning: array index 2 is past the end of the array [-Warray-bounds] 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/float header x86-64-linux.c: -------------------------------------------------------------------------------- 1 | #include 2 | DBL_DIG 3 | DBL_EPSILON 4 | DBL_MANT_DIG 5 | DBL_MAX_10_EXP 6 | DBL_MAX_EXP 7 | DBL_MAX 8 | DBL_MIN_10_EXP 9 | DBL_MIN_EXP 10 | DBL_MIN 11 | DECIMAL_DIG 12 | FLT_DIG 13 | FLT_EPSILON 14 | FLT_MANT_DIG 15 | FLT_MAX_10_EXP 16 | FLT_MAX_EXP 17 | FLT_MAX 18 | FLT_MIN_10_EXP 19 | FLT_MIN_EXP 20 | FLT_MIN 21 | FLT_RADIX 22 | LDBL_DIG 23 | LDBL_EPSILON 24 | LDBL_MANT_DIG 25 | LDBL_MAX_10_EXP 26 | LDBL_MAX_EXP 27 | LDBL_MAX 28 | LDBL_MIN_10_EXP 29 | LDBL_MIN_EXP 30 | LDBL_MIN 31 | FLT_EVAL_METHOD 32 | 33 | /** manifest: 34 | expand 35 | args = --target=x86_64-linux-gnu -std=c11 36 | */ 37 | -------------------------------------------------------------------------------- /test/cases/layout overflow.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | char x[2305843009213693952ULL -1]; 3 | char y[2305843009213693952ULL -1]; 4 | }; 5 | 6 | 7 | struct __declspec(align(268435456)) S1 { 8 | char one; 9 | char two[2]; 10 | char eight[8]; 11 | char four[4]; 12 | }; 13 | 14 | struct S2 { 15 | __attribute__((aligned(268435456))) int x; 16 | }; 17 | 18 | union U { 19 | int a; 20 | char bytes[3333333333333333333]; 21 | }; 22 | 23 | /** manifest: 24 | syntax 25 | args = -fdeclspec 26 | 27 | layout overflow.c:1:8: error: type 'struct S' is too large 28 | layout overflow.c:20:15: error: array is too large 29 | */ 30 | -------------------------------------------------------------------------------- /test/cases/__auto_type self init.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int x; 3 | __auto_type x = x; 4 | 5 | __auto_type y = (int []){1, y}; 6 | 7 | auto z = z + 1; 8 | } 9 | 10 | /** manifest: 11 | syntax 12 | args = -std=c23 13 | 14 | __auto_type self init.c:3:21: error: variable 'x' declared with deduced type '__auto_type' cannot appear in its own initializer 15 | __auto_type self init.c:5:33: error: variable 'y' declared with deduced type '__auto_type' cannot appear in its own initializer 16 | __auto_type self init.c:7:14: error: variable 'z' declared with deduced type '__auto_type' cannot appear in its own initializer 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/arithmetic overflow.c: -------------------------------------------------------------------------------- 1 | _Static_assert(0xFFFFFFFF + 1 == 0, ""); 2 | _Static_assert(1 + 0xFFFFFFFF == 0, ""); 3 | _Static_assert(0 - 0x00000001 == 0xFFFFFFFF, ""); 4 | _Static_assert(0x00000000 - 0x00000001 == 0xFFFFFFFF, ""); 5 | _Static_assert(0x80000000 * 2 == 0, ""); 6 | _Static_assert(2 * 0x80000000 == 0, ""); 7 | _Static_assert(sizeof(int) != 4 || ((unsigned)(-1) << 1) == 0xFFFFFFFFU - 1, ""); 8 | _Static_assert((-9223372036854775807LL - 1LL) / -1 != 0, "failed"); 9 | 10 | /** manifest: 11 | syntax 12 | 13 | arithmetic overflow.c:8:47: warning: overflow in expression; result is '9223372036854775808' [-Winteger-overflow] 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/ast/forever stmt.c: -------------------------------------------------------------------------------- 1 | implicit typedef: '__int128' 2 | name: __int128_t 3 | 4 | implicit typedef: 'unsigned __int128' 5 | name: __uint128_t 6 | 7 | implicit typedef: '*char' 8 | name: __builtin_ms_va_list 9 | 10 | implicit typedef: '[1]struct __va_list_tag' 11 | name: __builtin_va_list 12 | 13 | implicit typedef: 'struct __NSConstantString_tag' 14 | name: __NSConstantString 15 | 16 | implicit typedef: 'long double' 17 | name: __float80 18 | 19 | function: 'fn () int' 20 | name: main 21 | body: 22 | compound_stmt 23 | for_stmt 24 | body: 25 | null_stmt: 'void' 26 | 27 | implicit return_stmt: 'int' 28 | 29 | -------------------------------------------------------------------------------- /test/cases/implicitly unsigned literal.c: -------------------------------------------------------------------------------- 1 | _Static_assert(-9223372036854775808LL > 0, "lhs should be unsigned"); 2 | long long x = 9223372036854775808LL; 3 | _Static_assert(0xFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFE + 1, ""); 4 | 5 | /** manifest: 6 | syntax 7 | args = --emulate=clang 8 | 9 | implicitly unsigned literal.c:1:17: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal] 10 | implicitly unsigned literal.c:2:15: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal] 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/invalid k&r functions.c: -------------------------------------------------------------------------------- 1 | int invalid1() 2 | int invalid2(x) 3 | 4 | /** manifest: 5 | syntax 6 | args = -std=c17 7 | 8 | invalid k&r functions.c:1:14: error: expected function body after function declaration 9 | invalid k&r functions.c:2:5: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype] 10 | invalid k&r functions.c:2:14: error: parameter 'x' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int] 11 | invalid k&r functions.c:2:16: error: expected function body after function declaration 12 | */ 13 | -------------------------------------------------------------------------------- /test/fuzz/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | __AFL_FUZZ_INIT(); 3 | 4 | void compile_c_buf(unsigned char *buf, int len); 5 | 6 | int main(void) { 7 | 8 | #ifdef __AFL_HAVE_MANUAL_CONTROL 9 | __AFL_INIT(); 10 | #endif 11 | 12 | unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT 13 | // and before __AFL_LOOP! 14 | 15 | while (__AFL_LOOP(10000)) { 16 | 17 | int len = __AFL_FUZZ_TESTCASE_LEN; // don't use the macro directly in a 18 | // call! 19 | 20 | compile_c_buf(buf, len); 21 | } 22 | 23 | return 0; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /test/cases/float header netbsd 6.99.26.c: -------------------------------------------------------------------------------- 1 | #include 2 | DBL_DIG 3 | DBL_EPSILON 4 | DBL_MANT_DIG 5 | DBL_MAX_10_EXP 6 | DBL_MAX_EXP 7 | DBL_MAX 8 | DBL_MIN_10_EXP 9 | DBL_MIN_EXP 10 | DBL_MIN 11 | DECIMAL_DIG 12 | FLT_DIG 13 | FLT_EPSILON 14 | FLT_MANT_DIG 15 | FLT_MAX_10_EXP 16 | FLT_MAX_EXP 17 | FLT_MAX 18 | FLT_MIN_10_EXP 19 | FLT_MIN_EXP 20 | FLT_MIN 21 | FLT_RADIX 22 | LDBL_DIG 23 | LDBL_EPSILON 24 | LDBL_MANT_DIG 25 | LDBL_MAX_10_EXP 26 | LDBL_MAX_EXP 27 | LDBL_MAX 28 | LDBL_MIN_10_EXP 29 | LDBL_MIN_EXP 30 | LDBL_MIN 31 | FLT_EVAL_METHOD 32 | 33 | /** manifest: 34 | expand 35 | args = --target=x86-netbsd.6.99.26-gnu -std=c11 36 | */ 37 | -------------------------------------------------------------------------------- /test/cases/standard-concatenation-strings-example.c: -------------------------------------------------------------------------------- 1 | #define str(s) # s 2 | #define xstr(s) str(s) 3 | #define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ 4 | x ## s, x ## t) 5 | #define INCFILE(n) vers ## n 6 | #define glue(a, b) a ## b 7 | #define xglue(a, b) glue(a, b) 8 | #define HIGHLOW "hello" 9 | #define LOW LOW ", world" 10 | debug(1, 2); 11 | fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away 12 | == 0) str(: @\n), s); 13 | xstr(INCFILE(2).h) 14 | xstr(INCFILE(2) . h) 15 | str(INCFILE(2).h) 16 | str(INCFILE(2) . h) 17 | glue(HIGH, LOW); 18 | xglue(HIGH, LOW) 19 | 20 | /** manifest: 21 | expand 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/builtin functions.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | char c[] = "hello"; 3 | return strlen(c); 4 | } 5 | 6 | void bar(int x) { 7 | __builtin_ppc_trap(x); 8 | } 9 | 10 | void ns_constant_string(void) { 11 | const __NSConstantString *ns_str = __builtin___NSStringMakeConstantString("Hello, world!"); 12 | (void)ns_str; 13 | } 14 | 15 | /** manifest: 16 | syntax 17 | args = --target=powerpc-freestanding-none 18 | 19 | builtin functions.c:3:12: error: implicitly declaring library function 'strlen' [-Wimplicit-function-declaration] 20 | builtin functions.c:3:12: note: include the header or explicitly provide a declaration for 'strlen' 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/float header aarch64-linux-gnu.c: -------------------------------------------------------------------------------- 1 | #include 2 | DBL_DIG 3 | DBL_EPSILON 4 | DBL_MANT_DIG 5 | DBL_MAX_10_EXP 6 | DBL_MAX_EXP 7 | DBL_MAX 8 | DBL_MIN_10_EXP 9 | DBL_MIN_EXP 10 | DBL_MIN 11 | DECIMAL_DIG 12 | FLT_DIG 13 | FLT_EPSILON 14 | FLT_MANT_DIG 15 | FLT_MAX_10_EXP 16 | FLT_MAX_EXP 17 | FLT_MAX 18 | FLT_MIN_10_EXP 19 | FLT_MIN_EXP 20 | FLT_MIN 21 | FLT_RADIX 22 | LDBL_DIG 23 | LDBL_EPSILON 24 | LDBL_MANT_DIG 25 | LDBL_MAX_10_EXP 26 | LDBL_MAX_EXP 27 | LDBL_MAX 28 | LDBL_MIN_10_EXP 29 | LDBL_MIN_EXP 30 | LDBL_MIN 31 | FLT_EVAL_METHOD 32 | 33 | /** manifest: 34 | expand 35 | args = --target=aarch64-linux-gnu -std=c11 -ffp-eval-method=extended 36 | */ 37 | -------------------------------------------------------------------------------- /test/cases/types.c: -------------------------------------------------------------------------------- 1 | int _Alignas(int) _Alignas(float) _Alignas(16) a; 2 | 3 | const volatile int b; 4 | __const __volatile int c; 5 | __const__ __volatile__ int d; 6 | int foo(int *restrict a, int *__restrict b, int *__restrict__ c); 7 | 8 | int bar(int n, int bar[n]); 9 | 10 | typedef void baz; 11 | 12 | _Noreturn void abort(void); 13 | 14 | typedef int A; 15 | typedef A B; 16 | typedef A C; 17 | typedef C B; 18 | 19 | typedef int I[2]; 20 | void qux(I const a, const I b) { 21 | b += 1; 22 | a += 1; 23 | } 24 | 25 | enum E { 26 | D = (char) 2, 27 | E = (long) 3, 28 | }; 29 | 30 | /** manifest: 31 | syntax 32 | args = --target=x86_64-linux 33 | */ 34 | -------------------------------------------------------------------------------- /test/cases/_Float16.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | _Float16 foo(_Float16 x, _Float16 y) { 4 | return x + y ; 5 | } 6 | 7 | void bar(int x, ...) { 8 | va_list va; 9 | va_start(va, x); 10 | va_end(va); 11 | } 12 | 13 | void quux(void) { 14 | _Float16 f = 1.0f16; 15 | bar(1, f); // skip 16 | } 17 | 18 | void conversions(void) { 19 | double d = 1.0; 20 | _Float16 f16 = 2.0f16; 21 | __fp16 fp16 = 0; 22 | d = d + f16; 23 | (void)(f16 + fp16); // _Float16 + __fp16 promotes both to float 24 | } 25 | 26 | /** manifest: 27 | syntax 28 | args = --target=x86_64-linux-gnu 29 | skip = _Float16 does not promote to double when used as vararg 30 | */ 31 | -------------------------------------------------------------------------------- /test/cases/undefined macro.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic warning "-Wundef" 2 | 3 | #if FOO 4 | #error "Error" 5 | #endif 6 | 7 | #define FOO BAR 8 | 9 | #if FOO 10 | #error "Error" 11 | #endif 12 | 13 | #if undefined(foo) 14 | #error bad 15 | #endif 16 | 17 | /** manifest: 18 | syntax 19 | 20 | undefined macro.c:3:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef] 21 | undefined macro.c:9:5: warning: 'BAR' is not defined, evaluates to 0 [-Wundef] 22 | undefined macro.c:7:13: note: expanded from here 23 | undefined macro.c:13:5: warning: 'undefined' is not defined, evaluates to 0 [-Wundef] 24 | undefined macro.c:13:5: error: function-like macro 'undefined' is not defined 25 | */ 26 | -------------------------------------------------------------------------------- /test/cases/ast/typeof_unqual.c: -------------------------------------------------------------------------------- 1 | implicit typedef: 'unsigned char' 2 | name: char8_t 3 | 4 | implicit typedef: '__int128' 5 | name: __int128_t 6 | 7 | implicit typedef: 'unsigned __int128' 8 | name: __uint128_t 9 | 10 | implicit typedef: '*char' 11 | name: __builtin_ms_va_list 12 | 13 | implicit typedef: '[1]struct __va_list_tag' 14 | name: __builtin_va_list 15 | 16 | implicit typedef: 'struct __NSConstantString_tag' 17 | name: __NSConstantString 18 | 19 | implicit typedef: 'long double' 20 | name: __float80 21 | 22 | variable: 'const int' 23 | name: a 24 | 25 | variable: 'const typeof(: const int)' 26 | name: b 27 | 28 | variable: 'typeof(: const int)' 29 | name: c 30 | 31 | -------------------------------------------------------------------------------- /test/cases/misplaced attribute.c: -------------------------------------------------------------------------------- 1 | __attribute__ ((aligned (8))) struct S { short f[3]; }; 2 | __attribute__ ((packed)) union U { int x; }; 3 | __attribute__ ((aligned)) enum E { e }; 4 | 5 | /** manifest: 6 | syntax 7 | 8 | misplaced attribute.c:1:18: warning: attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration [-Wignored-attributes] 9 | misplaced attribute.c:2:18: warning: attribute 'packed' is ignored, place it after "union" to apply attribute to type declaration [-Wignored-attributes] 10 | misplaced attribute.c:3:18: warning: attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration [-Wignored-attributes] 11 | */ 12 | -------------------------------------------------------------------------------- /test/cases/c17 char8_t.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | char8_t c = 0; 3 | } 4 | 5 | _Static_assert (_Generic (u8"hello", char*: 1, default: 2) == 1, "Incorrect type for u8 string literal"); 6 | _Static_assert (_Generic (u8"A"[0], char: 1, default: 2) == 1, "Incorrect type for u8 string literal element"); 7 | 8 | const char cbuf1[] = u8"text"; 9 | const char cbuf2[] = { u8"text" }; 10 | const signed char scbuf1[] = u8"text"; 11 | const signed char scbuf2[] = { u8"text" }; 12 | const unsigned char ucbuf1[] = u8"text"; 13 | const unsigned char ucbuf2[] = { u8"text" }; 14 | 15 | /** manifest: 16 | syntax 17 | args = -std=c17 18 | 19 | c17 char8_t.c:2:5: error: use of undeclared identifier 'char8_t' 20 | */ 21 | -------------------------------------------------------------------------------- /test/cases/msvc attribute keywords.c: -------------------------------------------------------------------------------- 1 | int __unaligned * __unaligned a; 2 | int __unaligned b; 3 | int _cdecl foo(); 4 | int *__stdcall bar(); 5 | 6 | int baz(int __unaligned [], int [__unaligned]); 7 | int qux(int __stdcall [], int [__cdecl]); 8 | 9 | void quux(void (__cdecl *fn_ptr)(void)); 10 | 11 | unsigned __int64 l; 12 | unsigned long __int64 l; 13 | 14 | /** manifest: 15 | syntax 16 | args = --target=x86-windows-msvc 17 | 18 | msvc attribute keywords.c:7:13: warning: '__stdcall' only applies to function types; type here is 'int *' [-Wignored-attributes] 19 | msvc attribute keywords.c:7:32: error: expected ']', found '__cdecl' 20 | msvc attribute keywords.c:7:31: note: to match this '{' 21 | */ 22 | -------------------------------------------------------------------------------- /test/cases/newline splicing.c: -------------------------------------------------------------------------------- 1 | #de\ 2 | fine st\ 3 | r(x) #\ 4 | x 5 | void foo(void) { 6 | const char bar[] = str("\ 7 | "); 8 | _Static_assert(sizeof(bar) == 3, "wrong size"); 9 | const char baz[] = str(a.\ 10 | b); 11 | _Static_assert(sizeof(baz) == 4, "wrong size"); 12 | 13 | int ab\ 14 | c = 5; 15 | abc = 10; 16 | a\ 17 | bc = 5; 18 | 19 | char q\ 20 | ux[] = "\ 21 | ab\ 22 | c"; 23 | _Stat\ 24 | ic_assert(siz\ 25 | eof(qu\ 26 | x) =\ 27 | = 4, "wrong size"); 28 | 29 | } 30 | 31 | int trailing\ 32 | ws = 1; 33 | 34 | /** manifest: 35 | syntax 36 | 37 | newline splicing.c:31:14: warning: backslash and newline separated by space [-Wbackslash-newline-escape] 38 | */ 39 | -------------------------------------------------------------------------------- /test/cases/#pragma pack gcc.c: -------------------------------------------------------------------------------- 1 | struct A { 2 | char c; 3 | int x; 4 | }; 5 | 6 | struct B { 7 | #pragma pack(1) 8 | char c; 9 | int x; 10 | }; 11 | 12 | #pragma pack() 13 | struct C { 14 | char c; 15 | #pragma pack(1) 16 | int x; 17 | }; 18 | 19 | #pragma pack() 20 | struct D { 21 | char c; 22 | int x; 23 | #pragma pack(1) 24 | }; 25 | 26 | _Static_assert(sizeof(struct A) > sizeof(struct B), ""); 27 | _Static_assert(sizeof(struct B) == sizeof(char) + sizeof(int), ""); 28 | _Static_assert(sizeof(struct C) == sizeof(char) + sizeof(int), ""); 29 | _Static_assert(sizeof(struct D) == sizeof(char) + sizeof(int), ""); 30 | 31 | /** manifest: 32 | syntax 33 | args = --emulate=gcc 34 | */ 35 | -------------------------------------------------------------------------------- /test/cases/alternate spellings for signed.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__builtin_types_compatible_p(signed, __signed), ""); 2 | _Static_assert(__builtin_types_compatible_p(signed, __signed__), ""); 3 | _Static_assert(__builtin_types_compatible_p(signed char, __signed char), ""); 4 | _Static_assert(__builtin_types_compatible_p(signed short, short __signed__), ""); 5 | 6 | _Static_assert(!__builtin_types_compatible_p(unsigned, __signed), ""); 7 | _Static_assert(!__builtin_types_compatible_p(unsigned, __signed__), ""); 8 | _Static_assert(!__builtin_types_compatible_p(unsigned char, char __signed), ""); 9 | _Static_assert(!__builtin_types_compatible_p(unsigned char, __signed__ char), ""); 10 | 11 | /** manifest: 12 | syntax 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/kr_def_deprecated.c: -------------------------------------------------------------------------------- 1 | int foo(a, int b, char c, d) 2 | int a; short d; 3 | { 4 | return a; 5 | } 6 | 7 | int baz() { 8 | return bar(1); 9 | // TODO no return-type warning 10 | } 11 | 12 | /** manifest: 13 | syntax 14 | args = -std=c23 15 | 16 | kr_def_deprecated.c:1:9: error: unknown type name 'a' 17 | kr_def_deprecated.c:1:27: error: unknown type name 'd' 18 | kr_def_deprecated.c:1:28: error: expected function body after function declaration 19 | kr_def_deprecated.c:3:1: error: expected external declaration 20 | kr_def_deprecated.c:8:12: error: use of undeclared identifier 'bar' 21 | kr_def_deprecated.c:10:1: warning: non-void function 'baz' does not return a value [-Wreturn-type] 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/int128.c: -------------------------------------------------------------------------------- 1 | #include 2 | _Static_assert(sizeof(int128_t) == __SIZEOF_INT128__); 3 | _Static_assert(INT128_WIDTH == 128); 4 | _Static_assert(UINT128_MAX == 340282366920938463463374607431768211455WBU); 5 | _Static_assert(INT128_MAX == 170141183460469231731687303715884105727WB); 6 | _Static_assert(INT128_MIN == -170141183460469231731687303715884105728WB); 7 | _Static_assert(INT128_C(-170141183460469231731687303715884105728) == -170141183460469231731687303715884105728wb); 8 | _Static_assert(UINT128_C(340282366920938463463374607431768211455) == 340282366920938463463374607431768211455uwb); 9 | 10 | /** manifest: 11 | syntax 12 | args = -std=c23 --target=x86_64-linux -Wno-c23-extensions -ffreestanding 13 | */ 14 | -------------------------------------------------------------------------------- /test/cases/__has_warning.c: -------------------------------------------------------------------------------- 1 | #if !__has_warning("-Wextern-initializer") 2 | #error 3 | #endif 4 | 5 | #if __has_warning("-Wfoo") 6 | #error foo should not exist 7 | #elif !__has_warning("-Wunrea" "chable-code") 8 | #error unreachable-code should exist 9 | #endif 10 | 11 | #if __has_warning("foobar") 12 | #error 13 | #elif __has_warning(foobar) 14 | #error 15 | #endif 16 | 17 | #define X __has_warning("-Wextern-initializer") 18 | _Static_assert(X == 1, "Failed to find warning"); 19 | 20 | /** manifest: 21 | expand_error 22 | 23 | __has_warning.c:11:19: warning: __has_warning expected option name (e.g. "-Wundef") [-Wmalformed-warning-check] 24 | __has_warning.c:13:21: error: expected string literal in '__has_warning' 25 | */ 26 | -------------------------------------------------------------------------------- /test/cases/c23 char8_t disabled.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | char8_t c = 0; 3 | } 4 | 5 | _Static_assert(_Generic(u8"hello", char*: 1, default: 2) == 1, "Incorrect type for u8 string literal"); 6 | _Static_assert(_Generic(u8"A"[0], char: 1, default: 2) == 1, "Incorrect type for u8 string literal element"); 7 | 8 | const char cbuf1[] = u8"text"; 9 | const char cbuf2[] = { u8"text" }; 10 | const signed char scbuf1[] = u8"text"; 11 | const signed char scbuf2[] = { u8"text" }; 12 | const unsigned char ucbuf1[] = u8"text"; 13 | const unsigned char ucbuf2[] = { u8"text" }; 14 | 15 | /** manifest: 16 | syntax 17 | args = -std=c23 -fno-char8_t 18 | 19 | c23 char8_t disabled.c:2:5: error: use of undeclared identifier 'char8_t' 20 | */ 21 | -------------------------------------------------------------------------------- /test/cases/#pragma pack msvc.c: -------------------------------------------------------------------------------- 1 | struct A { 2 | char c; 3 | int x; 4 | }; 5 | 6 | struct B { 7 | #pragma pack(1) 8 | char c; 9 | int x; 10 | }; 11 | 12 | #pragma pack() 13 | struct C { 14 | char c; 15 | #pragma pack(1) 16 | int x; 17 | }; 18 | 19 | #pragma pack() 20 | struct D { 21 | char c; 22 | int x; 23 | #pragma pack(1) 24 | }; 25 | 26 | _Static_assert(sizeof(struct A) > sizeof(struct B), ""); 27 | _Static_assert(sizeof(struct B) == sizeof(struct C), ""); 28 | _Static_assert(sizeof(struct B) == sizeof(char) + sizeof(int), ""); 29 | // _Static_assert(sizeof(struct A) == sizeof(struct D), ""); 30 | 31 | /** manifest: 32 | syntax 33 | args = --emulate=msvc 34 | skip = TODO per field pragma pack 35 | */ 36 | -------------------------------------------------------------------------------- /test/cases/extended identifiers c99.c: -------------------------------------------------------------------------------- 1 | #define Ǻ 42 2 | int fǿǿ(void) { 3 | int Ǿ = Ǻ; 4 | return Ǿ; 5 | } 6 | 7 | int bȁr(void) { 8 | int ™ = 0; 9 | return 0; 10 | } 11 | 12 | int bȁz(void) { 13 | int a١ = 0; 14 | int ١a = 0; 15 | return 0; 16 | } 17 | 18 | int uǿ = 0; 19 | int uǿ1 = 0; 20 | int u8ǿ = 0; 21 | int u8ǿ1 = 0; 22 | int Uǿ = 0; 23 | int Uǿ1 = 0; 24 | int Lǿ = 0; 25 | int Lǿ1 = 0; 26 | 27 | /** manifest: 28 | syntax 29 | args = -std=c99 30 | 31 | extended identifiers c99.c:8:9: error: unexpected character 32 | extended identifiers c99.c:8:11: error: expected identifier or '(' 33 | extended identifiers c99.c:14:9: error: character not allowed at the start of an identifier 34 | */ 35 | -------------------------------------------------------------------------------- /test/cases/repeated preprocessor tokens.c: -------------------------------------------------------------------------------- 1 | #define h(x)0(x(0)0 2 | #define s() 3 | #define K h( 4 | #define H h 5 | #define L H 6 | #define SS 7 | K H()L(s)H SS) 8 | 9 | /** manifest: 10 | syntax 11 | 12 | repeated preprocessor tokens.c:7:6: error: expected 0 argument(s) got 1 13 | repeated preprocessor tokens.c:5:11: note: expanded from here 14 | repeated preprocessor tokens.c:4:11: note: expanded from here 15 | repeated preprocessor tokens.c:1:15: note: expanded from here 16 | repeated preprocessor tokens.c:7:8: note: expanded from here 17 | repeated preprocessor tokens.c:7:1: error: expected external declaration 18 | repeated preprocessor tokens.c:3:11: note: expanded from here 19 | repeated preprocessor tokens.c:1:13: note: expanded from here 20 | */ 21 | -------------------------------------------------------------------------------- /test/cases/builtin macro errors.c: -------------------------------------------------------------------------------- 1 | #if __has_attribute(42) 2 | #endif 3 | 4 | #if __has_attribute aligned 5 | #endif 6 | 7 | #if __has_attribute(aligned 8 | #endif 9 | 10 | #define __has_attribute 42 11 | int x = __has_attribute; 12 | 13 | #if __has_feature(__const__) 14 | #endif 15 | 16 | /** manifest: 17 | syntax 18 | 19 | builtin macro errors.c:1:21: error: builtin feature check macro requires a parenthesized identifier 20 | builtin macro errors.c:4:5: error: Missing '(' after built-in macro '__has_attribute' 21 | builtin macro errors.c:7:5: error: unterminated function macro argument list 22 | builtin macro errors.c:8:28: error: expected value in expression 23 | builtin macro errors.c:10:9: warning: redefining builtin macro [-Wbuiltin-macro-redefined] 24 | */ 25 | -------------------------------------------------------------------------------- /test/cases/nested attributes.c: -------------------------------------------------------------------------------- 1 | typedef int __attribute__((aligned(1))) ALIGN_1; 2 | typedef ALIGN_1 __attribute__((unused)) UNUSED; 3 | _Static_assert(_Alignof(UNUSED) == 1, ""); 4 | 5 | typedef int __attribute__((aligned(16))) __attribute__((aligned(1))) ALIGN_16; 6 | _Static_assert(_Alignof(ALIGN_16) == 16, ""); 7 | 8 | typedef ALIGN_16 __attribute__((aligned(1))) LOWERED_ALIGNMENT; 9 | _Static_assert(_Alignof(LOWERED_ALIGNMENT) == 1, ""); 10 | 11 | typedef ALIGN_1 __attribute__((aligned(16))) RAISED_ALIGNMENT; 12 | _Static_assert(_Alignof(RAISED_ALIGNMENT) == 16, ""); 13 | 14 | __auto_type ARRAY = (__attribute__((aligned(16))) int[]) {1, 2, 3}; 15 | _Static_assert(_Alignof(__typeof__(ARRAY)) == _Alignof(int *), ""); 16 | 17 | /** manifest: 18 | syntax 19 | */ 20 | -------------------------------------------------------------------------------- /src/backend.zig: -------------------------------------------------------------------------------- 1 | pub const Assembly = @import("backend/Assembly.zig"); 2 | pub const CodeGenOptions = @import("backend/CodeGenOptions.zig"); 3 | pub const Interner = @import("backend/Interner.zig"); 4 | pub const Ir = @import("backend/Ir.zig"); 5 | pub const Object = @import("backend/Object.zig"); 6 | 7 | pub const CallingConvention = enum { 8 | c, 9 | stdcall, 10 | thiscall, 11 | vectorcall, 12 | fastcall, 13 | regcall, 14 | riscv_vector, 15 | aarch64_sve_pcs, 16 | aarch64_vector_pcs, 17 | arm_aapcs, 18 | arm_aapcs_vfp, 19 | x86_64_sysv, 20 | x86_64_win, 21 | }; 22 | 23 | pub const version_str = @import("build_options").version_str; 24 | pub const version = @import("std").SemanticVersion.parse(version_str) catch unreachable; 25 | -------------------------------------------------------------------------------- /test/cases/gnuc version default.c: -------------------------------------------------------------------------------- 1 | #if __ARO_EMULATE__ == __ARO_EMULATE_CLANG__ 2 | 3 | _Static_assert(__GNUC__ == 4, ""); 4 | _Static_assert(__GNUC_MINOR__ == 2, ""); 5 | _Static_assert(__GNUC_PATCHLEVEL__ == 1, ""); 6 | 7 | #elif __ARO_EMULATE__ == __ARO_EMULATE_GCC__ || __ARO_EMULATE__ == __ARO_EMULATE_NO__ 8 | 9 | _Static_assert(__GNUC__ == 7, ""); 10 | _Static_assert(__GNUC_MINOR__ == 1, ""); 11 | _Static_assert(__GNUC_PATCHLEVEL__ == 0, ""); 12 | 13 | #elif __ARO_EMULATE__ == __ARO_EMULATE_MSVC__ 14 | 15 | #if defined(__GNUC__) || defined(__GNUC_MINOR__) || defined(__GNUC_PATCHLEVEL__) 16 | #error "__GNUC__ macros should not be defined" 17 | #endif 18 | 19 | #else 20 | #error Invalid value for __ARO_EMULATE__ 21 | #endif 22 | 23 | /** manifest: 24 | syntax 25 | */ 26 | -------------------------------------------------------------------------------- /test/cases/macro redefinition.c: -------------------------------------------------------------------------------- 1 | #define FOO 1 2 | #define FOO 2 3 | #define FOO 3 4 | #define FOO 3 5 | 6 | #define BAR 1 /* fjfao */ /* fjfao */ 2 7 | #define BAR 1 2 8 | 9 | #define BAZ + /* fjfao */ /* fjfao */ / 10 | #define BAZ +/ 11 | 12 | #define QUX 1 /* FJDLKS */ 13 | #define QUX 1 14 | 15 | /** manifest: 16 | syntax 17 | 18 | macro redefinition.c:2:9: warning: 'FOO' macro redefined [-Wmacro-redefined] 19 | macro redefinition.c:1:9: note: previous definition is here 20 | macro redefinition.c:3:9: warning: 'FOO' macro redefined [-Wmacro-redefined] 21 | macro redefinition.c:2:9: note: previous definition is here 22 | macro redefinition.c:10:9: warning: 'BAZ' macro redefined [-Wmacro-redefined] 23 | macro redefinition.c:9:9: note: previous definition is here 24 | */ 25 | -------------------------------------------------------------------------------- /test/cases/cast to union.c: -------------------------------------------------------------------------------- 1 | union U { 2 | int x; 3 | float y; 4 | }; 5 | union Forward; 6 | 7 | void foo(void) { 8 | union U u; 9 | #pragma GCC diagnostic push 10 | #pragma GCC diagnostic warning "-Wpedantic" 11 | u = (union U)1; 12 | #pragma GCC diagnostic pop 13 | 14 | u = (union U)1.0f; 15 | u = (union U)1.0; 16 | (union Forward)1; 17 | (union DoesNotExist)1; 18 | } 19 | 20 | /** manifest: 21 | syntax 22 | 23 | cast to union.c:11:9: warning: cast to union type is a GNU extension [-Wgnu-union-cast] 24 | cast to union.c:15:9: error: cast to union type from type 'double' not present in union 25 | cast to union.c:16:5: error: cast to incomplete type 'union Forward' 26 | cast to union.c:17:5: error: cast to incomplete type 'union DoesNotExist' 27 | */ 28 | -------------------------------------------------------------------------------- /test/cases/c23 auto.c: -------------------------------------------------------------------------------- 1 | auto a(); 2 | 3 | void bad() { 4 | auto a; 5 | auto b = 1, c = 2, d = 3; 6 | auto e[] = ""; 7 | auto f = {1}; 8 | restrict auto g = 1; 9 | } 10 | 11 | void good() { 12 | auto a = 1; 13 | auto b = "foo"; 14 | auto c = good; 15 | } 16 | 17 | /** manifest: 18 | syntax 19 | args = -std=c23 --target=x86_64-linux-gnu 20 | 21 | c23 auto.c:1:1: error: 'auto' not allowed in function return type 22 | c23 auto.c:4:10: error: 'auto' requires an initializer 23 | c23 auto.c:5:5: error: 'auto' can only be used with a single declarator 24 | c23 auto.c:6:5: error: 'e' declared as array of 'auto' 25 | c23 auto.c:7:14: error: cannot use 'auto' with array 26 | c23 auto.c:8:5: error: restrict requires a pointer or reference ('auto' is invalid) 27 | */ 28 | -------------------------------------------------------------------------------- /test/cases/standard attributes.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic ignored "-Wgnu-alignof-expression" 2 | 3 | #if __has_c_attribute(foo) || __has_c_attribute(foo::bar) 4 | #error fail 5 | #endif 6 | 7 | #if !__has_c_attribute(deprecated) || !__has_c_attribute(gnu::__aligned__) 8 | #error fail 9 | #endif 10 | 11 | void foo(void) { 12 | [[deprecated]] int x; 13 | x = 5; 14 | } 15 | 16 | [[nodiscard]] int bar(void) { 17 | [[__gnu__::__aligned__(16)]] int x; 18 | _Static_assert(_Alignof(x) == 16, "incorrect alignment"); 19 | return 5; 20 | } 21 | 22 | /** manifest: 23 | syntax 24 | args = -std=c23 25 | 26 | standard attributes.c:13:5: warning: 'x' is deprecated [-Wdeprecated-declarations] 27 | standard attributes.c:12:7: note: 'x' has been explicitly marked deprecated here 28 | */ 29 | -------------------------------------------------------------------------------- /test/cases/extension.c: -------------------------------------------------------------------------------- 1 | __extension__; 2 | __extension__ int a; 3 | 4 | void foo(void) { 5 | __extension__ __auto_type a = 1; 6 | __extension__; 7 | __extension__ 1; 8 | } 9 | 10 | struct Foo { 11 | __extension__; 12 | __extension__ int a; 13 | }; 14 | 15 | #pragma GCC diagnostic warning "-Wextra-semi" 16 | 17 | ; 18 | 19 | __extension__; 20 | __extension__ __extension__ _Static_assert(1, ""); 21 | 22 | __extension__ 23 | 24 | /** manifest: 25 | syntax 26 | 27 | extension.c:6:18: error: expected expression 28 | extension.c:7:5: warning: expression result unused [-Wunused-value] 29 | extension.c:11:18: error: expected a type 30 | extension.c:17:1: warning: extra ';' outside of a function [-Wextra-semi] 31 | extension.c:22:14: error: expected external declaration 32 | */ 33 | -------------------------------------------------------------------------------- /test/cases/c23 char8_t.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | char8_t c = 0; 3 | } 4 | 5 | _Static_assert(_Generic(u8"hello", unsigned char*: 1, default: 2) == 1, "Incorrect type for u8 string literal"); 6 | _Static_assert(_Generic(u8"A"[0], unsigned char: 1, default: 2) == 1, "Incorrect type for u8 string literal element"); 7 | 8 | const char cbuf1[] = u8"text"; 9 | const char cbuf2[] = { u8"text" }; 10 | const signed char scbuf1[] = u8"text"; 11 | const signed char scbuf2[] = { u8"text" }; 12 | const unsigned char ucbuf1[] = u8"text"; 13 | const unsigned char ucbuf2[] = { u8"text" }; 14 | const char8_t c8buf1[] = u8"text"; 15 | const char8_t c8buf2[] = { u8"text" }; 16 | const char8_t c8buf3[] = "text"; 17 | const char8_t c8buf4[] = { "text" }; 18 | 19 | /** manifest: 20 | syntax 21 | args = -std=c23 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/preserve comments in macros.c: -------------------------------------------------------------------------------- 1 | #define a() 1 /*foo*/ ## /*bar*/ 2 2 | a() 3 | 4 | #define b 1 /*foo*/ ## /*bar*/ 2 5 | b 6 | 7 | #define c() 1 /*foo*/ 8 | c() 9 | 10 | #define d 1 /*foo*/ 11 | d 12 | 13 | #define e(p) p ## 1 14 | 15 | e(hello/*foo*/) 16 | 17 | 18 | // MS EOF used to stop preprocessing before nested block comment 19 | 20 | /** manifest: 21 | expand_error 22 | args = -CC -fms-extensions 23 | 24 | preserve comments in macros.c:1:15: error: pasting formed '/*foo*//*bar*/', an invalid preprocessing token 25 | preserve comments in macros.c:4:13: error: pasting formed '/*foo*//*bar*/', an invalid preprocessing token 26 | preserve comments in macros.c:13:14: error: pasting formed '/*foo*/1', an invalid preprocessing token 27 | preserve comments in macros.c:15:8: note: expanded from here 28 | */ 29 | -------------------------------------------------------------------------------- /test/cases/c17 char8_t enabled.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | char8_t c = 0; 3 | } 4 | 5 | _Static_assert (_Generic (u8"hello", unsigned char*: 1, default: 2) == 1, "Incorrect type for u8 string literal"); 6 | _Static_assert (_Generic (u8"A"[0], unsigned char: 1, default: 2) == 1, "Incorrect type for u8 string literal element"); 7 | 8 | const char cbuf1[] = u8"text"; 9 | const char cbuf2[] = { u8"text" }; 10 | const signed char scbuf1[] = u8"text"; 11 | const signed char scbuf2[] = { u8"text" }; 12 | const unsigned char ucbuf1[] = u8"text"; 13 | const unsigned char ucbuf2[] = { u8"text" }; 14 | const char8_t c8buf1[] = u8"text"; 15 | const char8_t c8buf2[] = { u8"text" }; 16 | const char8_t c8buf3[] = "text"; 17 | const char8_t c8buf4[] = { "text" }; 18 | 19 | /** manifest: 20 | syntax 21 | args = -std=c17 -fchar8_t 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/alloc_align attribute.c: -------------------------------------------------------------------------------- 1 | __attribute__((alloc_align(0))) int* foo1(int x, double y); 2 | __attribute__((alloc_align(1))) int* foo2(int x, double y); 3 | __attribute__((alloc_align(2))) int* foo3(int x, double y); 4 | __attribute__((alloc_align(3))) int* foo4(int x, double y); 5 | __attribute__((alloc_align(1))) int foo5(int x, double y); 6 | 7 | /** manifest: 8 | syntax 9 | 10 | alloc_align attribute.c:1:16: error: 'alloc_align' attribute parameter 1 is out of bounds 11 | alloc_align attribute.c:3:16: error: 'alloc_align' attribute argument may only refer to a function parameter of integer type 12 | alloc_align attribute.c:4:16: error: 'alloc_align' attribute parameter 1 is out of bounds 13 | alloc_align attribute.c:5:16: warning: 'alloc_align' attribute only applies to return values that are pointers [-Wignored-attributes] 14 | */ 15 | -------------------------------------------------------------------------------- /test/cases/unreachable code.c: -------------------------------------------------------------------------------- 1 | int test(int a){ 2 | switch(a) { 3 | default: break; 4 | } 5 | return 1; 6 | } 7 | int test1(int a){ 8 | switch(a) { 9 | break; 10 | a=1; 11 | } 12 | return 1; 13 | } 14 | int test2(int a){ 15 | switch(a) { 16 | return 1; 17 | a=1; 18 | } 19 | return 1; 20 | } 21 | int compound_stmt(int a){ 22 | { 23 | a=1; 24 | return 1; 25 | a=2; 26 | } 27 | } 28 | int if_then_else(int a){ 29 | if(a) 30 | return 1; 31 | else 32 | return 2; 33 | return 3; 34 | } 35 | 36 | /** manifest: 37 | syntax 38 | 39 | unreachable code.c:10:3: warning: unreachable code [-Wunreachable-code] 40 | unreachable code.c:17:3: warning: unreachable code [-Wunreachable-code] 41 | unreachable code.c:25:3: warning: unreachable code [-Wunreachable-code] 42 | unreachable code.c:33:2: warning: unreachable code [-Wunreachable-code] 43 | */ 44 | -------------------------------------------------------------------------------- /test/cases/float types.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __bf16 bf = 1.0bf16; 3 | __fp16 fp = 1.0; 4 | float f = 1.0f; 5 | double d = 1.0; 6 | long double a = 1.0L; 7 | _Float16 f16 = 1.0; 8 | _Float32 f32 = 1.0f32; 9 | _Float64 f64 = 1.0f64; 10 | _Float128 f128 = 1.0f128; 11 | _Float32x f32x = 1.0f32x; 12 | _Float64x f64x = 1.0f64x; 13 | _Float128x f128x = 1.0f128x; 14 | _Decimal32 d32 = 1.0d32; 15 | _Decimal64 d64 = 1.0d64; 16 | _Decimal128 d128 = 1.0d128; 17 | _Decimal64x d64x = 1.0d64x; 18 | 19 | f + f32x; 20 | f32 + d32; 21 | d64x + d128; 22 | } 23 | 24 | /** manifest: 25 | syntax 26 | args = --target=x86_64-linux -Wno-unused 27 | 28 | float types.c:13:5: error: _Float128x is not supported on this target 29 | float types.c:20:9: error: cannot mix operands of decimal floating and other floating types 30 | */ 31 | -------------------------------------------------------------------------------- /test/cases/u8 character constant.c: -------------------------------------------------------------------------------- 1 | const unsigned char c = u8'A'; 2 | _Static_assert(c == 'A', ""); 3 | #pragma GCC diagnostic ignored "-Wc23-extensions" 4 | _Static_assert(u8'\xff' == 0xFF, ""); 5 | 6 | const unsigned char c2 = u8'™'; 7 | const unsigned char c3 = u8'£'; // Unicode codepoint 0xA3 8 | const unsigned char c4 = u8'AA'; 9 | 10 | #if u8'A' 11 | #else 12 | #error Character constant should be true in preprocessor 13 | #endif 14 | 15 | /** manifest: 16 | syntax 17 | 18 | u8 character constant.c:1:25: warning: UTF-8 character literal is a C23 extension [-Wc23-extensions] 19 | u8 character constant.c:6:26: error: character too large for enclosing character literal type 20 | u8 character constant.c:7:26: error: character too large for enclosing character literal type 21 | u8 character constant.c:8:26: error: Unicode character literals may not contain multiple characters 22 | */ 23 | -------------------------------------------------------------------------------- /include/stddef.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | 5 | #define __STDC_VERSION_STDDEF_H__ 202311L 6 | 7 | typedef __PTRDIFF_TYPE__ ptrdiff_t; 8 | typedef __SIZE_TYPE__ size_t; 9 | typedef __WCHAR_TYPE__ wchar_t; 10 | 11 | /* define max_align_t to match GCC and Clang */ 12 | typedef struct { 13 | long long __aro_max_align_ll; 14 | long double __aro_max_align_ld; 15 | } max_align_t; 16 | 17 | #define NULL ((void*)0) 18 | #define offsetof(T, member) __builtin_offsetof(T, member) 19 | 20 | #if __STDC_VERSION__ >= 202311L 21 | # pragma GCC diagnostic push 22 | # pragma GCC diagnostic ignored "-Wpre-c23-compat" 23 | typedef typeof(nullptr) nullptr_t; 24 | # pragma GCC diagnostic pop 25 | 26 | # if defined unreachable 27 | # error unreachable() is a standard macro in C23 28 | # else 29 | # define unreachable() __builtin_unreachable() 30 | # endif 31 | #endif 32 | -------------------------------------------------------------------------------- /test/cases/array argument is null.c: -------------------------------------------------------------------------------- 1 | #include 2 | void foo(int x[static 10]) { 3 | 4 | } 5 | 6 | void bar(void) { 7 | foo(NULL); 8 | foo(nullptr); 9 | foo(0); 10 | } 11 | 12 | /** manifest: 13 | syntax 14 | args = -std=c23 15 | 16 | array argument is null.c:7:9: warning: null passed to a callee that requires a non-null argument [-Wnonnull] 17 | stddef.h:17:14: note: expanded from here 18 | array argument is null.c:2:14: note: callee declares array parameter as static here 19 | array argument is null.c:8:9: warning: null passed to a callee that requires a non-null argument [-Wnonnull] 20 | array argument is null.c:2:14: note: callee declares array parameter as static here 21 | array argument is null.c:9:9: warning: null passed to a callee that requires a non-null argument [-Wnonnull] 22 | array argument is null.c:2:14: note: callee declares array parameter as static here 23 | */ 24 | -------------------------------------------------------------------------------- /test/cases/imaginary constants.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic push 2 | #pragma GCC diagnostic warning "-Wgnu-imaginary-constant" 3 | 4 | void foo(void) { 5 | _Complex double cd = 1.0 + 2.0i; 6 | #pragma GCC diagnostic pop 7 | _Complex float cf = 1.0f + 2.0if; 8 | 9 | _Complex long double cld; 10 | cld = 1.0l + 2.0il; 11 | 12 | #pragma GCC diagnostic warning "-Wgnu-complex-integer" 13 | int _Complex ci = 1i; 14 | #pragma GCC diagnostic ignored "-Wgnu-complex-integer" 15 | _Complex unsigned long cl = 1uli; 16 | } 17 | 18 | #if 1.0i 19 | #endif 20 | 21 | /** manifest: 22 | syntax 23 | 24 | imaginary constants.c:18:5: error: floating point literal in preprocessor expression 25 | imaginary constants.c:5:32: warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant] 26 | imaginary constants.c:13:9: warning: complex integer types are a GNU extension [-Wgnu-complex-integer] 27 | */ 28 | -------------------------------------------------------------------------------- /test/cases/msvc zero size array.c: -------------------------------------------------------------------------------- 1 | typedef int J[]; 2 | 3 | #pragma pack(1) 4 | struct J_packed { 5 | J a; 6 | }; 7 | 8 | _Static_assert(sizeof(J) == 0, "incorrect size"); 9 | _Static_assert(_Alignof(J) == 4, "incorrect alignment"); 10 | 11 | struct J_size { 12 | char a[sizeof(J)+1]; 13 | char b; 14 | }; 15 | 16 | _Static_assert(sizeof(struct J_size) == 2, "incorrect size"); 17 | _Static_assert(_Alignof(struct J_size) == 1, "incorrect alignment"); 18 | 19 | struct J_extra_alignment { 20 | char a; 21 | J b; 22 | }; 23 | struct J_extra_alignment var83; 24 | 25 | _Static_assert(sizeof(J) == 0, ""); 26 | _Static_assert(_Alignof(J) == 4, ""); 27 | 28 | /** manifest: 29 | syntax 30 | args = --target=x86_64-windows-msvc 31 | 32 | msvc zero size array.c:8:16: warning: sizeof returns 0 33 | msvc zero size array.c:12:12: warning: sizeof returns 0 34 | msvc zero size array.c:25:16: warning: sizeof returns 0 35 | */ 36 | -------------------------------------------------------------------------------- /test/cases/__func__.c: -------------------------------------------------------------------------------- 1 | extern int puts(const char*); 2 | 3 | static const char *f = __func__; 4 | static const char *f1 = __FUNCTION__; 5 | static const char *f2 = __PRETTY_FUNCTION__; 6 | 7 | int foo(void) { 8 | puts(f); 9 | puts(f1); 10 | puts(f2); 11 | puts(__func__); 12 | puts(__FUNCTION__); 13 | puts(__PRETTY_FUNCTION__); 14 | return 0; 15 | } 16 | long *bar(int a) { 17 | puts(__FUNCTION__); 18 | puts(__func__); 19 | puts(__PRETTY_FUNCTION__); 20 | return 0; 21 | } 22 | 23 | /** manifest: 24 | syntax 25 | 26 | __func__.c:3:24: warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function] 27 | __func__.c:4:25: warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function] 28 | __func__.c:5:25: warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function] 29 | */ 30 | -------------------------------------------------------------------------------- /test/cases/address of label.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int x = 5; 3 | void *y = &&baz; 4 | bar: 5 | y = &&bar; 6 | baz: 7 | x = 0; 8 | goto *y; 9 | goto *&&baz; 10 | } 11 | 12 | void no_address_of_label(void *arg) { 13 | label: 14 | goto *arg; 15 | } 16 | 17 | void implicit_conversion(void) { 18 | int x = 0; 19 | void *y = &&label; 20 | label: 21 | goto *0; 22 | goto *x; 23 | } 24 | 25 | void invalid_param(void) { 26 | void *p = &&label; 27 | float f = 0.0f; 28 | label: 29 | goto *f; 30 | } 31 | 32 | /** manifest: 33 | syntax 34 | 35 | address of label.c:14:5: error: computed goto in function with no address-of-label expressions 36 | address of label.c:22:11: warning: implicit integer to pointer conversion from 'int' to 'const void *' [-Wint-conversion] 37 | address of label.c:29:11: error: passing 'float' to parameter of incompatible type 'const void *' 38 | */ 39 | -------------------------------------------------------------------------------- /test/cases/typedef extra specifiers disallowed.c: -------------------------------------------------------------------------------- 1 | typedef long foo; 2 | typedef unsigned foo bar; // TODO no missing type error 3 | 4 | typedef double baz; 5 | typedef long baz; 6 | 7 | /** manifest: 8 | syntax 9 | skip = TODO no missing type error after missing semicolon/comma 10 | 11 | typedef extra specifiers disallowed.c:2:18: error: typedef redefinition with different types ('unsigned int' vs 'long') 12 | typedef extra specifiers disallowed.c:1:14: note: previous definition is here 13 | typedef extra specifiers disallowed.c:2:22: error: expected ';', found 'an identifier' 14 | typedef extra specifiers disallowed.c:2:22: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int] 15 | typedef extra specifiers disallowed.c:5:14: error: typedef redefinition with different types ('long' vs 'double') 16 | typedef extra specifiers disallowed.c:4:16: note: previous definition is here 17 | */ 18 | -------------------------------------------------------------------------------- /test/cases/static assert messages.c: -------------------------------------------------------------------------------- 1 | void foo(int x) { 2 | _Static_assert(x, "not allowed"); 3 | _Static_assert(1); 4 | _Static_assert(0); 5 | } 6 | 7 | void bar(void) { 8 | _Static_assert(1, "ok", "not ok"); 9 | } 10 | 11 | _Static_assert(1 == 0, "They are not equal!"); 12 | 13 | /** manifest: 14 | syntax 15 | 16 | static assert messages.c:2:20: error: static assertion expression is not an integral constant expression 17 | static assert messages.c:3:5: warning: '_Static_assert' with no message is a C23 extension [-Wc23-extensions] 18 | static assert messages.c:4:5: warning: '_Static_assert' with no message is a C23 extension [-Wc23-extensions] 19 | static assert messages.c:4:5: error: static assertion failed 20 | static assert messages.c:8:27: error: expected ')', found ',' 21 | static assert messages.c:8:19: note: to match this '(' 22 | static assert messages.c:11:1: error: static assertion failed "They are not equal!" 23 | */ 24 | -------------------------------------------------------------------------------- /test/cases/ast/msvc attribute keywords.c: -------------------------------------------------------------------------------- 1 | implicit typedef: '__int128' 2 | name: __int128_t 3 | 4 | implicit typedef: 'unsigned __int128' 5 | name: __uint128_t 6 | 7 | implicit typedef: '*char' 8 | name: __builtin_ms_va_list 9 | 10 | implicit typedef: '*char' 11 | name: __builtin_va_list 12 | 13 | implicit typedef: 'struct __NSConstantString_tag' 14 | name: __NSConstantString 15 | 16 | variable: '*attributed(int)' 17 | name: a 18 | 19 | variable: 'attributed(int)' 20 | attr: unaligned 21 | name: b 22 | 23 | function: 'kr (...) int' 24 | name: foo 25 | 26 | function: 'attributed(kr (...) *int)' 27 | attr: calling_convention cc: stdcall 28 | name: bar 29 | 30 | function: 'fn (decayed *[]attributed(int), decayed *attributed([]int)) int' 31 | name: baz 32 | 33 | function: 'fn (fn_ptr: *fn () void) void' 34 | name: quux 35 | 36 | variable: 'unsigned long long' 37 | name: l 38 | 39 | variable: 'unsigned long long' 40 | name: l 41 | 42 | -------------------------------------------------------------------------------- /test/cases/c23 identifiers.c: -------------------------------------------------------------------------------- 1 | struct £ { 2 | int x; 3 | }; 4 | 5 | void foo(void) { 6 | int ™ = 0; 7 | int Dž = 0; 8 | int ʶ = 0; 9 | int Ⅸ = 9; 10 | int ڴ = 0; 11 | int ‿ = 0; 12 | int a‿1 = 0; 13 | } 14 | 15 | int à = 1; //NFC_Quick_Check=Maybe 16 | int à = 1; //NFC_Quick_Check=No 17 | 18 | /** manifest: 19 | syntax 20 | args = -std=c2x 21 | 22 | c23 identifiers.c:1:8: error: unexpected character 23 | c23 identifiers.c:1:1: warning: declaration does not declare anything [-Wmissing-declaration] 24 | c23 identifiers.c:6:9: error: unexpected character 25 | c23 identifiers.c:6:11: error: expected identifier or '(' 26 | c23 identifiers.c:11:9: error: unexpected character 27 | c23 identifiers.c:11:11: error: expected identifier or '(' 28 | c23 identifiers.c:15:5: warning: 'a\u0300' is not in NFC [-Wnormalized] 29 | c23 identifiers.c:16:5: warning: 'a\u0340' is not in NFC [-Wnormalized] 30 | */ 31 | -------------------------------------------------------------------------------- /test/cases/enumerator constants.c: -------------------------------------------------------------------------------- 1 | enum E { 2 | A, 3 | B = 10, 4 | C, 5 | D = 2, 6 | E = -2, 7 | F, 8 | #pragma GCC diagnostic warning "-Wpedantic" 9 | G = -2147483649, 10 | H = 2147483648, 11 | #pragma GCC diagnostic ignored "-Wpedantic" 12 | }; 13 | 14 | _Static_assert(A == 0, "A is wrong"); 15 | _Static_assert(B == 10, "B is wrong"); 16 | _Static_assert(C == 11, "C is wrong"); 17 | _Static_assert(D == 2, "D is wrong"); 18 | _Static_assert(E == -2, "E is wrong"); 19 | _Static_assert(F == -1, "F is wrong"); 20 | 21 | void foo(enum E e) { 22 | switch (e) { 23 | case A: return; 24 | default: return; 25 | } 26 | } 27 | 28 | /** manifest: 29 | syntax 30 | 31 | enumerator constants.c:9:5: warning: ISO C restricts enumerator values to range of 'int' (-2147483649 is too small) [-Wpedantic] 32 | enumerator constants.c:10:5: warning: ISO C restricts enumerator values to range of 'int' (2147483648 is too large) [-Wpedantic] 33 | */ 34 | -------------------------------------------------------------------------------- /test/cases/ucn identifiers.c: -------------------------------------------------------------------------------- 1 | #define \U0001F525 42 2 | _Static_assert(🔥 == 42, ""); 3 | 4 | #define FOO \u4F60 ## \u597D 5 | 6 | #define INCOMPLETE_UCN \u4F ## 60 7 | 8 | int foo(void) { 9 | int FOO = 0; 10 | \u4F60\u597D = 5; 11 | int \u0061 = 0x61; 12 | int ABC\U00000001 = 0x01; 13 | return 你好; 14 | } 15 | 16 | struct S { 17 | int 你好; 18 | int a\u4F60\u597D; 19 | }; 20 | 21 | int bar(int x) { 22 | struct S s; 23 | s.\u4F60\u597D = x; 24 | s.a\u4F60\u597D = x; 25 | return s.你好; 26 | } 27 | 28 | int \UFFFFFFFF = 42; 29 | 30 | /** manifest: 31 | syntax 32 | 33 | ucn identifiers.c:6:24: warning: incomplete universal character name; treating as '\' followed by identifier [-Wunicode] 34 | ucn identifiers.c:11:9: error: character 'a' cannot be specified by a universal character name 35 | ucn identifiers.c:12:9: error: universal character name refers to a control character 36 | ucn identifiers.c:28:7: error: invalid universal character 37 | */ 38 | -------------------------------------------------------------------------------- /test/cases/unterminated char literal.c: -------------------------------------------------------------------------------- 1 | /** manifest: 2 | syntax 3 | 4 | unterminated char literal.c:15:11: warning: missing terminating ' character [-Winvalid-pp-token] 5 | unterminated char literal.c:16:11: warning: empty character constant [-Winvalid-pp-token] 6 | unterminated char literal.c:17:14: warning: empty character constant [-Winvalid-pp-token] 7 | unterminated char literal.c:18:14: warning: missing terminating ' character [-Winvalid-pp-token] 8 | unterminated char literal.c:20:10: warning: empty character constant [-Winvalid-pp-token] 9 | unterminated char literal.c:21:10: warning: missing terminating ' character [-Winvalid-pp-token] 10 | unterminated char literal.c:20:10: error: empty character constant 11 | unterminated char literal.c:21:10: error: missing terminating ' character 12 | unterminated char literal.c:21:11: error: expected ';' before end of file 13 | */ 14 | 15 | #define A 'b 16 | #define B '' 17 | #define C(X) '' 18 | #define D(X) 'A 19 | 20 | char c = u8''; 21 | char d = ' -------------------------------------------------------------------------------- /test/cases/gnu pointer arith.c: -------------------------------------------------------------------------------- 1 | void foo(void *a, void *b) { 2 | b - a; 3 | a - 1; 4 | a + 1; 5 | ++a; 6 | --a; 7 | b++; 8 | b--; 9 | } 10 | 11 | /** manifest: 12 | syntax 13 | args = -Wgnu-pointer-arith 14 | 15 | gnu pointer arith.c:2:7: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 16 | gnu pointer arith.c:3:7: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 17 | gnu pointer arith.c:4:7: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 18 | gnu pointer arith.c:5:5: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 19 | gnu pointer arith.c:6:5: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 20 | gnu pointer arith.c:7:6: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 21 | gnu pointer arith.c:8:6: warning: arithmetic on pointers to void is a GNU extension [-Wgnu-pointer-arith] 22 | */ 23 | -------------------------------------------------------------------------------- /test/cases/ast/for decl stmt.c: -------------------------------------------------------------------------------- 1 | implicit typedef: '__int128' 2 | name: __int128_t 3 | 4 | implicit typedef: 'unsigned __int128' 5 | name: __uint128_t 6 | 7 | implicit typedef: '*char' 8 | name: __builtin_ms_va_list 9 | 10 | implicit typedef: '[1]struct __va_list_tag' 11 | name: __builtin_va_list 12 | 13 | implicit typedef: 'struct __NSConstantString_tag' 14 | name: __NSConstantString 15 | 16 | implicit typedef: 'long double' 17 | name: __float80 18 | 19 | function: 'fn () int' 20 | name: main 21 | body: 22 | compound_stmt 23 | for_stmt 24 | decl: 25 | variable: 'int' 26 | name: x 27 | init: 28 | int_literal: 'int' (value: 0) 29 | 30 | variable: 'int' 31 | name: y 32 | init: 33 | int_literal: 'int' (value: 1) 34 | 35 | incr: 36 | post_inc_expr: 'int' 37 | operand: 38 | decl_ref_expr: 'int' lvalue 39 | name: x 40 | body: 41 | null_stmt: 'void' 42 | 43 | implicit return_stmt: 'int' 44 | 45 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | /* for the Aro C compiler */ 2 | 3 | #pragma once 4 | /* Todo: Set to 202311L once header is compliant with C23 */ 5 | #define __STDC_VERSION_STDARG_H__ 0 6 | 7 | typedef __builtin_va_list va_list; 8 | #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L 9 | /* C23 no longer requires the second parameter */ 10 | #define va_start(ap, ...) __builtin_va_start(ap, __VA_ARGS__) 11 | #else 12 | #define va_start(ap, param) __builtin_va_start(ap, param) 13 | #endif 14 | #define va_end(ap) __builtin_va_end(ap) 15 | #define va_arg(ap, type) __builtin_va_arg(ap, type) 16 | 17 | /* GCC and Clang always define __va_copy */ 18 | #define __va_copy(d, s) __builtin_va_copy(d, s) 19 | 20 | /* but va_copy only on c99+ or when strict ansi mode is turned off */ 21 | #if __STDC_VERSION__ >= 199901L || !defined(__STRICT_ANSI__) 22 | #define va_copy(d, s) __builtin_va_copy(d, s) 23 | #endif 24 | 25 | #ifndef __GNUC_VA_LIST 26 | #define __GNUC_VA_LIST 1 27 | typedef __builtin_va_list __gnuc_va_list; 28 | #endif 29 | -------------------------------------------------------------------------------- /test/cases/float builtins.c: -------------------------------------------------------------------------------- 1 | _Static_assert(__builtin_isinf_sign(__builtin_inf()) == 1, ""); 2 | _Static_assert(__builtin_isinf_sign(2.0) == 0, ""); 3 | _Static_assert(__builtin_isinf_sign(-5.0 / 0.0) == -1, ""); 4 | double d = 10.0; 5 | _Static_assert(__builtin_isinf_sign(d) == 0, ""); 6 | _Static_assert(!__builtin_isinf(d), ""); 7 | 8 | _Static_assert(__builtin_inf() == __builtin_inf(), ""); 9 | _Static_assert(100.0 < __builtin_inf(), ""); 10 | _Static_assert(__builtin_inf() > 0.0, ""); 11 | 12 | _Static_assert(__builtin_isinf(__builtin_inff()), ""); 13 | _Static_assert(__builtin_isinf(__builtin_inf()), ""); 14 | _Static_assert(__builtin_isinf(__builtin_infl()), ""); 15 | _Static_assert(__builtin_isinf(1.0 / 0.0), ""); 16 | _Static_assert(!__builtin_isinf(2.0 + 3.0), ""); 17 | 18 | /** manifest: 19 | syntax 20 | 21 | float builtins.c:5:16: error: static assertion expression is not an integral constant expression 22 | float builtins.c:6:16: error: static assertion expression is not an integral constant expression 23 | */ 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - tmp 8 | pull_request: 9 | paths: 10 | - '**.zig' 11 | - '**.c' 12 | - '**.h' 13 | 14 | jobs: 15 | build: 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | os: [ubuntu-latest, macos-latest, windows-latest] 20 | runs-on: ${{ matrix.os }} 21 | steps: 22 | - uses: actions/checkout@v3 23 | with: 24 | submodules: true 25 | - uses: mlugg/setup-zig@v2 26 | with: 27 | version: master 28 | 29 | - name: Build 30 | run: zig build 31 | 32 | - name: Build 32-bit 33 | run: zig build -Dtarget=arm-linux 34 | if: matrix.os == 'ubuntu-latest' 35 | 36 | - name: Build release 37 | run: zig build -Doptimize=ReleaseSafe 38 | 39 | - name: Run Tests 40 | run: zig build test 41 | 42 | # - name: Run Tests in release mode 43 | # run: zig build test -Doptimize=ReleaseFast 44 | -------------------------------------------------------------------------------- /test/cases/avr sizeof long.c: -------------------------------------------------------------------------------- 1 | _Static_assert(sizeof(int) == 2, "wrong sizeof int"); 2 | _Static_assert(sizeof(unsigned) == 2, "wrong sizeof unsigned"); 3 | _Static_assert(sizeof(signed) == 2, "wrong sizeof signed"); 4 | _Static_assert(sizeof(short) == 2, "wrong sizeof short"); 5 | _Static_assert(sizeof(unsigned short) == 2, "wrong sizeof unsigned short"); 6 | _Static_assert(sizeof(signed short) == 2, "wrong sizeof signed short"); 7 | _Static_assert(sizeof(long) == 4, "wrong sizeof long"); 8 | _Static_assert(sizeof(unsigned long) == 4, "wrong sizeof unsigned long"); 9 | _Static_assert(sizeof(signed long) == 4, "wrong sizeof signed long"); 10 | _Static_assert(sizeof(long double) == 4, "wrong sizeof long double"); 11 | _Static_assert(sizeof(long long) == 8, "wrong sizeof long long"); 12 | _Static_assert(sizeof(unsigned long long) == 8, "wrong sizeof unsigned long long"); 13 | _Static_assert(sizeof(signed long long) == 8, "wrong sizeof signed long long"); 14 | 15 | /** manifest: 16 | syntax 17 | args = --target=avr-freestanding-none 18 | */ 19 | -------------------------------------------------------------------------------- /test/cases/nullability.c: -------------------------------------------------------------------------------- 1 | int *_Nonnull _Nonnull a; 2 | int _Nonnull *b; 3 | int _Nonnull _Nullable c; 4 | int _Nullable d(void); 5 | 6 | #pragma GCC diagnostic warning "-Wnullability-extension" 7 | int *_Null_unspecified e(void); 8 | #pragma GCC diagnostic pop 9 | 10 | typedef struct __sFILE { 11 | int (* _Nullable _close)(void *); 12 | } FILE; 13 | 14 | /** manifest: 15 | syntax 16 | args = --target=x86_64-linux-gnu 17 | 18 | nullability.c:1:15: warning: duplicate nullability specifier '_Nonnull' [-Wnullability] 19 | nullability.c:2:5: error: nullability specifier cannot be applied to non-pointer type 'int' 20 | nullability.c:3:14: error: nullaibility specifier '_Nullable' conflicts with existing specifier '_Nonnull' 21 | nullability.c:3:5: error: nullability specifier cannot be applied to non-pointer type 'int' 22 | nullability.c:4:5: error: nullability specifier cannot be applied to non-pointer type 'int' 23 | nullability.c:7:6: warning: type nullability specifier '_Null_unspecified' is a Clang extension [-Wnullability-extension] 24 | */ 25 | -------------------------------------------------------------------------------- /test/cases/divide by zero.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int x = 10; 3 | (void)(x/0); 4 | (void)(x%0); 5 | x /= 0; 6 | x %= 0; 7 | (void)(0/0); 8 | (void)(1%0); 9 | _Static_assert(1/0, "unavailable"); 10 | float f = 0.0f / 0.0f; 11 | f /= 0.0f; 12 | x = 1 / 2.0f; 13 | } 14 | 15 | /** manifest: 16 | syntax 17 | 18 | divide by zero.c:3:13: warning: division by zero is undefined [-Wdivision-by-zero] 19 | divide by zero.c:4:13: warning: remainder by zero is undefined [-Wdivision-by-zero] 20 | divide by zero.c:5:7: warning: division by zero is undefined [-Wdivision-by-zero] 21 | divide by zero.c:6:7: warning: remainder by zero is undefined [-Wdivision-by-zero] 22 | divide by zero.c:7:13: warning: division by zero is undefined [-Wdivision-by-zero] 23 | divide by zero.c:8:13: warning: remainder by zero is undefined [-Wdivision-by-zero] 24 | divide by zero.c:9:21: warning: division by zero is undefined [-Wdivision-by-zero] 25 | divide by zero.c:9:20: error: static assertion expression is not an integral constant expression 26 | */ 27 | -------------------------------------------------------------------------------- /test/cases/adjust diagnostic levels.c: -------------------------------------------------------------------------------- 1 | #define FOO 1 2 | #define FOO 2 3 | 4 | #pragma GCC diagnostic error "-Wmacro-redefined" 5 | #define BAR 1 6 | #define BAR 2 7 | 8 | #pragma GCC diagnostic push 9 | 10 | #pragma GCC diagnostic ignored "-Wmacro-redefined" 11 | #define BAZ 1 12 | #define BAZ 2 13 | 14 | #pragma GCC diagnostic pop 15 | #pragma GCC diagnostic pop 16 | 17 | #define QUX 1 18 | #define QUX 2 19 | 20 | #pragma GCC diagnostic push 21 | #pragma GCC diagnostic error "-Wpedantic" 22 | #pragma GCC diagnostic pop 23 | struct Foo {}; 24 | 25 | /** manifest: 26 | syntax 27 | 28 | adjust diagnostic levels.c:2:9: warning: 'FOO' macro redefined [-Wmacro-redefined] 29 | adjust diagnostic levels.c:1:9: note: previous definition is here 30 | adjust diagnostic levels.c:6:9: error: 'BAR' macro redefined [-Werror,-Wmacro-redefined] 31 | adjust diagnostic levels.c:5:9: note: previous definition is here 32 | adjust diagnostic levels.c:18:9: warning: 'QUX' macro redefined [-Wmacro-redefined] 33 | adjust diagnostic levels.c:17:9: note: previous definition is here 34 | */ 35 | -------------------------------------------------------------------------------- /test/cases/__is_identifier.c: -------------------------------------------------------------------------------- 1 | #if !__is_identifier(typeof) 2 | #error typeof should be an identifier in c17 3 | #endif 4 | 5 | #if __is_identifier(inline) 6 | #error inline should not be an identifier in c17 7 | #endif 8 | 9 | #if __is_identifier(for) 10 | #error for is not an identifier 11 | #endif 12 | 13 | #if __is_identifier("foo") 14 | #error string should not be an identifier 15 | #endif 16 | 17 | #if __is_identifier(_Static_assert) 18 | #error static assert is reserved 19 | #endif 20 | 21 | #define X __is_identifier(foobar) 22 | _Static_assert(X == 1, "'foobar' should be an identifier"); 23 | 24 | #if __is_identifier(foo bar) 25 | #error too many arguments 26 | #endif 27 | 28 | #if __is_identifier() 29 | #error not enough arguments 30 | #endif 31 | 32 | #define FOO & 33 | #if !__is_identifier(FOO) 34 | #error FOO is an identifier 35 | #endif 36 | 37 | /** manifest: 38 | expand_error 39 | args = -std=c17 40 | 41 | __is_identifier.c:24:25: error: missing ')', after builtin feature-check macro 42 | __is_identifier.c:28:5: error: expected 1 argument(s) got 0 43 | */ 44 | -------------------------------------------------------------------------------- /test/cases/expand #pragma args.c: -------------------------------------------------------------------------------- 1 | #undef _CRT_PACKING 2 | #define _CRT_PACKING 16 3 | #pragma pack(show) 4 | #pragma pack(push,_CRT_PACKING) 5 | #pragma pack(show) 6 | #pragma pack(pop) 7 | #pragma pack(show) 8 | 9 | #define PRAGMA_ACTION push 10 | #define PRAGMA_AMOUNT 16 11 | _Pragma("pack(PRAGMA_ACTION, PRAGMA_AMOUNT)"); 12 | #pragma pack(show) 13 | #pragma pack(pop) 14 | #pragma pack(show) 15 | 16 | 17 | #define P(s) _Pragma(#s) 18 | #define WHY(x, y) P(pack(x, y)); 19 | 20 | WHY(push, 16) 21 | #pragma pack(show) 22 | #pragma pack(pop) 23 | 24 | /** manifest: 25 | syntax 26 | args = --target=x86_64-linux-gnu 27 | 28 | expand #pragma args.c:3:14: warning: value of #pragma pack(show) == 8 29 | expand #pragma args.c:5:14: warning: value of #pragma pack(show) == 16 30 | expand #pragma args.c:7:14: warning: value of #pragma pack(show) == 8 31 | expand #pragma args.c:12:14: warning: value of #pragma pack(show) == 16 32 | expand #pragma args.c:14:14: warning: value of #pragma pack(show) == 8 33 | expand #pragma args.c:21:14: warning: value of #pragma pack(show) == 16 34 | */ 35 | -------------------------------------------------------------------------------- /test/cases/enum overflow linux.c: -------------------------------------------------------------------------------- 1 | enum E1 { 2 | A = 2147483647, 3 | B, 4 | C = 4294967295UL, 5 | D, 6 | F = 9223372036854775807, 7 | G, 8 | H = 18446744073709551615ULL, 9 | I 10 | }; 11 | 12 | _Static_assert(A == 2147483647, "A"); 13 | _Static_assert(B == 2147483648, "B"); 14 | _Static_assert(C == 4294967295UL, "C"); 15 | _Static_assert(D == 4294967296UL, "D"); 16 | _Static_assert(F == 9223372036854775807LL, "F"); 17 | _Static_assert(G == 9223372036854775808ULL, "G"); 18 | _Static_assert(H == 18446744073709551615ULL, "H"); 19 | 20 | _Static_assert(H != C, "enumerator value was not truncated"); 21 | 22 | /** manifest: 23 | syntax 24 | args = -target x86_64-linux-gnu 25 | 26 | enum overflow linux.c:3:5: warning: overflow in enumeration value 27 | enum overflow linux.c:7:5: warning: incremented enumerator value 9223372036854775808 is not representable in the largest integer type [-Wenum-too-large] 28 | enum overflow linux.c:9:5: warning: incremented enumerator value 18446744073709551616 is not representable in the largest integer type [-Wenum-too-large] 29 | */ 30 | -------------------------------------------------------------------------------- /test/cases/declspec.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic ignored "-Wgnu-alignof-expression" 2 | 3 | __declspec(align) int foo; 4 | __declspec(align(16)) int bar; 5 | __declspec(aligned(16)) int baz; 6 | 7 | _Static_assert(_Alignof(bar) == 16, "wrong alignment"); 8 | 9 | #if __has_declspec_attribute(foo) 10 | #error fail 11 | #endif 12 | 13 | #if !__has_declspec_attribute(align) 14 | #error fail 15 | #endif 16 | 17 | typedef int Int1 __declspec(align(8)); 18 | typedef __declspec(align(8)) int Int2; 19 | 20 | _Static_assert(_Alignof(Int2) == 8, ""); 21 | 22 | __declspec(restrict) int *qux(void); // TODO should be allowed 23 | 24 | /** manifest: 25 | syntax 26 | args = -fdeclspec --target=x86_64-linux 27 | skip = declspec restrict parsed on function return type parsed incorrectly 28 | 29 | declspec.c:5:12: warning: __declspec attribute 'aligned' is not supported [-Wignored-attributes] 30 | declspec.c:17:18: error: 'declspec' attribute not allowed after declarator 31 | declspec.c:17:13: note: this declarator 32 | declspec.c:22:12: warning: attribute 'restrict' ignored on functions [-Wignored-attributes] 33 | */ 34 | -------------------------------------------------------------------------------- /test/cases/attributed record fields.c: -------------------------------------------------------------------------------- 1 | struct S1 {}; 2 | 3 | struct S2 { 4 | __attribute__((packed)) int x; 5 | }; 6 | 7 | struct S3 { 8 | int __attribute__((packed)) x; 9 | }; 10 | 11 | struct S4 { 12 | int x __attribute__((packed)); 13 | }; 14 | 15 | struct S5 { 16 | __attribute__((packed)) int x, y; 17 | }; 18 | 19 | struct S6 { 20 | int __attribute__((packed)) x, y; 21 | }; 22 | 23 | struct S7 { 24 | int x __attribute__((packed)), y; 25 | }; 26 | 27 | struct S8 { 28 | int x, y __attribute__((packed)); 29 | }; 30 | 31 | struct S9 { 32 | int __attribute__((packed)) x __attribute__((aligned)); 33 | float f; 34 | __attribute__((packed)) long __attribute__((aligned(16))) l __attribute__((warn_if_not_aligned(16))); 35 | }; 36 | 37 | union U1 { 38 | long x; 39 | __attribute__((aligned(32))) int y; 40 | unsigned __attribute__((packed)) z; 41 | }; 42 | 43 | union U2 { 44 | int x __attribute__((packed)), y, __attribute__((packed)) z, w __attribute__((aligned)); 45 | }; 46 | 47 | /** manifest: 48 | syntax 49 | args = --target=x86_64-windows-msvc 50 | */ 51 | -------------------------------------------------------------------------------- /test/cases/warn unused result.c: -------------------------------------------------------------------------------- 1 | typedef int (*fnptr)(int, int); 2 | 3 | 4 | int foo() __attribute__((warn_unused_result)) { 5 | return 0; 6 | } 7 | 8 | fnptr make_fn(int a, int b) { 9 | return 0; 10 | } 11 | 12 | void bar(fnptr ptr) { 13 | foo(); 14 | (foo)(); 15 | (foo - 16)(); 16 | (foo + 16)(); 17 | (*****foo)(); 18 | make_fn(1, 2)(2, 2); 19 | } 20 | 21 | struct S { 22 | int __attribute__((warn_unused_result))(*close)(void); 23 | }; 24 | 25 | void baz(struct S *s){ 26 | (bar(0), s->close)(); 27 | } 28 | 29 | /** manifest: 30 | syntax 31 | 32 | warn unused result.c:13:4: warning: ignoring return value of 'foo', declared with 'warn_unused_result' attribute [-Wunused-result] 33 | warn unused result.c:14:4: warning: ignoring return value of 'foo', declared with 'warn_unused_result' attribute [-Wunused-result] 34 | warn unused result.c:17:4: warning: ignoring return value of 'foo', declared with 'warn_unused_result' attribute [-Wunused-result] 35 | warn unused result.c:26:5: warning: ignoring return value of 'close', declared with 'warn_unused_result' attribute [-Wunused-result] 36 | */ 37 | -------------------------------------------------------------------------------- /test/cases/ast/nullability.c: -------------------------------------------------------------------------------- 1 | implicit typedef: '__int128' 2 | name: __int128_t 3 | 4 | implicit typedef: 'unsigned __int128' 5 | name: __uint128_t 6 | 7 | implicit typedef: '*char' 8 | name: __builtin_ms_va_list 9 | 10 | implicit typedef: '[1]struct __va_list_tag' 11 | name: __builtin_va_list 12 | 13 | implicit typedef: 'struct __NSConstantString_tag' 14 | name: __NSConstantString 15 | 16 | implicit typedef: 'long double' 17 | name: __float80 18 | 19 | variable: 'attributed(*int)' 20 | attr: nullability kind: nonnull 21 | name: a 22 | 23 | variable: 'attributed(*int)' 24 | attr: nullability kind: nonnull 25 | name: b 26 | 27 | variable: 'attributed(int)' 28 | attr: nullability kind: nonnull 29 | name: c 30 | 31 | function: 'attributed(fn () int)' 32 | attr: nullability kind: nullable 33 | name: d 34 | 35 | function: 'attributed(fn () *int)' 36 | attr: nullability kind: unspecified 37 | name: e 38 | 39 | struct_decl: 'struct __sFILE' 40 | record_field: 'attributed(*fn (*void) int)' 41 | attr: nullability kind: nullable 42 | name: _close 43 | 44 | typedef: 'struct __sFILE' 45 | name: FILE 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Veikka Tuominen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/cases/invalid attributes.c: -------------------------------------------------------------------------------- 1 | struct S { 2 | __attribute__((__aligned__(x(long)))) long a; 3 | __attribute__((packed)) b; 4 | }; 5 | 6 | struct S2 { 7 | __attribute__((__aligned__(char: 1))) long a; 8 | __attribute__((packed)) b; 9 | }; 10 | 11 | void foo(void) { 12 | } 13 | 14 | /** manifest: 15 | syntax 16 | 17 | invalid attributes.c:2:30: error: call to undeclared function 'x'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 18 | invalid attributes.c:2:32: error: expected expression 19 | invalid attributes.c:2:36: warning: declaration does not declare anything [-Wmissing-declaration] 20 | invalid attributes.c:2:36: error: expected ';', found ')' 21 | invalid attributes.c:3:27: error: unknown type name 'b' 22 | invalid attributes.c:3:28: warning: declaration does not declare anything [-Wmissing-declaration] 23 | invalid attributes.c:7:30: error: expected expression 24 | invalid attributes.c:7:38: error: expected ';', found ')' 25 | invalid attributes.c:8:27: error: unknown type name 'b' 26 | invalid attributes.c:8:28: warning: declaration does not declare anything [-Wmissing-declaration] 27 | */ 28 | -------------------------------------------------------------------------------- /src/aro/StringInterner.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const mem = std.mem; 3 | const Compilation = @import("Compilation.zig"); 4 | 5 | const StringInterner = @This(); 6 | 7 | pub const StringId = enum(u32) { 8 | empty = std.math.maxInt(u32), 9 | _, 10 | 11 | pub fn lookup(id: StringId, comp: *const Compilation) []const u8 { 12 | if (id == .empty) return ""; 13 | return comp.string_interner.table.keys()[@intFromEnum(id)]; 14 | } 15 | 16 | pub fn lookupExtra(id: StringId, si: StringInterner) []const u8 { 17 | if (id == .empty) return ""; 18 | return si.table.keys()[@intFromEnum(id)]; 19 | } 20 | }; 21 | 22 | table: std.StringArrayHashMapUnmanaged(void) = .empty, 23 | 24 | pub fn deinit(si: *StringInterner, allocator: mem.Allocator) void { 25 | si.table.deinit(allocator); 26 | si.* = undefined; 27 | } 28 | 29 | /// Intern externally owned string. 30 | pub fn intern(si: *StringInterner, allocator: mem.Allocator, str: []const u8) !StringId { 31 | if (str.len == 0) return .empty; 32 | 33 | const gop = try si.table.getOrPut(allocator, str); 34 | return @enumFromInt(gop.index); 35 | } 36 | -------------------------------------------------------------------------------- /test/cases/token paste delete comma gnu.c: -------------------------------------------------------------------------------- 1 | #define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__) 2 | eprintf("foo"); 3 | eprintf("foo",); 4 | eprintf("foo", "bar"); 5 | 6 | #define ZERO_ARGS(...) foo(a, ##__VA_ARGS__) 7 | 8 | ZERO_ARGS() 9 | ZERO_ARGS(b) 10 | 11 | #define foo(a,...) a, ## __VA_ARGS__ 12 | #define bar 13 | 14 | foo(1,bar) 15 | 16 | /** manifest: 17 | expand 18 | args = -Wgnu-zero-variadic-macro-arguments 19 | 20 | token paste delete comma gnu.c:1:55: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments] 21 | token paste delete comma gnu.c:1:55: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments] 22 | token paste delete comma gnu.c:6:31: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments] 23 | token paste delete comma gnu.c:6:31: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments] 24 | token paste delete comma gnu.c:11:23: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments] 25 | */ 26 | -------------------------------------------------------------------------------- /test/cases/stdarg.c: -------------------------------------------------------------------------------- 1 | #include 2 | void foo(int a, ...) { 3 | va_list va, new; 4 | va_start(va, a); 5 | int arg = va_arg(va, int); 6 | va_copy(va, new); 7 | va_end(va); 8 | } 9 | void bar(int a, int b, ...) { 10 | va_list va; 11 | va_start(va, a); 12 | } 13 | void baz(int a) { 14 | va_list va; 15 | va_start(va, a); 16 | } 17 | va_list va; 18 | int a = va_start(va, 1); 19 | int b = __builtin_va_end; 20 | int c = __builtin_foo(); 21 | 22 | /** manifest: 23 | syntax 24 | 25 | stdarg.c:11:5: warning: second argument to 'va_start' is not the last named parameter [-Wvarargs] 26 | stdarg.h:12:52: note: expanded from here 27 | stdarg.c:11:18: note: expanded from here 28 | stdarg.c:15:5: error: 'va_start' used in a function with fixed args 29 | stdarg.h:12:29: note: expanded from here 30 | stdarg.c:18:9: error: 'va_start' cannot be used outside a function 31 | stdarg.h:12:29: note: expanded from here 32 | stdarg.c:18:9: error: initializing 'int' from incompatible type 'void' 33 | stdarg.h:12:29: note: expanded from here 34 | stdarg.c:19:9: error: builtin function must be directly called 35 | stdarg.c:20:9: error: use of unknown builtin '__builtin_foo' [-Wimplicit-function-declaration] 36 | */ 37 | -------------------------------------------------------------------------------- /test/cases/enum sizes windows.c: -------------------------------------------------------------------------------- 1 | enum Small { 2 | A 3 | } __attribute__((packed)); 4 | 5 | _Static_assert(sizeof(enum Small) == sizeof(int), "Small"); 6 | 7 | enum __attribute__((packed)) StillSmall { 8 | B = 255 9 | }; 10 | 11 | _Static_assert(sizeof(enum StillSmall) == sizeof(int), "StillSmall"); 12 | 13 | enum Medium { 14 | C = 255, 15 | D 16 | } __attribute__((packed)); 17 | 18 | _Static_assert(sizeof(enum Medium) == sizeof(int), "Medium"); 19 | 20 | enum StillMedium { 21 | E = -32768, 22 | F = 32767 23 | } __attribute__((packed)); 24 | 25 | _Static_assert(sizeof(enum StillMedium) == sizeof(int), "StillMedium"); 26 | 27 | enum Normal { 28 | G = -2147483648, 29 | H = 2147483647 30 | }; 31 | _Static_assert(sizeof(enum Normal) == sizeof(int), "Normal"); 32 | 33 | enum Unsigned { 34 | I = 4294967295, 35 | }; 36 | _Static_assert(sizeof(enum Unsigned) == sizeof(int), "Unsigned"); 37 | 38 | enum Large { 39 | J = -1, 40 | K = 4294967295 41 | }; 42 | _Static_assert(sizeof(enum Large) == sizeof(int), "Large"); 43 | 44 | enum Huge { 45 | L = 18446744073709551615ULL 46 | }; 47 | _Static_assert(sizeof(enum Huge) == sizeof(int), "Huge"); 48 | 49 | /** manifest: 50 | syntax 51 | args = --target=x86_64-windows-msvc 52 | */ 53 | -------------------------------------------------------------------------------- /test/cases/limits header.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | _Static_assert(CHAR_BIT == 8); 4 | 5 | _Static_assert(BOOL_WIDTH == 8); 6 | _Static_assert(CHAR_WIDTH == 8); 7 | _Static_assert(SCHAR_WIDTH == 8); 8 | _Static_assert(UCHAR_WIDTH == 8); 9 | _Static_assert(SHRT_WIDTH == 16); 10 | _Static_assert(INT_WIDTH == 32); 11 | _Static_assert(UINT_WIDTH == 32); 12 | _Static_assert(LONG_WIDTH == 64); 13 | _Static_assert(ULONG_WIDTH == 64); 14 | 15 | _Static_assert(UCHAR_MAX == 255); 16 | _Static_assert(SCHAR_MAX == 127); 17 | _Static_assert(USHRT_MAX == 65535); 18 | _Static_assert(SHRT_MAX == 32767); 19 | _Static_assert(INT_MAX == 2147483647); 20 | _Static_assert(LONG_MAX == 9223372036854775807L); 21 | 22 | _Static_assert(CHAR_MIN == -128); 23 | _Static_assert(SCHAR_MIN == -128); 24 | _Static_assert(SHRT_MIN == -32768); 25 | _Static_assert(INT_MIN == -2147483648); 26 | _Static_assert(LONG_MIN == -9223372036854775807L - 1L); 27 | _Static_assert(LLONG_MIN == -9223372036854775807L - 1L); 28 | 29 | _Static_assert(UINT_MAX == 4294967295U); 30 | _Static_assert(ULONG_MAX == 18446744073709551615UL); 31 | _Static_assert(ULLONG_MAX == 18446744073709551615UL); 32 | 33 | /** manifest: 34 | syntax 35 | args = --target=x86_64-linux-gnu -std=c23 36 | */ 37 | -------------------------------------------------------------------------------- /test/cases/enum overflow msvc.c: -------------------------------------------------------------------------------- 1 | enum E1 { 2 | A = 2147483647, 3 | B, 4 | C = 4294967295UL, 5 | D, 6 | F = 9223372036854775807, 7 | G, 8 | H = 18446744073709551615ULL, 9 | I 10 | }; 11 | 12 | _Static_assert(A == 2147483647, "A"); 13 | _Static_assert(B != 2147483648, "B"); 14 | _Static_assert(C == -1, "C"); 15 | _Static_assert(D != 4294967296UL, "D"); 16 | _Static_assert(F != 9223372036854775807LL, "F"); 17 | _Static_assert(G != 9223372036854775808ULL, "G"); 18 | _Static_assert(H == -1, "H"); 19 | 20 | _Static_assert(H == C, "enumerator value was truncated"); 21 | 22 | /** manifest: 23 | syntax 24 | args = -target x86_64-windows-msvc 25 | skip = should not warn about overflow 26 | skip = should not warn about enumerator value not being representable 27 | 28 | enum overflow msvc.c:3:5: warning: overflow in enumeration value 29 | enum overflow msvc.c:5:5: warning: overflow in enumeration value 30 | enum overflow msvc.c:7:5: warning: incremented enumerator value 9223372036854775808 is not representable in the largest integer type [-Wenum-too-large] 31 | enum overflow msvc.c:9:5: warning: incremented enumerator value 18446744073709551616 is not representable in the largest integer type [-Wenum-too-large] 32 | */ 33 | -------------------------------------------------------------------------------- /test/cases/msp430 builtin types.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #if !defined(MSP430) or !defined(__MSP430__) 5 | #error "Missing target macros" 6 | #endif 7 | 8 | _Static_assert(sizeof(int) == 2, "Wrong int size"); 9 | _Static_assert(sizeof(long double) == 8, "Wrong long double size"); 10 | _Static_assert(sizeof(char *) == 2, "Wrong pointer size"); 11 | _Static_assert((char)-1 >= 0, "char should be unsigned"); 12 | _Static_assert(sizeof(ptrdiff_t) == 2, "Wrong ptrdiff_t size"); 13 | _Static_assert(sizeof(size_t) == 2, "Wrong size_t size"); 14 | _Static_assert(sizeof(wchar_t) == 2, "Wrong wchar_t size"); 15 | _Static_assert(_Alignof(char *) == 2, "wrong pointer alignment"); 16 | _Static_assert(_Alignof(int) == 2, "wrong int alignment"); 17 | _Static_assert(_Alignof(long) == 2, "wrong long alignment"); 18 | _Static_assert(_Alignof(long long) == 2, "wrong long long alignment"); 19 | _Static_assert(_Alignof(float) == 2, "wrong float alignment"); 20 | _Static_assert(_Alignof(double) == 2, "wrong double alignment"); 21 | _Static_assert(_Alignof(long double) == 2, "wrong long double alignment"); 22 | 23 | void foo(int x, ... ) 24 | { 25 | va_list list; 26 | char *foo = list; 27 | } 28 | 29 | /** manifest: 30 | syntax 31 | args = --target=msp430-other-none 32 | */ 33 | -------------------------------------------------------------------------------- /test/cases/shufflevector.c: -------------------------------------------------------------------------------- 1 | typedef int i2v __attribute__((__vector_size__(4 * 2))); 2 | typedef int i4v __attribute__((__vector_size__(4 * 4))); 3 | 4 | void foo(i2v a, i2v b, i4v c) { 5 | i4v d = __builtin_shufflevector(a, b, 0, 1, 2, 3); 6 | i2v e = __builtin_shufflevector(a, b, -1, 3); 7 | i4v f = __builtin_shufflevector(a, b, 1, 1); 8 | __builtin_shufflevector(a, c); 9 | __builtin_shufflevector(1, b); 10 | __builtin_shufflevector(a, 1); 11 | __builtin_shufflevector(a, b, -2, 5); 12 | } 13 | 14 | /** manifest: 15 | syntax 16 | args = --target=x86_64-linux-gnu -Wno-unused 17 | 18 | shufflevector.c:7:13: error: initializing 'i4v' (vector of 4 'int' values) from incompatible type '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values) 19 | shufflevector.c:8:5: error: first two arguments to '__builtin_shufflevector' must have the same type 20 | shufflevector.c:9:29: error: first argument to __builtin_shufflevector must be a vector type 21 | shufflevector.c:10:32: error: second argument to __builtin_shufflevector must be a vector type 22 | shufflevector.c:11:35: error: index for __builtin_shufflevector must be positive or -1 23 | shufflevector.c:11:39: error: index for __builtin_shufflevector must be less than the total number of vector elements 24 | */ 25 | -------------------------------------------------------------------------------- /test/cases/numbers.c: -------------------------------------------------------------------------------- 1 | int a = 0b; 2 | int b = 0x; 3 | int c = 0b12; 4 | int d = 0b1.2; 5 | double e = 019.5; 6 | double f = 0x12.e; 7 | int g = 0128; 8 | int h = 0iull; 9 | int i = 1e; 10 | double j = 0x1p; 11 | int k = 123LLuf; 12 | float l = 12e+2f; 13 | float m = 12E-2f; 14 | float n = 0x12P+2; 15 | float o = 0x12p-2; 16 | _Static_assert(0xE+0xC == 0xE + 0xC, ""); 17 | double p = 0x1.ep-1; 18 | double q = 0x1.eP-1; 19 | double r = 0x1.Ep-1; 20 | double s = 0x1.EP-1; 21 | double t = 1.ep-1; 22 | double u = 1.pp-1; 23 | 24 | /** manifest: 25 | syntax 26 | 27 | numbers.c:1:9: error: invalid suffix 'b' on integer constant 28 | numbers.c:2:9: error: invalid suffix 'x' on integer constant 29 | numbers.c:3:9: error: invalid digit '2' in binary constant 30 | numbers.c:4:9: error: invalid suffix '.2' on integer constant 31 | numbers.c:6:12: error: hexadecimal floating constant requires an exponent 32 | numbers.c:7:9: error: invalid digit '8' in octal constant 33 | numbers.c:9:9: error: exponent has no digits 34 | numbers.c:10:12: error: exponent has no digits 35 | numbers.c:11:9: error: invalid suffix 'LLuf' on integer constant 36 | numbers.c:16:16: error: invalid suffix '+0xC' on integer constant 37 | numbers.c:21:12: error: exponent has no digits 38 | numbers.c:22:12: error: invalid suffix 'pp-1' on floating constant 39 | */ 40 | -------------------------------------------------------------------------------- /test/cases/c23 keywords.c: -------------------------------------------------------------------------------- 1 | #include 2 | static_assert(1 == 1); 3 | static_assert(alignof(char) == 1); 4 | thread_local int x; 5 | bool b = 1; 6 | int alignas(16) y; 7 | 8 | #define static_assert no 9 | #define alignof no 10 | #define thread_local no 11 | #define bool no 12 | #define alignas no 13 | 14 | typedef typeof(int) MyInt; 15 | 16 | #if false 17 | #error false should expand to 0 18 | #endif 19 | 20 | #if true 21 | #else 22 | #error true should expand to 1 23 | #endif 24 | 25 | #define FOO true 26 | #if FOO 27 | #else 28 | #error true should expand to 1 29 | #endif 30 | 31 | #if true + 1 != 2 32 | #error true should expand to 1 in preprocessor arithmetic 33 | #endif 34 | 35 | #if defined(true) || defined(false) 36 | #error true and false should not be defined 37 | #endif 38 | 39 | /** manifest: 40 | syntax 41 | args = -std=c23 -pedantic -Wundef 42 | 43 | c23 keywords.c:8:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 44 | c23 keywords.c:9:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 45 | c23 keywords.c:10:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 46 | c23 keywords.c:11:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 47 | c23 keywords.c:12:9: warning: keyword is hidden by macro definition [-Wkeyword-macro] 48 | */ 49 | --------------------------------------------------------------------------------