]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/ada/gcc-interface/utils2.c
Fix small issues with -fgnat-encodings=minimal
[gcc.git] / gcc / ada / gcc-interface / utils2.c
index d5dd436d48e5a8091207ba46f40992bdcaf8e88d..edbb8161fea1c3a81cef594fd0d25f1eabc770f9 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *          Copyright (C) 1992-2016, Free Software Foundation, Inc.         *
+ *          Copyright (C) 1992-2019, Free Software Foundation, Inc.         *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "memmodel.h"
 #include "tm.h"
 #include "vec.h"
 #include "alias.h"
 #include "tree.h"
 #include "inchash.h"
+#include "builtins.h"
 #include "fold-const.h"
 #include "stor-layout.h"
 #include "stringpool.h"
@@ -166,11 +168,18 @@ known_alignment (tree exp)
       break;
 
     case ADDR_EXPR:
-      this_alignment = expr_align (TREE_OPERAND (exp, 0));
+      if (DECL_P (TREE_OPERAND (exp, 0)))
+       this_alignment = DECL_ALIGN (TREE_OPERAND (exp, 0));
+      else
+       this_alignment = get_object_alignment (TREE_OPERAND (exp, 0));
       break;
 
     case CALL_EXPR:
       {
+       tree fndecl = get_callee_fndecl (exp);
+       if (fndecl == malloc_decl || fndecl == realloc_decl)
+         return get_target_system_allocator_alignment () * BITS_PER_UNIT;
+
        tree t = maybe_inline_call_in_expr (exp);
        if (t)
          return known_alignment (t);
@@ -184,7 +193,8 @@ known_alignment (tree exp)
         have a dummy type here (e.g. a Taft Amendment type), for which the
         alignment is meaningless and should be ignored.  */
       if (POINTER_TYPE_P (TREE_TYPE (exp))
-         && !TYPE_IS_DUMMY_P (TREE_TYPE (TREE_TYPE (exp))))
+         && !TYPE_IS_DUMMY_P (TREE_TYPE (TREE_TYPE (exp)))
+         && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (exp))))
        this_alignment = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
       else
        this_alignment = 0;
@@ -210,27 +220,40 @@ find_common_type (tree t1, tree t2)
      calling into build_binary_op), some others are really expected and we
      have to be careful.  */
 
+  const bool variable_record_on_lhs
+    = (TREE_CODE (t1) == RECORD_TYPE
+       && TREE_CODE (t2) == RECORD_TYPE
+       && get_variant_part (t1)
+       && !get_variant_part (t2));
+
+  const bool variable_array_on_lhs
+    = (TREE_CODE (t1) == ARRAY_TYPE
+       && TREE_CODE (t2) == ARRAY_TYPE
+       && !TREE_CONSTANT (TYPE_MIN_VALUE (TYPE_DOMAIN (t1)))
+       && TREE_CONSTANT (TYPE_MIN_VALUE (TYPE_DOMAIN (t2))));
+
   /* We must avoid writing more than what the target can hold if this is for
      an assignment and the case of tagged types is handled in build_binary_op
      so we use the lhs type if it is known to be smaller or of constant size
      and the rhs type is not, whatever the modes.  We also force t1 in case of
      constant size equality to minimize occurrences of view conversions on the
-     lhs of an assignment, except for the case of record types with a variant
-     part on the lhs but not on the rhs to make the conversion simpler.  */
+     lhs of an assignment, except for the case of types with a variable part
+     on the lhs but not on the rhs to make the conversion simpler.  */
   if (TREE_CONSTANT (TYPE_SIZE (t1))
       && (!TREE_CONSTANT (TYPE_SIZE (t2))
          || tree_int_cst_lt (TYPE_SIZE (t1), TYPE_SIZE (t2))
          || (TYPE_SIZE (t1) == TYPE_SIZE (t2)
-             && !(TREE_CODE (t1) == RECORD_TYPE
-                  && TREE_CODE (t2) == RECORD_TYPE
-                  && get_variant_part (t1)
-                  && !get_variant_part (t2)))))
+             && !variable_record_on_lhs
+             && !variable_array_on_lhs)))
     return t1;
 
