This is the mail archive of the gcc-bugs@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]

[Bug c++/20103] [4.0/4.1 regression] ICE in create_tmp_var with C99 style struct initializer


------- Additional Comments From aoliva at gcc dot gnu dot org  2005-03-08 21:55 -------
Subject: Re: [PR c++/20103] failure to gimplify constructors for addressable types

On Mar  8, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> Okie dokie, how about this?

> The change to the gimplify.c is needed to avoid having
> gimple_add_tmp_var twice for the variable, once while expanding the
> declaration/initialization, once while expanding the clean-ups.

> Ok to install?  Passed check-g++ (except for the already-broken
> eh/cleanup1.C) on x86_64-linux-gnu; just started bootstrap and full
> reg-testing.

Err...  *This* was the one that passed check-g++.  The one I posted in
a hurry earlier was very incomplete, and contained fragments of other
patches.  Sorry about that.

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/20103
	* gimplify.c (gimplify_decl_expr): Don't add temp variable if it
	was already seen in a bind expr.

Index: gcc/gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.115
diff -u -p -r2.115 gimplify.c
--- gcc/gimplify.c 8 Mar 2005 13:56:57 -0000 2.115
+++ gcc/gimplify.c 8 Mar 2005 21:48:41 -0000
@@ -1047,7 +1047,8 @@ gimplify_decl_expr (tree *stmt_p)
       /* This decl isn't mentioned in the enclosing block, so add it to the
 	 list of temps.  FIXME it seems a bit of a kludge to say that
 	 anonymous artificial vars aren't pushed, but everything else is.  */
-      if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+      if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE
+	  && !DECL_SEEN_IN_BIND_EXPR_P (decl))
 	gimple_add_tmp_var (decl);
     }
 
