@@ -5411,16 +5411,17 @@ class ConstructDynamicBoundType
5411
5411
const BoundsAttributedType *ConstructedType = nullptr ;
5412
5412
unsigned Level;
5413
5413
bool ScopeCheck;
5414
+ bool AllowRedecl;
5414
5415
bool AutoPtrAttributed = false ;
5415
- bool AllowCountRedecl = false ;
5416
5416
bool AtomicErrorEmitted = false ;
5417
5417
5418
5418
public:
5419
5419
explicit ConstructDynamicBoundType (Sema &S, unsigned Level,
5420
5420
const StringRef DiagName, Expr *ArgExpr,
5421
- SourceLocation Loc, bool ScopeCheck)
5421
+ SourceLocation Loc, bool ScopeCheck,
5422
+ bool AllowRedecl)
5422
5423
: S(S), DiagName(DiagName), ArgExpr(ArgExpr), Loc(Loc), Level(Level),
5423
- ScopeCheck(ScopeCheck) {}
5424
+ ScopeCheck(ScopeCheck), AllowRedecl(AllowRedecl) {}
5424
5425
5425
5426
QualType Visit (QualType T) {
5426
5427
SplitQualType SQT = T.split ();
@@ -5449,7 +5450,6 @@ class ConstructDynamicBoundType
5449
5450
5450
5451
QualType VisitFunctionProtoType (const FunctionProtoType *FPT) {
5451
5452
// The attribute applies to the return type.
5452
- SaveAndRestore<bool > AllowCountRedeclLocal (AllowCountRedecl, true );
5453
5453
QualType QT = Visit (FPT->getReturnType ());
5454
5454
if (QT.isNull ())
5455
5455
return QualType ();
@@ -5461,7 +5461,6 @@ class ConstructDynamicBoundType
5461
5461
5462
5462
QualType VisitFunctionNoProtoType (const FunctionNoProtoType *FPT) {
5463
5463
// The attribute applies to the return type.
5464
- SaveAndRestore<bool > AllowCountRedeclLocal (AllowCountRedecl, true );
5465
5464
QualType QT = Visit (FPT->getReturnType ());
5466
5465
if (QT.isNull ())
5467
5466
return QualType ();
@@ -5592,8 +5591,10 @@ class ConstructCountAttributedType :
5592
5591
explicit ConstructCountAttributedType (Sema &S, unsigned Level,
5593
5592
const StringRef DiagName, Expr *ArgExpr,
5594
5593
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),
5597
5598
CountInBytes(CountInBytes), OrNull(OrNull) {
5598
5599
if (!ArgExpr->getType ()->isIntegralOrEnumerationType ()) {
5599
5600
S.Diag (Loc, diag::err_attribute_argument_type_for_bounds_safety_count)
@@ -5661,7 +5662,7 @@ class ConstructCountAttributedType :
5661
5662
}
5662
5663
5663
5664
QualType DiagnoseConflictingType (const CountAttributedType *T) {
5664
- if (AllowCountRedecl ) {
5665
+ if (AllowRedecl ) {
5665
5666
QualType NewTy = BuildDynamicBoundType (T->desugar ());
5666
5667
const auto *NewDCPTy = NewTy->getAs <CountAttributedType>();
5667
5668
// We don't have a way to distinguish if '__counted_by' is conflicting or has been
@@ -5684,6 +5685,16 @@ class ConstructCountAttributedType :
5684
5685
return QualType ();
5685
5686
}
5686
5687
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
+
5687
5698
QualType DiagnoseConflictingType (const DynamicRangePointerType *T) {
5688
5699
S.Diag (Loc, diag::err_bounds_safety_conflicting_count_range_attributes);
5689
5700
return QualType ();
@@ -5858,9 +5869,10 @@ class ConstructDynamicRangePointerType :
5858
5869
public:
5859
5870
explicit ConstructDynamicRangePointerType (
5860
5871
Sema &S, unsigned Level, const StringRef DiagName, Expr *ArgExpr,
5861
- SourceLocation Loc, bool ScopeCheck = false ,
5872
+ SourceLocation Loc, bool AllowRedecl, bool ScopeCheck = false ,
5862
5873
std::optional<TypeCoupledDeclRefInfo> StartPtrInfo = std::nullopt)
5863
- : ConstructDynamicBoundType(S, Level, DiagName, ArgExpr, Loc, ScopeCheck),
5874
+ : ConstructDynamicBoundType(S, Level, DiagName, ArgExpr, Loc, ScopeCheck,
5875
+ AllowRedecl),
5864
5876
StartPtrInfo(StartPtrInfo) {
5865
5877
assert (ArgExpr->getType ()->isPointerType ());
5866
5878
}
@@ -5900,11 +5912,11 @@ class ConstructDynamicRangePointerType :
5900
5912
}
5901
5913
5902
5914
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.
5905
5917
Expr *StartPtr = T->getStartPointer ();
5906
5918
auto StartPtrDecls = T->getStartPtrDecls ();
5907
- assert (StartPtr);
5919
+ assert (StartPtr || AllowRedecl );
5908
5920
5909
5921
assert (ConstructedType == nullptr );
5910
5922
// Construct an ended_by() pointer type.
@@ -5917,6 +5929,20 @@ class ConstructDynamicRangePointerType :
5917
5929
Expr *EndPtr = DRPT->getEndPointer ();
5918
5930
auto EndPtrDecls = DRPT->getEndPtrDecls ();
5919
5931
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
+ }
5920
5946
5921
5947
// ConstructType was already set while visiting the nested PointerType.
5922
5948
// Reconstruct DRPT by merging started_by and ended_by.
@@ -6383,7 +6409,8 @@ diagnoseRangeDependentDecls(Sema &S, const ValueDecl *TheDepender,
6383
6409
void Sema::applyPtrCountedByEndedByAttr (Decl *D, unsigned Level,
6384
6410
AttributeCommonInfo::Kind Kind,
6385
6411
Expr *AttrArg, SourceLocation Loc,
6386
- SourceRange Range, StringRef DiagName) {
6412
+ SourceRange Range, StringRef DiagName,
6413
+ bool OriginatesInAPINotes) {
6387
6414
// If the decl is invalid, the indirection Level might not exist in the type,
6388
6415
// since the type may have not been constructed correctly. Example:
6389
6416
// 'int (*param)[__counted_by_or_null(10)][]'
@@ -6571,13 +6598,15 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6571
6598
}
6572
6599
6573
6600
auto TypeConstructor = ConstructDynamicRangePointerType (
6574
- *this , Level, DiagName, AttrArg, Loc, ScopeCheck, StartPtrInfo);
6601
+ *this , Level, DiagName, AttrArg, Loc, OriginatesInAPINotes, ScopeCheck,
6602
+ StartPtrInfo);
6575
6603
NewDeclTy = TypeConstructor.Visit (DeclTy);
6576
6604
HadAtomicError = TypeConstructor.hadAtomicError ();
6577
6605
ConstructedType = TypeConstructor.getConstructedType ();
6578
6606
} else {
6579
6607
auto TypeConstructor = ConstructCountAttributedType (
6580
- *this , Level, DiagName, AttrArg, Loc, CountInBytes, OrNull, ScopeCheck);
6608
+ *this , Level, DiagName, AttrArg, Loc, CountInBytes, OrNull,
6609
+ OriginatesInAPINotes, ScopeCheck);
6581
6610
NewDeclTy = TypeConstructor.Visit (DeclTy);
6582
6611
HadAtomicError = TypeConstructor.hadAtomicError ();
6583
6612
ConstructedType = TypeConstructor.getConstructedType ();
0 commit comments