]> granicus.if.org Git - clang/commitdiff
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331692 91177308-0d34-0410-b5e6-96231b3b80d8

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

index d6bc16b6350fc1b6050c73acfdeffba8875689cf..abfec13a995b2cab995185790060087e4229a8cb 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 7a4221784ad359986e9e7efe5e8c4f593cc7e2f3..3c9b181f1c8f0e6de2b6bf28b63f9d4860f707bf 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