]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold-const.c (make_range): Do not access operand 1 for a zero-operand operator.
authorMark Mitchell <mark@codesourcery.com>
Wed, 9 Jul 2003 08:48:08 +0000 (08:48 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 9 Jul 2003 08:48:08 +0000 (08:48 +0000)
* fold-const.c (make_range): Do not access operand 1 for a
zero-operand operator.

2003-07-08  Mark Mitchell  <mark@codesourcery.com>

* cp-tree.def (NON_DEPENDENT_EXPR): New node.
* cp-tree.h (build_call_from_tree): Remove.
(build_member_call): Likewise.
(dependent_template_arg_p): Remove.
(any_dependent_template_arguments_p): New function.
(dependent_template_id_p): Likewise.
(any_type_dependent_arguments_p): Likewise.
(build_non_dependent_expr): Likewise.
(build_non_dependent_args): Likewise.
(build_x_compound_expr): Adjust prototype.
* call.c (build_new_method_call): Handle non-dependent expressions
correctly.
* decl2.c (grok_array_decl): Likewise.
(build_offset_ref_call_from_tree): Likewise.
(build_call_from_tree): Remove.
* error.c (dump_decl): Handle NON_DEPENDENT_EXPR.
(dump_expr): Likewise.
* init.c (build_member_call): Remove.
* mangle.c (write_expression): Update handling for template-ids.
* parser.c (cp_parser_primary_expression): Use
any_dependent_template_arguments_p.  Update constant-expression
handling.
(cp_parser_postfix_expression): Use
any_type_dependent_arguments_p.  Simplify call processing.
(cp_parser_unary_expression): Simplify.
(cp_parser_expression): Adjust for changes to
build_x_compound_expr.
(cp_parser_template_argument): Implement standard-conforming
parsing of non-type template arguments.
(cp_parser_direct_declarator): Use
cp_parser_fold_non_dependent_expr.
(cp_parser_fold_non_dependent_expr): New function.
(cp_parser_next_token_ends_template_argument_p): Likewise.
* pt.c (convert_template_argument): Do not call
maybe_fold_nontype_arg.
(tsubst_baselink): Likewise.
(tsubst_copy_and_build): Share common code.  Make sizeof/alignof
processing work correctly for non-dependent expressions.  Adjust
handling of COMPOUND_EXPR.  Simplify call processing.
(value_dependent_expression_p): Deal with functional casts and
sizeof/alignof correctly.
(type_dependent_expression_p): Handle overloaded functions.
(any_type_dependent_arguments_p): New function.
(any_dependent_template_arguments_p): Likewise.
(dependent_template_p): Treat SCOPE_REFs as dependent.
(dependent_template_id_p): Simplify.
(build_non_dependent_expr): New function.
(build_non_dependent_args): Likewise.
* semantics.c (finish_stmt_expr): Don't make dependent
statement-expresions have void type.
(finish_call_expr): Handle non-dependent expressions
correctly.
* tree.c (lvalue_p_1): Treat NON_DEPENDENT_EXPRs as lvalues.
* typeck.c (cxx_sizeof_or_alignof_type): Give the expression
type size_t, even in templates.
(expr_sizeof): Likewise.
(finish_class_member_access_expr): Handle non-dependent expressions
correctly.
(build_x_indirect_ref): Likewise.
(build_x_binary_op): Likewise.
(build_x_unary_op): Likewise.
(build_x_conditional_expr): Likewise.
(build_x_compound_expr): Likewise.
* typeck2.c (build_x_arrow): Likewise.

2003-07-08  Mark Mitchell  <mark@codesourcery.com>

* g++.dg/abi/mangle17.C: Make sure template expressions are
dependent.
* g++.dg/abi/mangle4.C: Mark erroneous casts.
* g++.dg/debug/debug7.C: Mark erronous new-declarator.
* g++.dg/opt/stack1.C: Remove erroneous code.
* g++.dg/parse/template7.C: New test.
* g++.dg/template/dependent-expr1.C: Mark erroneous code.
* g++.old-deja/g++.pt/crash4.C: Likewise.

2003-07-09  Mark Mitchell  <mark@codesourcery.com>

* gcj/array.h (JvPrimClass): Don't parenthesize the output.

From-SVN: r69130

26 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/mangle.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle17.C
gcc/testsuite/g++.dg/abi/mangle4.C
gcc/testsuite/g++.dg/debug/debug7.C
gcc/testsuite/g++.dg/opt/stack1.C
gcc/testsuite/g++.dg/parse/template7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/dependent-expr1.C
gcc/testsuite/g++.old-deja/g++.pt/crash41.C
libjava/ChangeLog
libjava/gcj/array.h

index d5ee8c611e1b0bb13c027efbfa96b1da021085e7..e5cf6bba07802019c6266c76359a64e839a73152 100644 (file)
@@ -1,3 +1,8 @@
+2003-07-08  Mark Mitchell  <mark@codesourcery.com>
+
+       * fold-const.c (make_range): Do not access operand 1 for a
+       zero-operand operator.
+
 2003-07-09  Neil Booth  <neil@daikokuya.co.uk>
 
        * toplev.c (warn_dummy, W_options): Die.
index a4b9aea45351a32a8497941ed84c79708a898c1c..8d83247f636e82c44293007f22ff0e59a53f7ce3 100644 (file)
@@ -1,3 +1,70 @@
+2003-07-08  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.def (NON_DEPENDENT_EXPR): New node.
+       * cp-tree.h (build_call_from_tree): Remove.
+       (build_member_call): Likewise.
+       (dependent_template_arg_p): Remove.
+       (any_dependent_template_arguments_p): New function.
+       (dependent_template_id_p): Likewise.
+       (any_type_dependent_arguments_p): Likewise.
+       (build_non_dependent_expr): Likewise.
+       (build_non_dependent_args): Likewise.
+       (build_x_compound_expr): Adjust prototype.
+       * call.c (build_new_method_call): Handle non-dependent expressions
+       correctly.
+       * decl2.c (grok_array_decl): Likewise.
+       (build_offset_ref_call_from_tree): Likewise.
+       (build_call_from_tree): Remove.
+       * error.c (dump_decl): Handle NON_DEPENDENT_EXPR.
+       (dump_expr): Likewise.
+       * init.c (build_member_call): Remove.
+       * mangle.c (write_expression): Update handling for template-ids.
+       * parser.c (cp_parser_primary_expression): Use
+       any_dependent_template_arguments_p.  Update constant-expression
+       handling.
+       (cp_parser_postfix_expression): Use
+       any_type_dependent_arguments_p.  Simplify call processing.
+       (cp_parser_unary_expression): Simplify.
+       (cp_parser_expression): Adjust for changes to
+       build_x_compound_expr.
+       (cp_parser_template_argument): Implement standard-conforming
+       parsing of non-type template arguments.
+       (cp_parser_direct_declarator): Use
+       cp_parser_fold_non_dependent_expr.
+       (cp_parser_fold_non_dependent_expr): New function.
+       (cp_parser_next_token_ends_template_argument_p): Likewise.
+       * pt.c (convert_template_argument): Do not call
+       maybe_fold_nontype_arg.
+       (tsubst_baselink): Likewise.
+       (tsubst_copy_and_build): Share common code.  Make sizeof/alignof
+       processing work correctly for non-dependent expressions.  Adjust
+       handling of COMPOUND_EXPR.  Simplify call processing.
+       (value_dependent_expression_p): Deal with functional casts and
+       sizeof/alignof correctly.
+       (type_dependent_expression_p): Handle overloaded functions.
+       (any_type_dependent_arguments_p): New function.
+       (any_dependent_template_arguments_p): Likewise.
+       (dependent_template_p): Treat SCOPE_REFs as dependent.
+       (dependent_template_id_p): Simplify.
+       (build_non_dependent_expr): New function.
+       (build_non_dependent_args): Likewise.
+       * semantics.c (finish_stmt_expr): Don't make dependent
+       statement-expresions have void type.
+       (finish_call_expr): Handle non-dependent expressions
+       correctly.
+       * tree.c (lvalue_p_1): Treat NON_DEPENDENT_EXPRs as lvalues.
+       * typeck.c (cxx_sizeof_or_alignof_type): Give the expression
+       type size_t, even in templates.
+       (expr_sizeof): Likewise.
+       (finish_class_member_access_expr): Handle non-dependent expressions
+       correctly.
+       (build_x_indirect_ref): Likewise.
+       (build_x_binary_op): Likewise.
+       (build_x_unary_op): Likewise.
+       (build_x_conditional_expr): Likewise.
+       (build_x_compound_expr): Likewise.
+       * typeck2.c (build_x_arrow): Likewise.
+
 Wed Jul  9 02:28:39 CEST 2003  Jan Hubicka  <jh@suse.cz>
 
        * cp-lang.c (LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS): New.
@@ -210,13 +277,13 @@ Wed Jul  9 02:28:39 CEST 2003  Jan Hubicka  <jh@suse.cz>
        (build_conditional_expr): Likewise.
        (build_new_method_call): Likewise.
        * cp-tree.def (OFFSET_REF): Update documentation.
-       (cp_convert_to_pointer): Update handling of conversions from
+       * cvt.c (cp_convert_to_pointer): Update handling of conversions from
        pointers to members to pointers.
        (ocp_convert): Do not call resolve_offset_ref.
        (convert_to_void): Likewise.
        (build_expr_type_conversion): Likewise.
-       (delete_sanity): Likewise.
-       (resolve_offset_ref): Simplify greatly.
+       * decl2.c (delete_sanity): Likewise.
+       * init.c (resolve_offset_ref): Simplify greatly.
        (build_vec_delete): Do not call resolve_offset_ref.
        * parser.c (cp_parser_postfix_expression): Call resolve_offset_ref
        if appropriate.
index fbf5c06a32fed257b6216d4190b783b4b5a87c4f..6659592b22dcd3f602abf0bf84db6089770ef633 100644 (file)
@@ -325,8 +325,7 @@ build_call (tree function, tree parms)
 
    BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
    down to the real instance type to use for access checking.  We need this
-   information to get protected accesses correct.  This parameter is used
-   by build_member_call.
+   information to get protected accesses correct.
 
    FLAGS is the logical disjunction of zero or more LOOKUP_
    flags.  See cp-tree.h for more info.
@@ -4883,6 +4882,9 @@ build_new_method_call (tree instance, tree fns, tree args,
   tree class_type;
   int template_only = 0;
   bool any_viable_p;
+  tree orig_instance;
+  tree orig_fns;
+  tree orig_args;
 
   my_friendly_assert (instance != NULL_TREE, 20020729);
 
@@ -4891,6 +4893,20 @@ build_new_method_call (tree instance, tree fns, tree args,
       || args == error_mark_node)
     return error_mark_node;
 
+  orig_instance = instance;
+  orig_fns = fns;
+  orig_args = args;
+
+  if (processing_template_decl)
+    {
+      instance = build_non_dependent_expr (instance);
+      if (!BASELINK_P (fns)
+         && TREE_CODE (fns) != PSEUDO_DTOR_EXPR
+         && TREE_TYPE (fns) != unknown_type_node)
+       fns = build_non_dependent_expr (fns);
+      args = build_non_dependent_args (orig_args);
+    }
+
   /* Process the argument list.  */
   user_args = args;
   args = resolve_args (args);
@@ -5068,6 +5084,13 @@ build_new_method_call (tree instance, tree fns, tree args,
        call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
     }
 
+  if (processing_template_decl && call != error_mark_node)
+    return build_min (CALL_EXPR,
+                     TREE_TYPE (call),
+                     build_min_nt (COMPONENT_REF,
+                                   orig_instance, 
+                                   orig_fns),
+                     orig_args);
   return call;
 }
 
index e988a4e25f98595b77aeff37f27e4b8a8e0a037e..f9819ec1cad020606b55aa6381f07f0bb83e37cd 100644 (file)
@@ -238,6 +238,16 @@ DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
 DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
 DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
 
+/* A placeholder for an expression that is not type-dependent, but
+   does occur in a template.  When an expression that is not
+   type-dependent appears in a larger expression, we must compute the
+   type of that larger expression.  That computation would normally
+   modify the original expression, which would change the mangling of
+   that expression if it appeared in a template argument list.  In
+   that situation, we create a NON_DEPENDENT_EXPR to take the place of
+   the original expression.  */
+DEFTREECODE (NON_DEPENDENT_EXPR, "non_dependent_expr", 'e', 0)
+
 /* CTOR_INITIALIZER is a placeholder in template code for a call to
    setup_vtbl_pointer (and appears in all functions, not just ctors).  */
 DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)
