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]

Re: [PATCH] Fix points-to / call-clobber solution in the face of pointer-arithmetic


On Fri, Jul 4, 2008 at 10:14 AM, Richard Guenther <rguenther@suse.de> wrote:
>
> This (again) fixes how we handle pointer-arithmetic in (field-sensitive)
> PTA.
>
> First, as shown in the single testcase included, we have to be able
> to compute the reachability set of a pointer that points after
> an object - which we cannot do right now because the points-to set
> we create at the moment is empty in that case.
>
> Second, repeated increments smaller than a sub-field size do not
> cause the solution to change, so the solution for p + 2 + 2 may
> be different of that for p + 4.  This problem is a real problem
> if we have a sub-field which includes multiple "real" fields
> (which happens for structs with variable sized fields, or of course
> with the patch globbing non-pointer fields).
>
> The solution to the above problems is for 1) use the last sub-field
> as the solution for off-variable pointers


Err, no.
This will do Bad Things (TM) for indirect function calls, where the
last sub field is equivalent to the last argument ;)
Unless you are going to mark which varinfos are indirect function
calls, and not do this for them.


>, 2) include the next
> sub-field in the solution iff the sub-field doesn't start at the
> offset.

I'm okay with this.


>
> An alternative solution to 1) is to drop to anything.
>

I'd much prefer dropping to anything for things like variably sized
fields than messing around in a way that will break indirect function
calls.

