PR37352: mangle numbering for decomposition declarations.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 7 May 2018 22:23:38 +0000 (22:23 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 7 May 2018 22:23:38 +0000 (22:23 +0000)
In order to match our mangling scheme, use a different set of numbers for
decomposition declarations, and consider all binding names when forming the
numbering. This does not yet affect any mangled names we produce, because
local decomposition declarations can't yet have linkage, but a C++ standard
proposal to change that is currently being processed.

llvm-svn: 331692

clang/lib/AST/ItaniumCXXABI.cpp
clang/test/SemaCXX/cxx1z-decomposition.cpp

index d6bc16b..abfec13 100644 (file)
@@ -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;
 }
 
+/// 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 {
@@ -82,9 +135,14 @@ public:
 
   /// 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];
index 7a42217..3c9b181 100644 (file)
@@ -76,4 +76,9 @@ template <class T> void dependent_foreach(T t) {
     a,b,c;
 }
 
+struct PR37352 {
+  int n;
+  void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}}
+};
+
 // FIXME: by-value array copies