index 9d383cf24aef768d21906090d2e914bb658b5b0f..58eabc3a396afb3d99d8ec03919fc8e65be834da 100644 (file)
@@ -215,6 +215,7 @@ struct diagnostic_context;
 
 #define abi_version_at_least(N) \
   (flag_abi_version == 0 || flag_abi_version >= (N))
+
 \f
 /* Language-dependent contents of an identifier.  */
 
@@ -3775,7 +3776,6 @@ extern void import_export_tinfo   (tree, tree, bool);
 extern void finish_file                                (void);
 extern tree build_cleanup                      (tree);
 extern tree build_offset_ref_call_from_tree     (tree, tree);
-extern tree build_call_from_tree                (tree, tree, bool);
 extern void set_decl_namespace (tree, tree, bool);
 extern tree current_decl_namespace              (void);
 extern void push_decl_namespace                 (tree);
@@ -3853,7 +3853,6 @@ extern int is_aggr_type                           (tree, int);
 extern tree get_aggr_from_typedef              (tree, int);
 extern tree get_type_value                     (tree);
 extern tree build_zero_init                    (tree, tree, bool);
-extern tree build_member_call                  (tree, tree, tree);
 extern tree build_offset_ref                   (tree, tree);
 extern tree resolve_offset_ref                 (tree);
 extern tree build_new                          (tree, tree, tree, int);
@@ -3974,12 +3973,16 @@ extern tree current_instantiation               (void);
 extern tree maybe_get_template_decl_from_type_decl (tree);
 extern int processing_template_parmlist;
 extern bool dependent_type_p                    (tree);
-extern bool dependent_template_arg_p            (tree);
+extern bool any_dependent_template_arguments_p  (tree);
 extern bool dependent_template_p                (tree);
+extern bool dependent_template_id_p             (tree, tree);
 extern bool type_dependent_expression_p         (tree);
+extern bool any_type_dependent_arguments_p      (tree);
 extern bool value_dependent_expression_p        (tree);
 extern tree resolve_typename_type               (tree, bool);
 extern tree template_for_substitution           (tree);
+extern tree build_non_dependent_expr            (tree);
+extern tree build_non_dependent_args            (tree);
 
 /* in repo.c */
 extern void repo_template_used (tree);
@@ -4267,7 +4270,7 @@ extern tree build_x_binary_op                     (enum tree_code, tree, tree);
 extern tree build_x_unary_op                   (enum tree_code, tree);
 extern tree unary_complex_lvalue               (enum tree_code, tree);
 extern tree build_x_conditional_expr           (tree, tree, tree);
-extern tree build_x_compound_expr              (tree);
+extern tree build_x_compound_expr              (tree, tree);
 extern tree build_compound_expr                        (tree);
 extern tree build_static_cast                  (tree, tree);
 extern tree build_reinterpret_cast             (tree, tree);
index 7a2399a6016d7865325d47c9e94ba260ac7c934a..c77e5039fb9a9d5a709907cbc3198b9c743266d8 100644 (file)
@@ -398,59 +398,77 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
 tree
 grok_array_decl (tree array_expr, tree index_exp)
 {
-  tree type = TREE_TYPE (array_expr);
-  tree p1, p2, i1, i2;
+  tree type;
+  tree expr;
+  tree orig_array_expr = array_expr;
+  tree orig_index_exp = index_exp;
 
-  if (type == error_mark_node || index_exp == error_mark_node)
+  if (error_operand_p (array_expr) || error_operand_p (index_exp))
     return error_mark_node;
+
   if (processing_template_decl)
-    return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
-                     array_expr, index_exp);
+    {
+      if (type_dependent_expression_p (array_expr)
+         || type_dependent_expression_p (index_exp))
+       return build_min_nt (ARRAY_REF, array_expr, index_exp);
+      array_expr = build_non_dependent_expr (array_expr);
+      index_exp = build_non_dependent_expr (index_exp);
+    }
 
+  type = TREE_TYPE (array_expr);
   my_friendly_assert (type, 20030626);
-
   type = non_reference (type);
 
   /* If they have an `operator[]', use that.  */
   if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
-    return build_new_op (ARRAY_REF, LOOKUP_NORMAL,
+    expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
                         array_expr, index_exp, NULL_TREE);
-
-  /* Otherwise, create an ARRAY_REF for a pointer or array type.  It
-     is a little-known fact that, if `a' is an array and `i' is an
-     int, you can write `i[a]', which means the same thing as `a[i]'.  */
-
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    p1 = array_expr;
   else
-    p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
+    {
+      tree p1, p2, i1, i2;
+
+      /* Otherwise, create an ARRAY_REF for a pointer or array type.
+        It is a little-known fact that, if `a' is an array and `i' is
+        an int, you can write `i[a]', which means the same thing as
+        `a[i]'.  */
+      if (TREE_CODE (type) == ARRAY_TYPE)
+       p1 = array_expr;
+      else
+       p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
 
-  if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
-    p2 = index_exp;
-  else
-    p2 = build_expr_type_conversion (WANT_POINTER, index_exp, false);
+      if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
+       p2 = index_exp;
+      else
+       p2 = build_expr_type_conversion (WANT_POINTER, index_exp, false);
 
-  i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, false);
-  i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, false);
+      i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 
+                                      false);
+      i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 
+                                      false);
 
-  if ((p1 && i2) && (i1 && p2))
-    error ("ambiguous conversion for array subscript");
+      if ((p1 && i2) && (i1 && p2))
+       error ("ambiguous conversion for array subscript");
 
-  if (p1 && i2)
-    array_expr = p1, index_exp = i2;
-  else if (i1 && p2)
-    array_expr = p2, index_exp = i1;
-  else
-    {
-      error ("invalid types `%T[%T]' for array subscript",
-               type, TREE_TYPE (index_exp));
-      return error_mark_node;
-    }
+      if (p1 && i2)
+       array_expr = p1, index_exp = i2;
+      else if (i1 && p2)
+       array_expr = p2, index_exp = i1;
+      else
+       {
+         error ("invalid types `%T[%T]' for array subscript",
+                   type, TREE_TYPE (index_exp));
+         return error_mark_node;
+       }
 
-  if (array_expr == error_mark_node || index_exp == error_mark_node)
-    error ("ambiguous conversion for array subscript");
+      if (array_expr == error_mark_node || index_exp == error_mark_node)
+       error ("ambiguous conversion for array subscript");
 
-  return build_array_ref (array_expr, index_exp);
+      expr = build_array_ref (array_expr, index_exp);
+    }
+  if (processing_template_decl && expr != error_mark_node)
+    return build_min (ARRAY_REF, TREE_TYPE (expr), orig_array_expr, 
+                     orig_index_exp);
+  return expr;
 }
 
 /* Given the cast expression EXP, checking out its validity.   Either return
@@ -2949,8 +2967,37 @@ tree
 build_offset_ref_call_from_tree (tree fn, tree args)
 {
   tree object_addr;
+  tree orig_fn;
+  tree orig_args;
+  tree expr;
+
+  orig_fn = fn;
+  orig_args = args;
 
-  my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
+  if (processing_template_decl)
+    {
+      tree object;
+      tree object_type;
+
+      my_friendly_assert (TREE_CODE (fn) == DOTSTAR_EXPR
+                         || TREE_CODE (fn) == MEMBER_REF,
+                         20030708);
+      if (type_dependent_expression_p (fn)
+         || any_type_dependent_arguments_p (args))
+       return build_min_nt (CALL_EXPR, fn, args);
+
+      /* Transform the arguments and add the implicit "this"
+        parameter.  That must be done before the FN is transformed
+        because we depend on the form of FN.  */
+      args = build_non_dependent_args (args);
+      object_type = TREE_TYPE (TREE_OPERAND (fn, 0));
+      if (TREE_CODE (fn) == DOTSTAR_EXPR)
+       object_type = build_pointer_type (non_reference (object_type));
+      object = build (NON_DEPENDENT_EXPR, object_type);
+      args = tree_cons (NULL_TREE, object, args);
+      /* Now that the arguments are done, transform FN.  */
+      fn = build_non_dependent_expr (fn);
+    }
 
   /* A qualified name corresponding to a bound pointer-to-member is
      represented as an OFFSET_REF:
@@ -2958,79 +3005,18 @@ build_offset_ref_call_from_tree (tree fn, tree args)
        struct B { void g(); };
        void (B::*p)();
        void B::g() { (this->*p)(); }  */
-  if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
-    /* This case should now be handled elsewhere.  */
-    abort ();
-  else
+  if (TREE_CODE (fn) == OFFSET_REF)
     {
       object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
       fn = TREE_OPERAND (fn, 1);
       fn = get_member_function_from_ptrfunc (&object_addr, fn);
       args = tree_cons (NULL_TREE, object_addr, args);
     }
-  return build_function_call (fn, args);
-}
-
-/* FN indicates the function to call.  Name resolution has been
-   performed on FN.  ARGS are the arguments to the function.  They
-   have already been semantically analyzed.  DISALLOW_VIRTUAL is true
-   if the function call should be determined at compile time, even if
-   FN is virtual.  */
-
-tree
-build_call_from_tree (tree fn, tree args, bool disallow_virtual)
-{
-  tree template_args;
-  tree template_id;
-  tree f;
-  
-  /* Check to see that name lookup has already been performed.  */
-  my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725);
-  my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725);
-
-  /* In the future all of this should be eliminated.  Instead,
-     name-lookup for a member function should simply return a
-     baselink, instead of a FUNCTION_DECL, TEMPLATE_DECL, or
-     TEMPLATE_ID_EXPR.  */
-
-  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
-    {
-      template_id = fn;
-      template_args = TREE_OPERAND (fn, 1);
-      fn = TREE_OPERAND (fn, 0);
-    }
-  else
-    {
-      template_id = NULL_TREE;
-      template_args = NULL_TREE;
-    }
-
-  f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn;
-  /* Make sure we have a baselink (rather than simply a
-     FUNCTION_DECL) for a member function.  */
-  if (current_class_type
-      && ((TREE_CODE (f) == FUNCTION_DECL
-          && DECL_FUNCTION_MEMBER_P (f))
-         || (DECL_FUNCTION_TEMPLATE_P (f) 
-             && DECL_FUNCTION_MEMBER_P (f))))
-    {
-      f = lookup_member (current_class_type, DECL_NAME (f), 
-                        /*protect=*/1, /*want_type=*/false);
-      if (f)
-       fn = f;
-    }
-
-  if (template_id)
-    {
-      if (BASELINK_P (fn))
-         BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR, 
-                                             BASELINK_FUNCTIONS (fn),
-                                             template_args);
-      else
-       fn = template_id;
-    }
 
-  return finish_call_expr (fn, args, disallow_virtual);
+  expr = build_function_call (fn, args);
+  if (processing_template_decl && expr != error_mark_node)
+    return build_min (CALL_EXPR, TREE_TYPE (expr), orig_fn, orig_args);
+  return expr;
 }
 
 /* Returns true if ROOT (a namespace, class, or function) encloses
index a9f5b15834accd3ee7c1733971213c9af0519f8e..79803d2dfff91ed38ad13b59088a0d565f82a6ec 100644 (file)
@@ -988,6 +988,10 @@ dump_decl (tree t, int flags)
       dump_decl (BASELINK_FUNCTIONS (t), flags);
       break;
 
+    case NON_DEPENDENT_EXPR:
+      dump_expr (t, flags);
+      break;
+
     default:
       sorry_for_unsupported_tree (t);
       /* Fallthrough to error.  */
@@ -2028,7 +2032,11 @@ dump_expr (tree t, int flags)
       dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
       break;
 
