cp-tree.h (PARM_DECL_EXPR): Delete.
authorMark Mitchell <mark@markmitchell.com>
Thu, 21 Jan 1999 14:29:33 +0000 (14:29 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 21 Jan 1999 14:29:33 +0000 (14:29 +0000)
* cp-tree.h (PARM_DECL_EXPR): Delete.
(convert_default_arg): Change prototype.
(check_default_argument): Declare.
(search_tree): Likewise.
* call.c (convert_default_arg): Take the function to which the
default argument belongs as a parameter, and do any necessary
instantiation here, instead of ...
(build_over_call): Here.
* decl.c (local_variable_p): New function.
(check_default_argument): Likewise, split out and tidied from ...
(grokparms): Here.
* error.c (dump_expr): Don't set PARM_DECL_EXPR.
* pt.c (tsubst_call_declarator_parms): New function.
(for_each_template_parm): Handle ARRAY_REFs.  Do the obvious thing
with CALL_EXPRs, rather than trying to be clever.
(tsubst): Use tsubst_call_declarator_parms.
* tree.c (search_tree): Don't make it static.
* typeck.c (convert_arguments): Use new interface to
convert_default_arg.

From-SVN: r24803

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.other/defarg1.C [new file with mode: 0644]

index 9b14cda2d53f38993bdec221f784ccc1267497c5..498560a77cd6bcc58f0dc8fdc451dff2d1c53a5b 100644 (file)
@@ -1,3 +1,25 @@
+1999-01-21  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (PARM_DECL_EXPR): Delete.
+       (convert_default_arg): Change prototype.
+       (check_default_argument): Declare.
+       (search_tree): Likewise.
+       * call.c (convert_default_arg): Take the function to which the
+       default argument belongs as a parameter, and do any necessary
+       instantiation here, instead of ...
+       (build_over_call): Here.
+       * decl.c (local_variable_p): New function.
+       (check_default_argument): Likewise, split out and tidied from ...
+       (grokparms): Here.
+       * error.c (dump_expr): Don't set PARM_DECL_EXPR.
+       * pt.c (tsubst_call_declarator_parms): New function.
+       (for_each_template_parm): Handle ARRAY_REFs.  Do the obvious thing
+       with CALL_EXPRs, rather than trying to be clever.
+       (tsubst): Use tsubst_call_declarator_parms.
+       * tree.c (search_tree): Don't make it static.
+       * typeck.c (convert_arguments): Use new interface to
+       convert_default_arg.
+       
 1999-01-20  Mark Mitchell  <mark@markmitchell.com>
 
        * error.c (dump_function_decl): Don't print the argument types for
index 356a57d76ae2cd5da2f6fab313065acb9523f9c3..3891ea75b7e3175497a24e45cb903b0ce9669414 100644 (file)
@@ -3176,13 +3176,41 @@ convert_arg_to_ellipsis (arg)
 }
 
 /* ARG is a default argument expression being passed to a parameter of
-   the indicated TYPE.  Do any required conversions.  Return the
-   converted value.  */
+   the indicated TYPE, which is a parameter to FN.  Do any required
+   conversions.  Return the converted value.  */
 
 tree
