68
68
#include " clang/AST/Type.h"
69
69
#include " clang/Basic/Specifiers.h"
70
70
#include " clang/Basic/TargetInfo.h"
71
+ #include " clang/Sema/SemaDiagnostic.h"
71
72
#include " clang/Lex/Preprocessor.h"
72
73
#include " clang/Sema/Lookup.h"
73
74
@@ -172,6 +173,9 @@ bool importer::recordHasReferenceSemantics(
172
173
!importerImpl->SwiftContext .LangOpts .CForeignReferenceTypes )
173
174
return false ;
174
175
176
+ // ACTODO: Check versioned attrs in case of
177
+ // captureSwiftVersionIndependentAPINotes
178
+
175
179
// At this point decl might not be fully imported into Swift yet, which
176
180
// means we might not have asked Clang to generate its implicit members, such
177
181
// as copy or move constructors. This would cause CxxRecordSemanticsRequest to
@@ -9339,6 +9343,67 @@ static bool isUsingMacroName(clang::SourceManager &SM,
9339
9343
return content == MacroName;
9340
9344
}
9341
9345
9346
+ static void filterUsableVersionedAttrs (const clang::NamedDecl *clangDecl,
9347
+ llvm::VersionTuple currentVersion,
9348
+ std::unordered_set<clang::Attr*> &discardVersionedAttrSet) {
9349
+ // Scan through Swift-Versioned clang attributes and select which one to apply
9350
+ // if multiple candidates exist.
9351
+ SmallVector<clang::SwiftVersionedAdditionAttr*, 4 > swiftVersionedAttributes;
9352
+ for (auto attr : clangDecl->attrs ())
9353
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(attr))
9354
+ swiftVersionedAttributes.push_back (versionedAttr);
9355
+
9356
+ // An attribute version is valid to apply if it is greater than the current version
9357
+ // or is unversioned
9358
+ auto applicableVersion = [currentVersion] (clang::VersionTuple attrVersion) -> bool {
9359
+ return attrVersion.empty () || attrVersion >= currentVersion;
9360
+ };
9361
+
9362
+ // We have a better attribute option if there exists another versioned attr
9363
+ // wrapper for this attribute kind with a valid version that is lower than the
9364
+ // one of the attribute we are considering
9365
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion]
9366
+ (clang::VersionTuple attrVersion, clang::attr::Kind attrKind) -> bool {
9367
+ for (auto VAI = swiftVersionedAttributes.begin (),
9368
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
9369
+ auto otherVersionedAttr = *VAI;
9370
+ auto otherAttrKind = otherVersionedAttr->getAdditionalAttr ()->getKind ();
9371
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
9372
+ // Same exact attribute, ignore
9373
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
9374
+ continue ;
9375
+
9376
+ // For a matching attribute kind, an un-versioned attribute
9377
+ // never takes precedence over an exsiting valid versioned one.
9378
+ if (otherAttrKind == attrKind && !attrVersion.empty () && otherAttrVersion.empty ())
9379
+ continue ;
9380
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) && attrVersion.empty ())
9381
+ return true ;
9382
+
9383
+ // For two versioned attributes of the same kind, the one with the lower applicable
9384
+ // version takes precedence.
9385
+ if (otherAttrKind == attrKind &&
9386
+ applicableVersion (otherAttrVersion) &&
9387
+ otherAttrVersion < attrVersion)
9388
+ return true ;
9389
+ }
9390
+ return false ;
9391
+ };
9392
+
9393
+ for (auto VAI = swiftVersionedAttributes.begin (),
9394
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
9395
+ auto versionedAttr = *VAI;
9396
+ auto attrKind = versionedAttr->getAdditionalAttr ()->getKind ();
9397
+ auto attrVersion = versionedAttr->getVersion ();
9398
+ if (!applicableVersion (attrVersion))
9399
+ discardVersionedAttrSet.insert (versionedAttr);
9400
+ else if (haveBetterAttr (attrVersion, attrKind))
9401
+ discardVersionedAttrSet.insert (versionedAttr);
9402
+ else
9403
+ continue ;
9404
+ }
9405
+ }
9406
+
9342
9407
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
9343
9408
{
9344
9409
// 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.
@@ -9372,17 +9437,40 @@ void ClangImporter::Implementation::importAttributes(
9372
9437
if (auto func = dyn_cast<AbstractFunctionDecl>(MappedDecl))
9373
9438
isAsync = func->hasAsync ();
9374
9439
9440
+ // Determine which versioned attributes are applicable
9441
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9442
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9443
+ filterUsableVersionedAttrs (ClangDecl, CurrentVersion.asClangVersionTuple (),
9444
+ discardVersionedAttrSet);
9445
+
9375
9446
// Scan through Clang attributes and map them onto Swift
9376
9447
// equivalents.
9377
9448
bool AnyUnavailable = MappedDecl->isUnavailable ();
9378
9449
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9379
9450
AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9451
+ clang::Attr *consideringAttr = *AI;
9452
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
9453
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(consideringAttr)) {
9454
+ // "type" and "nullability" attributes are handled earlier since they change
9455
+ // the decl's type.
9456
+ auto additionalAttr = versionedAttr->getAdditionalAttr ();
9457
+ if (isa<clang::SwiftTypeAttr>(additionalAttr) ||
9458
+ isa<clang::SwiftNullabilityAttr>(additionalAttr))
9459
+ continue ;
9460
+
9461
+ if (discardVersionedAttrSet.count (versionedAttr))
9462
+ continue ;
9463
+
9464
+ consideringAttr = additionalAttr;
9465
+ }
9466
+ }
9467
+
9380
9468
//
9381
9469
// __attribute__((unavailable))
9382
9470
//
9383
9471
// Mapping: @available(*,unavailable)
9384
9472
//
9385
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
9473
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
9386
9474
auto Message = unavailable->getMessage ();
9387
9475
auto attr = AvailableAttr::createUniversallyUnavailable (C, Message);
9388
9476
MappedDecl->getAttrs ().add (attr);
@@ -9395,7 +9483,7 @@ void ClangImporter::Implementation::importAttributes(
9395
9483
//
9396
9484
// Mapping: @available(*, unavailable)
9397
9485
//
9398
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
9486
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
9399
9487
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
9400
9488
auto attr = AvailableAttr::createUnavailableInSwift (C, " " , " " );
9401
9489
MappedDecl->getAttrs ().add (attr);
@@ -9408,7 +9496,7 @@ void ClangImporter::Implementation::importAttributes(
9408
9496
//
9409
9497
// Mapping: @available(*,deprecated)
9410
9498
//
9411
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
9499
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
9412
9500
auto Message = deprecated->getMessage ();
9413
9501
auto attr = AvailableAttr::createUniversallyDeprecated (C, Message, " " );
9414
9502
MappedDecl->getAttrs ().add (attr);
@@ -9417,7 +9505,7 @@ void ClangImporter::Implementation::importAttributes(
9417
9505
9418
9506
// __attribute__((availability))
9419
9507
//
9420
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
9508
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
9421
9509
StringRef Platform = avail->getPlatform ()->getName ();
9422
9510
9423
9511
// Is this our special "availability(swift, unavailable)" attribute?
@@ -9649,6 +9737,62 @@ void ClangImporter::Implementation::importAttributes(
9649
9737
}
9650
9738
}
9651
9739
9740
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
9741
+ clang::Sema &Sema,
9742
+ const ImportNameVersion CurrentImporterVersion) {
9743
+ // Determine which versioned attributes are applicable
9744
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9745
+ filterUsableVersionedAttrs (ClangDecl,
9746
+ CurrentImporterVersion.asClangVersionTuple (),
9747
+ discardVersionedAttrSet);
9748
+
9749
+ // When importing from a module built with version-independent APINotes payload,
9750
+ // the decl will carry all possible versioned notes, without directly applying any
9751
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
9752
+ // since they change the actual type of the decl as seen downstream.
9753
+ //
9754
+ // Other kinds of notes will be handled in `importAttributes`.
9755
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9756
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9757
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAdditionAttr>(*AI)) {
9758
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAdditionalAttr ()) &&
9759
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAdditionalAttr ())) {
9760
+ continue ;
9761
+ }
9762
+
9763
+ if (discardVersionedAttrSet.count (versionedAttr))
9764
+ continue ;
9765
+
9766
+ // Apply Type APINotes
9767
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAdditionalAttr ())) {
9768
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
9769
+ typeRenameAttr->getTypeString ());
9770
+ }
9771
+
9772
+ // Apply Nullability APINotes
9773
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAdditionalAttr ())) {
9774
+ clang::NullabilityKind nullability;
9775
+ switch (nullabilityAttr->getKind ()) {
9776
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
9777
+ nullability = clang::NullabilityKind::NonNull;
9778
+ break ;
9779
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
9780
+ nullability = clang::NullabilityKind::Nullable;
9781
+ break ;
9782
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
9783
+ nullability = clang::NullabilityKind::Unspecified;
9784
+ break ;
9785
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
9786
+ nullability = clang::NullabilityKind::NullableResult;
9787
+ break ;
9788
+ }
9789
+
9790
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
9791
+ }
9792
+ }
9793
+ }
9794
+ }
9795
+
9652
9796
Decl *
9653
9797
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
9654
9798
ImportNameVersion version,
@@ -9660,6 +9804,24 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
9660
9804
if (ClangDecl->isInvalidDecl ())
9661
9805
return nullptr ;
9662
9806
9807
+ // Private and protected C++ class members should never be used from Swift,
9808
+ // however, parts of the Swift typechecker rely on being able to iterate over
9809
+ // all of the stored fields of a particular struct. This means we still need
9810
+ // to add private fields to the Swift AST.
9811
+ //
9812
+ // Other kinds of private and protected C++ decls are not relevant for Swift.
9813
+ clang::AccessSpecifier access = ClangDecl->getAccess ();
9814
+ if ((access == clang::AS_protected || access == clang::AS_private) &&
9815
+ !isa<clang::FieldDecl>(ClangDecl))
9816
+ return nullptr ;
9817
+
9818
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
9819
+ // notes are applied by the client (Importer) instead of the producer of the
9820
+ // Clang module we are consuming. Do so now, early, since these notes
9821
+ // affect the decl's type.
9822
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9823
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
9824
+
9663
9825
bool SkippedOverTypedef = false ;
9664
9826
Decl *Result = nullptr ;
9665
9827
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
0 commit comments