re PR c++/17642 (internal compiler error: in invert_truthvalue, at fold-const.c:2997)
authorMark Mitchell <mark@codesourcery.com>
Tue, 28 Sep 2004 02:56:11 +0000 (02:56 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 28 Sep 2004 02:56:11 +0000 (02:56 +0000)
PR c++/17642
* stor-layout.c (layout_decl): Use fold_convert, not convert.
(bit_from_pos): Likewise.
(byte_from_pos): Likewise.
(pos_from_bit): Likewise.
(normalize_offset): Likewise.
(place_field): Likewise.
(finalize_type_size): Likewise.
(layout_type): Likewise.
* tree.c (build_index_type): Likewise.

PR c++/17642
* cp-tree.h (fold_if_not_in_template): New function.
* call.c (build_conditional_expr): Use fold_if_not_in_template.
(build_cxx_call): Likewise.
* cvt.c (convert_to_complex): Likewise.
(ocp_convert): Likewise.
(convert): Likewise.
(convert_force): Likewise.
* decl.c (compute_array_index_type): Clear
processing_template_decl while folding array bounds.
* pt.c (convert_nontype_argument): Clear
processing_template_decl while processing non-type argument
initialization.
* tree.c (fold_if_not_in_template): New function.
* typeck.c (build_class_member_access_expr): Use
fold_if_not_in_template.
(build_array_ref): Likewise.
(build_binary_op): Likewise.  Do not try to optimize computations
when processing templates.
(cp_pointer_int_sum): Use fold_if_not_in_template.
(pointer_diff): Likewise.
(build_unary_op): Likewise.
(build_reinterpret_cast): Likewise.
(get_delta_difference): Likewise.
(expand_ptrmemfunc_cst): Likewise.
(dubious_conversion_warnings): Likewise.

* g++.dg/template/crash23.C: New test.

From-SVN: r88217

13 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/crash23.C [new file with mode: 0644]
gcc/tree.c

index f392069de66b252e602c64f8c9964fb8ac63bec0..d7fb97a35ac0b1673af96aa2cddc86c0e5e6981f 100644 (file)
@@ -1,3 +1,16 @@
+2004-09-27  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/17642
+       * stor-layout.c (layout_decl): Use fold_convert, not convert.
+       (bit_from_pos): Likewise.
+       (byte_from_pos): Likewise.
+       (pos_from_bit): Likewise.
+       (normalize_offset): Likewise.
+       (place_field): Likewise.
+       (finalize_type_size): Likewise.
+       (layout_type): Likewise.
+       * tree.c (build_index_type): Likewise.
+
 2004-09-27  Devang Patel  <dpatel@apple.com>
 
        * expr.c (expand_expr_real_1): Handle VEC_COND_EXPR.
index 6da00c46ce5811f22866b2d236f55a9e1d24ffe2..561ac7a97f0235184fab1eec3d473538223017e6 100644 (file)
@@ -1,3 +1,32 @@
+2004-09-27  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/17642
+       * cp-tree.h (fold_if_not_in_template): New function.
+       * call.c (build_conditional_expr): Use fold_if_not_in_template.
+       (build_cxx_call): Likewise.
+       * cvt.c (convert_to_complex): Likewise.
+       (ocp_convert): Likewise.
+       (convert): Likewise.
+       (convert_force): Likewise.
+       * decl.c (compute_array_index_type): Clear
+       processing_template_decl while folding array bounds.
+       * pt.c (convert_nontype_argument): Clear
+       processing_template_decl while processing non-type argument
+       initialization.
+       * tree.c (fold_if_not_in_template): New function.
+       * typeck.c (build_class_member_access_expr): Use
+       fold_if_not_in_template.
+       (build_array_ref): Likewise.
+       (build_binary_op): Likewise.  Do not try to optimize computations
+       when processing templates.
+       (cp_pointer_int_sum): Use fold_if_not_in_template.
+       (pointer_diff): Likewise.
+       (build_unary_op): Likewise.
+       (build_reinterpret_cast): Likewise.
+       (get_delta_difference): Likewise.
+       (expand_ptrmemfunc_cst): Likewise.
+       (dubious_conversion_warnings): Likewise.
+
 2004-09-27  Matt Austern  <austern@apple.com>
 
        * cp/parser.c (struct cp_token): new one-bit field , implicit_extern_c
index c5761ec166899092f190b17151cb6385c41259d9..f61fa2a754d6ccd9ff82b4748c212230a7c34303 100644 (file)
@@ -3442,7 +3442,8 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
     }
 
  valid_operands:
