Fix a couple of mangling canonicalizer corner case bugs.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 13 Sep 2018 20:00:21 +0000 (20:00 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 13 Sep 2018 20:00:21 +0000 (20:00 +0000)
Summary:
The hash computed for an ArrayType was different when first constructed
versus when later profiled due to the constructor default argument, and
we were not tracking constructor / destructor variant as part of the
mangled name AST, leading to incorrect equivalences.

Reviewers: erik.pilkington

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D51463

llvm-svn: 342166

llvm/include/llvm/Demangle/ItaniumDemangle.h
llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp

index 81d8508..bc60bc3 100644 (file)
@@ -637,7 +637,7 @@ class ArrayType final : public Node {
   NodeOrString Dimension;
 
 public:
-  ArrayType(const Node *Base_, NodeOrString Dimension_ = NodeOrString())
+  ArrayType(const Node *Base_, NodeOrString Dimension_)
       : Node(KArrayType,
              /*RHSComponentCache=*/Cache::Yes,
              /*ArrayCache=*/Cache::Yes),
@@ -1360,12 +1360,14 @@ public:
 class CtorDtorName final : public Node {
   const Node *Basename;
   const bool IsDtor;
+  const int Variant;
 
 public:
-  CtorDtorName(const Node *Basename_, bool IsDtor_)
-      : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {}
+  CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
+      : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
+        Variant(Variant_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Basename, IsDtor); }
+  template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
 
   void printLeft(OutputStream &S) const override {
     if (IsDtor)
@@ -2800,20 +2802,22 @@ Node *Db<Alloc>::parseCtorDtorName(Node *&SoFar, NameState *State) {
     bool IsInherited = consumeIf('I');
     if (look() != '1' && look() != '2' && look() != '3' && look() != '5')
       return nullptr;
+    int Variant = look() - '0';
     ++First;
     if (State) State->CtorDtorConversion = true;
     if (IsInherited) {
       if (parseName(State) == nullptr)
         return nullptr;
     }
-    return make<CtorDtorName>(SoFar, false);
+    return make<CtorDtorName>(SoFar, false, Variant);
   }
 
   if (look() == 'D' &&
       (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) {
+    int Variant = look(1) - '0';
     First += 2;
     if (State) State->CtorDtorConversion = true;
-    return make<CtorDtorName>(SoFar, true);
+    return make<CtorDtorName>(SoFar, true, Variant);
   }
 
   return nullptr;
@@ -3292,32 +3296,25 @@ template<typename Alloc> Node *Db<Alloc>::parseArrayType() {
   if (!consumeIf('A'))
     return nullptr;
 
+  NodeOrString Dimension;
+
   if (std::isdigit(look())) {
-    StringView Dimension = parseNumber();
+    Dimension = parseNumber();
     if (!consumeIf('_'))
       return nullptr;
-    Node *Ty = parseType();
-    if (Ty == nullptr)
-      return nullptr;
-    return make<ArrayType>(Ty, Dimension);
-  }
-
-  if (!consumeIf('_')) {
+  } else if (!consumeIf('_')) {
     Node *DimExpr = parseExpr();
     if (DimExpr == nullptr)
       return nullptr;
     if (!consumeIf('_'))
       return nullptr;
-    Node *ElementType = parseType();
-    if (ElementType == nullptr)
-      return nullptr;
-    return make<ArrayType>(ElementType, DimExpr);
+    Dimension = DimExpr;
   }
 
   Node *Ty = parseType();
   if (Ty == nullptr)
     return nullptr;
-  return make<ArrayType>(Ty);
+  return make<ArrayType>(Ty, Dimension);
 }
 
 // <pointer-to-member-type> ::= M <class type> <member type>
index b8a42f6..2fd6bd8 100644 (file)
@@ -233,6 +233,23 @@ static std::vector<Testcase> getTestcases() {
       },
       {}
     },
+
+    // Check that ctor and dtor variants are considered distinct.
+    {
+      {},
+      {{"_ZN1XC1Ev"}, {"_ZN1XC2Ev"}, {"_ZN1XD1Ev"}, {"_ZN1XD2Ev"}}
+    },
+
+    // Ensure array types with and without bounds are handled properly.
+    {
+      {
+        {FragmentKind::Type, "A_i", "A1_f"},
+      },
+      {
+        {"_Z1fRA_i", "_Z1fRA_i", "_Z1fRA1_f"},
+        {"_Z1fRA1_i"}, {"_Z1fRA_f"},
+      }
+    },
   };
 }