@@ -910,6 +910,7 @@ class StructFieldAccess
910910
911911public:
912912 const Expr *ArrayIndex = 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 ArrayIndex = E->getIdx ();
929+ ArrayElementTy = E->getBase ()->getType ();
928930 return Visit (E->getBase ());
929931 }
930932 const Expr *VisitCastExpr (const CastExpr *E) {
@@ -1059,15 +1061,17 @@ llvm::Value *CodeGenFunction::emitCountedBySize(const Expr *E,
10591061 }
10601062 }
10611063
1064+ // __counted_by on either a flexible array member or a pointer into a struct
1065+ // with a flexible array member.
10621066 if (const auto *ME = dyn_cast<MemberExpr>(E))
1063- // This is either a flexible array member or a pointer into a struct with a
1064- // flexible array member.
1065- return emitCountedByMemberSize (ME, Idx, EmittedE, Type, ResType);
1067+ return emitCountedByMemberSize (ME, Idx, EmittedE, Visitor.ArrayElementTy ,
1068+ Type, ResType);
10661069
1070+ // __counted_by on a pointer in a struct.
10671071 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
10681072 ICE && ICE->getCastKind () == CK_LValueToRValue)
1069- // This may be a pointer.
1070- return emitCountedByPointerSize (ICE, Idx, EmittedE, Type, ResType);
1073+ return emitCountedByPointerSize (ICE, Idx, EmittedE, Visitor. ArrayElementTy ,
1074+ Type, ResType);
10711075
10721076 return nullptr ;
10731077}
@@ -1111,7 +1115,7 @@ GetCountFieldAndIndex(CodeGenFunction &CGF, const MemberExpr *ME,
11111115
11121116llvm::Value *CodeGenFunction::emitCountedByPointerSize (
11131117 const ImplicitCastExpr *E, const Expr *Idx, llvm::Value *EmittedE,
1114- unsigned Type, llvm::IntegerType *ResType) {
1118+ QualType CastedArrayElementTy, unsigned Type, llvm::IntegerType *ResType) {
11151119 assert (E->getCastKind () == CK_LValueToRValue &&
11161120 " must be an LValue to RValue cast" );
11171121
@@ -1144,52 +1148,67 @@ llvm::Value *CodeGenFunction::emitCountedByPointerSize(
11441148 //
11451149 // count = ptr->count;
11461150 //
1147- // array_base_size = sizeof (*ptr->array);
1148- // array_size = count * array_base_size ;
1151+ // array_element_size = sizeof (*ptr->array);
1152+ // array_size = count * array_element_size ;
11491153 //
11501154 // result = array_size;
11511155 //
11521156 // cmp = (result >= 0)
11531157 // return cmp ? result : 0;
11541158 //
1155- // 2) '&ptr->array[idx]':
1159+ // 2) '&((cast) ptr->array) [idx]':
11561160 //
11571161 // count = ptr->count;
11581162 // index = idx;
11591163 //
1160- // array_base_size = sizeof (*ptr->array_base_size );
1161- // array_size = count * array_base_size ;
1164+ // array_element_size = sizeof (*ptr->array );
1165+ // array_size = count * array_element_size ;
11621166 //
1163- // index_size = index * array_base_size ;
1167+ // casted_array_element_size = sizeof (*((cast) ptr->array)) ;
11641168 //
1169+ // index_size = index * casted_array_element_size;
11651170 // result = array_size - index_size;
11661171 //
11671172 // cmp = (result >= 0)
11681173 // if (index)
11691174 // cmp = (cmp && index > 0)
11701175 // return cmp ? result : 0;
11711176
1172- bool IsSigned = CountFD->getType ()->isSignedIntegerType ();
1177+ auto GetElementBaseSize = [&](QualType ElementTy) {
1178+ CharUnits ElementSize =
1179+ getContext ().getTypeSizeInChars (ElementTy->getPointeeType ());
1180+
1181+ if (ElementSize.isZero ()) {
1182+ // This might be a __sized_by on a 'void *', which counts bytes, not
1183+ // elements.
1184+ auto *CAT = ElementTy->getAs <CountAttributedType>();
1185+ if (!CAT || (CAT->getKind () != CountAttributedType::SizedBy &&
1186+ CAT->getKind () != CountAttributedType::SizedByOrNull))
1187+ // Okay, not sure what it is now.
1188+ // FIXME: Should this be an assert?
1189+ return std::optional<CharUnits>();
1190+
1191+ ElementSize = CharUnits::One ();
1192+ }
11731193
1174- // array_base_size = sizeof (*ptr->array);
1175- ASTContext &Ctx = getContext ();
1176- QualType ArrayBaseTy = ArrayBaseFD->getType ()->getPointeeType ();
1177- CharUnits BaseSize = Ctx.getTypeSizeInChars (ArrayBaseTy);
1178- if (BaseSize.isZero ()) {
1179- // This might be a __sized_by on a 'void *', which counts bytes, not
1180- // elements.
1181- auto *CAT = ArrayBaseFD->getType ()->getAs <CountAttributedType>();
1182- if (CAT->getKind () != CountAttributedType::SizedBy &&
1183- CAT->getKind () != CountAttributedType::SizedByOrNull)
1184- // Okay, not sure what it is now.
1185- // FIXME: Should this be an assert?
1186- return nullptr ;
1194+ return std::optional<CharUnits>(ElementSize);
1195+ };
11871196
1188- BaseSize = CharUnits::One ();
1197+ // Get the sizes of the original array element and the casted array element,
1198+ // if different.
1199+ std::optional<CharUnits> ArrayElementBaseSize =
1200+ GetElementBaseSize (ArrayBaseFD->getType ());
1201+ if (!ArrayElementBaseSize)
1202+ return nullptr ;
1203+
1204+ std::optional<CharUnits> CastedArrayElementBaseSize = ArrayElementBaseSize;
1205+ if (!CastedArrayElementTy.isNull () && CastedArrayElementTy->isPointerType ()) {
1206+ CastedArrayElementBaseSize = GetElementBaseSize (CastedArrayElementTy);
1207+ if (!CastedArrayElementBaseSize)
1208+ return nullptr ;
11891209 }
11901210
1191- auto *ArrayBaseSize =
1192- llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
1211+ bool IsSigned = CountFD->getType ()->isSignedIntegerType ();
11931212
11941213 // count = ptr->count;
11951214 // index = ptr->index;
@@ -1199,30 +1218,38 @@ llvm::Value *CodeGenFunction::emitCountedByPointerSize(
11991218 if (!Count)
12001219 return nullptr ;
12011220
1202- // array_size = count * array_base_size;
1203- Value *ArraySize = Builder.CreateMul (Count, ArrayBaseSize, " array_size" ,
1221+ // array_element_size = sizeof (*ptr->array)
1222+ auto *ArrayElementSize = llvm::ConstantInt::get (
1223+ ResType, ArrayElementBaseSize->getQuantity (), IsSigned);
1224+
1225+ // casted_array_element_size = sizeof (*((cast) ptr->array));
1226+ auto *CastedArrayElementSize = llvm::ConstantInt::get (
1227+ ResType, CastedArrayElementBaseSize->getQuantity (), IsSigned);
1228+
1229+ // array_size = count * array_element_size;
1230+ Value *ArraySize = Builder.CreateMul (Count, ArrayElementSize, " array_size" ,
12041231 !IsSigned, IsSigned);
12051232
12061233 // Option (1) 'ptr->array'
1207- // result = array_size
1208- Value *Res = ArraySize;
1234+ // result = array_size
1235+ Value *Result = ArraySize;
12091236
1210- if (Idx) { // Option (2) '&ptr->array[idx]'
1211- // index_size = index * array_base_size ;
1212- Value *IndexSize = Builder.CreateMul (ArrayBaseSize, Index, " index_size " ,
1213- !IsSigned, IsSigned);
1237+ if (Idx) { // Option (2) '&((cast) ptr->array) [idx]'
1238+ // index_size = index * casted_array_element_size ;
1239+ Value *IndexSize = Builder.CreateMul (Index, CastedArrayElementSize ,
1240+ " index_size " , !IsSigned, IsSigned);
12141241
12151242 // result = result - index_size;
1216- Res = Builder.CreateSub (Res, IndexSize, " result" , !IsSigned, IsSigned);
1243+ Result =
1244+ Builder.CreateSub (Result, IndexSize, " result" , !IsSigned, IsSigned);
12171245 }
12181246
1219- return EmitPositiveResultOrZero (*this , Res , Index, ResType, IsSigned);
1247+ return EmitPositiveResultOrZero (*this , Result , Index, ResType, IsSigned);
12201248}
12211249
1222- llvm::Value *
1223- CodeGenFunction::emitCountedByMemberSize (const MemberExpr *ME, const Expr *Idx,
1224- llvm::Value *EmittedE, unsigned Type,
1225- llvm::IntegerType *ResType) {
1250+ llvm::Value *CodeGenFunction::emitCountedByMemberSize (
1251+ const MemberExpr *ME, const Expr *Idx, llvm::Value *EmittedE,
1252+ QualType CastedArrayElementTy, unsigned Type, llvm::IntegerType *ResType) {
12261253 const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl ());
12271254 if (!FD)
12281255 return nullptr ;
@@ -1264,25 +1291,27 @@ CodeGenFunction::emitCountedByMemberSize(const MemberExpr *ME, const Expr *Idx,
12641291 //
12651292 // count = ptr->count;
12661293 //
1267- // flexible_array_member_base_size = sizeof (*ptr->array);
1294+ // flexible_array_member_element_size = sizeof (*ptr->array);
12681295 // flexible_array_member_size =
1269- // count * flexible_array_member_base_size ;
1296+ // count * flexible_array_member_element_size ;
12701297 //
12711298 // result = flexible_array_member_size;
12721299 //
12731300 // cmp = (result >= 0)
12741301 // return cmp ? result : 0;
12751302 //
1276- // 2) '&ptr->array[idx]':
1303+ // 2) '&((cast) ptr->array) [idx]':
12771304 //
12781305 // count = ptr->count;
12791306 // index = idx;
12801307 //
1281- // flexible_array_member_base_size = sizeof (*ptr->array);
1308+ // flexible_array_member_element_size = sizeof (*ptr->array);
12821309 // flexible_array_member_size =
1283- // count * flexible_array_member_base_size ;
1310+ // count * flexible_array_member_element_size ;
12841311 //
1285- // index_size = index * flexible_array_member_base_size;
1312+ // casted_flexible_array_member_element_size =
1313+ // sizeof (*((cast) ptr->array));
1314+ // index_size = index * casted_flexible_array_member_element_size;
12861315 //
12871316 // result = flexible_array_member_size - index_size;
12881317 //
@@ -1296,9 +1325,9 @@ CodeGenFunction::emitCountedByMemberSize(const MemberExpr *ME, const Expr *Idx,
12961325 // count = ptr->count;
12971326 // sizeof_struct = sizeof (struct s);
12981327 //
1299- // flexible_array_member_base_size = sizeof (*ptr->array);
1328+ // flexible_array_member_element_size = sizeof (*ptr->array);
13001329 // flexible_array_member_size =
1301- // count * flexible_array_member_base_size ;
1330+ // count * flexible_array_member_element_size ;
13021331 //
13031332 // field_offset = offsetof (struct s, field);
13041333 // offset_diff = sizeof_struct - field_offset;
@@ -1308,19 +1337,19 @@ CodeGenFunction::emitCountedByMemberSize(const MemberExpr *ME, const Expr *Idx,
13081337 // cmp = (result >= 0)
13091338 // return cmp ? result : 0;
13101339 //
1311- // 4) '&ptr->field_array[idx]':
1340+ // 4) '&((cast) ptr->field_array) [idx]':
13121341 //
13131342 // count = ptr->count;
13141343 // index = idx;
13151344 // sizeof_struct = sizeof (struct s);
13161345 //
1317- // flexible_array_member_base_size = sizeof (*ptr->array);
1346+ // flexible_array_member_element_size = sizeof (*ptr->array);
13181347 // flexible_array_member_size =
1319- // count * flexible_array_member_base_size ;
1348+ // count * flexible_array_member_element_size ;
13201349 //
1321- // field_base_size = sizeof (*ptr->field_array);
1350+ // casted_field_element_size = sizeof (*((cast) ptr->field_array) );
13221351 // field_offset = offsetof (struct s, field)
1323- // field_offset += index * field_base_size ;
1352+ // field_offset += index * casted_field_element_size ;
13241353 //
13251354 // offset_diff = sizeof_struct - field_offset;
13261355 //
@@ -1334,7 +1363,6 @@ CodeGenFunction::emitCountedByMemberSize(const MemberExpr *ME, const Expr *Idx,
13341363 bool IsSigned = CountFD->getType ()->isSignedIntegerType ();
13351364
13361365 QualType FlexibleArrayMemberTy = FlexibleArrayMemberFD->getType ();
1337- QualType FieldTy = FD->getType ();
13381366
13391367 // Explicit cast because otherwise the CharWidth will promote an i32's into
13401368 // u64's leading to overflows.
@@ -1358,31 +1386,43 @@ CodeGenFunction::emitCountedByMemberSize(const MemberExpr *ME, const Expr *Idx,
13581386 if (!Count)
13591387 return nullptr ;
13601388
1361- // flexible_array_member_base_size = sizeof (*ptr->array);
1389+ // flexible_array_member_element_size = sizeof (*ptr->array);
13621390 const ArrayType *ArrayTy = Ctx.getAsArrayType (FlexibleArrayMemberTy);
13631391 CharUnits BaseSize = Ctx.getTypeSizeInChars (ArrayTy->getElementType ());
1364- auto *FlexibleArrayMemberBaseSize =
1392+ auto *FlexibleArrayMemberElementSize =
13651393 llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
13661394
1367- // flexible_array_member_size =
1368- // count * flexible_array_member_base_size;
1395+ // flexible_array_member_size = count * flexible_array_member_element_size;
13691396 Value *FlexibleArrayMemberSize =
1370- Builder.CreateMul (Count, FlexibleArrayMemberBaseSize ,
1397+ Builder.CreateMul (Count, FlexibleArrayMemberElementSize ,
13711398 " flexible_array_member_size" , !IsSigned, IsSigned);
13721399
1373- Value *Res = nullptr ;
1400+ Value *Result = nullptr ;
13741401 if (FlexibleArrayMemberFD == FD) {
1375- if (Idx) { // Option (2) '&ptr->array[idx]'
1376- // index_size = index * flexible_array_member_base_size;
1377- Value *IndexSize = Builder.CreateMul (FlexibleArrayMemberBaseSize, Index,
1378- " index_size" , !IsSigned, IsSigned);
1402+ if (Idx) { // Option (2) '&((cast) ptr->array)[idx]'
1403+ // casted_flexible_array_member_element_size =
1404+ // sizeof (*((cast) ptr->array));
1405+ llvm::ConstantInt *CastedFlexibleArrayMemberElementSize =
1406+ FlexibleArrayMemberElementSize;
1407+ if (!CastedArrayElementTy.isNull () &&
1408+ CastedArrayElementTy->isPointerType ()) {
1409+ CharUnits BaseSize =
1410+ Ctx.getTypeSizeInChars (CastedArrayElementTy->getPointeeType ());
1411+ CastedFlexibleArrayMemberElementSize =
1412+ llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
1413+ }
1414+
1415+ // index_size = index * casted_flexible_array_member_element_size;
1416+ Value *IndexSize =
1417+ Builder.CreateMul (Index, CastedFlexibleArrayMemberElementSize,
1418+ " index_size" , !IsSigned, IsSigned);
13791419
13801420 // result = flexible_array_member_size - index_size;
1381- Res = Builder.CreateSub (FlexibleArrayMemberSize, IndexSize, " result" ,
1382- !IsSigned, IsSigned);
1421+ Result = Builder.CreateSub (FlexibleArrayMemberSize, IndexSize, " result" ,
1422+ !IsSigned, IsSigned);
13831423 } else { // Option (1) 'ptr->array'
13841424 // result = flexible_array_member_size;
1385- Res = FlexibleArrayMemberSize;
1425+ Result = FlexibleArrayMemberSize;
13861426 }
13871427 } else {
13881428 // sizeof_struct = sizeof (struct s);
@@ -1392,29 +1432,36 @@ CodeGenFunction::emitCountedByMemberSize(const MemberExpr *ME, const Expr *Idx,
13921432 Value *SizeofStruct =
13931433 llvm::ConstantInt::get (ResType, Size.getKnownMinValue () / CharWidth);
13941434
1395- if (Idx) { // Option (4) '&ptr->field_array[idx]'
1396- // field_base_size = sizeof (*ptr->field_array);
1397- const ArrayType *ArrayTy = Ctx.getAsArrayType (FieldTy);
1398- CharUnits BaseSize = Ctx.getTypeSizeInChars (ArrayTy->getElementType ());
1399- auto *FieldBaseSize =
1435+ if (Idx) { // Option (4) '&((cast) ptr->field_array)[idx]'
1436+ // casted_field_element_size = sizeof (*((cast) ptr->field_array));
1437+ CharUnits BaseSize;
1438+ if (!CastedArrayElementTy.isNull () &&
1439+ CastedArrayElementTy->isPointerType ()) {
1440+ BaseSize =
1441+ Ctx.getTypeSizeInChars (CastedArrayElementTy->getPointeeType ());
1442+ } else {
1443+ const ArrayType *ArrayTy = Ctx.getAsArrayType (FD->getType ());
1444+ BaseSize = Ctx.getTypeSizeInChars (ArrayTy->getElementType ());
1445+ }
1446+
1447+ llvm::ConstantInt *CastedFieldElementSize =
14001448 llvm::ConstantInt::get (ResType, BaseSize.getQuantity (), IsSigned);
14011449
1402- // field_offset += index * field_base_size ;
1403- Value *Mul = Builder.CreateMul (Index, FieldBaseSize, " field_offset " ,
1404- !IsSigned, IsSigned);
1450+ // field_offset += index * casted_field_element_size ;
1451+ Value *Mul = Builder.CreateMul (Index, CastedFieldElementSize ,
1452+ " field_offset " , !IsSigned, IsSigned);
14051453 FieldOffset = Builder.CreateAdd (FieldOffset, Mul);
14061454 }
14071455 // Option (3) '&ptr->field', and Option (4) continuation.
1408-
14091456 // offset_diff = flexible_array_member_offset - field_offset;
14101457 Value *OffsetDiff = Builder.CreateSub (SizeofStruct, FieldOffset,
14111458 " offset_diff" , !IsSigned, IsSigned);
14121459
14131460 // result = offset_diff + flexible_array_member_size;
1414- Res = Builder.CreateAdd (FlexibleArrayMemberSize, OffsetDiff, " result" );
1461+ Result = Builder.CreateAdd (FlexibleArrayMemberSize, OffsetDiff, " result" );
14151462 }
14161463
1417- return EmitPositiveResultOrZero (*this , Res , Index, ResType, IsSigned);
1464+ return EmitPositiveResultOrZero (*this , Result , Index, ResType, IsSigned);
14181465}
14191466
14201467// / Returns a Value corresponding to the size of the given expression.
0 commit comments