-convert_default_arg (type, arg)
-     tree type, arg;
+convert_default_arg (type, arg, fn)
+     tree type;
+     tree arg;
+     tree fn;
 {
+  if (fn && DECL_TEMPLATE_INFO (fn))
+    {
+      /* This default argument came from a template.  Instantiate the
+        default argument here, not in tsubst.  In the case of
+        something like: 
+
+          template <class T>
+          struct S {
+            static T t();
+            void f(T = t());
+          };
+
+        we must be careful to do name lookup in the scope of S<T>,
+        rather than in the current class.  */
+      if (DECL_CLASS_SCOPE_P (fn))
+       pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+      arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
+
+      if (DECL_CLASS_SCOPE_P (fn))
+       popclass (1);
+
+      /* Make sure the default argument is reasonable.  */
+      arg = check_default_argument (type, arg);
+    }
+
   arg = break_out_target_exprs (arg);
 
   if (TREE_CODE (arg) == CONSTRUCTOR)
@@ -3326,34 +3354,12 @@ build_over_call (cand, args, flags)
 
   /* Default arguments */
   for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
-    {
-      tree arg = TREE_PURPOSE (parm);
-
-      if (DECL_TEMPLATE_INFO (fn))
-       {
-         /* This came from a template.  Instantiate the default arg here,
-            not in tsubst.  In the case of something like:
-
-              template <class T>
-              struct S {
-                static T t();
-                void f(T = t());
-              };
-
-            we must be careful to do name lookup in the scope of
-            S<T>, rather than in the current class.  */
-         if (DECL_CLASS_SCOPE_P (fn))
-           pushclass (DECL_REAL_CONTEXT (fn), 2);
-
-         arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
-
-         if (DECL_CLASS_SCOPE_P (fn))
-           popclass (1);
-       }
-      converted_args = expr_tree_cons
-       (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
-        converted_args);
-    }
+    converted_args 
+      = expr_tree_cons (NULL_TREE, 
+                       convert_default_arg (TREE_VALUE (parm), 
+                                            TREE_PURPOSE (parm),
+                                            fn),
+                       converted_args);
 
   /* Ellipsis */
   for (; arg; arg = TREE_CHAIN (arg))
index 18f697ae860504885bceef8271f3b612989fc1bf..7dc06ff2edb3dcf6800232285eb9d9e25a6f856b 100644 (file)
@@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA.  */
       BINFO_VBASE_MARKED.
       BINFO_FIELDS_MARKED.
       TYPE_VIRTUAL_P.
-      PARM_DECL_EXPR (in SAVE_EXPR).
    3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
       BINFO_VTABLE_PATH_MARKED.
       BINFO_PUSHDECLS_MARKED.
@@ -1704,9 +1703,6 @@ extern int flag_new_for_scope;
    specified in its declaration.  */
 #define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE))
 
-/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL.  */
-#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
-
 /* Nonzero in FUNCTION_DECL means it is really an operator.
    Just used to communicate formatting information to dbxout.c.  */
 #define DECL_OPERATOR(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.operator_attr)
@@ -2645,7 +2641,7 @@ extern tree build_op_delete_call          PROTO((enum tree_code, tree, tree, int, tree))
 extern int can_convert                         PROTO((tree, tree));
 extern int can_convert_arg                     PROTO((tree, tree, tree));
 extern void enforce_access                      PROTO((tree, tree));
-extern tree convert_default_arg                 PROTO((tree, tree));
+extern tree convert_default_arg                 PROTO((tree, tree, tree));
 extern tree convert_arg_to_ellipsis             PROTO((tree));
 
 /* in class.c */
@@ -2819,6 +2815,7 @@ extern void fixup_anonymous_union               PROTO((tree));
 extern int check_static_variable_definition     PROTO((tree, tree));
 extern void push_local_binding                  PROTO((tree, tree));
 extern void push_class_binding                  PROTO((tree, tree));
+extern tree check_default_argument              PROTO((tree, tree));
 
 /* in decl2.c */
 extern int check_java_method                   PROTO((tree));
@@ -3300,6 +3297,7 @@ extern void push_expression_obstack               PROTO((void));
 extern tree build_dummy_object                 PROTO((tree));
 extern tree maybe_dummy_object                 PROTO((tree, tree *));
 extern int is_dummy_object                     PROTO((tree));
+extern tree search_tree                         PROTO((tree, tree (*)(tree)));
 #define scratchalloc expralloc
 #define scratch_tree_cons expr_tree_cons
 #define build_scratch_list build_expr_list
index bb2ef729f3ca96dff49097f611e34a0400b500b1..161876ee80c791ac24f602545d4d940af7f02a3c 100644 (file)
@@ -182,6 +182,7 @@ static boolean typename_compare PROTO((hash_table_key, hash_table_key));
 static void push_binding PROTO((tree, tree, struct binding_level*));
 static void add_binding PROTO((tree, tree));
 static void pop_binding PROTO((tree, tree));
+static tree local_variable_p PROTO((tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -11260,6 +11261,103 @@ require_complete_types_for_parms (parms)
     }
 }
 
+/* Returns DECL if DECL is a local variable (or parameter).  Returns
+   NULL_TREE otherwise.  */
+
+static tree
+local_variable_p (t)
+     tree t;
+{
+  if ((TREE_CODE (t) == VAR_DECL 
+       /* A VAR_DECL with a context that is a _TYPE is a static data
+         member.  */
+       && !TYPE_P (CP_DECL_CONTEXT (t))
+       /* Any other non-local variable must be at namespace scope.  */
+       && TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL)
+      || (TREE_CODE (t) == PARM_DECL))
+    return t;
+
+  return NULL_TREE;
+}
+
+/* Check that ARG, which is a default-argument expression for a
+   parameter DECL, is legal.  Returns ARG, or ERROR_MARK_NODE, if
+   something goes wrong.  DECL may also be a _TYPE node, rather than a
+   DECL, if there is no DECL available.  */
+
+tree
+check_default_argument (decl, arg)
+     tree decl;
+     tree arg;
+{
+  tree var;
+  tree decl_type;
+
+  if (TREE_CODE (arg) == DEFAULT_ARG)
+    /* We get a DEFAULT_ARG when looking at an in-class declaration
+       with a default argument.  Ignore the argument for now; we'll
+       deal with it after the class is complete.  */
+    return arg;
+
+  if (processing_template_decl || uses_template_parms (arg))
+    /* We don't do anything checking until instantiation-time.  Note
+       that there may be uninstantiated arguments even for an
+       instantiated function, since default arguments are not
+       instantiated until they are needed.  */
+    return arg;
+
+  if (TYPE_P (decl))
+    {
+      decl_type = decl;
+      decl = NULL_TREE;
+    }
+  else
+    decl_type = TREE_TYPE (decl);
+
+  if (arg == error_mark_node 
+      || decl == error_mark_node
+      || TREE_TYPE (arg) == error_mark_node
+      || decl_type == error_mark_node)
+    /* Something already went wrong.  There's no need to check
+       further.  */
+    return error_mark_node;
+
+  /* [dcl.fct.default]
+     
+     A default argument expression is implicitly converted to the
+     parameter type.  */
+  if (!TREE_TYPE (arg)
+      || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
+    {
+      if (decl)
+       cp_error ("default argument for `%#D' has type `%T'", 
+                 decl, TREE_TYPE (arg));
+      else
+       cp_error ("default argument for paramter of type `%T' has type `%T'",
+                 decl_type, TREE_TYPE (arg));
+
+      return error_mark_node;
+    }
+
+  /* [dcl.fct.default]
+
+     Local variables shall not be used in default argument
+     expressions. 
+
+     The keyword `this' shall not be used in a default argument of a
+     member function.  */
+  var = search_tree (arg, local_variable_p);
+  if (var)
+    {
+      cp_error ("default argument `%E' uses local variable `%D'",
+               arg, var);
+      return error_mark_node;
+    }
+
+  /* All is well.  */
+  return arg;
+}
+
 /* Decode the list of parameter types for a function type.
    Given the list of things declared inside the parens,
    return a list of types.
@@ -11437,51 +11535,10 @@ grokparms (first_parm, funcdef_flag)
                  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
                DECL_ARG_TYPE (decl) = integer_type_node;
 #endif
-             if (!any_error)
+             if (!any_error && init)
                {
-                 if (init)
-                   {
-                     any_init++;
-                     if (TREE_CODE (init) == SAVE_EXPR)
-                       PARM_DECL_EXPR (init) = 1;
-                     else if (processing_template_decl)
-                       ;
-                     /* Unparsed default arg from in-class decl.  */
-                     else if (TREE_CODE (init) == DEFAULT_ARG)
-                       ;
-                     else if (TREE_CODE (init) == PARM_DECL
-                              || TREE_CODE (init) == VAR_DECL)
-                       {
-                         if (TREE_CODE (init) == VAR_DECL
-                             && (IDENTIFIER_VALUE (DECL_NAME (init))
-                                 == init)
-                             && LOCAL_BINDING_P
-                             (IDENTIFIER_BINDING (DECL_NAME
-                                                  (init))))
-                           {
-                             /* ``Local variables may not be used in
-                                default argument expressions.''
-                                dpANSI C++ 8.2.6 */
-
-                             cp_error ("local variable `%D' may not be used as a default argument", init);
-                             any_error = 1;
-                           }
-                         else if (TREE_READONLY_DECL_P (init))
-                           init = decl_constant_value (init);
-                       }
-                     else if (TREE_TYPE (init) == NULL_TREE)
-                       {
-                         error ("argument list may not have an initializer list");
-                         init = error_mark_node;
-                       }
-
-                     if (! processing_template_decl
-                         && init != error_mark_node
-                         && TREE_CODE (init) != DEFAULT_ARG
-                         && ! can_convert_arg (type, TREE_TYPE (init), init))
-                       cp_pedwarn ("invalid type `%T' for default argument to `%#D'",
-                                   TREE_TYPE (init), decl);
-                   }
+                 any_init++;
+                 init = check_default_argument (decl, init);
                }
              else
                init = NULL_TREE;
