#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/iterator.h"
using namespace clang;
return nullptr;
}
+/// 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 {
+
/// \brief 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 {
/// Variable decls are numbered by identifier.
unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
+ if (auto *DD = dyn_cast<DecompositionDecl>(VD))
+ return ++DecompsitionDeclManglingNumbers[
+ DecompositionDeclName{DD->bindings()}];
+
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];