gcc or clang) to expand macros, include headers, and process directives.
Overview
MCC delegates preprocessing to the system C compiler rather than implementing its own preprocessor. This stage transforms source files with preprocessor directives into plain C code ready for parsing. Input:SourceFile (raw C source code)Output:
Text (preprocessed C code)Module:
crates/mcc/src/preprocessing.rs
Entry Point
Implementation Details
External Command
The preprocessor is invoked viastd::process::Command with specific flags:
-E: Stop after preprocessing (don’t compile)-P: Omit linemarker annotations (cleaner output for parsing)
Error Handling
Two types of errors are caught:- Failed to start: The compiler executable is missing or unexecutable
- Non-zero exit: The preprocessor encountered errors (syntax, missing files, etc.)
Output
On success, stdout is decoded as UTF-8 and wrapped in aText type:
Design Rationale
Why external preprocessing?- Reuses robust, battle-tested preprocessor implementations
- Avoids reimplementing complex macro expansion and conditional compilation
- Ensures compatibility with existing C codebases
- Simplifies MCC’s architecture by focusing on compilation stages
- Requires system C compiler installation
- Adds process invocation overhead
- Diagnostic quality depends on external tool
Example
Input (main.c):RETURN_CODE is expanded, and the #define directive is removed.
Related Stages
- Next: Parsing – Converts preprocessed text to AST
- Error Recovery: Preprocessing errors prevent further compilation