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::SwiftVersionedAttr*, 4 > swiftVersionedAttributes;
9352
+ for (auto attr : clangDecl->attrs ())
9353
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(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->getAttrToAdd ()->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->getAttrToAdd ()->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,39 @@ 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::SwiftVersionedAttr>(consideringAttr)) {
9454
+ // "type" and "nullability" attributes are handled earlier since they change
9455
+ // the decl's type.
9456
+ if (isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) ||
9457
+ isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ()))
9458
+ continue ;
9459
+
9460
+ if (discardVersionedAttrSet.count (versionedAttr))
9461
+ continue ;
9462
+
9463
+ consideringAttr = versionedAttr->getAttrToAdd ();
9464
+ }
9465
+ }
9466
+
9380
9467
//
9381
9468
// __attribute__((unavailable))
9382
9469
//
9383
9470
// Mapping: @available(*,unavailable)
9384
9471
//
9385
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
9472
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
9386
9473
auto Message = unavailable->getMessage ();
9387
9474
auto attr = AvailableAttr::createUniversallyUnavailable (C, Message);
9388
9475
MappedDecl->getAttrs ().add (attr);
@@ -9395,7 +9482,7 @@ void ClangImporter::Implementation::importAttributes(
9395
9482
//
9396
9483
// Mapping: @available(*, unavailable)
9397
9484
//
9398
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
9485
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
9399
9486
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
9400
9487
auto attr = AvailableAttr::createUnavailableInSwift (C, " " , " " );
9401
9488
MappedDecl->getAttrs ().add (attr);
@@ -9408,7 +9495,7 @@ void ClangImporter::Implementation::importAttributes(
9408
9495
//
9409
9496
// Mapping: @available(*,deprecated)
9410
9497
//
9411
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
9498
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
9412
9499
auto Message = deprecated->getMessage ();
9413
9500
auto attr = AvailableAttr::createUniversallyDeprecated (C, Message, " " );
9414
9501
MappedDecl->getAttrs ().add (attr);
@@ -9417,7 +9504,7 @@ void ClangImporter::Implementation::importAttributes(
9417
9504
9418
9505
// __attribute__((availability))
9419
9506
//
9420
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
9507
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
9421
9508
StringRef Platform = avail->getPlatform ()->getName ();
9422
9509
9423
9510
// Is this our special "availability(swift, unavailable)" attribute?
@@ -9649,6 +9736,62 @@ void ClangImporter::Implementation::importAttributes(
9649
9736
}
9650
9737
}
9651
9738
9739
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
9740
+ clang::Sema &Sema,
9741
+ const ImportNameVersion CurrentImporterVersion) {
9742
+ // Determine which versioned attributes are applicable
9743
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9744
+ filterUsableVersionedAttrs (ClangDecl,
9745
+ CurrentImporterVersion.asClangVersionTuple (),
9746
+ discardVersionedAttrSet);
9747
+
9748
+ // When importing from a module built with version-independent APINotes payload,
9749
+ // the decl will carry all possible versioned notes, without directly applying any
9750
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
9751
+ // since they change the actual type of the decl as seen downstream.
9752
+ //
9753
+ // Other kinds of notes will be handled in `importAttributes`.
9754
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9755
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9756
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(*AI)) {
9757
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) &&
9758
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
9759
+ continue ;
9760
+ }
9761
+
9762
+ if (discardVersionedAttrSet.count (versionedAttr))
9763
+ continue ;
9764
+
9765
+ // Apply Type APINotes
9766
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ())) {
9767
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
9768
+ typeRenameAttr->getTypeString ());
9769
+ }
9770
+
9771
+ // Apply Nullability APINotes
9772
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
9773
+ clang::NullabilityKind nullability;
9774
+ switch (nullabilityAttr->getKind ()) {
9775
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
9776
+ nullability = clang::NullabilityKind::NonNull;
9777
+ break ;
9778
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
9779
+ nullability = clang::NullabilityKind::Nullable;
9780
+ break ;
9781
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
9782
+ nullability = clang::NullabilityKind::Unspecified;
9783
+ break ;
9784
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
9785
+ nullability = clang::NullabilityKind::NullableResult;
9786
+ break ;
9787
+ }
9788
+
9789
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
9790
+ }
9791
+ }
9792
+ }
9793
+ }
9794
+
9652
9795
Decl *
9653
9796
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
9654
9797
ImportNameVersion version,
@@ -9660,6 +9803,24 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
9660
9803
if (ClangDecl->isInvalidDecl ())
9661
9804
return nullptr ;
9662
9805
9806
+ // Private and protected C++ class members should never be used from Swift,
9807
+ // however, parts of the Swift typechecker rely on being able to iterate over
9808
+ // all of the stored fields of a particular struct. This means we still need
9809
+ // to add private fields to the Swift AST.
9810
+ //
9811
+ // Other kinds of private and protected C++ decls are not relevant for Swift.
9812
+ clang::AccessSpecifier access = ClangDecl->getAccess ();
9813
+ if ((access == clang::AS_protected || access == clang::AS_private) &&
9814
+ !isa<clang::FieldDecl>(ClangDecl))
9815
+ return nullptr ;
9816
+
9817
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
9818
+ // notes are applied by the client (Importer) instead of the producer of the
9819
+ // Clang module we are consuming. Do so now, early, since these notes
9820
+ // affect the decl's type.
9821
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9822
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
9823
+
9663
9824
bool SkippedOverTypedef = false ;
9664
9825
Decl *Result = nullptr ;
9665
9826
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
0 commit comments