@@ -910,6 +910,7 @@ class StructFieldAccess
910910
911911public:
912912 const ArraySubscriptExpr *ASE = nullptr ;
913+ QualType ArrayElementTy;
913914
914915 const Expr *VisitMemberExpr (const MemberExpr *E) {
915916 if (AddrOfSeen && E->getType ()->isArrayType ())
@@ -925,6 +926,7 @@ class StructFieldAccess
925926
926927 AddrOfSeen = false ; // '&ptr->array[idx]' is okay.
927928 ASE = E;
929+ ArrayElementTy = E->getBase ()->getType ();
928930 return Visit (E->getBase ());
929931 }
930932 const Expr *VisitCastExpr (const CastExpr *E) {
@@ -1101,23 +1103,23 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
11011103 // count = ptr->count;
11021104 //
11031105 // flexible_array_member_base_size = sizeof (*ptr->array);
1104- // flexible_array_member_size =
1105- // count * flexible_array_member_base_size;
1106+ // flexible_array_member_size = count * flexible_array_member_base_size;
11061107 //
11071108 // if (flexible_array_member_size < 0)
11081109 // return 0;
11091110 // return flexible_array_member_size;
11101111 //
1111- // 2) '&ptr->array[idx]':
1112+ // 2) '&((cast) ptr->array) [idx]':
11121113 //
11131114 // count = ptr->count;
11141115 // index = idx;
11151116 //
1117+ // casted_flexible_array_member_base_size = sizeof (*((cast) ptr->array));
1118+ //
11161119 // flexible_array_member_base_size = sizeof (*ptr->array);
1117- // flexible_array_member_size =
1118- // count * flexible_array_member_base_size;
1120+ // flexible_array_member_size = count * flexible_array_member_base_size;
11191121 //
1120- // index_size = index * flexible_array_member_base_size ;
1122+ // index_size = index * casted_flexible_array_member_base_size ;
11211123 //
11221124 // if (flexible_array_member_size < 0 || index < 0)
11231125 // return 0;
@@ -1129,8 +1131,7 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
11291131 // sizeof_struct = sizeof (struct s);
11301132 //
11311133 // flexible_array_member_base_size = sizeof (*ptr->array);
1132- // flexible_array_member_size =
1133- // count * flexible_array_member_base_size;
1134+ // flexible_array_member_size = count * flexible_array_member_base_size;
11341135 //
11351136 // field_offset = offsetof (struct s, field);
11361137 // offset_diff = sizeof_struct - field_offset;
@@ -1139,19 +1140,19 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
11391140 // return 0;
11401141 // return offset_diff + flexible_array_member_size;
11411142 //
1142- // 4) '&ptr->field_array[idx]':
1143+ // 4) '&((cast) ptr->field_array) [idx]':
11431144 //
11441145 // count = ptr->count;
11451146 // index = idx;
11461147 // sizeof_struct = sizeof (struct s);
11471148 //
11481149 // flexible_array_member_base_size = sizeof (*ptr->array);
1149- // flexible_array_member_size =
1150- // count * flexible_array_member_base_size;
1150+ // flexible_array_member_size = count * flexible_array_member_base_size;
1151+ //
1152+ // casted_field_base_size = sizeof (*((cast) ptr->field_array));
11511153 //
1152- // field_base_size = sizeof (*ptr->field_array);
11531154 // field_offset = offsetof (struct s, field)
1154- // field_offset += index * field_base_size ;
1155+ // field_offset += index * casted_field_base_size ;
11551156 //
11561157 // offset_diff = sizeof_struct - field_offset;
11571158 //
@@ -1162,14 +1163,11 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
11621163 QualType CountTy = CountFD->getType ();
11631164 bool IsSigned = CountTy->isSignedIntegerType ();
11641165
1165- QualType FlexibleArrayMemberTy = FlexibleArrayMemberFD->getType ();
1166- QualType FieldTy = FD->getType ();
1167-
11681166 // Explicit cast because otherwise the CharWidth will promote an i32's into
11691167 // u64's leading to overflows..
11701168 int64_t CharWidth = static_cast <int64_t >(CGM.getContext ().getCharWidth ());
11711169
1172- // size_t field_offset = offsetof (struct s, field);
1170+ // field_offset = offsetof (struct s, field);
11731171 Value *FieldOffset = nullptr ;
11741172 if (FlexibleArrayMemberFD != FD) {
11751173 std::optional<int64_t > Offset = GetFieldOffset (Ctx, RD, FD);
@@ -1179,37 +1177,49 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
11791177 llvm::ConstantInt::get (ResType, *Offset / CharWidth, IsSigned);
11801178 }
11811179
1182- // size_t count = (size_t) ptr->count;
1180+ // count = ptr->count;
11831181 Value *Count = EmitLoadOfCountedByField (ME, FlexibleArrayMemberFD, CountFD);
11841182 if (!Count)
11851183 return nullptr ;
11861184 Count = Builder.CreateIntCast (Count, ResType, IsSigned, " count" );
11871185
1188- // size_t index = (size_t) ptr->index;
1186+ // index = ptr->index;
11891187 Value *Index = nullptr ;
11901188 if (Idx) {
11911189 bool IdxSigned = Idx->getType ()->isSignedIntegerType ();
11921190 Index = EmitScalarExpr (Idx);
11931191 Index = Builder.CreateIntCast (Index, ResType, IdxSigned, " index" );
11941192 }
11951193
1196- // size_t flexible_array_member_base_size = sizeof (*ptr->array);
1197- const ArrayType *ArrayTy = Ctx.getAsArrayType (FlexibleArrayMemberTy);
1198- CharUnits BaseSize = Ctx.getTypeSizeInChars (ArrayTy->getElementType ());
1194+ // flexible_array_member_base_size = sizeof (*ptr->array);
1195+ QualType FlexibleArrayMemberTy = FlexibleArrayMemberFD->getType ();
1196+ const ArrayType *FAMTy = Ctx.getAsArrayType (FlexibleArrayMemberTy);
1197+ CharUnits BaseSize = Ctx.getTypeSizeInChars (FAMTy->getElementType ());
11991198 auto *FlexibleArrayMemberBaseSize =
12001199 llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
12011200
1202- // size_t flexible_array_member_size =
1203- // count * flexible_array_member_base_size;
1201+ // flexible_array_member_size = count * flexible_array_member_base_size;
12041202 Value *FlexibleArrayMemberSize =
12051203 Builder.CreateMul (Count, FlexibleArrayMemberBaseSize,
12061204 " flexible_array_member_size" , !IsSigned, IsSigned);
12071205
1206+ QualType CastedArrayElementTy = Visitor.ArrayElementTy ;
1207+ llvm::ConstantInt *CastedArrayElementSize = nullptr ;
1208+ if (!CastedArrayElementTy.isNull () && CastedArrayElementTy->isPointerType ()) {
1209+ const PointerType *FAMTy = cast<clang::PointerType>(CastedArrayElementTy);
1210+ CharUnits BaseSize = Ctx.getTypeSizeInChars (FAMTy->getPointeeType ());
1211+ CastedArrayElementSize =
1212+ llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
1213+ }
1214+
12081215 Value *Res = nullptr ;
12091216 if (FlexibleArrayMemberFD == FD) {
1210- if (Idx) { // Option (2) '&ptr->array[idx]'
1211- // size_t index_size = index * flexible_array_member_base_size;
1212- Value *IndexSize = Builder.CreateMul (FlexibleArrayMemberBaseSize, Index,
1217+ if (Idx) { // Option (2) '&((cast) ptr->array)[idx]'
1218+ if (!CastedArrayElementSize)
1219+ CastedArrayElementSize = FlexibleArrayMemberBaseSize;
1220+
1221+ // index_size = index * flexible_array_member_base_size;
1222+ Value *IndexSize = Builder.CreateMul (CastedArrayElementSize, Index,
12131223 " index_size" , !IsSigned, IsSigned);
12141224
12151225 // return flexible_array_member_size - index_size;
@@ -1220,28 +1230,30 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
12201230 Res = FlexibleArrayMemberSize;
12211231 }
12221232 } else {
1223- // size_t sizeof_struct = sizeof (struct s);
1233+ // sizeof_struct = sizeof (struct s);
12241234 llvm::StructType *StructTy = getTypes ().getCGRecordLayout (RD).getLLVMType ();
12251235 const llvm::DataLayout &Layout = CGM.getDataLayout ();
12261236 TypeSize Size = Layout.getTypeSizeInBits (StructTy);
12271237 Value *SizeofStruct =
12281238 llvm::ConstantInt::get (ResType, Size.getKnownMinValue () / CharWidth);
12291239
1230- if (Idx) { // Option (4) '&ptr->field_array[idx]'
1231- // size_t field_base_size = sizeof (*ptr->field_array);
1232- const ArrayType *ArrayTy = Ctx.getAsArrayType (FieldTy);
1233- CharUnits BaseSize = Ctx.getTypeSizeInChars (ArrayTy->getElementType ());
1234- auto *FieldBaseSize =
1235- llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
1240+ if (Idx) { // Option (4) '&((cast) ptr->field_array)[idx]'
1241+ // casted_field_base_size = sizeof (*((cast) ptr->field_array));
1242+ if (!CastedArrayElementSize) {
1243+ const ArrayType *ArrayTy = Ctx.getAsArrayType (FD->getType ());
1244+ CharUnits BaseSize = Ctx.getTypeSizeInChars (ArrayTy->getElementType ());
1245+ CastedArrayElementSize =
1246+ llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
1247+ }
12361248
1237- // field_offset += index * field_base_size ;
1238- Value *Mul = Builder.CreateMul (Index, FieldBaseSize , " field_offset" ,
1249+ // field_offset += index * casted_field_base_size ;
1250+ Value *Mul = Builder.CreateMul (Index, CastedArrayElementSize , " field_offset" ,
12391251 !IsSigned, IsSigned);
12401252 FieldOffset = Builder.CreateAdd (FieldOffset, Mul);
12411253 }
12421254 // Option (3) '&ptr->field', and Option (4) continuation.
12431255
1244- // size_t offset_diff = flexible_array_member_offset - field_offset;
1256+ // offset_diff = flexible_array_member_offset - field_offset;
12451257 Value *OffsetDiff = Builder.CreateSub (SizeofStruct, FieldOffset,
12461258 " offset_diff" , !IsSigned, IsSigned);
12471259
0 commit comments