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