-  result = fold (build3 (COND_EXPR, result_type, arg1, arg2, arg3));
+  result = fold_if_not_in_template (build3 (COND_EXPR, result_type, arg1, 
+                                           arg2, arg3));
   /* We can't use result_type below, as fold might have returned a
      throw_expr.  */
 
@@ -4869,7 +4870,7 @@ build_cxx_call (tree fn, tree args)
 
   /* Some built-in function calls will be evaluated at compile-time in
      fold ().  */
-  fn = fold (fn);
+  fn = fold_if_not_in_template (fn);
 
   if (VOID_TYPE_P (TREE_TYPE (fn)))
     return fn;
index 3c9ea57fda9a027dac5b664adc70cbc3f87c81f4..0a2d9706e9381148eab3847edbe7defb4c1e8616 100644 (file)
@@ -4207,6 +4207,7 @@ extern tree cp_add_pending_fn_decls (void*,tree);
 extern int cp_is_overload_p (tree);
 extern int cp_auto_var_in_fn_p (tree,tree);
 extern void cp_update_decl_after_saving (tree, void *);
+extern tree fold_if_not_in_template             (tree);
 
 /* in typeck.c */
 extern int string_conv_p                       (tree, tree, int);
index d93351e399e1474272646f73156a4178b119e465..a5d42e463e57c6c2bea9ac480462246fbcaa0a73 100644 (file)
@@ -643,7 +643,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       /* For complex data types, we need to perform componentwise
          conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
-        return fold (convert_to_complex (type, e));
+        return fold_if_not_in_template (convert_to_complex (type, e));
       else if (TREE_CODE (e) == TARGET_EXPR)
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
@@ -659,7 +659,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          /* We shouldn't be treating objects of ADDRESSABLE type as
             rvalues.  */
          gcc_assert (!TREE_ADDRESSABLE (type));
-         return fold (build1 (NOP_EXPR, type, e));
+         return fold_if_not_in_template (build_nop (type, e));
        }
     }
 
@@ -696,10 +696,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       if (code == BOOLEAN_TYPE)
        return cp_truthvalue_conversion (e);
 
-      return fold (convert_to_integer (type, e));
+      return fold_if_not_in_template (convert_to_integer (type, e));
     }
   if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
-    return fold (cp_convert_to_pointer (type, e, false));
+    return fold_if_not_in_template (cp_convert_to_pointer (type, e, false));
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
@@ -713,7 +713,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
             error ("`%#T' used where a `%T' was expected", in_vtype, type);
           return error_mark_node;
        }
-      return fold (convert_to_vector (type, e));
+      return fold_if_not_in_template (convert_to_vector (type, e));
     }
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
@@ -729,9 +729,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
                        TREE_TYPE (e));
        }
       if (code == REAL_TYPE)
-       return fold (convert_to_real (type, e));
+       return fold_if_not_in_template (convert_to_real (type, e));
       else if (code == COMPLEX_TYPE)
-       return fold (convert_to_complex (type, e));
+       return fold_if_not_in_template (convert_to_complex (type, e));
     }
 
   /* New C++ semantics:  since assignment is now based on
@@ -945,7 +945,7 @@ convert (tree type, tree expr)
   if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
     {
       expr = decl_constant_value (expr);
-      return fold (build1 (NOP_EXPR, type, expr));
+      return fold_if_not_in_template (build_nop (type, expr));
     }
 
   return ocp_convert (type, expr, CONV_OLD_CONVERT,
@@ -963,13 +963,14 @@ convert_force (tree type, tree expr, int convtype)
   enum tree_code code = TREE_CODE (type);
 
   if (code == REFERENCE_TYPE)
-    return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
-                                      NULL_TREE));
+    return (fold_if_not_in_template 
+           (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
+                                  NULL_TREE)));
   else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
     e = convert_from_reference (e);
 
   if (code == POINTER_TYPE)
-    return fold (convert_to_pointer_force (type, e));
+    return fold_if_not_in_template (convert_to_pointer_force (type, e));
 
   /* From typeck.c convert_for_assignment */
   if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR
