This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++] Fix 18905


This fixes 18905 where we erroneously reject a templated array index.
The primary cause of this is because we don't do lazy constant folding
at the point of use, but scatter it throughout the compiler.  As out template
machinery gets more correct about dependent/non-dependent types
and expressions this bites us.

The patch replaces decl_constant_value with a new integral_constant_value
which only processes those types the standard says it should process.  In
doing this, it breaks an optimization tested for by static3.C, namely that we
do see through such initializers.  However, I think it reasonable to only
make sure we do that when we're actually optimizing -- hence the optimizer
switch.

booted & tested on i686-pc-linux-gnu.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2004-12-16  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/18905
	* cp-tree.h (integral_constant_value): Declare.
	* call.c (null_ptr_cst_p): Use integral_constant_value, not
	decl_constant_value.
	(convert_like_real): Likewise.
	* class.c (check_bitfield_decl): Likewise.
	* cvt.c (ocp_convert): Likewise.
	(convert): Remove unnecessary decl_constant_value call.
	* decl.c (compute_array_index_type): Use integral_constant_value,
	not decl_constant_value.
	(build_enumerator): Likewise.
	* decl2.c (grokfield): Likewise.
	* init.c (decl_constant_value): Simplify.
	(integral_constant_value): New.
	* pt.c (fold_decl_constant_value): Use integral_constant_value,
	remove subsequent check.
	(tsubst): Use integral_constant_value, not decl_constant_value.
	(tsubst_copy, unify): Likewise.
	* typeck.c (decay_conversion): Likewise.
	(build_compound_expr): Remove unnecessary decl_constant_value
	calls.
	(build_static_cast_1, build_reinterpret_cast_1):
	(convert_for_assignment): Remove comment about not calling
	decl_constant_value.

2004-12-16  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/18905
	* g++.dg/template/init4.C: New.
	* g++.dg/opt/static3.C: Enable optimizer.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.522
diff -c -3 -p -r1.522 call.c
*** cp/call.c	8 Dec 2004 08:35:33 -0000	1.522
--- cp/call.c	16 Dec 2004 10:26:19 -0000
*************** null_ptr_cst_p (tree t)
*** 428,435 ****
  
       A null pointer constant is an integral constant expression
       (_expr.const_) rvalue of integer type that evaluates to zero.  */