-      /* else fall through */
+    case NON_DEPENDENT_EXPR:
+      output_add_string (scratch_buffer, "<expression of type ");
+      dump_type (TREE_TYPE (t), flags);
+      output_add_character (scratch_buffer, '>');
+      break;
 
       /*  This list is incomplete, but should suffice for now.
          It is very important that `sorry' does not call
index f89b4248e65fa37b71c5359532212afda3b462ad..4a11b4319fa32e2ca9bb9d576f90b765909c352a 100644 (file)
@@ -1337,157 +1337,6 @@ get_type_value (tree name)
     return NULL_TREE;
 }
 
-\f
-/* This code could just as well go in `class.c', but is placed here for
-   modularity.  */
-
-/* For an expression of the form TYPE :: NAME (PARMLIST), build
-   the appropriate function call.  */
-
-tree
-build_member_call (tree type, tree name, tree parmlist)
-{
-  tree t;
-  tree method_name;
-  tree fns;
-  int dtor = 0;
-  tree basetype_path, decl;
-
-  if (TREE_CODE (name) == TEMPLATE_ID_EXPR
-      && TREE_CODE (type) == NAMESPACE_DECL)
-    {
-      /* 'name' already refers to the decls from the namespace, since we
-        hit do_identifier for template_ids.  */
-      method_name = TREE_OPERAND (name, 0);
-      /* FIXME: Since we don't do independent names right yet, the
-        name might also be a LOOKUP_EXPR. Once we resolve this to a
-        real decl earlier, this can go. This may happen during
-        tsubst'ing.  */
-      if (TREE_CODE (method_name) == LOOKUP_EXPR)
-       {
-         method_name = lookup_namespace_name 
-           (type, TREE_OPERAND (method_name, 0));
-         TREE_OPERAND (name, 0) = method_name;
-       }
-      my_friendly_assert (is_overloaded_fn (method_name), 980519);
-      return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
-    }
-
-  if (DECL_P (name))
-    name = DECL_NAME (name);
-
-  if (TREE_CODE (type) == NAMESPACE_DECL)
-    return finish_call_expr (lookup_namespace_name (type, name),
-                            parmlist,
-                            /*disallow_virtual=*/true);
-
-  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-    {
-      method_name = TREE_OPERAND (name, 0);
-      if (TREE_CODE (method_name) == COMPONENT_REF)
-       method_name = TREE_OPERAND (method_name, 1);
-      if (is_overloaded_fn (method_name))
-       method_name = DECL_NAME (OVL_CURRENT (method_name));
-      TREE_OPERAND (name, 0) = method_name;
-    }
-  else
-    method_name = name;
-
-  if (TREE_CODE (method_name) == BIT_NOT_EXPR)
-    {
-      method_name = TREE_OPERAND (method_name, 0);
-      dtor = 1;
-    }
-
-  /* This shouldn't be here, and build_member_call shouldn't appear in
-     parse.y!  (mrs)  */
-  if (type && TREE_CODE (type) == IDENTIFIER_NODE
-      && get_aggr_from_typedef (type, 0) == 0)
-    {
-      tree ns = lookup_name (type, 0);
-      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
-       return finish_call_expr (lookup_namespace_name (ns, name),
-                                parmlist,
-                                /*disallow_virtual=*/true);
-    }
-
-  if (type == NULL_TREE || ! is_aggr_type (type, 1))
-    return error_mark_node;
-
-  /* An operator we did not like.  */
-  if (name == NULL_TREE)
-    return error_mark_node;
-
-  if (dtor)
-    {
-      error ("cannot call destructor `%T::~%T' without object", type,
-               method_name);
-      return error_mark_node;
-    }
-
-  decl = maybe_dummy_object (type, &basetype_path);
-
-  fns = lookup_fnfields (basetype_path, method_name, 0);
-  if (fns)
-    {
-      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-       BASELINK_FUNCTIONS (fns) = build_nt (TEMPLATE_ID_EXPR,
-                                            BASELINK_FUNCTIONS (fns),
-                                            TREE_OPERAND (name, 1));
-      return build_new_method_call (decl, fns, parmlist,
-                                   /*conversion_path=*/NULL_TREE,
-                                   LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
-    }
-
-  /* Convert 'this' to the specified type to disambiguate conversion
-     to the function's context.  */
-  if (decl == current_class_ref
-      /* ??? this is wrong, but if this conversion is invalid we need to
-        defer it until we know whether we are calling a static or
-        non-static member function.  Be conservative for now.  */
-      && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
-    {
-      basetype_path = NULL_TREE;
-      decl = build_scoped_ref (decl, type, &basetype_path);
-      if (decl == error_mark_node)
-       return error_mark_node;
-    }
-
-  if (constructor_name_p (method_name, type))
-    return build_functional_cast (type, parmlist);
-  if (TREE_CODE (name) == IDENTIFIER_NODE
-      && ((t = lookup_field (TYPE_BINFO (type), name, 1, false))))
-    {
-      if (t == error_mark_node)
-       return error_mark_node;
-      if (TREE_CODE (t) == FIELD_DECL)
-       {
-         if (is_dummy_object (decl))
-           {
-             error ("invalid use of non-static field `%D'", t);
-             return error_mark_node;
-           }
-         decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);
-       }
-      else if (TREE_CODE (t) == VAR_DECL)
-       decl = t;
-      else
-       {
-         error ("invalid use of member `%D'", t);
-         return error_mark_node;
-       }
-      if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
-       return build_new_op (CALL_EXPR, LOOKUP_NORMAL, decl,
-                            parmlist, NULL_TREE);
-      return build_function_call (decl, parmlist);
-    }
-  else
-    {
-      error ("no method `%T::%D'", type, name);
-      return error_mark_node;
-    }
-}
-
 /* Build a reference to a member of an aggregate.  This is not a
    C++ `&', but really something which can have its address taken,
    and then act as a pointer to member, for example TYPE :: FIELD
index 63c58baf059e2ed638731804f2e58098cc54886b..29fd523c7271d113f2f7ac803019baa4f5a4f30e 100644 (file)
@@ -2019,6 +2019,19 @@ write_expression (tree expr)
          write_type (TREE_OPERAND (expr, 0));
          if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
            write_source_name (TREE_OPERAND (expr, 1));
+         else if (TREE_CODE (TREE_OPERAND (expr, 1)) == TEMPLATE_ID_EXPR)
+           {
+             tree template_id;
+             tree name;
+
+             template_id = TREE_OPERAND (expr, 1);
+             name = TREE_OPERAND (template_id, 0);
+             /* FIXME: What about operators?  */
+             my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE,
+                                 20030707);
+             write_source_name (TREE_OPERAND (template_id, 0));
+             write_template_args (TREE_OPERAND (template_id, 1));
+           }
          else
            {
              /* G++ 3.2 incorrectly put out both the "sr" code and
index 27e73cb967fa7af638170a79585e72e66920065d..19f55f40a8e706b83b66da520698991cbb751ef3 100644 (file)
@@ -1651,6 +1651,8 @@ static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
+static tree cp_parser_fold_non_dependent_expr
+  (tree);
 static bool cp_parser_friend_p
   (tree);
 static cp_token *cp_parser_require
@@ -1661,6 +1663,8 @@ static bool cp_parser_token_starts_function_definition_p
   (cp_token *);
 static bool cp_parser_next_token_starts_class_definition_p
   (cp_parser *);
+static bool cp_parser_next_token_ends_template_argument_p
+  (cp_parser *);
 static enum tag_types cp_parser_token_is_class_key
   (cp_token *);
 static void cp_parser_check_class_key
@@ -2381,7 +2385,6 @@ cp_parser_primary_expression (cp_parser *parser,
          cp_parser_error (parser, "expected primary-expression");
          return error_mark_node;
        }
-      /* Fall through.  */
 
       /* An id-expression can start with either an identifier, a
         `::' as the beginning of a qualified-id, or the "operator"
@@ -2600,30 +2603,7 @@ cp_parser_primary_expression (cp_parser *parser,
                if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
                  {
                    tree args = TREE_OPERAND (fns, 1);
-
-                   if (args && TREE_CODE (args) == TREE_LIST)
-                     {
-                       while (args)
-                         {
-                           if (dependent_template_arg_p (TREE_VALUE (args)))
-                             {
-                               dependent_p = true;
-                               break;
-                             }
-                           args = TREE_CHAIN (args);
-                         }
-                     }
-                   else if (args && TREE_CODE (args) == TREE_VEC)
-                     {
-                       int i; 
-                       for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
-                         if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
-                           {
-                             dependent_p = true;
-                             break;
-                           }
-                     }
-
+                   dependent_p = any_dependent_template_arguments_p (args);
                    /* The functions are those referred to by the
                       template-id.  */
                    fns = TREE_OPERAND (fns, 0);
@@ -2687,27 +2667,34 @@ cp_parser_primary_expression (cp_parser *parser,
            /* Only certain kinds of names are allowed in constant
               expression.  Enumerators have already been handled
               above.  */
-           if (parser->constant_expression_p
+           if (parser->constant_expression_p)
+             {
                /* Non-type template parameters of integral or
-                  enumeration type.  */
-               && !(TREE_CODE (decl) == TEMPLATE_PARM_INDEX
-                    && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
+                  enumeration type are OK.  */
+               if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
+                   && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
+                 ;
                /* Const variables or static data members of integral
                   or enumeration types initialized with constant
-                   expressions (or dependent expressions - in this case
-                   the check will be done at instantiation time).  */
-               && !(TREE_CODE (decl) == VAR_DECL
-                    && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
-                    && DECL_INITIAL (decl)
-                     && (TREE_CONSTANT (DECL_INITIAL (decl))
-                         || type_dependent_expression_p 
-                         (DECL_INITIAL (decl))
-                         || value_dependent_expression_p 
-                         (DECL_INITIAL (decl)))))
-             {
-               if (!parser->allow_non_constant_expression_p)
-                 return cp_parser_non_constant_id_expression (decl);
-               parser->non_constant_expression_p = true;
+                   expressions are OK.  We also accept dependent
+                  initializers; they may turn out to be constant at
+                  instantiation-time.  */
+               else if (TREE_CODE (decl) == VAR_DECL
+                        && CP_TYPE_CONST_P (TREE_TYPE (decl))
+                        && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
+                        && DECL_INITIAL (decl)
+                        && (TREE_CONSTANT (DECL_INITIAL (decl))
+                            || type_dependent_expression_p (DECL_INITIAL 
+                                                            (decl))
+                            || value_dependent_expression_p (DECL_INITIAL 
+                                                             (decl))))
+                 ;
+               else
+                 {
+                   if (!parser->allow_non_constant_expression_p)
+                     return cp_parser_non_constant_id_expression (decl);
+                   parser->non_constant_expression_p = true;
+                 }
              }
 
            if (parser->scope)
@@ -3792,7 +3779,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                    || TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
                && args)
              {
-               tree arg;
                tree identifier = NULL_TREE;
                tree functions = NULL_TREE;
 
@@ -3815,10 +3801,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 
                   Do Koenig lookup -- unless any of the arguments are
                   type-dependent.  */
-               for (arg = args; arg; arg = TREE_CHAIN (arg))
-                 if (type_dependent_expression_p (TREE_VALUE (arg)))
-                     break;
-               if (!arg)
+               if (!any_type_dependent_arguments_p (args))
                  {
                    postfix_expression 
                      = lookup_arg_dependent (identifier, functions, args);
@@ -3827,14 +3810,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                        /* The unqualified name could not be resolved.  */
                        unqualified_name_lookup_error (identifier);
                        postfix_expression = error_mark_node;
+                       break;
                      }
-                   postfix_expression
-                     = build_call_from_tree (postfix_expression, args, 
-                                             /*diallow_virtual=*/false);
-                   break;
                  }
-               postfix_expression = build_min_nt (LOOKUP_EXPR,
-                                                  identifier);
+               else
+                 postfix_expression = build_min_nt (LOOKUP_EXPR,
+                                                    identifier);
              }
            else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED 
                     && TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
@@ -3845,25 +3826,31 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                break;
              }
 
-           /* In the body of a template, no further processing is
-              required.  */
-           if (processing_template_decl)
+           if (TREE_CODE (postfix_expression) == COMPONENT_REF)
              {
-               postfix_expression = build_nt (CALL_EXPR,
-                                              postfix_expression, 
-                                              args);
-               break;
+               tree instance = TREE_OPERAND (postfix_expression, 0);
+               tree fn = TREE_OPERAND (postfix_expression, 1);
+
+               if (processing_template_decl
+                   && (type_dependent_expression_p (instance)
+                       || (!BASELINK_P (fn)
+                           && TREE_CODE (fn) != FIELD_DECL)
+                       || any_type_dependent_arguments_p (args)))
+                 {
+                   postfix_expression
+                     = build_min_nt (CALL_EXPR, postfix_expression, args);
+                   break;
+                 }
+                 
+               postfix_expression
+                 = (build_new_method_call 
+                    (instance, fn, args, NULL_TREE, 
+                     (idk == CP_PARSER_ID_KIND_QUALIFIED 
+                      ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
              }
-
-           if (TREE_CODE (postfix_expression) == COMPONENT_REF)
-             postfix_expression
-               = (build_new_method_call 
-                  (TREE_OPERAND (postfix_expression, 0),
-                   TREE_OPERAND (postfix_expression, 1),
-                   args, NULL_TREE, 
-                   (idk == CP_PARSER_ID_KIND_QUALIFIED 
-                    ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
-           else if (TREE_CODE (postfix_expression) == OFFSET_REF)
+           else if (TREE_CODE (postfix_expression) == OFFSET_REF
+                    || TREE_CODE (postfix_expression) == MEMBER_REF
+                    || TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
              postfix_expression = (build_offset_ref_call_from_tree
                                    (postfix_expression, args));
            else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
@@ -3967,8 +3954,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                      struct X { void f(); };
                      template <typename T> void f(T* t) { t->X::f(); }
  
-                   Even though "t" is dependent, "X::f" is not and has 
-                  except that for a BASELINK there is no need to
+                   Even though "t" is dependent, "X::f" is not and has
+                  been resolved to a BASELINK; there is no need to
                   include scope information.  */
 
                /* But we do need to remember that there was an explicit
@@ -4336,7 +4323,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
          return build_x_indirect_ref (cast_expression, "unary *");
          
        case ADDR_EXPR:
-         return build_x_unary_op (ADDR_EXPR, cast_expression);
+       case BIT_NOT_EXPR:
+         return build_x_unary_op (unary_operator, cast_expression);
          
        case PREINCREMENT_EXPR:
        case PREDECREMENT_EXPR:
@@ -4354,9 +4342,6 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
        case TRUTH_NOT_EXPR:
          return finish_unary_op_expr (unary_operator, cast_expression);
 
-       case BIT_NOT_EXPR:
-         return build_x_unary_op (BIT_NOT_EXPR, cast_expression);
-
        default:
          abort ();
          return error_mark_node;
@@ -5293,7 +5278,6 @@ static tree
 cp_parser_expression (cp_parser* parser)
 {
   tree expression = NULL_TREE;
-  bool saw_comma_p = false;
 
   while (true)
     {
@@ -5306,45 +5290,23 @@ cp_parser_expression (cp_parser* parser)
         save it away.  */
       if (!expression)
        expression = assignment_expression;
-      /* Otherwise, chain the expressions together.  It is unclear why
-        we do not simply build COMPOUND_EXPRs as we go.  */
       else
-       expression = tree_cons (NULL_TREE, 
-                               assignment_expression,
-                               expression);
+       expression = build_x_compound_expr (expression,
+                                           assignment_expression);
       /* If the next token is not a comma, then we are done with the
         expression.  */
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
        break;
       /* Consume the `,'.  */
       cp_lexer_consume_token (parser->lexer);
-      /* The first time we see a `,', we must take special action
-        because the representation used for a single expression is
-        different from that used for a list containing the single
-        expression.  */
-      if (!saw_comma_p)
-       {
-         /* Remember that this expression has a `,' in it.  */
-         saw_comma_p = true;
-         /* Turn the EXPRESSION into a TREE_LIST so that we can link
-            additional expressions to it.  */
-         expression = build_tree_list (NULL_TREE, expression);
-       }
-    }
-
-  /* Build a COMPOUND_EXPR to represent the entire expression, if
-     necessary.  We built up the list in reverse order, so we must
-     straighten it out here.  */
-  if (saw_comma_p)
-    {
       /* A comma operator cannot appear in a constant-expression.  */
       if (parser->constant_expression_p)
        {
          if (!parser->allow_non_constant_expression_p)
-           return cp_parser_non_constant_expression ("a comma operator");
+           expression 
+             = cp_parser_non_constant_expression ("a comma operator");
          parser->non_constant_expression_p = true;
        }
-      expression = build_x_compound_expr (nreverse (expression));
     }
 
   return expression;
@@ -5356,8 +5318,9 @@ cp_parser_expression (cp_parser* parser)
      conditional-expression  
 
   If ALLOW_NON_CONSTANT_P a non-constant expression is silently
-  accepted.  In that case *NON_CONSTANT_P is set to TRUE.  If
-  ALLOW_NON_CONSTANT_P is false, NON_CONSTANT_P should be NULL.  */
+  accepted.  If ALLOW_NON_CONSTANT_P is true and the expression is not
+  constant, *NON_CONSTANT_P is set to TRUE.  If ALLOW_NON_CONSTANT_P
+  is false, NON_CONSTANT_P should be NULL.  */
 
 static tree
 cp_parser_constant_expression (cp_parser* parser, 
@@ -5547,7 +5510,7 @@ cp_parser_labeled_statement (cp_parser* parser)
        cp_lexer_consume_token (parser->lexer);
        /* Parse the constant-expression.  */
        expr = cp_parser_constant_expression (parser, 
-                                             /*allow_non_constant=*/false,
+                                             /*allow_non_constant_p=*/false,
                                              NULL);
        /* Create the label.  */
        statement = finish_case_label (expr, NULL_TREE);
@@ -8051,13 +8014,21 @@ cp_parser_template_argument_list (cp_parser* parser)
    The representation is that of an assignment-expression, type-id, or
    id-expression -- except that the qualified id-expression is
    evaluated, so that the value returned is either a DECL or an
-   OVERLOAD.  */
+   OVERLOAD.  
+
+   Although the standard says "assignment-expression", it forbids
+   throw-expressions or assignments in the template argument.
+   Therefore, we use "conditional-expression" instead.  */
 
 static tree
 cp_parser_template_argument (cp_parser* parser)
 {
   tree argument;
   bool template_p;
+  bool address_p;
+  cp_token *token;
+  cp_parser_id_kind idk;
+  tree qualifying_class;
 
   /* There's really no way to know what we're looking at, so we just
      try each alternative in order.  
@@ -8073,8 +8044,7 @@ cp_parser_template_argument (cp_parser* parser)
   argument = cp_parser_type_id (parser);
   /* If the next token isn't a `,' or a `>', then this argument wasn't
      really finished.  */
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
-      && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER))
+  if (!cp_parser_next_token_ends_template_argument_p (parser))
     cp_parser_error (parser, "expected template-argument");
   /* If that worked, we're done.  */
   if (cp_parser_parse_definitely (parser))
@@ -8088,8 +8058,7 @@ cp_parser_template_argument (cp_parser* parser)
                                      &template_p);
   /* If the next token isn't a `,' or a `>', then this argument wasn't
      really finished.  */
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
-      && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER))
+  if (!cp_parser_next_token_ends_template_argument_p (parser))
     cp_parser_error (parser, "expected template-argument");
   if (!cp_parser_error_occurred (parser))
     {
@@ -8104,8 +8073,101 @@ cp_parser_template_argument (cp_parser* parser)
     }
   if (cp_parser_parse_definitely (parser))
     return argument;
-  /* It must be an assignment-expression.  */
-  return cp_parser_assignment_expression (parser);
+  /* It must be a non-type argument.  There permitted cases are given
+     in [temp.arg.nontype]:
+
+     -- an integral constant-expression of integral or enumeration
+        type; or
+
+     -- the name of a non-type template-parameter; or
+
+     -- the name of an object or function with external linkage...
+
+     -- the address of an object or function with external linkage...
+
+     -- a pointer to member... */
+  /* Look for a non-type template parameter.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      cp_parser_parse_tentatively (parser);
+      argument = cp_parser_primary_expression (parser,
+                                              &idk,
+                                              &qualifying_class);
+      if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
+         || !cp_parser_next_token_ends_template_argument_p (parser))
+       cp_parser_simulate_error (parser);
+      if (cp_parser_parse_definitely (parser))
+       return argument;
+    }
+  /* If the next token is "&", the argument must be the address of an
+     object or function with external linkage.  */
+  address_p = cp_lexer_next_token_is (parser->lexer, CPP_AND);
+  if (address_p)
+    cp_lexer_consume_token (parser->lexer);
+  /* See if we might have an id-expression.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_NAME
+      || token->keyword == RID_OPERATOR
+      || token->type == CPP_SCOPE
+      || token->type == CPP_TEMPLATE_ID
+      || token->type == CPP_NESTED_NAME_SPECIFIER)
+    {
+      cp_parser_parse_tentatively (parser);
+      argument = cp_parser_primary_expression (parser,
+                                              &idk,
+                                              &qualifying_class);
+      if (cp_parser_error_occurred (parser)
+         || !cp_parser_next_token_ends_template_argument_p (parser))
+       cp_parser_abort_tentative_parse (parser);
+      else
+       {
+         if (qualifying_class)
+           argument = finish_qualified_id_expr (qualifying_class,
+                                                argument,
+                                                /*done=*/true,
+                                                address_p);
+         if (TREE_CODE (argument) == VAR_DECL)
+           {
+             /* A variable without external linkage might still be a
+                valid constant-expression, so no error is issued here
+                if the external-linkage check fails.  */
+             if (!DECL_EXTERNAL_LINKAGE_P (argument))
+               cp_parser_simulate_error (parser);
+           }
+         else if (is_overloaded_fn (argument))
+           /* All overloaded functions are allowed; if the external
+              linkage test does not pass, an error will be issued
+              later.  */
+           ;
+         else if (address_p
+                  && (TREE_CODE (argument) == OFFSET_REF 
+                      || TREE_CODE (argument) == SCOPE_REF))
+           /* A pointer-to-member.  */
+           ;
+         else
+           cp_parser_simulate_error (parser);
+
+         if (cp_parser_parse_definitely (parser))
+           {
+             if (address_p)
+               argument = build_x_unary_op (ADDR_EXPR, argument);
+             return argument;
+           }
+       }
+    }
+  /* If the argument started with "&", there are no other valid
+     alternatives at this point.  */
+  if (address_p)
+    {
+      cp_parser_error (parser, "invalid non-type template argument");
+      return error_mark_node;
+    }
+  /* The argument must be a constant-expression. */
+  argument = cp_parser_constant_expression (parser, 
+                                           /*allow_non_constant_p=*/false,
+                                           /*non_constant_p=*/NULL);
+  /* If it's non-dependent, simplify it.  */
+  return cp_parser_fold_non_dependent_expr (argument);
 }
 
 /* Parse an explicit-instantiation.
@@ -8914,7 +8976,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
       cp_lexer_consume_token (parser->lexer);
       /* Parse the value.  */
       value = cp_parser_constant_expression (parser, 
-                                            /*allow_non_constant=*/false,
+                                            /*allow_non_constant_p=*/false,
                                             NULL);
     }
   else
