]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/37302 (function parameters are declared too late)
authorJason Merrill <jason@redhat.com>
Mon, 8 Sep 2008 20:52:44 +0000 (16:52 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 8 Sep 2008 20:52:44 +0000 (16:52 -0400)
        PR c++/37302
        * parser.c (cp_parser_parameter_declaration_list): Process the
        PARM_DECLs as we go and push them.  Return a TREE_LIST.
        (cp_parser_parameter_declaration_clause): Return a TREE_LIST.
        (cp_parser_direct_declarator): Create a binding level and
        suppress deprecated warnings in the parameter list.
        (make_call_declarator): PARMS is now a tree.
        * cp-tree.h (struct cp_declarator): Function parms are now a tree.
        * decl.h (enum deprecated_states, deprecated_state): Move here.
        * decl.c: From here.
        (type_is_deprecated): New fn.
        (grokparms): PARMLIST is a tree now.  Warn about parms that
        use deprecated types.
        * mangle.c (write_expression): Handle PARM_DECL, CALL_EXPR and
        0-operand cast.
        * pt.c (tsubst) [DECLTYPE_TYPE]: Set skip_evaluation.
        (tsubst_copy) [PARM_DECL]: Handle a PARM_DECL used outside of a
        function.
        * name-lookup.c (pushtag): Look through function parameter scopes.
        (pushdecl_maybe_friend): Don't set DECL_CONTEXT on a PARM_DECL
        when we're parsing a function declarator.

From-SVN: r140120

18 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl.h
gcc/cp/mangle.c
gcc/cp/name-lookup.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/auto2.C
gcc/testsuite/g++.dg/cpp0x/auto3.C
gcc/testsuite/g++.dg/cpp0x/auto6.C
gcc/testsuite/g++.dg/other/error15.C
gcc/testsuite/g++.dg/other/error6.C
gcc/testsuite/g++.dg/other/pr28114.C
gcc/testsuite/g++.dg/parse/error3.C
gcc/testsuite/g++.old-deja/g++.jason/rfg16.C
gcc/testsuite/g++.old-deja/g++.oliva/template1.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp29.C

index cb5c31402e8ffd67120efd12d086240752501962..cd5b52cbb8abc093f2ed5576719ccbb3c83ddc83 100644 (file)
@@ -1,3 +1,27 @@
+2008-09-06  Jason Merrill  <jason@redhat.com>
+
+       PR c++/37302
+       * parser.c (cp_parser_parameter_declaration_list): Process the
+       PARM_DECLs as we go and push them.  Return a TREE_LIST.
+       (cp_parser_parameter_declaration_clause): Return a TREE_LIST.
+       (cp_parser_direct_declarator): Create a binding level and
+       suppress deprecated warnings in the parameter list.
+       (make_call_declarator): PARMS is now a tree.
+       * cp-tree.h (struct cp_declarator): Function parms are now a tree.
+       * decl.h (enum deprecated_states, deprecated_state): Move here.
+       * decl.c: From here.
+       (type_is_deprecated): New fn.
+       (grokparms): PARMLIST is a tree now.  Warn about parms that
+       use deprecated types.
+       * mangle.c (write_expression): Handle PARM_DECL, CALL_EXPR and
+       0-operand cast.
+       * pt.c (tsubst) [DECLTYPE_TYPE]: Set skip_evaluation.
+       (tsubst_copy) [PARM_DECL]: Handle a PARM_DECL used outside of a 
+       function.
+       * name-lookup.c (pushtag): Look through function parameter scopes.
+       (pushdecl_maybe_friend): Don't set DECL_CONTEXT on a PARM_DECL 
+       when we're parsing a function declarator.
+
 2008-09-05  Douglas Gregor  <doug.gregor@gmail.com>
 
        PR c++/37342
index ca069b765cf9aec9fbd0efa72f10ad6a4210e44f..4f6716b4c5bee23d2623a0f297a07e9a21066f38 100644 (file)
@@ -4108,8 +4108,8 @@ struct cp_declarator {
     } id;
     /* For functions.  */
     struct {
-      /* The parameters to the function.  */
-      cp_parameter_declarator *parameters;
+      /* The parameters to the function as a TREE_LIST of decl/default.  */
+      tree parameters;
       /* The cv-qualifiers for the function.  */
       cp_cv_quals qualifiers;
       /* The exception-specification for the function.  */
index c045353fe7f541627e369f2835b894525af13d2b..3348d28425c1253f07fd7580a0c0631b8e7388d1 100644 (file)
@@ -54,7 +54,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-flow.h"
 #include "pointer-set.h"
 
-static tree grokparms (cp_parameter_declarator *, tree *);
+static tree grokparms (tree parmlist, tree *);
 static const char *redeclaration_error_message (tree, tree);
 
 static int decl_jump_unsafe (tree);
@@ -236,13 +236,7 @@ VEC(tree, gc) *deferred_mark_used_calls;
    with __attribute__((deprecated)).  An object declared as
    __attribute__((deprecated)) suppresses warnings of uses of other
    deprecated items.  */
-
-enum deprecated_states {
-  DEPRECATED_NORMAL,
-  DEPRECATED_SUPPRESS
-};
-
-static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
 \f
 /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
@@ -9494,6 +9488,32 @@ check_default_argument (tree decl, tree arg)
   return arg;
 }
 
+/* Returns a deprecated type used within TYPE, or NULL_TREE if none.  */
+
+static tree
+type_is_deprecated (tree type)
+{
+  enum tree_code code;
+  if (TREE_DEPRECATED (type))
+    return type;
+  if (TYPE_NAME (type)
+      && TREE_DEPRECATED (TYPE_NAME (type)))
+    return type;
+
+  code = TREE_CODE (type);
+
+  if (code == POINTER_TYPE || code == REFERENCE_TYPE
+      || code == OFFSET_TYPE || code == FUNCTION_TYPE
+      || code == METHOD_TYPE || code == ARRAY_TYPE)
+    return type_is_deprecated (TREE_TYPE (type));
+
+  if (TYPE_PTRMEMFUNC_P (type))
+    return type_is_deprecated
+      (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+  return NULL_TREE;
+}
+
 /* Decode the list of parameter types for a function type.
    Given the list of things declared inside the parens,
    return a list of types.
@@ -9504,41 +9524,31 @@ check_default_argument (tree decl, tree arg)
    *PARMS is set to the chain of PARM_DECLs created.  */
 
 static tree
-grokparms (cp_parameter_declarator *first_parm, tree *parms)
+grokparms (tree parmlist, tree *parms)
 {
   tree result = NULL_TREE;
   tree decls = NULL_TREE;
-  int ellipsis = !first_parm || first_parm->ellipsis_p;
-  cp_parameter_declarator *parm;
+  tree parm;
   int any_error = 0;
-  struct pointer_set_t *unique_decls = pointer_set_create ();
 
-  for (parm = first_parm; parm != NULL; parm = parm->next)
+  for (parm = parmlist; parm != NULL_TREE; parm = TREE_CHAIN (parm))
     {
       tree type = NULL_TREE;
-      tree init = parm->default_argument;
-      tree attrs;
-      tree decl;
+      tree init = TREE_PURPOSE (parm);
+      tree decl = TREE_VALUE (parm);
 
-      if (parm == no_parameters)
+      if (parm == void_list_node)
        break;
 
-      attrs = parm->decl_specifiers.attributes;
-      parm->decl_specifiers.attributes = NULL_TREE;
-      decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
-                            PARM, init != NULL_TREE, &attrs);
       if (! decl || TREE_TYPE (decl) == error_mark_node)
        continue;
 
-      if (attrs)
-       cplus_decl_attributes (&decl, attrs, 0);
-
       type = TREE_TYPE (decl);
       if (VOID_TYPE_P (type))
        {
          if (same_type_p (type, void_type_node)
              && DECL_SELF_REFERENCE_P (type)
-             && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
+             && !DECL_NAME (decl) && !result && TREE_CHAIN (parm) == void_list_node)
            /* this is a parmlist of `(void)', which is ok.  */
            break;
          cxx_incomplete_type_error (decl, type);
@@ -9561,6 +9571,13 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
 
       if (type != error_mark_node)
        {
+         if (deprecated_state != DEPRECATED_SUPPRESS)
+           {
+             tree deptype = type_is_deprecated (type);
+             if (deptype)
+               warn_deprecated_use (deptype);
+           }
+
          /* Top-level qualifiers on the parameters are
             ignored for function types.  */
          type = cp_build_qualified_type (type, 0);
@@ -9603,28 +9620,20 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
 
       if (TREE_CODE (decl) == PARM_DECL
           && FUNCTION_PARAMETER_PACK_P (decl)
-          && parm->next)
+          && TREE_CHAIN (parm)
+          && TREE_CHAIN (parm) != void_list_node)
         error ("parameter packs must be at the end of the parameter list");
 
-      if (DECL_NAME (decl))
-        {
-          if (pointer_set_contains (unique_decls, DECL_NAME (decl)))
-            error ("multiple parameters named %qE", DECL_NAME (decl));
-          else
-            pointer_set_insert (unique_decls, DECL_NAME (decl));
-        }
-
       TREE_CHAIN (decl) = decls;
       decls = decl;
       result = tree_cons (init, type, result);
     }
   decls = nreverse (decls);
   result = nreverse (result);
-  if (!ellipsis)
+  if (parm)
     result = chainon (result, void_list_node);
   *parms = decls;
 
-  pointer_set_destroy (unique_decls);
   return result;
 }
 
index 52ab0fbaef5b90a8f734f7d14fca05a15ea18a44..ed287149d87e55fb317a17981bc887f250eb8bdc 100644 (file)
@@ -34,3 +34,16 @@ enum decl_context
 extern tree grokdeclarator (const cp_declarator *,
                            const cp_decl_specifier_seq *,
                            enum decl_context, int, tree*);
+
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
+
+extern enum deprecated_states deprecated_state;
+
index dea92b9c9ea4c8ec671743b331e97a93ea9a81ce..7b4c30344cce5e4ad1c69f3b8e086a712a105c52 100644 (file)
@@ -2016,7 +2016,8 @@ write_template_args (tree args)
    <expr-primary> ::= <template-param>
                  ::= L <type> <value number> E         # literal
                  ::= L <mangled-name> E                # external name
-                 ::= sr <type> <unqualified-name>
+                 ::= st <type>                         # sizeof
+                 ::= sr <type> <unqualified-name>      # dependent name
                  ::= sr <type> <unqualified-name> <template-args> */
 
 static void
@@ -2042,6 +2043,12 @@ write_expression (tree expr)
       code = TREE_CODE (expr);
     }
 
+  if (code == OVERLOAD)
+    {
+      expr = OVL_FUNCTION (expr);
+      code = TREE_CODE (expr);
+    }
+
   /* Handle pointers-to-members by making them look like expression
      nodes.  */
   if (code == PTRMEM_CST)
@@ -2064,6 +2071,13 @@ write_expression (tree expr)
   else if (TREE_CODE_CLASS (code) == tcc_constant
           || (abi_version_at_least (2) && code == CONST_DECL))
     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)));