!   if (DECL_INTEGRAL_CONSTANT_VAR_P (t))
!     t = decl_constant_value (t);
    if (t == null_node
        || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
      return true;
--- 428,434 ----
  
       A null pointer constant is an integral constant expression
       (_expr.const_) rvalue of integer type that evaluates to zero.  */
!   t = integral_constant_value (t);
    if (t == null_node
        || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
      return true;
*************** convert_like_real (conversion *convs, tr
*** 4227,4238 ****
      case ck_identity:
        if (type_unknown_p (expr))
  	expr = instantiate_type (totype, expr, tf_error | tf_warning);
!       /* Convert a non-array constant variable to its underlying value, unless we
! 	 are about to bind it to a reference, in which case we need to
  	 leave it as an lvalue.  */
!       if (inner >= 0
! 	  && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
! 	expr = decl_constant_value (expr);
        if (convs->check_copy_constructor_p)
  	check_constructor_callable (totype, expr);
        return expr;
--- 4226,4236 ----
      case ck_identity:
        if (type_unknown_p (expr))
  	expr = instantiate_type (totype, expr, tf_error | tf_warning);
!       /* Convert a constant to its underlying value, unless we are
! 	 about to bind it to a reference, in which case we need to
  	 leave it as an lvalue.  */
!       if (inner >= 0)
! 	expr = integral_constant_value (expr);
        if (convs->check_copy_constructor_p)
  	check_constructor_callable (totype, expr);
        return expr;
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.694
diff -c -3 -p -r1.694 class.c
*** cp/class.c	14 Dec 2004 02:21:46 -0000	1.694
--- cp/class.c	16 Dec 2004 10:26:35 -0000
*************** check_bitfield_decl (tree field)
*** 2613,2622 ****
        STRIP_NOPS (w);
  
        /* detect invalid field size.  */
!       if (TREE_CODE (w) == CONST_DECL)
! 	w = DECL_INITIAL (w);
!       else
! 	w = decl_constant_value (w);
  
        if (TREE_CODE (w) != INTEGER_CST)
  	{
--- 2613,2619 ----
        STRIP_NOPS (w);
  
        /* detect invalid field size.  */
!       w = integral_constant_value (w);
  
        if (TREE_CODE (w) != INTEGER_CST)
  	{
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1080
diff -c -3 -p -r1.1080 cp-tree.h
*** cp/cp-tree.h	8 Dec 2004 08:35:34 -0000	1.1080
--- cp/cp-tree.h	16 Dec 2004 10:26:47 -0000
*************** extern tree build_vec_delete			(tree, tr
*** 3917,3922 ****
--- 3917,3923 ----
  extern tree create_temporary_var                (tree);
  extern void initialize_vtbl_ptrs                (tree);
  extern tree build_java_class_ref                (tree);
+ extern tree integral_constant_value 		(tree);
  
  /* in lex.c */
  extern void cxx_dup_lang_specific_decl		(tree);
Index: cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.173
diff -c -3 -p -r1.173 cvt.c
*** cp/cvt.c	8 Dec 2004 08:35:35 -0000	1.173
--- cp/cvt.c	16 Dec 2004 10:26:50 -0000
*************** ocp_convert (tree type, tree expr, int c
*** 621,627 ****
    complete_type (type);
    complete_type (TREE_TYPE (expr));
  
!   e = decl_constant_value (e);
  
    if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
        /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
--- 621,627 ----
    complete_type (type);
    complete_type (TREE_TYPE (expr));
  
!   e = integral_constant_value (e);
  
    if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
        /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
*************** convert (tree type, tree expr)
*** 945,954 ****
    intype = TREE_TYPE (expr);
  
    if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
!     {
!       expr = decl_constant_value (expr);
!       return fold_if_not_in_template (build_nop (type, expr));
!     }
  
    return ocp_convert (type, expr, CONV_OLD_CONVERT,
  		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
--- 945,951 ----
    intype = TREE_TYPE (expr);
  
    if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
!     return fold_if_not_in_template (build_nop (type, expr));
  
    return ocp_convert (type, expr, CONV_OLD_CONVERT,
  		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1341
diff -c -3 -p -r1.1341 decl.c
*** cp/decl.c	15 Dec 2004 00:42:31 -0000	1.1341
--- cp/decl.c	16 Dec 2004 10:27:14 -0000
*************** cp_finish_decl (tree decl, tree init, tr
*** 4853,4858 ****
--- 4853,4859 ----
  	  && !DECL_PRETTY_FUNCTION_P (decl)
  	  && !dependent_type_p (TREE_TYPE (decl)))
  	maybe_deduce_size_from_array_init (decl, init);
+       
        goto finish_end;
      }
  
*************** compute_array_index_type (tree name, tre
*** 6207,6213 ****
    STRIP_TYPE_NOPS (size);
  
    /* It might be a const variable or enumeration constant.  */
!   size = decl_constant_value (size);
  
    /* Normally, the array-bound will be a constant.  */
    if (TREE_CODE (size) == INTEGER_CST)
--- 6208,6214 ----
    STRIP_TYPE_NOPS (size);
  
    /* It might be a const variable or enumeration constant.  */
!   size = integral_constant_value (size);
  
    /* Normally, the array-bound will be a constant.  */
    if (TREE_CODE (size) == INTEGER_CST)
*************** build_enumerator (tree name, tree value,
*** 9792,9798 ****
        /* Validate and default VALUE.  */
        if (value != NULL_TREE)
  	{
! 	  value = decl_constant_value (value);
  
  	  if (TREE_CODE (value) == INTEGER_CST)
  	    {
--- 9793,9799 ----
        /* Validate and default VALUE.  */
        if (value != NULL_TREE)
  	{
! 	  value = integral_constant_value (value);
  
  	  if (TREE_CODE (value) == INTEGER_CST)
  	    {
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.760
diff -c -3 -p -r1.760 decl2.c
*** cp/decl2.c	8 Dec 2004 08:35:41 -0000	1.760
--- cp/decl2.c	16 Dec 2004 10:27:25 -0000
*************** grokfield (const cp_declarator *declarat
*** 917,928 ****
  
  	  if (!processing_template_decl)
  	    {
! 	      if (TREE_CODE (init) == CONST_DECL)
! 		init = DECL_INITIAL (init);
! 	      else if (TREE_READONLY_DECL_P (init))
! 		init = decl_constant_value (init);
! 	      else if (TREE_CODE (init) == CONSTRUCTOR)
  		init = digest_init (TREE_TYPE (value), init, (tree *)0);
  	      if (init != error_mark_node && ! TREE_CONSTANT (init))
  		{
  		  /* We can allow references to things that are effectively
--- 917,927 ----
  
  	  if (!processing_template_decl)
  	    {
! 	      if (TREE_CODE (init) == CONSTRUCTOR)
  		init = digest_init (TREE_TYPE (value), init, (tree *)0);
+ 	      else
+ 		init = integral_constant_value (init);
+ 	      
  	      if (init != error_mark_node && ! TREE_CONSTANT (init))
  		{
  		  /* We can allow references to things that are effectively
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.405
diff -c -3 -p -r1.405 init.c
*** cp/init.c	14 Dec 2004 20:13:03 -0000	1.405
--- cp/init.c	16 Dec 2004 10:27:37 -0000
*************** build_offset_ref (tree type, tree name, 
*** 1558,1605 ****
    return member;
  }
  
! /* If DECL is a `const' declaration, and its value is a known
!    constant, then return that value.  */
  
  tree
! decl_constant_value (tree decl)
  {
!   /* When we build a COND_EXPR, we don't know whether it will be used
!      as an lvalue or as an rvalue.  If it is an lvalue, it's not safe
!      to replace the second and third operands with their
!      initializers.  So, we do that here.  */
!   if (TREE_CODE (decl) == COND_EXPR)
!     {
!       tree d1;
!       tree d2;
! 
!       d1 = decl_constant_value (TREE_OPERAND (decl, 1));
!       d2 = decl_constant_value (TREE_OPERAND (decl, 2));
! 
!       if (d1 != TREE_OPERAND (decl, 1) || d2 != TREE_OPERAND (decl, 2))
! 	return build3 (COND_EXPR,
! 		       TREE_TYPE (decl),
! 		       TREE_OPERAND (decl, 0), d1, d2);
!     }
! 
!   if (DECL_P (decl)
!       && (/* Enumeration constants are constant.  */
! 	  TREE_CODE (decl) == CONST_DECL
  	  /* And so are variables with a 'const' type -- unless they
  	     are also 'volatile'.  */
! 	  || CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))
!       && TREE_CODE (decl) != PARM_DECL
        && DECL_INITIAL (decl)
        && DECL_INITIAL (decl) != error_mark_node
!       /* This is invalid if initial value is not constant.
! 	 If it has either a function call, a memory reference,
! 	 or a variable, then re-evaluating it could give different results.  */
!       && TREE_CONSTANT (DECL_INITIAL (decl))
!       /* Check for cases where this is sub-optimal, even though valid.  */
!       && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
      return DECL_INITIAL (decl);
    return decl;
  }
  
  /* Common subroutines of build_new and build_vec_delete.  */
  
--- 1558,1607 ----
    return member;
  }
  
! /* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by
!    constant of integral or enumeration type, then return that value.
!    These are those variables permitted in constant expressions by
!    [5.19/1].  FIXME:If we did lazy folding, this could be localized.  */
  
  tree
! integral_constant_value (tree decl)
  {
!   if ((TREE_CODE (decl) == CONST_DECL
!       || (TREE_CODE (decl) == VAR_DECL
  	  /* And so are variables with a 'const' type -- unless they
  	     are also 'volatile'.  */
! 	  && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))
! 	  && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))
        && DECL_INITIAL (decl)
        && DECL_INITIAL (decl) != error_mark_node
!       && TREE_TYPE (DECL_INITIAL (decl))
!       && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
      return DECL_INITIAL (decl);
    return decl;
  }
+ 
+ /* A more relaxed version of integral_constant_value, for which type
+    is not considered.  This is used by the common C/C++ code, and not
+    directly by the C++ front end.  */
+ 
+ tree
+ decl_constant_value (tree decl)
+ {
+   if ((TREE_CODE (decl) == CONST_DECL
+       || (TREE_CODE (decl) == VAR_DECL
+ 	  /* And so are variables with a 'const' type -- unless they
+              are also 'volatile'.  */
+ 	  && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))
+       && DECL_INITIAL (decl)
+       && DECL_INITIAL (decl) != error_mark_node
+       /* This is invalid if initial value is not constant.  If it has
+        	 either a function call, a memory reference, or a variable,
+        	 then re-evaluating it could give different results.  */
+       && TREE_CONSTANT (DECL_INITIAL (decl)))
+     return DECL_INITIAL (decl);
+   
+   return decl;
+ }
  
  /* Common subroutines of build_new and build_vec_delete.  */
  
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.957
diff -c -3 -p -r1.957 pt.c
*** cp/pt.c	14 Dec 2004 15:38:55 -0000	1.957
--- cp/pt.c	16 Dec 2004 10:28:25 -0000
*************** fold_non_dependent_expr (tree expr)
*** 3310,3346 ****
     For instance, it could be a VAR_DECL with a constant initializer.
     Extract the innest constant expression.
     
!    This is basically a more powerful version of decl_constant_value, which
!    can be used also in templates where initializers can maintain a
!    syntactic rather than semantic form (even if they are non-dependent, for
!    access-checking purposes).  */
  
  tree
  fold_decl_constant_value (tree expr)
  {
    while (true)
      {
!       tree const_expr = decl_constant_value (expr);
!       /* In a template, the initializer for a VAR_DECL may not be
! 	 marked as TREE_CONSTANT, in which case decl_constant_value
! 	 will not return the initializer.  Handle that special case
! 	 here.  */
!       if (expr == const_expr
! 	  && TREE_CODE (expr) == VAR_DECL
! 	  && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr)
! 	  && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr))
! 	  /* DECL_INITIAL can be NULL if we are processing a
! 	     variable initialized to an expression involving itself.
! 	     We know it is initialized to a constant -- but not what
! 	     constant, yet.  */
! 	  && DECL_INITIAL (expr))
! 	const_expr = DECL_INITIAL (expr);
        if (expr == const_expr)
  	break;
        expr = fold_non_dependent_expr (const_expr);
      }
  
!     return expr;
  }
  
  /* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
--- 3310,3332 ----
     For instance, it could be a VAR_DECL with a constant initializer.
     Extract the innest constant expression.
     
!    This is basically a more powerful version of
!    integral_constant_value, which can be used also in templates where
!    initializers can maintain a syntactic rather than semantic form
!    (even if they are non-dependent, for access-checking purposes).  */
  
  tree
  fold_decl_constant_value (tree expr)
  {
    while (true)
      {
!       tree const_expr = integral_constant_value (expr);
        if (expr == const_expr)
  	break;
        expr = fold_non_dependent_expr (const_expr);
      }
  
!   return expr;
  }
  
  /* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
*************** tsubst (tree t, tree args, tsubst_flags_
*** 6962,6968 ****
  	   in that we want to fold it as much as possible.  */
  	max = tsubst_template_arg (omax, args, complain, in_decl);
  	if (!processing_template_decl)
! 	  max = decl_constant_value (max);
  
  	if (integer_zerop (omax))
  	  {
--- 6948,6954 ----
  	   in that we want to fold it as much as possible.  */
  	max = tsubst_template_arg (omax, args, complain, in_decl);
  	if (!processing_template_decl)
! 	  max = integral_constant_value (max);
  
  	if (integer_zerop (omax))
  	  {
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 7665,7671 ****
  	  return t;
  	/* If ARGS is NULL, then T is known to be non-dependent.  */
  	if (args == NULL_TREE)
! 	  return decl_constant_value (t);
  
  	/* Unfortunately, we cannot just call lookup_name here.
  	   Consider:
--- 7651,7657 ----
  	  return t;
  	/* If ARGS is NULL, then T is known to be non-dependent.  */
  	if (args == NULL_TREE)
! 	  return integral_constant_value (t);
  
  	/* Unfortunately, we cannot just call lookup_name here.
  	   Consider:
*************** unify (tree tparms, tree targs, tree par
*** 10293,10299 ****
      case CONST_DECL:
        if (DECL_TEMPLATE_PARM_P (parm))
  	return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
!       if (arg != decl_constant_value (parm)) 
  	return 1;
        return 0;
  
--- 10279,10285 ----
      case CONST_DECL:
        if (DECL_TEMPLATE_PARM_P (parm))
  	return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
!       if (arg != integral_constant_value (parm)) 
  	return 1;
        return 0;
  
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.604
diff -c -3 -p -r1.604 typeck.c
*** cp/typeck.c	14 Dec 2004 15:38:58 -0000	1.604
--- cp/typeck.c	16 Dec 2004 10:28:51 -0000
*************** decay_conversion (tree exp)
*** 1351,1370 ****
        cxx_incomplete_type_error (exp, TREE_TYPE (exp));
        return error_mark_node;
      }
-   
-   /* Constants can be used directly unless they're not loadable.  */
-   if (TREE_CODE (exp) == CONST_DECL)
-     exp = DECL_INITIAL (exp);
-   /* Replace a nonvolatile const static variable with its value.  We
-      don't do this for arrays, though; we want the address of the
-      first element of the array, not the address of the first element
-      of its initializing constant.  */
-   else if (code != ARRAY_TYPE)
-     {
-       exp = decl_constant_value (exp);
-       type = TREE_TYPE (exp);
-     }
  
    /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
       Leave such NOP_EXPRs, since RHS is being used in non-lvalue context.  */
  
--- 1351,1359 ----
        cxx_incomplete_type_error (exp, TREE_TYPE (exp));
        return error_mark_node;
      }
  
+   exp = integral_constant_value (exp);
+   
    /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
       Leave such NOP_EXPRs, since RHS is being used in non-lvalue context.  */
  
*************** build_x_compound_expr (tree op1, tree op
*** 4450,4456 ****
  tree
  build_compound_expr (tree lhs, tree rhs)
  {
-   lhs = decl_constant_value (lhs);
    lhs = convert_to_void (lhs, "left-hand operand of comma");
    
    if (lhs == error_mark_node || rhs == error_mark_node)
--- 4439,4444 ----
*************** build_static_cast_1 (tree type, tree exp
*** 4666,4672 ****
        || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
  	  && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
      {
-       expr = decl_constant_value (expr);
        expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
  
        /* Ignore any integer overflow caused by the cast.  */
--- 4654,4659 ----
*************** build_reinterpret_cast_1 (tree type, tre
*** 4918,4927 ****
      ;
    else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
  	   || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
!     {
!       expr = decl_constant_value (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)))
      {
--- 4905,4911 ----
      ;
    else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
  	   || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
!     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)))
      {
*************** build_reinterpret_cast_1 (tree type, tre
*** 4938,4944 ****
  	warning ("cast from %qT to %qT increases required alignment of "
  		 "target type",
  		 intype, type);
!       expr = decl_constant_value (expr);
        return fold_if_not_in_template (build_nop (type, expr));
      }
    else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
--- 4922,4928 ----
  	warning ("cast from %qT to %qT increases required alignment of "
  		 "target type",
  		 intype, type);
!       
        return fold_if_not_in_template (build_nop (type, expr));
      }
    else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
*************** build_reinterpret_cast_1 (tree type, tre
*** 4950,4957 ****
   	   addresses this issue, but as of 2004/10/26 is still in
   	   drafting.  */
   	warning ("ISO C++ forbids casting between pointer-to-function and pointer-to-object");
-       
-       expr = decl_constant_value (expr);
        return fold_if_not_in_template (build_nop (type, expr));
      }
    else if (TREE_CODE (type) == VECTOR_TYPE)
--- 4934,4939 ----
*************** convert_for_assignment (tree type, tree 
*** 5926,5941 ****
    if (TREE_CODE (rhs) == CONST_DECL)
      rhs = DECL_INITIAL (rhs);
    
-   /* We do not use decl_constant_value here because of this case:
- 
-        const char* const s = "s";
-  
-      The conversion rules for a string literal are more lax than for a
-      variable; in particular, a string literal can be converted to a
-      "char *" but the variable "s" cannot be converted in the same
-      way.  If the conversion is allowed, the optimization should be
-      performed while creating the converted expression.  */
- 
    /* [expr.ass]
  
       The expression is implicitly converted (clause _conv_) to the
--- 5908,5913 ----
Index: testsuite/g++.dg/opt/static3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/opt/static3.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 static3.C
*** testsuite/g++.dg/opt/static3.C	28 Aug 2003 07:14:25 -0000	1.1
--- testsuite/g++.dg/opt/static3.C	16 Dec 2004 10:28:57 -0000
***************
*** 1,4 ****
--- 1,5 ----
  // { dg-do link }
+ // { dg-options "-O2" }
  
  class Foo {
  public:
// { dg-do compile }

// Copyright (C) 2004 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Dec 2004 <nathan@codesourcery.com>

// PR 18905. bogus error
// Origin:  Andrew Pinski  <pinskia@gcc.gnu.org>

int f1(char);
template <int t>
void f(void)
{
 const char* const suffixes = "plpv";
 f1(suffixes[t]);
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]