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