Skip to content

[clang] Avoid re-evaluating field bitwidth #117732

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/Hover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3142,7 +3142,9 @@ 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;
/// Note that in order to successfully use this function, the bitwidth
/// expression must be a ConstantExpr with a valid integer result set.
unsigned getBitWidthValue() const;

/// Set the bit-field width for this member.
// Note: used by some clients (i.e., do not remove it).
Expand Down Expand Up @@ -3173,7 +3175,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
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2795,7 +2795,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())
Expand Down Expand Up @@ -7769,7 +7769,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
Expand Down Expand Up @@ -8797,7 +8797,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
Expand Down Expand Up @@ -9223,7 +9223,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),
Expand Down Expand Up @@ -9320,7 +9320,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();
Expand Down
10 changes: 4 additions & 6 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1471,8 +1471,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;
}
Expand All @@ -1495,8 +1494,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;
Expand Down Expand Up @@ -1750,7 +1748,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;
Expand All @@ -1765,7 +1763,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;
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx,
Bits BitWidth = FullBitWidth;

if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
BitWidth = Bits(std::min(FD->getBitWidthValue(),
(unsigned)FullBitWidth.getQuantity()));
else if (T == PT_Bool && PackedBools)
BitWidth = Bits(1);
Expand Down Expand Up @@ -301,8 +301,8 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx,
assert(NumBits.isFullByte());
assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
F.bitcastToMemory(Buff.get());
// Now, only (maybe) swap the actual size of the float, excluding the
// padding bits.
// Now, only (maybe) swap the actual size of the float, excluding
// the padding bits.
if (llvm::sys::IsBigEndianHost)
swapBytes(Buff.get(), NumBits.roundToBytes());

Expand Down Expand Up @@ -406,7 +406,7 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,

Bits BitWidth;
if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
BitWidth = Bits(std::min(FD->getBitWidthValue(),
(unsigned)FullBitWidth.getQuantity()));
else if (T == PT_Bool && PackedBools)
BitWidth = Bits(1);
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4599,18 +4599,24 @@ 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();
assert(isa<ConstantExpr>(getBitWidth()));
assert(cast<ConstantExpr>(getBitWidth())->hasAPValueResult());
assert(cast<ConstantExpr>(getBitWidth())->getAPValueResult().isInt());
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:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Randstruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/ABIInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
continue;

if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
FD->isZeroLengthBitField(getContext()))
FD->isZeroLengthBitField())
continue;

uint64_t FldMembers;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/ABIInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand All @@ -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.");
Expand Down Expand Up @@ -3682,7 +3682,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;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 -
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -3214,9 +3213,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());
}

Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGNonTrivialStruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/CGObjCMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGObjCRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading
Loading