pub enum Expr {
Show 30 variants
Error,
Name(Symbol),
Int(IntId),
Float(FloatId),
Char(CharId),
Str(StrId),
Bool(bool),
Nullptr,
Index {
base: ExprId,
index: ExprId,
},
Call {
callee: ExprId,
args: ExprList,
},
Member {
base: ExprId,
name: Symbol,
arrow: bool,
},
Unary {
op: UnaryOp,
operand: ExprId,
},
Binary {
op: BinaryOp,
lhs: ExprId,
rhs: ExprId,
},
Assign {
op: Option<BinaryOp>,
lhs: ExprId,
rhs: ExprId,
},
Cond {
cond: ExprId,
then: Option<ExprId>,
otherwise: ExprId,
},
Comma {
lhs: ExprId,
rhs: ExprId,
},
Cast {
ty: TypeNameId,
operand: ExprId,
},
CompoundLiteral {
ty: TypeNameId,
init: InitId,
},
SizeofExpr(ExprId),
SizeofType(TypeNameId),
AlignofExpr(ExprId),
AlignofType(TypeNameId),
Generic {
control: ExprId,
assocs: GenericList,
},
StmtExpr(StmtId),
LabelAddr(Symbol),
Offsetof {
ty: TypeNameId,
path: DesignatorList,
},
ChooseExpr {
cond: ExprId,
then: ExprId,
otherwise: ExprId,
},
TypesCompatible {
a: TypeNameId,
b: TypeNameId,
},
VaArg {
list: ExprId,
ty: TypeNameId,
},
Extension(ExprId),
}Expand description
One expression node.
Sixteen bytes, which is what the widest variant needs and what the whole arena therefore
costs per node. Anything that would not fit is an index into a side table on
Ast, which is why a call holds a range and not a vector.
Variants§
Error
A parse that did not work out.
Poisoned, per section 6.8: semantic analysis says nothing about a node that is already the result of a diagnostic, which is the mechanism that stops one syntax error becoming forty type errors.
Name(Symbol)
An identifier, before anything has looked it up.
The parser already knows whether the name is a typedef name, because it had to know to parse the surrounding text at all, but it does not resolve it to a declaration. That is semantic analysis, which has the scopes and the linkage rules.
Int(IntId)
An integer constant, in the constant table on Ast.
Float(FloatId)
A floating constant.
Char(CharId)
A character constant.
Str(StrId)
A string literal, with the adjacent ones already joined onto it by phase 7.
Bool(bool)
true or false, which C23 made constants rather than macros.
Nullptr
nullptr.
Index
base[index], in the order it was written, which is not always the pointer first.
Call
callee(args).
Fields
Member
base.name or base->name.
Fields
Unary
A prefix or postfix operator on one operand.
Binary
A binary operator, including the ones that do not evaluate both sides.
Assign
lhs = rhs, or a compound assignment with the operator kept as written.
Fields
Cond
cond ? then : otherwise, where then is absent in GNU’s cond ?: otherwise.
Fields
Comma
lhs, rhs.
Its own node rather than a BinaryOp, because the comma operator is a sequence point
with a discarded left side and shares nothing with arithmetic but its spelling.
Fields
Cast
(ty)operand.
CompoundLiteral
(ty){ ... }, which is an object and not a conversion.
SizeofExpr(ExprId)
sizeof operand, written without parentheses around a type.
SizeofType(TypeNameId)
sizeof (ty).
AlignofExpr(ExprId)
alignof operand, which is GNU’s __alignof__ since ISO C only has the type form.
AlignofType(TypeNameId)
alignof (ty).
Generic
_Generic(control, ...).
Fields
assocs: GenericListThe associations, in the order they were written, including the default one.
StmtExpr(StmtId)
({ ... }), GNU’s statement expression, whose value is its last expression statement.
LabelAddr(Symbol)
&&label, GNU’s label address.
Offsetof
__builtin_offsetof(ty, path), where path is a member and not an expression.
Fields
ty: TypeNameIdThe type being measured.
path: DesignatorListThe member path, which is a designator list because a.b[3].c is legal here.
ChooseExpr
__builtin_choose_expr(cond, then, otherwise).
The whole reason this exists is that the branch not chosen is never type checked, so it has to survive to semantic analysis as itself rather than as a conditional.
Fields
TypesCompatible
__builtin_types_compatible_p(a, b).
VaArg
__builtin_va_arg(list, ty).
Extension(ExprId)
__extension__ operand, which turns the pedantic diagnostics off inside it.