Index: gcc/cp/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/20103
	* cp-tree.h (build_compound_literal): Declare.
	* semantics.c (finish_compound_literal): Move most of the code...
	* tree.c (build_compound_literal): ... here.  New function.
	(lvalue_p_1): Handle COMPOUND_LITERAL_EXPR.
	(stabilize_init): Likewise.
	* pt.c (tsubst_copy_and_build): Likewise.
	* call.c (build_over_call): Likewise.
	* class.c (fixed_type_or_null): Likewise.
	* cp-gimplify.c (cp_gimplify_init_expr): Likewise.
	* cvt.c (force_rvalue, ocp_convert): Likewise.
	* typeck.c (build_x_unary_op): Likewise.
	(cxx_mark_addressable): Likewise.
	(maybe_warn_about_returning_address_of_local): Likewise.

Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1107
diff -u -p -r1.1107 cp-tree.h
--- gcc/cp/cp-tree.h 1 Mar 2005 09:57:38 -0000 1.1107
+++ gcc/cp/cp-tree.h 8 Mar 2005 21:48:50 -0000
@@ -4218,6 +4218,7 @@ extern tree build_min_nt			(enum tree_co
 extern tree build_min_non_dep			(enum tree_code, tree, ...);
 extern tree build_cplus_new			(tree, tree);
 extern tree get_target_expr			(tree);
+extern tree build_compound_literal		(tree, tree);
 extern tree build_cplus_array_type		(tree, tree);
 extern tree hash_tree_cons			(tree, tree, tree);
 extern tree hash_tree_chain			(tree, tree);
Index: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.463
diff -u -p -r1.463 semantics.c
--- gcc/cp/semantics.c 23 Feb 2005 05:30:48 -0000 1.463
+++ gcc/cp/semantics.c 8 Mar 2005 21:48:52 -0000
@@ -1980,23 +1980,16 @@ finish_compound_literal (tree type, tree
   compound_literal = build_constructor (NULL_TREE, initializer_list);
   /* Mark it as a compound-literal.  */
   TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+
   if (processing_template_decl)
+    /* This causes template substitution to run digest_init on the
+       CONSTRUCTOR.  */
     TREE_TYPE (compound_literal) = type;
   else
-    {
-      /* Check the initialization.  */
-      compound_literal = digest_init (type, compound_literal, NULL);
-      /* If the TYPE was an array type with an unknown bound, then we can
-	 figure out the dimension now.  For example, something like:
-
-	   `(int []) { 2, 3 }'
-
-	 implies that the array has two elements.  */
-      if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
-	complete_array_type (type, compound_literal, 1);
-    }
+    /* Check the initialization.  */
+    compound_literal = digest_init (type, compound_literal, NULL);
 
-  return compound_literal;
+  return build_compound_literal (type, compound_literal);
 }
 
 /* Return the declaration for the function-name variable indicated by
Index: gcc/cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.427
diff -u -p -r1.427 tree.c
--- gcc/cp/tree.c 21 Feb 2005 23:12:27 -0000 1.427
+++ gcc/cp/tree.c 8 Mar 2005 21:48:53 -0000
@@ -154,6 +154,7 @@ lvalue_p_1 (tree ref,
 			 treat_class_rvalues_as_lvalues);
 
     case TARGET_EXPR:
+    case COMPOUND_LITERAL_EXPR:
       return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
 
     case CALL_EXPR:
@@ -365,6 +366,43 @@ get_target_expr (tree init)
   return build_target_expr_with_type (init, TREE_TYPE (init));
 }
 
+/* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the
+   compound literal, which may be an incomplete array type completed
+   by the initializer; COMPOUND_LITERAL is a CONSTRUCTOR that
+   initializes the compound literal.  */
+
+tree
+build_compound_literal (tree type, tree compound_literal)
+{
+  /* We do not use start_decl here because we have a type, not a declarator;
+     and do not use finish_decl because the decl should be stored inside
+     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR.  */
+  tree decl;
+  tree complit;
+  tree stmt;
+
+  if (type == error_mark_node || compound_literal == error_mark_node)
+    return error_mark_node;
+
+  /* If the TYPE was an array type with an unknown bound, then we can
+     figure out the dimension now.  For example, something like:
+
+     `(int []) { 2, 3 }'
+
+     implies that the array has two elements.  */
+  if (!processing_template_decl
+      && TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+    complete_array_type (type, compound_literal, 1);
+
+  decl = build_local_temp (type);
+  DECL_INITIAL (decl) = compound_literal;
+
+  stmt = build_stmt (DECL_EXPR, decl);
+  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+  TREE_SIDE_EFFECTS (complit) = 1;
+
+  return complit;
+}
 
 static tree
 build_cplus_array_type_1 (tree elt_type, tree index_type)
@@ -2241,6 +2279,8 @@ stabilize_init (tree init, tree *initp)
 	t = TREE_OPERAND (t, 1);
       if (TREE_CODE (t) == TARGET_EXPR)
 	t = TARGET_EXPR_INITIAL (t);
+      if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+	t = DECL_INITIAL (COMPOUND_LITERAL_EXPR_DECL (t));
       if (TREE_CODE (t) == COMPOUND_EXPR)
 	t = expr_last (t);
       if (TREE_CODE (t) == CONSTRUCTOR
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.979
diff -u -p -r1.979 pt.c
--- gcc/cp/pt.c 5 Mar 2005 15:44:20 -0000 1.979
+++ gcc/cp/pt.c 8 Mar 2005 21:49:01 -0000
@@ -8744,6 +8744,11 @@ tsubst_copy_and_build (tree t, 
       return build_throw
 	(RECUR (TREE_OPERAND (t, 0)));
 
+    case COMPOUND_LITERAL_EXPR:
+      return build_compound_literal
+	(RECUR (TREE_TYPE (COMPOUND_LITERAL_EXPR_DECL (t))),
+	 RECUR (DECL_INITIAL (COMPOUND_LITERAL_EXPR_DECL (t))));
+
     case CONSTRUCTOR:
       {
 	tree r;
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.531
diff -u -p -r1.531 call.c
--- gcc/cp/call.c 24 Feb 2005 21:55:10 -0000 1.531
+++ gcc/cp/call.c 8 Mar 2005 21:49:05 -0000
@@ -4850,12 +4850,14 @@ build_over_call (struct z_candidate *can
          temp or an INIT_EXPR otherwise.  */
       if (integer_zerop (TREE_VALUE (args)))
 	{
-	  if (TREE_CODE (arg) == TARGET_EXPR)
+	  if (TREE_CODE (arg) == TARGET_EXPR
+	      || TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
 	    return arg;
 	  else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
 	    return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
 	}
       else if (TREE_CODE (arg) == TARGET_EXPR
+	       || TREE_CODE (arg) == COMPOUND_LITERAL_EXPR
 	       || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
 	{
 	  tree to = stabilize_reference
Index: gcc/cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.709
diff -u -p -r1.709 class.c
--- gcc/cp/class.c 7 Mar 2005 23:08:57 -0000 1.709
+++ gcc/cp/class.c 8 Mar 2005 21:49:10 -0000
@@ -5234,6 +5234,7 @@ fixed_type_or_null (tree instance, int* 
 	}
       /* fall through...  */
     case TARGET_EXPR:
+    case COMPOUND_LITERAL_EXPR:
     case PARM_DECL:
     case RESULT_DECL:
       if (IS_AGGR_TYPE (TREE_TYPE (instance)))
Index: gcc/cp/cp-gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-gimplify.c,v
retrieving revision 1.17
diff -u -p -r1.17 cp-gimplify.c
--- gcc/cp/cp-gimplify.c 22 Dec 2004 18:00:38 -0000 1.17
+++ gcc/cp/cp-gimplify.c 8 Mar 2005 21:49:10 -0000
@@ -1,6 +1,6 @@
 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
 
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Jason Merrill <jason@redhat.com>
 
 This file is part of GCC.
@@ -125,6 +125,8 @@ cp_gimplify_init_expr (tree *expr_p, tre
     from = TARGET_EXPR_INITIAL (from);
   if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
     from = TREE_OPERAND (from, 0);
+  if (TREE_CODE (from) == COMPOUND_LITERAL_EXPR)
+    from = DECL_INITIAL (COMPOUND_LITERAL_EXPR_DECL (from));
 
   /* Look through any COMPOUND_EXPRs.  */
   sub = expr_last (from);
Index: gcc/cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.180
diff -u -p -r1.180 cvt.c
--- gcc/cp/cvt.c 9 Feb 2005 02:53:37 -0000 1.180
+++ gcc/cp/cvt.c 8 Mar 2005 21:49:11 -0000
@@ -575,7 +575,8 @@ convert_from_reference (tree val)
 tree
 force_rvalue (tree expr)
 {
-  if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
+  if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR
+      && TREE_CODE (expr) != COMPOUND_LITERAL_EXPR)
     expr = ocp_convert (TREE_TYPE (expr), expr,
 			CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
   else
@@ -640,6 +641,16 @@ ocp_convert (tree type, tree expr, int c
 	  TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
 	  return e;
 	}
+      else if (TREE_CODE (e) == COMPOUND_LITERAL_EXPR)
+	{
+	  /* Don't build a NOP_EXPR of class type.  Instead, change the
+	     type of the temporary.  Only allow this for cv-qual changes,
+	     though.  */
+	  gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
+				   TYPE_MAIN_VARIANT (type)));
+	  TREE_TYPE (e) = TREE_TYPE (COMPOUND_LITERAL_EXPR_DECL (e)) = type;
+	  return e;
+	}	  
       else
 	{
 	  /* We shouldn't be treating objects of ADDRESSABLE type as
Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.617
diff -u -p -r1.617 typeck.c
--- gcc/cp/typeck.c 5 Mar 2005 15:44:20 -0000 1.617
+++ gcc/cp/typeck.c 8 Mar 2005 21:49:15 -0000
@@ -3590,7 +3590,8 @@ build_x_unary_op (enum tree_code code, t
 	      PTRMEM_OK_P (xarg) = ptrmem;
 	    }	      
         }
-      else if (TREE_CODE (xarg) == TARGET_EXPR)
+      else if (TREE_CODE (xarg) == TARGET_EXPR
+	       || TREE_CODE (xarg) == COMPOUND_LITERAL_EXPR)
 	warning ("taking address of temporary");
       exp = build_unary_op (ADDR_EXPR, xarg, 0);
     }
@@ -4323,7 +4324,12 @@ cxx_mark_addressable (tree exp)
 
       case TARGET_EXPR:
 	TREE_ADDRESSABLE (x) = 1;
-	cxx_mark_addressable (TREE_OPERAND (x, 0));
+	cxx_mark_addressable (TARGET_EXPR_SLOT (x));
+	return true;
+
+      case COMPOUND_LITERAL_EXPR:
+	TREE_ADDRESSABLE (x) = 1;
+	cxx_mark_addressable (COMPOUND_LITERAL_EXPR_DECL (x));
 	return true;
 
       default:
@@ -5986,7 +5992,8 @@ maybe_warn_about_returning_address_of_lo
   if (TREE_CODE (valtype) == REFERENCE_TYPE)
     {
       if (TREE_CODE (whats_returned) == AGGR_INIT_EXPR
-	  || TREE_CODE (whats_returned) == TARGET_EXPR)
+	  || TREE_CODE (whats_returned) == TARGET_EXPR
+	  || TREE_CODE (whats_returned) == COMPOUND_LITERAL_EXPR)
 	{
 	  warning ("returning reference to temporary");
 	  return;
Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/20103
	* g++.dg/tree-ssa/pr20103.C: New test.
	* g++.dg/template/complit1.C: Expect error like ext/complit1.C.

Index: gcc/testsuite/g++.dg/tree-ssa/pr20103.C
===================================================================
RCS file: gcc/testsuite/g++.dg/tree-ssa/pr20103.C
diff -N gcc/testsuite/g++.dg/tree-ssa/pr20103.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/tree-ssa/pr20103.C 8 Mar 2005 21:49:29 -0000
@@ -0,0 +1,59 @@
+// PR c++/20103
+
+// { dg-do compile }
+
+// { dg-options "" }
+
+// Gimplification used to fail for (B){x}, because create_tmp_var
+// required a non-addressable type, and we didn't wrap the constructor
+// in a target_expr, ensuring it's moved to a separate decl.
+
+// Whether it is an lvalue, like in C, or an rvalue, is up to the ISO
+// C++ Commitete to decide in the second version of the C++ Standard.
+// We're going with rvalues for now.
+
+struct A
+{
+    A(const A&);
+};
+
+struct B
+{
+    A a;
+};
+
+void foo(B);
+void bar(B&); // { dg-error "in passing argument" }
+void bac(const B&);
+void bap(const B*);
+
+void baz(A &x)
+{
+    foo ((B){x});
+    bar ((B){x}); // { dg-error "non-const reference" }
+    bac ((B){x});
+    bap (&(B){x}); // { dg-error "address of temporary" }
+
+    foo ((const B&)(B){x});
+    bar ((B&)(B){x}); // { dg-error "invalid cast" }
+    bac ((const B&)(B){x});
+    bap (&(const B&)(B){x});
+}
+
+template <typename T, typename U>
+void baz(T &x)
+{
+    foo ((U){x});
+    bar ((U){x}); // { dg-error "non-const reference" }
+    bac ((U){x});
+    bap (&(U){x}); // { dg-error "address of temporary" }
+
+    foo ((const U&)(U){x});
+    bar ((U&)(U){x}); // { dg-error "invalid cast" }
+    bac ((const U&)(U){x});
+    bap (&(const U&)(U){x});
+}
+
+void bazT(A &x) {
+  baz<A,B>(x);
+}
Index: gcc/testsuite/g++.dg/template/complit1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/complit1.C,v
retrieving revision 1.3
diff -u -p -r1.3 complit1.C
--- gcc/testsuite/g++.dg/template/complit1.C 28 Dec 2002 07:48:08 -0000 1.3
+++ gcc/testsuite/g++.dg/template/complit1.C 8 Mar 2005 21:49:29 -0000
@@ -6,6 +6,6 @@ template <int D> struct C {
 };
 
 template<int D>
-C<D>::C() : d((int[]){1,2,3}) {}
+C<D>::C() : d((int[]){1,2,3}) {}  // { dg-error "assignment of arrays" }
 
-template class C<1>;
+template class C<1>; // { dg-error "instantiated from" }
Index: gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/20103
	* expr2.C: Fixed.

Index: gcc/testsuite/g++.old-deja/g++.oliva/expr2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.oliva/expr2.C,v
retrieving revision 1.5
diff -u -p -r1.5 expr2.C
--- gcc/testsuite/g++.old-deja/g++.oliva/expr2.C 1 May 2003 02:02:47 -0000 1.5
+++ gcc/testsuite/g++.old-deja/g++.oliva/expr2.C 8 Mar 2005 21:49:29 -0000
@@ -1,4 +1,4 @@
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
 
 // Copyright (C) 2000 Free Software Foundation
 

-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20103


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