10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
+ #include " DynamicCountPointerAssignmentAnalysis.h"
14
+ #include " TreeTransform.h"
13
15
#include " clang/AST/ASTConsumer.h"
14
16
#include " clang/AST/ASTContext.h"
15
17
#include " clang/AST/ASTMutationListener.h"
72
74
#include " llvm/Support/MathExtras.h"
73
75
#include " llvm/Support/raw_ostream.h"
74
76
#include " llvm/TargetParser/Triple.h"
75
- #include " TreeTransform.h"
76
- #include " DynamicCountPointerAssignmentAnalysis.h"
77
77
#include < optional>
78
78
79
79
using namespace clang ;
@@ -6141,6 +6141,66 @@ static bool CheckArgLifetimeAndScope(
6141
6141
return Invalid;
6142
6142
}
6143
6143
6144
+ static BoundsAttributedType::BoundsAttrKind
6145
+ getBoundsAttrKind (AttributeCommonInfo::Kind Kind) {
6146
+ switch (Kind) {
6147
+ case ParsedAttr::AT_SizedBy:
6148
+ return BoundsAttributedType::SizedBy;
6149
+ case ParsedAttr::AT_SizedByOrNull:
6150
+ return BoundsAttributedType::SizedByOrNull;
6151
+ case ParsedAttr::AT_CountedBy:
6152
+ return BoundsAttributedType::CountedBy;
6153
+ case ParsedAttr::AT_CountedByOrNull:
6154
+ return BoundsAttributedType::CountedByOrNull;
6155
+ case ParsedAttr::AT_PtrEndedBy:
6156
+ return BoundsAttributedType::EndedBy;
6157
+ default :
6158
+ llvm_unreachable (" unexpected bounds attribute" );
6159
+ }
6160
+ }
6161
+
6162
+ class EarlyLifetimeAndScopeCheck
6163
+ : public RecursiveASTVisitor<EarlyLifetimeAndScopeCheck> {
6164
+ Sema &SemaRef;
6165
+ bool ScopeCheck;
6166
+ Sema::LifetimeCheckKind LifetimeCheck;
6167
+ BoundsAttributedType::BoundsAttrKind AttrKind;
6168
+ bool IsArrayType;
6169
+ bool HadError = false ;
6170
+ llvm::SmallPtrSet<Decl *, 16 > Visited;
6171
+
6172
+ public:
6173
+ EarlyLifetimeAndScopeCheck (Sema &S, bool SC, Sema::LifetimeCheckKind LC,
6174
+ AttributeCommonInfo::Kind AK, bool IsArray)
6175
+ : SemaRef(S), ScopeCheck(SC), LifetimeCheck(LC),
6176
+ AttrKind (getBoundsAttrKind(AK)), IsArrayType(IsArray) {}
6177
+
6178
+ bool VisitDeclRefExpr (DeclRefExpr *E) {
6179
+ ValueDecl *VD = E->getDecl ();
6180
+ 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 ;
6187
+ }
6188
+
6189
+ bool VisitMemberExpr (MemberExpr *E) {
6190
+ TraverseStmt (E->getBase ());
6191
+ ValueDecl *VD = E->getMemberDecl ();
6192
+ bool IsNewVD = Visited.insert (VD).second ;
6193
+ if (IsNewVD) {
6194
+ HadError |=
6195
+ CheckArgLifetimeAndScope (SemaRef, VD, E->getExprLoc (), ScopeCheck,
6196
+ LifetimeCheck, AttrKind, IsArrayType);
6197
+ }
6198
+ return true ;
6199
+ }
6200
+
6201
+ bool hadError () { return HadError; }
6202
+ };
6203
+
6144
6204
static bool diagnoseBoundsAttrLifetimeAndScope (
6145
6205
Sema &SemaRef, const BoundsAttributedType *Ty, bool ScopeCheck,
6146
6206
Sema::LifetimeCheckKind LifetimeCheck) {
@@ -6383,11 +6443,35 @@ diagnoseRangeDependentDecls(Sema &S, const ValueDecl *TheDepender,
6383
6443
return HadError;
6384
6444
}
6385
6445
6446
+ class DynamicBoundsAttrInfo {
6447
+ public:
6448
+ QualType Ty;
6449
+ unsigned EffectiveLevel;
6450
+ bool IsFPtr;
6451
+
6452
+ DynamicBoundsAttrInfo (QualType DeclTy, unsigned Level) {
6453
+ IsFPtr = false ;
6454
+ EffectiveLevel = Level;
6455
+ Ty = DeclTy;
6456
+ for (unsigned i = 0 ; i != Level; ++i) {
6457
+ if (!Ty->isPointerType ())
6458
+ break ;
6459
+ Ty = Ty->getPointeeType ();
6460
+ if (Ty->isFunctionType ()) {
6461
+ IsFPtr = true ;
6462
+ EffectiveLevel = Level - i - 1 ;
6463
+ break ;
6464
+ }
6465
+ }
6466
+ }
6467
+ };
6468
+
6386
6469
void Sema::applyPtrCountedByEndedByAttr (Decl *D, unsigned Level,
6387
6470
AttributeCommonInfo::Kind Kind,
6388
6471
Expr *AttrArg, SourceLocation Loc,
6389
6472
SourceRange Range, StringRef DiagName,
6390
- bool OriginatesInAPINotes) {
6473
+ bool OriginatesInAPINotes,
6474
+ bool InInstantiatedTemplate) {
6391
6475
// If the decl is invalid, the indirection Level might not exist in the type,
6392
6476
// since the type may have not been constructed correctly. Example:
6393
6477
// 'int (*param)[__counted_by_or_null(10)][]'
@@ -6401,22 +6485,10 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6401
6485
auto *Var = dyn_cast<VarDecl>(D);
6402
6486
QualType DeclTy = TND ? TND->getUnderlyingType () : VD->getType ();
6403
6487
6404
- bool IsFPtr = false ;
6405
- unsigned EffectiveLevel = Level;
6406
- QualType Ty = DeclTy;
6407
- for (unsigned i = 0 ; i != Level; ++i) {
6408
- if (!Ty->isPointerType ())
6409
- break ;
6410
- Ty = Ty->getPointeeType ();
6411
- if (Ty->isFunctionType ()) {
6412
- IsFPtr = true ;
6413
- EffectiveLevel = Level - i - 1 ;
6414
- break ;
6415
- }
6416
- }
6488
+ DynamicBoundsAttrInfo Info (DeclTy, Level);
6417
6489
6418
6490
// Don't allow typedefs with __counted_by on non-function types.
6419
- if (TND && (!DeclTy->isFunctionType () && !IsFPtr)) {
6491
+ if (TND && (!DeclTy->isFunctionType () && !Info. IsFPtr )) {
6420
6492
Diag (Loc, diag::err_bounds_safety_typedef_dynamic_bound) << DiagName;
6421
6493
return ;
6422
6494
}
@@ -6490,7 +6562,7 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6490
6562
return ;
6491
6563
}
6492
6564
6493
- if (EffectiveLevel != 0 &&
6565
+ if (Info. EffectiveLevel != 0 &&
6494
6566
(!isa<ParmVarDecl>(VD) || DeclTy->isBoundsAttributedType ())) {
6495
6567
Diag (Loc, diag::err_bounds_safety_nested_dynamic_bound) << DiagName;
6496
6568
return ;
@@ -6519,14 +6591,14 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6519
6591
}
6520
6592
}
6521
6593
6522
- if (Ty->isArrayType () && OrNull &&
6523
- (FD || EffectiveLevel > 0 || (Var && Var->hasExternalStorage ()))) {
6594
+ if (Info. Ty ->isArrayType () && OrNull &&
6595
+ (FD || Info. EffectiveLevel > 0 || (Var && Var->hasExternalStorage ()))) {
6524
6596
auto ErrDiag = Diag (Loc, diag::err_bounds_safety_nullable_fam);
6525
6597
// Pointers to dynamic count types are only allowed for parameters, so any
6526
6598
// FieldDecl containing a dynamic count type is a FAM. I.e. a struct field
6527
6599
// with type 'int(*)[__counted_by(...)]' is not valid.
6528
6600
ErrDiag << CountInBytes << /* is FAM?*/ !!FD << DiagName;
6529
- assert (!FD || EffectiveLevel == 0 );
6601
+ assert (!FD || Info. EffectiveLevel == 0 );
6530
6602
6531
6603
SourceLocation FixItLoc = getSourceManager ().getExpansionLoc (Loc);
6532
6604
SourceLocation EndLoc =
@@ -6538,19 +6610,19 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6538
6610
return ;
6539
6611
}
6540
6612
6541
- if (Ty->isArrayType () && EffectiveLevel > 0 ) {
6613
+ if (Info. Ty ->isArrayType () && Info. EffectiveLevel > 0 ) {
6542
6614
auto ErrDiag =
6543
6615
Diag (
6544
6616
Loc,
6545
6617
diag::
6546
6618
err_bounds_safety_unsupported_address_of_incomplete_array_type)
6547
- << Ty;
6619
+ << Info. Ty ;
6548
6620
// apply attribute anyways to avoid too misleading follow-up diagnostics
6549
6621
}
6550
6622
}
6551
6623
6552
6624
QualType NewDeclTy{};
6553
- bool ScopeCheck = (Var && Var->isLocalVarDecl ()) || IsFPtr;
6625
+ bool ScopeCheck = (Var && Var->isLocalVarDecl ()) || Info. IsFPtr ;
6554
6626
const BoundsAttributedType *ConstructedType = nullptr ;
6555
6627
6556
6628
bool HadAtomicError = false ;
@@ -6598,19 +6670,24 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6598
6670
// nested type, so `ConstructedType` can be different from `NewDeclTy`.
6599
6671
assert (ConstructedType);
6600
6672
6601
- auto LifetimeCheck =
6602
- IsFPtr ? Sema::LifetimeCheckKind::None : Sema::getLifetimeCheckKind (Var);
6603
- if (diagnoseBoundsAttrLifetimeAndScope (*this , ConstructedType, ScopeCheck,
6673
+ auto LifetimeCheck = Info.IsFPtr ? Sema::LifetimeCheckKind::None
6674
+ : Sema::getLifetimeCheckKind (Var);
6675
+ // Scope information is not available after template instantiation, so this
6676
+ // check has been performed earlier if this is a template instantiation.
6677
+ if (!InInstantiatedTemplate &&
6678
+ diagnoseBoundsAttrLifetimeAndScope (*this , ConstructedType, ScopeCheck,
6604
6679
LifetimeCheck))
6605
6680
return ;
6606
6681
6607
6682
if (VD && !isa<FunctionDecl>(VD) && !HadAtomicError) {
6608
6683
if (const auto *BDTy = dyn_cast<CountAttributedType>(ConstructedType)) {
6609
- if (!diagnoseCountDependentDecls (*this , VD, BDTy, EffectiveLevel, IsFPtr))
6610
- AttachDependerDeclsAttr (VD, BDTy, EffectiveLevel);
6684
+ if (!diagnoseCountDependentDecls (*this , VD, BDTy, Info.EffectiveLevel ,
6685
+ Info.IsFPtr ))
6686
+ AttachDependerDeclsAttr (VD, BDTy, Info.EffectiveLevel );
6611
6687
} else if (const auto *BDTy =
6612
6688
dyn_cast<DynamicRangePointerType>(ConstructedType)) {
6613
- diagnoseRangeDependentDecls (*this , VD, BDTy, EffectiveLevel, IsFPtr);
6689
+ diagnoseRangeDependentDecls (*this , VD, BDTy, Info.EffectiveLevel ,
6690
+ Info.IsFPtr );
6614
6691
} else {
6615
6692
llvm_unreachable (" Unexpected bounds attributed type" );
6616
6693
}
@@ -6635,11 +6712,54 @@ void Sema::applyPtrCountedByEndedByAttr(Decl *D, unsigned Level,
6635
6712
}
6636
6713
}
6637
6714
6715
+ static void attachLateInstantiatedCountedByEndedByAttr (Sema &S, Decl *D,
6716
+ const ParsedAttr &AL,
6717
+ int Level) {
6718
+ #define ADD_ATTR (Kind ) \
6719
+ case ParsedAttr::AT_##Kind: \
6720
+ D->addAttr (::new (S.Context ) \
6721
+ Kind##Attr (S.Context , AL, AL.getArgAsExpr (0 ), Level)); \
6722
+ break ;
6723
+
6724
+ switch (AL.getKind ()) {
6725
+ ADD_ATTR (SizedBy)
6726
+ ADD_ATTR (SizedByOrNull)
6727
+ ADD_ATTR (CountedBy)
6728
+ ADD_ATTR (CountedByOrNull)
6729
+ ADD_ATTR (PtrEndedBy)
6730
+ default :
6731
+ llvm_unreachable (" Invalid dynamic bound attribute" );
6732
+ }
6733
+ #undef ADD_ATTR
6734
+ }
6735
+
6638
6736
static void handlePtrCountedByEndedByAttr (Sema &S, Decl *D,
6639
6737
const ParsedAttr &AL) {
6640
6738
unsigned Level;
6641
6739
if (!S.checkUInt32Argument (AL, AL.getArgAsExpr (1 ), Level))
6642
6740
return ;
6741
+
6742
+ 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);
6748
+ // Scope information will be invalid by the time we instantiate the
6749
+ // template, so perform these checks now and delay the rest of the
6750
+ // 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 ())
6758
+ return ;
6759
+ attachLateInstantiatedCountedByEndedByAttr (S, D, AL, Level);
6760
+ return ;
6761
+ }
6762
+
6643
6763
AttributeCommonInfo::Kind Kind = AL.getKind ();
6644
6764
const IdentifierInfo *AttrName =
6645
6765
AL.printAsMacro () ? AL.getMacroIdentifier () : AL.getAttrName ();
0 commit comments