@@ -52,63 +52,59 @@ static bool isIndirectPointerType(QualType Type) {
52
52
Pointee->isMemberPointerType ();
53
53
}
54
54
55
- // / Apply nullability to the given declaration.
56
- static void applyNullability (Sema &S, Decl *D, NullabilityKind Nullability,
57
- VersionedInfoMetadata Metadata) {
58
- if (!Metadata.IsActive )
59
- return ;
60
-
61
- auto GetModified =
62
- [&](Decl *D, QualType QT,
63
- NullabilityKind Nullability) -> std::optional<QualType> {
64
- QualType Original = QT;
65
- S.CheckImplicitNullabilityTypeSpecifier (QT, Nullability, D->getLocation (),
66
- isa<ParmVarDecl>(D),
67
- /* OverrideExisting=*/ true );
68
- return (QT.getTypePtr () != Original.getTypePtr ()) ? std::optional (QT)
69
- : std::nullopt;
70
- };
55
+ static void applyAPINotesType (Sema &S, Decl *decl, StringRef typeString,
56
+ VersionedInfoMetadata metadata) {
57
+ if (typeString.empty ())
71
58
72
- if (auto Function = dyn_cast<FunctionDecl>(D)) {
73
- if (auto Modified =
74
- GetModified (D, Function->getReturnType (), Nullability)) {
75
- const FunctionType *FnType = Function->getType ()->castAs <FunctionType>();
76
- if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
77
- Function->setType (S.Context .getFunctionType (
78
- *Modified, proto->getParamTypes (), proto->getExtProtoInfo ()));
79
- else
80
- Function->setType (
81
- S.Context .getFunctionNoProtoType (*Modified, FnType->getExtInfo ()));
82
- }
83
- } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
84
- if (auto Modified = GetModified (D, Method->getReturnType (), Nullability)) {
85
- Method->setReturnType (*Modified);
59
+ return ;
86
60
87
- // Make it a context-sensitive keyword if we can.
88
- if (!isIndirectPointerType (*Modified))
89
- Method->setObjCDeclQualifier (Decl::ObjCDeclQualifier (
90
- Method->getObjCDeclQualifier () | Decl::OBJC_TQ_CSNullability));
91
- }
92
- } else if (auto Value = dyn_cast<ValueDecl>(D)) {
93
- if (auto Modified = GetModified (D, Value->getType (), Nullability)) {
94
- Value->setType (*Modified);
61
+ // Version-independent APINotes add "type" annotations
62
+ // with a versioned attribute for the client to select and apply.
63
+ if (S.captureSwiftVersionIndependentAPINotes ()) {
64
+ auto *typeAttr = SwiftTypeAttr::CreateImplicit (
65
+ S.Context , typeString);
66
+ auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit (
67
+ S.Context , metadata.Version , typeAttr, metadata.IsReplacement );
68
+ decl->addAttr (versioned);
69
+ } else {
70
+ if (!metadata.IsActive )
71
+ return ;
72
+ S.ApplyAPINotesType (decl, typeString);
73
+ }
74
+ }
95
75
96
- // Make it a context-sensitive keyword if we can.
97
- if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
98
- if (Parm->isObjCMethodParameter () && !isIndirectPointerType (*Modified))
99
- Parm->setObjCDeclQualifier (Decl::ObjCDeclQualifier (
100
- Parm->getObjCDeclQualifier () | Decl::OBJC_TQ_CSNullability));
101
- }
76
+ // / Apply nullability to the given declaration.
77
+ static void applyNullability (Sema &S, Decl *decl, NullabilityKind nullability,
78
+ VersionedInfoMetadata metadata) {
79
+ // Version-independent APINotes add "nullability" annotations
80
+ // with a versioned attribute for the client to select and apply.
81
+ if (S.captureSwiftVersionIndependentAPINotes ()) {
82
+ SwiftNullabilityAttr::Kind attrNullabilityKind;
83
+ switch (nullability) {
84
+ case NullabilityKind::NonNull:
85
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::NonNull;
86
+ break ;
87
+ case NullabilityKind::Nullable:
88
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::Nullable;
89
+ break ;
90
+ case NullabilityKind::Unspecified:
91
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::Unspecified;
92
+ break ;
93
+ case NullabilityKind::NullableResult:
94
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::NullableResult;
95
+ break ;
102
96
}
103
- } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
104
- if (auto Modified = GetModified (D, Property->getType (), Nullability)) {
105
- Property->setType (*Modified, Property->getTypeSourceInfo ());
97
+ auto *nullabilityAttr = SwiftNullabilityAttr::CreateImplicit (
98
+ S.Context , attrNullabilityKind);
99
+ auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit (
100
+ S.Context , metadata.Version , nullabilityAttr, metadata.IsReplacement );
101
+ decl->addAttr (versioned);
102
+ return ;
103
+ } else {
104
+ if (!metadata.IsActive )
105
+ return ;
106
106
107
- // Make it a property attribute if we can.
108
- if (!isIndirectPointerType (*Modified))
109
- Property->setPropertyAttributes (
110
- ObjCPropertyAttribute::kind_null_resettable);
111
- }
107
+ S.ApplyNullability (decl, nullability);
112
108
}
113
109
}
114
110
@@ -361,42 +357,105 @@ static bool checkAPINotesReplacementType(Sema &S, SourceLocation Loc,
361
357
return false ;
362
358
}
363
359
364
- // / Process API notes for a variable or property.
365
- static void ProcessAPINotes (Sema &S, Decl *D,
366
- const api_notes::VariableInfo &Info,
367
- VersionedInfoMetadata Metadata) {
368
- // Type override.
369
- if (Metadata.IsActive && !Info.getType ().empty () &&
370
- S.ParseTypeFromStringCallback ) {
371
- auto ParsedType = S.ParseTypeFromStringCallback (
372
- Info.getType (), " <API Notes>" , D->getLocation ());
360
+ void Sema::ApplyAPINotesType (Decl *D, StringRef TypeString) {
361
+ if (!TypeString.empty () &&
362
+ ParseTypeFromStringCallback) {
363
+ auto ParsedType = ParseTypeFromStringCallback (TypeString,
364
+ " <API Notes>" ,
365
+ D->getLocation ());
373
366
if (ParsedType.isUsable ()) {
374
367
QualType Type = Sema::GetTypeFromParser (ParsedType.get ());
375
368
auto TypeInfo =
376
- S.Context .getTrivialTypeSourceInfo (Type, D->getLocation ());
377
-
369
+ Context.getTrivialTypeSourceInfo (Type, D->getLocation ());
378
370
if (auto Var = dyn_cast<VarDecl>(D)) {
379
371
// Make adjustments to parameter types.
380
372
if (isa<ParmVarDecl>(Var)) {
381
- Type = S.ObjC ().AdjustParameterTypeForObjCAutoRefCount (
382
- Type, D->getLocation (), TypeInfo);
383
- Type = S.Context .getAdjustedParameterType (Type);
373
+ Type = ObjC ().AdjustParameterTypeForObjCAutoRefCount (Type,
374
+ D->getLocation (),
375
+ TypeInfo);
376
+ Type = Context.getAdjustedParameterType (Type);
384
377
}
385
378
386
- if (!checkAPINotesReplacementType (S, Var->getLocation (), Var->getType (),
379
+ if (!checkAPINotesReplacementType (*this , Var->getLocation (),
380
+ Var->getType (),
387
381
Type)) {
388
382
Var->setType (Type);
389
383
Var->setTypeSourceInfo (TypeInfo);
390
384
}
391
- } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
392
- if (!checkAPINotesReplacementType (S, Property->getLocation (),
393
- Property->getType (), Type))
394
- Property->setType (Type, TypeInfo);
395
-
396
- } else
385
+ } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
386
+ if (!checkAPINotesReplacementType (*this , property->getLocation (),
387
+ property->getType (),
388
+ Type)) {
389
+ property->setType (Type, TypeInfo);
390
+ }
391
+ } else {
397
392
llvm_unreachable (" API notes allowed a type on an unknown declaration" );
393
+ }
398
394
}
399
395
}
396
+ }
397
+
398
+ void Sema::ApplyNullability (Decl *D, NullabilityKind Nullability) {
399
+ auto GetModified =
400
+ [&](class Decl *D, QualType QT,
401
+ NullabilityKind Nullability) -> std::optional<QualType> {
402
+ QualType Original = QT;
403
+ CheckImplicitNullabilityTypeSpecifier (QT, Nullability, D->getLocation (),
404
+ isa<ParmVarDecl>(D),
405
+ /* OverrideExisting=*/ true );
406
+ return (QT.getTypePtr () != Original.getTypePtr ()) ? std::optional (QT)
407
+ : std::nullopt;
408
+ };
409
+
410
+ if (auto Function = dyn_cast<FunctionDecl>(D)) {
411
+ if (auto Modified =
412
+ GetModified (D, Function->getReturnType (), Nullability)) {
413
+ const FunctionType *FnType = Function->getType ()->castAs <FunctionType>();
414
+ if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
415
+ Function->setType (Context.getFunctionType (
416
+ *Modified, proto->getParamTypes (), proto->getExtProtoInfo ()));
417
+ else
418
+ Function->setType (
419
+ Context.getFunctionNoProtoType (*Modified, FnType->getExtInfo ()));
420
+ }
421
+ } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
422
+ if (auto Modified = GetModified (D, Method->getReturnType (), Nullability)) {
423
+ Method->setReturnType (*Modified);
424
+
425
+ // Make it a context-sensitive keyword if we can.
426
+ if (!isIndirectPointerType (*Modified))
427
+ Method->setObjCDeclQualifier (Decl::ObjCDeclQualifier (
428
+ Method->getObjCDeclQualifier () | Decl::OBJC_TQ_CSNullability));
429
+ }
430
+ } else if (auto Value = dyn_cast<ValueDecl>(D)) {
431
+ if (auto Modified = GetModified (D, Value->getType (), Nullability)) {
432
+ Value->setType (*Modified);
433
+
434
+ // Make it a context-sensitive keyword if we can.
435
+ if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
436
+ if (Parm->isObjCMethodParameter () && !isIndirectPointerType (*Modified))
437
+ Parm->setObjCDeclQualifier (Decl::ObjCDeclQualifier (
438
+ Parm->getObjCDeclQualifier () | Decl::OBJC_TQ_CSNullability));
439
+ }
440
+ }
441
+ } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
442
+ if (auto Modified = GetModified (D, Property->getType (), Nullability)) {
443
+ Property->setType (*Modified, Property->getTypeSourceInfo ());
444
+
445
+ // Make it a property attribute if we can.
446
+ if (!isIndirectPointerType (*Modified))
447
+ Property->setPropertyAttributes (
448
+ ObjCPropertyAttribute::kind_null_resettable);
449
+ }
450
+ }
451
+ }
452
+
453
+ // / Process API notes for a variable or property.
454
+ static void ProcessAPINotes (Sema &S, Decl *D,
455
+ const api_notes::VariableInfo &Info,
456
+ VersionedInfoMetadata Metadata) {
457
+ // Type override.
458
+ applyAPINotesType (S, D, Info.getType (), Metadata);
400
459
401
460
// Nullability.
402
461
if (auto Nullability = Info.getNullability ())
@@ -814,7 +873,8 @@ static void ProcessVersionedAPINotes(
814
873
Sema &S, SpecificDecl *D,
815
874
const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
816
875
817
- maybeAttachUnversionedSwiftName (S, D, Info);
876
+ if (!S.captureSwiftVersionIndependentAPINotes ())
877
+ maybeAttachUnversionedSwiftName (S, D, Info);
818
878
819
879
unsigned Selected = Info.getSelected ().value_or (Info.size ());
820
880
@@ -824,10 +884,18 @@ static void ProcessVersionedAPINotes(
824
884
std::tie (Version, InfoSlice) = Info[i];
825
885
auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
826
886
auto Replacement = IsSubstitution_t::Original;
827
- if (Active == IsActive_t::Inactive && Version.empty ()) {
887
+
888
+ // When collection all APINotes as version-independent,
889
+ // capture all as inactive and defer to the client select the
890
+ // right one.
891
+ if (S.captureSwiftVersionIndependentAPINotes ()) {
892
+ Active = IsActive_t::Inactive;
893
+ Replacement = IsSubstitution_t::Original;
894
+ } else if (Active == IsActive_t::Inactive && Version.empty ()) {
828
895
Replacement = IsSubstitution_t::Replacement;
829
896
Version = Info[Selected].first ;
830
897
}
898
+
831
899
ProcessAPINotes (S, D, InfoSlice,
832
900
VersionedInfoMetadata (Version, Active, Replacement));
833
901
}
0 commit comments