index d3a0c8d4b21d1432db4a93082fe2f72e21a37392..fb1334fc16fbf691b6a360607c8239abb34a7bdc 100644 (file)
@@ -6196,12 +6196,20 @@ compute_array_index_type (tree name, tree size)
     itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
   else
     {
+      HOST_WIDE_INT saved_processing_template_decl;
+
       /* Compute the index of the largest element in the array.  It is
-        one less than the number of elements in the array.  */
-      itype
-       = fold (cp_build_binary_op (MINUS_EXPR,
-                                   cp_convert (ssizetype, size),
-                                   cp_convert (ssizetype, integer_one_node)));
+        one less than the number of elements in the array.  We save
+        and restore PROCESSING_TEMPLATE_DECL so that computations in
+        cp_build_binary_op will be appropriately folded.  */
+      saved_processing_template_decl = processing_template_decl;
+      processing_template_decl = 0;
+      itype = cp_build_binary_op (MINUS_EXPR,
+                                 cp_convert (ssizetype, size),
+                                 cp_convert (ssizetype, integer_one_node));
+      itype = fold (itype);
+      processing_template_decl = saved_processing_template_decl;
+
       if (!TREE_CONSTANT (itype))
        /* A variable sized array.  */
        itype = variable_size (itype);
index 3125c83baff7644bf8e6292f742c50f545eaeb56..99c70b5f26830058fea9f0176169c4cf6309731c 100644 (file)
@@ -3381,6 +3381,8 @@ convert_nontype_argument (tree type, tree expr)
 
   switch (TREE_CODE (type))
     {
+      HOST_WIDE_INT saved_processing_template_decl;
+
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
     case ENUMERAL_TYPE:
@@ -3398,8 +3400,12 @@ convert_nontype_argument (tree type, tree expr)
          return error_mark_node;
 
       /* It's safe to call digest_init in this case; we know we're
-        just converting one integral constant expression to another.  */
+        just converting one integral constant expression to another.
+        */
+      saved_processing_template_decl = processing_template_decl;
+      processing_template_decl = 0;
       expr = digest_init (type, expr, (tree*) 0);
+      processing_template_decl = saved_processing_template_decl;
 
       if (TREE_CODE (expr) != INTEGER_CST)
        /* Curiously, some TREE_CONSTANT integral expressions do not
index fc3516d8e8a8b8f823c54f378487d014811f316c..16bb39bc740739c3f2cac6e558d289f8ca82f077 100644 (file)
@@ -2331,6 +2331,19 @@ stabilize_init (tree init, tree *initp)
   return true;
 }
 
+/* Like "fold", but should be used whenever we might be processing the
+   body of a template.  */
+
+tree
+fold_if_not_in_template (tree expr)
+{
+  /* In the body of a template, there is never any need to call
+     "fold".  We will call fold later when actually instantiating the
+     template.  Integral constant expressions in templates will be
+     evaluted via fold_non_dependent_expr, as necessary.  */
+  return (processing_template_decl ? expr : fold (expr));
+}
+
 \f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
index 164f7a34a71aa0ad14d748ad42a1071ddc2f86cf..85337735f071a0cf785f56e742a8d202a3e59293 100644 (file)
@@ -1768,8 +1768,9 @@ build_class_member_access_expr (tree object, tree member,
          member_type = cp_build_qualified_type (member_type, type_quals);
        }
 
-      result = fold (build3 (COMPONENT_REF, member_type, object, member,
-                            NULL_TREE));
+      result = build3 (COMPONENT_REF, member_type, object, member,
+                      NULL_TREE);
+      result = fold_if_not_in_template (result);
 
       /* Mark the expression const or volatile, as appropriate.  Even
         though we've dealt with the type above, we still have to mark the
@@ -2272,7 +2273,7 @@ build_array_ref (tree array, tree idx)
        |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
       TREE_THIS_VOLATILE (rval)
        |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
-      return require_complete_type (fold (rval));
+      return require_complete_type (fold_if_not_in_template (rval));
     }
 
   {
@@ -2762,6 +2763,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
      convert it to this type.  */
   tree final_type = 0;
 
+  tree result;
+
   /* Nonzero if this is an operation like MIN or MAX which can
      safely be computed in short if both args are promoted shorts.
      Also implies COMMON.
@@ -2782,6 +2785,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   /* Nonzero means set RESULT_TYPE to the common type of the args.  */
   int common = 0;
 
+  /* True if both operands have arithmetic type.  */
+  bool arithmetic_types_p;
+
   /* Apply default conversions.  */
   op0 = orig_op0;
   op1 = orig_op1;
@@ -3169,14 +3175,31 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
     }
 
-  if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
-      &&
-      (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+  arithmetic_types_p = 
+    ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+     && (code1 == INTEGER_TYPE || code1 == REAL_TYPE 
+        || code1 == COMPLEX_TYPE));
+  /* Determine the RESULT_TYPE, if it is not already known.  */
+  if (!result_type
+      && arithmetic_types_p 
+      && (shorten || common || short_compare))
+    result_type = common_type (type0, type1);
+
+  if (!result_type)
     {
-      int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+      error ("invalid operands of types `%T' and `%T' to binary `%O'",
+            TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
+      return error_mark_node;
+    }
 
-      if (shorten || common || short_compare)
-       result_type = common_type (type0, type1);
+  /* If we're in a template, the only thing we need to know is the
+     RESULT_TYPE.  */
+  if (processing_template_decl)
+    return build2 (resultcode, result_type, op0, op1);
+
+  if (arithmetic_types_p)
+    {
+      int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
@@ -3419,19 +3442,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        }
     }
 
-  /* At this point, RESULT_TYPE must be nonzero to avoid an error message.
-     If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
+  /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
      Then the expression will be built.
      It will be given type FINAL_TYPE if that is nonzero;
      otherwise, it will be given type RESULT_TYPE.  */
 
-  if (!result_type)
-    {
-      error ("invalid operands of types `%T' and `%T' to binary `%O'",
-               TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
-      return error_mark_node;
-    }
-
   /* Issue warnings about peculiar, but valid, uses of NULL.  */
   if (/* It's reasonable to use pointer values as operands of &&
         and ||, so NULL is no exception.  */
@@ -3465,12 +3480,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (build_type == NULL_TREE)
     build_type = result_type;
 
-  {
-    tree result = fold (build2 (resultcode, build_type, op0, op1));
-    if (final_type != 0)
-      result = cp_convert (final_type, result);
-    return result;
-  }
+  result = build2 (resultcode, build_type, op0, op1);
+  result = fold_if_not_in_template (result);
+  if (final_type != 0)
+    result = cp_convert (final_type, result);
+  return result;
 }
 \f
 /* Return a tree for the sum or difference (RESULTCODE says which)
@@ -3488,7 +3502,8 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      pointer_int_sum() anyway.  */
   complete_type (TREE_TYPE (res_type));
 
-  return pointer_int_sum (resultcode, ptrop, fold (intop));
+  return pointer_int_sum (resultcode, ptrop,
+                         fold_if_not_in_template (intop));
 }
 
 /* Return a tree for the difference of pointers OP0 and OP1.
@@ -3532,7 +3547,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype)
   /* Do the division.  */
 
   result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
-  return fold (result);
+  return fold_if_not_in_template (result);
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3782,7 +3797,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+       {
+         arg = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+         return fold_if_not_in_template (arg);
+       }
       else
        return arg;
 
@@ -3790,7 +3808,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+       {
+         arg = build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+         return fold_if_not_in_template (arg);
+       }
       else
        return cp_convert (TREE_TYPE (arg), integer_zero_node);
       
@@ -4133,7 +4154,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
     {
       if (argtype == 0)
        argtype = TREE_TYPE (arg);
-      return fold (build1 (code, argtype, arg));
+      return fold_if_not_in_template (build1 (code, argtype, arg));
     }
 
   error ("%s", errstring);
@@ -4721,21 +4742,21 @@ build_reinterpret_cast (tree type, tree expr)
           || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
     {
       expr = decl_constant_value (expr);
-      return fold (build1 (NOP_EXPR, type, expr));
+      return fold_if_not_in_template (build_nop (type, expr));
     }
   else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
           || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
     {
       check_for_casting_away_constness (intype, type, "reinterpret_cast");
       expr = decl_constant_value (expr);
-      return fold (build1 (NOP_EXPR, type, expr));
+      return fold_if_not_in_template (build_nop (type, expr));
     }
   else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
           || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
     {
       pedwarn ("ISO C++ forbids casting between pointer-to-function and pointer-to-object");
       expr = decl_constant_value (expr);
-      return fold (build1 (NOP_EXPR, type, expr));
+      return fold_if_not_in_template (build_nop (type, expr));
     }
   else
     {
@@ -5382,7 +5403,8 @@ get_delta_difference (tree from, tree to, int force)
        }
     }
 
