7070#include " clang/AST/Type.h"
7171#include " clang/Basic/Specifiers.h"
7272#include " clang/Basic/TargetInfo.h"
73+ #include " clang/Sema/SemaDiagnostic.h"
7374#include " clang/Lex/Preprocessor.h"
7475#include " clang/Sema/Lookup.h"
7576
@@ -9481,6 +9482,72 @@ static bool isUsingMacroName(clang::SourceManager &SM,
94819482 return content == MacroName;
94829483}
94839484
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+
94849551void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
94859552{
94869553 // 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(
97919858 }
97929859}
97939860
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+
97949931Decl *
97959932ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
97969933 ImportNameVersion version,
@@ -9802,6 +9939,21 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
98029939 if (ClangDecl->isInvalidDecl ())
98039940 return nullptr ;
98049941
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+
98059957 bool SkippedOverTypedef = false ;
98069958 Decl *Result = nullptr ;
98079959 if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
0 commit comments