[llvm] 0882c70 - [TextAPI] Introduce SymbolSet
Cyndy Ishida via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 24 12:02:28 PDT 2023
Author: Cyndy Ishida
Date: 2023-07-24T12:01:25-07:00
New Revision: 0882c70df222a89c15f2776b85a60696e6ecd712
URL: https://github.com/llvm/llvm-project/commit/0882c70df222a89c15f2776b85a60696e6ecd712
DIFF: https://github.com/llvm/llvm-project/commit/0882c70df222a89c15f2776b85a60696e6ecd712.diff
LOG: [TextAPI] Introduce SymbolSet
SymbolSet is a structure that acts as a simple container class for exported symbols that
belong to a library interface. It allows tapi to decouple the globals
from the other library attributes. It's uniqued by symbol name and `kind`, which all contain their assigned target triples.
Reviewed By: zixuw
Differential Revision: https://reviews.llvm.org/D149860
Added:
llvm/include/llvm/TextAPI/SymbolSet.h
llvm/lib/TextAPI/SymbolSet.cpp
Modified:
llvm/include/llvm/TextAPI/InterfaceFile.h
llvm/include/llvm/TextAPI/Symbol.h
llvm/lib/TextAPI/CMakeLists.txt
llvm/lib/TextAPI/InterfaceFile.cpp
llvm/lib/TextAPI/Symbol.cpp
llvm/unittests/TextAPI/TextStubV5Tests.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/TextAPI/InterfaceFile.h b/llvm/include/llvm/TextAPI/InterfaceFile.h
index 7d20c6f6348607..7b0cd6109a2f15 100644
--- a/llvm/include/llvm/TextAPI/InterfaceFile.h
+++ b/llvm/include/llvm/TextAPI/InterfaceFile.h
@@ -24,6 +24,7 @@
#include "llvm/TextAPI/PackedVersion.h"
#include "llvm/TextAPI/Platform.h"
#include "llvm/TextAPI/Symbol.h"
+#include "llvm/TextAPI/SymbolSet.h"
#include "llvm/TextAPI/Target.h"
namespace llvm {
@@ -123,37 +124,15 @@ class InterfaceFileRef {
} // end namespace MachO.
-struct SymbolsMapKey {
- MachO::SymbolKind Kind;
- StringRef Name;
-
- SymbolsMapKey(MachO::SymbolKind Kind, StringRef Name)
- : Kind(Kind), Name(Name) {}
-};
-template <> struct DenseMapInfo<SymbolsMapKey> {
- static inline SymbolsMapKey getEmptyKey() {
- return SymbolsMapKey(MachO::SymbolKind::GlobalSymbol, StringRef{});
- }
-
- static inline SymbolsMapKey getTombstoneKey() {
- return SymbolsMapKey(MachO::SymbolKind::ObjectiveCInstanceVariable,
- StringRef{});
- }
-
- static unsigned getHashValue(const SymbolsMapKey &Key) {
- return hash_combine(hash_value(Key.Kind), hash_value(Key.Name));
- }
-
- static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) {
- return std::tie(LHS.Kind, LHS.Name) == std::tie(RHS.Kind, RHS.Name);
- }
-};
-
namespace MachO {
/// Defines the interface file.
class InterfaceFile {
public:
+ InterfaceFile(std::unique_ptr<SymbolSet> &&InputSymbols)
+ : SymbolsSet(std::move(InputSymbols)) {}
+
+ InterfaceFile() : SymbolsSet(std::make_unique<SymbolSet>()){};
/// Set the path from which this file was generated (if applicable).
///
/// \param Path_ The path to the source file.
@@ -360,66 +339,63 @@ class InterfaceFile {
return RPaths;
}
- /// Add a symbol to the symbols list or extend an existing one.
- void addSymbol(SymbolKind Kind, StringRef Name, const TargetList &Targets,
- SymbolFlags Flags = SymbolFlags::None);
-
- using SymbolMapType = DenseMap<SymbolsMapKey, Symbol *>;
- struct const_symbol_iterator
- : public iterator_adaptor_base<
- const_symbol_iterator, SymbolMapType::const_iterator,
- std::forward_iterator_tag, const Symbol *, ptr
diff _t,
- const Symbol *, const Symbol *> {
- const_symbol_iterator() = default;
-
- template <typename U>
- const_symbol_iterator(U &&u)
- : iterator_adaptor_base(std::forward<U &&>(u)) {}
-
- reference operator*() const { return I->second; }
- pointer operator->() const { return I->second; }
- };
+ /// Get symbol if exists in file.
+ ///
+ /// \param Kind The kind of global symbol to record.
+ /// \param Name The name of the symbol.
+ std::optional<const Symbol *> getSymbol(SymbolKind Kind,
+ StringRef Name) const {
+ if (auto *Sym = SymbolsSet->findSymbol(Kind, Name))
+ return Sym;
+ return std::nullopt;
+ }
- using const_symbol_range = iterator_range<const_symbol_iterator>;
+ /// Add a symbol to the symbols list or extend an existing one.
+ template <typename RangeT,
+ typename ElT = typename std::remove_reference<
+ decltype(*std::begin(std::declval<RangeT>()))>::type>
+ void addSymbol(SymbolKind Kind, StringRef Name, RangeT &&Targets,
+ SymbolFlags Flags = SymbolFlags::None) {
+ SymbolsSet->addGlobal(Kind, Name, Flags, Targets);
+ }
- using const_filtered_symbol_iterator =
- filter_iterator<const_symbol_iterator,
- std::function<bool(const Symbol *)>>;
- using const_filtered_symbol_range =
- iterator_range<const_filtered_symbol_iterator>;
+ /// Add Symbol with multiple targets.
+ ///
+ /// \param Kind The kind of global symbol to record.
+ /// \param Name The name of the symbol.
+ /// \param Targets The list of targets the symbol is defined in.
+ /// \param Flags The properties the symbol holds.
+ void addSymbol(SymbolKind Kind, StringRef Name, TargetList &&Targets,
+ SymbolFlags Flags = SymbolFlags::None) {
+ SymbolsSet->addGlobal(Kind, Name, Flags, Targets);
+ }
- const_symbol_range symbols() const {
- return {Symbols.begin(), Symbols.end()};
+ /// Add Symbol with single target.
+ ///
+ /// \param Kind The kind of global symbol to record.
+ /// \param Name The name of the symbol.
+ /// \param Target The target the symbol is defined in.
+ /// \param Flags The properties the symbol holds.
+ void addSymbol(SymbolKind Kind, StringRef Name, Target &Target,
+ SymbolFlags Flags = SymbolFlags::None) {
+ SymbolsSet->addGlobal(Kind, Name, Flags, Target);
}
- size_t symbolsCount() const { return Symbols.size(); }
+ /// Get size of symbol set.
+ /// \return The number of symbols the file holds.
+ size_t symbolsCount() const { return SymbolsSet->size(); }
- const_filtered_symbol_range exports() const {
- std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
- return !Symbol->isUndefined() && !Symbol->isReexported();
- };
- return make_filter_range(
- make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
- fn);
- }
+ using const_symbol_range = SymbolSet::const_symbol_range;
+ using const_filtered_symbol_range = SymbolSet::const_filtered_symbol_range;
+ const_symbol_range symbols() const { return SymbolsSet->symbols(); };
+ const_filtered_symbol_range exports() const { return SymbolsSet->exports(); };
const_filtered_symbol_range reexports() const {
- std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
- return Symbol->isReexported();
- };
- return make_filter_range(
- make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
- fn);
- }
-
+ return SymbolsSet->reexports();
+ };
const_filtered_symbol_range undefineds() const {
- std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
- return Symbol->isUndefined();
- };
- return make_filter_range(
- make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
- fn);
- }
+ return SymbolsSet->undefineds();
+ };
/// The equality is determined by attributes that impact linking
/// compatibilities. UUIDs, Path, & FileKind are irrelevant since these by
@@ -457,23 +433,20 @@ class InterfaceFile {
std::vector<std::shared_ptr<InterfaceFile>> Documents;
std::vector<std::pair<Target, std::string>> UUIDs;
std::vector<std::pair<Target, std::string>> RPaths;
- SymbolMapType Symbols;
+ std::unique_ptr<SymbolSet> SymbolsSet;
InterfaceFile *Parent = nullptr;
};
-template <typename DerivedT, typename KeyInfoT, typename BucketT>
-bool operator==(const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
- KeyInfoT, BucketT> &LHS,
- const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
- KeyInfoT, BucketT> &RHS) {
- if (LHS.size() != RHS.size())
- return false;
- for (const auto &KV : LHS) {
- auto I = RHS.find(KV.first);
- if (I == RHS.end() || *I->second != *KV.second)
- return false;
- }
- return true;
+// Keep containers that hold InterfaceFileRefs in sorted order and uniqued.
+template <typename C>
+typename C::iterator addEntry(C &Container, StringRef InstallName) {
+ auto I = partition_point(Container, [=](const InterfaceFileRef &O) {
+ return O.getInstallName() < InstallName;
+ });
+ if (I != Container.end() && I->getInstallName() == InstallName)
+ return I;
+
+ return Container.emplace(I, InstallName);
}
} // end namespace MachO.
diff --git a/llvm/include/llvm/TextAPI/Symbol.h b/llvm/include/llvm/TextAPI/Symbol.h
index 48627c3d893a28..a20fcc785b4097 100644
--- a/llvm/include/llvm/TextAPI/Symbol.h
+++ b/llvm/include/llvm/TextAPI/Symbol.h
@@ -65,12 +65,26 @@ constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
using TargetList = SmallVector<Target, 5>;
+
+// Keep containers that hold Targets in sorted order and uniqued.
+template <typename C>
+typename C::iterator addEntry(C &Container, const Target &Targ) {
+ auto Iter =
+ lower_bound(Container, Targ, [](const Target &LHS, const Target &RHS) {
+ return LHS < RHS;
+ });
+ if ((Iter != std::end(Container)) && !(Targ < *Iter))
+ return Iter;
+
+ return Container.insert(Iter, Targ);
+}
+
class Symbol {
public:
Symbol(SymbolKind Kind, StringRef Name, TargetList Targets, SymbolFlags Flags)
: Name(Name), Targets(std::move(Targets)), Kind(Kind), Flags(Flags) {}
- void addTarget(Target target) { Targets.emplace_back(target); }
+ void addTarget(Target InputTarget) { addEntry(Targets, InputTarget); }
SymbolKind getKind() const { return Kind; }
StringRef getName() const { return Name; }
ArchitectureSet getArchitectures() const {
diff --git a/llvm/include/llvm/TextAPI/SymbolSet.h b/llvm/include/llvm/TextAPI/SymbolSet.h
new file mode 100644
index 00000000000000..238385178d605d
--- /dev/null
+++ b/llvm/include/llvm/TextAPI/SymbolSet.h
@@ -0,0 +1,182 @@
+//===- llvm/TextAPI/SymbolSet.h - TAPI Symbol Set --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TEXTAPI_SYMBOLSET_H
+#define LLVM_TEXTAPI_SYMBOLSET_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/TextAPI/Architecture.h"
+#include "llvm/TextAPI/ArchitectureSet.h"
+#include "llvm/TextAPI/Symbol.h"
+#include <stddef.h>
+
+namespace llvm {
+
+struct SymbolsMapKey {
+ MachO::SymbolKind Kind;
+ StringRef Name;
+
+ SymbolsMapKey(MachO::SymbolKind Kind, StringRef Name)
+ : Kind(Kind), Name(Name) {}
+};
+template <> struct DenseMapInfo<SymbolsMapKey> {
+ static inline SymbolsMapKey getEmptyKey() {
+ return SymbolsMapKey(MachO::SymbolKind::GlobalSymbol, StringRef{});
+ }
+
+ static inline SymbolsMapKey getTombstoneKey() {
+ return SymbolsMapKey(MachO::SymbolKind::ObjectiveCInstanceVariable,
+ StringRef{});
+ }
+
+ static unsigned getHashValue(const SymbolsMapKey &Key) {
+ return hash_combine(hash_value(Key.Kind), hash_value(Key.Name));
+ }
+
+ static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) {
+ return std::tie(LHS.Kind, LHS.Name) == std::tie(RHS.Kind, RHS.Name);
+ }
+};
+
+template <typename DerivedT, typename KeyInfoT, typename BucketT>
+bool operator==(const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
+ KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
+ KeyInfoT, BucketT> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+ for (const auto &KV : LHS) {
+ auto I = RHS.find(KV.first);
+ if (I == RHS.end() || *I->second != *KV.second)
+ return false;
+ }
+ return true;
+}
+
+template <typename DerivedT, typename KeyInfoT, typename BucketT>
+bool operator!=(const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
+ KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
+ KeyInfoT, BucketT> &RHS) {
+ return !(LHS == RHS);
+}
+
+namespace MachO {
+
+class SymbolSet {
+private:
+ llvm::BumpPtrAllocator Allocator;
+ StringRef copyString(StringRef String) {
+ if (String.empty())
+ return {};
+ void *Ptr = Allocator.Allocate(String.size(), 1);
+ memcpy(Ptr, String.data(), String.size());
+ return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
+ }
+
+ using SymbolsMapType = llvm::DenseMap<SymbolsMapKey, Symbol *>;
+ SymbolsMapType Symbols;
+
+ Symbol *addGlobalImpl(SymbolKind, StringRef Name, SymbolFlags Flags);
+
+public:
+ SymbolSet() = default;
+ Symbol *addGlobal(SymbolKind Kind, StringRef Name, SymbolFlags Flags,
+ const Target &Targ);
+ size_t size() const { return Symbols.size(); }
+
+ template <typename RangeT,
+ typename ElT = typename std::remove_reference<
+ decltype(*std::begin(std::declval<RangeT>()))>::type>
+ Symbol *addGlobal(SymbolKind Kind, StringRef Name, SymbolFlags Flags,
+ RangeT &&Targets) {
+ auto *Global = addGlobalImpl(Kind, Name, Flags);
+ for (const auto &Targ : Targets)
+ Global->addTarget(Targ);
+ if (Kind == SymbolKind::ObjectiveCClassEHType)
+ addGlobal(SymbolKind::ObjectiveCClass, Name, Flags, Targets);
+ return Global;
+ }
+
+ const Symbol *findSymbol(SymbolKind Kind, StringRef Name) const;
+
+ struct const_symbol_iterator
+ : public iterator_adaptor_base<
+ const_symbol_iterator, SymbolsMapType::const_iterator,
+ std::forward_iterator_tag, const Symbol *, ptr
diff _t,
+ const Symbol *, const Symbol *> {
+ const_symbol_iterator() = default;
+
+ template <typename U>
+ const_symbol_iterator(U &&u)
+ : iterator_adaptor_base(std::forward<U &&>(u)) {}
+
+ reference operator*() const { return I->second; }
+ pointer operator->() const { return I->second; }
+ };
+
+ using const_symbol_range = iterator_range<const_symbol_iterator>;
+
+ using const_filtered_symbol_iterator =
+ filter_iterator<const_symbol_iterator,
+ std::function<bool(const Symbol *)>>;
+ using const_filtered_symbol_range =
+ iterator_range<const_filtered_symbol_iterator>;
+
+ // Range that contains all symbols.
+ const_symbol_range symbols() const {
+ return {Symbols.begin(), Symbols.end()};
+ }
+
+ // Range that contains all defined and exported symbols.
+ const_filtered_symbol_range exports() const {
+ std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
+ return !Symbol->isUndefined() && !Symbol->isReexported();
+ };
+ return make_filter_range(
+ make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
+ fn);
+ }
+
+ // Range that contains all reexported symbols.
+ const_filtered_symbol_range reexports() const {
+ std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
+ return Symbol->isReexported();
+ };
+ return make_filter_range(
+ make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
+ fn);
+ }
+
+ // Range that contains all undefined and exported symbols.
+ const_filtered_symbol_range undefineds() const {
+ std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
+ return Symbol->isUndefined();
+ };
+ return make_filter_range(
+ make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
+ fn);
+ }
+
+ bool operator==(const SymbolSet &O) const;
+
+ bool operator!=(const SymbolSet &O) const { return !(Symbols == O.Symbols); }
+
+ void *allocate(size_t Size, unsigned Align = 8) {
+ return Allocator.Allocate(Size, Align);
+ }
+};
+
+} // namespace MachO
+} // namespace llvm
+#endif // LLVM_TEXTAPI_SYMBOLSET_H
diff --git a/llvm/lib/TextAPI/CMakeLists.txt b/llvm/lib/TextAPI/CMakeLists.txt
index 1714ce33ef205a..647a04f5da7881 100644
--- a/llvm/lib/TextAPI/CMakeLists.txt
+++ b/llvm/lib/TextAPI/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMTextAPI
PackedVersion.cpp
Platform.cpp
Symbol.cpp
+ SymbolSet.cpp
Target.cpp
TextStub.cpp
TextStubCommon.cpp
diff --git a/llvm/lib/TextAPI/InterfaceFile.cpp b/llvm/lib/TextAPI/InterfaceFile.cpp
index 8c0b65916026e0..bb98c92f71782b 100644
--- a/llvm/lib/TextAPI/InterfaceFile.cpp
+++ b/llvm/lib/TextAPI/InterfaceFile.cpp
@@ -17,31 +17,6 @@
using namespace llvm;
using namespace llvm::MachO;
-namespace {
-template <typename C>
-typename C::iterator addEntry(C &Container, StringRef InstallName) {
- auto I = partition_point(Container, [=](const InterfaceFileRef &O) {
- return O.getInstallName() < InstallName;
- });
- if (I != Container.end() && I->getInstallName() == InstallName)
- return I;
-
- return Container.emplace(I, InstallName);
-}
-
-template <typename C>
-typename C::iterator addEntry(C &Container, const Target &Target_) {
- auto Iter =
- lower_bound(Container, Target_, [](const Target &LHS, const Target &RHS) {
- return LHS < RHS;
- });
- if ((Iter != std::end(Container)) && !(Target_ < *Iter))
- return Iter;
-
- return Container.insert(Iter, Target_);
-}
-} // end namespace
-
void InterfaceFileRef::addTarget(const Target &Target) {
addEntry(Targets, Target);
}
@@ -120,17 +95,6 @@ InterfaceFile::targets(ArchitectureSet Archs) const {
return make_filter_range(Targets, fn);
}
-void InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name,
- const TargetList &Targets, SymbolFlags Flags) {
- Name = copyString(Name);
- auto result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
- if (result.second)
- result.first->second = new (Allocator) Symbol{Kind, Name, Targets, Flags};
- else
- for (const auto &Target : Targets)
- result.first->second->addTarget(Target);
-}
-
void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
auto Pos = llvm::lower_bound(Documents, Document,
[](const std::shared_ptr<InterfaceFile> &LHS,
@@ -167,7 +131,7 @@ bool InterfaceFile::operator==(const InterfaceFile &O) const {
return false;
if (ReexportedLibraries != O.ReexportedLibraries)
return false;
- if (Symbols != O.Symbols)
+ if (*SymbolsSet != *O.SymbolsSet)
return false;
// Don't compare run search paths for older filetypes that cannot express
// them.
diff --git a/llvm/lib/TextAPI/Symbol.cpp b/llvm/lib/TextAPI/Symbol.cpp
index f56493e54973d0..20fa6362716acf 100644
--- a/llvm/lib/TextAPI/Symbol.cpp
+++ b/llvm/lib/TextAPI/Symbol.cpp
@@ -65,10 +65,9 @@ bool Symbol::operator==(const Symbol &O) const {
};
SymbolFlags LHSFlags = Flags;
SymbolFlags RHSFlags = O.Flags;
- if ((!O.isData() && !O.isText()) || (!isData() && !isText())) {
- RemoveFlag(*this, LHSFlags);
- RemoveFlag(O, RHSFlags);
- }
+ // Ignore Text and Data for now.
+ RemoveFlag(*this, LHSFlags);
+ RemoveFlag(O, RHSFlags);
return std::tie(Name, Kind, Targets, LHSFlags) ==
std::tie(O.Name, O.Kind, O.Targets, RHSFlags);
}
diff --git a/llvm/lib/TextAPI/SymbolSet.cpp b/llvm/lib/TextAPI/SymbolSet.cpp
new file mode 100644
index 00000000000000..157e1374972938
--- /dev/null
+++ b/llvm/lib/TextAPI/SymbolSet.cpp
@@ -0,0 +1,36 @@
+//===- lib/TextAPI/SymbolSet.cpp - TAPI Symbol Set ------------*- C++-*----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TextAPI/SymbolSet.h"
+
+using namespace llvm;
+using namespace llvm::MachO;
+
+Symbol *SymbolSet::addGlobalImpl(SymbolKind Kind, StringRef Name,
+ SymbolFlags Flags) {
+ Name = copyString(Name);
+ auto Result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
+ if (Result.second)
+ Result.first->second =
+ new (Allocator) Symbol{Kind, Name, TargetList(), Flags};
+ return Result.first->second;
+}
+
+Symbol *SymbolSet::addGlobal(SymbolKind Kind, StringRef Name, SymbolFlags Flags,
+ const Target &Targ) {
+ auto *Sym = addGlobalImpl(Kind, Name, Flags);
+ Sym->addTarget(Targ);
+ return Sym;
+}
+
+const Symbol *SymbolSet::findSymbol(SymbolKind Kind, StringRef Name) const {
+ auto It = Symbols.find({Kind, Name});
+ if (It != Symbols.end())
+ return It->second;
+ return nullptr;
+}
diff --git a/llvm/unittests/TextAPI/TextStubV5Tests.cpp b/llvm/unittests/TextAPI/TextStubV5Tests.cpp
index 5f8d3de991d0d6..782b32444ae33b 100644
--- a/llvm/unittests/TextAPI/TextStubV5Tests.cpp
+++ b/llvm/unittests/TextAPI/TextStubV5Tests.cpp
@@ -124,6 +124,8 @@ TEST(TBDv5, ReadFile) {
"_globalVar"
],
"objc_class": [
+ "ClassA",
+ "ClassB",
"ClassData"
],
"objc_eh_type": [
@@ -264,7 +266,18 @@ TEST(TBDv5, ReadFile) {
false,
true,
{Target(AK_x86_64, PLATFORM_MACOS)}},
- {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
+ {SymbolKind::ObjectiveCClass,
+ "ClassA",
+ false,
+ false,
+ true,
+ {Target(AK_x86_64, PLATFORM_MACOS)}},
+ {SymbolKind::ObjectiveCClass,
+ "ClassB",
+ false,
+ false,
+ true,
+ {Target(AK_x86_64, PLATFORM_MACOS)}},
{SymbolKind::ObjectiveCClass,
"ClassData",
false,
@@ -333,6 +346,9 @@ TEST(TBDv5, ReadFile) {
std::begin(ExpectedReexportedSymbols)));
EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
std::begin(ExpectedUndefinedSymbols)));
+
+ EXPECT_TRUE(
+ File->getSymbol(SymbolKind::GlobalSymbol, "_globalBind").has_value());
}
TEST(TBDv5, ReadMultipleTargets) {
@@ -440,7 +456,7 @@ TEST(TBDv5, ReadMultipleDocuments) {
{
"data": {
"thread_local": [ "_globalVar" ],
- "objc_class": [ "ClassData" ],
+ "objc_class": [ "ClassData", "ClassA", "ClassB"],
"objc_eh_type": [ "ClassA", "ClassB" ]
},
"text": {
@@ -495,6 +511,8 @@ TEST(TBDv5, ReadMultipleDocuments) {
ExportedSymbolSeq ExpectedExports = {
{SymbolKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}},
{SymbolKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}},
+ {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}},
+ {SymbolKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}},
{SymbolKind::ObjectiveCClass,
"ClassData",
false,
@@ -622,6 +640,8 @@ TEST(TBDv5, WriteFile) {
"_globalVar"
],
"objc_class": [
+ "ClassA",
+ "ClassB",
"ClassData"
],
"objc_eh_type": [
More information about the llvm-commits
mailing list