-  return fold (convert_to_integer (ptrdiff_type_node, result));
+  return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node, 
+                                                     result));
 }
 
 /* Return a constructor for the pointer-to-member-function TYPE using
@@ -5540,36 +5562,41 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
          fn; the call will do the opposite adjustment.  */
       tree orig_class = DECL_CONTEXT (fn);
       tree binfo = binfo_or_else (orig_class, fn_class);
-      *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
-                            *delta, BINFO_OFFSET (binfo)));
+      *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
+                      *delta, BINFO_OFFSET (binfo));
+      *delta = fold_if_not_in_template (*delta);
 
       /* We set PFN to the vtable offset at which the function can be
         found, plus one (unless ptrmemfunc_vbit_in_delta, in which
         case delta is shifted left, and then incremented).  */
       *pfn = DECL_VINDEX (fn);
-      *pfn = fold (build2 (MULT_EXPR, integer_type_node, *pfn,
-                          TYPE_SIZE_UNIT (vtable_entry_type)));
+      *pfn = build2 (MULT_EXPR, integer_type_node, *pfn,
+                    TYPE_SIZE_UNIT (vtable_entry_type));
+      *pfn = fold_if_not_in_template (*pfn);
 
       switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
        {
        case ptrmemfunc_vbit_in_pfn:
-         *pfn = fold (build2 (PLUS_EXPR, integer_type_node, *pfn,
-                              integer_one_node));
+         *pfn = build2 (PLUS_EXPR, integer_type_node, *pfn,
+                        integer_one_node);
+         *pfn = fold_if_not_in_template (*pfn);
          break;
 
        case ptrmemfunc_vbit_in_delta:
-         *delta = fold (build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
-                                *delta, integer_one_node));
-         *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
-                                *delta, integer_one_node));
+         *delta = build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+                          *delta, integer_one_node);
+         *delta = fold_if_not_in_template (*delta);
+         *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
+                          *delta, integer_one_node);
+         *delta = fold_if_not_in_template (*delta);
          break;
 
        default:
          gcc_unreachable ();
        }
 
