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]

[PATCH] Fix wrong range transformation


The attached testcase is miscompiled at -O2 because build_range_check
creates arithmetics in ENUMERAL_TYPE.  The wrong code is eventually
generated by VRP but, even with maximal bounds, arithmetics in non 
INTEGER_TYPEs must be avoided since it doesn't work for non-standard 
precision (build_range_check already avoids it in most cases).

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


2009-04-12  Eric Botcazou  <ebotcazou@adacore.com>

	* fold-const.c (build_range_check): Properly deal with enumeral and
	boolean base types.


2009-04-12  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/enum1.adb: New test.
	* gnat.dg/enum1_pkg.ads: New helper.


-- 
Eric Botcazou
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 145974)
+++ fold-const.c	(working copy)
@@ -4671,8 +4671,8 @@ make_range (tree exp, int *pin_p, tree *
 static tree
 build_range_check (tree type, tree exp, int in_p, tree low, tree high)
 {
-  tree etype = TREE_TYPE (exp);
-  tree value;
+  tree etype = TREE_TYPE (exp), value;
+  enum tree_code code;
 
 #ifdef HAVE_canonicalize_funcptr_for_compare
   /* Disable this optimization for function pointer expressions
@@ -4756,20 +4756,25 @@ build_range_check (tree type, tree exp,
 
   /* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
      This requires wrap-around arithmetics for the type of the expression.  */
-  switch (TREE_CODE (etype))
+  code = TREE_CODE (etype);
+  switch (code)
     {
     case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
       /* There is no requirement that LOW be within the range of ETYPE
 	 if the latter is a subtype.  It must, however, be within the base
 	 type of ETYPE.  So be sure we do the subtraction in that type.  */
-      if (TREE_TYPE (etype))
-	etype = TREE_TYPE (etype);
-      break;
+      if (code == INTEGER_TYPE && TREE_TYPE (etype))
+	{
+	  etype = TREE_TYPE (etype);
+	  /* But not in an enumeral or boolean type though.  */
+	  code = TREE_CODE (etype);
+	}
 
-    case ENUMERAL_TYPE:
-    case BOOLEAN_TYPE:
-      etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
-					      TYPE_UNSIGNED (etype));
+      if (code != INTEGER_TYPE)
+	etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+						TYPE_UNSIGNED (etype));
       break;
 
     default:
-- { dg-do run }
-- { dg-options "-O2" }

with Enum1_Pkg; use Enum1_Pkg;

procedure Enum1 is

  function Cond return Boolean is
  begin
    return My_N = Two or My_N = Three;
  end;

begin
  if Cond then
    raise Constraint_Error;
  end if;
end;
package Enum1_Pkg is

  type Enum is (One, Two, Three);

  subtype Sub_Enum is Enum;

  My_N : Sub_Enum := One;

end Enum1_Pkg;

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