69
69
#include " clang/AST/Type.h"
70
70
#include " clang/Basic/Specifiers.h"
71
71
#include " clang/Basic/TargetInfo.h"
72
+ #include " clang/Sema/SemaDiagnostic.h"
72
73
#include " clang/Lex/Preprocessor.h"
73
74
#include " clang/Sema/Lookup.h"
74
75
@@ -173,6 +174,9 @@ bool importer::recordHasReferenceSemantics(
173
174
!importerImpl->SwiftContext .LangOpts .CForeignReferenceTypes )
174
175
return false ;
175
176
177
+ // ACTODO: Check versioned attrs in case of
178
+ // captureSwiftVersionIndependentAPINotes
179
+
176
180
// At this point decl might not be fully imported into Swift yet, which
177
181
// means we might not have asked Clang to generate its implicit members, such
178
182
// as copy or move constructors. This would cause CxxRecordSemanticsRequest to
@@ -9336,6 +9340,67 @@ static bool isUsingMacroName(clang::SourceManager &SM,
9336
9340
return content == MacroName;
9337
9341
}
9338
9342
9343
+ static void filterUsableVersionedAttrs (const clang::NamedDecl *clangDecl,
9344
+ llvm::VersionTuple currentVersion,
9345
+ std::unordered_set<clang::Attr*> &discardVersionedAttrSet) {
9346
+ // Scan through Swift-Versioned clang attributes and select which one to apply
9347
+ // if multiple candidates exist.
9348
+ SmallVector<clang::SwiftVersionedAdditionAttr*, 4 > swiftVersionedAttributes;
9349
+ for (auto attr : clangDecl->attrs ())
9350
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(attr))
9351
+ swiftVersionedAttributes.push_back (versionedAttr);
9352
+
9353
+ // An attribute version is valid to apply if it is greater than the current version
9354
+ // or is unversioned
9355
+ auto applicableVersion = [currentVersion] (clang::VersionTuple attrVersion) -> bool {
9356
+ return attrVersion.empty () || attrVersion >= currentVersion;
9357
+ };
9358
+
9359
+ // We have a better attribute option if there exists another versioned attr
9360
+ // wrapper for this attribute kind with a valid version that is lower than the
9361
+ // one of the attribute we are considering
9362
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion]
9363
+ (clang::VersionTuple attrVersion, clang::attr::Kind attrKind) -> bool {
9364
+ for (auto VAI = swiftVersionedAttributes.begin (),
9365
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
9366
+ auto otherVersionedAttr = *VAI;
9367
+ auto otherAttrKind = otherVersionedAttr->getAdditionalAttr ()->getKind ();
9368
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
9369
+ // Same exact attribute, ignore
9370
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
9371
+ continue ;
9372
+
9373
+ // For a matching attribute kind, an un-versioned attribute
9374
+ // never takes precedence over an exsiting valid versioned one.
9375
+ if (otherAttrKind == attrKind && !attrVersion.empty () && otherAttrVersion.empty ())
9376
+ continue ;
9377
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) && attrVersion.empty ())
9378
+ return true ;
9379
+
9380
+ // For two versioned attributes of the same kind, the one with the lower applicable
9381
+ // version takes precedence.
9382
+ if (otherAttrKind == attrKind &&
9383
+ applicableVersion (otherAttrVersion) &&
9384
+ otherAttrVersion < attrVersion)
9385
+ return true ;
9386
+ }
9387
+ return false ;
9388
+ };
9389
+
9390
+ for (auto VAI = swiftVersionedAttributes.begin (),
9391
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
9392
+ auto versionedAttr = *VAI;
9393
+ auto attrKind = versionedAttr->getAdditionalAttr ()->getKind ();
9394
+ auto attrVersion = versionedAttr->getVersion ();
9395
+ if (!applicableVersion (attrVersion))
9396
+ discardVersionedAttrSet.insert (versionedAttr);
9397
+ else if (haveBetterAttr (attrVersion, attrKind))
9398
+ discardVersionedAttrSet.insert (versionedAttr);
9399
+ else
9400
+ continue ;
9401
+ }
9402
+ }
9403
+
9339
9404
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
9340
9405
{
9341
9406
// sourceDecl->getClangDecl() can be null because some lazily instantiated cases like C++ members that were instantiated from using-shadow-decls have no corresponding Clang decl.
@@ -9369,17 +9434,40 @@ void ClangImporter::Implementation::importAttributes(
9369
9434
if (auto func = dyn_cast<AbstractFunctionDecl>(MappedDecl))
9370
9435
isAsync = func->hasAsync ();
9371
9436
9437
+ // Determine which versioned attributes are applicable
9438
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9439
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9440
+ filterUsableVersionedAttrs (ClangDecl, CurrentVersion.asClangVersionTuple (),
9441
+ discardVersionedAttrSet);
9442
+
9372
9443
// Scan through Clang attributes and map them onto Swift
9373
9444
// equivalents.
9374
9445
bool AnyUnavailable = MappedDecl->isUnavailable ();
9375
9446
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9376
9447
AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9448
+ clang::Attr *consideringAttr = *AI;
9449
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
9450
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(consideringAttr)) {
9451
+ // "type" and "nullability" attributes are handled earlier since they change
9452
+ // the decl's type.
9453
+ auto additionalAttr = versionedAttr->getAdditionalAttr ();
9454
+ if (isa<clang::SwiftTypeAttr>(additionalAttr) ||
9455
+ isa<clang::SwiftNullabilityAttr>(additionalAttr))
9456
+ continue ;
9457
+
9458
+ if (discardVersionedAttrSet.count (versionedAttr))
9459
+ continue ;
9460
+
9461
+ consideringAttr = additionalAttr;
9462
+ }
9463
+ }
9464
+
9377
9465
//
9378
9466
// __attribute__((unavailable))
9379
9467
//
9380
9468
// Mapping: @available(*,unavailable)
9381
9469
//
9382
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
9470
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
9383
9471
auto Message = unavailable->getMessage ();
9384
9472
auto attr = AvailableAttr::createUniversallyUnavailable (C, Message);
9385
9473
MappedDecl->getAttrs ().add (attr);
@@ -9392,7 +9480,7 @@ void ClangImporter::Implementation::importAttributes(
9392
9480
//
9393
9481
// Mapping: @available(*, unavailable)
9394
9482
//
9395
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
9483
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
9396
9484
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
9397
9485
auto attr = AvailableAttr::createUnavailableInSwift (C, " " , " " );
9398
9486
MappedDecl->getAttrs ().add (attr);
@@ -9405,7 +9493,7 @@ void ClangImporter::Implementation::importAttributes(
9405
9493
//
9406
9494
// Mapping: @available(*,deprecated)
9407
9495
//
9408
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
9496
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
9409
9497
auto Message = deprecated->getMessage ();
9410
9498
auto attr = AvailableAttr::createUniversallyDeprecated (C, Message, " " );
9411
9499
MappedDecl->getAttrs ().add (attr);
@@ -9414,7 +9502,7 @@ void ClangImporter::Implementation::importAttributes(
9414
9502
9415
9503
// __attribute__((availability))
9416
9504
//
9417
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
9505
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
9418
9506
StringRef Platform = avail->getPlatform ()->getName ();
9419
9507
9420
9508
// Is this our special "availability(swift, unavailable)" attribute?
@@ -9646,6 +9734,62 @@ void ClangImporter::Implementation::importAttributes(
9646
9734
}
9647
9735
}
9648
9736
9737
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
9738
+ clang::Sema &Sema,
9739
+ const ImportNameVersion CurrentImporterVersion) {
9740
+ // Determine which versioned attributes are applicable
9741
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9742
+ filterUsableVersionedAttrs (ClangDecl,
9743
+ CurrentImporterVersion.asClangVersionTuple (),
9744
+ discardVersionedAttrSet);
9745
+
9746
+ // When importing from a module built with version-independent APINotes payload,
9747
+ // the decl will carry all possible versioned notes, without directly applying any
9748
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
9749
+ // since they change the actual type of the decl as seen downstream.
9750
+ //
9751
+ // Other kinds of notes will be handled in `importAttributes`.
9752
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9753
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9754
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(*AI)) {
9755
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAdditionalAttr ()) &&
9756
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAdditionalAttr ())) {
9757
+ continue ;
9758
+ }
9759
+
9760
+ if (discardVersionedAttrSet.count (versionedAttr))
9761
+ continue ;
9762
+
9763
+ // Apply Type APINotes
9764
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAdditionalAttr ())) {
9765
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
9766
+ typeRenameAttr->getTypeString ());
9767
+ }
9768
+
9769
+ // Apply Nullability APINotes
9770
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAdditionalAttr ())) {
9771
+ clang::NullabilityKind nullability;
9772
+ switch (nullabilityAttr->getKind ()) {
9773
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
9774
+ nullability = clang::NullabilityKind::NonNull;
9775
+ break ;
9776
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
9777
+ nullability = clang::NullabilityKind::Nullable;
9778
+ break ;
9779
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
9780
+ nullability = clang::NullabilityKind::Unspecified;
9781
+ break ;
9782
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
9783
+ nullability = clang::NullabilityKind::NullableResult;
9784
+ break ;
9785
+ }
9786
+
9787
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
9788
+ }
9789
+ }
9790
+ }
9791
+ }
9792
+
9649
9793
Decl *
9650
9794
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
9651
9795
ImportNameVersion version,
@@ -9657,6 +9801,13 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
9657
9801
if (ClangDecl->isInvalidDecl ())
9658
9802
return nullptr ;
9659
9803
9804
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
9805
+ // notes are applied by the client (Importer) instead of the producer of the
9806
+ // Clang module we are consuming. Do so now, early, since these notes
9807
+ // affect the decl's type.
9808
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9809
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
9810
+
9660
9811
bool SkippedOverTypedef = false ;
9661
9812
Decl *Result = nullptr ;
9662
9813
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
0 commit comments