24
24
#include " clang/AST/ExprCXX.h"
25
25
#include " clang/AST/Mangle.h"
26
26
#include " clang/AST/RecursiveASTVisitor.h"
27
+ #include " clang/AST/StmtVisitor.h"
27
28
#include " clang/AST/Type.h"
28
29
#include " clang/AST/TypeVisitor.h"
29
30
#include " clang/Basic/CharInfo.h"
@@ -6160,13 +6161,12 @@ getBoundsAttrKind(AttributeCommonInfo::Kind Kind) {
6160
6161
}
6161
6162
6162
6163
class EarlyLifetimeAndScopeCheck
6163
- : public RecursiveASTVisitor <EarlyLifetimeAndScopeCheck> {
6164
+ : public StmtVisitor <EarlyLifetimeAndScopeCheck, bool > {
6164
6165
Sema &SemaRef;
6165
6166
bool ScopeCheck;
6166
6167
Sema::LifetimeCheckKind LifetimeCheck;
6167
6168
BoundsAttributedType::BoundsAttrKind AttrKind;
6168
6169
bool IsArrayType;
6169
- bool HadError = false ;
6170
6170
llvm::SmallPtrSet<Decl *, 16 > Visited;
6171
6171
6172
6172
public:
@@ -6175,30 +6175,32 @@ class EarlyLifetimeAndScopeCheck
6175
6175
: SemaRef(S), ScopeCheck(SC), LifetimeCheck(LC),
6176
6176
AttrKind (getBoundsAttrKind(AK)), IsArrayType(IsArray) {}
6177
6177
6178
+ bool VisitStmt (Stmt *S) {
6179
+ bool HadError = false ;
6180
+ for (auto Child : S->children ())
6181
+ HadError |= Visit (Child);
6182
+ return HadError;
6183
+ }
6184
+
6178
6185
bool VisitDeclRefExpr (DeclRefExpr *E) {
6179
6186
ValueDecl *VD = E->getDecl ();
6180
6187
bool IsNewVD = Visited.insert (VD).second ;
6181
- if (IsNewVD) {
6182
- HadError |=
6183
- CheckArgLifetimeAndScope (SemaRef, VD, E->getExprLoc (), ScopeCheck,
6184
- LifetimeCheck, AttrKind, IsArrayType);
6185
- }
6186
- return true ;
6188
+ return IsNewVD &&
6189
+ CheckArgLifetimeAndScope (SemaRef, VD, E->getExprLoc (), ScopeCheck,
6190
+ LifetimeCheck, AttrKind, IsArrayType);
6187
6191
}
6188
6192
6189
6193
bool VisitMemberExpr (MemberExpr *E) {
6190
- TraverseStmt (E->getBase ());
6194
+ bool HadError = Visit (E->getBase ());
6191
6195
ValueDecl *VD = E->getMemberDecl ();
6192
6196
bool IsNewVD = Visited.insert (VD).second ;
6193
6197
if (IsNewVD) {
6194
6198
HadError |=
6195
6199
CheckArgLifetimeAndScope (SemaRef, VD, E->getExprLoc (), ScopeCheck,
6196
6200
LifetimeCheck, AttrKind, IsArrayType);
6197
6201
}
6198
- return true ;
6202
+ return HadError ;
6199
6203
}
6200
-
6201
- bool hadError () { return HadError; }
6202
6204
};
6203
6205
6204
6206
static bool diagnoseBoundsAttrLifetimeAndScope (
@@ -6443,13 +6445,24 @@ diagnoseRangeDependentDecls(Sema &S, const ValueDecl *TheDepender,
6443
6445
return HadError;
6444
6446
}
6445
6447
6448
+ namespace {
6446
6449
class DynamicBoundsAttrInfo {
6447
6450
public:
6451
+ TypedefNameDecl *TND;
6452
+ ValueDecl *VD;
6453
+ VarDecl *Var;
6454
+ QualType DeclTy;
6448
6455
QualType Ty;
6449
6456
unsigned EffectiveLevel;
6450
6457
bool IsFPtr;
6458
+ Sema::LifetimeCheckKind LifetimeCheck = Sema::LifetimeCheckKind::None;
6459
+ bool ScopeCheck;
6451
6460
6452
- DynamicBoundsAttrInfo (QualType DeclTy, unsigned Level) {
6461
+ DynamicBoundsAttrInfo (Decl *D, unsigned Level) {
6462
+ TND = dyn_cast<TypedefNameDecl>(D);
6463
+ VD = dyn_cast<ValueDecl>(D);
6464
+ Var = dyn_cast<VarDecl>(D);
6465
+ DeclTy = TND ? TND->getUnderlyingType () : VD->getType ();
6453
6466
IsFPtr = false ;
6454
6467
EffectiveLevel = Level;
6455
6468
Ty = DeclTy;
@@ -6463,8 +6476,12 @@ class DynamicBoundsAttrInfo {
6463
6476
break ;
6464
6477
}
6465
6478
}
6479
+ if (!IsFPtr)
6480
+ LifetimeCheck = Sema::getLifetimeCheckKind (Var);
6481
+ ScopeCheck = (Var && Var->isLocalVarDecl ()) || IsFPtr;
6466
6482
}
6467
6483
};
6484
+ } // namespace
6468
6485
6469
6486
void Sema::applyPtrCountedByEndedByAttr (Decl *D, unsigned Level,
6470
6487
AttributeCommonInfo::Kind Kind,
@@ -6480,15 +6497,10 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6480
6497
if (D->isInvalidDecl ())
6481
6498
return ;
6482
6499
6483
- auto *TND = dyn_cast<TypedefNameDecl>(D);
6484
- auto *VD = dyn_cast<ValueDecl>(D);
6485
- auto *Var = dyn_cast<VarDecl>(D);
6486
- QualType DeclTy = TND ? TND->getUnderlyingType () : VD->getType ();
6487
-
6488
- DynamicBoundsAttrInfo Info (DeclTy, Level);
6500
+ DynamicBoundsAttrInfo Info (D, Level);
6489
6501
6490
6502
// Don't allow typedefs with __counted_by on non-function types.
6491
- if (TND && (!DeclTy->isFunctionType () && !Info.IsFPtr )) {
6503
+ if (Info. TND && (!Info. DeclTy ->isFunctionType () && !Info.IsFPtr )) {
6492
6504
Diag (Loc, diag::err_bounds_safety_typedef_dynamic_bound) << DiagName;
6493
6505
return ;
6494
6506
}
@@ -6519,7 +6531,8 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6519
6531
if (!IsEndedBy) {
6520
6532
// Nullability as indicated by _Nonnull or _Nullable. Does not impact
6521
6533
// semantics, only warnings.
6522
- std::optional<NullabilityKind> AttrNullability = DeclTy->getNullability ();
6534
+ std::optional<NullabilityKind> AttrNullability =
6535
+ Info.DeclTy ->getNullability ();
6523
6536
if (OrNull) {
6524
6537
// Function parameter/return value attribute that *does* impact semantics,
6525
6538
// letting the compiler elide null checks. This could remove bounds safety
@@ -6554,16 +6567,16 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6554
6567
}
6555
6568
}
6556
6569
6557
- if (VD) {
6558
- const auto *FD = dyn_cast<FieldDecl>(VD);
6570
+ if (Info. VD ) {
6571
+ const auto *FD = dyn_cast<FieldDecl>(Info. VD );
6559
6572
if (FD && FD->getParent ()->isUnion ()) {
6560
6573
Diag (Loc, diag::err_invalid_decl_kind_bounds_safety_union_count)
6561
6574
<< DiagName;
6562
6575
return ;
6563
6576
}
6564
6577
6565
6578
if (Info.EffectiveLevel != 0 &&
6566
- (!isa<ParmVarDecl>(VD) || DeclTy->isBoundsAttributedType ())) {
6579
+ (!isa<ParmVarDecl>(Info. VD ) || Info. DeclTy ->isBoundsAttributedType ())) {
6567
6580
Diag (Loc, diag::err_bounds_safety_nested_dynamic_bound) << DiagName;
6568
6581
return ;
6569
6582
}
@@ -6574,7 +6587,7 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6574
6587
// case of ConstructCountAttributedType, which complains that the type
6575
6588
// has two count attributes. See if we can produce a better diagnostic here
6576
6589
// instead.
6577
- if (const auto *PVD = dyn_cast_or_null<ParmVarDecl>(Var)) {
6590
+ if (const auto *PVD = dyn_cast_or_null<ParmVarDecl>(Info. Var )) {
6578
6591
QualType TSITy = PVD->getTypeSourceInfo ()->getType ();
6579
6592
if (IsEndedBy) {
6580
6593
if (Level == 0 && TSITy->isArrayType ()) {
@@ -6592,7 +6605,8 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6592
6605
}
6593
6606
6594
6607
if (Info.Ty ->isArrayType () && OrNull &&
6595
- (FD || Info.EffectiveLevel > 0 || (Var && Var->hasExternalStorage ()))) {
6608
+ (FD || Info.EffectiveLevel > 0 ||
6609
+ (Info.Var && Info.Var ->hasExternalStorage ()))) {
6596
6610
auto ErrDiag = Diag (Loc, diag::err_bounds_safety_nullable_fam);
6597
6611
// Pointers to dynamic count types are only allowed for parameters, so any
6598
6612
// FieldDecl containing a dynamic count type is a FAM. I.e. a struct field
@@ -6622,7 +6636,6 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6622
6636
}
6623
6637
6624
6638
QualType NewDeclTy{};
6625
- bool ScopeCheck = (Var && Var->isLocalVarDecl ()) || Info.IsFPtr ;
6626
6639
const BoundsAttributedType *ConstructedType = nullptr ;
6627
6640
6628
6641
bool HadAtomicError = false ;
@@ -6641,22 +6654,22 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6641
6654
// Make started_by() pointers if VD is a field or variable. We don't want to
6642
6655
// create started_by(X) pointers where X is a function etc.
6643
6656
std::optional<TypeCoupledDeclRefInfo> StartPtrInfo;
6644
- if (VD && (isa<FieldDecl>(VD) || isa<VarDecl>(VD))) {
6657
+ if (Info. VD && (isa<FieldDecl>(Info. VD ) || isa<VarDecl>(Info. VD ))) {
6645
6658
assert (Level <= 1 );
6646
- StartPtrInfo = TypeCoupledDeclRefInfo (VD, /* Deref=*/ Level != 0 );
6659
+ StartPtrInfo = TypeCoupledDeclRefInfo (Info. VD , /* Deref=*/ Level != 0 );
6647
6660
}
6648
6661
6649
6662
auto TypeConstructor = ConstructDynamicRangePointerType (
6650
- *this , Level, DiagName, AttrArg, Loc, OriginatesInAPINotes, ScopeCheck,
6651
- StartPtrInfo);
6652
- NewDeclTy = TypeConstructor.Visit (DeclTy);
6663
+ *this , Level, DiagName, AttrArg, Loc, OriginatesInAPINotes,
6664
+ Info. ScopeCheck , StartPtrInfo);
6665
+ NewDeclTy = TypeConstructor.Visit (Info. DeclTy );
6653
6666
HadAtomicError = TypeConstructor.hadAtomicError ();
6654
6667
ConstructedType = TypeConstructor.getConstructedType ();
6655
6668
} else {
6656
6669
auto TypeConstructor = ConstructCountAttributedType (
6657
6670
*this , Level, DiagName, AttrArg, Loc, CountInBytes, OrNull,
6658
- OriginatesInAPINotes, ScopeCheck);
6659
- NewDeclTy = TypeConstructor.Visit (DeclTy);
6671
+ OriginatesInAPINotes, Info. ScopeCheck );
6672
+ NewDeclTy = TypeConstructor.Visit (Info. DeclTy );
6660
6673
HadAtomicError = TypeConstructor.hadAtomicError ();
6661
6674
ConstructedType = TypeConstructor.getConstructedType ();
6662
6675
}
@@ -6670,44 +6683,43 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6670
6683
// nested type, so `ConstructedType` can be different from `NewDeclTy`.
6671
6684
assert (ConstructedType);
6672
6685
6673
- auto LifetimeCheck = Info.IsFPtr ? Sema::LifetimeCheckKind::None
6674
- : Sema::getLifetimeCheckKind (Var);
6675
6686
// Scope information is not available after template instantiation, so this
6676
6687
// check has been performed earlier if this is a template instantiation.
6677
6688
if (!InInstantiatedTemplate &&
6678
- diagnoseBoundsAttrLifetimeAndScope (*this , ConstructedType, ScopeCheck,
6679
- LifetimeCheck))
6689
+ diagnoseBoundsAttrLifetimeAndScope (*this , ConstructedType,
6690
+ Info. ScopeCheck , Info. LifetimeCheck ))
6680
6691
return ;
6681
6692
6682
- if (VD && !isa<FunctionDecl>(VD) && !HadAtomicError) {
6693
+ if (Info. VD && !isa<FunctionDecl>(Info. VD ) && !HadAtomicError) {
6683
6694
if (const auto *BDTy = dyn_cast<CountAttributedType>(ConstructedType)) {
6684
- if (!diagnoseCountDependentDecls (*this , VD, BDTy, Info. EffectiveLevel ,
6685
- Info.IsFPtr ))
6686
- AttachDependerDeclsAttr (VD, BDTy, Info.EffectiveLevel );
6695
+ if (!diagnoseCountDependentDecls (*this , Info. VD , BDTy,
6696
+ Info.EffectiveLevel , Info. IsFPtr ))
6697
+ AttachDependerDeclsAttr (Info. VD , BDTy, Info.EffectiveLevel );
6687
6698
} else if (const auto *BDTy =
6688
6699
dyn_cast<DynamicRangePointerType>(ConstructedType)) {
6689
- diagnoseRangeDependentDecls (*this , VD, BDTy, Info.EffectiveLevel ,
6700
+ diagnoseRangeDependentDecls (*this , Info. VD , BDTy, Info.EffectiveLevel ,
6690
6701
Info.IsFPtr );
6691
6702
} else {
6692
6703
llvm_unreachable (" Unexpected bounds attributed type" );
6693
6704
}
6694
6705
}
6695
6706
6696
- if (TND) {
6707
+ if (Info. TND ) {
6697
6708
// We need to create a TypeSourceInfo, as TypedefNameDecl is not a ValueDecl
6698
6709
// and thus doesn't have setType() method.
6699
- SourceLocation Loc = TND->getTypeSourceInfo ()->getTypeLoc ().getBeginLoc ();
6700
- TypeSourceInfo *Info = Context.getTrivialTypeSourceInfo (NewDeclTy, Loc);
6701
- TND->setTypeSourceInfo (Info);
6710
+ SourceLocation Loc =
6711
+ Info.TND ->getTypeSourceInfo ()->getTypeLoc ().getBeginLoc ();
6712
+ TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo (NewDeclTy, Loc);
6713
+ Info.TND ->setTypeSourceInfo (TSI);
6702
6714
} else {
6703
- VD->setType (NewDeclTy);
6715
+ Info. VD ->setType (NewDeclTy);
6704
6716
// Reconstruct implicit cast for initializer after variable type change.
6705
- if (Var && Var->hasInit ()) {
6706
- Expr *Init = Var->getInit ();
6717
+ if (Info. Var && Info. Var ->hasInit ()) {
6718
+ Expr *Init = Info. Var ->getInit ();
6707
6719
ExprResult Res = removeUnusedOVEs (*this , Init, Init->IgnoreImpCasts ());
6708
6720
if (Res.isInvalid ())
6709
6721
return ;
6710
- AddInitializerToDecl (Var, Res.get (), Var->isDirectInit ());
6722
+ AddInitializerToDecl (Info. Var , Res.get (), Info. Var ->isDirectInit ());
6711
6723
}
6712
6724
}
6713
6725
}
@@ -6740,21 +6752,14 @@ static void handlePtrCountedByEndedByAttr(Sema &S, Decl *D,
6740
6752
return ;
6741
6753
6742
6754
if (D->getDescribedTemplate () || S.CurContext ->isDependentContext ()) {
6743
- auto *TND = dyn_cast<TypedefNameDecl>(D);
6744
- auto *VD = dyn_cast<ValueDecl>(D);
6745
- auto *Var = dyn_cast<VarDecl>(D);
6746
- QualType DeclTy = TND ? TND->getUnderlyingType () : VD->getType ();
6747
- DynamicBoundsAttrInfo Info (DeclTy, Level);
6755
+ DynamicBoundsAttrInfo Info (D, Level);
6748
6756
// Scope information will be invalid by the time we instantiate the
6749
6757
// template, so perform these checks now and delay the rest of the
6750
6758
// processing until the point of instantiation.
6751
- auto LifetimeCheck = Info.IsFPtr ? Sema::LifetimeCheckKind::None
6752
- : Sema::getLifetimeCheckKind (Var);
6753
- bool ScopeCheck = (Var && Var->isLocalVarDecl ()) || Info.IsFPtr ;
6754
- EarlyLifetimeAndScopeCheck EarlyCheck (S, ScopeCheck, LifetimeCheck,
6755
- AL.getKind (), Info.Ty ->isArrayType ());
6756
- EarlyCheck.TraverseStmt (AL.getArgAsExpr (0 ));
6757
- if (EarlyCheck.hadError ())
6759
+ EarlyLifetimeAndScopeCheck EarlyCheck (S, Info.ScopeCheck ,
6760
+ Info.LifetimeCheck , AL.getKind (),
6761
+ Info.Ty ->isArrayType ());
6762
+ if (EarlyCheck.Visit (AL.getArgAsExpr (0 )))
6758
6763
return ;
6759
6764
attachLateInstantiatedCountedByEndedByAttr (S, D, AL, Level);
6760
6765
return ;
0 commit comments