OSDN Git Service

cp/:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 17 Mar 2009 23:31:18 +0000 (23:31 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 17 Mar 2009 23:31:18 +0000 (23:31 +0000)
        * decl.c (grokfndecl): Set DECL_CONTEXT on parms.
        (duplicate_decls): Adjust DECL_CONTEXT of newdecl's parms.
        * pt.c (check_explicit_specialization): Likewise.
        (tsubst_copy) [PARM_DECL]: Return a dummy parm if we don't have a
        local specialization.
        * tree.c (cp_tree_equal) [PARM_DECL]: Check type and index, not name.
        * decl2.c (parm_index): New fn.
        * semantics.c (finish_decltype_type): Don't use describable_type.
        * mangle.c (write_expression): Likewise.  Mangle ALIGNOF_EXPR.
        Give a sorry for unsupported codes rather than crash.  Mangle
        conversions with other than 1 operand.  New mangling for PARM_DECL.
        * operators.def (ALIGNOF_EXPR): Mangle as az.

        * include/demangle.h (enum demangle_component_type): Add
        DEMANGLE_COMPONENT_FUNCTION_PARAM.
        * libiberty/cp-demangle.c (d_make_function_param): new fn.
        (cplus_demangle_mangled_name): Work around abi v2 bug.
        (d_expr_primary): Likewise.
        (cplus_demangle_operators): Add alignof ops.
        (d_expression): Handle function parameters and conversions
        with other than 1 operand.
        (d_print_comp): Handle function parameters.  Fix bug with
        function used in type of function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@144924 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/mangle.c
gcc/cp/operators.def
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/auto12.C
gcc/testsuite/g++.dg/cpp0x/auto6.C
include/ChangeLog
include/demangle.h
libiberty/ChangeLog
libiberty/cp-demangle.c
libiberty/testsuite/demangle-expected

index a925c5d..1f5dd9d 100644 (file)
@@ -1,3 +1,18 @@
+2009-03-17  Jason Merrill  <jason@redhat.com>
+
+       * decl.c (grokfndecl): Set DECL_CONTEXT on parms.
+       (duplicate_decls): Adjust DECL_CONTEXT of newdecl's parms.
+       * pt.c (check_explicit_specialization): Likewise.
+       (tsubst_copy) [PARM_DECL]: Return a dummy parm if we don't have a
+       local specialization.
+       * tree.c (cp_tree_equal) [PARM_DECL]: Check type and index, not name.
+       * decl2.c (parm_index): New fn.
+       * semantics.c (finish_decltype_type): Don't use describable_type.
+       * mangle.c (write_expression): Likewise.  Mangle ALIGNOF_EXPR.
+       Give a sorry for unsupported codes rather than crash.  Mangle
+       conversions with other than 1 operand.  New mangling for PARM_DECL.
+       * operators.def (ALIGNOF_EXPR): Mangle as "az".
+
 2009-03-17  Jing Yu  <jingyu@google.com>
 
        PR middle-end/39378
index 0b1d7c6..1745ede 100644 (file)
@@ -4436,6 +4436,7 @@ extern bool decl_needed_p                 (tree);
 extern void note_vague_linkage_fn              (tree);
 extern tree build_artificial_parm              (tree, tree);
 extern bool possibly_inlined_p                 (tree);
+extern int parm_index                           (tree);
 
 /* in error.c */
 extern void init_error                         (void);
index 03e65d0..9a6ab02 100644 (file)
@@ -1684,8 +1684,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
            = DECL_SOURCE_LOCATION (newdecl);
          DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
          if (DECL_FUNCTION_TEMPLATE_P (newdecl))
-           DECL_ARGUMENTS (old_result)
-             = DECL_ARGUMENTS (new_result);
+           {
+             tree parm;
+             DECL_ARGUMENTS (old_result)
+               = DECL_ARGUMENTS (new_result);
+             for (parm = DECL_ARGUMENTS (old_result); parm;
+                  parm = TREE_CHAIN (parm))
+               DECL_CONTEXT (parm) = old_result;
+           }
        }
 
       return olddecl;