index fd3f5f50e4c7ddb0900c58fba78134a02270e976..ec3bf71b00fd7fb9da95e6f7e72ab0b0db79a3eb 100644 (file)
@@ -1344,7 +1344,6 @@ dump_expr (t, nop)
        {
          OB_PUTS ("new ");
          dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
-         PARM_DECL_EXPR (t) = 1;
        }
       else
        {
index 0a675359d025f313c8cfd44f8174da2579d84e8d..9bd73c240b81ee4f4bc760ef382609a7e50941f4 100644 (file)
@@ -136,6 +136,7 @@ static void check_specialization_scope PROTO((void));
 static tree process_partial_specialization PROTO((tree));
 static void set_current_access_from_decl PROTO((tree));
 static void check_default_tmpl_args PROTO((tree, tree, int, int));
+static tree tsubst_call_declarator_parms PROTO((tree, tree, tree));
 
 /* We use TREE_VECs to hold template arguments.  If there is only one
    level of template arguments, then the TREE_VEC contains the
@@ -3809,6 +3810,10 @@ for_each_template_parm (t, fn, data)
         COMPONENT_REF uses template parms.  */
       return for_each_template_parm (TREE_TYPE (t), fn, data);
 
+    case ARRAY_REF:
+      return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
+             || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
+
     case IDENTIFIER_NODE:
       if (!IDENTIFIER_TEMPLATE (t))
        return 0;
@@ -3917,7 +3922,9 @@ for_each_template_parm (t, fn, data)
       return 0;
 
     case CALL_EXPR:
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
+      return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
+             || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
+       
     case ADDR_EXPR:
       return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
 
@@ -5628,6 +5635,43 @@ tsubst_arg_types (arg_types, args, in_decl)
                         
 }
 