+    }
   else if (DECL_P (expr))
     {
       /* G++ 3.2 incorrectly mangled non-type template arguments of
@@ -2175,16 +2189,17 @@ write_expression (tree expr)
       switch (code)
        {
        case CALL_EXPR:
-         sorry ("call_expr cannot be mangled due to a defect in the C++ ABI");
+         write_expression (CALL_EXPR_FN (expr));
+         for (i = 0; i < call_expr_nargs (expr); ++i)
+           write_expression (CALL_EXPR_ARG (expr, i));
+         write_char ('E');
          break;
 
        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");
+         /* "T()" is mangled as "T(void)".  */
+           write_char ('v');
          else
            write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
          break;
@@ -2195,7 +2210,6 @@ write_expression (tree expr)
          write_expression (TREE_OPERAND (expr, 0));
          break;
 
-
        /* Handle pointers-to-members specially.  */
        case SCOPE_REF:
          write_type (TREE_OPERAND (expr, 0));
index 7fc6a9341ae4411e6b33811b820d1068134cfa32..743f02365ee91542d8d82dd02eee88f954f7facb 100644 (file)
@@ -604,6 +604,13 @@ pushdecl_maybe_friend (tree x, bool is_friend)
             scope of the current namespace, not the current
             function.  */
          && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
+         /* When parsing the parameter list of a function declarator,
+            don't set DECL_CONTEXT to an enclosing function.  When we
+            push the PARM_DECLs in order to process the function body,
+            current_binding_level->this_entity will be set.  */
+         && !(TREE_CODE (x) == PARM_DECL
+              && current_binding_level->kind == sk_function_parms
+              && current_binding_level->this_entity == NULL)
          && !DECL_CONTEXT (x))
        DECL_CONTEXT (x) = current_function_decl;
 