@@ -9919,29 +9981,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = cp_parser_constant_expression (parser,
                                                 /*allow_non_constant=*/true,
                                                 &non_constant_p);
-             /* If we're in a template, but the constant-expression
-                isn't value dependent, simplify it.  We're supposed
-                to treat:
-
-                  template <typename T> void f(T[1 + 1]);
-                  template <typename T> void f(T[2]);
-                  
-                as two declarations of the same function, for
-                example.  */
-             if (processing_template_decl
-                 && !non_constant_p
-                 && !value_dependent_expression_p (bounds))
-               {
-                 HOST_WIDE_INT saved_processing_template_decl;
-
-                 saved_processing_template_decl = processing_template_decl;
-                 processing_template_decl = 0;
-                 bounds = tsubst_copy_and_build (bounds, 
-                                                 /*args=*/NULL_TREE,
-                                                 tf_error,
-                                                 /*in_decl=*/NULL_TREE);
-                 processing_template_decl = saved_processing_template_decl;
-               }
+             if (!non_constant_p)
+               bounds = cp_parser_fold_non_dependent_expr (bounds);
            }
          else
            bounds = NULL_TREE;
@@ -14129,6 +14170,36 @@ cp_parser_declares_only_class_p (cp_parser *parser)
          || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
+/* Simplify EXPR if it is a non-dependent expression.  Returns the
+   (possibly simplified) expression.  */
+
+static tree
+cp_parser_fold_non_dependent_expr (tree expr)
+{
+  /* If we're in a template, but EXPR isn't value dependent, simplify
+     it.  We're supposed to treat:
+     
+       template <typename T> void f(T[1 + 1]);
+       template <typename T> void f(T[2]);
+                  
+     as two declarations of the same function, for example.  */
+  if (processing_template_decl
+      && !type_dependent_expression_p (expr)
+      && !value_dependent_expression_p (expr))
+    {
+      HOST_WIDE_INT saved_processing_template_decl;
+
+      saved_processing_template_decl = processing_template_decl;
+      processing_template_decl = 0;
+      expr = tsubst_copy_and_build (expr,
+                                   /*args=*/NULL_TREE,
+                                   tf_error,
+                                   /*in_decl=*/NULL_TREE);
+      processing_template_decl = saved_processing_template_decl;
+    }
+  return expr;
+}
+
 /* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
    Returns TRUE iff `friend' appears among the DECL_SPECIFIERS.  */
 
