Skip to content

Commit 2acfa1a

Browse files
[ADT] Refactor StringMap iterators (NFC)
StringMap has four iterator classes: - StringMapIterBase - StringMapIterator - StringMapConstIterator - StringMapKeyIterator This patch consolidates the first three into one class, namely StringMapIterBase, adds a boolean template parameter to indicate desired constness, and then use "using" directives to specialize the common class: using const_iterator = StringMapIterBase<ValueTy, true>; using iterator = StringMapIterBase<ValueTy, false>; just like how we simplified DenseMapIterator. Remarks: - This patch drops CRTP and iterator_facade_base for simplicity. For fairly simple forward iterators, iterator_facade_base doesn't buy us much. We just have to write a few "using" directives and operator!= manually. - StringMapIterBase has a SFINAE-based constructor to construct a const iterator from a non-const one just like DenseMapIterator. - We now rely on compiler-generated copy and assignment operators.
1 parent 3e6ec47 commit 2acfa1a

File tree

3 files changed

+39
-64
lines changed

3 files changed

+39
-64
lines changed

clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ bool MultipleInheritanceCheck::getInterfaceStatus(const CXXRecordDecl *Node,
3939
bool &IsInterface) const {
4040
assert(Node->getIdentifier());
4141
StringRef Name = Node->getIdentifier()->getName();
42-
llvm::StringMapConstIterator<bool> Pair = InterfaceMap.find(Name);
42+
auto Pair = InterfaceMap.find(Name);
4343
if (Pair == InterfaceMap.end())
4444
return false;
4545
IsInterface = Pair->second;

clang/lib/Driver/OffloadBundler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,8 +1936,7 @@ Error OffloadBundler::UnbundleArchive() {
19361936
/// Write out an archive for each target
19371937
for (auto &Target : BundlerConfig.TargetNames) {
19381938
StringRef FileName = TargetOutputFileNameMap[Target];
1939-
StringMapIterator<std::vector<llvm::NewArchiveMember>> CurArchiveMembers =
1940-
OutputArchivesMap.find(Target);
1939+
auto CurArchiveMembers = OutputArchivesMap.find(Target);
19411940
if (CurArchiveMembers != OutputArchivesMap.end()) {
19421941
if (Error WriteErr = writeArchive(FileName, CurArchiveMembers->getValue(),
19431942
SymtabWritingMode::NormalSymtab,

llvm/include/llvm/ADT/StringMap.h

Lines changed: 37 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
#include "llvm/Support/PointerLikeTypeTraits.h"
2222
#include <initializer_list>
2323
#include <iterator>
24+
#include <type_traits>
2425

2526
namespace llvm {
2627

27-
template <typename ValueTy> class StringMapConstIterator;
28-
template <typename ValueTy> class StringMapIterator;
28+
template <typename ValueTy, bool IsConst> class StringMapIterBase;
2929
template <typename ValueTy> class StringMapKeyIterator;
3030

3131
/// StringMapImpl - This is the base class of StringMap that is shared among
@@ -217,8 +217,8 @@ class LLVM_ALLOCATORHOLDER_EMPTYBASE StringMap
217217
using value_type = StringMapEntry<ValueTy>;
218218
using size_type = size_t;
219219

220-
using const_iterator = StringMapConstIterator<ValueTy>;
221-
using iterator = StringMapIterator<ValueTy>;
220+
using const_iterator = StringMapIterBase<ValueTy, true>;
221+
using iterator = StringMapIterBase<ValueTy, false>;
222222

223223
iterator begin() { return iterator(TheTable, NumBuckets == 0); }
224224
iterator end() { return iterator(TheTable + NumBuckets, true); }
@@ -431,14 +431,19 @@ class LLVM_ALLOCATORHOLDER_EMPTYBASE StringMap
431431
}
432432
};
433433

434-
template <typename DerivedTy, typename ValueTy>
435-
class StringMapIterBase
436-
: public iterator_facade_base<DerivedTy, std::forward_iterator_tag,
437-
ValueTy> {
438-
protected:
434+
template <typename ValueTy, bool IsConst> class StringMapIterBase {
435+
using EntryTy = std::conditional_t<IsConst, const StringMapEntry<ValueTy>,
436+
StringMapEntry<ValueTy>>;
437+
439438
StringMapEntryBase **Ptr = nullptr;
440439

441440
public:
441+
using iterator_category = std::forward_iterator_tag;
442+
using value_type = EntryTy;
443+
using difference_type = std::ptrdiff_t;
444+
using pointer = value_type *;
445+
using reference = value_type &;
446+
442447
StringMapIterBase() = default;
443448

444449
explicit StringMapIterBase(StringMapEntryBase **Bucket,
@@ -448,85 +453,56 @@ class StringMapIterBase
448453
AdvancePastEmptyBuckets();
449454
}
450455

451-
DerivedTy &operator=(const DerivedTy &Other) {
452-
Ptr = Other.Ptr;
453-
return static_cast<DerivedTy &>(*this);
454-
}
455-
456-
friend bool operator==(const DerivedTy &LHS, const DerivedTy &RHS) {
457-
return LHS.Ptr == RHS.Ptr;
458-
}
456+
reference operator*() const { return *static_cast<EntryTy *>(*Ptr); }
457+
pointer operator->() const { return &operator*(); }
459458

460-
DerivedTy &operator++() { // Preincrement
459+
StringMapIterBase &operator++() { // Preincrement
461460
++Ptr;
462461
AdvancePastEmptyBuckets();
463-
return static_cast<DerivedTy &>(*this);
462+
return *this;
464463
}
465464

466-
DerivedTy operator++(int) { // Post-increment
467-
DerivedTy Tmp(Ptr);
465+
StringMapIterBase operator++(int) { // Post-increment
466+
StringMapIterBase Tmp(*this);
468467
++*this;
469468
return Tmp;
470469
}
471470

472-
private:
473-
void AdvancePastEmptyBuckets() {
474-
while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
475-
++Ptr;
471+
template <bool ToConst,
472+
typename = typename std::enable_if<!IsConst && ToConst>::type>
473+
operator StringMapIterBase<ValueTy, ToConst>() const {
474+
return StringMapIterBase<ValueTy, ToConst>(Ptr, true);
476475
}
477-
};
478-
479-
template <typename ValueTy>
480-
class StringMapConstIterator
481-
: public StringMapIterBase<StringMapConstIterator<ValueTy>,
482-
const StringMapEntry<ValueTy>> {
483-
using base = StringMapIterBase<StringMapConstIterator<ValueTy>,
484-
const StringMapEntry<ValueTy>>;
485-
486-
public:
487-
StringMapConstIterator() = default;
488-
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
489-
bool NoAdvance = false)
490-
: base(Bucket, NoAdvance) {}
491476

492-
const StringMapEntry<ValueTy> &operator*() const {
493-
return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr);
477+
friend bool operator==(const StringMapIterBase &LHS,
478+
const StringMapIterBase &RHS) {
479+
return LHS.Ptr == RHS.Ptr;
494480
}
495-
};
496-
497-
template <typename ValueTy>
498-
class StringMapIterator : public StringMapIterBase<StringMapIterator<ValueTy>,
499-
StringMapEntry<ValueTy>> {
500-
using base =
501-
StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>;
502481

503-
public:
504-
StringMapIterator() = default;
505-
explicit StringMapIterator(StringMapEntryBase **Bucket,
506-
bool NoAdvance = false)
507-
: base(Bucket, NoAdvance) {}
508-
509-
StringMapEntry<ValueTy> &operator*() const {
510-
return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr);
482+
friend bool operator!=(const StringMapIterBase &LHS,
483+
const StringMapIterBase &RHS) {
484+
return !(LHS == RHS);
511485
}
512486

513-
operator StringMapConstIterator<ValueTy>() const {
514-
return StringMapConstIterator<ValueTy>(this->Ptr, true);
487+
private:
488+
void AdvancePastEmptyBuckets() {
489+
while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
490+
++Ptr;
515491
}
516492
};
517493

518494
template <typename ValueTy>
519495
class StringMapKeyIterator
520496
: public iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
521-
StringMapConstIterator<ValueTy>,
497+
StringMapIterBase<ValueTy, true>,
522498
std::forward_iterator_tag, StringRef> {
523499
using base = iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
524-
StringMapConstIterator<ValueTy>,
500+
StringMapIterBase<ValueTy, true>,
525501
std::forward_iterator_tag, StringRef>;
526502

527503
public:
528504
StringMapKeyIterator() = default;
529-
explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
505+
explicit StringMapKeyIterator(StringMapIterBase<ValueTy, true> Iter)
530506
: base(std::move(Iter)) {}
531507

532508
StringRef operator*() const { return this->wrapped()->getKey(); }

0 commit comments

Comments
 (0)