@@ -851,78 +851,94 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type,
851
851
// max(sizeof(struct s),
852
852
// offsetof(struct s, array) + p->count * sizeof(*p->array))
853
853
//
854
+ ASTContext &Ctx = getContext();
854
855
const Expr *Base = E->IgnoreParenImpCasts();
855
856
const Expr *Idx = nullptr;
856
857
857
858
if (const auto *UO = dyn_cast<UnaryOperator>(Base);
858
859
UO && UO->getOpcode() == UO_AddrOf) {
859
- if (const auto *ASE =
860
- dyn_cast<ArraySubscriptExpr>(UO->getSubExpr()->IgnoreParens() )) {
861
- Base = ASE->getBase();
860
+ Expr *SubExpr = UO->getSubExpr()->IgnoreParenImpCasts();
861
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(SubExpr )) {
862
+ Base = ASE->getBase()->IgnoreParenImpCasts() ;
862
863
Idx = ASE->getIdx()->IgnoreParenImpCasts();
863
864
864
- if (const auto *IL = dyn_cast<IntegerLiteral>(Idx);
865
- IL && !IL->getValue().getSExtValue())
866
- Idx = nullptr;
865
+ if (const auto *IL = dyn_cast<IntegerLiteral>(Idx)) {
866
+ int64_t Val = IL->getValue().getSExtValue();
867
+ if (Val < 0)
868
+ // __bdos returns 0 for negative indexes into an array in a struct.
869
+ return getDefaultBuiltinObjectSizeResult(Type, ResType);
870
+
871
+ if (Val == 0)
872
+ // The index is 0, so we don't need to take it into account.
873
+ Idx = nullptr;
874
+ }
875
+ } else {
876
+ // Potential pointer to another element in the struct.
877
+ Base = SubExpr;
867
878
}
868
879
}
869
880
881
+ // Get the flexible array member Decl.
882
+ const ValueDecl *FAMDecl = nullptr;
883
+ if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
884
+ // Check if \p Base is referencing the FAM itself.
885
+ if (const ValueDecl *MD = ME->getMemberDecl()) {
886
+ const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
887
+ getLangOpts().getStrictFlexArraysLevel();
888
+ if (!Decl::isFlexibleArrayMemberLike(
889
+ Ctx, MD, MD->getType(), StrictFlexArraysLevel,
890
+ /*IgnoreTemplateOrMacroSubstitution=*/true))
891
+ return nullptr;
892
+
893
+ FAMDecl = MD;
894
+ }
895
+ } else if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
896
+ // Check if we're pointing to the whole struct.
897
+ QualType Ty = DRE->getDecl()->getType();
898
+ if (Ty->isPointerType())
899
+ Ty = Ty->getPointeeType();
900
+
901
+ if (const auto *RD = Ty->getAsRecordDecl())
902
+ // Don't use the outer lexical record because the FAM might be in a
903
+ // different RecordDecl.
904
+ FAMDecl = FindFlexibleArrayMemberField(Ctx, RD);
905
+ }
906
+
907
+ if (!FAMDecl || !FAMDecl->hasAttr<CountedByAttr>())
908
+ // No flexible array member found or it doesn't have the "counted_by"
909
+ // attribute.
910
+ return nullptr;
911
+
870
912
const ValueDecl *CountedByFD = FindCountedByField(Base);
871
913
if (!CountedByFD)
872
914
// Can't find the field referenced by the "counted_by" attribute.
873
915
return nullptr;
874
916
875
917
// Build a load of the counted_by field.
876
918
bool IsSigned = CountedByFD->getType()->isSignedIntegerType();
877
- const RecordDecl *OuterRD =
878
- CountedByFD->getDeclContext()->getOuterLexicalRecordContext();
879
- ASTContext &Ctx = getContext();
880
-
881
- // Load the counted_by field.
882
919
const Expr *CountedByExpr = BuildCountedByFieldExpr(Base, CountedByFD);
883
920
Value *CountedByInst = EmitAnyExprToTemp(CountedByExpr).getScalarVal();
884
921
llvm::Type *CountedByTy = CountedByInst->getType();
885
922
923
+ // Build a load of the index and subtract it from the count.
924
+ Value *IdxInst = nullptr;
886
925
if (Idx) {
887
- // There's an index into the array. Remove it from the count.
888
926
bool IdxSigned = Idx->getType()->isSignedIntegerType();
889
- Value * IdxInst = EmitAnyExprToTemp(Idx).getScalarVal();
927
+ IdxInst = EmitAnyExprToTemp(Idx).getScalarVal();
890
928
IdxInst = IdxSigned ? Builder.CreateSExtOrTrunc(IdxInst, CountedByTy)
891
929
: Builder.CreateZExtOrTrunc(IdxInst, CountedByTy);
892
930
893
- // If the index is negative, don't subtract it from the counted_by
894
- // value. The pointer is pointing to something before the FAM.
895
- IdxInst = Builder.CreateNeg(IdxInst, "", !IdxSigned, IdxSigned);
931
+ // We go ahead with the calculation here. If the index turns out to be
932
+ // negative, we'll catch it at the end.
896
933
CountedByInst =
897
- Builder.CreateAdd (CountedByInst, IdxInst, "", !IsSigned, IsSigned);
934
+ Builder.CreateSub (CountedByInst, IdxInst, "", !IsSigned, IsSigned);
898
935
}
899
936
900
- // Get the size of the flexible array member's base type.
901
- const ValueDecl *FAMDecl = nullptr;
902
- if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
903
- const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
904
- getLangOpts().getStrictFlexArraysLevel();
905
- if (const ValueDecl *MD = ME->getMemberDecl()) {
906
- if (!Decl::isFlexibleArrayMemberLike(
907
- Ctx, MD, MD->getType(), StrictFlexArraysLevel,
908
- /*IgnoreTemplateOrMacroSubstitution=*/true))
909
- return nullptr;
910
- // Base is referencing the FAM itself.
911
- FAMDecl = MD;
912
- }
913
- }
914
-
915
- if (!FAMDecl)
916
- FAMDecl = FindFlexibleArrayMemberField(Ctx, OuterRD);
917
-
918
- assert(FAMDecl && "Can't find the flexible array member field");
919
-
937
+ // Calculate how large the flexible array member is in bytes.
920
938
const ArrayType *ArrayTy = Ctx.getAsArrayType(FAMDecl->getType());
921
939
CharUnits Size = Ctx.getTypeSizeInChars(ArrayTy->getElementType());
922
940
llvm::Constant *ElemSize =
923
941
llvm::ConstantInt::get(CountedByTy, Size.getQuantity(), IsSigned);
924
-
925
- // Calculate how large the flexible array member is in bytes.
926
942
Value *FAMSize =
927
943
Builder.CreateMul(CountedByInst, ElemSize, "", !IsSigned, IsSigned);
928
944
FAMSize = IsSigned ? Builder.CreateSExtOrTrunc(FAMSize, ResType)
@@ -931,47 +947,38 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type,
931
947
932
948
if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
933
949
// The whole struct is specificed in the __bdos.
950
+ const RecordDecl *OuterRD =
951
+ CountedByFD->getDeclContext()->getOuterLexicalRecordContext();
934
952
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(OuterRD);
935
953
936
954
// Get the offset of the FAM.
937
955
CharUnits Offset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FAMDecl));
938
956
llvm::Constant *FAMOffset =
939
957
ConstantInt::get(ResType, Offset.getQuantity(), IsSigned);
940
-
941
- // max(sizeof(struct s),
942
- // offsetof(struct s, array) + p->count * sizeof(*p->array))
943
958
Value *OffsetAndFAMSize =
944
959
Builder.CreateAdd(FAMOffset, Res, "", !IsSigned, IsSigned);
945
960
946
961
// Get the full size of the struct.
947
962
llvm::Constant *SizeofStruct =
948
963
ConstantInt::get(ResType, Layout.getSize().getQuantity(), IsSigned);
949
964
965
+ // max(sizeof(struct s),
966
+ // offsetof(struct s, array) + p->count * sizeof(*p->array))
950
967
Res = IsSigned
951
968
? Builder.CreateBinaryIntrinsic(llvm::Intrinsic::smax,
952
969
OffsetAndFAMSize, SizeofStruct)
953
970
: Builder.CreateBinaryIntrinsic(llvm::Intrinsic::umax,
954
971
OffsetAndFAMSize, SizeofStruct);
955
- } else if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
956
- // Pointing to a place before the FAM. Add the difference to the FAM's
957
- // size.
958
- if (const ValueDecl *MD = ME->getMemberDecl(); MD != FAMDecl) {
959
- CharUnits Offset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MD));
960
- CharUnits FAMOffset =
961
- Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FAMDecl));
962
-
963
- Res = Builder.CreateAdd(
964
- Res, ConstantInt::get(ResType, FAMOffset.getQuantity() -
965
- Offset.getQuantity()));
966
- }
967
972
}
968
973
969
- // A negative 'FAMSize' means that the index was greater than the count,
970
- // or an improperly set count field. Return -1 (for types 0 and 1) or 0
971
- // (for types 2 and 3).
972
- return Builder.CreateSelect(Builder.CreateIsNeg(FAMSize),
973
- getDefaultBuiltinObjectSizeResult(Type, ResType),
974
- Res);
974
+ // A negative \p IdxInst or \p CountedByInst means that the index lands
975
+ // outside of the flexible array member. If that's the case, we want to
976
+ // return 0.
977
+ Value *Cmp = Builder.CreateIsNotNeg(CountedByInst);
978
+ if (IdxInst)
979
+ Cmp = Builder.CreateAnd(Builder.CreateIsNotNeg(IdxInst), Cmp);
980
+
981
+ return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned));
975
982
}
976
983
977
984
/// Returns a Value corresponding to the size of the given expression.
@@ -1006,19 +1013,19 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
1006
1013
}
1007
1014
}
1008
1015
1009
- // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't
1010
- // evaluate E for side-effects. In either case, we shouldn't lower to
1011
- // @llvm.objectsize.
1012
- if (Type == 3 || (!EmittedE && E->HasSideEffects(getContext())))
1013
- return getDefaultBuiltinObjectSizeResult(Type, ResType);
1014
-
1015
1016
if (IsDynamic) {
1016
1017
// Emit special code for a flexible array member with the "counted_by"
1017
1018
// attribute.
1018
1019
if (Value *V = emitFlexibleArrayMemberSize(E, Type, ResType))
1019
1020
return V;
1020
1021
}
1021
1022
1023
+ // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't
1024
+ // evaluate E for side-effects. In either case, we shouldn't lower to
1025
+ // @llvm.objectsize.
1026
+ if (Type == 3 || (!EmittedE && E->HasSideEffects(getContext())))
1027
+ return getDefaultBuiltinObjectSizeResult(Type, ResType);
1028
+
1022
1029
Value *Ptr = EmittedE ? EmittedE : EmitScalarExpr(E);
1023
1030
assert(Ptr->getType()->isPointerTy() &&
1024
1031
"Non-pointer passed to __builtin_object_size?");
0 commit comments