llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Artem Chikin (artemcm)

<details>
<summary>Changes</summary>

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.

---

Patch is 26.67 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/224860.diff


7 Files Affected:

- (modified) clang/include/clang/APINotes/APINotesManager.h (+8) 
- (modified) clang/include/clang/Basic/Attr.td (+20-2) 
- (modified) clang/lib/APINotes/APINotesManager.cpp (+8) 
- (modified) clang/lib/Sema/SemaAPINotes.cpp (+78-34) 
- (modified) clang/test/APINotes/properties.m (+4-4) 
- (modified) clang/test/APINotes/versioned-version-independent.m (+17-6) 
- (modified) clang/test/APINotes/versioned.m (+10-10) 


``````````diff
diff --git a/clang/include/clang/APINotes/APINotesManager.h 
b/clang/include/clang/APINotes/APINotesManager.h
index aaf48706fb26b..7aa1711efb009 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 61ef3fb612440..6a54f20bc121c 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 2cc801d5415b8..65da1c50177f1 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 4c7e5ea16cfd7..695339fe17451 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 79b5e2b10c47c..cad7e399000f9 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 da8b34a1d9ba3..29b9b3aa88ffa 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 ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/224860
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to