@@ -712,8 +719,6 @@ pushdecl_maybe_friend (tree x, bool is_friend)
            }
          else if (TREE_CODE (t) == PARM_DECL)
            {
-             gcc_assert (DECL_CONTEXT (t));
-
              /* Check for duplicate params.  */
              if (duplicate_decls (x, t, is_friend))
                POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
@@ -4987,6 +4992,8 @@ pushtag (tree name, tree type, tag_scope scope)
   while (/* Cleanup scopes are not scopes from the point of view of
            the language.  */
         b->kind == sk_cleanup
+        /* Neither are function parameter scopes.  */
+        || b->kind == sk_function_parms
         /* Neither are the scopes used to hold template parameters
            for an explicit specialization.  For an ordinary template
            declaration, these scopes are not scopes from the point of
index 3f6e370112776a1472737503eabdd1b337dee799..88f92e7ccc469a0d1efb00531adf7f251b7865eb 100644 (file)
@@ -853,7 +853,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
 
 static cp_declarator *make_call_declarator
-  (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree, tree);
+  (cp_declarator *, tree, cp_cv_quals, tree, tree);
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
@@ -1013,7 +1013,7 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
 
 cp_declarator *
 make_call_declarator (cp_declarator *target,
-                     cp_parameter_declarator *parms,
+                     tree parms,
                      cp_cv_quals cv_qualifiers,
                      tree exception_specification,
                      tree late_return_type)
@@ -1736,9 +1736,9 @@ static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_clause
+static tree cp_parser_parameter_declaration_clause
   (cp_parser *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_list
+static tree cp_parser_parameter_declaration_list
   (cp_parser *, bool *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, bool, bool *);
@@ -12986,8 +12986,10 @@ cp_parser_direct_declarator (cp_parser* parser,
 
          if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
-             cp_parameter_declarator *params;
+             tree params;
              unsigned saved_num_template_parameter_lists;
+             bool is_declarator = false;
+             tree t;
 
              /* In a member-declarator, the only valid interpretation
                 of a parenthesis is the start of a
@@ -13014,6 +13016,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = parser->num_template_parameter_lists;
              parser->num_template_parameter_lists = 0;
 
+             begin_scope (sk_function_parms, NULL_TREE);
+
              /* Parse the parameter-declaration-clause.  */
              params = cp_parser_parameter_declaration_clause (parser);
 
@@ -13028,6 +13032,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                  tree exception_specification;
                  tree late_return;
 
+                 is_declarator = true;
+
                  if (ctor_dtor_or_conv_p)
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
                  first = false;
@@ -13053,10 +13059,16 @@ cp_parser_direct_declarator (cp_parser* parser,
                     return type, so are not those of the declared
                     function.  */
                  parser->default_arg_ok_p = false;
-
-                 /* Repeat the main loop.  */
-                 continue;
                }
+
+             /* Remove the function parms from scope.  */
+             for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+               pop_binding (DECL_NAME (t), t);
+             leave_scope();
+
+             if (is_declarator)
+               /* Repeat the main loop.  */
+               continue;
            }
 
          /* If this is the first, we can try a parenthesized
@@ -13728,10 +13740,10 @@ cp_parser_type_specifier_seq (cp_parser* parser,
    value of NULL indicates a parameter-declaration-clause consisting
    only of an ellipsis.  */
 
-static cp_parameter_declarator *
+static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser)
 {
-  cp_parameter_declarator *parameters;
+  tree parameters;
   cp_token *token;
   bool ellipsis_p;
   bool is_error;
@@ -13743,7 +13755,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     {
       /* Consume the `...' token.  */
       cp_lexer_consume_token (parser->lexer);
-      return NULL;
+      return NULL_TREE;
     }
   else if (token->type == CPP_CLOSE_PAREN)
     /* There are no parameters.  */
@@ -13751,10 +13763,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 #ifndef NO_IMPLICIT_EXTERN_C
       if (in_system_header && current_class_type == NULL
          && current_lang_name == lang_name_c)
-       return NULL;
+       return NULL_TREE;
       else
 #endif
-       return no_parameters;
+       return void_list_node;
     }
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
@@ -13764,7 +13776,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       /* Consume the `void' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* There are no parameters.  */
-      return no_parameters;
+      return void_list_node;
     }
 
   /* Parse the parameter-declaration-list.  */