@@ -14274,6 +14345,18 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
   return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
 }
 
+/* Returns TRUE iff the next token is the "," or ">" ending a
+   template-argument.  */
+
+static bool
+cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
+{
+  cp_token *token;
+
+  token = cp_lexer_peek_token (parser->lexer);
+  return (token->type == CPP_COMMA || token->type == CPP_GREATER);
+}
 /* Returns the kind of tag indicated by TOKEN, if it is a class-key,
    or none_type otherwise.  */
 
index abb51b25b7d4992326db6686cfb154fe18b81163..4d650c5e23d030153b57036f052f2adc1ecddef1 100644 (file)
@@ -167,7 +167,6 @@ static void copy_default_args_to_explicit_spec (tree);
 static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
 static int eq_local_specializations (const void *, const void *);
 static bool dependent_type_p_r (tree);
-static bool dependent_template_id_p (tree, tree);
 static tree tsubst (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
@@ -3594,9 +3593,6 @@ convert_template_argument (tree parm,
       if (invalid_nontype_parm_type_p (t, complain))
         return error_mark_node;
       
-      if (processing_template_decl)
-       arg = maybe_fold_nontype_arg (arg);
-
       if (!uses_template_parms (arg) && !uses_template_parms (t))
        /* We used to call digest_init here.  However, digest_init
           will report errors, which we don't want when complain
@@ -7108,9 +7104,8 @@ tsubst_baselink (tree baselink, tree object_type,
        template_id_p = true;
        template_args = TREE_OPERAND (fns, 1);
        fns = TREE_OPERAND (fns, 0);
-       template_args = tsubst_copy (template_args, args,
-                                    complain, in_decl);
-       maybe_fold_nontype_args (template_args);
+       template_args = tsubst_copy_and_build (template_args, args,
+                                              complain, in_decl);
       }
     name = DECL_NAME (get_first_fn (fns));
     baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
@@ -8003,30 +7998,17 @@ tsubst_copy_and_build (tree t,
 
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      if (TREE_TYPE (t))
-       return tsubst_copy (t, args, complain, in_decl);
-      else
-       return build_x_unary_op
-         (TREE_CODE (t),
-          tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
-                                 in_decl));
-
     case NEGATE_EXPR:
     case BIT_NOT_EXPR:
-      if (TREE_TYPE (t))
-       return tsubst_copy (t, args, complain, in_decl);
-      else
-       return build_x_unary_op
-         (TREE_CODE (t),
-          tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
-                                 in_decl));
-
     case ABS_EXPR:
-      if (TREE_TYPE (t))
-       return t;
-      return build_x_unary_op
-       (TREE_CODE (t),
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+    case TRUTH_NOT_EXPR:
+    case CONVERT_EXPR:  /* Unary + */
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      return (build_x_unary_op
+             (TREE_CODE (t),
+              tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                     in_decl)));
 
     case ADDR_EXPR:
       op1 = TREE_OPERAND (t, 0);
@@ -8037,18 +8019,6 @@ tsubst_copy_and_build (tree t,
        op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
       return build_x_unary_op (ADDR_EXPR, op1);
 
-    case TRUTH_NOT_EXPR:
-    case CONVERT_EXPR:  /* Unary + */
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-      if (TREE_TYPE (t))
-       return tsubst_copy (t, args, complain, in_decl);
-      else
-       return build_x_unary_op
-         (TREE_CODE (t),
-          tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
-                                 in_decl));
-
     case PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR:
@@ -8119,15 +8089,25 @@ tsubst_copy_and_build (tree t,
 
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
-      {
-       tree r =
-         tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
-       if (!TYPE_P (r))
-         return TREE_CODE (t) == SIZEOF_EXPR ?
-           expr_sizeof (r) : c_alignof_expr (r);
-       else
-         return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
-      }
+      op1 = TREE_OPERAND (t, 0);
+      if (!args)
+       {
+         /* When there are no ARGS, we are trying to evaluate a
+            non-dependent expression from the parser.  Trying to do
+            the substitutions may not work.  */
+         if (!TYPE_P (op1))
+           op1 = TREE_TYPE (op1);
+       }
+      else
+       {
+         ++skip_evaluation;
+         op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+         --skip_evaluation;
+       }
+      if (TREE_CODE (t) == SIZEOF_EXPR)
+       return finish_sizeof (op1);
+      else
+       return finish_alignof (op1);
 
     case MODOP_EXPR:
       return build_x_modify_expr
@@ -8162,15 +8142,11 @@ tsubst_copy_and_build (tree t,
        DELETE_EXPR_USE_GLOBAL (t));
 
     case COMPOUND_EXPR:
-      {
-       if (tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl)
-           == NULL_TREE)
-         return build_x_compound_expr
-           (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
-                                   in_decl));
-       else
-         abort ();
-      }
+      return (build_x_compound_expr
+             (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, 
+                                     in_decl),
+              tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, 
+                                     in_decl)));
 
     case CALL_EXPR:
       {
@@ -8210,25 +8186,23 @@ tsubst_copy_and_build (tree t,
                                           complain, in_decl);
          
        if (BASELINK_P (function))
-         return build_call_from_tree (function, call_args, 1);
-       else
-         {
-           if (call_args != NULL_TREE && koenig_name)
-             function = lookup_arg_dependent (koenig_name,
-                                              function, 
-                                              call_args);
-
-           if (TREE_CODE (function) == OFFSET_REF)
-             return build_offset_ref_call_from_tree (function, call_args);
-           if (TREE_CODE (function) == COMPONENT_REF)
-             return (build_new_method_call 
-                     (TREE_OPERAND (function, 0),
-                      TREE_OPERAND (function, 1),
-                      call_args, NULL_TREE, 
-                      qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
-           return finish_call_expr (function, call_args, 
-                                    /*disallow_virtual=*/qualified_p);
-         }
+         qualified_p = 1;
+
+       if (call_args != NULL_TREE && koenig_name)
+         function = lookup_arg_dependent (koenig_name,
+                                          function, 
+                                          call_args);
+
+       if (TREE_CODE (function) == OFFSET_REF)
+         return build_offset_ref_call_from_tree (function, call_args);
+       if (TREE_CODE (function) == COMPONENT_REF)
+         return (build_new_method_call 
+                 (TREE_OPERAND (function, 0),
+                  TREE_OPERAND (function, 1),
+                  call_args, NULL_TREE, 
+                  qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+       return finish_call_expr (function, call_args, 
+                                /*disallow_virtual=*/qualified_p);
       }
 
     case COND_EXPR:
@@ -8389,6 +8363,11 @@ tsubst_copy_and_build (tree t,
     case VAR_DECL:
       if (args)
        t = tsubst_copy (t, args, complain, in_decl);
+      else
+       /* If there are no ARGS, then we are evaluating a
+          non-dependent expression.  If the expression is
+          non-dependent, the variable must be a constant.  */
+       t = DECL_INITIAL (t);
       return convert_from_reference (t);
 
     case VA_ARG_EXPR:
@@ -11491,26 +11470,46 @@ value_dependent_expression_p (tree expression)
      with an expression that is value-dependent.  */
   if (TREE_CODE (expression) == VAR_DECL
       && DECL_INITIAL (expression)
-      && INTEGRAL_OR_ENUMERATION_TYPE_P (expression)
+      && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
       && value_dependent_expression_p (DECL_INITIAL (expression)))
     return true;
   /* These expressions are value-dependent if the type to which the
      cast occurs is dependent or the expression being casted is
      value-dependent.  */
-  if ((TREE_CODE (expression) == DYNAMIC_CAST_EXPR
-       || TREE_CODE (expression) == STATIC_CAST_EXPR
-       || TREE_CODE (expression) == CONST_CAST_EXPR
-       || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
-       || TREE_CODE (expression) == CAST_EXPR)
-      && (dependent_type_p (TREE_TYPE (expression))
-   || value_dependent_expression_p (TREE_OPERAND (expression, 0))))
-    return true;
-  /* A `sizeof' expression where the sizeof operand is a type is
-     value-dependent if the type is dependent.  If the type was not
-     dependent, we would no longer have a SIZEOF_EXPR, so any
-     SIZEOF_EXPR is dependent.  */
-  if (TREE_CODE (expression) == SIZEOF_EXPR)
-    return true;
+  if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
+      || TREE_CODE (expression) == STATIC_CAST_EXPR
+      || TREE_CODE (expression) == CONST_CAST_EXPR
+      || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
+      || TREE_CODE (expression) == CAST_EXPR)
+    {
+      if (dependent_type_p (TREE_TYPE (expression)))
+       return true;
+      /* A functional cast has a list of operands.  */
+      expression = TREE_OPERAND (expression, 0);
+      if (TREE_CODE (expression) == TREE_LIST)
+       {
+         do
+           {
+             if (value_dependent_expression_p (TREE_VALUE (expression)))
+               return true;
+             expression = TREE_CHAIN (expression);
+           }
+         while (expression);
+         return false;
+       }
+      else
+       return value_dependent_expression_p (expression);
+    }
+  /* A `sizeof' expression is value-dependent if the operand is
+     type-dependent.  */
+  if (TREE_CODE (expression) == SIZEOF_EXPR
+      || TREE_CODE (expression) == ALIGNOF_EXPR)
+    {
+      expression = TREE_OPERAND (expression, 0);
+      if (TYPE_P (expression))
+       return dependent_type_p (expression);
+      return type_dependent_expression_p (expression);
+    }
   /* A constant expression is value-dependent if any subexpression is
      value-dependent.  */
   if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
@@ -11574,10 +11573,11 @@ type_dependent_expression_p (tree expression)
       || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
       || TREE_CODE (expression) == CAST_EXPR)
     return dependent_type_p (TREE_TYPE (expression));
+
   /* The types of these expressions depends only on the type created
      by the expression.  */
-  else if (TREE_CODE (expression) == NEW_EXPR
-          || TREE_CODE (expression) == VEC_NEW_EXPR)
+  if (TREE_CODE (expression) == NEW_EXPR
+      || TREE_CODE (expression) == VEC_NEW_EXPR)
     {
       /* For NEW_EXPR tree nodes created inside a template, either
         the object type itself or a TREE_LIST may appear as the
@@ -11601,12 +11601,53 @@ type_dependent_expression_p (tree expression)
           INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
     return true;
 
+  if (TREE_TYPE (expression) == unknown_type_node)
+    {
+      if (TREE_CODE (expression) == ADDR_EXPR)
+       return type_dependent_expression_p (TREE_OPERAND (expression, 0));
+      if (TREE_CODE (expression) == BASELINK)
+       expression = BASELINK_FUNCTIONS (expression);
+      if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
+       {
+         if (any_dependent_template_arguments_p (TREE_OPERAND (expression, 
+                                                               1)))
+           return true;
+         expression = TREE_OPERAND (expression, 0);
+       }
+      if (TREE_CODE (expression) == OVERLOAD)
+       {
+         while (expression)
+           {
+             if (type_dependent_expression_p (OVL_CURRENT (expression)))
+               return true;
+             expression = OVL_NEXT (expression);
+           }
+         return false;
+       }
+      abort ();
+    }
+  
   return (dependent_type_p (TREE_TYPE (expression)));
 }
 
-/* Returns TRUE if the ARG (a template argument) is dependent.  */
+/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call)
+   contains a type-dependent expression.  */
 
 bool
+any_type_dependent_arguments_p (tree args)
+{
+  while (args)
+    {
+      if (type_dependent_expression_p (TREE_VALUE (args)))
+       return true;
+      args = TREE_CHAIN (args);
+    }
+  return false;
+}
+
+/* Returns TRUE if the ARG (a template argument) is dependent.  */
+
+static bool
 dependent_template_arg_p (tree arg)
 {
   if (!processing_template_decl)
@@ -11622,18 +11663,36 @@ dependent_template_arg_p (tree arg)
            || value_dependent_expression_p (arg));
 }
 
-/* Returns TRUE if the specialization TMPL<ARGS> is dependent.  */
+/* Returns true if ARGS (a collection of template arguments) contains
+   any dependent arguments.  */
 
-static bool
-dependent_template_id_p (tree tmpl, tree args)
+bool
+any_dependent_template_arguments_p (tree args)
 {
-  int i;
+  if (!args)
+    return false;
+
+  my_friendly_assert (TREE_CODE (args) == TREE_LIST
+                     || TREE_CODE (args) == TREE_VEC,
+                     20030707);
+
+  if (TREE_CODE (args) == TREE_LIST)
+    {
+      while (args)
+       {
+         if (dependent_template_arg_p (TREE_VALUE (args)))
+           return true;
+         args = TREE_CHAIN (args);
+       }
+    }
+  else
+    {
+      int i; 
+      for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+       if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
+         return true;
+    }
 
-  if (dependent_template_p (tmpl))
-    return true;
-  for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
-    if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
-      return true;
   return false;
 }
 
@@ -11646,12 +11705,24 @@ dependent_template_p (tree tmpl)
   if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
       || TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
     return true;
+  /* So are qualified names that have not been looked up.  */
+  if (TREE_CODE (tmpl) == SCOPE_REF)
+    return true;
   /* So are member templates of dependent classes.  */
   if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
     return dependent_type_p (DECL_CONTEXT (tmpl));
   return false;
 }
 
+/* Returns TRUE if the specialization TMPL<ARGS> is dependent.  */
+
+bool
+dependent_template_id_p (tree tmpl, tree args)
+{
+  return (dependent_template_p (tmpl)
+         || any_dependent_template_arguments_p (args));
+}
+
 /* TYPE is a TYPENAME_TYPE.  Returns the ordinary TYPE to which the
    TYPENAME_TYPE corresponds.  Returns ERROR_MARK_NODE if no such TYPE
    can be found.  Note that this function peers inside uninstantiated
@@ -11730,4 +11801,54 @@ resolve_typename_type (tree type, bool only_current_p)
   return type;
 }
 
+/* EXPR is an expression which is not type-dependent.  Return a proxy
+   for EXPR that can be used to compute the types of larger
+   expressions containing EXPR.  */
+
+tree
+build_non_dependent_expr (tree expr)
+{
+  /* Preserve null pointer constants so that the type of things like 
+     "p == 0" where "p" is a pointer can be determined.  */
+  if (null_ptr_cst_p (expr))
+    return expr;
+  /* Preserve OVERLOADs; the functions must be available to resolve
+     types.  */
+  if (TREE_CODE (expr) == OVERLOAD)
+    return expr;
+  /* Otherwise, build a NON_DEPENDENT_EXPR.  
+
+     REFERENCE_TYPEs are not stripped for expressions in templates
+     because doing so would play havoc with mangling.  Consider, for
+     example:
+
+       template <typename T> void f<T& g>() { g(); } 
+
+     In the body of "f", the expression for "g" will have
+     REFERENCE_TYPE, even though the standard says that it should
+     not.  The reason is that we must preserve the syntactic form of
+     the expression so that mangling (say) "f<g>" inside the body of
+     "f" works out correctly.  Therefore, the REFERENCE_TYPE is
+     stripped here.  */
+  return build (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)));
+}
+
+/* ARGS is a TREE_LIST of expressions as arguments to a function call.
+   Return a new TREE_LIST with the various arguments replaced with
+   equivalent non-dependent expressions.  */
+
+tree
+build_non_dependent_args (tree args)
+{
+  tree a;
+  tree new_args;
+
+  new_args = NULL_TREE;
+  for (a = args; a; a = TREE_CHAIN (a))
+    new_args = tree_cons (NULL_TREE, 
+                         build_non_dependent_expr (TREE_VALUE (a)),
+                         new_args);
+  return nreverse (new_args);
+}
+
 #include "gt-cp-pt.h"