@@ -1918,6 +1924,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
+      tree parm;
+
       if (DECL_TEMPLATE_INSTANTIATION (olddecl)
          && !DECL_TEMPLATE_INSTANTIATION (newdecl))
        {
@@ -1974,6 +1982,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       /* Preserve abstractness on cloned [cd]tors.  */
       DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
 
+      /* Update newdecl's parms to point at olddecl.  */
+      for (parm = DECL_ARGUMENTS (newdecl); parm;
+          parm = TREE_CHAIN (parm))
+       DECL_CONTEXT (parm) = olddecl;
+
       if (! types_match)
        {
          SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
@@ -2006,7 +2019,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
            }
 
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-         /* Don't clear out the arguments if we're redefining a function.  */
+         /* Don't clear out the arguments if we're just redeclaring a
+            function.  */
          if (DECL_ARGUMENTS (olddecl))
            DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
        }
@@ -6555,6 +6569,8 @@ grokfndecl (tree ctype,
       parms = parm;
     }
   DECL_ARGUMENTS (decl) = parms;
+  for (t = parms; t; t = TREE_CHAIN (t))
+    DECL_CONTEXT (t) = decl;
   /* Propagate volatile out from type to decl.  */
   if (TYPE_VOLATILE (type))
     TREE_THIS_VOLATILE (decl) = 1;
index d570150..deba8b4 100644 (file)
@@ -3907,4 +3907,27 @@ mark_used (tree decl)
   processing_template_decl = saved_processing_template_decl;
 }
 
+/* Given function PARM_DECL PARM, return its index in the function's list
+   of parameters, beginning with 1.  */
+
+int
+parm_index (tree parm)
+{
+  int index;
+  tree arg;
+
+  for (index = 1, arg = DECL_ARGUMENTS (DECL_CONTEXT (parm));
+       arg;
+       ++index, arg = TREE_CHAIN (arg))
+    {
+      if (DECL_NAME (parm) == DECL_NAME (arg))
+       break;
+      if (DECL_ARTIFICIAL (arg))
+       --index;
+    }
+
+  gcc_assert (arg);
+  return index;
+}
+
 #include "gt-cp-decl2.h"
index c72747c..eabab7f 100644 (file)
@@ -2143,27 +2143,6 @@ write_expression (tree expr)
 {
   enum tree_code code = TREE_CODE (expr);
 
-  /* Inside decltype we can simplify some expressions, since we're only
-     interested in the type.  */
-  if (skip_evaluation)
-    {
-      tree type = describable_type (expr);
-      if (type == NULL_TREE)
-       ;
-      else if (TREE_CODE (type) == REFERENCE_TYPE)
-       {
-         write_string ("sT");
-         write_type (TREE_TYPE (type));
-         return;
-       }
-      else
-       {
-         write_string ("sR");
-         write_type (type);
-         return;
-       }
-    }
-
   /* Skip NOP_EXPRs.  They can occur when (say) a pointer argument
      is converted (via qualification conversions) to another
      type.  */
@@ -2210,10 +2189,12 @@ write_expression (tree expr)
     write_template_arg_literal (expr);
   else if (code == PARM_DECL)
     {
-      /* A function parameter used under decltype in a late-specified
-        return type.  Represented with a type placeholder.  */
-      write_string ("sT");
-      write_type (non_reference (TREE_TYPE (expr)));
+      /* A function parameter used in a late-specified return type.  */
+      int index = parm_index (expr);
+      write_string ("fp");
+      if (index > 1)
+       write_unsigned_number (index - 2);
+      write_char ('_');
     }
   else if (DECL_P (expr))
     {
@@ -2231,6 +2212,12 @@ write_expression (tree expr)
       write_string ("st");
       write_type (TREE_OPERAND (expr, 0));
     }
+  else if (TREE_CODE (expr) == ALIGNOF_EXPR
+          && TYPE_P (TREE_OPERAND (expr, 0)))
+    {
+      write_string ("at");
+      write_type (TREE_OPERAND (expr, 0));
+    }
   else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
     {
       tree scope = TREE_OPERAND (expr, 0);
@@ -2298,9 +2285,16 @@ write_expression (tree expr)
            write_template_args (template_args);
        }
     }