-  /* Otherwise, if the lhs type is non-BLKmode, use it.  Note that we know
-     that we will not have any alignment problems since, if we did, the
-     non-BLKmode type could not have been used.  */
-  if (TYPE_MODE (t1) != BLKmode)
+  /* Otherwise, if the lhs type is non-BLKmode, use it, except for the case of
+     a non-BLKmode rhs and array types with a variable part on the lhs but not
+     on the rhs to make sure the conversion is preserved during gimplification.
+     Note that we know that we will not have any alignment problems since, if
+     we did, the non-BLKmode type could not have been used.  */
+  if (TYPE_MODE (t1) != BLKmode
+      && (TYPE_MODE (t2) == BLKmode || !variable_array_on_lhs))
     return t1;
 
   /* If the rhs type is of constant size, use it whatever the modes.  At
@@ -282,19 +305,31 @@ compare_arrays (location_t loc, tree result_type, tree a1, tree a2)
      in order to suppress the comparison of the data at the end.  */
   while (TREE_CODE (t1) == ARRAY_TYPE && TREE_CODE (t2) == ARRAY_TYPE)
     {
-      tree lb1 = TYPE_MIN_VALUE (TYPE_DOMAIN (t1));
-      tree ub1 = TYPE_MAX_VALUE (TYPE_DOMAIN (t1));
-      tree lb2 = TYPE_MIN_VALUE (TYPE_DOMAIN (t2));
-      tree ub2 = TYPE_MAX_VALUE (TYPE_DOMAIN (t2));
-      tree length1 = size_binop (PLUS_EXPR, size_binop (MINUS_EXPR, ub1, lb1),
+      tree dom1 = TYPE_DOMAIN (t1);
+      tree dom2 = TYPE_DOMAIN (t2);
+      tree length1 = size_binop (PLUS_EXPR,
+                                size_binop (MINUS_EXPR,
+                                            TYPE_MAX_VALUE (dom1),
+                                            TYPE_MIN_VALUE (dom1)),
                                 size_one_node);
-      tree length2 = size_binop (PLUS_EXPR, size_binop (MINUS_EXPR, ub2, lb2),
+      tree length2 = size_binop (PLUS_EXPR,
+                                size_binop (MINUS_EXPR,
+                                            TYPE_MAX_VALUE (dom2),
+                                            TYPE_MIN_VALUE (dom2)),
                                 size_one_node);
+      tree ind1 = TYPE_INDEX_TYPE (dom1);
+      tree ind2 = TYPE_INDEX_TYPE (dom2);
+      tree base_type = maybe_character_type (get_base_type (ind1));
+      tree lb1 = convert (base_type, TYPE_MIN_VALUE (ind1));
+      tree ub1 = convert (base_type, TYPE_MAX_VALUE (ind1));
+      tree lb2 = convert (base_type, TYPE_MIN_VALUE (ind2));
+      tree ub2 = convert (base_type, TYPE_MAX_VALUE (ind2));
       tree comparison, this_a1_is_null, this_a2_is_null;
 
-      /* If the length of the first array is a constant, swap our operands
-        unless the length of the second array is the constant zero.  */
-      if (TREE_CODE (length1) == INTEGER_CST && !integer_zerop (length2))
+      /* If the length of the first array is a constant and that of the second
+        array is not, swap our operands to have the constant second.  */
+      if (TREE_CODE (length1) == INTEGER_CST
+         && TREE_CODE (length2) != INTEGER_CST)
        {
          tree tem;
          bool btem;
@@ -314,17 +349,12 @@ compare_arrays (location_t loc, tree result_type, tree a1, tree a2)
         last < first holds.  */
       if (integer_zerop (length2))
        {
-         tree b = get_base_type (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
-
          length_zero_p = true;
 
-         ub1
-           = convert (b, TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1))));
-         lb1
-           = convert (b, TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1))));
+         lb1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lb1, a1);
+         ub1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (ub1, a1);
 
          comparison = fold_build2_loc (loc, LT_EXPR, result_type, ub1, lb1);
