[clang] [clang][AST] Reduce some AST node size. (PR #142585)
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 3 04:36:52 PDT 2025
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/142585
This patch reduces the size of several AST nodes by moving some fields into the free bitfield space in the base `Stmt` class:
* `CXXForRangeStmt`: 96 → 88 bytes
* `ChooseExpr`: 56 → 48 bytes
* `ArrayTypeTraitExpr`: 56 → 48 bytes
* `ExpressionTraitExpr`: 40 → 32 bytes
* `CXXFoldExpr`: 64 → 56 bytes
* `ShuffleExpr`: 40 → 32 bytes
* `PackIndexingExpr`: 48 → 40 bytes
There are no noticeable memory savings (`Expr/Stmt` memory usage 125,824,496 vs 125,826,336 bytes for `SemaExpr.cpp`) in my testing, likely because these node types are not among the most common in typical ASTs.
>From 4b1cdc30ddb476d7e30519e5fe5ab6c298b59809 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Sat, 10 May 2025 07:44:51 +0200
Subject: [PATCH 1/3] [AST] Restructure the CXXForRanageStmt class to reduce
the size, 96 -> 88
---
clang/include/clang/AST/Expr.h | 9 +++------
clang/include/clang/AST/Stmt.h | 4 +++-
clang/include/clang/AST/StmtCXX.h | 2 +-
clang/lib/AST/Expr.cpp | 7 ++++---
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index a83320a7ddec2..5125d1a8349c1 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2890,9 +2890,6 @@ class MatrixSubscriptExpr : public Expr {
class CallExpr : public Expr {
enum { FN = 0, PREARGS_START = 1 };
- /// The number of arguments in the call expression.
- unsigned NumArgs;
-
/// The location of the right parentheses. This has a different meaning for
/// the derived classes of CallExpr.
SourceLocation RParenLoc;
@@ -3056,7 +3053,7 @@ class CallExpr : public Expr {
}
/// getNumArgs - Return the number of actual arguments to this call.
- unsigned getNumArgs() const { return NumArgs; }
+ unsigned getNumArgs() const { return CallExprBits.NumArgs; }
/// Retrieve the call arguments.
Expr **getArgs() {
@@ -3104,13 +3101,13 @@ class CallExpr : public Expr {
void shrinkNumArgs(unsigned NewNumArgs) {
assert((NewNumArgs <= getNumArgs()) &&
"shrinkNumArgs cannot increase the number of arguments!");
- NumArgs = NewNumArgs;
+ CallExprBits.NumArgs = NewNumArgs;
}
/// Bluntly set a new number of arguments without doing any checks whatsoever.
/// Only used during construction of a CallExpr in a few places in Sema.
/// FIXME: Find a way to remove it.
- void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; }
+ void setNumArgsUnsafe(unsigned NewNumArgs) { CallExprBits.NumArgs = NewNumArgs; }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 336eb6d3df7e1..bea85271fbe92 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -572,8 +572,10 @@ class alignas(void *) Stmt {
/// trailing objects belonging to CallExpr. Intentionally byte sized
/// for faster access.
unsigned OffsetToTrailingObjects : 8;
+
+ unsigned NumArgs:20;
};
- enum { NumCallExprBits = 32 };
+ enum { NumCallExprBits = 52 };
class MemberExprBitfields {
friend class ASTStmtReader;
diff --git a/clang/include/clang/AST/StmtCXX.h b/clang/include/clang/AST/StmtCXX.h
index 8b4ef24ed376a..a15a445fbea40 100644
--- a/clang/include/clang/AST/StmtCXX.h
+++ b/clang/include/clang/AST/StmtCXX.h
@@ -133,11 +133,11 @@ class CXXTryStmt final : public Stmt,
/// analysis of the constituent components. The original syntactic components
/// can be extracted using getLoopVariable and getRangeInit.
class CXXForRangeStmt : public Stmt {
- SourceLocation ForLoc;
enum { INIT, RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END };
// SubExprs[RANGE] is an expression or declstmt.
// SubExprs[COND] and SubExprs[INC] are expressions.
Stmt *SubExprs[END];
+ SourceLocation ForLoc;
SourceLocation CoawaitLoc;
SourceLocation ColonLoc;
SourceLocation RParenLoc;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 59c0e47c7c195..2a659ef67144a 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1460,7 +1460,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
unsigned MinNumArgs, ADLCallKind UsesADL)
: Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) {
- NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ CallExprBits.NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
unsigned NumPreArgs = PreArgs.size();
CallExprBits.NumPreArgs = NumPreArgs;
assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
@@ -1477,7 +1477,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
setPreArg(I, PreArgs[I]);
for (unsigned I = 0; I != Args.size(); ++I)
setArg(I, Args[I]);
- for (unsigned I = Args.size(); I != NumArgs; ++I)
+ for (unsigned I = Args.size(); I != CallExprBits.NumArgs; ++I)
setArg(I, nullptr);
this->computeDependence();
@@ -1490,7 +1490,8 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
bool HasFPFeatures, EmptyShell Empty)
- : Expr(SC, Empty), NumArgs(NumArgs) {
+ : Expr(SC, Empty) {
+ CallExprBits.NumArgs = NumArgs;
CallExprBits.NumPreArgs = NumPreArgs;
assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
>From ba84803e11817d686ed9f2473bd6ea3e2ee6a794 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Tue, 3 Jun 2025 10:44:35 +0200
Subject: [PATCH 2/3] More AST nodes:
- ChooseExpr 56->48
- ArrayTypeTraitExpr 56->48
- ExpressionTraitExpr 40->32
- CXXFoldExpr 64->56
- ShuffleExpr 40->32
- PackIndexingExpr 48->40
---
clang/include/clang/AST/Expr.h | 32 +++++----
clang/include/clang/AST/ExprCXX.h | 74 ++++++++++-----------
clang/include/clang/AST/Stmt.h | 81 ++++++++++++++++++++++-
clang/lib/AST/Expr.cpp | 7 +-
clang/lib/AST/ExprCXX.cpp | 3 +-
clang/lib/Serialization/ASTReaderStmt.cpp | 14 ++--
clang/lib/Serialization/ASTWriterStmt.cpp | 6 +-
7 files changed, 150 insertions(+), 67 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5125d1a8349c1..71011dabdade4 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3107,7 +3107,9 @@ class CallExpr : public Expr {
/// Bluntly set a new number of arguments without doing any checks whatsoever.
/// Only used during construction of a CallExpr in a few places in Sema.
/// FIXME: Find a way to remove it.
- void setNumArgsUnsafe(unsigned NewNumArgs) { CallExprBits.NumArgs = NewNumArgs; }
+ void setNumArgsUnsafe(unsigned NewNumArgs) {
+ CallExprBits.NumArgs = NewNumArgs;
+ }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
@@ -4520,7 +4522,6 @@ class ShuffleVectorExpr : public Expr {
// indices. The number of values in this list is always
// 2+the number of indices in the vector type.
Stmt **SubExprs;
- unsigned NumExprs;
public:
ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type,
@@ -4546,34 +4547,39 @@ class ShuffleVectorExpr : public Expr {
/// getNumSubExprs - Return the size of the SubExprs array. This includes the
/// constant expression, the actual arguments passed in, and the function
/// pointers.
- unsigned getNumSubExprs() const { return NumExprs; }
+ unsigned getNumSubExprs() const { return ShuffleVectorExprBits.NumExprs; }
/// Retrieve the array of expressions.
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
/// getExpr - Return the Expr at the specified index.
Expr *getExpr(unsigned Index) {
- assert((Index < NumExprs) && "Arg access out of range!");
+ assert((Index < ShuffleVectorExprBits.NumExprs) &&
+ "Arg access out of range!");
return cast<Expr>(SubExprs[Index]);
}
const Expr *getExpr(unsigned Index) const {
- assert((Index < NumExprs) && "Arg access out of range!");
+ assert((Index < ShuffleVectorExprBits.NumExprs) &&
+ "Arg access out of range!");
return cast<Expr>(SubExprs[Index]);
}
void setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs);
llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const {
- assert((N < NumExprs - 2) && "Shuffle idx out of range!");
+ assert((N < ShuffleVectorExprBits.NumExprs - 2) &&
+ "Shuffle idx out of range!");
return getExpr(N+2)->EvaluateKnownConstInt(Ctx);
}
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
+ return child_range(&SubExprs[0],
+ &SubExprs[0] + ShuffleVectorExprBits.NumExprs);
}
const_child_range children() const {
- return const_child_range(&SubExprs[0], &SubExprs[0] + NumExprs);
+ return const_child_range(&SubExprs[0],
+ &SubExprs[0] + ShuffleVectorExprBits.NumExprs);
}
};
@@ -4715,13 +4721,13 @@ class ChooseExpr : public Expr {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
SourceLocation BuiltinLoc, RParenLoc;
- bool CondIsTrue;
+
public:
ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
ExprValueKind VK, ExprObjectKind OK, SourceLocation RP,
bool condIsTrue)
- : Expr(ChooseExprClass, t, VK, OK), BuiltinLoc(BLoc), RParenLoc(RP),
- CondIsTrue(condIsTrue) {
+ : Expr(ChooseExprClass, t, VK, OK), BuiltinLoc(BLoc), RParenLoc(RP) {
+ ChooseExprBits.CondIsTrue = condIsTrue;
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -4737,9 +4743,9 @@ class ChooseExpr : public Expr {
bool isConditionTrue() const {
assert(!isConditionDependent() &&
"Dependent condition isn't true or false");
- return CondIsTrue;
+ return ChooseExprBits.CondIsTrue;
}
- void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; }
+ void setIsConditionTrue(bool isTrue) { ChooseExprBits.CondIsTrue = isTrue; }
bool isConditionDependent() const {
return getCond()->isTypeDependent() || getCond()->isValueDependent();
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 844f6dd90ae1d..bc70ba08f3073 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2973,10 +2973,6 @@ class TypeTraitExpr final
/// __array_extent(int[10][20], 1) == 20
/// \endcode
class ArrayTypeTraitExpr : public Expr {
- /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
- LLVM_PREFERRED_TYPE(ArrayTypeTrait)
- unsigned ATT : 2;
-
/// The value of the type trait. Unspecified if dependent.
uint64_t Value = 0;
@@ -2998,21 +2994,27 @@ class ArrayTypeTraitExpr : public Expr {
ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att,
TypeSourceInfo *queried, uint64_t value, Expr *dimension,
SourceLocation rparen, QualType ty)
- : Expr(ArrayTypeTraitExprClass, ty, VK_PRValue, OK_Ordinary), ATT(att),
+ : Expr(ArrayTypeTraitExprClass, ty, VK_PRValue, OK_Ordinary),
Value(value), Dimension(dimension), Loc(loc), RParen(rparen),
QueriedType(queried) {
assert(att <= ATT_Last && "invalid enum value!");
- assert(static_cast<unsigned>(att) == ATT && "ATT overflow!");
+ ArrayTypeTraitExprBits.ATT = att;
+ assert(static_cast<unsigned>(att) == ArrayTypeTraitExprBits.ATT &&
+ "ATT overflow!");
setDependence(computeDependence(this));
}
explicit ArrayTypeTraitExpr(EmptyShell Empty)
- : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {}
+ : Expr(ArrayTypeTraitExprClass, Empty) {
+ ArrayTypeTraitExprBits.ATT = 0;
+ }
SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
SourceLocation getEndLoc() const LLVM_READONLY { return RParen; }
- ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); }
+ ArrayTypeTrait getTrait() const {
+ return static_cast<ArrayTypeTrait>(ArrayTypeTraitExprBits.ATT);
+ }
QualType getQueriedType() const { return QueriedType->getType(); }
@@ -3044,14 +3046,6 @@ class ArrayTypeTraitExpr : public Expr {
/// __is_lvalue_expr(1) == false
/// \endcode
class ExpressionTraitExpr : public Expr {
- /// The trait. A ExpressionTrait enum in MSVC compatible unsigned.
- LLVM_PREFERRED_TYPE(ExpressionTrait)
- unsigned ET : 31;
-
- /// The value of the type trait. Unspecified if dependent.
- LLVM_PREFERRED_TYPE(bool)
- unsigned Value : 1;
-
/// The location of the type trait keyword.
SourceLocation Loc;
@@ -3067,24 +3061,32 @@ class ExpressionTraitExpr : public Expr {
ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried,
bool value, SourceLocation rparen, QualType resultType)
: Expr(ExpressionTraitExprClass, resultType, VK_PRValue, OK_Ordinary),
- ET(et), Value(value), Loc(loc), RParen(rparen),
- QueriedExpression(queried) {
+ Loc(loc), RParen(rparen), QueriedExpression(queried) {
+ ExpressionTraitExprBits.ET = et;
+ ExpressionTraitExprBits.Value = value;
+
assert(et <= ET_Last && "invalid enum value!");
- assert(static_cast<unsigned>(et) == ET && "ET overflow!");
+ assert(static_cast<unsigned>(et) == ExpressionTraitExprBits.ET &&
+ "ET overflow!");
setDependence(computeDependence(this));
}
explicit ExpressionTraitExpr(EmptyShell Empty)
- : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {}
+ : Expr(ExpressionTraitExprClass, Empty) {
+ ExpressionTraitExprBits.ET = 0;
+ ExpressionTraitExprBits.Value = false;
+ }
SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
SourceLocation getEndLoc() const LLVM_READONLY { return RParen; }
- ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); }
+ ExpressionTrait getTrait() const {
+ return static_cast<ExpressionTrait>(ExpressionTraitExprBits.ET);
+ }
Expr *getQueriedExpression() const { return QueriedExpression; }
- bool getValue() const { return Value; }
+ bool getValue() const { return ExpressionTraitExprBits.Value; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ExpressionTraitExprClass;
@@ -4505,22 +4507,15 @@ class PackIndexingExpr final
// The pack being indexed, followed by the index
Stmt *SubExprs[2];
- // The size of the trailing expressions.
- unsigned TransformedExpressions : 31;
-
- LLVM_PREFERRED_TYPE(bool)
- unsigned FullySubstituted : 1;
-
PackIndexingExpr(QualType Type, SourceLocation EllipsisLoc,
SourceLocation RSquareLoc, Expr *PackIdExpr, Expr *IndexExpr,
ArrayRef<Expr *> SubstitutedExprs = {},
bool FullySubstituted = false)
: Expr(PackIndexingExprClass, Type, VK_LValue, OK_Ordinary),
EllipsisLoc(EllipsisLoc), RSquareLoc(RSquareLoc),
- SubExprs{PackIdExpr, IndexExpr},
- TransformedExpressions(SubstitutedExprs.size()),
- FullySubstituted(FullySubstituted) {
-
+ SubExprs{PackIdExpr, IndexExpr} {
+ PackIndexingExprBits.TransformedExpressions = SubstitutedExprs.size();
+ PackIndexingExprBits.FullySubstituted = FullySubstituted;
auto *Exprs = getTrailingObjects<Expr *>();
std::uninitialized_copy(SubstitutedExprs.begin(), SubstitutedExprs.end(),
Exprs);
@@ -4534,7 +4529,7 @@ class PackIndexingExpr final
PackIndexingExpr(EmptyShell Empty) : Expr(PackIndexingExprClass, Empty) {}
unsigned numTrailingObjects(OverloadToken<Expr *>) const {
- return TransformedExpressions;
+ return PackIndexingExprBits.TransformedExpressions;
}
public:
@@ -4547,11 +4542,14 @@ class PackIndexingExpr final
static PackIndexingExpr *CreateDeserialized(ASTContext &Context,
unsigned NumTransformedExprs);
- bool isFullySubstituted() const { return FullySubstituted; }
+ bool isFullySubstituted() const {
+ return PackIndexingExprBits.FullySubstituted;
+ }
/// Determine if the expression was expanded to empty.
bool expandsToEmptyPack() const {
- return isFullySubstituted() && TransformedExpressions == 0;
+ return isFullySubstituted() &&
+ PackIndexingExprBits.TransformedExpressions == 0;
}
/// Determine the location of the 'sizeof' keyword.
@@ -4589,7 +4587,8 @@ class PackIndexingExpr final
/// Return the trailing expressions, regardless of the expansion.
ArrayRef<Expr *> getExpressions() const {
- return {getTrailingObjects<Expr *>(), TransformedExpressions};
+ return {getTrailingObjects<Expr *>(),
+ PackIndexingExprBits.TransformedExpressions};
}
static bool classof(const Stmt *T) {
@@ -4987,7 +4986,6 @@ class CXXFoldExpr : public Expr {
// than the number of expansions.
UnsignedOrNone NumExpansions = std::nullopt;
Stmt *SubExprs[SubExpr::Count];
- BinaryOperatorKind Opcode;
public:
CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee,
@@ -5020,7 +5018,7 @@ class CXXFoldExpr : public Expr {
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
- BinaryOperatorKind getOperator() const { return Opcode; }
+ BinaryOperatorKind getOperator() const { return CXXFoldExprBits.Opcode; }
UnsignedOrNone getNumExpansions() const { return NumExpansions; }
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index bea85271fbe92..8ed00a275d5a5 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -19,6 +19,7 @@
#include "clang/AST/OperationKinds.h"
#include "clang/AST/StmtIterator.h"
#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/ExpressionTraits.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Lambda.h"
@@ -572,8 +573,8 @@ class alignas(void *) Stmt {
/// trailing objects belonging to CallExpr. Intentionally byte sized
/// for faster access.
unsigned OffsetToTrailingObjects : 8;
-
- unsigned NumArgs:20;
+
+ unsigned NumArgs : 20;
};
enum { NumCallExprBits = 52 };
@@ -734,6 +735,15 @@ class alignas(void *) Stmt {
unsigned ProducedByFoldExpansion : 1;
};
+ class ShuffleVectorExprBitfields {
+ friend class ShuffleVectorExpr;
+
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ unsigned NumExprs;
+ };
+
class StmtExprBitfields {
friend class ASTStmtReader;
friend class StmtExpr;
@@ -747,6 +757,16 @@ class alignas(void *) Stmt {
unsigned TemplateDepth;
};
+ class ChooseExprBitfields {
+ friend class ASTStmtReader;
+ friend class ChooseExpr;
+
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ bool CondIsTrue : 1;
+ };
+
//===--- C++ Expression bitfields classes ---===//
class CXXOperatorCallExprBitfields {
@@ -1182,6 +1202,57 @@ class alignas(void *) Stmt {
SourceLocation RequiresKWLoc;
};
+ class ArrayTypeTraitExprBitfields {
+ friend class ArrayTypeTraitExpr;
+ friend class ASTStmtReader;
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
+ LLVM_PREFERRED_TYPE(ArrayTypeTrait)
+ unsigned ATT : 2;
+ };
+
+ class ExpressionTraitExprBitfields {
+ friend class ExpressionTraitExpr;
+ friend class ASTStmtReader;
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ /// The trait. A ExpressionTrait enum in MSVC compatible unsigned.
+ LLVM_PREFERRED_TYPE(ExpressionTrait)
+ unsigned ET : 31;
+
+ /// The value of the type trait. Unspecified if dependent.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned Value : 1;
+ };
+
+ class CXXFoldExprBitfields {
+ friend class CXXFoldExpr;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ BinaryOperatorKind Opcode;
+ };
+
+ class PackIndexingExprBitfields {
+ friend class PackIndexingExpr;
+ friend class ASTStmtWriter;
+ friend class ASTStmtReader;
+
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+ // The size of the trailing expressions.
+ unsigned TransformedExpressions : 31;
+
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned FullySubstituted : 1;
+ };
+
//===--- C++ Coroutines bitfields classes ---===//
class CoawaitExprBitfields {
@@ -1277,9 +1348,11 @@ class alignas(void *) Stmt {
PseudoObjectExprBitfields PseudoObjectExprBits;
SourceLocExprBitfields SourceLocExprBits;
ParenExprBitfields ParenExprBits;
+ ShuffleVectorExprBitfields ShuffleVectorExprBits;
// GNU Extensions.
StmtExprBitfields StmtExprBits;
+ ChooseExprBitfields ChooseExprBits;
// C++ Expressions
CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
@@ -1306,6 +1379,10 @@ class alignas(void *) Stmt {
SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits;
LambdaExprBitfields LambdaExprBits;
RequiresExprBitfields RequiresExprBits;
+ ArrayTypeTraitExprBitfields ArrayTypeTraitExprBits;
+ ExpressionTraitExprBitfields ExpressionTraitExprBits;
+ CXXFoldExprBitfields CXXFoldExprBits;
+ PackIndexingExprBitfields PackIndexingExprBits;
// C++ Coroutines expressions
CoawaitExprBitfields CoawaitBits;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 2a659ef67144a..7009afdd13143 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4406,7 +4406,8 @@ ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr *> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
: Expr(ShuffleVectorExprClass, Type, VK_PRValue, OK_Ordinary),
- BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) {
+ BuiltinLoc(BLoc), RParenLoc(RP) {
+ ShuffleVectorExprBits.NumExprs = args.size();
SubExprs = new (C) Stmt*[args.size()];
for (unsigned i = 0; i != args.size(); i++)
SubExprs[i] = args[i];
@@ -4417,8 +4418,8 @@ ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr *> args,
void ShuffleVectorExpr::setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs) {
if (SubExprs) C.Deallocate(SubExprs);
- this->NumExprs = Exprs.size();
- SubExprs = new (C) Stmt*[NumExprs];
+ this->ShuffleVectorExprBits.NumExprs = Exprs.size();
+ SubExprs = new (C) Stmt *[ShuffleVectorExprBits.NumExprs];
memcpy(SubExprs, Exprs.data(), sizeof(Expr *) * Exprs.size());
}
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 169f11b611066..0d56d10d1a58b 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1989,7 +1989,8 @@ CXXFoldExpr::CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee,
UnsignedOrNone NumExpansions)
: Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary), LParenLoc(LParenLoc),
EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
- NumExpansions(NumExpansions), Opcode(Opcode) {
+ NumExpansions(NumExpansions) {
+ CXXFoldExprBits.Opcode = Opcode;
// We rely on asserted invariant to distinguish left and right folds.
assert(((LHS && LHS->containsUnexpandedParameterPack()) !=
(RHS && RHS->containsUnexpandedParameterPack())) &&
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index f41cfcc53a35d..142332b1cf4bc 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2156,7 +2156,7 @@ void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) {
void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
VisitExpr(E);
- E->ATT = (ArrayTypeTrait)Record.readInt();
+ E->ArrayTypeTraitExprBits.ATT = (ArrayTypeTrait)Record.readInt();
E->Value = (unsigned int)Record.readInt();
SourceRange Range = readSourceRange();
E->Loc = Range.getBegin();
@@ -2167,8 +2167,8 @@ void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
VisitExpr(E);
- E->ET = (ExpressionTrait)Record.readInt();
- E->Value = (bool)Record.readInt();
+ E->ExpressionTraitExprBits.ET = (ExpressionTrait)Record.readInt();
+ E->ExpressionTraitExprBits.Value = (bool)Record.readInt();
SourceRange Range = readSourceRange();
E->QueriedExpression = Record.readSubExpr();
E->Loc = Range.getBegin();
@@ -2209,14 +2209,14 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
void ASTStmtReader::VisitPackIndexingExpr(PackIndexingExpr *E) {
VisitExpr(E);
- E->TransformedExpressions = Record.readInt();
- E->FullySubstituted = Record.readInt();
+ E->PackIndexingExprBits.TransformedExpressions = Record.readInt();
+ E->PackIndexingExprBits.FullySubstituted = Record.readInt();
E->EllipsisLoc = readSourceLocation();
E->RSquareLoc = readSourceLocation();
E->SubExprs[0] = Record.readStmt();
E->SubExprs[1] = Record.readStmt();
auto **Exprs = E->getTrailingObjects<Expr *>();
- for (unsigned I = 0; I < E->TransformedExpressions; ++I)
+ for (unsigned I = 0; I < E->PackIndexingExprBits.TransformedExpressions; ++I)
Exprs[I] = Record.readExpr();
}
@@ -2275,7 +2275,7 @@ void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
E->SubExprs[0] = Record.readSubExpr();
E->SubExprs[1] = Record.readSubExpr();
E->SubExprs[2] = Record.readSubExpr();
- E->Opcode = (BinaryOperatorKind)Record.readInt();
+ E->CXXFoldExprBits.Opcode = (BinaryOperatorKind)Record.readInt();
}
void ASTStmtReader::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index b9eabd5ddb64c..83fe30e492b1f 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2211,8 +2211,8 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
void ASTStmtWriter::VisitPackIndexingExpr(PackIndexingExpr *E) {
VisitExpr(E);
- Record.push_back(E->TransformedExpressions);
- Record.push_back(E->FullySubstituted);
+ Record.push_back(E->PackIndexingExprBits.TransformedExpressions);
+ Record.push_back(E->PackIndexingExprBits.FullySubstituted);
Record.AddSourceLocation(E->getEllipsisLoc());
Record.AddSourceLocation(E->getRSquareLoc());
Record.AddStmt(E->getPackIdExpression());
@@ -2277,7 +2277,7 @@ void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) {
Record.AddStmt(E->SubExprs[0]);
Record.AddStmt(E->SubExprs[1]);
Record.AddStmt(E->SubExprs[2]);
- Record.push_back(E->Opcode);
+ Record.push_back(E->CXXFoldExprBits.Opcode);
Code = serialization::EXPR_CXX_FOLD;
}
>From bc998ea7085f4f012c3f15ec1a720cb07887cb36 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Tue, 3 Jun 2025 13:34:53 +0200
Subject: [PATCH 3/3] Revert the change in CallExpr
---
clang/include/clang/AST/Expr.h | 9 ++++++---
clang/include/clang/AST/Stmt.h | 4 +---
clang/lib/AST/Expr.cpp | 7 +++----
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 71011dabdade4..5b033ff8660fb 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2890,6 +2890,9 @@ class MatrixSubscriptExpr : public Expr {
class CallExpr : public Expr {
enum { FN = 0, PREARGS_START = 1 };
+ /// The number of arguments in the call expression.
+ unsigned NumArgs;
+
/// The location of the right parentheses. This has a different meaning for
/// the derived classes of CallExpr.
SourceLocation RParenLoc;
@@ -3053,7 +3056,7 @@ class CallExpr : public Expr {
}
/// getNumArgs - Return the number of actual arguments to this call.
- unsigned getNumArgs() const { return CallExprBits.NumArgs; }
+ unsigned getNumArgs() const { return NumArgs; }
/// Retrieve the call arguments.
Expr **getArgs() {
@@ -3101,14 +3104,14 @@ class CallExpr : public Expr {
void shrinkNumArgs(unsigned NewNumArgs) {
assert((NewNumArgs <= getNumArgs()) &&
"shrinkNumArgs cannot increase the number of arguments!");
- CallExprBits.NumArgs = NewNumArgs;
+ NumArgs = NewNumArgs;
}
/// Bluntly set a new number of arguments without doing any checks whatsoever.
/// Only used during construction of a CallExpr in a few places in Sema.
/// FIXME: Find a way to remove it.
void setNumArgsUnsafe(unsigned NewNumArgs) {
- CallExprBits.NumArgs = NewNumArgs;
+ NumArgs = NewNumArgs;
}
typedef ExprIterator arg_iterator;
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 8ed00a275d5a5..43e9f61c1b461 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -573,10 +573,8 @@ class alignas(void *) Stmt {
/// trailing objects belonging to CallExpr. Intentionally byte sized
/// for faster access.
unsigned OffsetToTrailingObjects : 8;
-
- unsigned NumArgs : 20;
};
- enum { NumCallExprBits = 52 };
+ enum { NumCallExprBits = 32 };
class MemberExprBitfields {
friend class ASTStmtReader;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 7009afdd13143..dee1258691698 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1460,7 +1460,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
unsigned MinNumArgs, ADLCallKind UsesADL)
: Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) {
- CallExprBits.NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
unsigned NumPreArgs = PreArgs.size();
CallExprBits.NumPreArgs = NumPreArgs;
assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
@@ -1477,7 +1477,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
setPreArg(I, PreArgs[I]);
for (unsigned I = 0; I != Args.size(); ++I)
setArg(I, Args[I]);
- for (unsigned I = Args.size(); I != CallExprBits.NumArgs; ++I)
+ for (unsigned I = Args.size(); I != NumArgs; ++I)
setArg(I, nullptr);
this->computeDependence();
@@ -1490,8 +1490,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
bool HasFPFeatures, EmptyShell Empty)
- : Expr(SC, Empty) {
- CallExprBits.NumArgs = NumArgs;
+ : Expr(SC, Empty), NumArgs(NumArgs) {
CallExprBits.NumPreArgs = NumPreArgs;
assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
More information about the cfe-commits
mailing list