diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index dcafc838548..63368868326 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -1746,7 +1746,8 @@ def SwiftVersioned : Attr {
// This attribute has no spellings as it is only ever created implicitly
// from API notes.
let Spellings = [];
- let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">];
+ let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
+ BoolArgument<"IsReplacedByActive">];
let SemaHandler = 0;
let Documentation = [Undocumented];
}
@@ -1755,7 +1756,8 @@ def SwiftVersionedRemoval : Attr {
// This attribute has no spellings as it is only ever created implicitly
// from API notes.
let Spellings = [];
- let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">];
+ let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
+ BoolArgument<"IsReplacedByActive">];
let SemaHandler = 0;
let Documentation = [Undocumented];
let AdditionalMembers = [{
diff --git a/lib/Sema/SemaAPINotes.cpp b/lib/Sema/SemaAPINotes.cpp
index 6145fef3de2..0b3cdbb9603 100644
--- a/lib/Sema/SemaAPINotes.cpp
+++ b/lib/Sema/SemaAPINotes.cpp
@@ -21,14 +21,21 @@ namespace {
IsNotActive,
IsActive
};
+ enum IsReplacement_t : bool {
+ IsNotReplacement,
+ IsReplacement
+ };
struct VersionedInfoMetadata {
/// An empty version refers to unversioned metadata.
VersionTuple Version;
- bool IsActive;
+ unsigned IsActive: 1;
+ unsigned IsReplacement: 1;
- VersionedInfoMetadata(VersionTuple version, IsActive_t active)
- : Version(version), IsActive(active == IsActive_t::IsActive) {}
+ VersionedInfoMetadata(VersionTuple version, IsActive_t active,
+ IsReplacement_t replacement)
+ : Version(version), IsActive(active == IsActive_t::IsActive),
+ IsReplacement(replacement == IsReplacement_t::IsReplacement) {}
};
} // end anonymous namespace
@@ -148,9 +155,8 @@ namespace {
if (existing != end) {
// Remove the existing attribute, and treat it as a superseded
// non-versioned attribute.
- auto *versioned =
- SwiftVersionedAttr::CreateImplicit(S.Context, clang::VersionTuple(),
- *existing);
+ auto *versioned = SwiftVersionedAttr::CreateImplicit(
+ S.Context, metadata.Version, *existing, /*IsReplacedByActive*/true);
D->getAttrs().erase(existing.getCurrent());
D->addAttr(versioned);
@@ -166,19 +172,18 @@ namespace {
} else {
if (shouldAddAttribute) {
if (auto attr = createAttr()) {
- auto *versioned =
- SwiftVersionedAttr::CreateImplicit(S.Context, metadata.Version,
- attr);
+ auto *versioned = SwiftVersionedAttr::CreateImplicit(
+ S.Context, metadata.Version, attr,
+ /*IsReplacedByActive*/metadata.IsReplacement);
D->addAttr(versioned);
}
} else {
// FIXME: This isn't preserving enough information for things like
// availability, where we're trying to remove a /specific/ kind of
// attribute.
- auto *versioned =
- SwiftVersionedRemovalAttr::CreateImplicit(S.Context,
- metadata.Version,
- AttrKindFor::value);
+ auto *versioned = SwiftVersionedRemovalAttr::CreateImplicit(
+ S.Context, metadata.Version, AttrKindFor::value,
+ /*IsReplacedByActive*/metadata.IsReplacement);
D->addAttr(versioned);
}
}
@@ -684,7 +689,8 @@ static void maybeAttachUnversionedSwiftName(
}
// Then explicitly call that out with a removal attribute.
- VersionedInfoMetadata DummyFutureMetadata(VersionTuple(), IsNotActive);
+ VersionedInfoMetadata DummyFutureMetadata(SelectedVersion, IsNotActive,
+ IsReplacement);
handleAPINotedAttribute(S, D, /*add*/false,
DummyFutureMetadata,
[]() -> SwiftNameAttr * {
@@ -709,7 +715,13 @@ static void ProcessVersionedAPINotes(
for (unsigned i = 0, e = Info.size(); i != e; ++i) {
std::tie(Version, InfoSlice) = Info[i];
auto Active = (i == Selected) ? IsActive : IsNotActive;
- ProcessAPINotes(S, D, InfoSlice, VersionedInfoMetadata(Version, Active));
+ auto Replacement = IsNotReplacement;
+ if (Active == IsNotActive && Version.empty()) {
+ Replacement = IsReplacement;
+ Version = Info[Selected].first;
+ }
+ ProcessAPINotes(S, D, InfoSlice, VersionedInfoMetadata(Version, Active,
+ Replacement));
}
}
diff --git a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes
index 9099615a142..572c714b3d6 100644
--- a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes
+++ b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes
@@ -15,6 +15,9 @@ Classes:
- Name: accessorsOnlyForClassExceptInVersion3
PropertyKind: Class
SwiftImportAsAccessors: true
+Functions:
+ - Name: unversionedRenameDUMP
+ SwiftName: 'unversionedRename_NOTES()'
Tags:
- Name: APINotedFlagEnum
FlagEnum: true
@@ -123,6 +126,9 @@ SwiftVersions:
- Name: MultiVersionedTypedef45Notes
SwiftName: MultiVersionedTypedef45Notes_5
- Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs.
+ Classes:
+ - Name: Swift4RenamedDUMP
+ SwiftName: SpecialSwift4Name
Typedefs:
- Name: MultiVersionedTypedef34
SwiftName: MultiVersionedTypedef34_4
diff --git a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h
index b060c9423cd..9ce95633c52 100644
--- a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h
+++ b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h
@@ -1,5 +1,7 @@
void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)")));
+void unversionedRenameDUMP(void) __attribute__((swift_name("unversionedRename_HEADER()")));
+
void acceptClosure(void (^ __attribute__((noescape)) block)(void));
void privateFunc(void) __attribute__((swift_private));
@@ -43,6 +45,10 @@ __attribute__((swift_bridge("MyValueType")))
__attribute__((swift_name("Swift4Name")))
@interface Swift3RenamedAlsoDUMP
@end
+
+@interface Swift4RenamedDUMP
+@end
+
#endif
diff --git a/test/APINotes/properties.m b/test/APINotes/properties.m
index fe3c7384044..0b3d24482c0 100644
--- a/test/APINotes/properties.m
+++ b/test/APINotes/properties.m
@@ -18,25 +18,25 @@
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyInVersion3 'id'
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
-// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0
+// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0{{$}}
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
// CHECK-NOT: Attr
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassInVersion3 'id'
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
-// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0
+// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0{{$}}
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
// CHECK-NOT: Attr
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyExceptInVersion3 'id'
-// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} 0{{$}}
+// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}}
// CHECK-NOT: Attr
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassExceptInVersion3 'id'
-// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} 0{{$}}
+// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}}
diff --git a/test/APINotes/versioned.m b/test/APINotes/versioned.m
index 905a9c7eb8a..e7ec2eb4337 100644
--- a/test/APINotes/versioned.m
+++ b/test/APINotes/versioned.m
@@ -16,38 +16,53 @@
// CHECK-VERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(a:b:)")));
// CHECK-DUMP-LABEL: Dumping moveToPointDUMP
-// CHECK-VERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 0
+// CHECK-VERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "moveTo(x:y:)"
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "moveTo(a:b:)"
// CHECK-UNVERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "moveTo(a:b:)"
// CHECK-DUMP-NOT: Attr
+// CHECK-DUMP-LABEL: Dumping unversionedRenameDUMP
+// CHECK-DUMP: in VersionedKit unversionedRenameDUMP
+// CHECK-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 0 IsReplacedByActive{{$}}
+// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_HEADER()"
+// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_NOTES()"
+// CHECK-DUMP-NOT: Attr
+
// CHECK-DUMP-LABEL: Dumping TestGenericDUMP
// CHECK-VERSIONED-DUMP: SwiftImportAsNonGenericAttr {{.+}} Implicit
-// CHECK-UNVERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 3.0
+// CHECK-UNVERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} Implicit
// CHECK-DUMP-NOT: Attr
// CHECK-DUMP-LABEL: Dumping Swift3RenamedOnlyDUMP
// CHECK-DUMP: in VersionedKit Swift3RenamedOnlyDUMP
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 0 {{[0-9]+}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} IsReplacedByActive{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "SpecialSwift3Name"
// CHECK-DUMP-NOT: Attr
// CHECK-DUMP-LABEL: Dumping Swift3RenamedAlsoDUMP
// CHECK-DUMP: in VersionedKit Swift3RenamedAlsoDUMP
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 0
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "Swift4Name"
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also"
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "Swift4Name"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "SpecialSwift3Also"
// CHECK-DUMP-NOT: Attr
+// CHECK-DUMP-LABEL: Dumping Swift4RenamedDUMP
+// CHECK-DUMP: in VersionedKit Swift4RenamedDUMP
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 4 {{[0-9]+}} IsReplacedByActive{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name"
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 4{{$}}
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "SpecialSwift4Name"
+// CHECK-DUMP-NOT: Attr
+
// CHECK-DUMP-NOT: Dumping
// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape)));