From: Richard Smith Date: Mon, 2 Apr 2018 18:29:43 +0000 (+0000) Subject: Add helper to determine if a field is a zero-length bitfield. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b75b68b657084d1c1c7b301e82818b993de8e6ce;p=clang Add helper to determine if a field is a zero-length bitfield. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@328999 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index da164c66a6..f9f5cf858d 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2635,6 +2635,11 @@ public: BitField = false; } + /// 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; + /// Get the kind of (C++11) default member initializer that this field has. InClassInitStyle getInClassInitStyle() const { InitStorageKind storageKind = InitStorage.getInt(); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4fb687d0fd..b49fda08a7 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3691,6 +3691,11 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); } +bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const { + return isUnnamedBitfield() && !getBitWidth()->isValueDependent() && + getBitWidthValue(Ctx) == 0; +} + unsigned FieldDecl::getFieldIndex() const { const FieldDecl *Canonical = getCanonicalDecl(); if (Canonical != this) diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 1e1ee439d8..45ecc1b5b1 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1085,10 +1085,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // T is a class type [...] with [...] no non-static data members other // than bit-fields of length 0... if (data().Empty) { - if (!Field->isBitField() || - (!Field->getBitWidth()->isTypeDependent() && - !Field->getBitWidth()->isValueDependent() && - Field->getBitWidthValue(Context) != 0)) + if (!Field->isZeroLengthBitField(Context)) data().Empty = false; } } diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 148a12eac8..d1daf5174d 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -906,8 +906,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { CharUnits UnionSize = CharUnits::Zero(); for (const auto *FD : RD->fields()) { - // Skip zero length bitfields. - if (FD->isBitField() && FD->getBitWidthValue(Context) == 0) + if (FD->isZeroLengthBitField(Context)) continue; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); @@ -928,8 +927,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { } for (const auto *FD : RD->fields()) { - // Skip zero length bitfields. - if (FD->isBitField() && FD->getBitWidthValue(Context) == 0) + if (FD->isZeroLengthBitField(Context)) continue; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 7296da7d7e..497c8aa481 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -294,8 +294,7 @@ void CGRecordLowering::lowerUnion() { // been doing and cause lit tests to change. for (const auto *Field : D->fields()) { if (Field->isBitField()) { - // Skip 0 sized bitfields. - if (Field->getBitWidthValue(Context) == 0) + if (Field->isZeroLengthBitField(Context)) continue; llvm::Type *FieldType = getStorageType(Field); if (LayoutSize < getSize(FieldType)) @@ -380,7 +379,7 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, for (; Field != FieldEnd; ++Field) { uint64_t BitOffset = getFieldBitOffset(*Field); // Zero-width bitfields end runs. - if (Field->getBitWidthValue(Context) == 0) { + if (Field->isZeroLengthBitField(Context)) { Run = FieldEnd; continue; } @@ -431,7 +430,7 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, if (Field == FieldEnd) break; // Any non-zero-length bitfield can start a new run. - if (Field->getBitWidthValue(Context) != 0) { + if (!Field->isZeroLengthBitField(Context)) { Run = Field; StartBitOffset = getFieldBitOffset(*Field); Tail = StartBitOffset + Field->getBitWidthValue(Context); @@ -452,7 +451,7 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, // Otherwise, try to add bitfields to the run. if (!StartFieldAsSingleRun && Field != FieldEnd && !IsBetterAsSingleFieldRun(Field) && - (Field->getBitWidthValue(Context) != 0 || + (!Field->isZeroLengthBitField(Context) || (!Context.getTargetInfo().useZeroLengthBitfieldAlignment() && !Context.getTargetInfo().useBitFieldTypeAlignment())) && Tail == getFieldBitOffset(*Field)) { @@ -811,7 +810,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, continue; // Don't inspect zero-length bitfields. - if (FD->getBitWidthValue(getContext()) == 0) + if (FD->isZeroLengthBitField(getContext())) continue; const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD); diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 02dd21483b..68edb32582 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -4560,7 +4560,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, // For compatibility with GCC, ignore empty bitfields in C++ mode. if (getContext().getLangOpts().CPlusPlus && - FD->isBitField() && FD->getBitWidthValue(getContext()) == 0) + FD->isZeroLengthBitField(getContext())) continue; uint64_t FldMembers; @@ -6406,7 +6406,7 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { // Unlike isSingleElementStruct(), empty structure and array fields // do count. So do anonymous bitfields that aren't zero-sized. if (getContext().getLangOpts().CPlusPlus && - FD->isBitField() && FD->getBitWidthValue(getContext()) == 0) + FD->isZeroLengthBitField(getContext())) continue; // Unlike isSingleElementStruct(), arrays do not count. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8100b955da..295d89a40d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -15206,7 +15206,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast(ivarDecl); - if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) + if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context)) return; ObjCInterfaceDecl *ID = dyn_cast(CurContext); if (!ID) { @@ -15588,7 +15588,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, (NonBitFields == 0 || ZeroSize) && I != E; ++I) { IsEmpty = false; if (I->isUnnamedBitfield()) { - if (I->getBitWidthValue(Context) > 0) + if (!I->isZeroLengthBitField(Context)) ZeroSize = false; } else { ++NonBitFields; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f8a3d9444a..55c7a9ae24 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4335,7 +4335,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. - if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) + if (Field->isZeroLengthBitField(SemaRef.Context)) return false; Expr *MemberExprBase = @@ -11740,7 +11740,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + if (Field->isZeroLengthBitField(Context)) continue; QualType FieldType = Field->getType().getNonReferenceType(); @@ -12107,7 +12107,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + if (Field->isZeroLengthBitField(Context)) continue; QualType FieldType = Field->getType().getNonReferenceType();