70
70
#include " clang/AST/Type.h"
71
71
#include " clang/Basic/Specifiers.h"
72
72
#include " clang/Basic/TargetInfo.h"
73
+ #include " clang/Sema/SemaDiagnostic.h"
73
74
#include " clang/Lex/Preprocessor.h"
74
75
#include " clang/Sema/Lookup.h"
75
76
@@ -9481,6 +9482,72 @@ static bool isUsingMacroName(clang::SourceManager &SM,
9481
9482
return content == MacroName;
9482
9483
}
9483
9484
9485
+ static void filterUsableVersionedAttrs (
9486
+ const clang::NamedDecl *clangDecl, llvm::VersionTuple currentVersion,
9487
+ std::set<clang::SwiftVersionedAdditionAttr *> &applicableVersionedAttrSet) {
9488
+ // Scan through Swift-Versioned clang attributes and select which one to apply
9489
+ // if multiple candidates exist.
9490
+ SmallVector<clang::SwiftVersionedAdditionAttr *, 4 > swiftVersionedAttributes;
9491
+ for (auto attr : clangDecl->attrs ())
9492
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(attr))
9493
+ swiftVersionedAttributes.push_back (versionedAttr);
9494
+
9495
+ // An attribute version is valid to apply if it is greater than the current
9496
+ // version or is unversioned
9497
+ auto applicableVersion =
9498
+ [currentVersion](clang::VersionTuple attrVersion) -> bool {
9499
+ return attrVersion.empty () || attrVersion >= currentVersion;
9500
+ };
9501
+
9502
+ // We have a better attribute option if there exists another versioned attr
9503
+ // wrapper for this attribute kind with a valid version that is lower than the
9504
+ // one of the attribute we are considering
9505
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion](
9506
+ clang::VersionTuple attrVersion,
9507
+ clang::attr::Kind attrKind) -> bool {
9508
+ for (auto VAI = swiftVersionedAttributes.begin (),
9509
+ VAE = swiftVersionedAttributes.end ();
9510
+ VAI != VAE; ++VAI) {
9511
+ auto otherVersionedAttr = *VAI;
9512
+ auto otherAttrKind = otherVersionedAttr->getAdditionalAttr ()->getKind ();
9513
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
9514
+ // Same exact attribute, ignore
9515
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
9516
+ continue ;
9517
+
9518
+ // For a matching attribute kind, an un-versioned attribute
9519
+ // never takes precedence over an exsiting valid versioned one.
9520
+ if (otherAttrKind == attrKind && !attrVersion.empty () &&
9521
+ otherAttrVersion.empty ())
9522
+ continue ;
9523
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) &&
9524
+ attrVersion.empty ())
9525
+ return true ;
9526
+
9527
+ // For two versioned attributes of the same kind, the one with the lower
9528
+ // applicable version takes precedence.
9529
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) &&
9530
+ otherAttrVersion < attrVersion)
9531
+ return true ;
9532
+ }
9533
+ return false ;
9534
+ };
9535
+
9536
+ for (auto VAI = swiftVersionedAttributes.begin (),
9537
+ VAE = swiftVersionedAttributes.end ();
9538
+ VAI != VAE; ++VAI) {
9539
+ auto versionedAttr = *VAI;
9540
+ auto attrKind = versionedAttr->getAdditionalAttr ()->getKind ();
9541
+ auto attrVersion = versionedAttr->getVersion ();
9542
+ if (!applicableVersion (attrVersion))
9543
+ continue ;
9544
+ else if (haveBetterAttr (attrVersion, attrKind))
9545
+ continue ;
9546
+ else
9547
+ applicableVersionedAttrSet.insert (versionedAttr);
9548
+ }
9549
+ }
9550
+
9484
9551
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
9485
9552
{
9486
9553
// 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.
@@ -9791,6 +9858,76 @@ void ClangImporter::Implementation::importAttributes(
9791
9858
}
9792
9859
}
9793
9860
9861
+ static void applyTypeAndNullabilityAPINotes (
9862
+ const clang::NamedDecl *ClangDecl, clang::Sema &Sema,
9863
+ const ImportNameVersion CurrentImporterVersion) {
9864
+ // When importing from a module built with version-independent APINotes
9865
+ // payload, the decl will carry all possible versioned notes, without directly
9866
+ // applying any of them. For "type" and "nullability" notes, we must apply
9867
+ // them first, here, since they change the actual type of the decl as seen
9868
+ // downstream.
9869
+ //
9870
+ // Other kinds of notes will be handled in `importAttributes`.
9871
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9872
+ AE = ClangDecl->attr_end ();
9873
+ AI != AE; ++AI) {
9874
+ if (!isa<clang::SwiftTypeAttr>(*AI) &&
9875
+ !isa<clang::SwiftNullabilityAttr>(*AI))
9876
+ continue ;
9877
+
9878
+ // Apply Type APINotes
9879
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(*AI)) {
9880
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl *>(ClangDecl),
9881
+ typeRenameAttr->getTypeString ());
9882
+ }
9883
+
9884
+ // Apply Nullability APINotes
9885
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(*AI)) {
9886
+ clang::NullabilityKind nullability;
9887
+ switch (nullabilityAttr->getKind ()) {
9888
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
9889
+ nullability = clang::NullabilityKind::NonNull;
9890
+ break ;
9891
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
9892
+ nullability = clang::NullabilityKind::Nullable;
9893
+ break ;
9894
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
9895
+ nullability = clang::NullabilityKind::Unspecified;
9896
+ break ;
9897
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
9898
+ nullability = clang::NullabilityKind::NullableResult;
9899
+ break ;
9900
+ }
9901
+
9902
+ Sema.ApplyNullability (const_cast <clang::NamedDecl *>(ClangDecl),
9903
+ nullability);
9904
+ }
9905
+ }
9906
+ }
9907
+
9908
+ static void canonicalizeVersionedSwiftAttributes (
9909
+ const clang::NamedDecl *ClangDecl,
9910
+ const ImportNameVersion CurrentImporterVersion) {
9911
+ if (!ClangDecl->hasAttrs ())
9912
+ return ;
9913
+
9914
+ // Filter out only the versioned attributes which apply to the
9915
+ // current compilation's language version
9916
+ std::set<clang::SwiftVersionedAdditionAttr *> applicableVersionedAttrSet;
9917
+ filterUsableVersionedAttrs (ClangDecl,
9918
+ CurrentImporterVersion.asClangVersionTuple (),
9919
+ applicableVersionedAttrSet);
9920
+
9921
+ // Drop all versioned addition attributes and re-add
9922
+ // above-filtered out applicable attributes in a non-versioned
9923
+ // form in order to ensure all downstream clients
9924
+ // get the expected attribute view.
9925
+ auto mutableDecl = const_cast <clang::NamedDecl *>(ClangDecl);
9926
+ mutableDecl->dropAttrs <clang::SwiftVersionedAdditionAttr>();
9927
+ for (const auto &attr : applicableVersionedAttrSet)
9928
+ mutableDecl->addAttr (attr->getAdditionalAttr ());
9929
+ }
9930
+
9794
9931
Decl *
9795
9932
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
9796
9933
ImportNameVersion version,
@@ -9802,6 +9939,21 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
9802
9939
if (ClangDecl->isInvalidDecl ())
9803
9940
return nullptr ;
9804
9941
9942
+ // If '-version-independent-apinotes' is used, the `ClangDecl`
9943
+ // will be carrying various APINotes-sourced attributes wrapped
9944
+ // in `SwiftVersionedAdditionAttr`. Filter out which ones are applicable
9945
+ // for the current compilation version and rewrite the set of versioned
9946
+ // attributes with the corresponding subset of only applicable wrapped
9947
+ // attributes.
9948
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
9949
+ canonicalizeVersionedSwiftAttributes (ClangDecl, CurrentVersion);
9950
+ // When '-version-independent-apinotes' is used, "type" and "nullability"
9951
+ // notes are applied by the client (Importer) instead of the producer of the
9952
+ // Clang module we are consuming. Do so now, early, since these notes
9953
+ // affect the decl's type and require mutation.
9954
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
9955
+ }
9956
+
9805
9957
bool SkippedOverTypedef = false ;
9806
9958
Decl *Result = nullptr ;
9807
9959
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
0 commit comments