diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index d6bc16b6350f..a75ae14f9015 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -24,6 +24,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/iterator.h" using namespace clang; @@ -50,12 +51,64 @@ static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { return nullptr; } -/// \brief Keeps track of the mangled names of lambda expressions and block +/// The name of a decomposition declaration. +struct DecompositionDeclName { + using BindingArray = ArrayRef<const BindingDecl*>; + + /// Representative example of a set of bindings with these names. + BindingArray Bindings; + + /// Iterators over the sequence of identifiers in the name. + struct Iterator + : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator, + std::random_access_iterator_tag, + const IdentifierInfo *> { + Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {} + const IdentifierInfo *operator*() const { + return (*this->I)->getIdentifier(); + } + }; + Iterator begin() const { return Iterator(Bindings.begin()); } + Iterator end() const { return Iterator(Bindings.end()); } +}; +} + +namespace llvm { +template<> +struct DenseMapInfo<DecompositionDeclName> { + using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>; + using IdentInfo = llvm::DenseMapInfo<const IdentifierInfo*>; + static DecompositionDeclName getEmptyKey() { + return {ArrayInfo::getEmptyKey()}; + } + static DecompositionDeclName getTombstoneKey() { + return {ArrayInfo::getTombstoneKey()}; + } + static unsigned getHashValue(DecompositionDeclName Key) { + assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey())); + return llvm::hash_combine_range(Key.begin(), Key.end()); + } + static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) { + if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey())) + return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey()); + if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey())) + return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey()); + return LHS.Bindings.size() == RHS.Bindings.size() && + std::equal(LHS.begin(), LHS.end(), RHS.begin()); + } +}; +} + +namespace { + +/// Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class ItaniumNumberingContext : public MangleNumberingContext { llvm::DenseMap<const Type *, unsigned> ManglingNumbers; llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers; llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers; + llvm::DenseMap<DecompositionDeclName, unsigned> + DecompsitionDeclManglingNumbers; public: unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { @@ -82,9 +135,15 @@ public: /// Variable decls are numbered by identifier. unsigned getManglingNumber(const VarDecl *VD, unsigned) override { + if (auto *DD = dyn_cast<DecompositionDecl>(VD)) { + DecompositionDeclName Name{DD->bindings()}; + return ++DecompsitionDeclManglingNumbers[Name]; + } + const IdentifierInfo *Identifier = VD->getIdentifier(); if (!Identifier) { - // VarDecl without an identifier represents an anonymous union declaration. + // VarDecl without an identifier represents an anonymous union + // declaration. Identifier = findAnonymousUnionVarDeclName(*VD); } return ++VarManglingNumbers[Identifier]; |