64
64
#include " clang/AST/Type.h"
65
65
#include " clang/Basic/Specifiers.h"
66
66
#include " clang/Basic/TargetInfo.h"
67
+ #include " clang/Sema/SemaDiagnostic.h"
67
68
#include " clang/Lex/Preprocessor.h"
68
69
#include " clang/Sema/Lookup.h"
69
70
@@ -167,6 +168,9 @@ bool ClangImporter::Implementation::recordHasReferenceSemantics(
167
168
if (!isa<clang::CXXRecordDecl>(decl) && !ctx.LangOpts .CForeignReferenceTypes )
168
169
return false ;
169
170
171
+ // ACTODO: Check versioned attrs in case of
172
+ // captureSwiftVersionIndependentAPINotes
173
+
170
174
// At this point decl might not be fully imported into Swift yet, which
171
175
// means we might not have asked Clang to generate its implicit members, such
172
176
// as copy or move constructors. This would cause CxxRecordSemanticsRequest to
@@ -8969,6 +8973,67 @@ static bool isUsingMacroName(clang::SourceManager &SM,
8969
8973
return content == MacroName;
8970
8974
}
8971
8975
8976
+ static void filterUsableVersionedAttrs (const clang::NamedDecl *clangDecl,
8977
+ llvm::VersionTuple currentVersion,
8978
+ std::unordered_set<clang::Attr*> &discardVersionedAttrSet) {
8979
+ // Scan through Swift-Versioned clang attributes and select which one to apply
8980
+ // if multiple candidates exist.
8981
+ SmallVector<clang::SwiftVersionedAttr*, 4 > swiftVersionedAttributes;
8982
+ for (auto attr : clangDecl->attrs ())
8983
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr))
8984
+ swiftVersionedAttributes.push_back (versionedAttr);
8985
+
8986
+ // An attribute version is valid to apply if it is greater than the current version
8987
+ // or is unversioned
8988
+ auto applicableVersion = [currentVersion] (clang::VersionTuple attrVersion) -> bool {
8989
+ return attrVersion.empty () || attrVersion >= currentVersion;
8990
+ };
8991
+
8992
+ // We have a better attribute option if there exists another versioned attr
8993
+ // wrapper for this attribute kind with a valid version that is lower than the
8994
+ // one of the attribute we are considering
8995
+ auto haveBetterAttr = [swiftVersionedAttributes, applicableVersion]
8996
+ (clang::VersionTuple attrVersion, clang::attr::Kind attrKind) -> bool {
8997
+ for (auto VAI = swiftVersionedAttributes.begin (),
8998
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
8999
+ auto otherVersionedAttr = *VAI;
9000
+ auto otherAttrKind = otherVersionedAttr->getAttrToAdd ()->getKind ();
9001
+ auto otherAttrVersion = otherVersionedAttr->getVersion ();
9002
+ // Same exact attribute, ignore
9003
+ if (otherAttrKind == attrKind && otherAttrVersion == attrVersion)
9004
+ continue ;
9005
+
9006
+ // For a matching attribute kind, an un-versioned attribute
9007
+ // never takes precedence over an exsiting valid versioned one.
9008
+ if (otherAttrKind == attrKind && !attrVersion.empty () && otherAttrVersion.empty ())
9009
+ continue ;
9010
+ if (otherAttrKind == attrKind && applicableVersion (otherAttrVersion) && attrVersion.empty ())
9011
+ return true ;
9012
+
9013
+ // For two versioned attributes of the same kind, the one with the lower applicable
9014
+ // version takes precedence.
9015
+ if (otherAttrKind == attrKind &&
9016
+ applicableVersion (otherAttrVersion) &&
9017
+ otherAttrVersion < attrVersion)
9018
+ return true ;
9019
+ }
9020
+ return false ;
9021
+ };
9022
+
9023
+ for (auto VAI = swiftVersionedAttributes.begin (),
9024
+ VAE = swiftVersionedAttributes.end (); VAI != VAE; ++VAI) {
9025
+ auto versionedAttr = *VAI;
9026
+ auto attrKind = versionedAttr->getAttrToAdd ()->getKind ();
9027
+ auto attrVersion = versionedAttr->getVersion ();
9028
+ if (!applicableVersion (attrVersion))
9029
+ discardVersionedAttrSet.insert (versionedAttr);
9030
+ else if (haveBetterAttr (attrVersion, attrKind))
9031
+ discardVersionedAttrSet.insert (versionedAttr);
9032
+ else
9033
+ continue ;
9034
+ }
9035
+ }
9036
+
8972
9037
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl (Decl *sourceDecl, Decl* synthesizedDecl)
8973
9038
{
8974
9039
// 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.
@@ -9002,17 +9067,39 @@ void ClangImporter::Implementation::importAttributes(
9002
9067
if (auto func = dyn_cast<AbstractFunctionDecl>(MappedDecl))
9003
9068
isAsync = func->hasAsync ();
9004
9069
9070
+ // Determine which versioned attributes are applicable
9071
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9072
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9073
+ filterUsableVersionedAttrs (ClangDecl, CurrentVersion.asClangVersionTuple (),
9074
+ discardVersionedAttrSet);
9075
+
9005
9076
// Scan through Clang attributes and map them onto Swift
9006
9077
// equivalents.
9007
9078
bool AnyUnavailable = MappedDecl->isUnavailable ();
9008
9079
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9009
9080
AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9081
+ clang::Attr *consideringAttr = *AI;
9082
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes ) {
9083
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(consideringAttr)) {
9084
+ // "type" and "nullability" attributes are handled earlier since they change
9085
+ // the decl's type.
9086
+ if (isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) ||
9087
+ isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ()))
9088
+ continue ;
9089
+
9090
+ if (discardVersionedAttrSet.count (versionedAttr))
9091
+ continue ;
9092
+
9093
+ consideringAttr = versionedAttr->getAttrToAdd ();
9094
+ }
9095
+ }
9096
+
9010
9097
//
9011
9098
// __attribute__((unavailable))
9012
9099
//
9013
9100
// Mapping: @available(*,unavailable)
9014
9101
//
9015
- if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI )) {
9102
+ if (auto unavailable = dyn_cast<clang::UnavailableAttr>(consideringAttr )) {
9016
9103
auto Message = unavailable->getMessage ();
9017
9104
auto attr = AvailableAttr::createUniversallyUnavailable (C, Message);
9018
9105
MappedDecl->getAttrs ().add (attr);
@@ -9025,7 +9112,7 @@ void ClangImporter::Implementation::importAttributes(
9025
9112
//
9026
9113
// Mapping: @available(*, unavailable)
9027
9114
//
9028
- if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI ))
9115
+ if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(consideringAttr ))
9029
9116
if (unavailable_annot->getAnnotation () == " swift1_unavailable" ) {
9030
9117
auto attr = AvailableAttr::createUnavailableInSwift (C, " " , " " );
9031
9118
MappedDecl->getAttrs ().add (attr);
@@ -9038,7 +9125,7 @@ void ClangImporter::Implementation::importAttributes(
9038
9125
//
9039
9126
// Mapping: @available(*,deprecated)
9040
9127
//
9041
- if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI )) {
9128
+ if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(consideringAttr )) {
9042
9129
auto Message = deprecated->getMessage ();
9043
9130
auto attr = AvailableAttr::createUniversallyDeprecated (C, Message, " " );
9044
9131
MappedDecl->getAttrs ().add (attr);
@@ -9047,7 +9134,7 @@ void ClangImporter::Implementation::importAttributes(
9047
9134
9048
9135
// __attribute__((availability))
9049
9136
//
9050
- if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI )) {
9137
+ if (auto avail = dyn_cast<clang::AvailabilityAttr>(consideringAttr )) {
9051
9138
StringRef Platform = avail->getPlatform ()->getName ();
9052
9139
9053
9140
// Is this our special "availability(swift, unavailable)" attribute?
@@ -9251,6 +9338,62 @@ void ClangImporter::Implementation::importAttributes(
9251
9338
}
9252
9339
}
9253
9340
9341
+ static void applyTypeAndNullabilityAPINotes (const clang::NamedDecl *ClangDecl,
9342
+ clang::Sema &Sema,
9343
+ const ImportNameVersion CurrentImporterVersion) {
9344
+ // Determine which versioned attributes are applicable
9345
+ std::unordered_set<clang::Attr*> discardVersionedAttrSet;
9346
+ filterUsableVersionedAttrs (ClangDecl,
9347
+ CurrentImporterVersion.asClangVersionTuple (),
9348
+ discardVersionedAttrSet);
9349
+
9350
+ // When importing from a module built with version-independent APINotes payload,
9351
+ // the decl will carry all possible versioned notes, without directly applying any
9352
+ // of them. For "type" and "nullability" notes, we must apply them first, here,
9353
+ // since they change the actual type of the decl as seen downstream.
9354
+ //
9355
+ // Other kinds of notes will be handled in `importAttributes`.
9356
+ for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin (),
9357
+ AE = ClangDecl->attr_end (); AI != AE; ++AI) {
9358
+ if (auto versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(*AI)) {
9359
+ if (!isa<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ()) &&
9360
+ !isa<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
9361
+ continue ;
9362
+ }
9363
+
9364
+ if (discardVersionedAttrSet.count (versionedAttr))
9365
+ continue ;
9366
+
9367
+ // Apply Type APINotes
9368
+ if (auto typeRenameAttr = dyn_cast<clang::SwiftTypeAttr>(versionedAttr->getAttrToAdd ())) {
9369
+ Sema.ApplyAPINotesType (const_cast <clang::NamedDecl*>(ClangDecl),
9370
+ typeRenameAttr->getTypeString ());
9371
+ }
9372
+
9373
+ // Apply Nullability APINotes
9374
+ if (auto nullabilityAttr = dyn_cast<clang::SwiftNullabilityAttr>(versionedAttr->getAttrToAdd ())) {
9375
+ clang::NullabilityKind nullability;
9376
+ switch (nullabilityAttr->getKind ()) {
9377
+ case clang::SwiftNullabilityAttr::Kind::NonNull:
9378
+ nullability = clang::NullabilityKind::NonNull;
9379
+ break ;
9380
+ case clang::SwiftNullabilityAttr::Kind::Nullable:
9381
+ nullability = clang::NullabilityKind::Nullable;
9382
+ break ;
9383
+ case clang::SwiftNullabilityAttr::Kind::Unspecified:
9384
+ nullability = clang::NullabilityKind::Unspecified;
9385
+ break ;
9386
+ case clang::SwiftNullabilityAttr::Kind::NullableResult:
9387
+ nullability = clang::NullabilityKind::NullableResult;
9388
+ break ;
9389
+ }
9390
+
9391
+ Sema.ApplyNullability (const_cast <clang::NamedDecl*>(ClangDecl), nullability);
9392
+ }
9393
+ }
9394
+ }
9395
+ }
9396
+
9254
9397
Decl *
9255
9398
ClangImporter::Implementation::importDeclImpl (const clang::NamedDecl *ClangDecl,
9256
9399
ImportNameVersion version,
@@ -9273,14 +9416,20 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
9273
9416
!isa<clang::FieldDecl>(ClangDecl))
9274
9417
return nullptr ;
9275
9418
9419
+ // If '-version-independent-apinotes' is used, then "type" and "nullability"
9420
+ // notes are applied by the client (Importer) instead of the producer of the
9421
+ // Clang module we are consuming. Do so now, early, since these notes
9422
+ // affect the decl's type.
9423
+ if (SwiftContext.ClangImporterOpts .LoadVersionIndependentAPINotes )
9424
+ applyTypeAndNullabilityAPINotes (ClangDecl, getClangSema (), CurrentVersion);
9425
+
9276
9426
bool SkippedOverTypedef = false ;
9277
9427
Decl *Result = nullptr ;
9278
9428
if (auto *UnderlyingDecl = canSkipOverTypedef (*this , ClangDecl,
9279
9429
TypedefIsSuperfluous)) {
9280
9430
Result = importDecl (UnderlyingDecl, version);
9281
9431
SkippedOverTypedef = true ;
9282
9432
}
9283
-
9284
9433
if (!Result) {
9285
9434
SwiftDeclConverter converter (*this , version);
9286
9435
Result = converter.Visit (ClangDecl);
0 commit comments