+/* Substitute into the PARMS of a call-declarator.  */
+
+tree
+tsubst_call_declarator_parms (parms, args, in_decl)
+     tree parms;
+     tree args;
+     tree in_decl;
+{
+  tree new_parms;
+  tree type;
+  tree defarg;
+
+  if (!parms || parms == void_list_node)
+    return parms;
+  
+  new_parms = tsubst_call_declarator_parms (TREE_CHAIN (parms),
+                                           args, in_decl);
+
+  /* Figure out the type of this parameter.  */
+  type = tsubst (TREE_VALUE (parms), args, in_decl);
+  
+  /* Figure out the default argument as well.  Note that we use
+     tsubst_copy since the default argument is really an 
+     expression.  */
+  defarg = tsubst_expr (TREE_PURPOSE (parms), args, in_decl);
+
+  /* Chain this parameter on to the front of those we have already
+     processed.  We don't use hash_tree_cons because that function
+     doesn't check TREE_PARMLIST.  */
+  new_parms = tree_cons (defarg, type, new_parms);
+
+  /* And note that these are parameters.  */
+  TREE_PARMLIST (new_parms) = 1;
+  
+  return new_parms;
+}
+
 /* Take the tree structure T and replace template parameters used therein
    with the argument vector ARGS.  IN_DECL is an associated decl for
    diagnostics.
@@ -6061,7 +6105,7 @@ tsubst (t, args, in_decl)
     case CALL_EXPR:
       return make_call_declarator
        (tsubst (TREE_OPERAND (t, 0), args, in_decl),
-        tsubst (TREE_OPERAND (t, 1), args, in_decl),
+        tsubst_call_declarator_parms (TREE_OPERAND (t, 1), args, in_decl),
         TREE_OPERAND (t, 2),
         tsubst (TREE_TYPE (t), args, in_decl));
 
index 85cd96827fbc20e397da23e37c9767207a91e189..65ae47a7f637a7fb79fdea96dd415f18a80d7110 100644 (file)
@@ -1545,7 +1545,7 @@ copy_template_template_parm (t)
 /* Walk through the tree structure T, applying func.  If func ever returns
    non-null, return that value.  */
 
-static tree
+tree
 search_tree (t, func)
      tree t;
      tree (*func) PROTO((tree));
index 9882f764345f207d514cb31633deb81ca8c33ae5..82ce5144fe26e04e3081da326b55ef4919ad3a32 100644 (file)
@@ -3088,9 +3088,10 @@ convert_arguments (typelist, values, fndecl, flags)
        {
          for (; typetail != void_list_node; ++i)
            {
-             tree type = TREE_VALUE (typetail);
-             tree val = TREE_PURPOSE (typetail);
-             tree parmval = convert_default_arg (type, val);
+             tree parmval 
+               = convert_default_arg (TREE_VALUE (typetail), 
+                                      TREE_PURPOSE (typetail), 
+                                      fndecl);
 
              if (parmval == error_mark_node)
                return error_mark_node;
diff --git a/gcc/testsuite/g++.old-deja/g++.other/defarg1.C b/gcc/testsuite/g++.old-deja/g++.other/defarg1.C
new file mode 100644 (file)
index 0000000..68b07a5
--- /dev/null
@@ -0,0 +1,28 @@
+// Build don't link:
+
+int f (int x)
+{
+  extern void g (int i = f (x)); // ERROR - default argument uses local
+  
+  g();
+
+  return 0;
+}
+
+int f (void);
+
+int h1 (int (*)(int) = f);
+int h2 (int (*)(double) = f); // ERROR - no matching f
+
+template <class T>
+int j (T t)
+{
+  extern void k (int i = j (t)); // ERROR - default argument uses local
+
+  k ();
+
+  return 0;
+}
+
+template int j (double); // ERROR - instantiated from here
+