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

Reply via email to