diff mbox

[Ada] Fix segfault on conditional expression with type String

Message ID 201109112112.56206.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Sept. 11, 2011, 7:12 p.m. UTC
Because of some quite complex expressions with variable size that outsmart the 
unsharing mechanism.  Fixed by being smarter earlier.

Tested on i586-suse-linux, applied on the mainline.


2011-09-11  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/utils.c (maybe_unconstrained_array): In the reference
	to unconstrained array case, deal with each branch of a COND_EXPR.
	* gcc-interface/utils2.c (build_allocator): Deal with each branch of
	a COND_EXPR in the initializer, if present.


2011-09-11  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/cond_expr2.ad[sb]: New test.
diff mbox

Patch

Index: gcc-interface/utils.c
===================================================================
--- gcc-interface/utils.c	(revision 178757)
+++ gcc-interface/utils.c	(working copy)
@@ -4241,22 +4241,44 @@  tree
 maybe_unconstrained_array (tree exp)
 {
   enum tree_code code = TREE_CODE (exp);
-  tree new_exp;
 
   switch (TREE_CODE (TREE_TYPE (exp)))
     {
     case UNCONSTRAINED_ARRAY_TYPE:
       if (code == UNCONSTRAINED_ARRAY_REF)
 	{
-	  new_exp = TREE_OPERAND (exp, 0);
-	  new_exp
-	    = build_unary_op (INDIRECT_REF, NULL_TREE,
-			      build_component_ref (new_exp, NULL_TREE,
-						   TYPE_FIELDS
-						   (TREE_TYPE (new_exp)),
-						   false));
-	  TREE_READONLY (new_exp) = TREE_READONLY (exp);
-	  return new_exp;
+	  const bool read_only = TREE_READONLY (exp);
+	  exp = TREE_OPERAND (exp, 0);
+	  if (TREE_CODE (exp) == COND_EXPR)
+	    {
+	      tree op1
+		= build_unary_op (INDIRECT_REF, NULL_TREE,
+				  build_component_ref (TREE_OPERAND (exp, 1),
+						       NULL_TREE,
+						       TYPE_FIELDS
+						       (TREE_TYPE (exp)),
+						       false));
+	      tree op2
+		= build_unary_op (INDIRECT_REF, NULL_TREE,
+				  build_component_ref (TREE_OPERAND (exp, 2),
+						       NULL_TREE,
+						       TYPE_FIELDS
+						       (TREE_TYPE (exp)),
+						       false));
+
+	      exp = build3 (COND_EXPR,
+			    TREE_TYPE (TREE_TYPE (TYPE_FIELDS
+					          (TREE_TYPE (exp)))),
+			    TREE_OPERAND (exp, 0), op1, op2);
+	    }
+	  else
+	    exp = build_unary_op (INDIRECT_REF, NULL_TREE,
+				  build_component_ref (exp, NULL_TREE,
+						       TYPE_FIELDS
+						       (TREE_TYPE (exp)),
+						       false));
+	  TREE_READONLY (exp) = read_only;
+	  return exp;
 	}
 
       else if (code == NULL_EXPR)
@@ -4270,7 +4292,8 @@  maybe_unconstrained_array (tree exp)
 	 it contains a template.  */
       if (TYPE_PADDING_P (TREE_TYPE (exp)))
 	{
-	  new_exp = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (exp))), exp);
+	  tree new_exp
+	    = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (exp))), exp);
 	  if (TREE_CODE (TREE_TYPE (new_exp)) == RECORD_TYPE
 	      && TYPE_CONTAINS_TEMPLATE_P (TREE_TYPE (new_exp)))
 	    return
Index: gcc-interface/utils2.c
===================================================================
--- gcc-interface/utils2.c	(revision 178762)
+++ gcc-interface/utils2.c	(working copy)
@@ -2046,6 +2046,16 @@  build_allocator (tree type, tree init, t
   if (init && TREE_CODE (init) == NULL_EXPR)
     return build1 (NULL_EXPR, result_type, TREE_OPERAND (init, 0));
 
+  /* If the initializer, if present, is a COND_EXPR, deal with each branch.  */
+  else if (init && TREE_CODE (init) == COND_EXPR)
+    return build3 (COND_EXPR, result_type, TREE_OPERAND (init, 0),
+		   build_allocator (type, TREE_OPERAND (init, 1), result_type,
+				    gnat_proc, gnat_pool, gnat_node,
+				    ignore_init_type),
+		   build_allocator (type, TREE_OPERAND (init, 2), result_type,
+				    gnat_proc, gnat_pool, gnat_node,
+				    ignore_init_type));
+
   /* If RESULT_TYPE is a fat or thin pointer, set SIZE to be the sum of the
      sizes of the object and its template.  Allocate the whole thing and
      fill in the parts that are known.  */