https://github.com/artemcm created
https://github.com/llvm/llvm-project/pull/224860
In addition to aggregating attributes with `SwiftVersionedAdditionAttr` and
`SwiftVersionedDeletionAttr`, we may need to also capture that an APINotes file
contained a versioned slice which may not have captured any keyed attributes.
For example:
```
Name: Bar
Functions:
- Name: foo
SwiftName: 'fooBase()' # unversioned
SwiftVersions:
- Version: 4
Functions:
- Name: foo
SwiftName: 'fooFour()' # the 4.0 slice
- Version: 5
Functions:
- Name: foo
SwiftPrivate: true # the 5.0 slice
```
When picking which attributes/notes to apply, the algorithm is to select from
the lowest version slice at or above the client requested one, or the
unversioned slice otherwise. Suppose we have a client at version 3.
In this case, the client will have reconstructed the attributes as 3 options:
- Unversioned: SwiftNameAttr "fooBase()"
- 4.0: SwiftNameAttr "fooFour()"
- 5.0: SwiftPrivateAttr According to the algorithm, slice 4 would win, so `foo`
would get a name `fooFour()` and **not** be private.
Now suppose there is instead a versioned slice which carries no keyed
attributes:
```
SwiftVersions:
- Version: 4
Functions:
- Name: foo # declared, no keys
```
With this slice, the client would have reconstructed just two
versioned-attribute options:
- Unversioned: SwiftNameAttr "fooBase()"
- 5.0: SwiftPrivateAttr And according to the algorithm selected 5 and marked
`foo` as private. This is incorrect because the presence of the 4.0 slice still
means that it is the one that must be selected for this declaration.
This change adds a new (no spelling) attribute called `SwiftVersionedSliceAttr`
to capture existence of all versioned slices, which the clients will then use
to know which slice version to select for a given declaration.
>From ae8e26b2d14a35ad64ff5f04ec831a55017b5ab8 Mon Sep 17 00:00:00 2001
From: Artem Chikin <[email protected]>
Date: Sat, 19 Sep 2026 20:36:35 +0100
Subject: [PATCH] [APINotes][Unversioned] Capture presence of versioned slices
separately, and track different readers
In addition to aggregating attributes with `SwiftVersionedAdditionAttr` and
`SwiftVersionedDeletionAttr`, we may need to also capture that an APINotes file
contained a versioned slice which may not have captured any keyed attributes.
For example:
```
Name: Bar
Functions:
- Name: foo
SwiftName: 'fooBase()' # unversioned
SwiftVersions:
- Version: 4
Functions:
- Name: foo
SwiftName: 'fooFour()' # the 4.0 slice
- Version: 5
Functions:
- Name: foo
SwiftPrivate: true # the 5.0 slice
```
When picking which attributes/notes to apply, the algorithm is to select from
the lowest version slice at or above the client requested one, or the
unversioned slice otherwise. Suppose we have a client at version 3.
In this case, the client will have reconstructed the attributes as 3 options:
- Unversioned: SwiftNameAttr "fooBase()"
- 4.0: SwiftNameAttr "fooFour()"
- 5.0: SwiftPrivateAttr
According to the algorithm, slice 4 would win, so `foo` would get a name
`fooFour()` and **not** be private.
Now suppose there is instead a versioned slice which carries no keyed
attributes:
```
SwiftVersions:
- Version: 4
Functions:
- Name: foo # declared, no keys
```
With this slice, the client would have reconstructed just two
versioned-attribute options:
- Unversioned: SwiftNameAttr "fooBase()"
- 5.0: SwiftPrivateAttr
And according to the algorithm selected 5 and marked `foo` as private. This is
incorrect because the presence of the 4.0 slice still means that it is the one
that must be selected for this declaration.
This change adds a new (no spelling) attribute called `SwiftVersionedSliceAttr`
to capture existence of all versioned slices, which the clients will then use
to know which slice version to select for a given declaration.
---
.../include/clang/APINotes/APINotesManager.h | 8 ++
clang/include/clang/Basic/Attr.td | 22 +++-
clang/lib/APINotes/APINotesManager.cpp | 8 ++
clang/lib/Sema/SemaAPINotes.cpp | 112 ++++++++++++------
clang/test/APINotes/properties.m | 8 +-
.../APINotes/versioned-version-independent.m | 23 +++-
clang/test/APINotes/versioned.m | 20 ++--
7 files changed, 145 insertions(+), 56 deletions(-)
diff --git a/clang/include/clang/APINotes/APINotesManager.h
b/clang/include/clang/APINotes/APINotesManager.h
index aaf48706fb26b2..7aa1711efb0090 100644
--- a/clang/include/clang/APINotes/APINotesManager.h
+++ b/clang/include/clang/APINotes/APINotesManager.h
@@ -182,6 +182,14 @@ class APINotesManager {
/// Find the API notes readers that correspond to the given source location.
llvm::SmallVector<APINotesReader *, 2> findAPINotes(SourceLocation Loc);
+ /// The position of \p Reader among the readers for the current module.
+ ///
+ /// Version selection runs independently per reader, so anything recording a
+ /// slice for a later consumer to re-select has to say which reader it came
+ /// from. Readers found by walking header directories are consulted one at a
+ /// time and all report 0.
+ unsigned getReaderIndex(const APINotesReader *Reader) const;
+
bool captureVersionIndependentSwift() { return VersionIndependentSwift; }
};
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index 61ef3fb6124405..6a54f20bc121ce 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3306,7 +3306,8 @@ def SwiftVersionedAddition : Attr {
// from API notes.
let Spellings = [];
let Args = [VersionArgument<"Version">, WrappedAttr<"AdditionalAttr">,
- BoolArgument<"IsReplacedByActive">];
+ BoolArgument<"IsReplacedByActive">,
+ UnsignedArgument<"ReaderIndex">];
let SemaHandler = 0;
let Documentation = [InternalOnly];
}
@@ -3316,7 +3317,8 @@ def SwiftVersionedRemoval : Attr {
// from API notes.
let Spellings = [];
let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
- BoolArgument<"IsReplacedByActive">];
+ BoolArgument<"IsReplacedByActive">,
+ UnsignedArgument<"ReaderIndex">];
let SemaHandler = 0;
let Documentation = [InternalOnly];
let AdditionalMembers = [{
@@ -3326,6 +3328,22 @@ def SwiftVersionedRemoval : Attr {
}];
}
+def SwiftVersionedSlice : Attr {
+ // This attribute has no spellings as it is only ever created implicitly
+ // from API notes, and only under -fswift-version-independent-apinotes.
+ //
+ // One of these records each Swift version slice an API notes reader supplied
+ // for the declaration, whether or not that slice set any key. A slice that
+ // sets no key still participates in version selection -- selecting it
+ // suppresses the annotations of every other slice -- so a consumer that
+ // recomputes the selection needs to know the slice exists. Addition and
+ // removal wrappers alone do not record that.
+ let Spellings = [];
+ let Args = [VersionArgument<"Version">, UnsignedArgument<"ReaderIndex">];
+ let SemaHandler = 0;
+ let Documentation = [InternalOnly];
+}
+
def NoDeref : TypeAttr {
let Spellings = [Clang<"noderef">];
let Documentation = [NoDerefDocs];
diff --git a/clang/lib/APINotes/APINotesManager.cpp
b/clang/lib/APINotes/APINotesManager.cpp
index 2cc801d5415b84..65da1c50177f1f 100644
--- a/clang/lib/APINotes/APINotesManager.cpp
+++ b/clang/lib/APINotes/APINotesManager.cpp
@@ -473,3 +473,11 @@ APINotesManager::findAPINotes(SourceLocation Loc) {
return Results;
}
+
+unsigned APINotesManager::getReaderIndex(const APINotesReader *Reader) const {
+ ArrayRef<APINotesReader *> Readers = getCurrentModuleReaders();
+ for (unsigned I = 0, N = Readers.size(); I != N; ++I)
+ if (Readers[I] == Reader)
+ return I;
+ return 0;
+}
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 4c7e5ea16cfd7d..695339fe174511 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -34,12 +34,17 @@ enum class IsSubstitution_t : bool { Original, Replacement
};
struct VersionedInfoMetadata {
/// An empty version refers to unversioned metadata.
VersionTuple Version;
+ /// Which API notes reader supplied this slice. Version selection runs
+ /// independently per reader, so a consumer that recomputes the selection has
+ /// to group slices by this index rather than pooling them.
+ unsigned ReaderIndex;
unsigned IsActive : 1;
unsigned IsReplacement : 1;
- VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
- IsSubstitution_t Replacement)
- : Version(Version), IsActive(Active == IsActive_t::Active),
+ VersionedInfoMetadata(VersionTuple Version, unsigned ReaderIndex,
+ IsActive_t Active, IsSubstitution_t Replacement)
+ : Version(Version), ReaderIndex(ReaderIndex),
+ IsActive(Active == IsActive_t::Active),
IsReplacement(Replacement == IsSubstitution_t::Replacement) {}
};
} // end anonymous namespace
@@ -65,7 +70,8 @@ static void applyAPINotesType(Sema &S, Decl *decl, StringRef
typeString,
if (S.captureSwiftVersionIndependentAPINotes()) {
auto *typeAttr = SwiftTypeAttr::CreateImplicit(S.Context, typeString);
auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
- S.Context, metadata.Version, typeAttr, metadata.IsReplacement);
+ S.Context, metadata.Version, typeAttr, metadata.IsReplacement,
+ metadata.ReaderIndex);
decl->addAttr(versioned);
} else {
if (!metadata.IsActive)
@@ -98,7 +104,8 @@ static void applyNullability(Sema &S, Decl *decl,
NullabilityKind nullability,
auto *nullabilityAttr =
SwiftNullabilityAttr::CreateImplicit(S.Context, attrNullabilityKind);
auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
- S.Context, metadata.Version, nullabilityAttr, metadata.IsReplacement);
+ S.Context, metadata.Version, nullabilityAttr, metadata.IsReplacement,
+ metadata.ReaderIndex);
decl->addAttr(versioned);
return;
} else {
@@ -149,7 +156,8 @@ void handleAPINotedAttribute(
// Remove the existing attribute, and treat it as a superseded
// non-versioned attribute.
auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
- S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true);
+ S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true,
+ Metadata.ReaderIndex);
D->getAttrs().erase(Existing);
D->addAttr(Versioned);
@@ -167,16 +175,18 @@ void handleAPINotedAttribute(
if (auto Attr = CreateAttr()) {
auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
S.Context, Metadata.Version, Attr,
- /*IsReplacedByActive*/ Metadata.IsReplacement);
+ /*IsReplacedByActive*/ Metadata.IsReplacement, Metadata.ReaderIndex);
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.
+ // The removal records only the attribute /kind/ to suppress, not which
+ // attribute. That is lossy for the retain-count family, whose members are
+ // interchangeable here: GetExistingAttr below matches any of them, so a
+ // consumer honoring this removal has to suppress the whole family rather
+ // than the recorded kind alone.
auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(
S.Context, Metadata.Version, AttrKindFor<A>::value,
- /*IsReplacedByActive*/ Metadata.IsReplacement);
+ /*IsReplacedByActive*/ Metadata.IsReplacement, Metadata.ReaderIndex);
D->addAttr(Versioned);
}
}
@@ -872,7 +882,8 @@ static void ProcessAPINotes(Sema &S, ObjCInterfaceDecl *D,
template <typename SpecificInfo>
static void maybeAttachUnversionedSwiftName(
Sema &S, Decl *D,
- const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
+ const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info,
+ unsigned ReaderIndex) {
if (D->hasAttr<SwiftNameAttr>())
return;
if (!Info.getSelected())
@@ -896,8 +907,9 @@ static void maybeAttachUnversionedSwiftName(
}
// Then explicitly call that out with a removal attribute.
- VersionedInfoMetadata DummyFutureMetadata(
- SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
+ VersionedInfoMetadata DummyFutureMetadata(SelectedVersion, ReaderIndex,
+ IsActive_t::Inactive,
+ IsSubstitution_t::Replacement);
handleAPINotedAttribute<SwiftNameAttr>(
S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
llvm_unreachable("should not try to add an attribute here");
@@ -907,13 +919,17 @@ static void maybeAttachUnversionedSwiftName(
/// Processes all versions of versioned API notes.
///
/// Just dispatches to the various ProcessAPINotes functions in this file.
+///
+/// \param ReaderIndex Which API notes reader supplied \p Info. Selection runs
+/// independently per reader, so this has to travel with every slice.
template <typename SpecificDecl, typename SpecificInfo>
static void ProcessVersionedAPINotes(
Sema &S, SpecificDecl *D,
- const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
+ const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info,
+ unsigned ReaderIndex) {
if (!S.captureSwiftVersionIndependentAPINotes())
- maybeAttachUnversionedSwiftName(S, D, Info);
+ maybeAttachUnversionedSwiftName(S, D, Info, ReaderIndex);
unsigned Selected = Info.getSelected().value_or(Info.size());
@@ -930,13 +946,22 @@ static void ProcessVersionedAPINotes(
if (S.captureSwiftVersionIndependentAPINotes()) {
Active = IsActive_t::Inactive;
Replacement = IsSubstitution_t::Original;
+
+ // Record that this slice exists, independently of whether it goes on to
+ // set any key. A slice that sets nothing still wins selection for the
+ // versions it covers, and winning suppresses every other slice, so a
+ // client recomputing the selection cannot infer the slice set from the
+ // addition and removal wrappers alone.
+ D->addAttr(SwiftVersionedSliceAttr::CreateImplicit(S.Context, Version,
+ ReaderIndex));
} else if (Active == IsActive_t::Inactive && Version.empty()) {
Replacement = IsSubstitution_t::Replacement;
Version = Info[Selected].first;
}
- ProcessAPINotes(S, D, InfoSlice,
- VersionedInfoMetadata(Version, Active, Replacement));
+ ProcessAPINotes(
+ S, D, InfoSlice,
+ VersionedInfoMetadata(Version, ReaderIndex, Active, Replacement));
}
}
@@ -1112,19 +1137,24 @@ void
APINotesSelectorDiagnosticReaderState::markCandidatesUsed(
// Apply the first exact selector entry found. This preserves source-spelling
// precedence over the desugared fallback and avoids applying multiple exact
// entries for the same declaration.
+//
+// \param ReaderIndex Which API notes reader \p LookupExact reads from. An
exact
+// selector entry competes only against the other slices from its own reader,
so
+// it has to carry the same index as the broad entry beside it.
template <typename SpecificInfo, typename SpecificDecl>
static void processExactAPINotes(
Sema &S, SpecificDecl *D,
const APINotesParameterSelectorCandidates &ParameterSelectorCandidates,
llvm::function_ref<api_notes::APINotesReader::VersionedInfo<SpecificInfo>(
ArrayRef<std::string>)>
- LookupExact) {
+ LookupExact,
+ unsigned ReaderIndex) {
auto ProcessSelector = [&](const APINotesParameterSelector &Selector) {
auto Info = LookupExact(Selector.Parameters);
if (Info.size() == 0)
return false;
- ProcessVersionedAPINotes(S, D, Info);
+ ProcessVersionedAPINotes(S, D, Info, ReaderIndex);
return true;
};
@@ -1157,7 +1187,8 @@ void Sema::ProcessAPINotes(Decl *D) {
for (auto Reader : Readers) {
auto Info =
Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
- ProcessVersionedAPINotes(*this, VD, Info);
+ ProcessVersionedAPINotes(*this, VD, Info,
+ APINotes.getReaderIndex(Reader));
}
return;
@@ -1172,7 +1203,8 @@ void Sema::ProcessAPINotes(Decl *D) {
for (auto Reader : Readers) {
auto Info =
Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
- ProcessVersionedAPINotes(*this, FD, Info);
+ ProcessVersionedAPINotes(*this, FD, Info,
+ APINotes.getReaderIndex(Reader));
if (ParameterSelectorCandidates)
processExactAPINotes<api_notes::GlobalFunctionInfo>(
@@ -1180,7 +1212,8 @@ void Sema::ProcessAPINotes(Decl *D) {
[&](ArrayRef<std::string> Parameters) {
return Reader->lookupGlobalFunction(FD->getName(),
Parameters,
APINotesContext);
- });
+ },
+ APINotes.getReaderIndex(Reader));
if (ParameterSelectorCandidates) {
auto &DiagnosticState =
@@ -1206,7 +1239,8 @@ void Sema::ProcessAPINotes(Decl *D) {
if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
for (auto Reader : Readers) {
auto Info = Reader->lookupObjCClassInfo(Class->getName());
- ProcessVersionedAPINotes(*this, Class, Info);
+ ProcessVersionedAPINotes(*this, Class, Info,
+ APINotes.getReaderIndex(Reader));
}
return;
@@ -1216,7 +1250,8 @@ void Sema::ProcessAPINotes(Decl *D) {
if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
for (auto Reader : Readers) {
auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
- ProcessVersionedAPINotes(*this, Protocol, Info);
+ ProcessVersionedAPINotes(*this, Protocol, Info,
+ APINotes.getReaderIndex(Reader));
}
return;
@@ -1260,7 +1295,8 @@ void Sema::ProcessAPINotes(Decl *D) {
if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
APINotesContext = UnwindTagContext(ParentTag, APINotes);
auto Info = Reader->lookupTag(LookupName, APINotesContext);
- ProcessVersionedAPINotes(*this, Tag, Info);
+ ProcessVersionedAPINotes(*this, Tag, Info,
+ APINotes.getReaderIndex(Reader));
}
return;
@@ -1270,7 +1306,8 @@ void Sema::ProcessAPINotes(Decl *D) {
if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
for (auto Reader : Readers) {
auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
- ProcessVersionedAPINotes(*this, Typedef, Info);
+ ProcessVersionedAPINotes(*this, Typedef, Info,
+ APINotes.getReaderIndex(Reader));
}
return;
@@ -1283,7 +1320,8 @@ void Sema::ProcessAPINotes(Decl *D) {
if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
for (auto Reader : Readers) {
auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
- ProcessVersionedAPINotes(*this, EnumConstant, Info);
+ ProcessVersionedAPINotes(*this, EnumConstant, Info,
+ APINotes.getReaderIndex(Reader));
}
return;
@@ -1352,7 +1390,8 @@ void Sema::ProcessAPINotes(Decl *D) {
auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
Method->isInstanceMethod());
- ProcessVersionedAPINotes(*this, Method, Info);
+ ProcessVersionedAPINotes(*this, Method, Info,
+ APINotes.getReaderIndex(Reader));
}
}
}
@@ -1366,7 +1405,8 @@ void Sema::ProcessAPINotes(Decl *D) {
ObjCPropertyAttribute::kind_class) == 0;
auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
isInstanceProperty);
- ProcessVersionedAPINotes(*this, Property, Info);
+ ProcessVersionedAPINotes(*this, Property, Info,
+ APINotes.getReaderIndex(Reader));
}
}
@@ -1392,7 +1432,8 @@ void Sema::ProcessAPINotes(Decl *D) {
MethodName = CXXMethod->getName();
auto Info = Reader->lookupCXXMethod(Context->id, MethodName);
- ProcessVersionedAPINotes(*this, CXXMethod, Info);
+ ProcessVersionedAPINotes(*this, CXXMethod, Info,
+ APINotes.getReaderIndex(Reader));
if (ParameterSelectorCandidates)
processExactAPINotes<api_notes::CXXMethodInfo>(
@@ -1400,7 +1441,8 @@ void Sema::ProcessAPINotes(Decl *D) {
[&](ArrayRef<std::string> Parameters) {
return Reader->lookupCXXMethod(Context->id, MethodName,
Parameters);
- });
+ },
+ APINotes.getReaderIndex(Reader));
if (ParameterSelectorCandidates) {
auto &DiagnosticState =
@@ -1426,7 +1468,8 @@ void Sema::ProcessAPINotes(Decl *D) {
for (auto Reader : Readers) {
if (auto Context = UnwindTagContext(TagContext, APINotes)) {
auto Info = Reader->lookupField(Context->id, Field->getName());
- ProcessVersionedAPINotes(*this, Field, Info);
+ ProcessVersionedAPINotes(*this, Field, Info,
+ APINotes.getReaderIndex(Reader));
}
}
}
@@ -1436,7 +1479,8 @@ void Sema::ProcessAPINotes(Decl *D) {
for (auto Reader : Readers) {
if (auto Context = UnwindTagContext(TagContext, APINotes)) {
auto Info = Reader->lookupTag(Tag->getName(), Context);
- ProcessVersionedAPINotes(*this, Tag, Info);
+ ProcessVersionedAPINotes(*this, Tag, Info,
+ APINotes.getReaderIndex(Reader));
}
}
}
diff --git a/clang/test/APINotes/properties.m b/clang/test/APINotes/properties.m
index 79b5e2b10c47c1..cad7e399000f96 100644
--- a/clang/test/APINotes/properties.m
+++ b/clang/test/APINotes/properties.m
@@ -15,25 +15,25 @@
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyInVersion3 'id'
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
-// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}}
+// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0 0{{$}}
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
// CHECK-NOT: Attr
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassInVersion3 'id'
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
-// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}}
+// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0 0{{$}}
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
// CHECK-NOT: Attr
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyExceptInVersion3 'id'
-// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive{{$}}
+// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive 0{{$}}
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}}
// CHECK-NOT: Attr
// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassExceptInVersion3
'id'
-// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive{{$}}
+// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive 0{{$}}
// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>>
// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}}
diff --git a/clang/test/APINotes/versioned-version-independent.m
b/clang/test/APINotes/versioned-version-independent.m
index da8b34a1d9ba3a..29b9b3aa88ffaf 100644
--- a/clang/test/APINotes/versioned-version-independent.m
+++ b/clang/test/APINotes/versioned-version-independent.m
@@ -7,30 +7,41 @@
#import <VersionedKit/VersionedKit.h>
+// Each slice an API notes reader supplied is recorded by a
+// SwiftVersionedSliceAttr, whether or not it went on to set a key, and both it
+// and the wrappers carry the reader index they came from. The trailing 0 on
+// every line below is that index: one reader here.
+
// CHECK-VERSIONED-DUMP-LABEL: Dumping moveToPointDUMP
// CHECK-VERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)"
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedSliceAttr {{.+}} Implicit 3.0
0{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>>
"moveTo(a:b:)"
// CHECK-VERSIONED-DUMP-LABEL: Dumping unversionedRenameDUMP
// CHECK-VERSIONED-DUMP: SwiftNameAttr {{.+}} "unversionedRename_HEADER()"
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedSliceAttr {{.+}} Implicit 0 0{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0
0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_NOTES()"
// CHECK-VERSIONED-DUMP-LABEL: Dumping TestGenericDUMP
-// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
+// CHECK-VERSIONED-DUMP: SwiftVersionedSliceAttr {{.+}} Implicit 3.0 0{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} <<invalid
sloc>>
// CHECK-VERSIONED-DUMP: Swift3RenamedOnlyDUMP
-// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
+// CHECK-VERSIONED-DUMP: SwiftVersionedSliceAttr {{.+}} Implicit 3.0 0{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name"
// CHECK-VERSIONED-DUMP: Swift3RenamedAlsoDUMP
// CHECK-VERSIONED-DUMP: SwiftNameAttr {{.+}} "Swift4Name"
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedSliceAttr {{.+}} Implicit 3.0
0{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also"
// CHECK-VERSIONED-DUMP: Swift4RenamedDUMP
-// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 4
+// CHECK-VERSIONED-DUMP: SwiftVersionedSliceAttr {{.+}} Implicit 4 0{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 4
0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name"
diff --git a/clang/test/APINotes/versioned.m b/clang/test/APINotes/versioned.m
index 264edde2a04fce..3b108407a49f9e 100644
--- a/clang/test/APINotes/versioned.m
+++ b/clang/test/APINotes/versioned.m
@@ -16,50 +16,50 @@
// CHECK-VERSIONED:__attribute__((swift_name("moveTo(a:b:)"))) void
moveToPointDUMP(double x, double y);
// CHECK-DUMP-LABEL: Dumping moveToPointDUMP
-// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive{{$}}
+// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive 0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "moveTo(x:y:)"
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>>
"moveTo(a:b:)"
// CHECK-UNVERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit
3.0{{$}}
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>>
"moveTo(a:b:)"
// CHECK-DUMP-NOT: Attr
// CHECK-DUMP-LABEL: Dumping unversionedRenameDUMP
// CHECK-DUMP: in VersionedKit unversionedRenameDUMP
-// CHECK-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0
IsReplacedByActive{{$}}
+// CHECK-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0
IsReplacedByActive 0{{$}}
// 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 {{.+}} <<invalid sloc>>
-// CHECK-UNVERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}}
+// CHECK-UNVERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} <<invalid
sloc>>
// CHECK-DUMP-NOT: Attr
// CHECK-DUMP-LABEL: Dumping Swift3RenamedOnlyDUMP
// CHECK-DUMP: in VersionedKit Swift3RenamedOnlyDUMP
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0
{{[0-9]+}} IsReplacedByActive{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0
{{[0-9]+}} IsReplacedByActive 0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit
3.0{{$}}
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>>
"SpecialSwift3Name"
// CHECK-DUMP-NOT: Attr
// CHECK-DUMP-LABEL: Dumping Swift3RenamedAlsoDUMP
// CHECK-DUMP: in VersionedKit Swift3RenamedAlsoDUMP
-// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive{{$}}
+// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
IsReplacedByActive 0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <line:{{.+}}, col:{{.+}}>
"Swift4Name"
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also"
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <line:{{.+}}, col:{{.+}}>
"Swift4Name"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit
3.0{{$}}
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0
0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>>
"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: SwiftVersionedRemovalAttr {{.+}} Implicit 4
{{[0-9]+}} IsReplacedByActive 0{{$}}
// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name"
-// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit
4{{$}}
+// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 4
0{{$}}
// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>>
"SpecialSwift4Name"
// CHECK-DUMP-NOT: Attr
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits