In the last lesson, we traced the journey of source code through the initial phases of the Clang frontend, culminating in the creation of a semantically validated Abstract Syntax Tree (AST). You learned that the Parser builds this tree and Sema annotates it with crucial information like types and resolved names. We now turn our full attention to this pivotal data structure.
Today's goal is to explain the logical structure and hierarchy of the Clang Abstract Syntax Tree (AST). The AST is the frontend's primary output and the main data structure you will interact with when analyzing code, writing Clang-based tools, or debugging many types of frontend bugs. A solid mental model of its structure is non-negotiable for any aspiring Clang contributor.
What is an Abstract Syntax Tree?
At its core, an Abstract Syntax Tree is a hierarchical data structure that represents the grammatical structure of your source code. It captures the essence of the program's logic, abstracting away superficial details like whitespace, comments, and the precise placement of parentheses. For a systems programmer, you can think of it as the in-memory, object-oriented representation of a C++ program.
The following short video provides a clear, visual introduction to the concept of an AST, starting from a simple mathematical expression and moving to a C function.
This video from the CompilersLab channel, "Introduction to Clang," offers an excellent conceptual starting point for understanding ASTs.
Watch the first three segments: the introduction explaining what an AST is, the tree representation of a mathematical expression, and finally, the AST of a simple C function. Pay close attention to how operations, variables, and function structure are mapped to nodes in the tree.
As the video mentions, Clang's AST is particularly "high-fidelity," meaning it retains a very close correspondence to the original source code. This makes it exceptionally powerful for tools that perform source-to-source transformations, a common task in many GSoC projects.
The Core AST Node Hierarchies
A key aspect of the Clang AST's design is that its nodes do not derive from a single, universal base class (like a hypothetical ASTNode). Instead, the AST is organized into several major class hierarchies. Understanding these distinct families of nodes is the first step to navigating the tree.
[PDF] Lecture Slides for the Clang Libraries (LLVM/Clang 15)
These lecture slides from a course on the Clang libraries provide a concise breakdown of the primary AST node categories.
Please read the slide titled ASTs (page 98). This slide introduces the four fundamental kinds of AST nodes and makes the important point that Expr derives from Stmt.
As the slides explain, almost every node you encounter in the Clang AST will belong to one of these four categories:
Decl(Declarations): Nodes that introduce new names or entities into the program. Examples include functions, variables, structs, classes, and namespaces.Stmt(Statements): Nodes that represent actions or control flow. Examples includeifstatements,forloops, andreturnstatements.Expr(Expressions): Nodes that represent computations which produce a value. Examples include binary operations (+,*), function calls, and variable references.Type: Nodes that represent a type in the C++ type system, such asint,float*, or a custom class type.
The most crucial relationship to internalize here is that Expr is a subclass of Stmt. This reflects the C++ grammar rule that any expression can be used as a statement (e.g., x + y; is a valid, though useless, statement).
This inheritance relationship is a fundamental part of the AST's structure. The following diagram, generated from the Clang source documentation, shows the complex inheritance graph for Expr and Stmt. Don't worry about the details; focus on the main arrow.

A Deeper Look at the Node Families
Let's explore the roles of Decl, Stmt, and Expr in more detail.
[PDF] Lecture Slides for the Clang Libraries (LLVM/Clang 15)
These slides provide excellent summaries of the different node types and give concrete examples for each.
First, read the slide on Decl Nodes (page 101). Then, read the slide on Stmt and Expr Nodes (page 102). As you read, try to map the class names (e.g., FunctionDecl, CompoundStmt, DeclRefExpr) to the C++ code constructs they represent.
To summarize and expand on these points:
-
DeclNodes (The Skeleton): Declarations form the backbone of your program's structure. The root of the entire AST for a translation unit is aTranslationUnitDecl. This node has children that are the top-level declarations in the file, such asFunctionDeclfor functions andCXXRecordDeclfor classes/structs. In turn, aFunctionDeclcontainsParmVarDecl(parameter variable declaration) nodes for its parameters. -
StmtandExprNodes (The Logic): These nodes represent the actual work being done.- Statements (
Stmt) define control flow and structure. ACompoundStmtrepresents a block of code enclosed in curly braces{}and contains a list of other statements. AnIfStmtcontains a condition (Expr), a "then" part (Stmt), and an optional "else" part (Stmt). - Expressions (
Expr) represent computations. ABinaryOperatornode has two children, which are the left-hand and right-hand side expressions. ACallExprrepresents a function call and holds the expression for the function being called and a list of argument expressions. ADeclRefExpris a crucial and extremely common node; it represents a reference to a previously declared entity, such as using a variable or function name in an expression.
- Statements (
Visualizing the Hierarchy
Let's see how these nodes connect to form a tree for a concrete piece of code. Consider this simple C++ function:
// Hypothetical code for the AST below
struct Vector2D { float x, y; };
Vector2D scale(Vector2D v, float s) {
Vector2D result;
result.x = v.x * s;
result.y = v.y * s;
return result;
}
A simplified AST for a function like this would have a structure similar to the one shown in this diagram.

By tracing the paths from the root (CompoundStmt in this fragment), you can see the program's logical hierarchy:
- A function body (
CompoundStmt) contains statements. - One statement is a
DeclStmt, which declares a local variable. - Another is a
ReturnStmt, which specifies the function's return value. - The
ReturnStmtcontains an expression, here aCompoundLiteralExprused to initialize an object. - This expression, in turn, is built from other expressions like
ArraySubscriptExpr(accessing a member/element) andDeclRefExpr(referencing a declared variable).
This tree is the compiler's "understanding" of your code. To solidify this, let's watch an expert walk through the AST for a simple example and discuss its key classes.
2019 LLVM Developers’ Meeting: S. Haastregt & A. Stulova “An overview of Clang ”
Let's return to the "An overview of Clang" video from the LLVM Developers' Meeting. The second half of the talk is dedicated to the AST.
Watch the segment from the AST explanation. The speaker covers the immutability of the AST, presents the key classes (Type, Stmt, Expr, Decl), and then shows the output of -ast-dump for a simple program, tying the concepts together.
Conclusion
You have now examined the fundamental structure of the Clang AST. This is not just theoretical knowledge; it's the architectural blueprint you'll need to navigate the Clang codebase. When you encounter a bug related to parsing or semantic analysis, the problem will almost always manifest as a malformed or incorrectly annotated AST.
Key Takeaways:
- The Abstract Syntax Tree (AST) is a hierarchical, in-memory representation of the source code's grammatical structure.
- Clang's AST does not have a single base class. It is organized into several main hierarchies, the most important being
Decl,Stmt,Expr, andType. Declnodes represent declarations (e.g.,FunctionDecl,VarDecl) and form the skeleton of the tree.Stmtnodes represent actions and control flow (e.g.,IfStmt,CompoundStmt).Exprnodes represent computations that yield a value (e.g.,BinaryOperator,CallExpr).- Crucially,
Exprinherits fromStmt, reflecting that any expression can be used as a statement.
In the next lesson, we will get our hands dirty with the clang -Xclang -ast-dump command. You'll learn how to use this indispensable tool to generate and read the AST for any C++ code snippet, allowing you to directly observe the structures we've discussed today. This is a critical, practical skill for debugging the compiler and building tools on top of it.