diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp index 82f1e63eea0..060c9ba4bd9 100644 --- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp +++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp @@ -200,6 +200,11 @@ bool FullySpecifiedType::operator < (const FullySpecifiedType &other) const return _type < other._type; } +size_t FullySpecifiedType::hash() const +{ + return std::hash()(_type) ^ std::hash()(_flags); +} + FullySpecifiedType FullySpecifiedType::simplified() const { if (const ReferenceType *refTy = type()->asReferenceType()) diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h index aa983ada109..a8462d503a3 100644 --- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h +++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h @@ -103,6 +103,8 @@ public: bool operator != (const FullySpecifiedType &other) const; bool operator < (const FullySpecifiedType &other) const; + size_t hash() const; + bool match(const FullySpecifiedType &otherTy, Matcher *matcher = nullptr) const; FullySpecifiedType simplified() const; diff --git a/src/libs/3rdparty/cplusplus/Name.cpp b/src/libs/3rdparty/cplusplus/Name.cpp index 815b74bbed5..05ef8277f6c 100644 --- a/src/libs/3rdparty/cplusplus/Name.cpp +++ b/src/libs/3rdparty/cplusplus/Name.cpp @@ -25,6 +25,7 @@ #include "NameVisitor.h" #include +#include using namespace CPlusPlus; @@ -77,22 +78,33 @@ bool Name::match(const Name *other, Matcher *matcher) const return Matcher::match(this, other, matcher); } -bool Name::Compare::operator()(const Name *name, const Name *other) const +bool Name::Equals::operator()(const Name *name, const Name *other) const { - if (name == nullptr) - return other != nullptr; - if (other == nullptr) - return false; if (name == other) + return true; + if (name == nullptr || other == nullptr) return false; const Identifier *id = name->identifier(); const Identifier *otherId = other->identifier(); - if (id == nullptr) - return otherId != nullptr; - if (otherId == nullptr) + if (id == otherId) + return true; + if (id == nullptr || otherId == nullptr) return false; - return std::strcmp(id->chars(), otherId->chars()) < 0; + return std::strcmp(id->chars(), otherId->chars()) == 0; +} + +size_t Name::Hash::operator()(const Name *name) const +{ + if (name == nullptr) + return 0; + + const Identifier *id = name->identifier(); + + if (id == nullptr) + return 0; + + return std::hash()(std::string_view(id->chars())); } diff --git a/src/libs/3rdparty/cplusplus/Name.h b/src/libs/3rdparty/cplusplus/Name.h index 7a4a159ffef..1806a1e4cb8 100644 --- a/src/libs/3rdparty/cplusplus/Name.h +++ b/src/libs/3rdparty/cplusplus/Name.h @@ -59,9 +59,12 @@ public: bool match(const Name *other, Matcher *matcher = nullptr) const; public: - struct Compare { + struct Equals { bool operator()(const Name *name, const Name *other) const; }; + struct Hash { + size_t operator()(const Name *name) const; + }; protected: virtual void accept0(NameVisitor *visitor) const = 0; diff --git a/src/libs/3rdparty/cplusplus/Names.cpp b/src/libs/3rdparty/cplusplus/Names.cpp index dc77d47c0b9..0d3029ae5d1 100644 --- a/src/libs/3rdparty/cplusplus/Names.cpp +++ b/src/libs/3rdparty/cplusplus/Names.cpp @@ -24,6 +24,7 @@ #include "Literals.h" #include #include +#include using namespace CPlusPlus; @@ -106,38 +107,48 @@ int TemplateNameId::templateArgumentCount() const const TemplateArgument &TemplateNameId::templateArgumentAt(int index) const { return _templateArguments[index]; } -bool TemplateNameId::Compare::operator()(const TemplateNameId *name, - const TemplateNameId *other) const +bool TemplateNameId::Equals::operator()(const TemplateNameId *name, + const TemplateNameId *other) const { - if (name == nullptr) - return other != nullptr; - if (other == nullptr) - return false; if (name == other) + return true; + if (name == nullptr || other == nullptr) return false; const Identifier *id = name->identifier(); const Identifier *otherId = other->identifier(); - if (id == nullptr) - return otherId != nullptr; - if (otherId == nullptr) + if (!id != !otherId) // mimic logical xor (id == nullptr ^^ otherId == nullptr) return false; - const int c = std::strcmp(id->chars(), otherId->chars()); + const int c = id ? std::strcmp(id->chars(), otherId->chars()) : 0; // 0 if both are nullptr if (c == 0) { // we have to differentiate TemplateNameId with respect to specialization or instantiation if (name->isSpecialization() == other->isSpecialization()) { - return std::lexicographical_compare(name->firstTemplateArgument(), - name->lastTemplateArgument(), - other->firstTemplateArgument(), - other->lastTemplateArgument()); - } else { - return name->isSpecialization(); + return std::equal(name->firstTemplateArgument(), + name->lastTemplateArgument(), + other->firstTemplateArgument(), + other->lastTemplateArgument()); } } + return false; +} - return c < 0; +size_t TemplateNameId::Hash::operator()(const TemplateNameId *name) const +{ + if (name == nullptr) + return 0; + + const Identifier *id = name->identifier(); + + size_t hash = id ? std::hash()(std::string_view(id->chars())) : 0; + hash ^= name->isSpecialization() ? 0x1 : 0x0; + std::for_each(name->firstTemplateArgument(), + name->lastTemplateArgument(), + [&hash](const TemplateArgument &ta) { + hash ^= ta.hash(); + }); + return hash; } OperatorNameId::OperatorNameId(Kind kind) diff --git a/src/libs/3rdparty/cplusplus/Names.h b/src/libs/3rdparty/cplusplus/Names.h index 6f9480b195e..7b8783740d3 100644 --- a/src/libs/3rdparty/cplusplus/Names.h +++ b/src/libs/3rdparty/cplusplus/Names.h @@ -113,6 +113,11 @@ public: bool match(const TemplateArgument &otherTy, Matcher *matcher = nullptr) const; + size_t hash() const + { + return _expressionTy.hash() ^ std::hash()(_numericLiteral); + } + private: FullySpecifiedType _expressionTy; const NumericLiteral *_numericLiteral = nullptr; @@ -145,10 +150,13 @@ public: TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); } bool isSpecialization() const { return _isSpecialization; } - // Comparator needed to distinguish between two different TemplateNameId(e.g.:used in std::map) - struct Compare { + // Comparator needed to distinguish between two different TemplateNameId(e.g.:used in std::unordered_map) + struct Equals { bool operator()(const TemplateNameId *name, const TemplateNameId *other) const; }; + struct Hash { + size_t operator()(const TemplateNameId *name) const; + }; protected: void accept0(NameVisitor *visitor) const override; diff --git a/src/libs/3rdparty/cplusplus/Templates.h b/src/libs/3rdparty/cplusplus/Templates.h index 3db31f46723..522ebf85046 100644 --- a/src/libs/3rdparty/cplusplus/Templates.h +++ b/src/libs/3rdparty/cplusplus/Templates.h @@ -60,7 +60,7 @@ public: private: Control *_control; Subst *_previous; - std::map _map; + std::unordered_map _map; }; class CPLUSPLUS_EXPORT CloneType: protected TypeVisitor diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 17f7be1fc8b..c55b2714f34 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -89,8 +89,8 @@ public: Class *rootClass() const { return _rootClass; } private: - typedef std::map Table; - typedef std::map TemplateNameIdTable; + typedef std::unordered_map Table; + typedef std::unordered_map TemplateNameIdTable; typedef QHash Anonymouses; /// \internal