-      *pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
-                          *pfn));
+      *pfn = build_nop (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
+      *pfn = fold_if_not_in_template (*pfn);
     }
 }
 
@@ -5639,7 +5666,7 @@ dubious_conversion_warnings (tree type, tree expr,
       overflow_warning (expr);
 
       if (TREE_CONSTANT (expr))
-       expr = fold (expr);
+       expr = fold_if_not_in_template (expr);
     }
   return expr;
 }
index 4ac93404a8e62533071d191ce71ce566a2be85f3..c86dd549700229d211281e6f92b1750ba4f8500f 100644 (file)
@@ -330,8 +330,8 @@ layout_decl (tree decl, unsigned int known_align)
     }
   else if (DECL_SIZE_UNIT (decl) == 0)
     DECL_SIZE_UNIT (decl)
-      = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
-                                      bitsize_unit_node));
+      = fold_convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
+                                           bitsize_unit_node));
 
   if (code != FIELD_DECL)
     /* For non-fields, update the alignment from the type.  */
@@ -540,7 +540,8 @@ tree
 bit_from_pos (tree offset, tree bitpos)
 {
   return size_binop (PLUS_EXPR, bitpos,
-                    size_binop (MULT_EXPR, convert (bitsizetype, offset),
+                    size_binop (MULT_EXPR, 
+                                fold_convert (bitsizetype, offset),
                                 bitsize_unit_node));
 }
 
@@ -548,9 +549,9 @@ tree
 byte_from_pos (tree offset, tree bitpos)
 {
   return size_binop (PLUS_EXPR, offset,
-                    convert (sizetype,
-                             size_binop (TRUNC_DIV_EXPR, bitpos,
-                                         bitsize_unit_node)));
+                    fold_convert (sizetype,
+                                  size_binop (TRUNC_DIV_EXPR, bitpos,
+                                              bitsize_unit_node)));
 }
 
 void
@@ -558,9 +559,9 @@ pos_from_bit (tree *poffset, tree *pbitpos, unsigned int off_align,
              tree pos)
 {
   *poffset = size_binop (MULT_EXPR,
-                        convert (sizetype,
-                                 size_binop (FLOOR_DIV_EXPR, pos,
-                                             bitsize_int (off_align))),
+                        fold_convert (sizetype,
+                                      size_binop (FLOOR_DIV_EXPR, pos,
+                                                  bitsize_int (off_align))),
                         size_int (off_align / BITS_PER_UNIT));
   *pbitpos = size_binop (FLOOR_MOD_EXPR, pos, bitsize_int (off_align));
 }
