[clang] [clang-tools-extra] [clang] Avoid re-evaluating field bitwidth (PR #117732)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 27 05:59:20 PST 2024
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/117732 at github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/117732
>From ca2184f07dbceda33ca429b3d63015d49fef3684 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Wed, 27 Nov 2024 08:54:51 +0100
Subject: [PATCH 1/2] Save FieldDecl BitWidth as a ConstantExpr
---
.../bugprone/TooSmallLoopVariableCheck.cpp | 2 +-
.../NarrowingConversionsCheck.cpp | 2 +-
.../hicpp/MultiwayPathsCoveredCheck.cpp | 2 +-
clang-tools-extra/clangd/Hover.cpp | 2 +-
clang/include/clang/AST/Decl.h | 4 ++--
clang/include/clang/ASTMatchers/ASTMatchers.h | 3 +--
clang/lib/AST/ASTContext.cpp | 10 ++++-----
clang/lib/AST/ByteCode/Interp.h | 10 ++++-----
.../lib/AST/ByteCode/InterpBuiltinBitCast.cpp | 2 +-
clang/lib/AST/Decl.cpp | 13 +++++++-----
clang/lib/AST/DeclCXX.cpp | 2 +-
clang/lib/AST/Expr.cpp | 3 +--
clang/lib/AST/ExprConstant.cpp | 2 +-
clang/lib/AST/Randstruct.cpp | 2 +-
clang/lib/AST/RecordLayoutBuilder.cpp | 6 +++---
clang/lib/CodeGen/ABIInfo.cpp | 2 +-
clang/lib/CodeGen/ABIInfoImpl.cpp | 2 +-
clang/lib/CodeGen/CGCall.cpp | 6 +++---
clang/lib/CodeGen/CGClass.cpp | 2 +-
clang/lib/CodeGen/CGDebugInfo.cpp | 8 +++----
clang/lib/CodeGen/CGNonTrivialStruct.cpp | 6 +++---
clang/lib/CodeGen/CGObjCMac.cpp | 3 +--
clang/lib/CodeGen/CGObjCRuntime.cpp | 2 +-
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 20 +++++++++---------
clang/lib/CodeGen/SwiftCallingConv.cpp | 2 +-
clang/lib/CodeGen/Targets/LoongArch.cpp | 2 +-
clang/lib/CodeGen/Targets/RISCV.cpp | 2 +-
clang/lib/CodeGen/Targets/X86.cpp | 2 +-
clang/lib/CodeGen/Targets/XCore.cpp | 2 +-
.../Frontend/Rewrite/RewriteModernObjC.cpp | 3 ++-
clang/lib/Sema/SemaChecking.cpp | 10 ++++-----
clang/lib/Sema/SemaDecl.cpp | 21 ++++++++++---------
clang/lib/Sema/SemaDeclCXX.cpp | 6 +++---
clang/lib/Sema/SemaDeclObjC.cpp | 3 +--
clang/lib/Sema/SemaOverload.cpp | 2 +-
clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 2 +-
clang/tools/libclang/CXType.cpp | 2 +-
clang/unittests/AST/ASTImporterTest.cpp | 4 ++--
38 files changed, 88 insertions(+), 91 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
index a73d46f01d9b2d..4ceeefb78ee824 100644
--- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
@@ -124,7 +124,7 @@ static MagnitudeBits calcMagnitudeBits(const ASTContext &Context,
unsigned SignedBits = IntExprType->isUnsignedIntegerType() ? 0U : 1U;
if (const auto *BitField = IntExpr->getSourceBitField()) {
- unsigned BitFieldWidth = BitField->getBitWidthValue(Context);
+ unsigned BitFieldWidth = BitField->getBitWidthValue();
return {BitFieldWidth - SignedBits, BitFieldWidth};
}
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
index 45fef9471d5211..25931d57943de1 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
@@ -38,7 +38,7 @@ AST_MATCHER(FieldDecl, hasIntBitwidth) {
assert(Node.isBitField());
const ASTContext &Ctx = Node.getASTContext();
unsigned IntBitWidth = Ctx.getIntWidth(Ctx.IntTy);
- unsigned CurrentBitWidth = Node.getBitWidthValue(Ctx);
+ unsigned CurrentBitWidth = Node.getBitWidthValue();
return IntBitWidth == CurrentBitWidth;
}
diff --git a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
index 47dafca2d03ff0..7028c3958f103e 100644
--- a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
+++ b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp
@@ -160,7 +160,7 @@ void MultiwayPathsCoveredCheck::handleSwitchWithoutDefault(
}
if (const auto *BitfieldDecl =
Result.Nodes.getNodeAs<FieldDecl>("bitfield")) {
- return twoPow(BitfieldDecl->getBitWidthValue(*Result.Context));
+ return twoPow(BitfieldDecl->getBitWidthValue());
}
return static_cast<std::size_t>(0);
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 298fa79e3fd0ba..5e136d0e76ece7 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -1018,7 +1018,7 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Record);
HI.Offset = Layout.getFieldOffset(FD->getFieldIndex());
if (FD->isBitField())
- HI.Size = FD->getBitWidthValue(Ctx);
+ HI.Size = FD->getBitWidthValue();
else if (auto Size = Ctx.getTypeSizeInCharsIfKnown(FD->getType()))
HI.Size = FD->isZeroSize(Ctx) ? 0 : Size->getQuantity() * 8;
if (HI.Size) {
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 8c39ef3d5a9fa6..4ec0781377c5af 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3143,7 +3143,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// Computes the bit width of this field, if this is a bit field.
/// May not be called on non-bitfields.
- unsigned getBitWidthValue(const ASTContext &Ctx) const;
+ unsigned getBitWidthValue() const;
/// Set the bit-field width for this member.
// Note: used by some clients (i.e., do not remove it).
@@ -3174,7 +3174,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// Is this a zero-length bit-field? Such bit-fields aren't really bit-fields
/// at all and instead act as a separator between contiguous runs of other
/// bit-fields.
- bool isZeroLengthBitField(const ASTContext &Ctx) const;
+ bool isZeroLengthBitField() const;
/// Determine if this field is a subobject of zero size, that is, either a
/// zero-length bit-field or a field of empty class type with the
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 4bcaa953a61af2..4452e4406a70e3 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -708,8 +708,7 @@ AST_MATCHER(FieldDecl, isBitField) {
/// fieldDecl(hasBitWidth(2))
/// matches 'int a;' and 'int c;' but not 'int b;'.
AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
- return Node.isBitField() &&
- Node.getBitWidthValue(Finder->getASTContext()) == Width;
+ return Node.isBitField() && Node.getBitWidthValue() == Width;
}
/// Matches non-static data members that have an in-class initializer.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 80e8c5b9df58e7..ee9d4e4d716ce6 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2774,7 +2774,7 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context,
if (Field->isUnnamedBitField())
return 0;
- int64_t BitfieldSize = Field->getBitWidthValue(Context);
+ int64_t BitfieldSize = Field->getBitWidthValue();
if (IsBitIntType) {
if ((unsigned)BitfieldSize >
cast<BitIntType>(Field->getType())->getNumBits())
@@ -7745,7 +7745,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
QualType FT = Field->getType();
- uint64_t BitWidth = Field->getBitWidthValue(*this);
+ uint64_t BitWidth = Field->getBitWidthValue();
uint64_t IntSize = getTypeSize(IntTy);
// C++ [conv.prom]p5:
// A prvalue for an integral bit-field can be converted to a prvalue of type
@@ -8773,7 +8773,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
S += getObjCEncodingForPrimitiveType(Ctx, BT);
}
}
- S += llvm::utostr(FD->getBitWidthValue(*Ctx));
+ S += llvm::utostr(FD->getBitWidthValue());
}
// Helper function for determining whether the encoded type string would include
@@ -9199,7 +9199,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
}
for (FieldDecl *Field : RDecl->fields()) {
- if (!Field->isZeroLengthBitField(*this) && Field->isZeroSize(*this))
+ if (!Field->isZeroLengthBitField() && Field->isZeroSize(*this))
continue;
uint64_t offs = layout.getFieldOffset(Field->getFieldIndex());
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
@@ -9296,7 +9296,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
if (field->isBitField()) {
EncodeBitField(this, S, field->getType(), field);
#ifndef NDEBUG
- CurOffs += field->getBitWidthValue(*this);
+ CurOffs += field->getBitWidthValue();
#endif
} else {
QualType qt = field->getType();
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 47dcfca79f7356..782b6f2e13d52c 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1489,8 +1489,7 @@ bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
return false;
const Pointer &Field = This.atField(FieldOffset);
const auto &Value = S.Stk.pop<T>();
- Field.deref<T>() =
- Value.truncate(F->Decl->getBitWidthValue(S.getASTContext()));
+ Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
Field.initialize();
return true;
}
@@ -1513,8 +1512,7 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
- Field.deref<T>() =
- Value.truncate(F->Decl->getBitWidthValue(S.getASTContext()));
+ Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
Field.activate();
Field.initialize();
return true;
@@ -1821,7 +1819,7 @@ bool StoreBitField(InterpState &S, CodePtr OpPC) {
if (Ptr.canBeInitialized())
Ptr.initialize();
if (const auto *FD = Ptr.getField())
- Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getASTContext()));
+ Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
else
Ptr.deref<T>() = Value;
return true;
@@ -1836,7 +1834,7 @@ bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
if (Ptr.canBeInitialized())
Ptr.initialize();
if (const auto *FD = Ptr.getField())
- Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getASTContext()));
+ Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
else
Ptr.deref<T>() = Value;
return true;
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index b1230f92ddf1d4..77c87a13d0a7f2 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -333,7 +333,7 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
} else {
if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
- BitWidth = FD->getBitWidthValue(ASTCtx);
+ BitWidth = FD->getBitWidthValue();
else if (T == PT_Bool && PackedBools)
BitWidth = 1;
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 741e908cf9bc56..597fc9a163aa5e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4599,18 +4599,21 @@ void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) {
Init = NewInit;
}
-unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
+unsigned FieldDecl::getBitWidthValue() const {
assert(isBitField() && "not a bitfield");
- return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
+ return cast<ConstantExpr>(getBitWidth())
+ ->getAPValueResult()
+ .getInt()
+ .getZExtValue();
}
-bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
+bool FieldDecl::isZeroLengthBitField() const {
return isUnnamedBitField() && !getBitWidth()->isValueDependent() &&
- getBitWidthValue(Ctx) == 0;
+ getBitWidthValue() == 0;
}
bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
- if (isZeroLengthBitField(Ctx))
+ if (isZeroLengthBitField())
return true;
// C++2a [intro.object]p7:
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 25560faae8672b..7d8bf509f03e20 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -993,7 +993,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++ [meta.unary.prop]p4: [LWG2358]
// T is a class type [...] with [...] no unnamed bit-fields of non-zero
// length
- if (data().Empty && !Field->isZeroLengthBitField(Context) &&
+ if (data().Empty && !Field->isZeroLengthBitField() &&
Context.getLangOpts().getClangABICompat() >
LangOptions::ClangABI::Ver6)
data().Empty = false;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a4fb4d5a1f2ec4..3af62ff7c4440e 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -196,8 +196,7 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const {
if (const FieldDecl *FD = E->getSourceBitField())
if (!Semantic && FD->getType()->isUnsignedIntegerType() &&
- !FD->getBitWidth()->isValueDependent() &&
- FD->getBitWidthValue(FD->getASTContext()) == 1)
+ !FD->getBitWidth()->isValueDependent() && FD->getBitWidthValue() == 1)
return true;
return false;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index c6d003073966f3..707ba0e08a4228 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2875,7 +2875,7 @@ static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E,
APSInt &Int = Value.getInt();
unsigned OldBitWidth = Int.getBitWidth();
- unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx);
+ unsigned NewBitWidth = FD->getBitWidthValue();
if (NewBitWidth < OldBitWidth)
Int = Int.trunc(NewBitWidth).extend(OldBitWidth);
return true;
diff --git a/clang/lib/AST/Randstruct.cpp b/clang/lib/AST/Randstruct.cpp
index b484afa4997bbc..4537ba5309e0bc 100644
--- a/clang/lib/AST/Randstruct.cpp
+++ b/clang/lib/AST/Randstruct.cpp
@@ -91,7 +91,7 @@ void randomizeStructureLayoutImpl(const ASTContext &Context,
auto FieldIter = FieldsOut.begin();
FieldDecl *FD = *FieldIter;
- if (FD->isBitField() && !FD->isZeroLengthBitField(Context)) {
+ if (FD->isBitField() && !FD->isZeroLengthBitField()) {
// Start a bitfield run if this is the first bitfield we have found.
if (!CurrentBitfieldRun)
CurrentBitfieldRun = std::make_unique<BitfieldRunBucket>();
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index b1b13b66a5e504..1c4edf06908e3b 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1542,7 +1542,7 @@ static bool isAIXLayout(const ASTContext &Context) {
void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
- uint64_t FieldSize = D->getBitWidthValue(Context);
+ uint64_t FieldSize = D->getBitWidthValue();
TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
uint64_t StorageUnitSize = FieldInfo.Width;
unsigned FieldAlign = FieldInfo.Align;
@@ -3022,7 +3022,7 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
}
void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
- unsigned Width = FD->getBitWidthValue(Context);
+ unsigned Width = FD->getBitWidthValue();
if (Width == 0) {
layoutZeroWidthBitField(FD);
return;
@@ -3692,7 +3692,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
if (Field.isBitField()) {
uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
- unsigned Width = Field.getBitWidthValue(C);
+ unsigned Width = Field.getBitWidthValue();
PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel);
} else {
PrintOffset(OS, FieldOffset, IndentLevel);
diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp
index edd7146dc1ac76..6954314e6aebba 100644
--- a/clang/lib/CodeGen/ABIInfo.cpp
+++ b/clang/lib/CodeGen/ABIInfo.cpp
@@ -106,7 +106,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
continue;
if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
- FD->isZeroLengthBitField(getContext()))
+ FD->isZeroLengthBitField())
continue;
uint64_t FldMembers;
diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp
index 79300df15d0e29..795874059bda71 100644
--- a/clang/lib/CodeGen/ABIInfoImpl.cpp
+++ b/clang/lib/CodeGen/ABIInfoImpl.cpp
@@ -303,7 +303,7 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,
const FieldDecl *FD) {
- if (FD->isZeroLengthBitField(Context))
+ if (FD->isZeroLengthBitField())
return true;
if (FD->isUnnamedBitField())
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 35d495d4dfab82..b90cd792b38ebe 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -954,7 +954,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
CharUnits UnionSize = CharUnits::Zero();
for (const auto *FD : RD->fields()) {
- if (FD->isZeroLengthBitField(Context))
+ if (FD->isZeroLengthBitField())
continue;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
@@ -974,7 +974,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
}
for (const auto *FD : RD->fields()) {
- if (FD->isZeroLengthBitField(Context))
+ if (FD->isZeroLengthBitField())
continue;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
@@ -3698,7 +3698,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset,
for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) {
const FieldDecl *F = *I;
- if (F->isUnnamedBitField() || F->isZeroLengthBitField(Context) ||
+ if (F->isUnnamedBitField() || F->isZeroLengthBitField() ||
F->getType()->isIncompleteArrayType())
continue;
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index c45688bd1ed3ce..8c190732c8cdcf 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -945,7 +945,7 @@ namespace {
ASTContext &Ctx = CGF.getContext();
unsigned LastFieldSize =
LastField->isBitField()
- ? LastField->getBitWidthValue(Ctx)
+ ? LastField->getBitWidthValue()
: Ctx.toBits(
Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width);
uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 60f32f76109e9a..84cc6a4b5f1388 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1721,8 +1721,7 @@ llvm::DIDerivedType *CGDebugInfo::createBitFieldSeparatorIfNeeded(
assert(PreviousBitfield->isBitField());
- ASTContext &Context = CGM.getContext();
- if (!PreviousBitfield->isZeroLengthBitField(Context))
+ if (!PreviousBitfield->isZeroLengthBitField())
return nullptr;
QualType Ty = PreviousBitfield->getType();
@@ -3231,9 +3230,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
if (!FType->isIncompleteArrayType()) {
// Bit size, align and offset of the type.
- FieldSize = Field->isBitField()
- ? Field->getBitWidthValue(CGM.getContext())
- : CGM.getContext().getTypeSize(FType);
+ FieldSize = Field->isBitField() ? Field->getBitWidthValue()
+ : CGM.getContext().getTypeSize(FType);
FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
}
diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
index 6a02e4dbf84d14..d90c44d770d14b 100644
--- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -25,7 +25,7 @@ using namespace CodeGen;
static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
ASTContext &Ctx) {
if (FD && FD->isBitField())
- return FD->getBitWidthValue(Ctx);
+ return FD->getBitWidthValue();
return Ctx.getTypeSize(FT);
}
@@ -255,7 +255,7 @@ struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
CharUnits CurStructOffset) {
// Zero-length bit-fields don't need to be copied/assigned.
- if (FD && FD->isZeroLengthBitField(this->Ctx))
+ if (FD && FD->isZeroLengthBitField())
return;
// Because volatile fields can be bit-fields and are individually copied,
@@ -544,7 +544,7 @@ struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
LValue DstLV, SrcLV;
if (FD) {
// No need to copy zero-length bit-fields.
- if (FD->isZeroLengthBitField(this->CGF->getContext()))
+ if (FD->isZeroLengthBitField())
return;
QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 7b85dcc2c7984f..dd900f9b32fb78 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -2543,8 +2543,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
if (LastFieldBitfieldOrUnnamed) {
if (LastFieldBitfieldOrUnnamed->isBitField()) {
// Last field was a bitfield. Must update the info.
- uint64_t BitFieldSize
- = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
+ uint64_t BitFieldSize = LastFieldBitfieldOrUnnamed->getBitWidthValue();
unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
((BitFieldSize % ByteSizeInBits) != 0);
CharUnits Size = CharUnits::fromQuantity(UnsSize);
diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp
index 01d0f35da19643..b438a92a4fd627 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -89,7 +89,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar);
uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth();
uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign();
- uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext());
+ uint64_t BitFieldSize = Ivar->getBitWidthValue();
CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits(
llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits));
CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits);
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index ea44e6f21f3c86..4afcd9d6d32ccc 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -148,8 +148,8 @@ struct CGRecordLowering {
llvm::Type *Type = Types.ConvertTypeForMem(FD->getType());
if (!FD->isBitField()) return Type;
if (isDiscreteBitFieldABI()) return Type;
- return getIntNType(std::min(FD->getBitWidthValue(Context),
- (unsigned)Context.toBits(getSize(Type))));
+ return getIntNType(std::min(FD->getBitWidthValue(),
+ (unsigned)Context.toBits(getSize(Type))));
}
/// Gets the llvm Basesubobject type from a CXXRecordDecl.
llvm::Type *getStorageType(const CXXRecordDecl *RD) const {
@@ -242,7 +242,7 @@ void CGRecordLowering::setBitFieldInfo(
CGBitFieldInfo &Info = BitFields[FD->getCanonicalDecl()];
Info.IsSigned = FD->getType()->isSignedIntegerOrEnumerationType();
Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset));
- Info.Size = FD->getBitWidthValue(Context);
+ Info.Size = FD->getBitWidthValue();
Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
Info.StorageOffset = StartOffset;
if (Info.Size > Info.StorageSize)
@@ -322,7 +322,7 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) {
// been doing and cause lit tests to change.
for (const auto *Field : D->fields()) {
if (Field->isBitField()) {
- if (Field->isZeroLengthBitField(Context))
+ if (Field->isZeroLengthBitField())
continue;
llvm::Type *FieldType = getStorageType(Field);
if (LayoutSize < getSize(FieldType))
@@ -423,7 +423,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
uint64_t StartBitOffset, Tail = 0;
for (; Field != FieldEnd && Field->isBitField(); ++Field) {
// Zero-width bitfields end runs.
- if (Field->isZeroLengthBitField(Context)) {
+ if (Field->isZeroLengthBitField()) {
Run = FieldEnd;
continue;
}
@@ -559,7 +559,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// Bitfield potentially begins a new span. This includes zero-length
// bitfields on non-aligning targets that lie at character boundaries
// (those are barriers to merging).
- if (Field->isZeroLengthBitField(Context))
+ if (Field->isZeroLengthBitField())
Barrier = true;
AtAlignedBoundary = true;
}
@@ -697,7 +697,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
}
Members.push_back(StorageInfo(BeginOffset, Type));
for (; Begin != BestEnd; ++Begin)
- if (!Begin->isZeroLengthBitField(Context))
+ if (!Begin->isZeroLengthBitField())
Members.push_back(
MemberInfo(BeginOffset, MemberInfo::Field, nullptr, *Begin));
}
@@ -709,7 +709,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
"Accumulating past end of bitfields");
assert(!Barrier && "Accumulating across barrier");
// Accumulate this bitfield into the current (potential) span.
- BitSizeSinceBegin += Field->getBitWidthValue(Context);
+ BitSizeSinceBegin += Field->getBitWidthValue();
++Field;
}
}
@@ -813,7 +813,7 @@ void CGRecordLowering::computeVolatileBitfields() {
bool Conflict = false;
for (const auto *F : D->fields()) {
// Allow sized bit-fields overlaps.
- if (F->isBitField() && !F->isZeroLengthBitField(Context))
+ if (F->isBitField() && !F->isZeroLengthBitField())
continue;
const CharUnits FOffset = Context.toCharUnitsFromBits(
@@ -823,7 +823,7 @@ void CGRecordLowering::computeVolatileBitfields() {
// fields after and before it should be race condition free.
// The AAPCS acknowledges it and imposes no restritions when the
// natural container overlaps a zero-length bit-field.
- if (F->isZeroLengthBitField(Context)) {
+ if (F->isZeroLengthBitField()) {
if (End > FOffset && StorageOffset < FOffset) {
Conflict = true;
break;
diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp
index 0873896df213e8..1ff4ece2811ec0 100644
--- a/clang/lib/CodeGen/SwiftCallingConv.cpp
+++ b/clang/lib/CodeGen/SwiftCallingConv.cpp
@@ -186,7 +186,7 @@ void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield,
uint64_t bitfieldBitBegin) {
assert(bitfield->isBitField());
auto &ctx = CGM.getContext();
- auto width = bitfield->getBitWidthValue(ctx);
+ auto width = bitfield->getBitWidthValue();
// We can ignore zero-width bit-fields.
if (width == 0) return;
diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp
index 6af9375461f095..6c90e48a5ea417 100644
--- a/clang/lib/CodeGen/Targets/LoongArch.cpp
+++ b/clang/lib/CodeGen/Targets/LoongArch.cpp
@@ -192,7 +192,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper(
for (const FieldDecl *FD : RD->fields()) {
QualType QTy = FD->getType();
if (FD->isBitField()) {
- unsigned BitWidth = FD->getBitWidthValue(getContext());
+ unsigned BitWidth = FD->getBitWidthValue();
// Zero-width bitfields are ignored.
if (BitWidth == 0)
continue;
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index b04e436c665f52..67bd7c120d02f3 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -246,7 +246,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex());
QualType QTy = FD->getType();
if (FD->isBitField()) {
- unsigned BitWidth = FD->getBitWidthValue(getContext());
+ unsigned BitWidth = FD->getBitWidthValue();
// Allow a bitfield with a type greater than XLen as long as the
// bitwidth is XLen or less.
if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 7f73bf2a65266e..5ee5179dd0f3e8 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2130,7 +2130,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
if (BitField) {
assert(!i->isUnnamedBitField());
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
- uint64_t Size = i->getBitWidthValue(getContext());
+ uint64_t Size = i->getBitWidthValue();
uint64_t EB_Lo = Offset / 64;
uint64_t EB_Hi = (Offset + Size - 1) / 64;
diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp
index f3e241171b8729..ced4981fd124f6 100644
--- a/clang/lib/CodeGen/Targets/XCore.cpp
+++ b/clang/lib/CodeGen/Targets/XCore.cpp
@@ -343,7 +343,7 @@ static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE,
if (Field->isBitField()) {
Enc += "b(";
llvm::raw_svector_ostream OS(Enc);
- OS << Field->getBitWidthValue(CGM.getContext());
+ OS << Field->getBitWidthValue();
Enc += ':';
}
if (!appendType(Enc, Field->getType(), CGM, TSC))
diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 8cdb463e2c99f2..fc65559e9d4a51 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -3699,7 +3699,8 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
Type.getAsStringInternal(Name, Context->getPrintingPolicy());
Result += Name;
if (fieldDecl->isBitField()) {
- Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context));
+ Result += " : ";
+ Result += utostr(fieldDecl->getBitWidthValue());
}
else if (EleboratedType && Type->isArrayType()) {
const ArrayType *AT = Context->getAsArrayType(Type);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a49605e4867651..c9530a86ac89d3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -657,7 +657,7 @@ struct BuiltinDumpStructGenerator {
Format += ": %zu ";
QualType SizeT = S.Context.getSizeType();
llvm::APInt BitWidth(S.Context.getIntWidth(SizeT),
- FD->getBitWidthValue(S.Context));
+ FD->getBitWidthValue());
Args.push_back(IntegerLiteral::Create(S.Context, BitWidth, SizeT, Loc));
}
@@ -9970,7 +9970,7 @@ static std::optional<IntRange> TryGetExprRange(ASTContext &C, const Expr *E,
Approximate);
if (const auto *BitField = E->getSourceBitField())
- return IntRange(BitField->getBitWidthValue(C),
+ return IntRange(BitField->getBitWidthValue(),
BitField->getType()->isUnsignedIntegerOrEnumerationType());
if (GetExprType(E)->isVoidType())
@@ -10523,7 +10523,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
return false;
Expr *OriginalInit = Init->IgnoreParenImpCasts();
- unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
+ unsigned FieldWidth = Bitfield->getBitWidthValue();
Expr::EvalResult Result;
if (!OriginalInit->EvaluateAsInt(Result, S.Context,
@@ -13987,8 +13987,8 @@ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1,
if (Field1->isBitField()) {
// Make sure that the bit-fields are the same length.
- unsigned Bits1 = Field1->getBitWidthValue(C);
- unsigned Bits2 = Field2->getBitWidthValue(C);
+ unsigned Bits1 = Field1->getBitWidthValue();
+ unsigned Bits2 = Field2->getBitWidthValue();
if (Bits1 != Bits2)
return false;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 74b0e5ad23bd48..30d16639d1f934 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18349,7 +18349,9 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
}
}
- return BitWidth;
+ if (isa<ConstantExpr>(BitWidth))
+ return BitWidth;
+ return ConstantExpr::Create(getASTContext(), BitWidth, APValue{Value});
}
Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
@@ -18724,7 +18726,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
- if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context))
+ if (!Ivar->isBitField() || Ivar->isZeroLengthBitField())
return;
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext);
if (!ID) {
@@ -18739,14 +18741,13 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
// All conditions are met. Add a new bitfield to the tail end of ivars.
llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0);
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
+ Expr *BitWidth =
+ ConstantExpr::Create(Context, BW, APValue(llvm::APSInt(Zero)));
- Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext),
- DeclLoc, DeclLoc, nullptr,
- Context.CharTy,
- Context.getTrivialTypeSourceInfo(Context.CharTy,
- DeclLoc),
- ObjCIvarDecl::Private, BW,
- true);
+ Ivar = ObjCIvarDecl::Create(
+ Context, cast<ObjCContainerDecl>(CurContext), DeclLoc, DeclLoc, nullptr,
+ Context.CharTy, Context.getTrivialTypeSourceInfo(Context.CharTy, DeclLoc),
+ ObjCIvarDecl::Private, BitWidth, true);
AllIvarDecls.push_back(Ivar);
}
@@ -19376,7 +19377,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
(NonBitFields == 0 || ZeroSize) && I != E; ++I) {
IsEmpty = false;
if (I->isUnnamedBitField()) {
- if (!I->isZeroLengthBitField(Context))
+ if (!I->isZeroLengthBitField())
ZeroSize = false;
} else {
++NonBitFields;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 26041e53de5061..4a81074664a3a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4873,7 +4873,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ParamType = Param->getType().getNonReferenceType();
// Suppress copying zero-width bitfields.
- if (Field->isZeroLengthBitField(SemaRef.Context))
+ if (Field->isZeroLengthBitField())
return false;
Expr *MemberExprBase =
@@ -15030,7 +15030,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isZeroLengthBitField(Context))
+ if (Field->isZeroLengthBitField())
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -15417,7 +15417,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isZeroLengthBitField(Context))
+ if (Field->isZeroLengthBitField())
continue;
QualType FieldType = Field->getType().getNonReferenceType();
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index ad1a02cf098b1e..fedc0c36891799 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -2210,8 +2210,7 @@ void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
<< ImplIvar->getType() << ClsIvar->getType();
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
} else if (ImplIvar->isBitField() && ClsIvar->isBitField() &&
- ImplIvar->getBitWidthValue(Context) !=
- ClsIvar->getBitWidthValue(Context)) {
+ ImplIvar->getBitWidthValue() != ClsIvar->getBitWidthValue()) {
Diag(ImplIvar->getBitWidth()->getBeginLoc(),
diag::err_conflicting_ivar_bitwidth)
<< ImplIvar->getIdentifier();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index e4bf9aa521224b..b81820d26a570c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -516,7 +516,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
if (const FieldDecl *BitField = Initializer->getSourceBitField()) {
if (BitField->getBitWidth()->isValueDependent())
DependentBitField = true;
- else if (unsigned BitFieldWidth = BitField->getBitWidthValue(Ctx);
+ else if (unsigned BitFieldWidth = BitField->getBitWidthValue();
BitFieldWidth < FromWidth) {
if (CanRepresentAll(FromSigned, BitFieldWidth, ToSigned, ToWidth))
return NK_Not_Narrowing;
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 46e294a1741cfe..9553e6221ed331 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -929,7 +929,7 @@ collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth();
} else if (const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
if (FR->getDecl()->isBitField())
- Length = FR->getDecl()->getBitWidthValue(SVB.getContext());
+ Length = FR->getDecl()->getBitWidthValue();
}
for (const auto &StoreEntry : Cluster) {
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index b4df12405cf356..990daadd322dc3 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -381,7 +381,7 @@ int clang_getFieldDeclBitWidth(CXCursor C) {
if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
if (FD->isBitField() && !FD->getBitWidth()->isValueDependent())
- return FD->getBitWidthValue(getCursorContext(C));
+ return FD->getBitWidthValue();
}
}
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index bf7313f882e455..236e4b3770fb2f 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -3402,12 +3402,12 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) {
FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("x")));
ASSERT_TRUE(FromF->isBitField());
- ASSERT_EQ(3u, FromF->getBitWidthValue(FromTU->getASTContext()));
+ ASSERT_EQ(3u, FromF->getBitWidthValue());
auto *ToField = Import(FromF, Lang_CXX03);
auto *ToTU = ToField->getTranslationUnitDecl();
EXPECT_TRUE(ToField->isBitField());
- EXPECT_EQ(3u, ToField->getBitWidthValue(ToTU->getASTContext()));
+ EXPECT_EQ(3u, ToField->getBitWidthValue());
const auto *FromBT = FromF->getBitWidth()->getType()->getAs<BuiltinType>();
const auto *ToBT = ToField->getBitWidth()->getType()->getAs<BuiltinType>();
>From 5516ef958946322ee15ec2933603fae149ca0fdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Wed, 27 Nov 2024 12:50:08 +0100
Subject: [PATCH 2/2] Save BitWidth as ConstantExpr
---
clang/include/clang/AST/Decl.h | 22 ++++++++++++++--------
clang/include/clang/AST/DeclObjC.h | 11 ++++++-----
clang/lib/AST/Decl.cpp | 9 +++------
clang/lib/AST/DeclObjC.cpp | 11 ++++++-----
clang/lib/Sema/SemaDecl.cpp | 7 +++++--
clang/lib/Sema/SemaDeclObjC.cpp | 6 +++++-
clang/lib/Sema/SemaObjCProperty.cpp | 9 ++++-----
clang/lib/Serialization/ASTReaderDecl.cpp | 2 +-
8 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 4ec0781377c5af..424213ebe3aad8 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -58,6 +58,7 @@ class CompoundStmt;
class DependentFunctionTemplateSpecializationInfo;
class EnumDecl;
class Expr;
+class ConstantExpr; // : Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class FunctionTypeLoc;
@@ -3030,6 +3031,11 @@ class FunctionDecl : public DeclaratorDecl,
}
};
+// class ConstantExpr : public Expr;
+// class ConstantExpr final
+// : public FullExpr,
+// private llvm::TrailingObjects<ConstantExpr, APValue, uint64_t>;
+
/// Represents a member of a struct/union/class.
class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// The kinds of value we can store in StorageKind.
@@ -3067,7 +3073,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// structure is used to represent the two expressions.
struct InitAndBitWidthStorage {
LazyDeclStmtPtr Init;
- Expr *BitWidth;
+ ConstantExpr *BitWidth;
};
/// Storage for either the bit-width, the in-class initializer, or
@@ -3083,7 +3089,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
// Active member if ISK is not ISK_CapturedVLAType and BitField is false.
LazyDeclStmtPtr Init;
// Active member if ISK is ISK_NoInit and BitField is true.
- Expr *BitWidth;
+ ConstantExpr *BitWidth;
// Active member if ISK is ISK_InClass*Init and BitField is true.
InitAndBitWidthStorage *InitAndBitWidth;
// Active member if ISK is ISK_CapturedVLAType.
@@ -3093,7 +3099,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+ TypeSourceInfo *TInfo, ConstantExpr *BW, bool Mutable,
InClassInitStyle InitStyle)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), BitField(false),
Mutable(Mutable), StorageKind((InitStorageKind)InitStyle),
@@ -3109,8 +3115,8 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
- InClassInitStyle InitStyle);
+ TypeSourceInfo *TInfo, ConstantExpr *BW,
+ bool Mutable, InClassInitStyle InitStyle);
static FieldDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
@@ -3135,7 +3141,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// Returns the expression that represents the bit width, if this field
/// is a bit field. For non-bitfields, this returns \c nullptr.
- Expr *getBitWidth() const {
+ ConstantExpr *getBitWidth() const {
if (!BitField)
return nullptr;
return hasInClassInitializer() ? InitAndBitWidth->BitWidth : BitWidth;
@@ -3147,7 +3153,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// Set the bit-field width for this member.
// Note: used by some clients (i.e., do not remove it).
- void setBitWidth(Expr *Width) {
+ void setBitWidth(ConstantExpr *Width) {
assert(!hasCapturedVLAType() && !BitField &&
"bit width or captured type already set");
assert(Width && "no bit width specified");
@@ -3224,7 +3230,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
StorageKind = ISK_NoInit;
if (BitField) {
// Read the bit width before we change the active union member.
- Expr *ExistingBitWidth = InitAndBitWidth->BitWidth;
+ ConstantExpr *ExistingBitWidth = InitAndBitWidth->BitWidth;
BitWidth = ExistingBitWidth;
}
}
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 4663603f797545..dcda9915c0a98b 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -1959,7 +1959,7 @@ class ObjCIvarDecl : public FieldDecl {
private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
+ TypeSourceInfo *TInfo, AccessControl ac, ConstantExpr *BW,
bool synthesized)
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
/*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
@@ -1970,7 +1970,8 @@ class ObjCIvarDecl : public FieldDecl {
SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, AccessControl ac,
- Expr *BW = nullptr, bool synthesized = false);
+ ConstantExpr *BW = nullptr,
+ bool synthesized = false);
static ObjCIvarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
@@ -2028,8 +2029,8 @@ class ObjCIvarDecl : public FieldDecl {
/// Represents a field declaration created by an \@defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- QualType T, Expr *BW)
+ SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
+ ConstantExpr *BW)
: FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
/*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
@@ -2040,7 +2041,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl {
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
- QualType T, Expr *BW);
+ QualType T, ConstantExpr *BW);
static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 597fc9a163aa5e..885cf94b7fab60 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4555,8 +4555,8 @@ unsigned FunctionDecl::getODRHash() {
FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
- InClassInitStyle InitStyle) {
+ TypeSourceInfo *TInfo, ConstantExpr *BW,
+ bool Mutable, InClassInitStyle InitStyle) {
return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
BW, Mutable, InitStyle);
}
@@ -4601,10 +4601,7 @@ void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) {
unsigned FieldDecl::getBitWidthValue() const {
assert(isBitField() && "not a bitfield");
- return cast<ConstantExpr>(getBitWidth())
- ->getAPValueResult()
- .getInt()
- .getZExtValue();
+ return getBitWidth()->getAPValueResult().getInt().getZExtValue();
}
bool FieldDecl::isZeroLengthBitField() const {
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index 5c107325df30c6..40c0f3760bf50d 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -1833,7 +1833,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, AccessControl ac,
- Expr *BW, bool synthesized) {
+ ConstantExpr *BW, bool synthesized) {
if (DC) {
// Ivar's can only appear in interfaces, implementations (via synthesized
// properties), and class extensions (via direct declaration, or synthesized
@@ -1905,10 +1905,11 @@ QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
void ObjCAtDefsFieldDecl::anchor() {}
-ObjCAtDefsFieldDecl
-*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, QualType T, Expr *BW) {
+ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id, QualType T,
+ ConstantExpr *BW) {
return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW);
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 30d16639d1f934..764658591241a4 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18547,12 +18547,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (InvalidDecl)
BitWidth = nullptr;
// If this is declared as a bit-field, check the bit-field.
+ ConstantExpr *ConstantBW = nullptr;
if (BitWidth) {
BitWidth =
VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth).get();
if (!BitWidth) {
InvalidDecl = true;
BitWidth = nullptr;
+ } else if (!BitWidth->isValueDependent() && !BitWidth->isTypeDependent()) {
+ ConstantBW = cast<ConstantExpr>(BitWidth);
}
}
@@ -18584,7 +18587,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Record), Loc);
FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
- BitWidth, Mutable, InitStyle);
+ ConstantBW, Mutable, InitStyle);
if (InvalidDecl)
NewFD->setInvalidDecl();
@@ -18741,7 +18744,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
// All conditions are met. Add a new bitfield to the tail end of ivars.
llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0);
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
- Expr *BitWidth =
+ ConstantExpr *BitWidth =
ConstantExpr::Create(Context, BW, APValue(llvm::APSInt(Zero)));
Ivar = ObjCIvarDecl::Create(
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index fedc0c36891799..ed715509a9a3ae 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -5577,6 +5577,7 @@ Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D,
TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
QualType T = TInfo->getType();
+ ConstantExpr *ConstantBW = nullptr;
if (BitWidth) {
// 6.7.2.1p3, 6.7.2.1p4
BitWidth =
@@ -5584,6 +5585,9 @@ Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D,
.get();
if (!BitWidth)
D.setInvalidType();
+ else
+ ConstantBW = cast<ConstantExpr>(BitWidth);
+
} else {
// Not a bitfield.
@@ -5633,7 +5637,7 @@ Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D,
// Construct the decl.
ObjCIvarDecl *NewID =
ObjCIvarDecl::Create(getASTContext(), EnclosingContext, DeclStart, Loc,
- II, T, TInfo, ac, BitWidth);
+ II, T, TInfo, ac, ConstantBW);
if (T->containsErrors())
NewID->setInvalidDecl();
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index 93a17e84598115..731e56b34f4102 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1295,11 +1295,10 @@ Decl *SemaObjC::ActOnPropertyImplDecl(
}
}
- Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
- PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
- PropertyIvarType, /*TInfo=*/nullptr,
- ObjCIvarDecl::Private,
- (Expr *)nullptr, true);
+ Ivar = ObjCIvarDecl::Create(
+ Context, ClassImpDecl, PropertyIvarLoc, PropertyIvarLoc, PropertyIvar,
+ PropertyIvarType, /*TInfo=*/nullptr, ObjCIvarDecl::Private,
+ (ConstantExpr *)nullptr, true);
if (SemaRef.RequireNonAbstractType(PropertyIvarLoc, PropertyIvarType,
diag::err_abstract_type_in_decl,
Sema::AbstractSynthesizedIvarType)) {
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 6ece3ba7af9f4b..75707cf29f76a6 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1545,7 +1545,7 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
FD->CapturedVLAType =
cast<VariableArrayType>(Record.readType().getTypePtr());
else if (Bits & 1)
- FD->setBitWidth(Record.readExpr());
+ FD->setBitWidth(cast<ConstantExpr>(Record.readExpr()));
if (!FD->getDeclName() ||
FD->isPlaceholderVar(Reader.getContext().getLangOpts())) {
More information about the cfe-commits
mailing list