index cc1e2ea3e9c314285694b29e63856064e94766b7..db9e4d2791b6e9b565e5d085f08ffb20e581acfd 100644 (file)
@@ -1449,8 +1449,12 @@ finish_stmt_expr (tree rtl_expr)
   tree result;
 
   /* If the last thing in the statement-expression was not an
-     expression-statement, then it has type `void'.  */
-  if (!last_expr_type)
+     expression-statement, then it has type `void'.  In a template, we
+     cannot distinguish the case where the last expression-statement
+     had a dependent type from the case where the last statement was
+     not an expression-statement.  Therefore, we (incorrectly) treat
+     the STMT_EXPR as dependent in that case.  */
+  if (!last_expr_type && !processing_template_decl)
     last_expr_type = void_type_node;
   result = build_min (STMT_EXPR, last_expr_type, last_tree);
   TREE_SIDE_EFFECTS (result) = 1;
@@ -1482,16 +1486,32 @@ finish_stmt_expr (tree rtl_expr)
 tree 
 finish_call_expr (tree fn, tree args, bool disallow_virtual)
 {
+  tree result;
+  tree orig_fn;
+  tree orig_args;
+
   if (fn == error_mark_node || args == error_mark_node)
     return error_mark_node;
 
-  if (processing_template_decl)
-    return build_nt (CALL_EXPR, fn, args, NULL_TREE);
-
   /* ARGS should be a list of arguments.  */
   my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
                      20020712);
 
+  orig_fn = fn;
+  orig_args = args;
+
+  if (processing_template_decl)
+    {
+      if (type_dependent_expression_p (fn)
+         || any_type_dependent_arguments_p (args))
+       return build_nt (CALL_EXPR, fn, args);
+      if (!BASELINK_P (fn)
+         && TREE_CODE (fn) != PSEUDO_DTOR_EXPR
+         && TREE_TYPE (fn) != unknown_type_node)
+       fn = build_non_dependent_expr (fn);
+      args = build_non_dependent_args (orig_args);
+    }
+
   /* A reference to a member function will appear as an overloaded
      function (rather than a BASELINK) if an unqualified name was used
      to refer to it.  */
@@ -1512,6 +1532,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
        }
     }
 
+  result = NULL_TREE;
   if (BASELINK_P (fn))
     {
       tree object;
@@ -1551,17 +1572,22 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
          object = build_dummy_object (DECL_CONTEXT (representative_fn));
        }
 
-      return build_new_method_call (object, fn, args, NULL_TREE,
-                                   (disallow_virtual 
-                                    ? LOOKUP_NONVIRTUAL : 0));
+      if (processing_template_decl)
+       {
+         if (type_dependent_expression_p (object))
+           return build_nt (CALL_EXPR, orig_fn, orig_args);
+         object = build_non_dependent_expr (object);
+       }
+
+      result = build_new_method_call (object, fn, args, NULL_TREE,
+                                     (disallow_virtual 
+                                      ? LOOKUP_NONVIRTUAL : 0));
     }
   else if (is_overloaded_fn (fn))
     /* A call to a namespace-scope function.  */
-    return build_new_function_call (fn, args);
+    result = build_new_function_call (fn, args);
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
     {
-      tree result;
-
       if (args)
        error ("arguments to destructor are not allowed");
       /* Mark the pseudo-destructor call as having side-effects so
@@ -1570,20 +1596,18 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
                       void_type_node,
                       TREE_OPERAND (fn, 0));
       TREE_SIDE_EFFECTS (result) = 1;
-      return result;
     }
   else if (CLASS_TYPE_P (TREE_TYPE (fn)))
-    {
-      /* If the "function" is really an object of class type, it might
-        have an overloaded `operator ()'.  */
-      tree result;
-      result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
-      if (result)
-       return result;
-    }
+    /* If the "function" is really an object of class type, it might
+       have an overloaded `operator ()'.  */
+    result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+  if (!result)
+    /* A call where the function is unknown.  */
+    result = build_function_call (fn, args);
 
-  /* A call where the function is unknown.  */
-  return build_function_call (fn, args);
+  if (processing_template_decl)
+    return build (CALL_EXPR, TREE_TYPE (result), orig_fn, orig_args);
+  return result;
 }
 
 /* Finish a call to a postfix increment or decrement or EXPR.  (Which
index 975c396c2be37202cc1414c567f65a6023ab5f61..366ea3ab01a88e89a3c945d91a7b7e374a241735 100644 (file)
@@ -174,6 +174,14 @@ lvalue_p_1 (tree ref,
       return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref) 
              ? clk_none : clk_ordinary);
 
+    case NON_DEPENDENT_EXPR:
+      /* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
+        things like "&E" where "E" is an expression with a
+        non-dependent type work. It is safe to be lenient because an
+        error will be issued when the template is instantiated if "E"
+        is not an lvalue.  */
+      return clk_ordinary;
+
     default:
       break;
     }
index e6abb3df57f28e2bed9544737956c08a4293212c..6d499d6c35f6c1a238eb94cb0843517764920043 100644 (file)
@@ -1417,7 +1417,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
 
   my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
   if (processing_template_decl)
-    return build_min_nt (op, type);
+    return build_min (op, size_type_node, type);
   
   op_name = operator_name_info[(int) op].name;
 
