Fix segfault on elaboration of empty 1-element array at -O
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 11 Nov 2020 13:52:45 +0000 (14:52 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Wed, 11 Nov 2020 13:52:45 +0000 (14:52 +0100)
This is a rather obscure case where the elaboration of an empty array
whose base type is an array type of length at most 1 goes awry when
the code is compiled with optimization.

gcc/ada/ChangeLog:
* gcc-interface/trans.c (can_be_lower_p): Remove.
(Regular_Loop_to_gnu): Add ENTRY_COND unconditionally if
BOTTOM_COND is non-zero.

gcc/testsuite/ChangeLog:
* gnat.dg/opt89.adb: New test.

gcc/ada/gcc-interface/trans.c
gcc/testsuite/gnat.dg/opt89.adb [new file with mode: 0644]

index d0663a2..065fcd2 100644 (file)
@@ -2814,38 +2814,6 @@ can_equal_max_val_p (tree val, tree type, bool reverse)
   return can_equal_min_or_max_val_p (val, type, !reverse);
 }
 
-/* Return true if VAL1 can be lower than VAL2.  */
-
-static bool
-can_be_lower_p (tree val1, tree val2)
-{
-  if (TREE_CODE (val1) == NOP_EXPR)
-    {
-      tree type = TREE_TYPE (TREE_OPERAND (val1, 0));
-      if (can_be_lower_p (TYPE_MAX_VALUE (type), TYPE_MIN_VALUE (type)))
-       return true;
-
-      val1 = TYPE_MIN_VALUE (type);
-    }
-
-  if (TREE_CODE (val1) != INTEGER_CST)
-    return true;
-
-  if (TREE_CODE (val2) == NOP_EXPR)
-    {
-      tree type = TREE_TYPE (TREE_OPERAND (val2, 0));
-      if (can_be_lower_p (TYPE_MAX_VALUE (type), TYPE_MIN_VALUE (type)))
-       return true;
-
-      val2 = TYPE_MAX_VALUE (type);
-    }
-
-  if (TREE_CODE (val2) != INTEGER_CST)
-    return true;
-
-  return tree_int_cst_lt (val1, val2);
-}
-
 /* Replace EXPR1 and EXPR2 by invariant expressions if possible.  Return
    true if both expressions have been replaced and false otherwise.  */
 
@@ -3126,19 +3094,16 @@ Regular_Loop_to_gnu (Node_Id gnat_node, tree *gnu_cond_expr_p)
        }
 
       /* If we use the BOTTOM_COND, we can turn the test into an inequality
-        test but we may have to add ENTRY_COND to protect the empty loop.  */
+        test but we have to add ENTRY_COND to protect the empty loop.  */
       if (LOOP_STMT_BOTTOM_COND_P (gnu_loop_stmt))
        {
          test_code = NE_EXPR;
-         if (can_be_lower_p (gnu_high, gnu_low))
-           {
-             gnu_cond_expr
-               = build3 (COND_EXPR, void_type_node,
-                         build_binary_op (LE_EXPR, boolean_type_node,
-                                          gnu_low, gnu_high),
-                         NULL_TREE, alloc_stmt_list ());
-             set_expr_location_from_node (gnu_cond_expr, gnat_iter_scheme);
-           }
+         gnu_cond_expr
+           = build3 (COND_EXPR, void_type_node,
+                     build_binary_op (LE_EXPR, boolean_type_node,
+                                      gnu_low, gnu_high),
+                     NULL_TREE, alloc_stmt_list ());
+         set_expr_location_from_node (gnu_cond_expr, gnat_iter_scheme);
        }
 
       /* Open a new nesting level that will surround the loop to declare the
diff --git a/gcc/testsuite/gnat.dg/opt89.adb b/gcc/testsuite/gnat.dg/opt89.adb
new file mode 100644 (file)
index 0000000..3752008
--- /dev/null
@@ -0,0 +1,18 @@
+-- { dg-do run }
+-- { dg-options "-O" }
+
+procedure Opt89 is
+
+  type Rec is record
+    I : Integer := 3;
+  end record;
+
+  subtype Index is Natural range 0..0;
+
+  type Arr is array (Index range <>) of Rec;
+
+  X : Arr (0 .. -1);
+
+begin
+  null;
+end;