+  else if (TREE_CODE (expr) == INDIRECT_REF
+          && TREE_TYPE (TREE_OPERAND (expr, 0))
+          && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
+    {
+      write_expression (TREE_OPERAND (expr, 0));
+    }
   else
     {
       int i;
+      const char *name;
 
       /* When we bind a variable or function to a non-type template
         argument with reference type, we create an ADDR_EXPR to show
@@ -2338,7 +2332,14 @@ write_expression (tree expr)
        }
 
       /* If it wasn't any of those, recursively expand the expression.  */
-      write_string (operator_name_info[(int) code].mangled_name);
+      name = operator_name_info[(int) code].mangled_name;
+      if (name == NULL)
+       {
+         sorry ("mangling %C", code);
+         return;
+       }
+      else
+       write_string (name);    
 
       switch (code)
        {
@@ -2351,23 +2352,29 @@ write_expression (tree expr)
 
        case CAST_EXPR:
          write_type (TREE_TYPE (expr));
-         /* There is no way to mangle a zero-operand cast like
-            "T()".  */
-         if (!TREE_OPERAND (expr, 0))
-           sorry ("zero-operand casts cannot be mangled due to a defect "
-                  "in the C++ ABI");
-         else if (list_length (TREE_OPERAND (expr, 0)) > 1)
-           sorry ("mangling function-style cast with more than one argument");
-         else
+         if (list_length (TREE_OPERAND (expr, 0)) == 1)          
            write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
+         else
+           {
+             tree args = TREE_OPERAND (expr, 0);
+             write_char ('_');
+             for (; args; args = TREE_CHAIN (args))
+               write_expression (TREE_VALUE (args));
+             write_char ('E');
+           }
          break;
 
+         /* FIXME these should have a distinct mangling.  */
        case STATIC_CAST_EXPR:
        case CONST_CAST_EXPR:
          write_type (TREE_TYPE (expr));
          write_expression (TREE_OPERAND (expr, 0));
          break;
 
+       case NEW_EXPR:
+         sorry ("mangling new-expression");
+         break;
+
        /* Handle pointers-to-members specially.  */
        case SCOPE_REF:
          write_type (TREE_OPERAND (expr, 0));
index 698f0de..20d811b 100644 (file)
@@ -94,7 +94,7 @@ DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", 1)
 DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", 1)
 DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", 1)
 /* These are extensions.  */
-DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "v17alignof", 1)
+DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", 1)
 DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 1)
 DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1)
 
index 8ae4ed5..62a7b88 100644 (file)
@@ -2217,17 +2217,21 @@ check_explicit_specialization (tree declarator,
             the specialization of it.  */
          if (tsk == tsk_template)
            {
+             tree result = DECL_TEMPLATE_RESULT (tmpl);
              SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
-             DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
+             DECL_INITIAL (result) = NULL_TREE;
              if (have_def)
                {
+                 tree parm;
                  DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
-                 DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl))
+                 DECL_SOURCE_LOCATION (result)
                    = DECL_SOURCE_LOCATION (decl);
                  /* We want to use the argument list specified in the
                     definition, not in the original declaration.  */
-                 DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl))
-                   = DECL_ARGUMENTS (decl);
+                 DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
+                 for (parm = DECL_ARGUMENTS (result); parm;
+                      parm = TREE_CHAIN (parm))
+                   DECL_CONTEXT (parm) = result;
                }
              return tmpl;
            }
@@ -9898,16 +9902,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       if (r == NULL)
        {
          /* This can happen for a parameter name used later in a function
-            declaration (such as in a late-specified return type).
-            Replace it with an arbitrary expression with the same type
-            (*(T*)0).  This should only occur in an unevaluated context
-            (i.e. decltype).  */
-         gcc_assert (skip_evaluation);
-         r = non_reference (TREE_TYPE (t));
-         r = tsubst (r, args, complain, in_decl);
-         r = build_pointer_type (r);
-         r = build_c_cast (r, null_node);
-         return cp_build_indirect_ref (r, NULL, tf_warning_or_error);
+            declaration (such as in a late-specified return type).  Just
+            make a dummy decl, since it's only used for its type.  */
+         gcc_assert (skip_evaluation);   
+         r = tsubst_decl (t, args, complain);
+         /* Give it the template pattern as its context; its true context
+            hasn't been instantiated yet and this is good enough for
+            mangling.  */
+         DECL_CONTEXT (r) = DECL_CONTEXT (t);
        }
       
       if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
index 82a6797..c728970 100644 (file)
@@ -4585,8 +4585,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
              break;
            }
        }
-      else
-       type = describable_type (expr);
 
       if (type && !type_uses_auto (type))
        return type;
index 82f3b89..2287f11 100644 (file)
@@ -1881,9 +1881,8 @@ cp_tree_equal (tree t1, tree t2)
     case PARM_DECL:
       /* For comparing uses of parameters in late-specified return types
         with an out-of-class definition of the function.  */
-      if ((!DECL_CONTEXT (t1) || !DECL_CONTEXT (t2))
-         && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
-         && DECL_NAME (t1) == DECL_NAME (t2))
+      if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+         && parm_index (t1) == parm_index (t2))
        return true;
       else
        return false;
