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 problem in convert_with_check


It's one of the problems uncovered by Jeff with his Ada-killer patch. :-)

In a few cases, Gigi builds types that are not present in the Ada source.
convert_with_check was converting the expression to be checked to the Ada
base type (present in the source) instead of the real base type, which
can lead to the following GIMPLE code:

            D.756 = for_the_value /[rd] 1000000000;
            D.757 = (UNSIGNED_64) D.756;
            if (D.757 > 255)
              {
                __gnat_rcheck_10 ("c460008.adb", 35);
                iftmp.5 = for_the_value /[rd] 1000000000;
              }
            else
              {
                iftmp.5 = for_the_value /[rd] 1000000000;
              }
            iftmp.6 = iftmp.5;
            if (0)
              {
                goto <D760>;
              }
            else
              {
                
              }
            D.763 = (c460008__unsigned_edge_8) iftmp.6;
            D.764 = (c460008__unsigned_edge_8___UMT) D.763;
            if (D.764 > 254)
              {
                goto <D760>;
              }
            else
              {
                goto <D761>;
              }
            <D760>:;
            __gnat_rcheck_12 ("c460008.adb", 35);

This is problematic because the expression in the original type iftmp.6
is converted to the (Ada base) type c460008__unsigned_edge_8 before the
check in the real type c460008__unsigned_edge_8___UMT that would validate
the conversion, thus potentially allowing objects of the former type to
have values outside its TYPE_MIN_VALUE..TYPE_MAX_VALUE range.

The change fixes ACATS c460008 and c460011 at -O2 so we are left with:

                === acats tests ===
FAIL:   c34004a
FAIL:   c46033a
FAIL:   cdd2a02
FAIL:   cxa4025
FAIL:   cxa4028
FAIL:   cxa4033
FAIL:   cxg2024

                === acats Summary ===
# of expected passes            2309
# of unexpected failures        7

of which cdd2a02 should be considered nominal.

Bootstrapped/regtested on x86, applied to mainline.


2006-03-04  Eric Botcazou  <ebotcazou@adacore.com>

	* gigi.h (get_ada_base_type): Delete.
        * utils2.c (get_ada_base_type): Likewise.
        * trans.c (convert_with_check): Operate in the real base type.


-- 
Eric Botcazou
Index: trans.c
===================================================================
--- trans.c	(revision 111596)
+++ trans.c	(working copy)
@@ -5323,7 +5323,6 @@ convert_with_check (Entity_Id gnat_type,
   tree gnu_in_type = TREE_TYPE (gnu_expr);
   tree gnu_in_basetype = get_base_type (gnu_in_type);
   tree gnu_base_type = get_base_type (gnu_type);
-  tree gnu_ada_base_type = get_ada_base_type (gnu_type);
   tree gnu_result = gnu_expr;
 
   /* If we are not doing any checks, the output is an integral type, and
@@ -5415,7 +5414,7 @@ convert_with_check (Entity_Id gnat_type,
 
   /* Now convert to the result base type.  If this is a non-truncating
      float-to-integer conversion, round.  */
-  if (INTEGRAL_TYPE_P (gnu_ada_base_type) && FLOAT_TYPE_P (gnu_in_basetype)
+  if (INTEGRAL_TYPE_P (gnu_base_type) && FLOAT_TYPE_P (gnu_in_basetype)
       && !truncatep)
     {
       REAL_VALUE_TYPE half_minus_pred_half, pred_half;
@@ -5474,12 +5473,12 @@ convert_with_check (Entity_Id gnat_type,
 			   gnu_add_pred_half, gnu_subtract_pred_half);
     }
 
-  if (TREE_CODE (gnu_ada_base_type) == INTEGER_TYPE
-      && TYPE_HAS_ACTUAL_BOUNDS_P (gnu_ada_base_type)
+  if (TREE_CODE (gnu_base_type) == INTEGER_TYPE
+      && TYPE_HAS_ACTUAL_BOUNDS_P (gnu_base_type)
       && TREE_CODE (gnu_result) == UNCONSTRAINED_ARRAY_REF)
-    gnu_result = unchecked_convert (gnu_ada_base_type, gnu_result, false);
+    gnu_result = unchecked_convert (gnu_base_type, gnu_result, false);
   else
-    gnu_result = convert (gnu_ada_base_type, gnu_result);
+    gnu_result = convert (gnu_base_type, gnu_result);
 
   /* Finally, do the range check if requested.  Note that if the
      result type is a modular type, the range check is actually
Index: utils2.c
===================================================================
--- utils2.c	(revision 111596)
+++ utils2.c	(working copy)
@@ -123,19 +123,6 @@ get_base_type (tree type)
 
   return type;
 }
-
-/* Likewise, but only return types known to the Ada source.  */
-tree
-get_ada_base_type (tree type)
-{
-  while (TREE_TYPE (type)
-	 && (TREE_CODE (type) == INTEGER_TYPE
-	     || TREE_CODE (type) == REAL_TYPE)
-	 && !TYPE_EXTRA_SUBTYPE_P (type))
-    type = TREE_TYPE (type);
-
-  return type;
-}
 
 /* EXP is a GCC tree representing an address.  See if we can find how
    strictly the object at that address is aligned.   Return that alignment
Index: gigi.h
===================================================================
--- gigi.h	(revision 111596)
+++ gigi.h	(working copy)
@@ -671,9 +671,6 @@ extern tree gnat_truthvalue_conversion (
 /* Return the base type of TYPE.  */
 extern tree get_base_type (tree type);
 
-/* Likewise, but only return types known at Ada source.  */
-extern tree get_ada_base_type (tree type);
-
 /* EXP is a GCC tree representing an address.  See if we can find how
    strictly the object at that address is aligned.   Return that alignment
    strictly the object at that address is aligned.   Return that alignment

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