@@ -5876,22 +5876,33 @@ enum class CountedByInvalidPointeeTypeKind {
58765876 VALID,
58775877};
58785878
5879- static bool CheckCountedByAttrOnField (
5880- Sema &S, FieldDecl *FD, Expr *E,
5881- llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) {
5879+ static bool
5880+ CheckCountedByAttrOnField (Sema &S, FieldDecl *FD, Expr *E,
5881+ llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls,
5882+ bool CountInBytes, bool OrNull) {
58825883 // Check the context the attribute is used in
58835884
5885+ unsigned Kind = CountInBytes;
5886+ if (OrNull)
5887+ Kind += 2 ;
5888+
58845889 if (FD->getParent ()->isUnion ()) {
58855890 S.Diag (FD->getBeginLoc (), diag::err_counted_by_attr_in_union)
5886- << FD->getSourceRange ();
5891+ << Kind << FD->getSourceRange ();
58875892 return true ;
58885893 }
58895894
58905895 const auto FieldTy = FD->getType ();
5896+ if (FieldTy->isArrayType () && (CountInBytes || OrNull)) {
5897+ S.Diag (FD->getBeginLoc (),
5898+ diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member)
5899+ << Kind << FD->getLocation ();
5900+ return true ;
5901+ }
58915902 if (!FieldTy->isArrayType () && !FieldTy->isPointerType ()) {
58925903 S.Diag (FD->getBeginLoc (),
58935904 diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member)
5894- << FD->getLocation ();
5905+ << Kind << FD->getLocation ();
58955906 return true ;
58965907 }
58975908
@@ -5902,7 +5913,7 @@ static bool CheckCountedByAttrOnField(
59025913 StrictFlexArraysLevel, true )) {
59035914 S.Diag (FD->getBeginLoc (),
59045915 diag::err_counted_by_attr_on_array_not_flexible_array_member)
5905- << FD->getLocation ();
5916+ << Kind << FD->getLocation ();
59065917 return true ;
59075918 }
59085919
@@ -5942,29 +5953,30 @@ static bool CheckCountedByAttrOnField(
59425953 InvalidTypeKind = CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER;
59435954 }
59445955
5945- if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) {
5956+ if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID &&
5957+ !CountInBytes) {
59465958 unsigned DiagID = ShouldWarn
59475959 ? diag::warn_counted_by_attr_elt_type_unknown_size
59485960 : diag::err_counted_by_attr_pointee_unknown_size;
59495961 S.Diag (FD->getBeginLoc (), DiagID)
59505962 << SelectPtrOrArr << PointeeTy << (int )InvalidTypeKind
5951- << (ShouldWarn ? 1 : 0 ) << FD->getSourceRange ();
5963+ << (ShouldWarn ? 1 : 0 ) << OrNull << FD->getSourceRange ();
59525964 return true ;
59535965 }
59545966
59555967 // Check the expression
59565968
59575969 if (!E->getType ()->isIntegerType () || E->getType ()->isBooleanType ()) {
59585970 S.Diag (E->getBeginLoc (), diag::err_counted_by_attr_argument_not_integer)
5959- << E->getSourceRange ();
5971+ << Kind << E->getSourceRange ();
59605972 return true ;
59615973 }
59625974
59635975 auto *DRE = dyn_cast<DeclRefExpr>(E);
59645976 if (!DRE) {
59655977 S.Diag (E->getBeginLoc (),
59665978 diag::err_counted_by_attr_only_support_simple_decl_reference)
5967- << E->getSourceRange ();
5979+ << Kind << E->getSourceRange ();
59685980 return true ;
59695981 }
59705982
@@ -5975,7 +5987,7 @@ static bool CheckCountedByAttrOnField(
59755987 }
59765988 if (!CountFD) {
59775989 S.Diag (E->getBeginLoc (), diag::err_counted_by_must_be_in_structure)
5978- << CountDecl << E->getSourceRange ();
5990+ << CountDecl << Kind << E->getSourceRange ();
59795991
59805992 S.Diag (CountDecl->getBeginLoc (),
59815993 diag::note_flexible_array_counted_by_attr_field)
@@ -5986,7 +5998,7 @@ static bool CheckCountedByAttrOnField(
59865998 if (FD->getParent () != CountFD->getParent ()) {
59875999 if (CountFD->getParent ()->isUnion ()) {
59886000 S.Diag (CountFD->getBeginLoc (), diag::err_counted_by_attr_refer_to_union)
5989- << CountFD->getSourceRange ();
6001+ << Kind << CountFD->getSourceRange ();
59906002 return true ;
59916003 }
59926004 // Whether CountRD is an anonymous struct is not determined at this
@@ -5998,7 +6010,7 @@ static bool CheckCountedByAttrOnField(
59986010 if (RD != CountRD) {
59996011 S.Diag (E->getBeginLoc (),
60006012 diag::err_flexible_array_count_not_in_same_struct)
6001- << CountFD << E->getSourceRange ();
6013+ << CountFD << Kind << E->getSourceRange ();
60026014 S.Diag (CountFD->getBeginLoc (),
60036015 diag::note_flexible_array_counted_by_attr_field)
60046016 << CountFD << CountFD->getSourceRange ();
@@ -6018,12 +6030,35 @@ static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) {
60186030 if (!CountExpr)
60196031 return ;
60206032
6033+ bool CountInBytes;
6034+ bool OrNull;
6035+ switch (AL.getKind ()) {
6036+ case ParsedAttr::AT_CountedBy:
6037+ CountInBytes = false ;
6038+ OrNull = false ;
6039+ break ;
6040+ case ParsedAttr::AT_CountedByOrNull:
6041+ CountInBytes = false ;
6042+ OrNull = true ;
6043+ break ;
6044+ case ParsedAttr::AT_SizedBy:
6045+ CountInBytes = true ;
6046+ OrNull = false ;
6047+ break ;
6048+ case ParsedAttr::AT_SizedByOrNull:
6049+ CountInBytes = true ;
6050+ OrNull = true ;
6051+ break ;
6052+ default :
6053+ llvm_unreachable (" unexpected counted_by family attribute" );
6054+ }
6055+
60216056 llvm::SmallVector<TypeCoupledDeclRefInfo, 1 > Decls;
6022- if (CheckCountedByAttrOnField (S, FD, CountExpr, Decls))
6057+ if (CheckCountedByAttrOnField (S, FD, CountExpr, Decls, CountInBytes, OrNull ))
60236058 return ;
60246059
6025- QualType CAT =
6026- S. BuildCountAttributedArrayOrPointerType ( FD->getType (), CountExpr);
6060+ QualType CAT = S. BuildCountAttributedArrayOrPointerType (
6061+ FD->getType (), CountExpr, CountInBytes, OrNull );
60276062 FD->setType (CAT);
60286063}
60296064
@@ -6971,6 +7006,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
69717006 break ;
69727007
69737008 case ParsedAttr::AT_CountedBy:
7009+ case ParsedAttr::AT_CountedByOrNull:
7010+ case ParsedAttr::AT_SizedBy:
7011+ case ParsedAttr::AT_SizedByOrNull:
69747012 handleCountedByAttrField (S, D, AL);
69757013 break ;
69767014
0 commit comments