[demangler] Simplify the AST for function types, NFC.

git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@325092 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index c962203..82b9de0 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -176,8 +176,6 @@
     KArrayType,
     KFunctionType,
     KFunctionEncoding,
-    KFunctionQualType,
-    KFunctionRefQualType,
     KLiteralOperator,
     KSpecialName,
     KCtorVtableSpecialName,
@@ -357,6 +355,12 @@
   }
 };
 
+enum FunctionRefQual : unsigned char {
+  FrefQualNone,
+  FrefQualLValue,
+  FrefQualRValue,
+};
+
 enum Qualifiers {
   QualNone = 0,
   QualConst = 0x1,
@@ -714,13 +718,16 @@
 class FunctionType final : public Node {
   Node *Ret;
   NodeArray Params;
+  Qualifiers CVQuals;
+  FunctionRefQual RefQual;
 
 public:
-  FunctionType(Node *Ret_, NodeArray Params_)
+  FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
+               FunctionRefQual RefQual_)
       : Node(KFunctionType, Ret_->ParameterPackSize,
              /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
              /*FunctionCache=*/Cache::Yes),
-        Ret(Ret_), Params(Params_) {
+        Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_) {
     for (Node *P : Params)
       ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
   }
@@ -745,6 +752,18 @@
     Params.printWithComma(S);
     S += ")";
     Ret->printRight(S);
+
+    if (CVQuals & QualConst)
+      S += " const";
+    if (CVQuals & QualVolatile)
+      S += " volatile";
+    if (CVQuals & QualRestrict)
+      S += " restrict";
+
+    if (RefQual == FrefQualLValue)
+      S += " &";
+    else if (RefQual == FrefQualRValue)
+      S += " &&";
   }
 };
 
@@ -752,13 +771,17 @@
   const Node *Ret;
   const Node *Name;
   NodeArray Params;
+  Qualifiers CVQuals;
+  FunctionRefQual RefQual;
 
 public:
-  FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_)
+  FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_,
+                   Qualifiers CVQuals_, FunctionRefQual RefQual_)
       : Node(KFunctionEncoding, NoParameterPack,
              /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
              /*FunctionCache=*/Cache::Yes),
-        Ret(Ret_), Name(Name_), Params(Params_) {
+        Ret(Ret_), Name(Name_), Params(Params_), CVQuals(CVQuals_),
+        RefQual(RefQual_) {
     for (Node *P : Params)
       ParameterPackSize = std::min(ParameterPackSize, P->ParameterPackSize);
     if (Ret)
@@ -785,66 +808,19 @@
     S += ")";
     if (Ret)
       Ret->printRight(S);
-  }
-};
 
-enum FunctionRefQual : unsigned char {
-  FrefQualNone,
-  FrefQualLValue,
-  FrefQualRValue,
-};
+    if (CVQuals & QualConst)
+      S += " const";
+    if (CVQuals & QualVolatile)
+      S += " volatile";
+    if (CVQuals & QualRestrict)
+      S += " restrict";
 
-class FunctionRefQualType : public Node {
-  Node *Fn;
-  FunctionRefQual Quals;
-
-  friend class FunctionQualType;
-
-public:
-  FunctionRefQualType(Node *Fn_, FunctionRefQual Quals_)
-      : Node(KFunctionRefQualType, Fn_->ParameterPackSize,
-             /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
-             /*FunctionCache=*/Cache::Yes),
-        Fn(Fn_), Quals(Quals_) {}
-
-  bool hasFunctionSlow(OutputStream &) const override { return true; }
-  bool hasRHSComponentSlow(OutputStream &) const override { return true; }
-
-  void printQuals(OutputStream &S) const {
-    if (Quals == FrefQualLValue)
+    if (RefQual == FrefQualLValue)
       S += " &";
-    else
+    else if (RefQual == FrefQualRValue)
       S += " &&";
   }
-
-  void printLeft(OutputStream &S) const override { Fn->printLeft(S); }
-
-  void printRight(OutputStream &S) const override {
-    Fn->printRight(S);
-    printQuals(S);
-  }
-};
-
-class FunctionQualType final : public QualType {
-public:
-  FunctionQualType(Node *Child_, Qualifiers Quals_)
-      : QualType(Child_, Quals_) {
-    K = KFunctionQualType;
-  }
-
-  void printLeft(OutputStream &S) const override { Child->printLeft(S); }
-
-  void printRight(OutputStream &S) const override {
-    if (Child->getKind() == KFunctionRefQualType) {
-      auto *RefQuals = static_cast<const FunctionRefQualType *>(Child);
-      RefQuals->Fn->printRight(S);
-      printQuals(S);
-      RefQuals->printQuals(S);
-    } else {
-      Child->printRight(S);
-      printQuals(S);
-    }
-  }
 };
 
 class LiteralOperator : public Node {
@@ -2077,7 +2053,7 @@
   Node *parseArrayType();
   Node *parsePointerToMemberType();
   Node *parseClassEnumType();
-  Node *parseQualifiedType(bool &AppliesToFunction);
+  Node *parseQualifiedType();
 
   Node *parseNestedName();
   Node *parseCtorDtorName(Node *&SoFar);
@@ -2384,11 +2360,16 @@
   return R;
 }
 
-// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
+// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
 //
-//  <ref-qualifier> ::= R                   # & ref-qualifier
-//  <ref-qualifier> ::= O                   # && ref-qualifier
+// <exception-spec> ::= Do                # non-throwing exception-specification (e.g., noexcept, throw())
+//                  ::= DO <expression> E # computed (instantiation-dependent) noexcept
+//                  ::= Dw <type>+ E      # dynamic exception specification with instantiation-dependent types
+//
+// <ref-qualifier> ::= R                   # & ref-qualifier
+// <ref-qualifier> ::= O                   # && ref-qualifier
 Node *Db::parseFunctionType() {
+  Qualifiers CVQuals = parseCVQualifiers();
   if (!consumeIf('F'))
     return nullptr;
   consumeIf('Y'); // extern "C"
@@ -2418,10 +2399,7 @@
   }
 
   NodeArray Params = popTrailingNodeArray(ParamsBegin);
-  Node *Fn = make<FunctionType>(ReturnType, Params);
-  if (ReferenceQualifier != FrefQualNone)
-    Fn = make<FunctionRefQualType>(Fn, ReferenceQualifier);
-  return Fn;
+  return make<FunctionType>(ReturnType, Params, CVQuals, ReferenceQualifier);
 }
 
 // extension:
@@ -2549,7 +2527,7 @@
 // <qualified-type>     ::= <qualifiers> <type>
 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
 // <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
-Node *Db::parseQualifiedType(bool &AppliesToFunction) {
+Node *Db::parseQualifiedType() {
   if (consumeIf('U')) {
     StringView Qual = parseBareSourceName();
     if (Qual.empty())
@@ -2568,27 +2546,24 @@
       }
       if (Proto.empty())
         return nullptr;
-      Node *Child = parseQualifiedType(AppliesToFunction);
+      Node *Child = parseQualifiedType();
       if (Child == nullptr)
         return nullptr;
       return make<ObjCProtoName>(Child, Proto);
     }
 
-    Node *Child = parseQualifiedType(AppliesToFunction);
+    Node *Child = parseQualifiedType();
     if (Child == nullptr)
       return nullptr;
     return make<VendorExtQualType>(Child, Qual);
   }
 
   Qualifiers Quals = parseCVQualifiers();
-  AppliesToFunction = look() == 'F';
   Node *Ty = parseType();
   if (Ty == nullptr)
     return nullptr;
-  if (Quals != QualNone) {
-    return AppliesToFunction ?
-      make<FunctionQualType>(Ty, Quals) : make<QualType>(Ty, Quals);
-  }
+  if (Quals != QualNone)
+    Ty = make<QualType>(Ty, Quals);
   return Ty;
 }
 
@@ -2619,16 +2594,19 @@
   //             ::= <qualified-type>
   case 'r':
   case 'V':
-  case 'K':
+  case 'K': {
+    unsigned AfterQuals = 0;
+    if (look(AfterQuals) == 'r') ++AfterQuals;
+    if (look(AfterQuals) == 'V') ++AfterQuals;
+    if (look(AfterQuals) == 'K') ++AfterQuals;
+    if (look(AfterQuals) == 'F') {
+      Result = parseFunctionType();
+      break;
+    }
+    _LIBCPP_FALLTHROUGH();
+  }
   case 'U': {
-    bool AppliesToFunction = false;
-    Result = parseQualifiedType(AppliesToFunction);
-
-    // Itanium C++ ABI 5.1.5.3:
-    //   For the purposes of substitution, the CV-qualifiers and ref-qualifier
-    //   of a function type are an indivisible part of the type.
-    if (AppliesToFunction)
-      return Result;
+    Result = parseQualifiedType();
     break;
   }
   // <builtin-type> ::= v    # void
@@ -5506,7 +5484,7 @@
                         Node* name = db.Names.back();
                         db.Names.pop_back();
                         result = db.make<FunctionEncoding>(
-                            return_type, name, NodeArray());
+                            return_type, name, NodeArray(), cv, ref);
                     }
                     else
                     {
@@ -5527,12 +5505,8 @@
                         Node* name = db.Names.back();
                         db.Names.pop_back();
                         result = db.make<FunctionEncoding>(
-                            return_type, name, params);
+                            return_type, name, params, cv, ref);
                     }
-                    if (ref != FrefQualNone)
-                        result = db.make<FunctionRefQualType>(result, ref);
-                    if (cv != QualNone)
-                        result = db.make<FunctionQualType>(result, cv);
                     db.Names.push_back(result);
                     first = t;
                 }