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]

[Ada] Fix PR ada/24880 and PR ada/26635


PR ada/26635 is a bogus Storage_Error warning introduced by the fix for PR 
tree-optimization/25125.  I initially complained about this fix but I now
think that the problem can be interpreted slightly differently: the conversion 
introduced by the fix is correct under the assumption that the arithmetics 
doesn't trap on overflow resulting from conversions from unsigned to signed, 
which is true on the hardware since such conversions are no-op.  The problem 
arises with the arithmetics of the compiler performed on PLACEHOLDER_EXPRs, 
because of the propagation of TREE_OVERFLOW during the substitution, so I 
think it's reasonable to make a special case here.

All the more so that another special case needs to be made at the same place 
for biased types to avoid an endless loop because of the same conversion, this 
is PR ada/24880.

Tested on i586-suse-linux, applied on the mainline and 4.3 branch.


2008-05-13  Eric Botcazou  <ebotcazou@adacore.com>

	PR ada/24880
	PR ada/26635
	* utils.c (convert) <INTEGER_TYPE>: When converting an additive
	expression to an integral type with lower precision, use NOP_EXPR
	directly in a couple of special cases.


2008-05-13  Eric Botcazou  <ebotcazou@adacore.com>

        * gnat.dg/discr7.adb: New test.
	* gnat.dg/conv_integer.adb: Likewise.


-- 
Eric Botcazou
Index: utils.c
===================================================================
--- utils.c	(revision 135221)
+++ utils.c	(working copy)
@@ -3627,7 +3627,7 @@ convert (tree type, tree expr)
   if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype))
     return convert_to_fat_pointer (type, expr);
 
-  /* If we're converting between two aggregate types that are mere
+  /* If we are converting between two aggregate types that are mere
      variants, just make a VIEW_CONVERT_EXPR.  */
   else if (code == ecode
 	   && AGGREGATE_TYPE_P (type)
@@ -3662,6 +3662,30 @@ convert (tree type, tree expr)
       /* ... fall through ... */
 
     case ENUMERAL_TYPE:
+      /* If we are converting an additive expression to an integer type
+	 with lower precision, be wary of the optimization that can be
+	 applied by convert_to_integer.  There are 2 problematic cases:
+	   - if the first operand was originally of a biased type,
+	     because we could be recursively called to convert it
+	     to an intermediate type and thus rematerialize the
+	     additive operator endlessly,
+	   - if the expression contains a placeholder, because an
+	     intermediate conversion that changes the sign could
+	     be inserted and thus introduce an artificial overflow
+	     at compile time when the placeholder is substituted.  */
+      if (code == INTEGER_TYPE
+	  && ecode == INTEGER_TYPE
+	  && TYPE_PRECISION (type) < TYPE_PRECISION (etype)
+	  && (TREE_CODE (expr) == PLUS_EXPR || TREE_CODE (expr) == MINUS_EXPR))
+	{
+	  tree op0 = get_unwidened (TREE_OPERAND (expr, 0), type);
+
+	  if ((TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+	       && TYPE_BIASED_REPRESENTATION_P (TREE_TYPE (op0)))
+	      || CONTAINS_PLACEHOLDER_P (expr))
+	    return build1 (NOP_EXPR, type, expr);
+	}
+
       return fold (convert_to_integer (type, expr));
 
     case POINTER_TYPE:
-- { dg-do compile }

procedure Discr7 is

  subtype Index is Natural range 0..5;
  type BitString is array(Index range <>) of Boolean;
  pragma Pack(BitString);

  function Id (I : Integer) return Integer is
  begin
    return I;
  end;

  type E(D : Index) is record
    C : BitString(1..D);
  end record;

  subtype E0 is E(Id(0));

  function F return E0 is
  begin
    return E'(D=>0, C=>(1..0=>FALSE));
  end;

begin
  null;
end;
-- { dg-do compile }
-- { dg-options "-gnatws" }

procedure Conv_Integer is
   S : constant := Integer'Size;
   type Regoff_T is range -1 .. 2 ** (S-1);
   for Regoff_T'Size use S;
   B : Integer;
   C : Regoff_T;
begin
   B := Integer (C);
end;

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