The test suite for the upcoming book Writing a C Compiler, a hands-on guide to writing your own compiler for a big chunk of C. These tests are still a work in progress!
Each test case is a C program. Some (in the valid/
subdirectories) are valid, and others (in the invalid_*/
subdirectories) have compile-time errors.
The test runner compiles each test program with the compiler under test. An invalid test case passes if the compiler rejects it (i.e. terminates with a non-zero exit code and does not produce any output files). A valid test case passes if it's compiled correctly (i.e. the compiler produces an executable which, when run, produces the expected output and terminates with the expected exit code).
Some invalid test cases include errors that most compilers don't warn about by default. If GCC or Clang isn't complaining about an invalid test case, try compiling it again with the -pedantic
flag.
You need the gcc
command on your path. (On macOS this is an alias for Clang; this is fine.) You also need Python 3.8 or later.
git clone https://github.com/nlsandler/writing-a-c-compiler-tests.git
cd writing-a-c-compiler-tests
./test_compiler --check-setup # make sure you meet all the system requirements
- Run the tests for chapters 1-4
./test_compiler ~/mycc --chapter 4
- Run the tests for chapter 4 but not chapters 1-3
./test_compiler ~/mycc --chapter 4 --latest-only
- Run the valid test cases for chapters 1-4, but skip the invalid ones (useful when your frontend passess are working but the backend is buggy).
./test_compiler ~/mycc --chapter 4 --skip-invalid
- Run the tests for chapters 1-4, stopping after the first test failure:
./test_compiler ~/mycc --chapter 4 -f
- Run the tests for chapters 1-9; include tests for bitwise operations and switch statements (extra credit features) but not for other extra credit features.
./test_compiler ~/mycc --chapter 9 --bitwise --compound
- Run test cases for chapter 1; specify that the compiler exits with code
1
or2
if it hits a lexer or parser error. When specified, an invalid test case passes only if the compiler exits with one of these exit codes, and fails otherwise. Useful for distinguishing expected failures (i.e. the compiler detected an error) from unexpected failures (e.g. internal errors, segfaults).
./test_compiler ~/my_cc --chapter 1 --expected-error-codes 1 2
Two things have changed since the initial early access version of the book:
- The chapter numbers have decreased by 1 (e.g. Chapter 2 in the EA version is now Chapter 1).
- We now use
int main(void)
instead ofint main()
to declare a function with no parameters. You'll need to define avoid
token in the lexer and include it in the grammar rule for function definitions.