-         comparison = SUBSTITUTE_PLACEHOLDER_IN_EXPR (comparison, a1);
          if (EXPR_P (comparison))
            SET_EXPR_LOCATION (comparison, loc);
 
@@ -337,24 +367,17 @@ compare_arrays (location_t loc, tree result_type, tree a1, tree a2)
         just use its length computed from the actual stored bounds.  */
       else if (TREE_CODE (length2) == INTEGER_CST)
        {
-         tree b = get_base_type (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1)));
-
-         ub1
-           = convert (b, TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1))));
-         lb1
-           = convert (b, TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t1))));
-         /* Note that we know that UB2 and LB2 are constant and hence
+         /* Note that we know that LB2 and UB2 are constant and hence
             cannot contain a PLACEHOLDER_EXPR.  */
-         ub2
-           = convert (b, TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t2))));
-         lb2
-           = convert (b, TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (t2))));
+         lb1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lb1, a1);
+         ub1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (ub1, a1);
 
          comparison
            = fold_build2_loc (loc, EQ_EXPR, result_type,
-                              build_binary_op (MINUS_EXPR, b, ub1, lb1),
-                              build_binary_op (MINUS_EXPR, b, ub2, lb2));
-         comparison = SUBSTITUTE_PLACEHOLDER_IN_EXPR (comparison, a1);
+                              build_binary_op (MINUS_EXPR, base_type,
+                                               ub1, lb1),
+                              build_binary_op (MINUS_EXPR, base_type,
+                                               ub2, lb2));
          if (EXPR_P (comparison))
            SET_EXPR_LOCATION (comparison, loc);
 
@@ -372,26 +395,20 @@ compare_arrays (location_t loc, tree result_type, tree a1, tree a2)
 
          comparison
            = fold_build2_loc (loc, EQ_EXPR, result_type, length1, length2);
+         if (EXPR_P (comparison))
+           SET_EXPR_LOCATION (comparison, loc);
 
-         /* If the length expression is of the form (cond ? val : 0), assume
-            that cond is equivalent to (length != 0).  That's guaranteed by
-            construction of the array types in gnat_to_gnu_entity.  */
-         if (TREE_CODE (length1) == COND_EXPR
-             && integer_zerop (TREE_OPERAND (length1, 2)))
-           this_a1_is_null
-             = invert_truthvalue_loc (loc, TREE_OPERAND (length1, 0));
-         else
-           this_a1_is_null = fold_build2_loc (loc, EQ_EXPR, result_type,
-                                              length1, size_zero_node);
-
-         /* Likewise for the second array.  */
-         if (TREE_CODE (length2) == COND_EXPR
-             && integer_zerop (TREE_OPERAND (length2, 2)))
-           this_a2_is_null
-             = invert_truthvalue_loc (loc, TREE_OPERAND (length2, 0));
-         else
-           this_a2_is_null = fold_build2_loc (loc, EQ_EXPR, result_type,
-                                              length2, size_zero_node);
+         lb1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lb1, a1);
+         ub1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (ub1, a1);
+
+         this_a1_is_null
+           = fold_build2_loc (loc, LT_EXPR, result_type, ub1, lb1);
+
+         lb2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lb2, a2);
+         ub2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (ub2, a2);
+
+         this_a2_is_null
+           = fold_build2_loc (loc, LT_EXPR, result_type, ub2, lb2);
        }
 
       /* Append expressions for this dimension to the final expressions.  */
@@ -781,7 +798,8 @@ build_load_modify_store (tree dest, tree src, Node_Id gnat_node)
                {
                  unsigned int size = tree_to_uhwi (TYPE_SIZE (type));
                  type = copy_type (type);
-                 SET_TYPE_MODE (type, mode_for_size (size, MODE_INT, 0));
+                 machine_mode mode = int_mode_for_size (size, 0).else_blk ();
+                 SET_TYPE_MODE (type, mode);
                }
 
              /* Create the temporary by inserting a SAVE_EXPR.  */