index 2352594..b59350c 100644 (file)
@@ -1,3 +1,7 @@
+2009-03-17  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/auto6.C, auto12.C: Update mangling.
+
 2009-03-17  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/39475
index 437088d..45ceedf 100644 (file)
@@ -37,16 +37,16 @@ auto A<T>::f(U u) -> decltype (u + i)
 
 int main()
 {
-  // { dg-final { scan-assembler  "_ZN1AIiE1fIiEEDTplsTT_sTiES2_" } }
+  // { dg-final { scan-assembler  "_ZN1AIiE1fIiEEDTplfp_L_ZNS0_1iEEET_" } }
   A<int>().f(1);
-  // { dg-final { scan-assembler  "_ZN1AIiE2frIiEEDTplsTT_sTiES2_" } }
+  // { dg-final { scan-assembler  "_ZN1AIiE2frIiEEDTplfp_L_ZNS0_2irEEET_" } }
   A<int>().fr(1);
-  // { dg-final { scan-assembler  "_ZN1AIiE3frrIiEEDTplsTT_sTiES2_" } }
+  // { dg-final { scan-assembler  "_ZN1AIiE3frrIiEEDTplfp_L_ZNS0_3irrEEET_" } }
   A<int>().frr(1);
-  // { dg-final { scan-assembler  "_ZN1AIiE1gIiEEDTplsTT_sR.ES2_" } }
+  // { dg-final { scan-assembler  "_ZN1AIiE1gIiEEDTplfp_szL_ZNS0_1iEEET_" } }
   A<int>().g(1);
-  // { dg-final { scan-assembler  "_ZN1AIiE1hIiEEDTplsTT_sr1BIS2_E1iES2_" } }
+  // { dg-final { scan-assembler  "_ZN1AIiE1hIiEEDTplfp_sr1BIT_E1iES3_" } }
   A<int>().h(1);
-  // { dg-final { scan-assembler  "_ZN1AIiE1jIiEEDTplsTT_sRiES2_" } }
+  // { dg-final { scan-assembler  "_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_" } }
   A<int>().j(1);
 }
index 7d659c7..dfd6a20 100644 (file)
@@ -95,21 +95,21 @@ A<int> a, *p;
 
 int main()
 {
-  // { dg-final { scan-assembler  "_Z3addIidEDTplsTT_sTT0_ES0_S1_" } }
+  // { dg-final { scan-assembler  "_Z3addIidEDTplfp_fp0_ET_T0_" } }
   auto i = add(1, 2.0);
-  // { dg-final { scan-assembler "_Z4add4IidEDTplsTT_sTT0_ES0_S1_" } }
+  // { dg-final { scan-assembler "_Z4add4IidEDTpldecvPT_Li0EdecvPT0_Li0EES0_S2_" } }
   auto i4 = add4(1, 2.0);
-  // { dg-final { scan-assembler "_Z4add2IidEDTplsRT_sRT0_ES0_S1_" } }
+  // { dg-final { scan-assembler "_Z4add2IidEDTplcvT__EcvT0__EES0_S1_" } }
   auto i2 = add2(1, 2.0);
-  // { dg-final { scan-assembler "_Z4add3IidEDTclL_Z2agEsTT_sTT0_EES0_S1_" } }
+  // { dg-final { scan-assembler "_Z4add3IidEDTclL_Z2agEfp_fp0_EET_T0_" } }
   auto i3 = add3(1, 2.0);
-  // { dg-final { scan-assembler "_Z1fI1AIiEEDTclptsTPT_1fEES3_" } }
+  // { dg-final { scan-assembler "_Z1fI1AIiEEDTclptfp_1fEEPT_" } }
   f(p);
-  // { dg-final { scan-assembler "_Z1gI1AIiEEDTcldtsTT_1fEES2_" } }
+  // { dg-final { scan-assembler "_Z1gI1AIiEEDTcldtfp_1fEET_" } }
   g(a);
-  // { dg-final { scan-assembler "_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_" } }
+  // { dg-final { scan-assembler "_Z1hI1AIiEdEDTcldtfp_1gIT0_EEET_S2_" } }
   h(a,1.0);
-  // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtsTT_srNT0_1BIT1_EE3MEMES4_S5_S7_" } }
+  // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtfp_srNT0_1BIT1_EE3MEMET_S4_S6_" } }
   k( C(), A<int>(), D() );
   // { dg-final { scan-assembler "_Z1lIiET_S0_" } }
   l(1);
index a07e075..64dd0d9 100644 (file)
@@ -1,3 +1,8 @@
+2009-03-17  Jason Merrill  <jason@redhat.com>
+
+       * demangle.h (enum demangle_component_type): Add
+       DEMANGLE_COMPONENT_FUNCTION_PARAM.
+
 2008-12-10  Jason Merrill  <jason@redhat.com>
 
        * demangle.h (enum demangle_component_type): Add 
index 28c69f5..eb39c7c 100644 (file)
@@ -221,6 +221,8 @@ enum demangle_component_type
   /* A template parameter.  This holds a number, which is the template
      parameter index.  */
   DEMANGLE_COMPONENT_TEMPLATE_PARAM,
+  /* A function parameter.  This holds a number, which is the index.  */
+  DEMANGLE_COMPONENT_FUNCTION_PARAM,
   /* A constructor.  This holds a name and the kind of
      constructor.  */
   DEMANGLE_COMPONENT_CTOR,
@@ -466,10 +468,10 @@ struct demangle_component
       int len;
     } s_string;
 
