@@ -5411,16 +5411,17 @@ class ConstructDynamicBoundType
54115411 const BoundsAttributedType *ConstructedType = nullptr ;
54125412 unsigned Level;
54135413 bool ScopeCheck;
5414+ bool AllowRedecl;
54145415 bool AutoPtrAttributed = false ;
5415- bool AllowCountRedecl = false ;
54165416 bool AtomicErrorEmitted = false ;
54175417
54185418public:
54195419 explicit ConstructDynamicBoundType (Sema &S, unsigned Level,
54205420 const StringRef DiagName, Expr *ArgExpr,
5421- SourceLocation Loc, bool ScopeCheck)
5421+ SourceLocation Loc, bool ScopeCheck,
5422+ bool AllowRedecl)
54225423 : S(S), DiagName(DiagName), ArgExpr(ArgExpr), Loc(Loc), Level(Level),
5423- ScopeCheck(ScopeCheck) {}
5424+ ScopeCheck(ScopeCheck), AllowRedecl(AllowRedecl) {}
54245425
54255426 QualType Visit (QualType T) {
54265427 SplitQualType SQT = T.split ();
@@ -5449,7 +5450,6 @@ class ConstructDynamicBoundType
54495450
54505451 QualType VisitFunctionProtoType (const FunctionProtoType *FPT) {
54515452 // The attribute applies to the return type.
5452- SaveAndRestore<bool > AllowCountRedeclLocal (AllowCountRedecl, true );
54535453 QualType QT = Visit (FPT->getReturnType ());
54545454 if (QT.isNull ())
54555455 return QualType ();
@@ -5461,7 +5461,6 @@ class ConstructDynamicBoundType
54615461
54625462 QualType VisitFunctionNoProtoType (const FunctionNoProtoType *FPT) {
54635463 // The attribute applies to the return type.
5464- SaveAndRestore<bool > AllowCountRedeclLocal (AllowCountRedecl, true );
54655464 QualType QT = Visit (FPT->getReturnType ());
54665465 if (QT.isNull ())
54675466 return QualType ();
@@ -5592,8 +5591,10 @@ class ConstructCountAttributedType :
55925591 explicit ConstructCountAttributedType (Sema &S, unsigned Level,
55935592 const StringRef DiagName, Expr *ArgExpr,
55945593 SourceLocation Loc, bool CountInBytes,
5595- bool OrNull, bool ScopeCheck = false )
5596- : ConstructDynamicBoundType(S, Level, DiagName, ArgExpr, Loc, ScopeCheck),
5594+ bool OrNull, bool AllowRedecl,
5595+ bool ScopeCheck = false )
5596+ : ConstructDynamicBoundType(S, Level, DiagName, ArgExpr, Loc, ScopeCheck,
5597+ AllowRedecl),
55975598 CountInBytes(CountInBytes), OrNull(OrNull) {
55985599 if (!ArgExpr->getType ()->isIntegralOrEnumerationType ()) {
55995600 S.Diag (Loc, diag::err_attribute_argument_type_for_bounds_safety_count)
@@ -5661,7 +5662,7 @@ class ConstructCountAttributedType :
56615662 }
56625663
56635664 QualType DiagnoseConflictingType (const CountAttributedType *T) {
5664- if (AllowCountRedecl ) {
5665+ if (AllowRedecl ) {
56655666 QualType NewTy = BuildDynamicBoundType (T->desugar ());
56665667 const auto *NewDCPTy = NewTy->getAs <CountAttributedType>();
56675668 // We don't have a way to distinguish if '__counted_by' is conflicting or has been
@@ -5684,6 +5685,16 @@ class ConstructCountAttributedType :
56845685 return QualType ();
56855686 }
56865687
5688+ QualType VisitFunctionProtoType (const FunctionProtoType *FPT) {
5689+ SaveAndRestore<bool > AllowRedeclLocal (AllowRedecl, true );
5690+ return ConstructDynamicBoundType::VisitFunctionProtoType (FPT);
5691+ }
5692+
5693+ QualType VisitFunctionNoProtoType (const FunctionNoProtoType *FPT) {
5694+ SaveAndRestore<bool > AllowRedeclLocal (AllowRedecl, true );
5695+ return ConstructDynamicBoundType::VisitFunctionNoProtoType (FPT);
5696+ }
5697+
56875698 QualType DiagnoseConflictingType (const DynamicRangePointerType *T) {
56885699 S.Diag (Loc, diag::err_bounds_safety_conflicting_count_range_attributes);
56895700 return QualType ();
@@ -5858,9 +5869,10 @@ class ConstructDynamicRangePointerType :
58585869public:
58595870 explicit ConstructDynamicRangePointerType (
58605871 Sema &S, unsigned Level, const StringRef DiagName, Expr *ArgExpr,
5861- SourceLocation Loc, bool ScopeCheck = false ,
5872+ SourceLocation Loc, bool AllowRedecl, bool ScopeCheck = false ,
58625873 std::optional<TypeCoupledDeclRefInfo> StartPtrInfo = std::nullopt )
5863- : ConstructDynamicBoundType(S, Level, DiagName, ArgExpr, Loc, ScopeCheck),
5874+ : ConstructDynamicBoundType(S, Level, DiagName, ArgExpr, Loc, ScopeCheck,
5875+ AllowRedecl),
58645876 StartPtrInfo(StartPtrInfo) {
58655877 assert (ArgExpr->getType ()->isPointerType ());
58665878 }
@@ -5900,11 +5912,11 @@ class ConstructDynamicRangePointerType :
59005912 }
59015913
59025914 QualType VisitDynamicRangePointerType (const DynamicRangePointerType *T) {
5903- if (Level == 0 && T->getEndPointer () == nullptr ) {
5904- // T is a started_by() pointer type.
5915+ if (Level == 0 && (AllowRedecl || T->getEndPointer () == nullptr ) ) {
5916+ // T could be a started_by() pointer type.
59055917 Expr *StartPtr = T->getStartPointer ();
59065918 auto StartPtrDecls = T->getStartPtrDecls ();
5907- assert (StartPtr);
5919+ assert (StartPtr || AllowRedecl );
59085920
59095921 assert (ConstructedType == nullptr );
59105922 // Construct an ended_by() pointer type.
@@ -5917,6 +5929,20 @@ class ConstructDynamicRangePointerType :
59175929 Expr *EndPtr = DRPT->getEndPointer ();
59185930 auto EndPtrDecls = DRPT->getEndPtrDecls ();
59195931 assert (EndPtr);
5932+ if (auto OldEndPtr = T->getEndPointer ()) {
5933+ assert (AllowRedecl);
5934+ llvm::FoldingSetNodeID NewID;
5935+ llvm::FoldingSetNodeID OldID;
5936+ EndPtr->Profile (NewID, S.Context , /* Canonical*/ true );
5937+ OldEndPtr->Profile (OldID, S.Context , /* Canonical*/ true );
5938+
5939+ if (NewID != OldID) {
5940+ S.Diag (Loc, diag::err_bounds_safety_conflicting_pointer_attributes)
5941+ << /* pointer */ 1 << /* end */ 3 ;
5942+ ConstructedType = nullptr ;
5943+ return QualType ();
5944+ }
5945+ }
59205946
59215947 // ConstructType was already set while visiting the nested PointerType.
59225948 // Reconstruct DRPT by merging started_by and ended_by.
@@ -6383,7 +6409,8 @@ diagnoseRangeDependentDecls(Sema &S, const ValueDecl *TheDepender,
63836409void Sema::applyPtrCountedByEndedByAttr (Decl *D, unsigned Level,
63846410 AttributeCommonInfo::Kind Kind,
63856411 Expr *AttrArg, SourceLocation Loc,
6386- SourceRange Range, StringRef DiagName) {
6412+ SourceRange Range, StringRef DiagName,
6413+ bool OriginatesInAPINotes) {
63876414 // If the decl is invalid, the indirection Level might not exist in the type,
63886415 // since the type may have not been constructed correctly. Example:
63896416 // 'int (*param)[__counted_by_or_null(10)][]'
@@ -6571,13 +6598,15 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
65716598 }
65726599
65736600 auto TypeConstructor = ConstructDynamicRangePointerType (
6574- *this , Level, DiagName, AttrArg, Loc, ScopeCheck, StartPtrInfo);
6601+ *this , Level, DiagName, AttrArg, Loc, OriginatesInAPINotes, ScopeCheck,
6602+ StartPtrInfo);
65756603 NewDeclTy = TypeConstructor.Visit (DeclTy);
65766604 HadAtomicError = TypeConstructor.hadAtomicError ();
65776605 ConstructedType = TypeConstructor.getConstructedType ();
65786606 } else {
65796607 auto TypeConstructor = ConstructCountAttributedType (
6580- *this , Level, DiagName, AttrArg, Loc, CountInBytes, OrNull, ScopeCheck);
6608+ *this , Level, DiagName, AttrArg, Loc, CountInBytes, OrNull,
6609+ OriginatesInAPINotes, ScopeCheck);
65816610 NewDeclTy = TypeConstructor.Visit (DeclTy);
65826611 HadAtomicError = TypeConstructor.hadAtomicError ();
65836612 ConstructedType = TypeConstructor.getConstructedType ();
0 commit comments