@@ -5868,6 +5868,15 @@ static const RecordDecl *GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD) {
58685868 return RD;
58695869}
58705870
5871+ static CountAttributedType::DynamicCountPointerKind
5872+ getCountAttrKind (bool CountInBytes, bool OrNull) {
5873+ if (CountInBytes)
5874+ return OrNull ? CountAttributedType::SizedByOrNull
5875+ : CountAttributedType::SizedBy;
5876+ return OrNull ? CountAttributedType::CountedByOrNull
5877+ : CountAttributedType::CountedBy;
5878+ }
5879+
58715880enum class CountedByInvalidPointeeTypeKind {
58725881 INCOMPLETE,
58735882 SIZELESS,
@@ -5876,22 +5885,31 @@ enum class CountedByInvalidPointeeTypeKind {
58765885 VALID,
58775886};
58785887
5879- static bool CheckCountedByAttrOnField (
5880- Sema &S, FieldDecl *FD, Expr *E,
5881- llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) {
5888+ static bool
5889+ CheckCountedByAttrOnField (Sema &S, FieldDecl *FD, Expr *E,
5890+ llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls,
5891+ bool CountInBytes, bool OrNull) {
58825892 // Check the context the attribute is used in
58835893
5894+ unsigned Kind = getCountAttrKind (CountInBytes, OrNull);
5895+
58845896 if (FD->getParent ()->isUnion ()) {
5885- S.Diag (FD->getBeginLoc (), diag::err_counted_by_attr_in_union )
5886- << FD->getSourceRange ();
5897+ S.Diag (FD->getBeginLoc (), diag::err_count_attr_in_union )
5898+ << Kind << FD->getSourceRange ();
58875899 return true ;
58885900 }
58895901
58905902 const auto FieldTy = FD->getType ();
5903+ if (FieldTy->isArrayType () && (CountInBytes || OrNull)) {
5904+ S.Diag (FD->getBeginLoc (),
5905+ diag::err_count_attr_not_on_ptr_or_flexible_array_member)
5906+ << Kind << FD->getLocation () << /* suggest counted_by */ 1 ;
5907+ return true ;
5908+ }
58915909 if (!FieldTy->isArrayType () && !FieldTy->isPointerType ()) {
58925910 S.Diag (FD->getBeginLoc (),
5893- diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member )
5894- << FD->getLocation ();
5911+ diag::err_count_attr_not_on_ptr_or_flexible_array_member )
5912+ << Kind << FD->getLocation () << /* do not suggest counted_by */ 0 ;
58955913 return true ;
58965914 }
58975915
@@ -5902,7 +5920,7 @@ static bool CheckCountedByAttrOnField(
59025920 StrictFlexArraysLevel, true )) {
59035921 S.Diag (FD->getBeginLoc (),
59045922 diag::err_counted_by_attr_on_array_not_flexible_array_member)
5905- << FD->getLocation ();
5923+ << Kind << FD->getLocation ();
59065924 return true ;
59075925 }
59085926
@@ -5923,7 +5941,7 @@ static bool CheckCountedByAttrOnField(
59235941 // only `PointeeTy->isStructureTypeWithFlexibleArrayMember()` is reachable
59245942 // when `FieldTy->isArrayType()`.
59255943 bool ShouldWarn = false ;
5926- if (PointeeTy->isIncompleteType ()) {
5944+ if (PointeeTy->isIncompleteType () && !CountInBytes ) {
59275945 InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
59285946 } else if (PointeeTy->isSizelessType ()) {
59295947 InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS;
@@ -5948,23 +5966,23 @@ static bool CheckCountedByAttrOnField(
59485966 : diag::err_counted_by_attr_pointee_unknown_size;
59495967 S.Diag (FD->getBeginLoc (), DiagID)
59505968 << SelectPtrOrArr << PointeeTy << (int )InvalidTypeKind
5951- << (ShouldWarn ? 1 : 0 ) << FD->getSourceRange ();
5969+ << (ShouldWarn ? 1 : 0 ) << Kind << FD->getSourceRange ();
59525970 return true ;
59535971 }
59545972
59555973 // Check the expression
59565974
59575975 if (!E->getType ()->isIntegerType () || E->getType ()->isBooleanType ()) {
5958- S.Diag (E->getBeginLoc (), diag::err_counted_by_attr_argument_not_integer )
5959- << E->getSourceRange ();
5976+ S.Diag (E->getBeginLoc (), diag::err_count_attr_argument_not_integer )
5977+ << Kind << E->getSourceRange ();
59605978 return true ;
59615979 }
59625980
59635981 auto *DRE = dyn_cast<DeclRefExpr>(E);
59645982 if (!DRE) {
59655983 S.Diag (E->getBeginLoc (),
5966- diag::err_counted_by_attr_only_support_simple_decl_reference )
5967- << E->getSourceRange ();
5984+ diag::err_count_attr_only_support_simple_decl_reference )
5985+ << Kind << E->getSourceRange ();
59685986 return true ;
59695987 }
59705988
@@ -5974,8 +5992,8 @@ static bool CheckCountedByAttrOnField(
59745992 CountFD = IFD->getAnonField ();
59755993 }
59765994 if (!CountFD) {
5977- S.Diag (E->getBeginLoc (), diag::err_counted_by_must_be_in_structure )
5978- << CountDecl << E->getSourceRange ();
5995+ S.Diag (E->getBeginLoc (), diag::err_count_attr_must_be_in_structure )
5996+ << CountDecl << Kind << E->getSourceRange ();
59795997
59805998 S.Diag (CountDecl->getBeginLoc (),
59815999 diag::note_flexible_array_counted_by_attr_field)
@@ -5985,8 +6003,8 @@ static bool CheckCountedByAttrOnField(
59856003
59866004 if (FD->getParent () != CountFD->getParent ()) {
59876005 if (CountFD->getParent ()->isUnion ()) {
5988- S.Diag (CountFD->getBeginLoc (), diag::err_counted_by_attr_refer_to_union )
5989- << CountFD->getSourceRange ();
6006+ S.Diag (CountFD->getBeginLoc (), diag::err_count_attr_refer_to_union )
6007+ << Kind << CountFD->getSourceRange ();
59906008 return true ;
59916009 }
59926010 // Whether CountRD is an anonymous struct is not determined at this
@@ -5996,9 +6014,8 @@ static bool CheckCountedByAttrOnField(
59966014 auto *CountRD = GetEnclosingNamedOrTopAnonRecord (CountFD);
59976015
59986016 if (RD != CountRD) {
5999- S.Diag (E->getBeginLoc (),
6000- diag::err_flexible_array_count_not_in_same_struct)
6001- << CountFD << E->getSourceRange ();
6017+ S.Diag (E->getBeginLoc (), diag::err_count_attr_param_not_in_same_struct)
6018+ << CountFD << Kind << FieldTy->isArrayType () << E->getSourceRange ();
60026019 S.Diag (CountFD->getBeginLoc (),
60036020 diag::note_flexible_array_counted_by_attr_field)
60046021 << CountFD << CountFD->getSourceRange ();
@@ -6018,12 +6035,35 @@ static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) {
60186035 if (!CountExpr)
60196036 return ;
60206037
6038+ bool CountInBytes;
6039+ bool OrNull;
6040+ switch (AL.getKind ()) {
6041+ case ParsedAttr::AT_CountedBy:
6042+ CountInBytes = false ;
6043+ OrNull = false ;
6044+ break ;
6045+ case ParsedAttr::AT_CountedByOrNull:
6046+ CountInBytes = false ;
6047+ OrNull = true ;
6048+ break ;
6049+ case ParsedAttr::AT_SizedBy:
6050+ CountInBytes = true ;
6051+ OrNull = false ;
6052+ break ;
6053+ case ParsedAttr::AT_SizedByOrNull:
6054+ CountInBytes = true ;
6055+ OrNull = true ;
6056+ break ;
6057+ default :
6058+ llvm_unreachable (" unexpected counted_by family attribute" );
6059+ }
6060+
60216061 llvm::SmallVector<TypeCoupledDeclRefInfo, 1 > Decls;
6022- if (CheckCountedByAttrOnField (S, FD, CountExpr, Decls))
6062+ if (CheckCountedByAttrOnField (S, FD, CountExpr, Decls, CountInBytes, OrNull ))
60236063 return ;
60246064
6025- QualType CAT =
6026- S. BuildCountAttributedArrayOrPointerType ( FD->getType (), CountExpr);
6065+ QualType CAT = S. BuildCountAttributedArrayOrPointerType (
6066+ FD->getType (), CountExpr, CountInBytes, OrNull );
60276067 FD->setType (CAT);
60286068}
60296069
@@ -6971,6 +7011,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
69717011 break ;
69727012
69737013 case ParsedAttr::AT_CountedBy:
7014+ case ParsedAttr::AT_CountedByOrNull:
7015+ case ParsedAttr::AT_SizedBy:
7016+ case ParsedAttr::AT_SizedByOrNull:
69747017 handleCountedByAttrField (S, D, AL);
69757018 break ;
69767019
0 commit comments