@@ -7521,6 +7521,25 @@ static bool HandleWebAssemblyFuncrefAttr(TypeProcessingState &State,
7521
7521
return false ;
7522
7522
}
7523
7523
7524
+ // / Rebuild an attributed type without the nullability attribute on it.
7525
+ static QualType rebuildAttributedTypeWithoutNullability (ASTContext &Ctx,
7526
+ QualType Type) {
7527
+ auto Attributed = dyn_cast<AttributedType>(Type.getTypePtr ());
7528
+ if (!Attributed)
7529
+ return Type;
7530
+
7531
+ // Skip the nullability attribute; we're done.
7532
+ if (Attributed->getImmediateNullability ())
7533
+ return Attributed->getModifiedType ();
7534
+
7535
+ // Build the modified type.
7536
+ QualType Modified = rebuildAttributedTypeWithoutNullability (
7537
+ Ctx, Attributed->getModifiedType ());
7538
+ assert (Modified.getTypePtr () != Attributed->getModifiedType ().getTypePtr ());
7539
+ return Ctx.getAttributedType (Attributed->getAttrKind (), Modified,
7540
+ Attributed->getEquivalentType ());
7541
+ }
7542
+
7524
7543
// / Map a nullability attribute kind to a nullability kind.
7525
7544
static NullabilityKind mapNullabilityAttrKind (ParsedAttr::Kind kind) {
7526
7545
switch (kind) {
@@ -7541,74 +7560,65 @@ static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
7541
7560
}
7542
7561
}
7543
7562
7544
- // / Applies a nullability type specifier to the given type, if possible.
7545
- // /
7546
- // / \param state The type processing state.
7547
- // /
7548
- // / \param type The type to which the nullability specifier will be
7549
- // / added. On success, this type will be updated appropriately.
7550
- // /
7551
- // / \param attr The attribute as written on the type.
7552
- // /
7553
- // / \param allowOnArrayType Whether to accept nullability specifiers on an
7554
- // / array type (e.g., because it will decay to a pointer).
7555
- // /
7556
- // / \returns true if a problem has been diagnosed, false on success.
7557
- static bool checkNullabilityTypeSpecifier (TypeProcessingState &state,
7558
- QualType &type,
7559
- ParsedAttr &attr,
7560
- bool allowOnArrayType) {
7561
- Sema &S = state.getSema ();
7562
-
7563
- NullabilityKind nullability = mapNullabilityAttrKind (attr.getKind ());
7564
- SourceLocation nullabilityLoc = attr.getLoc ();
7565
- bool isContextSensitive = attr.isContextSensitiveKeywordAttribute ();
7566
-
7567
- recordNullabilitySeen (S, nullabilityLoc);
7563
+ static bool CheckNullabilityTypeSpecifier (
7564
+ Sema &S, TypeProcessingState *State, ParsedAttr *PAttr, QualType &QT,
7565
+ NullabilityKind Nullability, SourceLocation NullabilityLoc,
7566
+ bool IsContextSensitive, bool AllowOnArrayType, bool OverrideExisting) {
7567
+ bool Implicit = (State == nullptr );
7568
+ if (!Implicit)
7569
+ recordNullabilitySeen (S, NullabilityLoc);
7568
7570
7569
7571
// Check for existing nullability attributes on the type.
7570
- QualType desugared = type ;
7571
- while (auto attributed = dyn_cast<AttributedType>(desugared .getTypePtr ())) {
7572
+ QualType Desugared = QT ;
7573
+ while (auto *Attributed = dyn_cast<AttributedType>(Desugared .getTypePtr ())) {
7572
7574
// Check whether there is already a null
7573
- if (auto existingNullability = attributed ->getImmediateNullability ()) {
7575
+ if (auto ExistingNullability = Attributed ->getImmediateNullability ()) {
7574
7576
// Duplicated nullability.
7575
- if (nullability == *existingNullability) {
7576
- S.Diag (nullabilityLoc, diag::warn_nullability_duplicate)
7577
- << DiagNullabilityKind (nullability, isContextSensitive)
7578
- << FixItHint::CreateRemoval (nullabilityLoc);
7577
+ if (Nullability == *ExistingNullability) {
7578
+ if (Implicit)
7579
+ break ;
7580
+
7581
+ S.Diag (NullabilityLoc, diag::warn_nullability_duplicate)
7582
+ << DiagNullabilityKind (Nullability, IsContextSensitive)
7583
+ << FixItHint::CreateRemoval (NullabilityLoc);
7579
7584
7580
7585
break ;
7581
7586
}
7582
7587
7583
- // Conflicting nullability.
7584
- S.Diag (nullabilityLoc, diag::err_nullability_conflicting)
7585
- << DiagNullabilityKind (nullability, isContextSensitive)
7586
- << DiagNullabilityKind (*existingNullability, false );
7587
- return true ;
7588
+ if (!OverrideExisting) {
7589
+ // Conflicting nullability.
7590
+ S.Diag (NullabilityLoc, diag::err_nullability_conflicting)
7591
+ << DiagNullabilityKind (Nullability, IsContextSensitive)
7592
+ << DiagNullabilityKind (*ExistingNullability, false );
7593
+ return true ;
7594
+ }
7595
+
7596
+ // Rebuild the attributed type, dropping the existing nullability.
7597
+ QT = rebuildAttributedTypeWithoutNullability (S.Context , QT);
7588
7598
}
7589
7599
7590
- desugared = attributed ->getModifiedType ();
7600
+ Desugared = Attributed ->getModifiedType ();
7591
7601
}
7592
7602
7593
7603
// If there is already a different nullability specifier, complain.
7594
7604
// This (unlike the code above) looks through typedefs that might
7595
7605
// have nullability specifiers on them, which means we cannot
7596
7606
// provide a useful Fix-It.
7597
- if (auto existingNullability = desugared ->getNullability ()) {
7598
- if (nullability != *existingNullability ) {
7599
- S.Diag (nullabilityLoc , diag::err_nullability_conflicting)
7600
- << DiagNullabilityKind (nullability, isContextSensitive )
7601
- << DiagNullabilityKind (*existingNullability , false );
7607
+ if (auto ExistingNullability = Desugared ->getNullability ()) {
7608
+ if (Nullability != *ExistingNullability && !Implicit ) {
7609
+ S.Diag (NullabilityLoc , diag::err_nullability_conflicting)
7610
+ << DiagNullabilityKind (Nullability, IsContextSensitive )
7611
+ << DiagNullabilityKind (*ExistingNullability , false );
7602
7612
7603
7613
// Try to find the typedef with the existing nullability specifier.
7604
- if (auto typedefType = desugared ->getAs <TypedefType>()) {
7605
- TypedefNameDecl *typedefDecl = typedefType ->getDecl ();
7614
+ if (auto TT = Desugared ->getAs <TypedefType>()) {
7615
+ TypedefNameDecl *typedefDecl = TT ->getDecl ();
7606
7616
QualType underlyingType = typedefDecl->getUnderlyingType ();
7607
- if (auto typedefNullability
7608
- = AttributedType::stripOuterNullability (underlyingType)) {
7609
- if (*typedefNullability == *existingNullability ) {
7617
+ if (auto typedefNullability =
7618
+ AttributedType::stripOuterNullability (underlyingType)) {
7619
+ if (*typedefNullability == *ExistingNullability ) {
7610
7620
S.Diag (typedefDecl->getLocation (), diag::note_nullability_here)
7611
- << DiagNullabilityKind (*existingNullability , false );
7621
+ << DiagNullabilityKind (*ExistingNullability , false );
7612
7622
}
7613
7623
}
7614
7624
}
@@ -7618,44 +7628,73 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
7618
7628
}
7619
7629
7620
7630
// If this definitely isn't a pointer type, reject the specifier.
7621
- if (!desugared->canHaveNullability () &&
7622
- !(allowOnArrayType && desugared->isArrayType ())) {
7623
- S.Diag (nullabilityLoc, diag::err_nullability_nonpointer)
7624
- << DiagNullabilityKind (nullability, isContextSensitive) << type;
7631
+ if (!Desugared->canHaveNullability () &&
7632
+ !(AllowOnArrayType && Desugared->isArrayType ())) {
7633
+ if (!Implicit)
7634
+ S.Diag (NullabilityLoc, diag::err_nullability_nonpointer)
7635
+ << DiagNullabilityKind (Nullability, IsContextSensitive) << QT;
7636
+
7625
7637
return true ;
7626
7638
}
7627
7639
7628
7640
// For the context-sensitive keywords/Objective-C property
7629
7641
// attributes, require that the type be a single-level pointer.
7630
- if (isContextSensitive ) {
7642
+ if (IsContextSensitive ) {
7631
7643
// Make sure that the pointee isn't itself a pointer type.
7632
7644
const Type *pointeeType = nullptr ;
7633
- if (desugared ->isArrayType ())
7634
- pointeeType = desugared ->getArrayElementTypeNoTypeQual ();
7635
- else if (desugared ->isAnyPointerType ())
7636
- pointeeType = desugared ->getPointeeType ().getTypePtr ();
7645
+ if (Desugared ->isArrayType ())
7646
+ pointeeType = Desugared ->getArrayElementTypeNoTypeQual ();
7647
+ else if (Desugared ->isAnyPointerType ())
7648
+ pointeeType = Desugared ->getPointeeType ().getTypePtr ();
7637
7649
7638
7650
if (pointeeType && (pointeeType->isAnyPointerType () ||
7639
7651
pointeeType->isObjCObjectPointerType () ||
7640
7652
pointeeType->isMemberPointerType ())) {
7641
- S.Diag (nullabilityLoc, diag::err_nullability_cs_multilevel)
7642
- << DiagNullabilityKind (nullability, true )
7643
- << type;
7644
- S.Diag (nullabilityLoc, diag::note_nullability_type_specifier)
7645
- << DiagNullabilityKind (nullability, false )
7646
- << type
7647
- << FixItHint::CreateReplacement (nullabilityLoc,
7648
- getNullabilitySpelling (nullability));
7653
+ S.Diag (NullabilityLoc, diag::err_nullability_cs_multilevel)
7654
+ << DiagNullabilityKind (Nullability, true ) << QT;
7655
+ S.Diag (NullabilityLoc, diag::note_nullability_type_specifier)
7656
+ << DiagNullabilityKind (Nullability, false ) << QT
7657
+ << FixItHint::CreateReplacement (NullabilityLoc,
7658
+ getNullabilitySpelling (Nullability));
7649
7659
return true ;
7650
7660
}
7651
7661
}
7652
7662
7653
7663
// Form the attributed type.
7654
- type = state.getAttributedType (
7655
- createNullabilityAttr (S.Context , attr, nullability), type, type);
7664
+ if (State) {
7665
+ assert (PAttr);
7666
+ Attr *A = createNullabilityAttr (S.Context , *PAttr, Nullability);
7667
+ QT = State->getAttributedType (A, QT, QT);
7668
+ } else {
7669
+ attr::Kind attrKind = AttributedType::getNullabilityAttrKind (Nullability);
7670
+ QT = S.Context .getAttributedType (attrKind, QT, QT);
7671
+ }
7656
7672
return false ;
7657
7673
}
7658
7674
7675
+ static bool CheckNullabilityTypeSpecifier (TypeProcessingState &State,
7676
+ QualType &Type, ParsedAttr &Attr,
7677
+ bool AllowOnArrayType) {
7678
+ NullabilityKind Nullability = mapNullabilityAttrKind (Attr.getKind ());
7679
+ SourceLocation NullabilityLoc = Attr.getLoc ();
7680
+ bool IsContextSensitive = Attr.isContextSensitiveKeywordAttribute ();
7681
+
7682
+ return CheckNullabilityTypeSpecifier (State.getSema (), &State, &Attr, Type,
7683
+ Nullability, NullabilityLoc,
7684
+ IsContextSensitive, AllowOnArrayType,
7685
+ /* overrideExisting*/ false );
7686
+ }
7687
+
7688
+ bool Sema::CheckImplicitNullabilityTypeSpecifier (QualType &Type,
7689
+ NullabilityKind Nullability,
7690
+ SourceLocation DiagLoc,
7691
+ bool AllowArrayTypes,
7692
+ bool OverrideExisting) {
7693
+ return CheckNullabilityTypeSpecifier (
7694
+ *this , nullptr , nullptr , Type, Nullability, DiagLoc,
7695
+ /* isContextSensitive*/ false , AllowArrayTypes, OverrideExisting);
7696
+ }
7697
+
7659
7698
// / Check the application of the Objective-C '__kindof' qualifier to
7660
7699
// / the given type.
7661
7700
static bool checkObjCKindOfType (TypeProcessingState &state, QualType &type,
@@ -8950,11 +8989,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
8950
8989
bool allowOnArrayType =
8951
8990
state.getDeclarator ().isPrototypeContext () &&
8952
8991
!hasOuterPointerLikeChunk (state.getDeclarator (), endIndex);
8953
- if (checkNullabilityTypeSpecifier (
8954
- state,
8955
- type,
8956
- attr,
8957
- allowOnArrayType)) {
8992
+ if (CheckNullabilityTypeSpecifier (state, type, attr,
8993
+ allowOnArrayType)) {
8958
8994
attr.setInvalid ();
8959
8995
}
8960
8996
0 commit comments