@@ -580,7 +581,8 @@ normalize_offset (tree *poffset, tree *pbitpos, unsigned int off_align)
 
       *poffset
        = size_binop (PLUS_EXPR, *poffset,
-                     size_binop (MULT_EXPR, convert (sizetype, extra_aligns),
+                     size_binop (MULT_EXPR, 
+                                 fold_convert (sizetype, extra_aligns),
                                  size_int (off_align / BITS_PER_UNIT)));
 
       *pbitpos
@@ -869,9 +871,9 @@ place_field (record_layout_info rli, tree field)
          /* First adjust OFFSET by the partial bits, then align.  */
          rli->offset
            = size_binop (PLUS_EXPR, rli->offset,
-                         convert (sizetype,
-                                  size_binop (CEIL_DIV_EXPR, rli->bitpos,
-                                              bitsize_unit_node)));
+                         fold_convert (sizetype,
+                                       size_binop (CEIL_DIV_EXPR, rli->bitpos,
+                                                   bitsize_unit_node)));
          rli->bitpos = bitsize_zero_node;
 
          rli->offset = round_up (rli->offset, desired_align / BITS_PER_UNIT);
@@ -1147,9 +1149,9 @@ place_field (record_layout_info rli, tree field)
     {
       rli->offset
        = size_binop (PLUS_EXPR, rli->offset,
-                     convert (sizetype,
-                              size_binop (CEIL_DIV_EXPR, rli->bitpos,
-                                          bitsize_unit_node)));
+                     fold_convert (sizetype,
+                                   size_binop (CEIL_DIV_EXPR, rli->bitpos,
+                                               bitsize_unit_node)));
       rli->offset
        = size_binop (PLUS_EXPR, rli->offset, DECL_SIZE_UNIT (field));
       rli->bitpos = bitsize_zero_node;
@@ -1353,9 +1355,9 @@ finalize_type_size (tree type)
        result will fit in sizetype.  We will get more efficient code using
        sizetype, so we force a conversion.  */
     TYPE_SIZE_UNIT (type)
-      = convert (sizetype,
-                size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
-                            bitsize_unit_node));
+      = fold_convert (sizetype,
+                     size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
+                                 bitsize_unit_node));
 
   if (TYPE_SIZE (type) != 0)
     {
@@ -1638,10 +1640,10 @@ layout_type (tree type)
            /* The initial subtraction should happen in the original type so
               that (possible) negative values are handled appropriately.  */
            length = size_binop (PLUS_EXPR, size_one_node,
-                                convert (sizetype,
-                                         fold (build2 (MINUS_EXPR,
-                                                       TREE_TYPE (lb),
-                                                       ub, lb))));
+                                fold_convert (sizetype,
+                                              fold (build2 (MINUS_EXPR,
+                                                            TREE_TYPE (lb),
+                                                            ub, lb))));
 
            /* Special handling for arrays of bits (for Chill).  */
            element_size = TYPE_SIZE (element);
@@ -1670,7 +1672,8 @@ layout_type (tree type)
              length = size_binop (MAX_EXPR, length, size_zero_node);
 
            TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
-                                          convert (bitsizetype, length));
+                                          fold_convert (bitsizetype, 
+                                                        length));
 
            /* If we know the size of the element, calculate the total
               size directly, rather than do some division thing below.
index eb4165c93b3e3dd976f596ccdf86380214740709..29293815d8cddbdd901e5c79e4d8eca262086397 100644 (file)
@@ -8,6 +8,10 @@
        PR fortran/16938
        * gfortran.dg/pr16938.f90: New test.
 
+2004-09-27  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/template/crash23.C: New test.
+
 2004-09-27  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/17585
diff --git a/gcc/testsuite/g++.dg/template/crash23.C b/gcc/testsuite/g++.dg/template/crash23.C
new file mode 100644 (file)
index 0000000..0c3eac1
--- /dev/null
@@ -0,0 +1,9 @@
+// PR c++/17642
+
+template<int dim>
+int f(const int* const lsh, const int* const bbox, const int* const nghostzones, int d)
+{
+  for (int d=0; d<dim; ++d)
+    lsh[d] - (bbox[2*d+1] ? 0 : nghostzones[d]);
+}
+
index 0237d072271d9e4c45df92c5f594bded756b81ea..c3912e9ee72a76327782a848dbf26cbf39cf49a1 100644 (file)
@@ -4218,7 +4218,7 @@ build_index_type (tree maxval)
   TREE_TYPE (itype) = sizetype;
   TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
   TYPE_MIN_VALUE (itype) = size_zero_node;
-  TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
+  TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval);
   TYPE_MODE (itype) = TYPE_MODE (sizetype);
   TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
   TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);