> We still only handle positive offsets in arithmetic (we can handle
> them if we drop to anything in case 1), or if we have an explicit
> sub-field for one-after-the-object pointers, in which case we
> would have to drop to anything if we go off that one).
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk?
>
> Thanks,
> Richard.
>
> 2008-07-04  Richard Guenther  <rguenther@suse.de>
>
>        * tree-ssa-structalias.c (solution_set_add): Correctly handle
>        pointers outside a var and inside a field.
>        (process_constraint): Remove zeroing offset for !use_field_sensitive.
>        (get_constraint_for_ptr_offset): New function.
>        (get_constraint_for_component_ref): For addresses at least include
>        the last field of the variable.
>        (get_constraint_for_1): Factor common code, handle POINTER_PLUS_EXPR.
>        (handle_ptr_arith): Remove.
>        (find_func_aliases): Simplify assignment handling.
>        (init_alias_vars): Initialize use_field_sensitive from
>        max-fields-for-field-sensitive parameter.
>
>        * gcc.dg/torture/pta-ptrarith-1.c: New testcase.
>
> Index: trunk/gcc/tree-ssa-structalias.c
> ===================================================================
> *** trunk.orig/gcc/tree-ssa-structalias.c       2008-07-04
> 11:36:20.000000000 +0200
> --- trunk/gcc/tree-ssa-structalias.c    2008-07-04 13:52:19.000000000 +0200
> *************** solution_set_add (bitmap set, unsigned H
> *** 756,778 ****
>
>    EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
>      {
> !       /* If this is a properly sized variable, only add offset if it's
> !        less than end.  Otherwise, it is globbed to a single
> !        variable.  */
> ! !       if ((get_varinfo (i)->offset + offset) < get_varinfo
> (i)->fullsize)
>        {
>          unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset +
> offset;
>          varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset);
>          if (!v)
> !           continue;
>          bitmap_set_bit (result, v->id);
> !       }
> !       else if (get_varinfo (i)->is_artificial_var
> !              || get_varinfo (i)->has_union
> !              || get_varinfo (i)->is_unknown_size_var)
> !       {
> !         bitmap_set_bit (result, i);
>        }
>      }
>
> --- 756,784 ----
>
>    EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
>      {
> !       /* Artificial and unknown-size variables are not split.  */
> !       if (get_varinfo (i)->is_artificial_var
> !         || get_varinfo (i)->has_union
> !         || get_varinfo (i)->is_unknown_size_var)
> !       bitmap_set_bit (result, i);
> !       else
>        {
>          unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset +
> offset;
>          varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset);
> +         /* If the result is outside of the variable use the last field.
>  */
>          if (!v)
> !           {
> !             v = get_varinfo (i);
> !             while (v->next != NULL)
> !               v = v->next;
> !           }
>          bitmap_set_bit (result, v->id);
> !         /* If the result is not exactly at fieldoffset include the next
> !            field as well.  See get_constraint_for_ptr_offset for more
> !            rationale.  */
> !         if (v->offset != fieldoffset
> !             && v->next != NULL)
> !           bitmap_set_bit (result, v->next->id);
>        }
>      }
>
> *************** process_constraint (constraint_t t)
> *** 2602,2613 ****
>    gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
>    gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
>
> -   if (!use_field_sensitive)
> -     {
> -       t->rhs.offset = 0;
> -       t->lhs.offset = 0;
> -     }
> -
>    /* ANYTHING == ANYTHING is pointless.  */
>    if (lhs.var == anything_id && rhs.var == anything_id)
>      return;
> --- 2608,2613 ----
> *************** bitpos_of_field (const tree fdecl)
> *** 2683,2688 ****
> --- 2683,2809 ----
>  }
>
>
> + /* Handle pointer arithmetic EXPR when creating aliasing constraints.
> +    Expressions of the type PTR + CST can be handled in two ways:
> + +    1- If the constraint for PTR is ADDRESSOF for a non-structure
> +       variable, then we can use it directly because adding or
> +       subtracting a constant may not alter the original ADDRESSOF
> +       constraint (i.e., pointer arithmetic may not legally go outside
> +       an object's boundaries).
> + +    2- If the constraint for PTR is ADDRESSOF for a structure variable,
> +       then if CST is a compile-time constant that can be used as an
> +       offset, we can determine which sub-variable will be pointed-to
> +       by the expression.
> + +    Return true if the expression is handled.  For any other kind of
> +    expression, return false so that each operand can be added as a
> +    separate constraint by the caller.  */
> + + static void
> + get_constraint_for_ptr_offset (tree ptr, tree offset,
> +                              VEC (ce_s, heap) **results)
> + {
> +   struct constraint_expr *c;
> +   unsigned int j, n;
> +   unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
> + +   /* If we do not do field-sensitive PTA adding offsets to pointers
> +      does not change the points-to solution.  */
> +   if (!use_field_sensitive)
> +     {
> +       get_constraint_for (ptr, results);
> +       return;
> +     }
> + +   /* If the offset is not a non-negative integer constant that fits
> +      in a HOST_WIDE_INT, we have to fall back to a conservative
> +      solution which includes all sub-fields of all pointed-to
> +      variables of ptr.
> +      ???  As we do not have the ability to express this, fall back
> +      to anything.  */
> +   if (!host_integerp (offset, 1))
> +     {
> +       struct constraint_expr temp;
> +       temp.var = anything_id;
> +       temp.type = SCALAR;
> +       temp.offset = 0;
> +       VEC_safe_push (ce_s, heap, *results, &temp);
> +       return;
> +     }
> + +   /* Make sure the bit-offset also fits.  */
> +   rhsunitoffset = TREE_INT_CST_LOW (offset);
> +   rhsoffset = rhsunitoffset * BITS_PER_UNIT;
> +   if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
> +     {
> +       struct constraint_expr temp;
> +       temp.var = anything_id;
> +       temp.type = SCALAR;
> +       temp.offset = 0;
> +       VEC_safe_push (ce_s, heap, *results, &temp);
> +       return;
> +     }
> + +   get_constraint_for (ptr, results);
> +   if (rhsoffset == 0)
> +     return;
> + +   /* As we are eventually appending to the solution do not use
> +      VEC_iterate here.  */
> +   n = VEC_length (ce_s, *results);
> +   for (j = 0; j < n; j++)
> +     {
> +       c = VEC_index (ce_s, *results, j);
> + +       if (c->type == ADDRESSOF)
> +       {
> +         varinfo_t temp, curr = get_varinfo (c->var);
> + +         /* Search the sub-field which overlaps with the
> +            pointed-to offset.  As we deal with positive offsets
> +            only, we can start the search from the current variable.  */
> +         temp = first_vi_for_offset (curr, curr->offset + rhsoffset);
> + +         /* If the result is outside of the variable we have to provide
> +            a conservative result, as the variable is still reachable
> +            from the resulting pointer (even though it technically
> +            cannot point to anything).  The last sub-field is such
> +            a conservative result.
> +            ???  If we always had a sub-field for &object + 1 then
> +            we could represent this in a more precise way.  */
> +         if (temp == NULL)
> +           {
> +             temp = curr;
> +             while (temp->next != NULL)
> +               temp = temp->next;
> +             continue;
> +           }
> + +         /* If the found variable is not exactly at the pointed to
> +            result, we have to include the next variable in the
> +            solution as well.  Otherwise two increments by offset / 2
> +            do not result in the same or a conservative superset
> +            solution.  */
> +         if (temp->offset != curr->offset + rhsoffset
> +             && temp->next != NULL)
> +           {
> +             struct constraint_expr c2;
> +             c2.var = temp->next->id;
> +             c2.type = ADDRESSOF;
> +             c2.offset = 0;
> +             VEC_safe_push (ce_s, heap, *results, &c2);
> +           }
> +         c->var = temp->id;
> +         c->offset = 0;
> +       }
> +       else
> +       c->offset = rhsoffset;
> +     }
> + }
> + +
>  /* Given a COMPONENT_REF T, return the constraint_expr vector for it.
>     If address_p is true the result will be taken its address of.  */
>
> *************** get_constraint_for_component_ref (tree t
> *** 2719,2727 ****
>    /* Pretend to take the address of the base, we'll take care of
>       adding the required subset of sub-fields below.  */
>    get_constraint_for_1 (t, results, true);
> -   result = VEC_last (ce_s, *results);
> -
>    gcc_assert (VEC_length (ce_s, *results) == 1);
>
>    /* This can also happen due to weird offsetof type macros.  */
>    if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
> --- 2840,2847 ----
>    /* Pretend to take the address of the base, we'll take care of
>       adding the required subset of sub-fields below.  */
>    get_constraint_for_1 (t, results, true);
>    gcc_assert (VEC_length (ce_s, *results) == 1);
> +   result = VEC_last (ce_s, *results);
>
>    /* This can also happen due to weird offsetof type macros.  */
>    if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
> *************** get_constraint_for_component_ref (tree t
> *** 2756,2767 ****
>                    break;
>                }
>            }
> !         /* assert that we found *some* field there. The user couldn't be
> !            accessing *only* padding.  */
> !         /* Still the user could access one past the end of an array
> !            embedded in a struct resulting in accessing *only* padding.  */
> !         gcc_assert (VEC_length (ce_s, *results) >= 1
> !                     || ref_contains_array_ref (orig_t));
>        }
>        else if (bitmaxsize == 0)
>        {
> --- 2876,2900 ----
>                    break;
>                }
>            }
> !         /* If we are going to take the address of this field then
> !            to be able to compute reachability correctly add at least
> !            the last field of the variable.  */
> !         if (address_p
> !             && VEC_length (ce_s, *results) == 0)
> !           {
> !             curr = get_varinfo (cexpr.var);
> !             while (curr->next != NULL)
> !               curr = curr->next;
> !             cexpr.var = curr->id;
> !             VEC_safe_push (ce_s, heap, *results, &cexpr);
> !           }
> !         else
> !           /* Assert that we found *some* field there. The user couldn't be
> !              accessing *only* padding.  */
> !           /* Still the user could access one past the end of an array
> !              embedded in a struct resulting in accessing *only* padding.
>  */
> !           gcc_assert (VEC_length (ce_s, *results) >= 1
> !                       || ref_contains_array_ref (orig_t));
>        }
>        else if (bitmaxsize == 0)
>        {
> *************** get_constraint_for_1 (tree t, VEC (ce_s,
> *** 2905,2928 ****
>                VEC_safe_push (ce_s, heap, *results, &temp);
>                return;
>              }
> -           else
> -             {
> -               temp.var = anything_id;
> -               temp.type = SCALAR;
> -               temp.offset = 0;
> -               VEC_safe_push (ce_s, heap, *results, &temp);
> -               return;
> -             }
>            break;
> !         default:
> !           {
> !             temp.type = ADDRESSOF;
> !             temp.var = anything_id;
> !             temp.offset = 0;
> !             VEC_safe_push (ce_s, heap, *results, &temp);
> !             return;
> !           }
>          }
>        }
>      case tcc_reference:
>        {
> --- 3038,3047 ----
>                VEC_safe_push (ce_s, heap, *results, &temp);
>                return;
>              }
>            break;
> !         default:;
>          }
> +       break;
>        }
>      case tcc_reference:
>        {
> *************** get_constraint_for_1 (tree t, VEC (ce_s,
> *** 2939,2953 ****
>          case COMPONENT_REF:
>            get_constraint_for_component_ref (t, results, address_p);
>            return;
> !         default:
> !           {
> !             temp.type = ADDRESSOF;
> !             temp.var = anything_id;
> !             temp.offset = 0;
> !             VEC_safe_push (ce_s, heap, *results, &temp);
> !             return;
> !           }
>          }
>        }
>      case tcc_unary:
>        {
> --- 3058,3066 ----
>          case COMPONENT_REF:
>            get_constraint_for_component_ref (t, results, address_p);
>            return;
> !         default:;
>          }
> +       break;
>        }
>      case tcc_unary:
>        {
> *************** get_constraint_for_1 (tree t, VEC (ce_s,
> *** 2968,2982 ****
>
>              /* FALLTHRU  */
>            }
> !         default:
> !           {
> !             temp.type = ADDRESSOF;
> !             temp.var = anything_id;
> !             temp.offset = 0;
> !             VEC_safe_push (ce_s, heap, *results, &temp);
> !             return;
> !           }
>          }
>        }
>      case tcc_exceptional:
>        {
> --- 3081,3099 ----
>
>              /* FALLTHRU  */
>            }
> !         default:;
>          }
> +       break;
> +       }
> +     case tcc_binary:
> +       {
> +       if (TREE_CODE (t) == POINTER_PLUS_EXPR)
> +         {
> +           get_constraint_for_ptr_offset (TREE_OPERAND (t, 0),
> +                                          TREE_OPERAND (t, 1), results);
> +           return;
> +         }
> +       break;
>        }
>      case tcc_exceptional:
>        {
> *************** get_constraint_for_1 (tree t, VEC (ce_s,
> *** 2987,3023 ****
>              get_constraint_for_1 (PHI_RESULT (t), results, address_p);
>              return;
>            }
> -           break;
>          case SSA_NAME:
>            {
>              get_constraint_for_ssa_var (t, results, address_p);
>              return;
>            }
> !           break;
> !         default:
> !           {
> !             temp.type = ADDRESSOF;
> !             temp.var = anything_id;
> !             temp.offset = 0;
> !             VEC_safe_push (ce_s, heap, *results, &temp);
> !             return;
> !           }
>          }
>        }
>      case tcc_declaration:
>        {
>        get_constraint_for_ssa_var (t, results, address_p);
>        return;
>        }
> !     default:
> !       {
> !       temp.type = ADDRESSOF;
> !       temp.var = anything_id;
> !       temp.offset = 0;
> !       VEC_safe_push (ce_s, heap, *results, &temp);
> !       return;
> !       }
>      }
>  }
>
>  /* Given a gimple tree T, return the constraint expression vector for it.
>  */
> --- 3104,3131 ----
>              get_constraint_for_1 (PHI_RESULT (t), results, address_p);
>              return;
>            }
>          case SSA_NAME:
>            {
>              get_constraint_for_ssa_var (t, results, address_p);
>              return;
>            }
> !         default:;
>          }
> +       break;
>        }
>      case tcc_declaration:
>        {
>        get_constraint_for_ssa_var (t, results, address_p);
>        return;
>        }
> !     default:;
>      }
> + +   /* The default fallback is a constraint from anything.  */
> +   temp.type = ADDRESSOF;
> +   temp.var = anything_id;
> +   temp.offset = 0;
> +   VEC_safe_push (ce_s, heap, *results, &temp);
>  }
>
>  /* Given a gimple tree T, return the constraint expression vector for it.
>  */
> *************** do_structure_copy (tree lhsop, tree rhso
> *** 3303,3382 ****
>      }
>  }
>
> - - /* Handle pointer arithmetic EXPR when creating aliasing constraints.
> -    Expressions of the type PTR + CST can be handled in two ways:
> - -    1- If the constraint for PTR is ADDRESSOF for a non-structure
> -       variable, then we can use it directly because adding or
> -       subtracting a constant may not alter the original ADDRESSOF
> -       constraint (i.e., pointer arithmetic may not legally go outside
> -       an object's boundaries).
> - -    2- If the constraint for PTR is ADDRESSOF for a structure variable,
> -       then if CST is a compile-time constant that can be used as an
> -       offset, we can determine which sub-variable will be pointed-to
> -       by the expression.
> - -    Return true if the expression is handled.  For any other kind of
> -    expression, return false so that each operand can be added as a
> -    separate constraint by the caller.  */
> - - static bool
> - handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
> - {
> -   tree op0, op1;
> -   struct constraint_expr *c, *c2;
> -   unsigned int i = 0;
> -   unsigned int j = 0;
> -   VEC (ce_s, heap) *temp = NULL;
> -   unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
> - -   if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
> -     return false;
> - -   op0 = TREE_OPERAND (expr, 0);
> -   op1 = TREE_OPERAND (expr, 1);
> -   gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
> - -   /* If the offset is not a non-negative integer constant that fits
> -      in a HOST_WIDE_INT, we cannot handle it here.  */
> -   if (!host_integerp (op1, 1))
> -     return false;
> - -   /* Make sure the bit-offset also fits.  */
> -   rhsunitoffset = TREE_INT_CST_LOW (op1);
> -   rhsoffset = rhsunitoffset * BITS_PER_UNIT;
> -   if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
> -     return false;
> - -   get_constraint_for (op0, &temp);
> - -   for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
> -     for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
> -       {
> -       if (c2->type == ADDRESSOF && rhsoffset != 0)
> -         {
> -           varinfo_t temp = get_varinfo (c2->var);
> - -           /* An access one after the end of an array is valid,
> -              so simply punt on accesses we cannot resolve.  */
> -           temp = first_vi_for_offset (temp, rhsoffset);
> -           if (temp == NULL)
> -             continue;
> -           c2->var = temp->id;
> -           c2->offset = 0;
> -         }
> -       else
> -         c2->offset = rhsoffset;
> -       process_constraint (new_constraint (*c, *c2));
> -       }
> - -   VEC_free (ce_s, heap, temp);
> - -   return true;
> - }
> -
>  /* Create a constraint ID = OP.  */
>
>  static void
> --- 3411,3416 ----
> *************** find_func_aliases (tree origt)
> *** 3776,3864 ****
>            }
>        }
>      }
> !   /* Otherwise, just a regular assignment statement.  */
> !   else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
>      {
>        tree lhsop = GIMPLE_STMT_OPERAND (t, 0);
>        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
> -       int i;
>
> !       if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
> !         && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
> !       {
> !         do_structure_copy (lhsop, rhsop);
> !       }
>        else
>        {
> !         /* Only care about operations with pointers, structures
> !            containing pointers, dereferences, and call expressions.  */
> !         if (could_have_pointers (lhsop)
> !             || TREE_CODE (rhsop) == CALL_EXPR)
>            {
> !             get_constraint_for (lhsop, &lhsc);
> !             switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
> !               {
> !                 /* RHS that consist of unary operations,
> !                    exceptional types, or bare decls/constants, get
> !                    handled directly by get_constraint_for.  */
> !                 case tcc_reference:
> !                 case tcc_declaration:
> !                 case tcc_constant:
> !                 case tcc_exceptional:
> !                 case tcc_expression:
> !                 case tcc_vl_exp:
> !                 case tcc_unary:
> !                     {
> !                       unsigned int j;
> ! !                       get_constraint_for (rhsop, &rhsc);
> !                       for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
> !                         {
> !                           struct constraint_expr *c2;
> !                           unsigned int k;
> ! !                           for (k = 0; VEC_iterate (ce_s, rhsc, k, c2);
> k++)
> !                             process_constraint (new_constraint (*c, *c2));
> !                         }
> ! !                     }
> !                   break;
>
> !                 case tcc_binary:
> !                     {
> !                       /* For pointer arithmetic of the form
> !                          PTR + CST, we can simply use PTR's
> !                          constraint because pointer arithmetic is
> !                          not allowed to go out of bounds.  */
> !                       if (handle_ptr_arith (lhsc, rhsop))
> !                         break;
> !                     }
> !                   /* FALLTHRU  */
> ! !                 /* Otherwise, walk each operand.  Notice that we
> !                    can't use the operand interface because we need
> !                    to process expressions other than simple operands
> !                    (e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR).  */
> !                 default:
> !                   for (i = 0; i < TREE_OPERAND_LENGTH (rhsop); i++)
> !                     {
> !                       tree op = TREE_OPERAND (rhsop, i);
> !                       unsigned int j;
> ! !                       gcc_assert (VEC_length (ce_s, rhsc) == 0);
> !                       get_constraint_for (op, &rhsc);
> !                       for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
> !                         {
> !                           struct constraint_expr *c2;
> !                           while (VEC_length (ce_s, rhsc) > 0)
> !                             {
> !                               c2 = VEC_last (ce_s, rhsc);
> !                               process_constraint (new_constraint (*c,
> *c2));
> !                               VEC_pop (ce_s, rhsc);
> !                             }
> !                         }
> !                     }
> !               }
>            }
>        }
>      }
> --- 3810,3838 ----
>            }
>        }
>      }
> !   /* Otherwise, just a regular assignment statement.  Only care about
> !      operations with pointer result, others are dealt with as escape
> !      points if they have pointer operands.  */
> !   else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT
> !          && could_have_pointers (GIMPLE_STMT_OPERAND (t, 0)))
>      {
>        tree lhsop = GIMPLE_STMT_OPERAND (t, 0);
>        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
>
> !       if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop)))
> !       do_structure_copy (lhsop, rhsop);
>        else
>        {
> !         unsigned int j;
> !         get_constraint_for (lhsop, &lhsc);
> !         get_constraint_for (rhsop, &rhsc);
> !         for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
>            {
> !             struct constraint_expr *c2;
> !             unsigned int k;
>
> !             for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
> !               process_constraint (new_constraint (*c, *c2));
>            }
>        }
>      }
> *************** init_base_vars (void)
> *** 5209,5214 ****
> --- 5183,5190 ----
>  static void
>  init_alias_vars (void)
>  {
> +   use_field_sensitive = (MAX_FIELDS_FOR_FIELD_SENSITIVE > 1);
> +
>    bitmap_obstack_initialize (&pta_obstack);
>    bitmap_obstack_initialize (&oldpta_obstack);
>    bitmap_obstack_initialize (&predbitmap_obstack);
> Index: trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
> ===================================================================
> *** /dev/null   1970-01-01 00:00:00.000000000 +0000
> --- trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c 2008-07-04
> 14:43:54.000000000 +0200
> ***************
> *** 0 ****
> --- 1,33 ----
> + /* { dg-do run } */
> + /* { dg-options "-fdump-tree-alias" } */
> + /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
> + + struct Foo {
> +   int *p;
> + };
> + + void __attribute__((noinline))
> + foo (void *p)
> + {
> +   struct Foo *f = (struct Foo *)p - 1;
> +   *f->p = 0;
> + }
> + + int bar (void)
> + {
> +   struct Foo f;
> +   int i = 1;
> +   f.p = &i;
> +   foo (&f + 1);
> +   return i;
> + }
> + extern void abort (void);
> + int main()
> + {
> +   if (bar () != 0)
> +     abort ();
> +   return 0;
> + }
> + + /* { dg-final { scan-tree-dump "ESCAPED = { ESCAPED NONLOCAL f i }"
> "alias" } } */
> + /* { dg-final { cleanup-tree-dump "alias" } } */
>


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