@@ -8328,22 +8328,33 @@ enum class CountedByInvalidPointeeTypeKind {
83288328 VALID,
83298329};
83308330
8331- static bool CheckCountedByAttrOnField (
8332- Sema &S, FieldDecl *FD, Expr *E,
8333- llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) {
8331+ static bool
8332+ CheckCountedByAttrOnField (Sema &S, FieldDecl *FD, Expr *E,
8333+ llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls,
8334+ bool CountInBytes, bool OrNull) {
83348335 // Check the context the attribute is used in
83358336
8337+ unsigned Kind = CountInBytes;
8338+ if (OrNull)
8339+ Kind += 2 ;
8340+
83368341 if (FD->getParent ()->isUnion ()) {
83378342 S.Diag (FD->getBeginLoc (), diag::err_counted_by_attr_in_union)
8338- << FD->getSourceRange ();
8343+ << Kind << FD->getSourceRange ();
83398344 return true ;
83408345 }
83418346
83428347 const auto FieldTy = FD->getType ();
8348+ if (FieldTy->isArrayType () && (CountInBytes || OrNull)) {
8349+ S.Diag (FD->getBeginLoc (),
8350+ diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member)
8351+ << Kind << FD->getLocation ();
8352+ return true ;
8353+ }
83438354 if (!FieldTy->isArrayType () && !FieldTy->isPointerType ()) {
83448355 S.Diag (FD->getBeginLoc (),
83458356 diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member)
8346- << FD->getLocation ();
8357+ << Kind << FD->getLocation ();
83478358 return true ;
83488359 }
83498360
@@ -8354,7 +8365,7 @@ static bool CheckCountedByAttrOnField(
83548365 StrictFlexArraysLevel, true )) {
83558366 S.Diag (FD->getBeginLoc (),
83568367 diag::err_counted_by_attr_on_array_not_flexible_array_member)
8357- << FD->getLocation ();
8368+ << Kind << FD->getLocation ();
83588369 return true ;
83598370 }
83608371
@@ -8394,29 +8405,30 @@ static bool CheckCountedByAttrOnField(
83948405 InvalidTypeKind = CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER;
83958406 }
83968407
8397- if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) {
8408+ if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID &&
8409+ !CountInBytes) {
83988410 unsigned DiagID = ShouldWarn
83998411 ? diag::warn_counted_by_attr_elt_type_unknown_size
84008412 : diag::err_counted_by_attr_pointee_unknown_size;
84018413 S.Diag (FD->getBeginLoc (), DiagID)
84028414 << SelectPtrOrArr << PointeeTy << (int )InvalidTypeKind
8403- << (ShouldWarn ? 1 : 0 ) << FD->getSourceRange ();
8415+ << (ShouldWarn ? 1 : 0 ) << OrNull << FD->getSourceRange ();
84048416 return true ;
84058417 }
84068418
84078419 // Check the expression
84088420
84098421 if (!E->getType ()->isIntegerType () || E->getType ()->isBooleanType ()) {
84108422 S.Diag (E->getBeginLoc (), diag::err_counted_by_attr_argument_not_integer)
8411- << E->getSourceRange ();
8423+ << Kind << E->getSourceRange ();
84128424 return true ;
84138425 }
84148426
84158427 auto *DRE = dyn_cast<DeclRefExpr>(E);
84168428 if (!DRE) {
84178429 S.Diag (E->getBeginLoc (),
84188430 diag::err_counted_by_attr_only_support_simple_decl_reference)
8419- << E->getSourceRange ();
8431+ << Kind << E->getSourceRange ();
84208432 return true ;
84218433 }
84228434
@@ -8427,7 +8439,7 @@ static bool CheckCountedByAttrOnField(
84278439 }
84288440 if (!CountFD) {
84298441 S.Diag (E->getBeginLoc (), diag::err_counted_by_must_be_in_structure)
8430- << CountDecl << E->getSourceRange ();
8442+ << CountDecl << Kind << E->getSourceRange ();
84318443
84328444 S.Diag (CountDecl->getBeginLoc (),
84338445 diag::note_flexible_array_counted_by_attr_field)
@@ -8438,7 +8450,7 @@ static bool CheckCountedByAttrOnField(
84388450 if (FD->getParent () != CountFD->getParent ()) {
84398451 if (CountFD->getParent ()->isUnion ()) {
84408452 S.Diag (CountFD->getBeginLoc (), diag::err_counted_by_attr_refer_to_union)
8441- << CountFD->getSourceRange ();
8453+ << Kind << CountFD->getSourceRange ();
84428454 return true ;
84438455 }
84448456 // Whether CountRD is an anonymous struct is not determined at this
@@ -8450,7 +8462,7 @@ static bool CheckCountedByAttrOnField(
84508462 if (RD != CountRD) {
84518463 S.Diag (E->getBeginLoc (),
84528464 diag::err_flexible_array_count_not_in_same_struct)
8453- << CountFD << E->getSourceRange ();
8465+ << CountFD << Kind << E->getSourceRange ();
84548466 S.Diag (CountFD->getBeginLoc (),
84558467 diag::note_flexible_array_counted_by_attr_field)
84568468 << CountFD << CountFD->getSourceRange ();
@@ -8470,12 +8482,35 @@ static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) {
84708482 if (!CountExpr)
84718483 return ;
84728484
8485+ bool CountInBytes;
8486+ bool OrNull;
8487+ switch (AL.getKind ()) {
8488+ case ParsedAttr::AT_CountedBy:
8489+ CountInBytes = false ;
8490+ OrNull = false ;
8491+ break ;
8492+ case ParsedAttr::AT_CountedByOrNull:
8493+ CountInBytes = false ;
8494+ OrNull = true ;
8495+ break ;
8496+ case ParsedAttr::AT_SizedBy:
8497+ CountInBytes = true ;
8498+ OrNull = false ;
8499+ break ;
8500+ case ParsedAttr::AT_SizedByOrNull:
8501+ CountInBytes = true ;
8502+ OrNull = true ;
8503+ break ;
8504+ default :
8505+ llvm_unreachable (" unexpected counted_by family attribute" );
8506+ }
8507+
84738508 llvm::SmallVector<TypeCoupledDeclRefInfo, 1 > Decls;
8474- if (CheckCountedByAttrOnField (S, FD, CountExpr, Decls))
8509+ if (CheckCountedByAttrOnField (S, FD, CountExpr, Decls, CountInBytes, OrNull ))
84758510 return ;
84768511
8477- QualType CAT =
8478- S. BuildCountAttributedArrayOrPointerType ( FD->getType (), CountExpr);
8512+ QualType CAT = S. BuildCountAttributedArrayOrPointerType (
8513+ FD->getType (), CountExpr, CountInBytes, OrNull );
84798514 FD->setType (CAT);
84808515}
84818516
@@ -9502,6 +9537,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
95029537 break ;
95039538
95049539 case ParsedAttr::AT_CountedBy:
9540+ case ParsedAttr::AT_CountedByOrNull:
9541+ case ParsedAttr::AT_SizedBy:
9542+ case ParsedAttr::AT_SizedByOrNull:
95059543 handleCountedByAttrField (S, D, AL);
95069544 break ;
95079545
0 commit comments