@@ -1446,7 +1446,7 @@ tree
 expr_sizeof (tree e)
 {
   if (processing_template_decl)
-    return build_min_nt (SIZEOF_EXPR, e);
+    return build_min (SIZEOF_EXPR, size_type_node, e);
 
   if (TREE_CODE (e) == COMPONENT_REF
       && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
@@ -2015,17 +2015,36 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
 tree
 finish_class_member_access_expr (tree object, tree name)
 {
+  tree expr;
   tree object_type;
   tree member;
   tree access_path = NULL_TREE;
+  tree orig_object = object;
+  tree orig_name = name;
 
   if (object == error_mark_node || name == error_mark_node)
     return error_mark_node;
 
+  object_type = TREE_TYPE (object);
+
   if (processing_template_decl)
-    return build_min_nt (COMPONENT_REF, object, name);
+    {
+      if (/* If OBJECT_TYPE is dependent, so is OBJECT.NAME.  */
+         dependent_type_p (object_type)
+         /* If NAME is "f<args>", where either 'f' or 'args' is
+            dependent, then the expression is dependent.  */
+         || (TREE_CODE (name) == TEMPLATE_ID_EXPR
+             && dependent_template_id_p (TREE_OPERAND (name, 0),
+                                         TREE_OPERAND (name, 1)))
+         /* If NAME is "T::X" where "T" is dependent, then the
+            expression is dependent.  */
+         || (TREE_CODE (name) == SCOPE_REF
+             && TYPE_P (TREE_OPERAND (name, 0))
+             && dependent_type_p (TREE_OPERAND (name, 0))))
+       return build_min_nt (COMPONENT_REF, object, name);
+      object = build_non_dependent_expr (object);
+    }
   
-  object_type = TREE_TYPE (object);
   if (TREE_CODE (object_type) == REFERENCE_TYPE)
     {
       object = convert_from_reference (object);
@@ -2057,6 +2076,7 @@ finish_class_member_access_expr (tree object, tree name)
     {
       bool is_template_id = false;
       tree template_args = NULL_TREE;
+      tree scope;
 
       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
        {
@@ -2067,8 +2087,6 @@ finish_class_member_access_expr (tree object, tree name)
 
       if (TREE_CODE (name) == SCOPE_REF)
        {
-         tree scope;
-
          /* A qualified name.  The qualifying class or namespace `S' has
             already been looked up; it is either a TYPE or a
             NAMESPACE_DECL.  The member name is either an IDENTIFIER_NODE
@@ -2095,57 +2113,35 @@ finish_class_member_access_expr (tree object, tree name)
          access_path = lookup_base (object_type, scope, ba_check, NULL);
          if (!access_path || access_path == error_mark_node)
            return error_mark_node;
-
-         if (TREE_CODE (name) == BIT_NOT_EXPR)
-           member = lookup_destructor (object, scope, name);
-         else
-           {
-             /* Look up the member.  */
-             member = lookup_member (access_path, name, /*protect=*/1, 
-                                     /*want_type=*/false);
-             if (member == NULL_TREE)
-               {
-                 error ("'%D' has no member named '%E'", object_type, name);
-                 return error_mark_node;
-               }
-             if (member == error_mark_node)
-               return error_mark_node;
-           }
        }
-      else if (TREE_CODE (name) == BIT_NOT_EXPR)
-       member = lookup_destructor (object, /*scope=*/NULL_TREE, name);
-      else if (TREE_CODE (name) == IDENTIFIER_NODE)
+      else
+       {
+         scope = NULL_TREE;
+         access_path = object_type;
+       }
+
+      if (TREE_CODE (name) == BIT_NOT_EXPR)
+       member = lookup_destructor (object, scope, name);
+      else
        {
-         /* An unqualified name.  */
-         member = lookup_member (object_type, name, /*protect=*/1, 
+         /* Look up the member.  */
+         member = lookup_member (access_path, name, /*protect=*/1, 
                                  /*want_type=*/false);
          if (member == NULL_TREE)
            {
              error ("'%D' has no member named '%E'", object_type, name);
              return error_mark_node;
            }
-         else if (member == error_mark_node)
+         if (member == error_mark_node)
            return error_mark_node;
        }
-      else
-       {
-         /* The YACC parser sometimes gives us things that are not names.
-            These always indicate errors.  The recursive-descent parser
-            does not do this, so this code can go away once that parser
-            replaces the YACC parser.  */
-         error ("invalid use of `%D'", name);
-         return error_mark_node;
-       }
       
       if (is_template_id)
        {
          tree template = member;
          
          if (BASELINK_P (template))
-           BASELINK_FUNCTIONS (template) 
-             = build_nt (TEMPLATE_ID_EXPR,
-                         BASELINK_FUNCTIONS (template),
-                         template_args);
+           template = lookup_template_function (template, template_args);
          else
            {
              error ("`%D' is not a member template function", name);
@@ -2157,8 +2153,12 @@ finish_class_member_access_expr (tree object, tree name)
   if (TREE_DEPRECATED (member))
     warn_deprecated_use (member);
 
-  return build_class_member_access_expr (object, member, access_path,
+  expr = build_class_member_access_expr (object, member, access_path,
                                         /*preserve_reference=*/false);
+  if (processing_template_decl && expr != error_mark_node)
+    return build_min (COMPONENT_REF, TREE_TYPE (expr), orig_object, 
+                     orig_name);
+  return expr;
 }
 
 /* Return an expression for the MEMBER_NAME field in the internal
@@ -2196,18 +2196,27 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
    Must also handle REFERENCE_TYPEs for C++.  */
 
 tree
-build_x_indirect_ref (tree ptr, const char *errorstring)
+build_x_indirect_ref (tree expr, const char *errorstring)
 {
+  tree orig_expr = expr;
   tree rval;
 
   if (processing_template_decl)
-    return build_min_nt (INDIRECT_REF, ptr);
+    {
+      if (type_dependent_expression_p (expr))
+       return build_min_nt (INDIRECT_REF, expr);
+      expr = build_non_dependent_expr (expr);
+    }
 
-  rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
+  rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
                       NULL_TREE);
-  if (rval)
+  if (!rval)
+    rval = build_indirect_ref (expr, errorstring);
+
+  if (processing_template_decl && rval != error_mark_node)
+    return build_min (INDIRECT_REF, TREE_TYPE (rval), orig_expr);
+  else
     return rval;
-  return build_indirect_ref (ptr, errorstring);
 }
 
 tree
@@ -2826,192 +2835,33 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
 tree
 build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
 {
-  if (processing_template_decl)
-    return build_min_nt (code, arg1, arg2);
-
-  if (code == DOTSTAR_EXPR)
-    return build_m_component_ref (arg1, arg2);
-
-  return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
-}
-
-#if 0
+  tree orig_arg1;
+  tree orig_arg2;
+  tree expr;
 
-tree
-build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
-{
-  tree type;
+  orig_arg1 = arg1;
+  orig_arg2 = arg2;
 
-  /* If any of the operands is erroneous the result is erroneous too.  */
-  if (error_operand_p (op0)
-      || (op1 && error_operand_p (op1))
-      || (op2 && error_operand_p (op2)))
-    return error_mark_node;
-      
-  if (dependent_type_p (TREE_TYPE (op0))
-      || (op1 && dependent_type_p (TREE_TYPE (op1)))
-      || (op2 && dependent_type_p (TREE_TYPE (op2))))
-    /* If at least one operand has a dependent type, we cannot
-       determine the type of the expression until instantiation time.  */
-    type = NULL_TREE;
-  else
+  if (processing_template_decl)
     {
-      struct z_candidate *cand;
-      tree op0_type;
-      tree op1_type;
-      tree op2_type;
-
-      /* None of the operands is dependent, so we can compute the type
-        of the expression at this point.  We must compute the type so
-        that in things like:
-
-          template <int I>
-          void f() { S<sizeof(I + 3)> s; ... }
+      if (type_dependent_expression_p (arg1)
+         || type_dependent_expression_p (arg2))
+       return build_min_nt (code, arg1, arg2);
+      arg1 = build_non_dependent_expr (arg1);
+      arg2 = build_non_dependent_expr (arg2);
+    }
 
-        we can tell that the type of "s" is non-dependent.
+  if (code == DOTSTAR_EXPR)
+    expr = build_m_component_ref (arg1, arg2);
+  else
+    expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
 
-        If we're processing a template argument, we do not want to
-        actually change the operands in any way.  Adding conversions,
-        performing constant folding, etc., would all change mangled
-        names.  For example, in:
-        
-          template <int I>
-          void f(S<sizeof(3 + 4 + I)>);
-        
-        we need to determine that "3 + 4 + I" has type "int", without
-        actually turning the expression into "7 + I".  */
-      cand = find_overloaded_op (code, op0, op1, op2);
-      if (cand) 
-       /* If an overloaded operator was found, the expression will
-          have the type returned by the function.  */
-       type = non_reference (TREE_TYPE (cand->fn));
-      else
-       {
-         /* There is no overloaded operator so we can just use the
-            default rules for determining the type of the operand.  */
-         op0_type = TREE_TYPE (op0);
-         op1_type = op1 ? TREE_TYPE (op1) : NULL_TREE;
-         op2_type = op2 ? TREE_TYPE (op2) : NULL_TREE;
-         type = NULL_TREE;
-
-         switch (code)
-           {
-           case MODIFY_EXPR:
-             /* [expr.ass]
-
-                The result of the assignment operation is the value
-                stored in the left operand.  */
-             type = op0_type;
-             break;
-           case COMPONENT_REF:
-             /* Implement this case.  */
-             break;
-           case POSTINCREMENT_EXPR:
-           case POSTDECREMENT_EXPR:
-             /* [expr.post.incr]
-
-                The type of the result is the cv-unqualified version
-                of the type of the operand.  */
-             type = TYPE_MAIN_VARIANT (op0_type);
-             break;
-           case PREINCREMENT_EXPR:
-           case PREDECREMENT_EXPR:
-             /* [expr.pre.incr]
-
-                The value is the new value of the operand.  */
-             type = op0_type;
-             break;
-           case INDIRECT_REF:
-             /* [expr.unary.op]
-
-                If the type of the expression is "pointer to T", the
-                type of the result is "T".  */
-             type = TREE_TYPE (op0_type);
-             break;
-           case ADDR_EXPR:
-             /* [expr.unary.op]
-
-                If the type of the expression is "T", the type of the
-                result is "pointer to T".  */
-             /* FIXME: Handle the pointer-to-member case.  */
-             break;
-           case MEMBER_REF:
-             /* FIXME: Implement this case.  */
-             break;
-           case LSHIFT_EXPR:
-           case RSHIFT_EXPR:
-             /* [expr.shift]
-
-                The type of the result is that of the promoted left
-                operand.  */
-             break;
-           case PLUS_EXPR:
-           case MINUS_EXPR:
-             /* FIXME: Be careful of special pointer-arithmetic
-                cases.  */
-             /* Fall through.  */
-           case MAX_EXPR:
-           case MIN_EXPR:
-             /* These are GNU extensions; the result type is computed
-                as it would be for other arithmetic operators.  */
-             /* Fall through.  */
-           case BIT_AND_EXPR:
-           case BIT_XOR_EXPR:
-           case BIT_IOR_EXPR:
-           case MULT_EXPR:
-           case TRUNC_DIV_EXPR:
-           case TRUNC_MOD_EXPR:
-             /* [expr.bit.and], [expr.xor], [expr.or], [expr.mul]
-
-                The usual arithmetic conversions are performed on the
-                operands and determine the type of the result.  */
-             /* FIXME: Check that this is possible.  */
-             type = type_after_usual_arithmetic_conversions (t1, t2);
-             break;
-           case GT_EXPR:
-           case LT_EXPR:
-           case GE_EXPR:
-           case LE_EXPR:
-           case EQ_EXPR:
-           case NE_EXPR:
-             /* [expr.rel]
-
-                The type of the result is bool.  */
-             type = boolean_type_node;
-             break;
-           case TRUTH_ANDIF_EXPR:
-           case TRUTH_ORIF_EXPR:
-             /* [expr.log.and], [expr.log.org]
-                
-                The result is a bool.  */
-             type = boolean_type_node;
-             break;
-           case COND_EXPR:
-             /* FIXME: Handle special rules for conditional
-                expressions.  */
-             break;
-           case COMPOUND_EXPR:
-             type = op1_type;
-             break;
-           default:
-             abort ();
-           }
-         /* If the type of the expression could not be determined,
-            something is wrong.  */
-         if (!type)
-           abort ();
-         /* If the type is erroneous, the expression is erroneous
-            too.  */
-         if (type == error_mark_node)
-           return error_mark_node;
-       }
-    }
+  if (processing_template_decl && expr != error_mark_node)
+    return build_min (code, TREE_TYPE (expr), orig_arg1, orig_arg2);
   
-  return build_min (code, type, op0, op1, op2, NULL_TREE);
+  return expr;
 }
 
-#endif
-
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    This function differs from `build' in several ways:
@@ -3839,11 +3689,18 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype)
 tree
 build_x_unary_op (enum tree_code code, tree xarg)
 {
+  tree orig_expr = xarg;
   tree exp;
   int ptrmem = 0;
   
   if (processing_template_decl)
-    return build_min_nt (code, xarg, NULL_TREE);
+    {
+      if (type_dependent_expression_p (xarg))
+       return build_min_nt (code, xarg, NULL_TREE);
+      xarg = build_non_dependent_expr (xarg);
+    }
+
+  exp = NULL_TREE;
 
   /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
      error message.  */
@@ -3854,15 +3711,8 @@ build_x_unary_op (enum tree_code code, tree xarg)
          || (TREE_CODE (xarg) == OFFSET_REF)))
     /* don't look for a function */;
   else
-    {
-      tree rval;
-
-      rval = build_new_op (code, LOOKUP_NORMAL, xarg,
-                          NULL_TREE, NULL_TREE);
-      if (rval || code != ADDR_EXPR)
-       return rval;
-    }
-  if (code == ADDR_EXPR)
+    exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
+  if (!exp && code == ADDR_EXPR)
     {
       /*  A pointer to member-function can be formed only by saying
          &X::mf.  */
@@ -3896,16 +3746,17 @@ build_x_unary_op (enum tree_code code, tree xarg)
                            TREE_OPERAND (xarg, 0),
                            ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
              PTRMEM_OK_P (xarg) = ptrmem;
-           }
-             
+           }         
         }
       else if (TREE_CODE (xarg) == TARGET_EXPR)
        warning ("taking address of temporary");
+      exp = build_unary_op (ADDR_EXPR, xarg, 0);
+      if (TREE_CODE (exp) == ADDR_EXPR)
+       PTRMEM_OK_P (exp) = ptrmem;
     }
-  exp = build_unary_op (code, xarg, 0);
-  if (TREE_CODE (exp) == ADDR_EXPR)
-    PTRMEM_OK_P (exp) = ptrmem;
 
+  if (processing_template_decl && exp != error_mark_node)
+    return build_min (code, TREE_TYPE (exp), orig_expr);
   return exp;
 }
 
@@ -4631,53 +4482,76 @@ cxx_mark_addressable (tree exp)
 tree
 build_x_conditional_expr (tree ifexp, tree op1, tree op2)
 {
-  if (processing_template_decl)
-    return build_min_nt (COND_EXPR, ifexp, op1, op2);
+  tree orig_ifexp = ifexp;
+  tree orig_op1 = op1;
+  tree orig_op2 = op2;
+  tree expr;
 
-  return build_conditional_expr (ifexp, op1, op2);
+  if (processing_template_decl)
+    {
+      /* The standard says that the expression is type-dependent if
+        IFEXP is type-dependent, even though the eventual type of the
+        expression doesn't dependent on IFEXP.  */
+      if (type_dependent_expression_p (ifexp)
+         || type_dependent_expression_p (op1)
+         || type_dependent_expression_p (op2))
+       return build_min_nt (COND_EXPR, ifexp, op1, op2);
+      ifexp = build_non_dependent_expr (ifexp);
+      op1 = build_non_dependent_expr (op1);
+      op2 = build_non_dependent_expr (op2);
+    }
+
+  expr = build_conditional_expr (ifexp, op1, op2);
+  if (processing_template_decl && expr != error_mark_node)
+    return build_min (COND_EXPR, TREE_TYPE (expr), 
+                     orig_ifexp, orig_op1, orig_op2);
+  return expr;
 }
 \f
 /* Handle overloading of the ',' operator when needed.  Otherwise,
    this function just builds an expression list.  */
 
 tree
-build_x_compound_expr (tree list)
+build_x_compound_expr (tree op1, tree op2)
 {
-  tree rest = TREE_CHAIN (list);
   tree result;
+  tree orig_op1 = op1;
+  tree orig_op2 = op2;
 
   if (processing_template_decl)
-    return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
-
-  if (rest == NULL_TREE)
-    return build_compound_expr (list);
+    {
+      if (type_dependent_expression_p (op1)
+         || type_dependent_expression_p (op2))
+       return build_min_nt (COMPOUND_EXPR, op1, op2);
+      op1 = build_non_dependent_expr (op1);
+      op2 = build_non_dependent_expr (op2);
+    }
 
-  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL,
-                        TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
-  if (result)
-    return build_x_compound_expr (tree_cons (NULL_TREE, result,
-                                                 TREE_CHAIN (rest)));
-
-  if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
-    {
-      /* FIXME: This test should be in the implicit cast to void of the LHS.  */
-      /* the left-hand operand of a comma expression is like an expression
-         statement: we should warn if it doesn't have any side-effects,
-         unless it was explicitly cast to (void).  */
-      if (warn_unused_value
-           && !(TREE_CODE (TREE_VALUE(list)) == CONVERT_EXPR
-                && VOID_TYPE_P (TREE_TYPE (TREE_VALUE(list)))))
-        warning("left-hand operand of comma expression has no effect");
-    }
-#if 0 /* this requires a gcc backend patch to export warn_if_unused_value */
-  else if (warn_unused_value)
-    warn_if_unused_value (TREE_VALUE(list));
-#endif
+  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE);
+  if (!result)
+    {
+      if (! TREE_SIDE_EFFECTS (op1))
+       {
+         /* FIXME: This test should be in the implicit cast to void
+            of the LHS.  */
+         /* the left-hand operand of a comma expression is like an expression
+            statement: we should warn if it doesn't have any side-effects,
+            unless it was explicitly cast to (void).  */
+         if (warn_unused_value
+             && !(TREE_CODE (op1) == CONVERT_EXPR
+                  && VOID_TYPE_P (TREE_TYPE (op1))))
+           warning("left-hand operand of comma expression has no effect");
+       }
+      result = build_compound_expr (tree_cons (NULL_TREE,
+                                              op1,
+                                              build_tree_list (NULL_TREE,
+                                                               op2)));
+    }
 
-  return build_compound_expr
-    (tree_cons (NULL_TREE, TREE_VALUE (list),
-                    build_tree_list (NULL_TREE,
-                                     build_x_compound_expr (rest))));
+  if (processing_template_decl && result != error_mark_node)
+    return build_min (COMPOUND_EXPR, TREE_TYPE (result), 
+                     orig_op1, orig_op2);
+  return result;
 }
 
 /* Given a list of expressions, return a compound expression
index edb9f5d5b212d77d01753e03ee52eb7ca31c09cd..6a14fecb4a99f51c7ba8661cb75c2c4184f88092 100644 (file)
@@ -980,44 +980,48 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
    delegation is detected.  */
 
 tree
-build_x_arrow (tree datum)
+build_x_arrow (tree expr)
 {
+  tree orig_expr = expr;
   tree types_memoized = NULL_TREE;
-  register tree rval = datum;
-  tree type = TREE_TYPE (rval);
+  tree type = TREE_TYPE (expr);
   tree last_rval = NULL_TREE;
 
   if (type == error_mark_node)
     return error_mark_node;
 
   if (processing_template_decl)
-    return build_min_nt (ARROW_EXPR, rval);
+    {
+      if (type_dependent_expression_p (expr))
+       return build_min_nt (ARROW_EXPR, expr);
+      expr = build_non_dependent_expr (expr);
+    }
 
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
-      rval = convert_from_reference (rval);
-      type = TREE_TYPE (rval);
+      expr = convert_from_reference (expr);
+      type = TREE_TYPE (expr);
     }
 
   if (IS_AGGR_TYPE (type))
     {
-      while ((rval = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, rval,
+      while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
                                   NULL_TREE, NULL_TREE)))
        {
-         if (rval == error_mark_node)
+         if (expr == error_mark_node)
            return error_mark_node;
 
-         if (value_member (TREE_TYPE (rval), types_memoized))
+         if (value_member (TREE_TYPE (expr), types_memoized))
            {
              error ("circular pointer delegation detected");
              return error_mark_node;
            }
          else
            {
-             types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval),
+             types_memoized = tree_cons (NULL_TREE, TREE_TYPE (expr),
                                          types_memoized);
            }
-         last_rval = rval;
+         last_rval = expr;
        }     
 
       if (last_rval == NULL_TREE)
@@ -1030,10 +1034,17 @@ build_x_arrow (tree datum)
        last_rval = convert_from_reference (last_rval);
     }
   else
-    last_rval = decay_conversion (rval);
+    last_rval = decay_conversion (expr);
 
   if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
-    return build_indirect_ref (last_rval, NULL);
+    {
+      if (processing_template_decl)
+       return build_min (ARROW_EXPR, 
+                         TREE_TYPE (TREE_TYPE (last_rval)), 
+                         orig_expr);
+
+      return build_indirect_ref (last_rval, NULL);
+    }
 
   if (types_memoized)
     error ("result of `operator->()' yields non-pointer result");
index e4f57b8cfa326191c9f8900b1fc061ed0b8b6127..e268055cb8e30d9f669022667ef743a72a4dae6c 100644 (file)
@@ -2908,7 +2908,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 
       if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
        {
-         arg0 = TREE_OPERAND (exp, 0);
+         if (first_rtl_op (code) > 0)
+           arg0 = TREE_OPERAND (exp, 0);
          if (TREE_CODE_CLASS (code) == '<'
              || TREE_CODE_CLASS (code) == '1'
              || TREE_CODE_CLASS (code) == '2')
index 9ee1e57f7519c63b0011ba54fd2ca1c2574c3382..859e8a5059a5860503e4ce429a733204553c455e 100644 (file)
@@ -1,3 +1,14 @@
+2003-07-08  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/mangle17.C: Make sure template expressions are
+       dependent.
+       * g++.dg/abi/mangle4.C: Mark erroneous casts.
+       * g++.dg/debug/debug7.C: Mark erronous new-declarator.
+       * g++.dg/opt/stack1.C: Remove erroneous code.
+       * g++.dg/parse/template7.C: New test.
+       * g++.dg/template/dependent-expr1.C: Mark erroneous code.
+       * g++.old-deja/g++.pt/crash4.C: Likewise.
+
 2003-07-09  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * gcc.dg/const-elim-1.c (dg-final): Change regexp to match labels
index 1da6dea632b7373b36542680127c72a32ec8be8a..6f8e387e1d7ecef648c4b16e2360db2dbb2bad80 100644 (file)
@@ -4,8 +4,8 @@ enum E { e = 3 };
 
 template <int I> struct S {};
 
-template <int I> void f (S<e + int (3.7)>) {}
-template void f<7>(S<e + int (3.7)>);  // { dg-warning "mangle" }
+template <int I> void f (S<I + e + int (3.7)>) {}
+template void f<7>(S<7 + e + int (3.7)>);  // { dg-warning "mangle" }
 
-template <int I> void g (S<e + int (3.7)>) {}
-template void g<7>(S<e + int (3.7)>); // { dg-warning "mangle" }
+template <int I> void g (S<I + e + int (3.7)>) {}
+template void g<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
index ec65654e8e2145fc0d4db32f885386f3a3715f57..d4b5936825ccf4eab9bdd4b43db40c2a17601ddc 100644 (file)
@@ -8,19 +8,17 @@ template<const A* a> class C {};
 template<const B* b> class D {};
 template<B* b> class E {};
 
-template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {}
-template<const B* b> void g(D<b> &, E<const_cast<B*>(b)> &) {}
+template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {} // { dg-error "" }
+template<const B* b> void g(D<b> &, E<const_cast<B*>(b)> &) {} // { dg-error "" }
 
 B b;
 
 int main()
 {
-  C<static_cast<const A*>(&b)> c;
+  C<static_cast<const A*>(&b)> c; // { dg-error "" }
   D<&b> d;
-  E<const_cast<B*>(&b)> e;
-  f(d, c);
-  g(d, e);
+  E<const_cast<B*>(&b)> e; // { dg-error "" }
+  f(d, c); // { dg-error "" }
+  g(d, e); // { dg-error "" }
 }
 
-// { dg-final { scan-assembler "\n_?_Z1fIXadL_Z1bEEEvR1DIXT_EER1CIXcvPK1AT_EE\[: \t\n\]" } }
-// { dg-final { scan-assembler "\n_?_Z1gIXadL_Z1bEEEvR1DIXT_EER1EIXcvP1BT_EE\[: \t\n\]" } }
index 78faa20ff03010f1b5d754bf59dd605fd0c3b6ab..31d47eda78f4178b62fdaa03432692d017260fe1 100644 (file)
@@ -7,7 +7,7 @@ main() {
 
   int a = 4;
   int b = 5;
-  int (*x)[b] = new int[a][b];
+  int (*x)[b] = new int[a][b]; // { dg-error "" }
 
   x[2][1] = 7;
 
index bb6159c568e992da387c45c955ee2b60d78d613c..7fac18dac03d22629a51347e2aa3a223542c6684 100644 (file)
@@ -68,7 +68,7 @@ template<typename=void>
 struct adaptor {
     adaptor (matrix<> &m) : m(&m), upper_ (1) {}
 
-    int size1 () const     { return m->size1 (); }
+    int size1 () const;
     int size2 () const     { return 3; }
     int lower () const     { return 1; }
     int upper () const     { return upper_; }
diff --git a/gcc/testsuite/g++.dg/parse/template7.C b/gcc/testsuite/g++.dg/parse/template7.C
new file mode 100644 (file)
index 0000000..b13e3ec
--- /dev/null
@@ -0,0 +1,4 @@
+template <int I>
+void f();
+
+void g() { f<(3, 2)>(); } // { dg-error "" }
index 079f033611be71d778102dd9f062feca62ba1cc3..e29b76d42d0699623513b8c4641b52d033f5e249 100644 (file)
@@ -21,9 +21,9 @@ namespace std
     Foo (__alignof__ (x));
     Foo (x->~I ());
     //    Foo (typeid (I));
-    Foo (delete x);
-    Foo (delete[] x);
-    Foo (throw x);
+    Foo (delete x); // { dg-error "" }
+    Foo (delete[] x); // { dg-error "" }
+    Foo (throw x); // { dg-error "" }
   }
 
 }
index a3d8088a2cd0329c49cfa229c2a678a1939d8e3d..fc7f7b51497c0d559555917b89a7dc295d133d70 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do assemble  }
+// { dg-do compile  }
 // Origin: Mark Mitchell <mark@codesourcery.com>
 
 template <int> struct S1{};
@@ -7,5 +7,5 @@ struct S2 { int i; };
 
 template <class T>
 void f(S2 s2) {
-  S1<s2.i> s1;
+  S1<s2.i> s1; // { dg-error "" }
 }
index 351b77f74f01956da1dcc02899f4d56b66ede699..f1cdea21ff8d73efb485007d98d512bdf4cbffb4 100644 (file)
@@ -1,3 +1,7 @@
+2003-07-09  Mark Mitchell  <mark@codesourcery.com>
+
+       * gcj/array.h (JvPrimClass): Don't parenthesize the output.
+
 2003-07-09  Michael Koch  <konqueror@gmx.de>
 
        * gnu/java/awt/peer/gtk/GtkComponentPeer.java,
index 33ea038df93bb67eb62e9dee1c7c58ba09afa8f3..4f134f33c5ccb49f1646e36fa0dd90eca0298efd 100644 (file)
@@ -71,7 +71,9 @@ typedef JArray<jstring> *jstringArray;
 extern java::lang::Class _Jv_byteClass, _Jv_shortClass, _Jv_intClass,
   _Jv_longClass, _Jv_booleanClass, _Jv_charClass, _Jv_floatClass,
   _Jv_doubleClass, _Jv_voidClass;
-#define JvPrimClass(TYPE) (& _Jv_##TYPE##Class)
+/* The definition of this macro cannot be enclosed in parentheses
+   because "JvPrimClass(x)" is used as a template argument.  */
+#define JvPrimClass(TYPE) & _Jv_##TYPE##Class
 
 extern "C" jobjectArray _Jv_NewObjectArray(jsize length, jclass, jobject init);
 extern "C" jobject _Jv_NewPrimArray (jclass eltype, jint count);