-    /* For DEMANGLE_COMPONENT_TEMPLATE_PARAM.  */
+    /* For DEMANGLE_COMPONENT_*_PARAM.  */
     struct
     {
-      /* Template parameter index.  */
+      /* Parameter index.  */
       long number;
     } s_number;
 
index db7d287..00aa57a 100644 (file)
@@ -1,3 +1,15 @@
+2009-03-17  Jason Merrill  <jason@redhat.com>
+
+       * cp-demangle.c (d_make_function_param): new fn.
+       (cplus_demangle_mangled_name): Work around abi v2 bug.
+       (d_expr_primary): Likewise.
+       (cplus_demangle_operators): Add alignof ops.
+       (d_expression): Handle function parameters and conversions
+       with other than 1 operand.
+       (d_print_comp): Handle function parameters.  Fix bug with
+       function used in type of function.
+       * testsuite/demangle-expected: Upate tests.
+
 2009-02-21  Mark Mitchell  <mark@codesourcery.com>
 
        * make-temp-file.c (<windows.h>): Include on Windows.
index 0b4e05c..e6d3d5e 100644 (file)
@@ -964,6 +964,22 @@ d_make_template_param (struct d_info *di, long i)
   return p;
 }
 
+/* Add a new function parameter.  */
+
+static struct demangle_component *
+d_make_function_param (struct d_info *di, long i)
+{
+  struct demangle_component *p;
+
+  p = d_make_empty (di);
+  if (p != NULL)
+    {
+      p->type = DEMANGLE_COMPONENT_FUNCTION_PARAM;
+      p->u.s_number.number = i;
+    }
+  return p;
+}
+
 /* Add a new standard substitution component.  */
 
 static struct demangle_component *
@@ -989,7 +1005,11 @@ CP_STATIC_IF_GLIBCPP_V3
 struct demangle_component *
 cplus_demangle_mangled_name (struct d_info *di, int top_level)
 {
-  if (! d_check_char (di, '_'))
+  if (! d_check_char (di, '_')
+      /* Allow missing _ if not at toplevel to work around a
+        bug in G++ abi-version=2 mangling; see the comment in
+        write_template_arg.  */
+      && top_level)
     return NULL;
   if (! d_check_char (di, 'Z'))
     return NULL;
@@ -1481,6 +1501,8 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "rs", NL (">>"),        2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
+  { "at", NL ("alignof "),   1 },
+  { "az", NL ("alignof "),   1 },
   { NULL, NULL, 0,          0 }
 };
 
@@ -2564,12 +2586,25 @@ d_expression (struct d_info *di)
                            d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
                                         d_template_args (di)));
     }
