c-typeck.c (build_function_call): Set fundecl = function again.
2005-06-20 Daniel Berlin <dberlin@dberlin.org> * c-typeck.c (build_function_call): Set fundecl = function again. * tree-ssa-alias.c (find_used_portions): Address taking causes the entire variable to be used. * tree-ssa-structalias.c (do_structure_copy): Fix handling of unknown size variables, and structure copies from addressof operations. Simplify how we do *a = *b type structure copies. (init_base_vars): Add ANYTHING = &ANYTHING constraint the right way. READONLY's address is not taken by default. INTEGER dereference should point to anything. (create_variable_info_for): It's okay for the first field to not start at 0. From-SVN: r101227
This commit is contained in:
parent
83fbfe42c2
commit
a5eadacc35
@ -1,3 +1,17 @@
|
|||||||
|
2005-06-20 Daniel Berlin <dberlin@dberlin.org>
|
||||||
|
|
||||||
|
* c-typeck.c (build_function_call): Set fundecl = function again.
|
||||||
|
* tree-ssa-alias.c (find_used_portions): Address taking causes the
|
||||||
|
entire variable to be used.
|
||||||
|
* tree-ssa-structalias.c (do_structure_copy): Fix handling of
|
||||||
|
unknown size variables, and structure copies from addressof
|
||||||
|
operations. Simplify how we do *a = *b type structure copies.
|
||||||
|
(init_base_vars): Add ANYTHING = &ANYTHING constraint the right
|
||||||
|
way. READONLY's address is not taken by default.
|
||||||
|
INTEGER dereference should point to anything.
|
||||||
|
(create_variable_info_for): It's okay for the first field to not start
|
||||||
|
at 0.
|
||||||
|
|
||||||
2005-06-20 Kaz Kojima <kkojima@gcc.gnu.org>
|
2005-06-20 Kaz Kojima <kkojima@gcc.gnu.org>
|
||||||
|
|
||||||
config/sh/linux.h (FUNCTION_PROFILER): Constify a char*.
|
config/sh/linux.h (FUNCTION_PROFILER): Constify a char*.
|
||||||
|
@ -1990,6 +1990,7 @@ build_function_call (tree function, tree params)
|
|||||||
return tem;
|
return tem;
|
||||||
|
|
||||||
name = DECL_NAME (function);
|
name = DECL_NAME (function);
|
||||||
|
fundecl = function;
|
||||||
}
|
}
|
||||||
function = default_function_array_conversion (function);
|
function = default_function_array_conversion (function);
|
||||||
|
|
||||||
|
31
gcc/testsuite/gcc.c-torture/compile/pta-1.c
Normal file
31
gcc/testsuite/gcc.c-torture/compile/pta-1.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
typedef struct JSObject JSObject;
|
||||||
|
typedef struct JSObjectMap *(*JSNewObjectMapOp) (JSObject *obj);
|
||||||
|
typedef JSObject *(*JSGetMethodOp) (JSObject *obj);
|
||||||
|
struct JSObjectOps {
|
||||||
|
JSNewObjectMapOp newObjectMap;
|
||||||
|
};
|
||||||
|
struct JSXMLObjectOps {
|
||||||
|
struct JSObjectOps base;
|
||||||
|
JSGetMethodOp getMethod;
|
||||||
|
};
|
||||||
|
struct JSObjectMap {
|
||||||
|
struct JSObjectOps *ops;
|
||||||
|
};
|
||||||
|
struct JSObject {
|
||||||
|
struct JSObjectMap *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JSXMLObjectOps js_XMLObjectOps;
|
||||||
|
|
||||||
|
|
||||||
|
/* We need to create SFT's for the entire structure when this address is taken,
|
||||||
|
not just the part in the component reference itself. */
|
||||||
|
JSObject *JS_GetMethod(JSObject *obj)
|
||||||
|
{
|
||||||
|
if (obj->map->ops == &js_XMLObjectOps.base) {
|
||||||
|
struct JSXMLObjectOps *ops;
|
||||||
|
ops = (struct JSXMLObjectOps *) obj->map->ops;
|
||||||
|
obj = ops->getMethod(obj);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
@ -3119,6 +3119,35 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
/* This is here to make sure we mark the entire base variable as used
|
||||||
|
when you take its address. Because our used portion analysis is
|
||||||
|
simple, we aren't looking at casts or pointer arithmetic to see what
|
||||||
|
happens when you take the address. */
|
||||||
|
case ADDR_EXPR:
|
||||||
|
{
|
||||||
|
tree var = get_base_address (TREE_OPERAND (*tp, 0));
|
||||||
|
|
||||||
|
if (var
|
||||||
|
&& DECL_P (var)
|
||||||
|
&& DECL_SIZE (var)
|
||||||
|
&& var_can_have_subvars (var)
|
||||||
|
&& TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
|
||||||
|
{
|
||||||
|
used_part_t up;
|
||||||
|
size_t uid = var_ann (var)->uid;
|
||||||
|
|
||||||
|
up = get_or_create_used_part_for (uid);
|
||||||
|
|
||||||
|
up->minused = 0;
|
||||||
|
up->maxused = TREE_INT_CST_LOW (DECL_SIZE (var));
|
||||||
|
up->implicit_uses = true;
|
||||||
|
|
||||||
|
used_portions[uid] = up;
|
||||||
|
*walk_subtrees = 0;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
{
|
{
|
||||||
|
@ -2210,8 +2210,7 @@ do_simple_structure_copy (const struct constraint_expr lhs,
|
|||||||
const unsigned HOST_WIDE_INT size)
|
const unsigned HOST_WIDE_INT size)
|
||||||
{
|
{
|
||||||
varinfo_t p = get_varinfo (lhs.var);
|
varinfo_t p = get_varinfo (lhs.var);
|
||||||
unsigned HOST_WIDE_INT pstart,last;
|
unsigned HOST_WIDE_INT pstart, last;
|
||||||
|
|
||||||
pstart = p->offset;
|
pstart = p->offset;
|
||||||
last = p->offset + size;
|
last = p->offset + size;
|
||||||
for (; p && p->offset < last; p = p->next)
|
for (; p && p->offset < last; p = p->next)
|
||||||
@ -2321,8 +2320,6 @@ do_structure_copy (tree lhsop, tree rhsop)
|
|||||||
unsigned HOST_WIDE_INT lhssize;
|
unsigned HOST_WIDE_INT lhssize;
|
||||||
unsigned HOST_WIDE_INT rhssize;
|
unsigned HOST_WIDE_INT rhssize;
|
||||||
|
|
||||||
lhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhsop)));
|
|
||||||
rhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (rhsop)));
|
|
||||||
lhs = get_constraint_for (lhsop);
|
lhs = get_constraint_for (lhsop);
|
||||||
rhs = get_constraint_for (rhsop);
|
rhs = get_constraint_for (rhsop);
|
||||||
|
|
||||||
@ -2334,8 +2331,18 @@ do_structure_copy (tree lhsop, tree rhsop)
|
|||||||
rhs = tmp;
|
rhs = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the RHS is a special var, set all the LHS fields to that
|
/* This is fairly conservative for the RHS == ADDRESSOF case, in that it's
|
||||||
special var. */
|
possible it's something we could handle. However, most cases falling
|
||||||
|
into this are dealing with transparent unions, which are slightly
|
||||||
|
weird. */
|
||||||
|
if (rhs.type == ADDRESSOF && rhs.var > integer_id)
|
||||||
|
{
|
||||||
|
rhs.type = ADDRESSOF;
|
||||||
|
rhs.var = anything_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the RHS is a special var, or an addressof, set all the LHS fields to
|
||||||
|
that special var. */
|
||||||
if (rhs.var <= integer_id)
|
if (rhs.var <= integer_id)
|
||||||
{
|
{
|
||||||
for (p = get_varinfo (lhs.var); p; p = p->next)
|
for (p = get_varinfo (lhs.var); p; p = p->next)
|
||||||
@ -2351,6 +2358,20 @@ do_structure_copy (tree lhsop, tree rhsop)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* The size only really matters insofar as we don't set more or less of
|
||||||
|
the variable. If we hit an unknown size var, the size should be the
|
||||||
|
whole darn thing. */
|
||||||
|
if (get_varinfo (rhs.var)->is_unknown_size_var)
|
||||||
|
rhssize = ~0;
|
||||||
|
else
|
||||||
|
rhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (rhsop)));
|
||||||
|
|
||||||
|
if (get_varinfo (lhs.var)->is_unknown_size_var)
|
||||||
|
lhssize = ~0;
|
||||||
|
else
|
||||||
|
lhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhsop)));
|
||||||
|
|
||||||
|
|
||||||
if (rhs.type == SCALAR && lhs.type == SCALAR)
|
if (rhs.type == SCALAR && lhs.type == SCALAR)
|
||||||
do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
|
do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
|
||||||
else if (lhs.type != DEREF && rhs.type == DEREF)
|
else if (lhs.type != DEREF && rhs.type == DEREF)
|
||||||
@ -2362,14 +2383,12 @@ do_structure_copy (tree lhsop, tree rhsop)
|
|||||||
tree rhsdecl = get_varinfo (rhs.var)->decl;
|
tree rhsdecl = get_varinfo (rhs.var)->decl;
|
||||||
tree pointertype = TREE_TYPE (rhsdecl);
|
tree pointertype = TREE_TYPE (rhsdecl);
|
||||||
tree pointedtotype = TREE_TYPE (pointertype);
|
tree pointedtotype = TREE_TYPE (pointertype);
|
||||||
tree tmpvar;
|
tree tmpvar;
|
||||||
|
|
||||||
gcc_assert (rhs.type == DEREF && lhs.type == DEREF);
|
gcc_assert (rhs.type == DEREF && lhs.type == DEREF);
|
||||||
tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp");
|
tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp");
|
||||||
lhs = get_constraint_for (tmpvar);
|
do_structure_copy (tmpvar, rhsop);
|
||||||
do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
|
do_structure_copy (lhsop, tmpvar);
|
||||||
rhs = lhs;
|
|
||||||
lhs = get_constraint_for (lhsop);
|
|
||||||
do_lhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2723,7 +2742,7 @@ create_variable_info_for (tree decl, const char *name)
|
|||||||
vi->offset = 0;
|
vi->offset = 0;
|
||||||
vi->has_union = hasunion;
|
vi->has_union = hasunion;
|
||||||
if (!TYPE_SIZE (decltype)
|
if (!TYPE_SIZE (decltype)
|
||||||
|| TREE_CODE (TYPE_SIZE (decltype)) != INTEGER_CST
|
|| TREE_CODE (TYPE_SIZE (decltype)) != INTEGER_CST
|
||||||
|| TREE_CODE (decltype) == ARRAY_TYPE
|
|| TREE_CODE (decltype) == ARRAY_TYPE
|
||||||
|| TREE_CODE (decltype) == UNION_TYPE
|
|| TREE_CODE (decltype) == UNION_TYPE
|
||||||
|| TREE_CODE (decltype) == QUAL_UNION_TYPE)
|
|| TREE_CODE (decltype) == QUAL_UNION_TYPE)
|
||||||
@ -2786,7 +2805,6 @@ create_variable_info_for (tree decl, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
field = fo->field;
|
field = fo->field;
|
||||||
gcc_assert (bitpos_of_field (field) == 0);
|
|
||||||
vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
|
vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
|
||||||
for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
|
for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
|
||||||
{
|
{
|
||||||
@ -3049,8 +3067,10 @@ init_base_vars (void)
|
|||||||
rhs.var = anything_id;
|
rhs.var = anything_id;
|
||||||
rhs.offset = 0;
|
rhs.offset = 0;
|
||||||
var_anything->address_taken = true;
|
var_anything->address_taken = true;
|
||||||
process_constraint (new_constraint (lhs, rhs));
|
/* This specifically does not use process_constraint because
|
||||||
|
process_constraint ignores all anything = anything constraints, since all
|
||||||
|
but this one are redundant. */
|
||||||
|
VEC_safe_push (constraint_t, gc, constraints, new_constraint (lhs, rhs));
|
||||||
|
|
||||||
/* Create the READONLY variable, used to represent that a variable
|
/* Create the READONLY variable, used to represent that a variable
|
||||||
points to readonly memory. */
|
points to readonly memory. */
|
||||||
@ -3075,7 +3095,6 @@ init_base_vars (void)
|
|||||||
rhs.type = ADDRESSOF;
|
rhs.type = ADDRESSOF;
|
||||||
rhs.var = anything_id;
|
rhs.var = anything_id;
|
||||||
rhs.offset = 0;
|
rhs.offset = 0;
|
||||||
var_readonly->address_taken = true;
|
|
||||||
|
|
||||||
process_constraint (new_constraint (lhs, rhs));
|
process_constraint (new_constraint (lhs, rhs));
|
||||||
|
|
||||||
@ -3091,6 +3110,16 @@ init_base_vars (void)
|
|||||||
var_integer->next = NULL;
|
var_integer->next = NULL;
|
||||||
integer_id = 3;
|
integer_id = 3;
|
||||||
VEC_safe_push (varinfo_t, gc, varmap, var_integer);
|
VEC_safe_push (varinfo_t, gc, varmap, var_integer);
|
||||||
|
|
||||||
|
/* *INTEGER = ANYTHING, because we don't know where a dereference of a random
|
||||||
|
integer will point to. */
|
||||||
|
lhs.type = SCALAR;
|
||||||
|
lhs.var = integer_id;
|
||||||
|
lhs.offset = 0;
|
||||||
|
rhs.type = ADDRESSOF;
|
||||||
|
rhs.var = anything_id;
|
||||||
|
rhs.offset = 0;
|
||||||
|
process_constraint (new_constraint (lhs, rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3101,7 +3130,6 @@ static void
|
|||||||
create_alias_vars (void)
|
create_alias_vars (void)
|
||||||
{
|
{
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
|
|
||||||
|
|
||||||
init_alias_vars ();
|
init_alias_vars ();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user