@@ -13799,8 +13811,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     ellipsis_p = false;
 
   /* Finish the parameter list.  */
-  if (parameters && ellipsis_p)
-    parameters->ellipsis_p = true;
+  if (!ellipsis_p)
+    parameters = chainon (parameters, void_list_node);
 
   return parameters;
 }
@@ -13816,11 +13828,11 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
    `void_list_node' is never appended to the list.  Upon return,
    *IS_ERROR will be true iff an error occurred.  */
 
-static cp_parameter_declarator *
+static tree
 cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
-  cp_parameter_declarator *parameters = NULL;
-  cp_parameter_declarator **tail = &parameters;
+  tree parameters = NULL_TREE;
+  tree *tail = &parameters; 
   bool saved_in_unbraced_linkage_specification_p;
 
   /* Assume all will go well.  */
@@ -13836,6 +13848,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   while (true)
     {
       cp_parameter_declarator *parameter;
+      tree decl = error_mark_node;
       bool parenthesized_p;
       /* Parse the parameter.  */
       parameter
@@ -13843,17 +13856,38 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
                                           /*template_parm_p=*/false,
                                           &parenthesized_p);
 
+      /* We don't know yet if the enclosing context is deprecated, so wait
+        and warn in grokparms if appropriate.  */
+      deprecated_state = DEPRECATED_SUPPRESS;
+
+      if (parameter)
+       decl = grokdeclarator (parameter->declarator,
+                              &parameter->decl_specifiers,
+                              PARM,
+                              parameter->default_argument != NULL_TREE,
+                              &parameter->decl_specifiers.attributes);
+
+      deprecated_state = DEPRECATED_NORMAL;
+
       /* If a parse error occurred parsing the parameter declaration,
         then the entire parameter-declaration-list is erroneous.  */
-      if (!parameter)
+      if (decl == error_mark_node)
        {
          *is_error = true;
-         parameters = NULL;
+         parameters = error_mark_node;
          break;
        }
+
+      if (parameter->decl_specifiers.attributes)
+       cplus_decl_attributes (&decl,
+                              parameter->decl_specifiers.attributes,
+                              0);
+      if (DECL_NAME (decl))
+       decl = pushdecl (decl);
+
       /* Add the new parameter to the list.  */
-      *tail = parameter;
-      tail = &parameter->next;
+      *tail = build_tree_list (parameter->default_argument, decl);
+      tail = &TREE_CHAIN (*tail);
 
       /* Peek at the next token.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
index 7c9165c20eabf5a7bf7439c5f084c05bb7181ac9..4aa7b1ad146c28de4d6a707064ce9cbd299eff4e 100644 (file)
@@ -9556,11 +9556,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree type;
 
-       type = 
-          finish_decltype_type (tsubst_expr 
-                                (DECLTYPE_TYPE_EXPR (t), args,
-                                 complain, in_decl,
-                                 /*integral_constant_expression_p=*/false),
+       ++skip_evaluation;
+
+       type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
+                           complain, in_decl,
+                           /*integral_constant_expression_p=*/false);
+
+       --skip_evaluation;
+
+       type =
+          finish_decltype_type (type,
                                 DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
        return cp_build_qualified_type_real (type,
                                             cp_type_quals (t)
@@ -9796,7 +9801,22 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     {
     case PARM_DECL:
       r = retrieve_local_specialization (t);
-      gcc_assert (r != NULL);
+
+      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 && DECL_CONTEXT (t) == NULL_TREE);
+         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);
+       }
+      
       if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
        r = ARGUMENT_PACK_SELECT_ARG (r);
       mark_used (r);
index a3df9d1927ef591c7cbed0560257f79a02961c32..626e9e245d4862ac6de64c5d8eb1975bb27c83f3 100644 (file)
@@ -69,4 +69,6 @@ int main()
     case 42:
       break;
     }
+
+  auto j = 42, k = 24;
 }
index dc4218bf023456924e8874d380f3ea0dc7e6b043..769d987c9610de11b417193e786f70cb6bc11ad3 100644 (file)
@@ -5,6 +5,10 @@
 
 auto x;                                // { dg-error "auto" }
 
+// If the type deduced for the template parameter U is not the same in each
+// deduction, the program is ill-formed.
+auto i = 42, j = 42.0;         // { dg-error "" "" { xfail *-*-* } }
+
 // New CWG issue
 auto a[2] = { 1, 2 };          // { dg-error "auto" }
 
index ac209934869b06677f81a9fd93281803a82dc85f..a574f54758f7efe2d4e58eafef56bfa2e066e69b 100644 (file)
@@ -6,4 +6,20 @@ auto f() -> int
 }
 
 template<class T, class U>
-auto add(T t, U u) -> decltype (t+u); // { dg-bogus "not declared" "" { xfail *-*-* } }
+auto add(T t, U u) -> decltype (t+u);
+
+template<class T, class U>
+decltype(T()+U()) add2(T t, U u);
+
+template <class T, class U>
+U g (T, U);
+
+template<class T, class U>
+auto add3(T t, U u) -> decltype (g(t,u));
+
+int main()
+{
+  auto i = add(1, 2.0);
+  auto i2 = add2(1, 2.0);
+  auto i3 = add3(1, 2.0);
+}
index 0a5bae1b3c0b70872cad9208f4f6771c35076386..3601852322a41c143725950137da67edbac9d4b2 100644 (file)
@@ -3,58 +3,54 @@
 extern void g0 (int a, int b);
 extern void g1 (int a, float b);
 
-extern void f0 (int a,
-                int a);  // { dg-error "multiple parameters named 'a'" }
-extern void f1 (int a,
-                float a);  // { dg-error "multiple parameters named 'a'" }
-extern void f3 (int a, int b, int c,
-                int a);  // { dg-error "multiple parameters named 'a'" }
-extern void f4 (int a, int b, int c,
-                int a,
-                int a);  // { dg-error "multiple parameters named 'a'" }
-extern void f5 (int a, int b, int c, int d, int e, int f, int g, int h,
-                int a,
+extern void f0 (int a,         // { dg-error "previous" }
+                int a);                // { dg-error "redefinition" }
+extern void f1 (int a,         // { dg-error "previous" }
+                float a);      // { dg-error "conflicting" }
+extern void f3 (int a, int b, int c, // { dg-error "previous" }
+                int a);                // { dg-error "redefinition" }
+extern void f4 (int a, int b, int c, // { dg-error "previous" }
+                int a,              // { dg-error "redefinition" }
+                int a);                     // { dg-error "redefinition" }
+extern void f5 (int a, int b, int c, int d, int e, int f, int g, int h, // { dg-error "previous" }
+                int a,                                                 // { dg-error "redefinition" }
                 int i, int j, int k, int l, int m, int n, int o, int p,
                 int q, int r, int s, int t, int u, int v, int w, int x, int y,
-                int z);  // { dg-error "multiple parameters named 'a'" }
+                int z);
 
-extern void f6 (int a, int, int, int, int, int, int, int, int, int, int,
-                int a,
+extern void f6 (int a, int, int, int, int, int, int, int, int, int, int, // { dg-error "previous" }
+                int a,         // { dg-error "redefinition" }
                 int, int, int, int, int, int, int, int, int, int, int,
                 float, float, float, float, float, float, float, float,
-                int);  // { dg-error "multiple parameters named 'a'" }
-
-extern void f7 (void (*a)(int),
-                void (*a)(int));  // { dg-error "multiple parameters named 'a'" }
-extern void f8 (float (*a)(int),
-                int (*a)(float));  // { dg-error "multiple parameters named 'a'" }
-
-extern void f9 (int a,
-                int a,
-                int a);
-// { dg-error "multiple parameters named 'a'" "" { target *-*-* } 34 }
-
-extern void f10 (int a,
-                 int b,
-                 int c,
-                 int c,
-                 int b,
-                 int a);
-// { dg-error "multiple parameters named 'a'" "" { target *-*-* } 42 }
-// { dg-error "multiple parameters named 'b'" "" { target *-*-* } 42 }
-// { dg-error "multiple parameters named 'c'" "" { target *-*-* } 42 }
+                int);
+
+extern void f7 (void (*a)(int),          // { dg-error "previous" }
+                void (*a)(int));  // { dg-error "redefinition" }
+extern void f8 (float (*a)(int),  // { dg-error "previous" }
+                int (*a)(float));  // { dg-error "conflicting" }
+
+extern void f9 (int a,         // { dg-error "previous" }
+                int a,         // { dg-error "redefinition" }
+                int a);                // { dg-error "redefinition" }
+
+extern void f10 (int a,                // { dg-error "previous" }
+                 int b,                // { dg-error "previous" }
+                 int c,                // { dg-error "previous" }
+                 int c,                // { dg-error "redefinition" }
+                 int b,                // { dg-error "redefinition" }
+                 int a);       // { dg-error "redefinition" }
 
 class C1 {
  public:
   void C1_g0 (int a, int b);
-  void C1_f0 (int a,
-              int a);  // { dg-error "multiple parameters named 'a'" }
+  void C1_f0 (int a,           // { dg-error "previous" }
+              int a);          // { dg-error "redefinition" }
 };
 
 template <class T>
 class C2 {
  public:
   void C2_g0 (T a, T b);
-  void C2_f0 (T a,
-              T a);  // { dg-error "multiple parameters named 'a'" }
+  void C2_f0 (T a,             // { dg-error "previous" }
+              T a);            // { dg-error "redefinition" }
 };
index 9b403c7207bc20e4b0a400d5cabffc9de46eb648..21180d765ab1bf4cc890b42df29e452e0b43cb22 100644 (file)
@@ -1,6 +1,7 @@
 // { dg-do compile }
 // Make sure we emit a decent error message when trying to mangle an
 //  expression not supported by the C++ ABI due to a defect.
+// Update: Better to make it supported, I think...
 
 template <int N>
 struct A {};
@@ -15,5 +16,5 @@ A<sizeof(T::foo())> func(void);
 
 int main()
 {
-  func<B>();  // { dg-error "sorry, unimplemented" }
+  func<B>();
 }
index e16f6b589e5f686e6a255e813c926baff36d9a67..e370f717c3a9e08b7ef80b22f272442cfffe4475 100644 (file)
@@ -5,5 +5,5 @@ template<int> void foo(struct {}*); // { dg-error "" }
 
 void bar()
 {
-  foo<0>(0);
+  foo<0>(0);                   // { dg-error "" }
 }
index 1f337e91cde4ac90a8ce95c922602f77db0afeff..2856850fb76bb3545836c260313264257a9b087e 100644 (file)
@@ -6,14 +6,4 @@ static void InstantiateConstraint(const float&, unsigned,
                                                      char*, char*,
                                                      unsigned*));
 // { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
-
-/// in the coming test, the column information is broken as it points to
-//  the end of the declaration instead of pointing to the begining of the
-//  'TYPE' identifier. This is due to the warning being generated by the
-//  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
-//  code, the exact token location information is lost as the declaration
-//  groking code manipulates TREEs only. The token location used is then
-//  the global one that is not accurate enough. Anyway, let's say it is
-//  good enough for now, until we find a way to propagate token location to
-//  code paths that manipulate TREEs only.
-// { dg-error "64: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } }
+// { dg-error "60: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 5 } }
index 6a39ff42e3d52cc303455f076b8b39706b59d3a7..d42516d4fcfe826f86b773b3ab3a07e41e00e956 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
 // Bug: g++ doesn't push parameter decls as they are parsed.
 
-void (*ptr) (int foo, int array[sizeof(foo)]); // { dg-bogus "" "" { xfail *-*-* } }  
-void test2 (int bar, int array[sizeof(bar)]) { } // { dg-bogus "" "" { xfail *-*-* } }  
+void (*ptr) (int foo, int array[sizeof(foo)]);
+void test2 (int bar, int array[sizeof(bar)]) { }
index 133899e55e8e49c22b84f9c0afea8b9caa925f92..8ac05146866c864305c94f936fd7f5d612e6faae 100644 (file)
@@ -11,5 +11,5 @@ template<int P = 0> struct foo {
 };
 
 void bar() {
-  foo<>::bar(0); // { dg-error "" "" } instantiated from here
+  foo<>::bar(0);
 }
index c14ca235772682d6f7800552bdb2d173b37dadfb..808f233c648230d32c26f67673dab52351db1b4c 100644 (file)
@@ -9,7 +9,7 @@ struct S
   void f(U u);
 
   template <class U>
-  void g(U U);
+  void g(U u);
 
   int c[16];
 };