60
60
#include " clang/AST/Type.h"
61
61
#include " clang/Basic/Specifiers.h"
62
62
#include " clang/Basic/TargetInfo.h"
63
+ #include " clang/Sema/SemaDiagnostic.h"
63
64
#include " clang/Lex/Preprocessor.h"
64
65
#include " clang/Sema/Lookup.h"
65
66
@@ -155,6 +156,8 @@ bool ClangImporter::Implementation::recordHasReferenceSemantics(
155
156
return false ;
156
157
157
158
return decl->hasAttrs () && llvm::any_of (decl->getAttrs (), [](auto *attr) {
159
+ // ACTODO: Check versioned attrs in case of
160
+ // captureSwiftVersionIndependentAPINotes
158
161
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
159
162
return swiftAttr->getAttribute () == " import_reference" ||
160
163
// TODO: Remove this once libSwift hosttools no longer
@@ -8513,6 +8516,67 @@ static bool isUsingMacroName(clang::SourceManager &SM,
8513
8516
return content == MacroName;
8514
8517
}
8515
8518
8519
+ static void filterUsableVersionedAttrs (const clang::NamedDecl *clangDecl,
8520
+ llvm::VersionTuple currentVersion,
8521
+ std::unordered_set<clang::Attr*> &discardVersionedAttrSet) {
8522
+ // Scan through Swift-Versioned clang attributes and select which one to apply
8523
+ // if multiple candidates exist.
8524
+ SmallVector<clang::SwiftVersionedAttr*, 4 > swiftVersionedAttributes;
8525
+ for (auto attr : clangDecl->attrs ())
8526
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr))
8527
+ swiftVersionedAttributes.push_back (versionedAttr);
8528
+
8529
+ // An attribute version is valid to apply if it is greater than the current version
8530
+ // or is unversioned
8531
+ auto applicableVersion = [currentVersion] (clang::VersionTuple attrVersion) -> bool {
8532
+ return attrVersion.empty () || attrVersion >= currentVersion;
8533
+ };
8534
+
8535
+ // We have a better attribute option if there exists another versioned attr
8536
+ // wrapper for this attribute kind with a valid version that is lower than the
8537
+ // one of the attribute we are considering
8538
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion]
8539
+ (clang::VersionTuple attrVersion, clang::attr::Kind attrKind) -> bool {
8540
+ for (auto VAI = swiftVersionedAttributes.begin (),
8541
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8542
+ auto otherVersionedAttr = *VAI;
8543
+ auto otherAttrKind = otherVersionedAttr->getAttrToAdd ()->getKind ();
8544
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
8545
+ // Same exact attribute, ignore
8546
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
8547
+ continue ;
8548
+
8549
+ // For a matching attribute kind, an un-versioned attribute
8550
+ // never takes precedence over an exsiting valid versioned one.
8551
+ if (otherAttrKind == attrKind && !attrVersion.empty () && otherAttrVersion.empty ())
8552
+ continue ;
8553
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) && attrVersion.empty ())
8554
+ return true ;
8555
+
8556
+ // For two versioned attributes of the same kind, the one with the lower applicable
8557
+ // version takes precedence.
8558
+ if (otherAttrKind == attrKind &&
8559
+ applicableVersion (otherAttrVersion) &&
8560
+ otherAttrVersion < attrVersion)
8561
+ return true ;
8562
+ }
8563
+ return false ;
8564
+ };
8565
+
8566
+ for (auto VAI = swiftVersionedAttributes.begin (),
8567
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8568
+ auto versionedAttr = *VAI;
8569
+ auto attrKind = versionedAttr->getAttrToAdd ()->getKind ();
8570
+ auto attrVersion = versionedAttr->getVersion ();
8571
+ if (!applicableVersion (attrVersion))
8572
+ discardVersionedAttrSet.insert (versionedAttr);
8573
+ else if (haveBetterAttr (attrVersion, attrKind))
8574
+ discardVersionedAttrSet.insert (versionedAttr);
8575
+ else
8576
+ continue ;
8577
+ }
8578
+ }
8579
+
8516
8580
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
8517
8581
{
8518
8582
// 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.
@@ -8546,17 +8610,39 @@ void ClangImporter::Implementation::importAttributes(
8546
8610
if (auto func = dyn_cast<AbstractFunctionDecl>(MappedDecl))
8547
8611
isAsync = func->hasAsync ();
8548
8612
8613
+ // Determine which versioned attributes are applicable
8614
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
8615
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
8616
+ filterUsableVersionedAttrs (ClangDecl, CurrentVersion.asClangVersionTuple (),
8617
+ discardVersionedAttrSet);
8618
+
8549
8619
// Scan through Clang attributes and map them onto Swift
8550
8620
// equivalents.
8551
8621
bool AnyUnavailable = MappedDecl->getAttrs ().isUnavailable (C);
8552
8622
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
8553
8623
AE = ClangDecl->attr_end (); AI != AE; ++AI) {
8624
+ clang::Attr *consideringAttr = *AI;
8625
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
8626
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(consideringAttr)) {
8627
+ // "type" and "nullability" attributes are handled earlier since they change
8628
+ // the decl's type.
8629
+ if (isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) ||
8630
+ isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ()))
8631
+ continue ;
8632
+
8633
+ if (discardVersionedAttrSet.count (versionedAttr))
8634
+ continue ;
8635
+
8636
+ consideringAttr = versionedAttr->getAttrToAdd ();
8637
+ }
8638
+ }
8639
+
8554
8640
//
8555
8641
// __attribute__((unavailable))
8556
8642
//
8557
8643
// Mapping: @available(*,unavailable)
8558
8644
//
8559
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
8645
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
8560
8646
auto Message = unavailable->getMessage ();
8561
8647
auto attr = AvailableAttr::createPlatformAgnostic (C, Message);
8562
8648
MappedDecl->getAttrs ().add (attr);
@@ -8569,7 +8655,7 @@ void ClangImporter::Implementation::importAttributes(
8569
8655
//
8570
8656
// Mapping: @available(*, unavailable)
8571
8657
//
8572
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
8658
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
8573
8659
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
8574
8660
auto attr = AvailableAttr::createPlatformAgnostic (
8575
8661
C, " " , " " , PlatformAgnosticAvailabilityKind::UnavailableInSwift);
@@ -8583,7 +8669,7 @@ void ClangImporter::Implementation::importAttributes(
8583
8669
//
8584
8670
// Mapping: @available(*,deprecated)
8585
8671
//
8586
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
8672
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
8587
8673
auto Message = deprecated->getMessage ();
8588
8674
auto attr = AvailableAttr::createPlatformAgnostic (C, Message, " " ,
8589
8675
PlatformAgnosticAvailabilityKind::Deprecated);
@@ -8593,7 +8679,7 @@ void ClangImporter::Implementation::importAttributes(
8593
8679
8594
8680
// __attribute__((availability))
8595
8681
//
8596
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
8682
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
8597
8683
StringRef Platform = avail->getPlatform ()->getName ();
8598
8684
8599
8685
// Is this our special "availability(swift, unavailable)" attribute?
@@ -8805,6 +8891,62 @@ void ClangImporter::Implementation::importAttributes(
8805
8891
}
8806
8892
}
8807
8893
8894
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
8895
+ clang::Sema &Sema,
8896
+ const ImportNameVersion CurrentImporterVersion) {
8897
+ // Determine which versioned attributes are applicable
8898
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
8899
+ filterUsableVersionedAttrs (ClangDecl,
8900
+ CurrentImporterVersion.asClangVersionTuple (),
8901
+ discardVersionedAttrSet);
8902
+
8903
+ // When importing from a module built with version-independent APINotes payload,
8904
+ // the decl will carry all possible versioned notes, without directly applying any
8905
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
8906
+ // since they change the actual type of the decl as seen downstream.
8907
+ //
8908
+ // Other kinds of notes will be handled in `importAttributes`.
8909
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
8910
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
8911
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(*AI)) {
8912
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) &&
8913
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
8914
+ continue ;
8915
+ }
8916
+
8917
+ if (discardVersionedAttrSet.count (versionedAttr))
8918
+ continue ;
8919
+
8920
+ // Apply Type APINotes
8921
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ())) {
8922
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
8923
+ typeRenameAttr->getTypeString ());
8924
+ }
8925
+
8926
+ // Apply Nullability APINotes
8927
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
8928
+ clang::NullabilityKind nullability;
8929
+ switch (nullabilityAttr->getKind ()) {
8930
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
8931
+ nullability = clang::NullabilityKind::NonNull;
8932
+ break ;
8933
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
8934
+ nullability = clang::NullabilityKind::Nullable;
8935
+ break ;
8936
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
8937
+ nullability = clang::NullabilityKind::Unspecified;
8938
+ break ;
8939
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
8940
+ nullability = clang::NullabilityKind::NullableResult;
8941
+ break ;
8942
+ }
8943
+
8944
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
8945
+ }
8946
+ }
8947
+ }
8948
+ }
8949
+
8808
8950
Decl *
8809
8951
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
8810
8952
ImportNameVersion version,
@@ -8827,14 +8969,20 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8827
8969
if (access == clang::AS_protected || access == clang::AS_private)
8828
8970
return nullptr ;
8829
8971
8972
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
8973
+ // notes are applied by the client (Importer) instead of the producer of the
8974
+ // Clang module we are consuming. Do so now, early, since these notes
8975
+ // affect the decl's type.
8976
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
8977
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
8978
+
8830
8979
bool SkippedOverTypedef = false ;
8831
8980
Decl *Result = nullptr ;
8832
8981
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
8833
8982
TypedefIsSuperfluous)) {
8834
8983
Result = importDecl (UnderlyingDecl, version);
8835
8984
SkippedOverTypedef = true ;
8836
8985
}
8837
-
8838
8986
if (!Result) {
8839
8987
SwiftDeclConverter converter (*this , version);
8840
8988
Result = converter.Visit (ClangDecl);
0 commit comments