57
57
#include " clang/Basic/CharInfo.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
@@ -8238,6 +8241,67 @@ static bool isUsingMacroName(clang::SourceManager &SM,
8238
8241
return content == MacroName;
8239
8242
}
8240
8243
8244
+ static void filterUsableVersionedAttrs (const clang::NamedDecl *clangDecl,
8245
+ llvm::VersionTuple currentVersion,
8246
+ std::unordered_set<clang::Attr*> &discardVersionedAttrSet) {
8247
+ // Scan through Swift-Versioned clang attributes and select which one to apply
8248
+ // if multiple candidates exist.
8249
+ SmallVector<clang::SwiftVersionedAttr*, 4 > swiftVersionedAttributes;
8250
+ for (auto attr : clangDecl->attrs ())
8251
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr))
8252
+ swiftVersionedAttributes.push_back (versionedAttr);
8253
+
8254
+ // An attribute version is valid to apply if it is greater than the current version
8255
+ // or is unversioned
8256
+ auto applicableVersion = [currentVersion] (clang::VersionTuple attrVersion) -> bool {
8257
+ return attrVersion.empty () || attrVersion >= currentVersion;
8258
+ };
8259
+
8260
+ // We have a better attribute option if there exists another versioned attr
8261
+ // wrapper for this attribute kind with a valid version that is lower than the
8262
+ // one of the attribute we are considering
8263
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion]
8264
+ (clang::VersionTuple attrVersion, clang::attr::Kind attrKind) -> bool {
8265
+ for (auto VAI = swiftVersionedAttributes.begin (),
8266
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8267
+ auto otherVersionedAttr = *VAI;
8268
+ auto otherAttrKind = otherVersionedAttr->getAttrToAdd ()->getKind ();
8269
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
8270
+ // Same exact attribute, ignore
8271
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
8272
+ continue ;
8273
+
8274
+ // For a matching attribute kind, an un-versioned attribute
8275
+ // never takes precedence over an exsiting valid versioned one.
8276
+ if (otherAttrKind == attrKind && !attrVersion.empty () && otherAttrVersion.empty ())
8277
+ continue ;
8278
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) && attrVersion.empty ())
8279
+ return true ;
8280
+
8281
+ // For two versioned attributes of the same kind, the one with the lower applicable
8282
+ // version takes precedence.
8283
+ if (otherAttrKind == attrKind &&
8284
+ applicableVersion (otherAttrVersion) &&
8285
+ otherAttrVersion < attrVersion)
8286
+ return true ;
8287
+ }
8288
+ return false ;
8289
+ };
8290
+
8291
+ for (auto VAI = swiftVersionedAttributes.begin (),
8292
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8293
+ auto versionedAttr = *VAI;
8294
+ auto attrKind = versionedAttr->getAttrToAdd ()->getKind ();
8295
+ auto attrVersion = versionedAttr->getVersion ();
8296
+ if (!applicableVersion (attrVersion))
8297
+ discardVersionedAttrSet.insert (versionedAttr);
8298
+ else if (haveBetterAttr (attrVersion, attrKind))
8299
+ discardVersionedAttrSet.insert (versionedAttr);
8300
+ else
8301
+ continue ;
8302
+ }
8303
+ }
8304
+
8241
8305
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
8242
8306
{
8243
8307
// 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.
@@ -8271,17 +8335,39 @@ void ClangImporter::Implementation::importAttributes(
8271
8335
if (auto func = dyn_cast<AbstractFunctionDecl>(MappedDecl))
8272
8336
isAsync = func->hasAsync ();
8273
8337
8338
+ // Determine which versioned attributes are applicable
8339
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
8340
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
8341
+ filterUsableVersionedAttrs (ClangDecl, CurrentVersion.asClangVersionTuple (),
8342
+ discardVersionedAttrSet);
8343
+
8274
8344
// Scan through Clang attributes and map them onto Swift
8275
8345
// equivalents.
8276
8346
bool AnyUnavailable = MappedDecl->getAttrs ().isUnavailable (C);
8277
8347
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
8278
8348
AE = ClangDecl->attr_end (); AI != AE; ++AI) {
8349
+ clang::Attr *consideringAttr = *AI;
8350
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
8351
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(consideringAttr)) {
8352
+ // "type" and "nullability" attributes are handled earlier since they change
8353
+ // the decl's type.
8354
+ if (isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) ||
8355
+ isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ()))
8356
+ continue ;
8357
+
8358
+ if (discardVersionedAttrSet.count (versionedAttr))
8359
+ continue ;
8360
+
8361
+ consideringAttr = versionedAttr->getAttrToAdd ();
8362
+ }
8363
+ }
8364
+
8279
8365
//
8280
8366
// __attribute__((unavailable))
8281
8367
//
8282
8368
// Mapping: @available(*,unavailable)
8283
8369
//
8284
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
8370
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
8285
8371
auto Message = unavailable->getMessage ();
8286
8372
auto attr = AvailableAttr::createPlatformAgnostic (C, Message);
8287
8373
MappedDecl->getAttrs ().add (attr);
@@ -8294,7 +8380,7 @@ void ClangImporter::Implementation::importAttributes(
8294
8380
//
8295
8381
// Mapping: @available(*, unavailable)
8296
8382
//
8297
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
8383
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
8298
8384
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
8299
8385
auto attr = AvailableAttr::createPlatformAgnostic (
8300
8386
C, " " , " " , PlatformAgnosticAvailabilityKind::UnavailableInSwift);
@@ -8308,7 +8394,7 @@ void ClangImporter::Implementation::importAttributes(
8308
8394
//
8309
8395
// Mapping: @available(*,deprecated)
8310
8396
//
8311
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
8397
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
8312
8398
auto Message = deprecated->getMessage ();
8313
8399
auto attr = AvailableAttr::createPlatformAgnostic (C, Message, " " ,
8314
8400
PlatformAgnosticAvailabilityKind::Deprecated);
@@ -8318,7 +8404,7 @@ void ClangImporter::Implementation::importAttributes(
8318
8404
8319
8405
// __attribute__((availability))
8320
8406
//
8321
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
8407
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
8322
8408
StringRef Platform = avail->getPlatform ()->getName ();
8323
8409
8324
8410
// Is this our special "availability(swift, unavailable)" attribute?
@@ -8530,6 +8616,62 @@ void ClangImporter::Implementation::importAttributes(
8530
8616
}
8531
8617
}
8532
8618
8619
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
8620
+ clang::Sema &Sema,
8621
+ const ImportNameVersion CurrentImporterVersion) {
8622
+ // Determine which versioned attributes are applicable
8623
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
8624
+ filterUsableVersionedAttrs (ClangDecl,
8625
+ CurrentImporterVersion.asClangVersionTuple (),
8626
+ discardVersionedAttrSet);
8627
+
8628
+ // When importing from a module built with version-independent APINotes payload,
8629
+ // the decl will carry all possible versioned notes, without directly applying any
8630
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
8631
+ // since they change the actual type of the decl as seen downstream.
8632
+ //
8633
+ // Other kinds of notes will be handled in `importAttributes`.
8634
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
8635
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
8636
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(*AI)) {
8637
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) &&
8638
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
8639
+ continue ;
8640
+ }
8641
+
8642
+ if (discardVersionedAttrSet.count (versionedAttr))
8643
+ continue ;
8644
+
8645
+ // Apply Type APINotes
8646
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ())) {
8647
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
8648
+ typeRenameAttr->getTypeString ());
8649
+ }
8650
+
8651
+ // Apply Nullability APINotes
8652
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
8653
+ clang::NullabilityKind nullability;
8654
+ switch (nullabilityAttr->getKind ()) {
8655
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
8656
+ nullability = clang::NullabilityKind::NonNull;
8657
+ break ;
8658
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
8659
+ nullability = clang::NullabilityKind::Nullable;
8660
+ break ;
8661
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
8662
+ nullability = clang::NullabilityKind::Unspecified;
8663
+ break ;
8664
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
8665
+ nullability = clang::NullabilityKind::NullableResult;
8666
+ break ;
8667
+ }
8668
+
8669
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
8670
+ }
8671
+ }
8672
+ }
8673
+ }
8674
+
8533
8675
Decl *
8534
8676
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
8535
8677
ImportNameVersion version,
@@ -8552,14 +8694,20 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8552
8694
if (access == clang::AS_protected || access == clang::AS_private)
8553
8695
return nullptr ;
8554
8696
8697
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
8698
+ // notes are applied by the client (Importer) instead of the producer of the
8699
+ // Clang module we are consuming. Do so now, early, since these notes
8700
+ // affect the decl's type.
8701
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
8702
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
8703
+
8555
8704
bool SkippedOverTypedef = false ;
8556
8705
Decl *Result = nullptr ;
8557
8706
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
8558
8707
TypedefIsSuperfluous)) {
8559
8708
Result = importDecl (UnderlyingDecl, version);
8560
8709
SkippedOverTypedef = true ;
8561
8710
}
8562
-
8563
8711
if (!Result) {
8564
8712
SwiftDeclConverter converter (*this , version);
8565
8713
Result = converter.Visit (ClangDecl);
0 commit comments