@@ -816,6 +834,7 @@ build_load_modify_store (tree dest, tree src, Node_Id gnat_node)
    in that type.  For INIT_EXPR and MODIFY_EXPR, RESULT_TYPE must be
    NULL_TREE.  For ARRAY_REF, RESULT_TYPE may be NULL_TREE, in which
    case the type to be used will be derived from the operands.
+   Don't fold the result if NO_FOLD is true.
 
    This function is very much unlike the ones for C and C++ since we
    have already done any type conversion and matching required.  All we
@@ -823,7 +842,8 @@ build_load_modify_store (tree dest, tree src, Node_Id gnat_node)
 
 tree
 build_binary_op (enum tree_code op_code, tree result_type,
-                 tree left_operand, tree right_operand)
+                tree left_operand, tree right_operand,
+                bool no_fold)
 {
   tree left_type = TREE_TYPE (left_operand);
   tree right_type = TREE_TYPE (right_operand);
@@ -839,9 +859,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
       && TYPE_JUSTIFIED_MODULAR_P (operation_type))
     operation_type = TREE_TYPE (TYPE_FIELDS (operation_type));
 
-  if (operation_type
-      && TREE_CODE (operation_type) == INTEGER_TYPE
-      && TYPE_EXTRA_SUBTYPE_P (operation_type))
+  if (operation_type && TYPE_IS_EXTRA_SUBTYPE_P (operation_type))
     operation_type = get_base_type (operation_type);
 
   modulus = (operation_type
@@ -1022,8 +1040,15 @@ build_binary_op (enum tree_code op_code, tree result_type,
       /* For a range, make sure the element type is consistent.  */
       if (op_code == ARRAY_RANGE_REF
          && TREE_TYPE (operation_type) != TREE_TYPE (left_type))
-       operation_type = build_array_type (TREE_TYPE (left_type),
-                                          TYPE_DOMAIN (operation_type));
+       {
+         operation_type
+           = build_nonshared_array_type (TREE_TYPE (left_type),
+                                         TYPE_DOMAIN (operation_type));
+         /* Declare it now since it will never be declared otherwise.  This
+            is necessary to ensure that its subtrees are properly marked.  */
+         create_type_decl (TYPE_NAME (operation_type), operation_type, true,
+                           false, Empty);
+       }
 
       /* Then convert the right operand to its base type.  This will prevent
         unneeded sign conversions when sizetype is wider than integer.  */
@@ -1265,10 +1290,16 @@ build_binary_op (enum tree_code op_code, tree result_type,
   else if (TREE_CODE (right_operand) == NULL_EXPR)
     return build1 (NULL_EXPR, operation_type, TREE_OPERAND (right_operand, 0));
   else if (op_code == ARRAY_REF || op_code == ARRAY_RANGE_REF)
-    result = fold (build4 (op_code, operation_type, left_operand,
-                          right_operand, NULL_TREE, NULL_TREE));
+    {
+      result = build4 (op_code, operation_type, left_operand, right_operand,
+                      NULL_TREE, NULL_TREE);
+      if (!no_fold)
+       result = fold (result);
+    }
   else if (op_code == INIT_EXPR || op_code == MODIFY_EXPR)
     result = build2 (op_code, void_type_node, left_operand, right_operand);
+  else if (no_fold)
+    result = build2 (op_code, operation_type, left_operand, right_operand);
   else
     result
       = fold_build2 (op_code, operation_type, left_operand, right_operand);
@@ -1289,8 +1320,13 @@ build_binary_op (enum tree_code op_code, tree result_type,
   /* If we are working with modular types, perform the MOD operation
      if something above hasn't eliminated the need for it.  */
   if (modulus)
-    result = fold_build2 (FLOOR_MOD_EXPR, operation_type, result,
-                         convert (operation_type, modulus));
+    {
+      modulus = convert (operation_type, modulus);
+      if (no_fold)
+       result = build2 (FLOOR_MOD_EXPR, operation_type, result, modulus);
+      else
+       result = fold_build2 (FLOOR_MOD_EXPR, operation_type, result, modulus);
+    }
 
   if (result_type && result_type != operation_type)
     result = convert (result_type, result);
@@ -1406,15 +1442,15 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
               the offset to the field.  Otherwise, do this the normal way.  */
          if (op_code == ATTR_ADDR_EXPR)
            {
-             HOST_WIDE_INT bitsize;
-             HOST_WIDE_INT bitpos;
+             poly_int64 bitsize;
+             poly_int64 bitpos;
              tree offset, inner;
              machine_mode mode;
              int unsignedp, reversep, volatilep;
 
              inner = get_inner_reference (operand, &bitsize, &bitpos, &offset,
                                           &mode, &unsignedp, &reversep,
-                                          &volatilep, false);
+                                          &volatilep);
 
              /* If INNER is a padding type whose field has a self-referential
                 size, convert to that inner type.  We know the offset is zero
@@ -1427,8 +1463,9 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
              if (!offset)
                offset = size_zero_node;
 
-             offset = size_binop (PLUS_EXPR, offset,
-                                  size_int (bitpos / BITS_PER_UNIT));
+             offset
+               = size_binop (PLUS_EXPR, offset,
+                             size_int (bits_to_bytes_round_down (bitpos)));
 
              /* Take the address of INNER, convert it to a pointer to our type
                 and add the offset.  */
@@ -1754,9 +1791,10 @@ build_call_n_expr (tree fndecl, int n, ...)
    MSG gives the exception's identity for the call to Local_Raise, if any.  */
 
 static tree
-build_goto_raise (tree label, int msg)
+build_goto_raise (Entity_Id gnat_label, int msg)
 {
-  tree gnu_result = build1 (GOTO_EXPR, void_type_node, label);
+  tree gnu_label = gnat_to_gnu_entity (gnat_label, NULL_TREE, false);
+  tree gnu_result = build1 (GOTO_EXPR, void_type_node, gnu_label);
   Entity_Id local_raise = Get_Local_Raise_Call_Entity ();
 
   /* If Local_Raise is present, build Local_Raise (Exception'Identity).  */
@@ -1774,6 +1812,7 @@ build_goto_raise (tree label, int msg)
        = build2 (COMPOUND_EXPR, void_type_node, gnu_call, gnu_result);
     }
 
+  TREE_USED (gnu_label) = 1;
   return gnu_result;
 }
 
@@ -1826,13 +1865,13 @@ expand_sloc (Node_Id gnat_node, tree *filename, tree *line, tree *col)
 tree
 build_call_raise (int msg, Node_Id gnat_node, char kind)
 {
+  Entity_Id gnat_label = get_exception_label (kind);
   tree fndecl = gnat_raise_decls[msg];
-  tree label = get_exception_label (kind);
   tree filename, line;
 
   /* If this is to be done as a goto, handle that case.  */
-  if (label)
-    return build_goto_raise (label, msg);
+  if (Present (gnat_label))
+    return build_goto_raise (gnat_label, msg);
 
   expand_sloc (gnat_node, &filename, &line, NULL);
 
@@ -1850,13 +1889,13 @@ build_call_raise (int msg, Node_Id gnat_node, char kind)
 tree
 build_call_raise_column (int msg, Node_Id gnat_node, char kind)
 {
+  Entity_Id gnat_label = get_exception_label (kind);
   tree fndecl = gnat_raise_decls_ext[msg];
-  tree label = get_exception_label (kind);
   tree filename, line, col;
 
   /* If this is to be done as a goto, handle that case.  */
-  if (label)
-    return build_goto_raise (label, msg);
+  if (Present (gnat_label))
+    return build_goto_raise (gnat_label, msg);
 
   expand_sloc (gnat_node, &filename, &line, &col);
 
@@ -1875,13 +1914,13 @@ tree
 build_call_raise_range (int msg, Node_Id gnat_node, char kind,
                        tree index, tree first, tree last)
 {
+  Entity_Id gnat_label = get_exception_label (kind);
   tree fndecl = gnat_raise_decls_ext[msg];
-  tree label = get_exception_label (kind);
   tree filename, line, col;
 
   /* If this is to be done as a goto, handle that case.  */
-  if (label)
-    return build_goto_raise (label, msg);
+  if (Present (gnat_label))
+    return build_goto_raise (gnat_label, msg);
 
   expand_sloc (gnat_node, &filename, &line, &col);
 
@@ -1902,8 +1941,8 @@ build_call_raise_range (int msg, Node_Id gnat_node, char kind,
 static int
 compare_elmt_bitpos (const PTR rt1, const PTR rt2)
 {
-  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
-  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
+  const constructor_elt * const elmt1 = (const constructor_elt *) rt1;
+  const constructor_elt * const elmt2 = (const constructor_elt *) rt2;
   const_tree const field1 = elmt1->index;
   const_tree const field2 = elmt2->index;
   const int ret
@@ -2268,8 +2307,6 @@ build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, tree gnu_type,
                           Entity_Id gnat_proc, Entity_Id gnat_pool,
                           Node_Id gnat_node)
 {
-  gnu_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_size, gnu_obj);
-
   /* Explicit proc to call ?  This one is assumed to deal with the type
      alignment constraints.  */
   if (Present (gnat_proc))
@@ -2319,6 +2356,12 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
   if (init && TREE_CODE (init) == NULL_EXPR)
     return build1 (NULL_EXPR, result_type, TREE_OPERAND (init, 0));
 
+  /* If we are just annotating types, also return a NULL_EXPR.  */
+  else if (type_annotate_only)
+    return build1 (NULL_EXPR, result_type,
+                  build_call_raise (CE_Range_Check_Failed, gnat_node,
+                                    N_Raise_Constraint_Error));
+
   /* 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),
@@ -2391,16 +2434,13 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
     size = TYPE_SIZE_UNIT (TREE_TYPE (init));
 
   /* If the size is still self-referential, reference the initializing
-     expression, if it is present.  If not, this must have been a
-     call to allocate a library-level object, in which case we use
-     the maximum size.  */
-  if (CONTAINS_PLACEHOLDER_P (size))
-    {
-      if (!ignore_init_type && init)
-       size = substitute_placeholder_in_expr (size, init);
-      else
-       size = max_size (size, true);
-    }
+     expression, if it is present.  If not, this must have been a call
+     to allocate a library-level object, in which case we just use the
+     maximum size.  */
+  if (!ignore_init_type && init)
+    size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, init);
+  else if (CONTAINS_PLACEHOLDER_P (size))
+    size = max_size (size, true);
 
   /* If the size overflows, pass -1 so Storage_Error will be raised.  */
   if (TREE_CODE (size) == INTEGER_CST && !valid_constant_size_p (size))
@@ -2510,7 +2550,7 @@ gnat_save_expr (tree exp)
   if (code == COMPONENT_REF
       && TYPE_IS_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
     return build3 (code, type, gnat_save_expr (TREE_OPERAND (exp, 0)),
-                  TREE_OPERAND (exp, 1), TREE_OPERAND (exp, 2));
+                  TREE_OPERAND (exp, 1), NULL_TREE);
 
   return save_expr (exp);
 }
@@ -2556,13 +2596,19 @@ gnat_protect_expr (tree exp)
       return t;
     }
 
+  /* Likewise if we're indirectly referencing part of something.  */
+  if (code == COMPONENT_REF
+      && TREE_CODE (TREE_OPERAND (exp, 0)) == INDIRECT_REF)
+    return build3 (code, type, gnat_protect_expr (TREE_OPERAND (exp, 0)),
+                  TREE_OPERAND (exp, 1), NULL_TREE);
+
   /* If this is a COMPONENT_REF of a fat pointer, save the entire fat pointer.
      This may be more efficient, but will also allow us to more easily find
      the match for the PLACEHOLDER_EXPR.  */
   if (code == COMPONENT_REF
       && TYPE_IS_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
     return build3 (code, type, gnat_protect_expr (TREE_OPERAND (exp, 0)),
-                  TREE_OPERAND (exp, 1), TREE_OPERAND (exp, 2));
+                  TREE_OPERAND (exp, 1), NULL_TREE);
 
   /* If this is a fat pointer or a scalar, just make a SAVE_EXPR.  Likewise
      for a CALL_EXPR as large objects are returned via invisible reference
@@ -2575,9 +2621,7 @@ gnat_protect_expr (tree exp)
   /* Otherwise reference, protect the address and dereference.  */
   return
     build_unary_op (INDIRECT_REF, type,
-                   save_expr (build_unary_op (ADDR_EXPR,
-                                              build_reference_type (type),
-                                              exp)));
+                   save_expr (build_unary_op (ADDR_EXPR, NULL_TREE, exp)));
 }
 
 /* This is equivalent to stabilize_reference_1 in tree.c but we take an extra
@@ -2610,7 +2654,7 @@ gnat_stabilize_reference_1 (tree e, void *data)
        result
          = build3 (code, type,
                    gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), data),
-                   TREE_OPERAND (e, 1), TREE_OPERAND (e, 2));
+                   TREE_OPERAND (e, 1), NULL_TREE);
       /* If the expression has side-effects, then encase it in a SAVE_EXPR
         so that it will only be evaluated once.  */
       /* The tcc_reference and tcc_comparison classes could be handled as
@@ -2718,7 +2762,7 @@ gnat_rewrite_reference (tree ref, rewrite_fn func, void *data, tree *init)
                  gnat_rewrite_reference (TREE_OPERAND (ref, 0), func, data,
                                          init),
                  func (TREE_OPERAND (ref, 1), data),
-                 TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
+                 TREE_OPERAND (ref, 2), NULL_TREE);
       break;
 
     case COMPOUND_EXPR:
@@ -2796,9 +2840,6 @@ get_inner_constant_reference (tree exp)
          break;
 
        case COMPONENT_REF:
-         if (TREE_OPERAND (exp, 2))
-           return NULL_TREE;
-
          if (!TREE_CONSTANT (DECL_FIELD_OFFSET (TREE_OPERAND (exp, 1))))
            return NULL_TREE;
          break;
@@ -2806,7 +2847,7 @@ get_inner_constant_reference (tree exp)
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
          {
-           if (TREE_OPERAND (exp, 2) || TREE_OPERAND (exp, 3))
+           if (TREE_OPERAND (exp, 2))
              return NULL_TREE;
 
            tree array_type = TREE_TYPE (TREE_OPERAND (exp, 0));
@@ -2886,7 +2927,7 @@ is_simple_additive_expression (tree expr, tree *add, tree *cst, bool *minus_p)
 tree
 gnat_invariant_expr (tree expr)
 {
-  const tree type = TREE_TYPE (expr);
+  tree type = TREE_TYPE (expr);
   tree add, cst;
   bool minus_p;
 
@@ -2900,8 +2941,7 @@ gnat_invariant_expr (tree expr)
     {
       expr = DECL_INITIAL (expr);
       /* Look into CONSTRUCTORs built to initialize padded types.  */
-      if (TYPE_IS_PADDING_P (TREE_TYPE (expr)))
-       expr = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))), expr);
+      expr = maybe_padded_object (expr);
       expr = remove_conversions (expr, false);
     }
 
@@ -2934,16 +2974,12 @@ gnat_invariant_expr (tree expr)
       switch (TREE_CODE (t))
        {
        case COMPONENT_REF:
-         if (TREE_OPERAND (t, 2))
-           return NULL_TREE;
          invariant_p |= DECL_INVARIANT_P (TREE_OPERAND (t, 1));
          break;
 
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
-         if (!TREE_CONSTANT (TREE_OPERAND (t, 1))
-             || TREE_OPERAND (t, 2)
-             || TREE_OPERAND (t, 3))
+         if (!TREE_CONSTANT (TREE_OPERAND (t, 1)) || TREE_OPERAND (t, 2))
            return NULL_TREE;
          break;
 
This page took 0.04979 seconds and 5 git commands to generate.