Skip to content

Commit 8c32baa

Browse files
committed
[APINotes] Record what version caused an annotation to get replaced. (apple#123)
Now that -fapinotes-swift-version=3 can pick up API notes for "Version: 4", the information for /inactive/ API notes isn't sufficient to tell what would have happened under a different version. That is, I can't ask "what would happen under version 4", because I can't tell if the active annotations are active because they were specified for version 3 or version 4. The inactive, unversioned attributes were no help, either: they just said "version 0". Fix this by adding a new flag 'IsReplacedByActive' to SwiftVersionedAttr and SwiftVersionedRemovalAttr. When set, the 'Version' field refers to the API note that caused this annotation to become inactive. Note that "version 0" can still exist: when an attribute written in source is replaced by an unversioned attribute in the API notes. (cherry picked from commit b9c7251)
1 parent f499ad9 commit 8c32baa

File tree

6 files changed

+69
-28
lines changed

6 files changed

+69
-28
lines changed

include/clang/Basic/Attr.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,8 @@ def SwiftVersioned : Attr {
17331733
// This attribute has no spellings as it is only ever created implicitly
17341734
// from API notes.
17351735
let Spellings = [];
1736-
let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">];
1736+
let Args = [VersionArgument<"Version">, AttrArgument<"AttrToAdd">,
1737+
BoolArgument<"IsReplacedByActive">];
17371738
let SemaHandler = 0;
17381739
let Documentation = [Undocumented];
17391740
}
@@ -1742,7 +1743,8 @@ def SwiftVersionedRemoval : Attr {
17421743
// This attribute has no spellings as it is only ever created implicitly
17431744
// from API notes.
17441745
let Spellings = [];
1745-
let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">];
1746+
let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
1747+
BoolArgument<"IsReplacedByActive">];
17461748
let SemaHandler = 0;
17471749
let Documentation = [Undocumented];
17481750
let AdditionalMembers = [{

lib/Sema/SemaAPINotes.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,21 @@ namespace {
2121
IsNotActive,
2222
IsActive
2323
};
24+
enum IsReplacement_t : bool {
25+
IsNotReplacement,
26+
IsReplacement
27+
};
2428

2529
struct VersionedInfoMetadata {
2630
/// An empty version refers to unversioned metadata.
2731
VersionTuple Version;
28-
bool IsActive;
32+
unsigned IsActive: 1;
33+
unsigned IsReplacement: 1;
2934

30-
VersionedInfoMetadata(VersionTuple version, IsActive_t active)
31-
: Version(version), IsActive(active == IsActive_t::IsActive) {}
35+
VersionedInfoMetadata(VersionTuple version, IsActive_t active,
36+
IsReplacement_t replacement)
37+
: Version(version), IsActive(active == IsActive_t::IsActive),
38+
IsReplacement(replacement == IsReplacement_t::IsReplacement) {}
3239
};
3340
} // end anonymous namespace
3441

@@ -148,9 +155,8 @@ namespace {
148155
if (existing != end) {
149156
// Remove the existing attribute, and treat it as a superseded
150157
// non-versioned attribute.
151-
auto *versioned =
152-
SwiftVersionedAttr::CreateImplicit(S.Context, clang::VersionTuple(),
153-
*existing);
158+
auto *versioned = SwiftVersionedAttr::CreateImplicit(
159+
S.Context, metadata.Version, *existing, /*IsReplacedByActive*/true);
154160

155161
D->getAttrs().erase(existing.getCurrent());
156162
D->addAttr(versioned);
@@ -166,19 +172,18 @@ namespace {
166172
} else {
167173
if (shouldAddAttribute) {
168174
if (auto attr = createAttr()) {
169-
auto *versioned =
170-
SwiftVersionedAttr::CreateImplicit(S.Context, metadata.Version,
171-
attr);
175+
auto *versioned = SwiftVersionedAttr::CreateImplicit(
176+
S.Context, metadata.Version, attr,
177+
/*IsReplacedByActive*/metadata.IsReplacement);
172178
D->addAttr(versioned);
173179
}
174180
} else {
175181
// FIXME: This isn't preserving enough information for things like
176182
// availability, where we're trying to remove a /specific/ kind of
177183
// attribute.
178-
auto *versioned =
179-
SwiftVersionedRemovalAttr::CreateImplicit(S.Context,
180-
metadata.Version,
181-
AttrKindFor<A>::value);
184+
auto *versioned = SwiftVersionedRemovalAttr::CreateImplicit(
185+
S.Context, metadata.Version, AttrKindFor<A>::value,
186+
/*IsReplacedByActive*/metadata.IsReplacement);
182187
D->addAttr(versioned);
183188
}
184189
}
@@ -684,7 +689,8 @@ static void maybeAttachUnversionedSwiftName(
684689
}
685690

686691
// Then explicitly call that out with a removal attribute.
687-
VersionedInfoMetadata DummyFutureMetadata(VersionTuple(), IsNotActive);
692+
VersionedInfoMetadata DummyFutureMetadata(SelectedVersion, IsNotActive,
693+
IsReplacement);
688694
handleAPINotedAttribute<SwiftNameAttr>(S, D, /*add*/false,
689695
DummyFutureMetadata,
690696
[]() -> SwiftNameAttr * {
@@ -709,7 +715,13 @@ static void ProcessVersionedAPINotes(
709715
for (unsigned i = 0, e = Info.size(); i != e; ++i) {
710716
std::tie(Version, InfoSlice) = Info[i];
711717
auto Active = (i == Selected) ? IsActive : IsNotActive;
712-
ProcessAPINotes(S, D, InfoSlice, VersionedInfoMetadata(Version, Active));
718+
auto Replacement = IsNotReplacement;
719+
if (Active == IsNotActive && Version.empty()) {
720+
Replacement = IsReplacement;
721+
Version = Info[Selected].first;
722+
}
723+
ProcessAPINotes(S, D, InfoSlice, VersionedInfoMetadata(Version, Active,
724+
Replacement));
713725
}
714726
}
715727

test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Classes:
1515
- Name: accessorsOnlyForClassExceptInVersion3
1616
PropertyKind: Class
1717
SwiftImportAsAccessors: true
18+
Functions:
19+
- Name: unversionedRenameDUMP
20+
SwiftName: 'unversionedRename_NOTES()'
1821
Tags:
1922
- Name: APINotedFlagEnum
2023
FlagEnum: true
@@ -123,6 +126,9 @@ SwiftVersions:
123126
- Name: MultiVersionedTypedef45Notes
124127
SwiftName: MultiVersionedTypedef45Notes_5
125128
- Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs.
129+
Classes:
130+
- Name: Swift4RenamedDUMP
131+
SwiftName: SpecialSwift4Name
126132
Typedefs:
127133
- Name: MultiVersionedTypedef34
128134
SwiftName: MultiVersionedTypedef34_4

test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)")));
22

3+
void unversionedRenameDUMP(void) __attribute__((swift_name("unversionedRename_HEADER()")));
4+
35
void acceptClosure(void (^ __attribute__((noescape)) block)(void));
46

57
void privateFunc(void) __attribute__((swift_private));
@@ -43,6 +45,10 @@ __attribute__((swift_bridge("MyValueType")))
4345
__attribute__((swift_name("Swift4Name")))
4446
@interface Swift3RenamedAlsoDUMP
4547
@end
48+
49+
@interface Swift4RenamedDUMP
50+
@end
51+
4652
#endif
4753

4854

test/APINotes/properties.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@
1818

1919
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyInVersion3 'id'
2020
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
21-
// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0
21+
// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0{{$}}
2222
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
2323
// CHECK-NOT: Attr
2424

2525
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassInVersion3 'id'
2626
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
27-
// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0
27+
// CHECK-4-NEXT: SwiftVersionedAttr {{.+}} 3.0{{$}}
2828
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
2929
// CHECK-NOT: Attr
3030

3131
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyExceptInVersion3 'id'
32-
// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} 0{{$}}
32+
// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
3333
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
3434
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
3535
// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}}
3636
// CHECK-NOT: Attr
3737

3838
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassExceptInVersion3 'id'
39-
// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} 0{{$}}
39+
// CHECK-3-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
4040
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
4141
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} Implicit
4242
// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}}

test/APINotes/versioned.m

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,53 @@
1616
// CHECK-VERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(a:b:)")));
1717

1818
// CHECK-DUMP-LABEL: Dumping moveToPointDUMP
19-
// CHECK-VERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 0
19+
// CHECK-VERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
2020
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "moveTo(x:y:)"
2121
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "moveTo(a:b:)"
2222
// CHECK-UNVERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)"
23-
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0
23+
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
2424
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "moveTo(a:b:)"
2525
// CHECK-DUMP-NOT: Attr
2626

27+
// CHECK-DUMP-LABEL: Dumping unversionedRenameDUMP
28+
// CHECK-DUMP: in VersionedKit unversionedRenameDUMP
29+
// CHECK-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 0 IsReplacedByActive{{$}}
30+
// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_HEADER()"
31+
// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_NOTES()"
32+
// CHECK-DUMP-NOT: Attr
33+
2734
// CHECK-DUMP-LABEL: Dumping TestGenericDUMP
2835
// CHECK-VERSIONED-DUMP: SwiftImportAsNonGenericAttr {{.+}} Implicit
29-
// CHECK-UNVERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 3.0
36+
// CHECK-UNVERSIONED-DUMP: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
3037
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} Implicit
3138
// CHECK-DUMP-NOT: Attr
3239

3340
// CHECK-DUMP-LABEL: Dumping Swift3RenamedOnlyDUMP
3441
// CHECK-DUMP: in VersionedKit Swift3RenamedOnlyDUMP
35-
// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 0 {{[0-9]+}}
42+
// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} IsReplacedByActive{{$}}
3643
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name"
37-
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0
44+
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
3845
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "SpecialSwift3Name"
3946
// CHECK-DUMP-NOT: Attr
4047

4148
// CHECK-DUMP-LABEL: Dumping Swift3RenamedAlsoDUMP
4249
// CHECK-DUMP: in VersionedKit Swift3RenamedAlsoDUMP
43-
// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 0
50+
// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}}
4451
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <line:{{.+}}, col:{{.+}}> "Swift4Name"
4552
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also"
4653
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <line:{{.+}}, col:{{.+}}> "Swift4Name"
47-
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0
54+
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 3.0{{$}}
4855
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "SpecialSwift3Also"
4956
// CHECK-DUMP-NOT: Attr
5057

58+
// CHECK-DUMP-LABEL: Dumping Swift4RenamedDUMP
59+
// CHECK-DUMP: in VersionedKit Swift4RenamedDUMP
60+
// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 4 {{[0-9]+}} IsReplacedByActive{{$}}
61+
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name"
62+
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAttr {{.+}} Implicit 4{{$}}
63+
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} Implicit "SpecialSwift4Name"
64+
// CHECK-DUMP-NOT: Attr
65+
5166
// CHECK-DUMP-NOT: Dumping
5267

5368
// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape)));

0 commit comments

Comments
 (0)