-  else if (peek == 's'
-          && (d_peek_next_char (di) == 'T' || d_peek_next_char (di) == 'R'))
+  else if (peek == 'f' && d_peek_next_char (di) == 'p')
     {
-      /* Just demangle a parameter placeholder as its type.  */
+      /* Function parameter used in a late-specified return type.  */
+      int index;
       d_advance (di, 2);
-      return cplus_demangle_type (di);
+      if (d_peek_char (di) == '_')
+       index = 1;
+      else
+       {
+         index = d_number (di);
+         if (index < 0)
+           return NULL;
+         index += 2;
+       }
+
+      if (! d_check_char (di, '_'))
+       return NULL;
+
+      return d_make_function_param (di, index);
     }
   else if (IS_DIGIT (peek))
     {
@@ -2619,8 +2654,16 @@ d_expression (struct d_info *di)
       switch (args)
        {
        case 1:
-         return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
-                             d_expression (di));
+         {
+           struct demangle_component *operand;
+           if (op->type == DEMANGLE_COMPONENT_CAST
+               && d_check_char (di, '_'))
+             operand = d_exprlist (di);
+           else
+             operand = d_expression (di);
+           return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+                               operand);
+         }
        case 2:
          {
            struct demangle_component *left;
@@ -2671,7 +2714,9 @@ d_expr_primary (struct d_info *di)
 
   if (! d_check_char (di, 'L'))
     return NULL;
-  if (d_peek_char (di) == '_')
+  if (d_peek_char (di) == '_'
+      /* Workaround for G++ bug; see comment in write_template_arg.  */
+      || d_peek_char (di) == 'Z')
     ret = cplus_demangle_mangled_name (di, 0);
   else
     {
@@ -3293,6 +3338,7 @@ d_print_comp (struct d_print_info *dpi,
           the right place for the type.  We also have to pass down
           any CV-qualifiers, which apply to the this parameter.  */
        hold_modifiers = dpi->modifiers;
+       dpi->modifiers = 0;
        i = 0;
        typed_name = d_left (dc);
        while (typed_name != NULL)
@@ -3981,6 +4027,15 @@ d_print_comp (struct d_print_info *dpi,
       }
       return;
 
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+      {
+       char buf[25];
+       d_append_string (dpi, "parm#");
+       sprintf(buf,"%ld", dc->u.s_number.number);
+       d_append_string (dpi, buf);
+       return;
+      }
+
     default:
       d_print_error (dpi);
       return;
index d9efbc0..cded6b5 100644 (file)
@@ -3723,7 +3723,7 @@ foo<int (*) [3]>
 # This used to crash the demangler--PR 16240
 --format=gnu-v3 --no-params
 _ZN13PatternDriver23StringScalarDeleteValueC1ERKNS_25ConflateStringScalarValueERKNS_25AbstractStringScalarValueERKNS_12TemplateEnumINS_12pdcomplementELZNS_16complement_namesEELZNS_14COMPLEMENTENUMEEEE
-_ZN13PatternDriver23StringScalarDeleteValueC1ERKNS_25ConflateStringScalarValueERKNS_25AbstractStringScalarValueERKNS_12TemplateEnumINS_12pdcomplementELZNS_16complement_namesEELZNS_14COMPLEMENTENUMEEEE
+PatternDriver::StringScalarDeleteValue::StringScalarDeleteValue(PatternDriver::ConflateStringScalarValue const&, PatternDriver::AbstractStringScalarValue const&, PatternDriver::TemplateEnum<PatternDriver::pdcomplement, PatternDriver::complement_names, PatternDriver::COMPLEMENTENUM> const&)
 PatternDriver::StringScalarDeleteValue::StringScalarDeleteValue
 #
 # This used to cause the demangler to walk into undefined memory--PR 22268
@@ -3884,12 +3884,12 @@ _ZGr32_java$Sutil$Siso4217$_properties
 java resource java/util/iso4217.properties
 # decltype/param placeholder test
 --format=gnu-v3
-_Z3addIidEDTplsTT_sTT0_ES0_S1_
-decltype ((int)+(double)) add<int, double>(int, double)
+_Z3addIidEDTplfp_fp0_ET_T0_
+decltype ((parm#1)+(parm#2)) add<int, double>(int, double)
 # decltype/fn call test
 --format=gnu-v3
-_Z4add3IidEDTclL_Z1gEsTT_sTT0_EES0_S1_
-decltype (g(int, double)) add3<int, double>(int, double)
+_Z4add3IidEDTclL_Z1gEfp_fp0_EET_T0_
+decltype (g(parm#1, parm#2)) add3<int, double>(int, double)
 # new (2008) built in types test
 --format=gnu-v3
 _Z1fDfDdDeDhDsDi
@@ -3900,5 +3900,9 @@ _Z1fIIPiPfPdEEvDpT_
 void f<int*, float*, double*>(int*, float*, double*)
 # '.' test
 --format=gnu-v3
-_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_
-decltype (((A<int>).(g<double>))()) h<A<int>, double>(A<int>, double)
+_Z1hI1AIiEdEDTcldtfp_1gIT0_EEET_S2_
+decltype (((parm#1).(g<double>))()) h<A<int>, double>(A<int>, double)
+# test for typed function in decltype
+--format=gnu-v3
+_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_
+decltype ((parm#1)+((x())())) A<int>::j<int>(int)