@@ -51,75 +51,57 @@ static bool isMultiLevelPointerType(QualType type) {
51
51
pointee->isMemberPointerType ();
52
52
}
53
53
54
- // Apply nullability to the given declaration.
55
- static void applyNullability (Sema &S, Decl *decl, NullabilityKind nullability,
56
- VersionedInfoMetadata metadata) {
57
- if (!metadata.IsActive )
54
+ static void applyAPINotesType (Sema &S, Decl *decl, StringRef typeString,
55
+ VersionedInfoMetadata metadata) {
56
+ if (typeString.empty ())
58
57
return ;
59
58
60
- QualType type;
61
-
62
- // Nullability for a function/method appertains to the retain type.
63
- if (auto function = dyn_cast<FunctionDecl>(decl)) {
64
- type = function->getReturnType ();
65
- } else if (auto method = dyn_cast<ObjCMethodDecl>(decl)) {
66
- type = method->getReturnType ();
67
- } else if (auto value = dyn_cast<ValueDecl>(decl)) {
68
- type = value->getType ();
69
- } else if (auto property = dyn_cast<ObjCPropertyDecl>(decl)) {
70
- type = property->getType ();
59
+ // Version-independent APINotes add "type" annotations
60
+ // with a versioned attribute for the client to select and apply.
61
+ if (S.captureSwiftVersionIndependentAPINotes ()) {
62
+ auto *typeAttr = SwiftTypeAttr::CreateImplicit (
63
+ S.Context , typeString);
64
+ auto *versioned = SwiftVersionedAttr::CreateImplicit (
65
+ S.Context , metadata.Version , typeAttr, metadata.IsReplacement );
66
+ decl->addAttr (versioned);
71
67
} else {
72
- return ;
68
+ if (!metadata.IsActive )
69
+ return ;
70
+ S.ApplyAPINotesType (decl, typeString);
73
71
}
72
+ }
74
73
75
- // Check the nullability specifier on this type.
76
- QualType origType = type;
77
- S.checkImplicitNullabilityTypeSpecifier (type, nullability,
78
- decl->getLocation (),
79
- isa<ParmVarDecl>(decl),
80
- /* overrideExisting=*/ true );
81
- if (type.getTypePtr () == origType.getTypePtr ())
82
- return ;
83
-
84
- if (auto function = dyn_cast<FunctionDecl>(decl)) {
85
- const FunctionType *fnType = function->getType ()->castAs <FunctionType>();
86
- if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
87
- function->setType (S.Context .getFunctionType (type, proto->getParamTypes (),
88
- proto->getExtProtoInfo ()));
89
- } else {
90
- function->setType (S.Context .getFunctionNoProtoType (type,
91
- fnType->getExtInfo ()));
92
- }
93
- } else if (auto method = dyn_cast<ObjCMethodDecl>(decl)) {
94
- method->setReturnType (type);
95
-
96
- // Make it a context-sensitive keyword if we can.
97
- if (!isMultiLevelPointerType (type)) {
98
- method->setObjCDeclQualifier (
99
- Decl::ObjCDeclQualifier (method->getObjCDeclQualifier () |
100
- Decl::OBJC_TQ_CSNullability));
101
- }
102
- } else if (auto value = dyn_cast<ValueDecl>(decl)) {
103
- value->setType (type);
104
-
105
- // Make it a context-sensitive keyword if we can.
106
- if (auto parm = dyn_cast<ParmVarDecl>(decl)) {
107
- if (parm->isObjCMethodParameter () && !isMultiLevelPointerType (type)) {
108
- parm->setObjCDeclQualifier (
109
- Decl::ObjCDeclQualifier (parm->getObjCDeclQualifier () |
110
- Decl::OBJC_TQ_CSNullability));
111
- }
112
- }
113
- } else if (auto property = dyn_cast<ObjCPropertyDecl>(decl)) {
114
- property->setType (type, property->getTypeSourceInfo ());
115
-
116
- // Make it a property attribute if we can.
117
- if (!isMultiLevelPointerType (type)) {
118
- property->setPropertyAttributes (
119
- ObjCPropertyAttribute::kind_null_resettable);
74
+ static void applyNullability (Sema &S, Decl *decl, NullabilityKind nullability,
75
+ VersionedInfoMetadata metadata) {
76
+ // Version-independent APINotes add "nullability" annotations
77
+ // with a versioned attribute for the client to select and apply.
78
+ if (S.captureSwiftVersionIndependentAPINotes ()) {
79
+ SwiftNullabilityAttr::Kind attrNullabilityKind;
80
+ switch (nullability) {
81
+ case NullabilityKind::NonNull:
82
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::NonNull;
83
+ break ;
84
+ case NullabilityKind::Nullable:
85
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::Nullable;
86
+ break ;
87
+ case NullabilityKind::Unspecified:
88
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::Unspecified;
89
+ break ;
90
+ case NullabilityKind::NullableResult:
91
+ attrNullabilityKind = SwiftNullabilityAttr::Kind::NullableResult;
92
+ break ;
120
93
}
94
+ auto *nullabilityAttr = SwiftNullabilityAttr::CreateImplicit (
95
+ S.Context , attrNullabilityKind);
96
+ auto *versioned = SwiftVersionedAttr::CreateImplicit (
97
+ S.Context , metadata.Version , nullabilityAttr, metadata.IsReplacement );
98
+ decl->addAttr (versioned);
99
+ return ;
121
100
} else {
122
- llvm_unreachable (" cannot handle nullability here" );
101
+ if (!metadata.IsActive )
102
+ return ;
103
+
104
+ S.ApplyNullability (decl, nullability);
123
105
}
124
106
}
125
107
@@ -376,37 +358,33 @@ static bool checkAPINotesReplacementType(Sema &S, SourceLocation loc,
376
358
return false ;
377
359
}
378
360
379
- // / Process API notes for a variable or property.
380
- static void ProcessAPINotes (Sema &S, Decl *D,
381
- const api_notes::VariableInfo &info,
382
- VersionedInfoMetadata metadata) {
383
- // Type override.
384
- if (metadata.IsActive && !info.getType ().empty () &&
385
- S.ParseTypeFromStringCallback ) {
386
- auto parsedType = S.ParseTypeFromStringCallback (info.getType (),
387
- " <API Notes>" ,
388
- D->getLocation ());
361
+ void Sema::ApplyAPINotesType (Decl *D, StringRef TypeString) {
362
+ if (!TypeString.empty () &&
363
+ ParseTypeFromStringCallback) {
364
+ auto parsedType = ParseTypeFromStringCallback (TypeString,
365
+ " <API Notes>" ,
366
+ D->getLocation ());
389
367
if (parsedType.isUsable ()) {
390
368
QualType type = Sema::GetTypeFromParser (parsedType.get ());
391
369
auto typeInfo =
392
- S. Context .getTrivialTypeSourceInfo (type, D->getLocation ());
370
+ Context.getTrivialTypeSourceInfo (type, D->getLocation ());
393
371
394
372
if (auto var = dyn_cast<VarDecl>(D)) {
395
373
// Make adjustments to parameter types.
396
374
if (isa<ParmVarDecl>(var)) {
397
- type = S. adjustParameterTypeForObjCAutoRefCount (type,
398
- D->getLocation (),
399
- typeInfo);
400
- type = S. Context .getAdjustedParameterType (type);
375
+ type = adjustParameterTypeForObjCAutoRefCount (type,
376
+ D->getLocation (),
377
+ typeInfo);
378
+ type = Context.getAdjustedParameterType (type);
401
379
}
402
380
403
- if (!checkAPINotesReplacementType (S , var->getLocation (), var->getType (),
381
+ if (!checkAPINotesReplacementType (* this , var->getLocation (), var->getType (),
404
382
type)) {
405
383
var->setType (type);
406
384
var->setTypeSourceInfo (typeInfo);
407
385
}
408
386
} else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
409
- if (!checkAPINotesReplacementType (S , property->getLocation (),
387
+ if (!checkAPINotesReplacementType (* this , property->getLocation (),
410
388
property->getType (),
411
389
type)) {
412
390
property->setType (type, typeInfo);
@@ -416,6 +394,83 @@ static void ProcessAPINotes(Sema &S, Decl *D,
416
394
}
417
395
}
418
396
}
397
+ }
398
+
399
+ // Apply nullability to the given declaration.
400
+ void Sema::ApplyNullability (Decl *Decl, NullabilityKind Nullability) {
401
+ QualType type;
402
+
403
+ // Nullability for a function/method appertains to the retain type.
404
+ if (auto function = dyn_cast<FunctionDecl>(Decl)) {
405
+ type = function->getReturnType ();
406
+ } else if (auto method = dyn_cast<ObjCMethodDecl>(Decl)) {
407
+ type = method->getReturnType ();
408
+ } else if (auto value = dyn_cast<ValueDecl>(Decl)) {
409
+ type = value->getType ();
410
+ } else if (auto property = dyn_cast<ObjCPropertyDecl>(Decl)) {
411
+ type = property->getType ();
412
+ } else {
413
+ return ;
414
+ }
415
+
416
+ // Check the nullability specifier on this type.
417
+ QualType origType = type;
418
+ checkImplicitNullabilityTypeSpecifier (type, Nullability,
419
+ Decl->getLocation (),
420
+ isa<ParmVarDecl>(Decl),
421
+ /* overrideExisting=*/ true );
422
+ if (type.getTypePtr () == origType.getTypePtr ())
423
+ return ;
424
+
425
+ if (auto function = dyn_cast<FunctionDecl>(Decl)) {
426
+ const FunctionType *fnType = function->getType ()->castAs <FunctionType>();
427
+ if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
428
+ function->setType (Context.getFunctionType (type, proto->getParamTypes (),
429
+ proto->getExtProtoInfo ()));
430
+ } else {
431
+ function->setType (Context.getFunctionNoProtoType (type,
432
+ fnType->getExtInfo ()));
433
+ }
434
+ } else if (auto method = dyn_cast<ObjCMethodDecl>(Decl)) {
435
+ method->setReturnType (type);
436
+
437
+ // Make it a context-sensitive keyword if we can.
438
+ if (!isMultiLevelPointerType (type)) {
439
+ method->setObjCDeclQualifier (
440
+ Decl::ObjCDeclQualifier (method->getObjCDeclQualifier () |
441
+ Decl::OBJC_TQ_CSNullability));
442
+ }
443
+ } else if (auto value = dyn_cast<ValueDecl>(Decl)) {
444
+ value->setType (type);
445
+
446
+ // Make it a context-sensitive keyword if we can.
447
+ if (auto parm = dyn_cast<ParmVarDecl>(Decl)) {
448
+ if (parm->isObjCMethodParameter () && !isMultiLevelPointerType (type)) {
449
+ parm->setObjCDeclQualifier (
450
+ Decl::ObjCDeclQualifier (parm->getObjCDeclQualifier () |
451
+ Decl::OBJC_TQ_CSNullability));
452
+ }
453
+ }
454
+ } else if (auto property = dyn_cast<ObjCPropertyDecl>(Decl)) {
455
+ property->setType (type, property->getTypeSourceInfo ());
456
+
457
+ // Make it a property attribute if we can.
458
+ if (!isMultiLevelPointerType (type)) {
459
+ property->setPropertyAttributes (
460
+ ObjCPropertyAttribute::kind_null_resettable);
461
+ }
462
+ } else {
463
+ llvm_unreachable (" cannot handle nullability here" );
464
+ }
465
+ }
466
+
467
+
468
+ // / Process API notes for a variable or property.
469
+ static void ProcessAPINotes (Sema &S, Decl *D,
470
+ const api_notes::VariableInfo &info,
471
+ VersionedInfoMetadata metadata) {
472
+ // Type override.
473
+ applyAPINotesType (S, D, info.getType (), metadata);
419
474
420
475
// Nullability.
421
476
if (auto Nullability = info.getNullability ()) {
@@ -802,8 +857,8 @@ template <typename SpecificDecl, typename SpecificInfo>
802
857
static void ProcessVersionedAPINotes (
803
858
Sema &S, SpecificDecl *D,
804
859
const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
805
-
806
- maybeAttachUnversionedSwiftName (S, D, Info);
860
+ if (!S. captureSwiftVersionIndependentAPINotes ())
861
+ maybeAttachUnversionedSwiftName (S, D, Info);
807
862
808
863
unsigned Selected = Info.getSelected ().value_or (Info.size ());
809
864
@@ -813,10 +868,18 @@ static void ProcessVersionedAPINotes(
813
868
std::tie (Version, InfoSlice) = Info[i];
814
869
auto Active = (i == Selected) ? IsActive : IsNotActive;
815
870
auto Replacement = IsNotReplacement;
816
- if (Active == IsNotActive && Version.empty ()) {
871
+
872
+ // When collection all APINotes as version-independent,
873
+ // capture all as inactive and defer to the client select the
874
+ // right one.
875
+ if (S.captureSwiftVersionIndependentAPINotes ()) {
876
+ Active = IsNotActive;
877
+ Replacement = IsNotReplacement;
878
+ } else if (Active == IsNotActive && Version.empty ()) {
817
879
Replacement = IsReplacement;
818
880
Version = Info[Selected].first ;
819
881
}
882
+
820
883
ProcessAPINotes (S, D, InfoSlice, VersionedInfoMetadata (Version, Active,
821
884
Replacement));
822
885
}
0 commit comments