57
57
#include " clang/AST/DeclObjCCommon.h"
58
58
#include " clang/Basic/Specifiers.h"
59
59
#include " clang/Basic/TargetInfo.h"
60
+ #include " clang/Sema/SemaDiagnostic.h"
60
61
#include " clang/Lex/Preprocessor.h"
61
62
#include " clang/Sema/Lookup.h"
62
63
@@ -152,6 +153,8 @@ bool ClangImporter::Implementation::recordHasReferenceSemantics(
152
153
return false ;
153
154
154
155
return decl->hasAttrs () && llvm::any_of (decl->getAttrs (), [](auto *attr) {
156
+ // ACTODO: Check versioned attrs in case of
157
+ // captureSwiftVersionIndependentAPINotes
155
158
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
156
159
return swiftAttr->getAttribute () == " import_reference" ||
157
160
// TODO: Remove this once libSwift hosttools no longer
@@ -8356,6 +8359,67 @@ static bool isUsingMacroName(clang::SourceManager &SM,
8356
8359
return content == MacroName;
8357
8360
}
8358
8361
8362
+ static void filterUsableVersionedAttrs (const clang::NamedDecl *clangDecl,
8363
+ llvm::VersionTuple currentVersion,
8364
+ std::unordered_set<clang::Attr*> &discardVersionedAttrSet) {
8365
+ // Scan through Swift-Versioned clang attributes and select which one to apply
8366
+ // if multiple candidates exist.
8367
+ SmallVector<clang::SwiftVersionedAttr*, 4 > swiftVersionedAttributes;
8368
+ for (auto attr : clangDecl->attrs ())
8369
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr))
8370
+ swiftVersionedAttributes.push_back (versionedAttr);
8371
+
8372
+ // An attribute version is valid to apply if it is greater than the current version
8373
+ // or is unversioned
8374
+ auto applicableVersion = [currentVersion] (clang::VersionTuple attrVersion) -> bool {
8375
+ return attrVersion.empty () || attrVersion >= currentVersion;
8376
+ };
8377
+
8378
+ // We have a better attribute option if there exists another versioned attr
8379
+ // wrapper for this attribute kind with a valid version that is lower than the
8380
+ // one of the attribute we are considering
8381
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion]
8382
+ (clang::VersionTuple attrVersion, clang::attr::Kind attrKind) -> bool {
8383
+ for (auto VAI = swiftVersionedAttributes.begin (),
8384
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8385
+ auto otherVersionedAttr = *VAI;
8386
+ auto otherAttrKind = otherVersionedAttr->getAttrToAdd ()->getKind ();
8387
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
8388
+ // Same exact attribute, ignore
8389
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
8390
+ continue ;
8391
+
8392
+ // For a matching attribute kind, an un-versioned attribute
8393
+ // never takes precedence over an exsiting valid versioned one.
8394
+ if (otherAttrKind == attrKind && !attrVersion.empty () && otherAttrVersion.empty ())
8395
+ continue ;
8396
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) && attrVersion.empty ())
8397
+ return true ;
8398
+
8399
+ // For two versioned attributes of the same kind, the one with the lower applicable
8400
+ // version takes precedence.
8401
+ if (otherAttrKind == attrKind &&
8402
+ applicableVersion (otherAttrVersion) &&
8403
+ otherAttrVersion < attrVersion)
8404
+ return true ;
8405
+ }
8406
+ return false ;
8407
+ };
8408
+
8409
+ for (auto VAI = swiftVersionedAttributes.begin (),
8410
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8411
+ auto versionedAttr = *VAI;
8412
+ auto attrKind = versionedAttr->getAttrToAdd ()->getKind ();
8413
+ auto attrVersion = versionedAttr->getVersion ();
8414
+ if (!applicableVersion (attrVersion))
8415
+ discardVersionedAttrSet.insert (versionedAttr);
8416
+ else if (haveBetterAttr (attrVersion, attrKind))
8417
+ discardVersionedAttrSet.insert (versionedAttr);
8418
+ else
8419
+ continue ;
8420
+ }
8421
+ }
8422
+
8359
8423
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
8360
8424
{
8361
8425
// 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.
@@ -8389,17 +8453,39 @@ void ClangImporter::Implementation::importAttributes(
8389
8453
if (auto func = dyn_cast<AbstractFunctionDecl>(MappedDecl))
8390
8454
isAsync = func->hasAsync ();
8391
8455
8456
+ // Determine which versioned attributes are applicable
8457
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
8458
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
8459
+ filterUsableVersionedAttrs (ClangDecl, CurrentVersion.asClangVersionTuple (),
8460
+ discardVersionedAttrSet);
8461
+
8392
8462
// Scan through Clang attributes and map them onto Swift
8393
8463
// equivalents.
8394
8464
bool AnyUnavailable = MappedDecl->getAttrs ().isUnavailable (C);
8395
8465
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
8396
8466
AE = ClangDecl->attr_end (); AI != AE; ++AI) {
8467
+ clang::Attr *consideringAttr = *AI;
8468
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
8469
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(consideringAttr)) {
8470
+ // "type" and "nullability" attributes are handled earlier since they change
8471
+ // the decl's type.
8472
+ if (isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) ||
8473
+ isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ()))
8474
+ continue ;
8475
+
8476
+ if (discardVersionedAttrSet.count (versionedAttr))
8477
+ continue ;
8478
+
8479
+ consideringAttr = versionedAttr->getAttrToAdd ();
8480
+ }
8481
+ }
8482
+
8397
8483
//
8398
8484
// __attribute__((unavailable))
8399
8485
//
8400
8486
// Mapping: @available(*,unavailable)
8401
8487
//
8402
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
8488
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
8403
8489
auto Message = unavailable->getMessage ();
8404
8490
auto attr = AvailableAttr::createPlatformAgnostic (C, Message);
8405
8491
MappedDecl->getAttrs ().add (attr);
@@ -8412,7 +8498,7 @@ void ClangImporter::Implementation::importAttributes(
8412
8498
//
8413
8499
// Mapping: @available(*, unavailable)
8414
8500
//
8415
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
8501
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
8416
8502
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
8417
8503
auto attr = AvailableAttr::createPlatformAgnostic (
8418
8504
C, " " , " " , PlatformAgnosticAvailabilityKind::UnavailableInSwift);
@@ -8426,7 +8512,7 @@ void ClangImporter::Implementation::importAttributes(
8426
8512
//
8427
8513
// Mapping: @available(*,deprecated)
8428
8514
//
8429
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
8515
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
8430
8516
auto Message = deprecated->getMessage ();
8431
8517
auto attr = AvailableAttr::createPlatformAgnostic (C, Message, " " ,
8432
8518
PlatformAgnosticAvailabilityKind::Deprecated);
@@ -8436,7 +8522,7 @@ void ClangImporter::Implementation::importAttributes(
8436
8522
8437
8523
// __attribute__((availability))
8438
8524
//
8439
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
8525
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
8440
8526
StringRef Platform = avail->getPlatform ()->getName ();
8441
8527
8442
8528
// Is this our special "availability(swift, unavailable)" attribute?
@@ -8648,6 +8734,62 @@ void ClangImporter::Implementation::importAttributes(
8648
8734
}
8649
8735
}
8650
8736
8737
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
8738
+ clang::Sema &Sema,
8739
+ const ImportNameVersion CurrentImporterVersion) {
8740
+ // Determine which versioned attributes are applicable
8741
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
8742
+ filterUsableVersionedAttrs (ClangDecl,
8743
+ CurrentImporterVersion.asClangVersionTuple (),
8744
+ discardVersionedAttrSet);
8745
+
8746
+ // When importing from a module built with version-independent APINotes payload,
8747
+ // the decl will carry all possible versioned notes, without directly applying any
8748
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
8749
+ // since they change the actual type of the decl as seen downstream.
8750
+ //
8751
+ // Other kinds of notes will be handled in `importAttributes`.
8752
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
8753
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
8754
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(*AI)) {
8755
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) &&
8756
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
8757
+ continue ;
8758
+ }
8759
+
8760
+ if (discardVersionedAttrSet.count (versionedAttr))
8761
+ continue ;
8762
+
8763
+ // Apply Type APINotes
8764
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ())) {
8765
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
8766
+ typeRenameAttr->getTypeString ());
8767
+ }
8768
+
8769
+ // Apply Nullability APINotes
8770
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
8771
+ clang::NullabilityKind nullability;
8772
+ switch (nullabilityAttr->getKind ()) {
8773
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
8774
+ nullability = clang::NullabilityKind::NonNull;
8775
+ break ;
8776
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
8777
+ nullability = clang::NullabilityKind::Nullable;
8778
+ break ;
8779
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
8780
+ nullability = clang::NullabilityKind::Unspecified;
8781
+ break ;
8782
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
8783
+ nullability = clang::NullabilityKind::NullableResult;
8784
+ break ;
8785
+ }
8786
+
8787
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
8788
+ }
8789
+ }
8790
+ }
8791
+ }
8792
+
8651
8793
Decl *
8652
8794
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
8653
8795
ImportNameVersion version,
@@ -8670,14 +8812,20 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8670
8812
if (access == clang::AS_protected || access == clang::AS_private)
8671
8813
return nullptr ;
8672
8814
8815
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
8816
+ // notes are applied by the client (Importer) instead of the producer of the
8817
+ // Clang module we are consuming. Do so now, early, since these notes
8818
+ // affect the decl's type.
8819
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
8820
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
8821
+
8673
8822
bool SkippedOverTypedef = false ;
8674
8823
Decl *Result = nullptr ;
8675
8824
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
8676
8825
TypedefIsSuperfluous)) {
8677
8826
Result = importDecl (UnderlyingDecl, version);
8678
8827
SkippedOverTypedef = true ;
8679
8828
}
8680
-
8681
8829
if (!Result) {
8682
8830
SwiftDeclConverter converter (*this , version);
8683
8831
Result = converter.Visit (ClangDecl);
0 commit comments