re PR c++/6994 (ICE in find_function_data)
PR middle-end/6994 * c-objc-common.c (inline_forbidden_p): Can not inline functions containing structures or unions containing VLAs. * tree-inline.c (walk_tree): For all class 't' nodes, walk TYPE_SIZE and TYPE_SIZE_UNIT. #undef WALK_SUBTREE_TAIL at end. (copy_tree_r): Copy types if they are variably modified. * hooks.c (hook_tree_bool_false): New. * hooks.h: Prototype it. * langhooks.h (struct lang_hooks_for_tree_inlining): Add var_mod_type_p. * langhooks-def.h: Default for tree_inlining.var_mod_type_p is hook_tree_bool_false. * tree.c (variably_modified_type_p): Moved here from cp/tree.c. Use lang_hooks.tree_inlining.var_mod_type_p for language-specific cases. Due to this, must weaken some 'if and only if' checks to merely 'if'. * tree.h: Prototype variably_modified_type_p. cp: * cp-lang.c (cp_var_mod_type_p): New: C++ hook for variably_modified_type_p. * cp-tree.h: Remove prototype of variably_modified_type_p. * tree.c (variably_modified_type_p): Remove; now implemented in language-independent code. PR c++/7266 * decl.c (grokdeclarator): Check that TREE_OPERAND 0 of a SCOPE_REF is not null before dereferencing it. testsuite: * g++.dg/ext/vla1.C, gcc.dg/vla-2.c, g++.dg/template/typename3.C: New tests. From-SVN: r58542
This commit is contained in:
parent
28f97059a6
commit
68a3e7e1aa
|
@ -1,3 +1,25 @@
|
|||
2002-10-25 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
PR middle-end/6994
|
||||
* c-objc-common.c (inline_forbidden_p): Can not inline
|
||||
functions containing structures or unions containing VLAs.
|
||||
* tree-inline.c (walk_tree): For all class 't' nodes, walk
|
||||
TYPE_SIZE and TYPE_SIZE_UNIT. #undef WALK_SUBTREE_TAIL at end.
|
||||
(copy_tree_r): Copy types if they are variably modified.
|
||||
|
||||
* hooks.c (hook_tree_bool_false): New.
|
||||
* hooks.h: Prototype it.
|
||||
* langhooks.h (struct lang_hooks_for_tree_inlining): Add
|
||||
var_mod_type_p.
|
||||
* langhooks-def.h: Default for tree_inlining.var_mod_type_p is
|
||||
hook_tree_bool_false.
|
||||
|
||||
* tree.c (variably_modified_type_p): Moved here from
|
||||
cp/tree.c. Use lang_hooks.tree_inlining.var_mod_type_p for
|
||||
language-specific cases. Due to this, must weaken some 'if
|
||||
and only if' checks to merely 'if'.
|
||||
* tree.h: Prototype variably_modified_type_p.
|
||||
|
||||
2002-10-22 Jim Wilson <wilson@redhat.com>
|
||||
|
||||
* config/i386/i386.md (subdi3_1): Add call to ix86_binary_operator_ok.
|
||||
|
|
|
@ -131,6 +131,22 @@ inline_forbidden_p (nodep, walk_subtrees, fn)
|
|||
|
||||
break;
|
||||
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
/* We cannot inline a function of the form
|
||||
|
||||
void F (int i) { struct S { int ar[i]; } s; }
|
||||
|
||||
Attempting to do so produces a catch-22 in tree-inline.c.
|
||||
If walk_tree examines the TYPE_FIELDS chain of RECORD_TYPE/
|
||||
UNION_TYPE nodes, then it goes into infinite recursion on a
|
||||
structure containing a pointer to its own type. If it doesn't,
|
||||
then the type node for S doesn't get adjusted properly when
|
||||
F is inlined, and we abort in find_function_data. */
|
||||
for (t = TYPE_FIELDS (node); t; t = TREE_CHAIN (t))
|
||||
if (variably_modified_type_p (TREE_TYPE (t)))
|
||||
return node;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
2002-10-25 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
PR middle-end/6994
|
||||
* cp-lang.c (cp_var_mod_type_p): New: C++ hook for
|
||||
variably_modified_type_p.
|
||||
* cp-tree.h: Remove prototype of variably_modified_type_p.
|
||||
* tree.c (variably_modified_type_p): Remove; now implemented
|
||||
in language-independent code.
|
||||
|
||||
PR c++/7266
|
||||
* decl.c (grokdeclarator): Check that TREE_OPERAND 0 of a
|
||||
SCOPE_REF is not null before dereferencing it.
|
||||
|
||||
2002-10-24 David Edelsohn <edelsohn@gnu.org>
|
||||
|
||||
PR c++/7228
|
||||
|
|
|
@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
|
||||
static tree cp_expr_size PARAMS ((tree));
|
||||
static bool cp_var_mod_type_p PARAMS ((tree));
|
||||
|
||||
#undef LANG_HOOKS_NAME
|
||||
#define LANG_HOOKS_NAME "GNU C++"
|
||||
|
@ -84,6 +85,8 @@ static tree cp_expr_size PARAMS ((tree));
|
|||
cp_copy_res_decl_for_inlining
|
||||
#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
|
||||
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
|
||||
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
|
||||
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p
|
||||
#undef LANG_HOOKS_TREE_INLINING_START_INLINING
|
||||
#define LANG_HOOKS_TREE_INLINING_START_INLINING cp_start_inlining
|
||||
#undef LANG_HOOKS_TREE_INLINING_END_INLINING
|
||||
|
@ -130,3 +133,21 @@ cp_expr_size (exp)
|
|||
/* Use the default code. */
|
||||
return lhd_expr_size (exp);
|
||||
}
|
||||
|
||||
/* Returns true if T is a variably modified type, in the sense of C99.
|
||||
This routine needs only check cases that cannot be handled by the
|
||||
language-independent logic in tree-inline.c. */
|
||||
|
||||
static bool
|
||||
cp_var_mod_type_p (tree type)
|
||||
{
|
||||
/* If TYPE is a pointer-to-member, it is variably modified if either
|
||||
the class or the member are variably modified. */
|
||||
if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
|
||||
return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|
||||
|| variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)));
|
||||
|
||||
/* All other types are not variably modified. */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -4213,7 +4213,6 @@ extern void end_input PARAMS ((void));
|
|||
/* in tree.c */
|
||||
extern void init_tree PARAMS ((void));
|
||||
extern int pod_type_p PARAMS ((tree));
|
||||
extern bool variably_modified_type_p (tree);
|
||||
extern int zero_init_p PARAMS ((tree));
|
||||
extern tree canonical_type_variant PARAMS ((tree));
|
||||
extern void unshare_base_binfos PARAMS ((tree));
|
||||
|
|
|
@ -11022,8 +11022,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
|||
pop_decl_namespace ();
|
||||
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
|
||||
/* Don't fall out into global scope. Hides real bug? --eichin */ ;
|
||||
else if (! IS_AGGR_TYPE_CODE
|
||||
(TREE_CODE (TREE_OPERAND (declarator, 0))))
|
||||
else if (!TREE_OPERAND (declarator, 0)
|
||||
|| !IS_AGGR_TYPE_CODE
|
||||
(TREE_CODE (TREE_OPERAND (declarator, 0))))
|
||||
;
|
||||
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
|
||||
{
|
||||
|
|
|
@ -1898,72 +1898,6 @@ pod_type_p (t)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Returns true if T is a variably modified type, in the sense of
|
||||
C99.
|
||||
|
||||
In C99, a struct type is never variably modified because a VLA may
|
||||
not appear as a structure member. However, in GNU C code like:
|
||||
|
||||
struct S { int i[f()]; };
|
||||
|
||||
is valid. Even though GNU C++ does not allow that, this function
|
||||
may sometimes be used in the C front end, so it treats any type
|
||||
with variable size in the same way that C99 treats VLAs.
|
||||
|
||||
In particular, a variably modified type is one that involves a type
|
||||
with variable size. */
|
||||
|
||||
bool
|
||||
variably_modified_type_p (tree type)
|
||||
{
|
||||
/* If TYPE itself has variable size, it is variably modified.
|
||||
|
||||
We do not yet have a representation of the C99 '[*]' syntax.
|
||||
When a representation is chosen, this function should be modified
|
||||
to test for that case as well. */
|
||||
if (TYPE_SIZE (type)
|
||||
&& TYPE_SIZE (type) != error_mark_node
|
||||
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
|
||||
return true;
|
||||
|
||||
/* If TYPE is a pointer or reference, it is variably modified if and
|
||||
only if the type pointed to is variably modified. */
|
||||
if (TYPE_PTR_P (type)
|
||||
|| TREE_CODE (type) == REFERENCE_TYPE)
|
||||
return variably_modified_type_p (TREE_TYPE (type));
|
||||
|
||||
/* If TYPE is an array, it is variably modified if the array
|
||||
elements are. (Note that the VLA case has alredy been checked
|
||||
above). */
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
return variably_modified_type_p (TREE_TYPE (type));
|
||||
|
||||
/* If TYPE is a pointer-to-member, it is variably modified if either
|
||||
the class or the member are variably modified. */
|
||||
if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
|
||||
return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|
||||
|| variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)));
|
||||
|
||||
/* If TYPE Is a function type, it is variably modified if any of the
|
||||
parameters or the return type are variably modified. */
|
||||
if (TREE_CODE (type) == FUNCTION_TYPE
|
||||
|| TREE_CODE (type) == METHOD_TYPE)
|
||||
{
|
||||
tree parm;
|
||||
|
||||
if (variably_modified_type_p (TREE_TYPE (type)))
|
||||
return true;
|
||||
for (parm = TYPE_ARG_TYPES (type);
|
||||
parm && parm != void_list_node;
|
||||
parm = TREE_CHAIN (parm))
|
||||
if (variably_modified_type_p (TREE_VALUE (parm)))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* All other types are not variably modified. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns 1 iff zero initialization of type T means actually storing
|
||||
zeros in it. */
|
||||
|
||||
|
|
|
@ -38,3 +38,11 @@ hook_void_bool_false ()
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generic hook that takes (tree) and returns false. */
|
||||
bool
|
||||
hook_tree_bool_false (a)
|
||||
tree a ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -24,5 +24,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
bool hook_void_bool_false PARAMS ((void));
|
||||
void hook_void_void PARAMS ((void));
|
||||
bool hook_tree_bool_false PARAMS ((tree));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,6 +104,8 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
|
|||
lhd_tree_inlining_copy_res_decl_for_inlining
|
||||
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
|
||||
lhd_tree_inlining_anon_aggr_type_p
|
||||
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
|
||||
hook_tree_bool_false
|
||||
#define LANG_HOOKS_TREE_INLINING_START_INLINING \
|
||||
lhd_tree_inlining_start_inlining
|
||||
#define LANG_HOOKS_TREE_INLINING_END_INLINING \
|
||||
|
@ -120,6 +122,7 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
|
|||
LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
|
||||
LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
|
||||
LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, \
|
||||
LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \
|
||||
LANG_HOOKS_TREE_INLINING_START_INLINING, \
|
||||
LANG_HOOKS_TREE_INLINING_END_INLINING, \
|
||||
LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
|
||||
|
|
|
@ -46,6 +46,7 @@ struct lang_hooks_for_tree_inlining
|
|||
void *, int *,
|
||||
void *));
|
||||
int (*anon_aggr_type_p) PARAMS ((union tree_node *));
|
||||
bool (*var_mod_type_p) PARAMS ((union tree_node *));
|
||||
int (*start_inlining) PARAMS ((union tree_node *));
|
||||
void (*end_inlining) PARAMS ((union tree_node *));
|
||||
union tree_node *(*convert_parm_for_inlining) PARAMS ((union tree_node *,
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2002-10-25 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
* g++.dg/ext/vla1.C, gcc.dg/vla-2.c,
|
||||
g++.dg/template/typename3.C: New tests.
|
||||
|
||||
2002-10-24 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/20021024-1.c: New test.
|
||||
|
@ -11,7 +16,7 @@
|
|||
|
||||
PR c++/7679
|
||||
* g++.dg/parse/inline1.C: New test.
|
||||
|
||||
|
||||
2002-10-22 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/6579
|
||||
|
|
|
@ -1224,6 +1224,12 @@ walk_tree (tp, func, data, htab_)
|
|||
{
|
||||
WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
|
||||
}
|
||||
else if (TREE_CODE_CLASS (code) == 't')
|
||||
{
|
||||
WALK_SUBTREE (TYPE_SIZE (*tp));
|
||||
WALK_SUBTREE (TYPE_SIZE_UNIT (*tp));
|
||||
/* Also examine various special fields, below. */
|
||||
}
|
||||
|
||||
result = (*lang_hooks.tree_inlining.walk_subtrees) (tp, &walk_subtrees, func,
|
||||
data, htab);
|
||||
|
@ -1320,6 +1326,7 @@ walk_tree (tp, func, data, htab_)
|
|||
return NULL_TREE;
|
||||
|
||||
#undef WALK_SUBTREE
|
||||
#undef WALK_SUBTREE_TAIL
|
||||
}
|
||||
|
||||
/* Like walk_tree, but does not walk duplicate nodes more than
|
||||
|
@ -1378,8 +1385,8 @@ copy_tree_r (tp, walk_subtrees, data)
|
|||
if (TREE_CODE (*tp) == SCOPE_STMT)
|
||||
SCOPE_STMT_BLOCK (*tp) = NULL_TREE;
|
||||
}
|
||||
else if (TREE_CODE_CLASS (code) == 't')
|
||||
/* There's no need to copy types, or anything beneath them. */
|
||||
else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp))
|
||||
/* Types only need to be copied if they are variably modified. */
|
||||
*walk_subtrees = 0;
|
||||
|
||||
return NULL_TREE;
|
||||
|
|
59
gcc/tree.c
59
gcc/tree.c
|
@ -4335,6 +4335,65 @@ int_fits_type_p (c, type)
|
|||
}
|
||||
}
|
||||
|
||||
/* Returns true if T is, contains, or refers to a type with variable
|
||||
size. This concept is more general than that of C99 'variably
|
||||
modified types': in C99, a struct type is never variably modified
|
||||
because a VLA may not appear as a structure member. However, in
|
||||
GNU C code like:
|
||||
|
||||
struct S { int i[f()]; };
|
||||
|
||||
is valid, and other languages may define similar constructs. */
|
||||
|
||||
bool
|
||||
variably_modified_type_p (type)
|
||||
tree type;
|
||||
{
|
||||
/* If TYPE itself has variable size, it is variably modified.
|
||||
|
||||
We do not yet have a representation of the C99 '[*]' syntax.
|
||||
When a representation is chosen, this function should be modified
|
||||
to test for that case as well. */
|
||||
if (TYPE_SIZE (type)
|
||||
&& TYPE_SIZE (type) != error_mark_node
|
||||
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
|
||||
return true;
|
||||
|
||||
/* If TYPE is a pointer or reference, it is variably modified if
|
||||
the type pointed to is variably modified. */
|
||||
if ((TREE_CODE (type) == POINTER_TYPE
|
||||
|| TREE_CODE (type) == REFERENCE_TYPE)
|
||||
&& variably_modified_type_p (TREE_TYPE (type)))
|
||||
return true;
|
||||
|
||||
/* If TYPE is an array, it is variably modified if the array
|
||||
elements are. (Note that the VLA case has already been checked
|
||||
above.) */
|
||||
if (TREE_CODE (type) == ARRAY_TYPE
|
||||
&& variably_modified_type_p (TREE_TYPE (type)))
|
||||
return true;
|
||||
|
||||
/* If TYPE is a function type, it is variably modified if any of the
|
||||
parameters or the return type are variably modified. */
|
||||
if (TREE_CODE (type) == FUNCTION_TYPE
|
||||
|| TREE_CODE (type) == METHOD_TYPE)
|
||||
{
|
||||
tree parm;
|
||||
|
||||
if (variably_modified_type_p (TREE_TYPE (type)))
|
||||
return true;
|
||||
for (parm = TYPE_ARG_TYPES (type);
|
||||
parm && parm != void_list_node;
|
||||
parm = TREE_CHAIN (parm))
|
||||
if (variably_modified_type_p (TREE_VALUE (parm)))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The current language may have other cases to check, but in general,
|
||||
all other types are not variably modified. */
|
||||
return (*lang_hooks.tree_inlining.var_mod_type_p) (type);
|
||||
}
|
||||
|
||||
/* Given a DECL or TYPE, return the scope in which it was declared, or
|
||||
NULL_TREE if there is no containing scope. */
|
||||
|
||||
|
|
|
@ -2938,6 +2938,7 @@ struct obstack;
|
|||
/* In tree.c */
|
||||
extern int really_constant_p PARAMS ((tree));
|
||||
extern int int_fits_type_p PARAMS ((tree, tree));
|
||||
extern bool variably_modified_type_p PARAMS ((tree));
|
||||
extern int tree_log2 PARAMS ((tree));
|
||||
extern int tree_floor_log2 PARAMS ((tree));
|
||||
extern void preserve_data PARAMS ((void));
|
||||
|
|
Loading…
Reference in New Issue