When dealing with large C++ projects, adding debugging or tracing code to every function manually can be time-consuming. By combining Python with Clang’s parsing library (libclang), this process can be automated.
The workflow begins with preprocessing the C++ source file using g++ -E. Preprocessing expands macros and resolves includes, producing a file that is easier to analyze with Clang.
Next, the Python script uses clang.cindex to create an AST (Abstract Syntax Tree). It walks through all nodes and collects functions such as:
- Regular functions
- Function templates
- Class methods, constructors, and destructors
- Lambdas
GPU-specific functions marked with __global__ or __device__ are skipped to avoid interference with CUDA code.
The script then records the start line and column of each function body (COMPOUND_STMT) to determine exactly where to insert new code.
After detecting function bodies, the script can insert custom code automatically. For example, a simple logging statement:
printf("func: %s\n", __func__);This line prints the function name whenever it is executed, helping with tracing and debugging.
To avoid shifting insertion points, the script sorts all target functions in reverse order by line and column before editing the source code.
- Automation: No need to manually edit each function.
- Accuracy: Uses Clang’s AST, ensuring correct detection of functions even in complex C++ code.
- Flexibility: Developers can insert any debugging or instrumentation code, not just
printf.
Given a simple input file, the script will:
- Preprocess it with
g++ -E. - Extract preprocessor mapping information.
- Parse the AST with Clang to locate all function bodies.
- Insert the logging code at the start of each function.
- Output a modified source file ready for compilation.
This approach allows developers to add consistent, automated instrumentation to C++ codebases—making debugging and runtime tracing much easier.