Commit f7a8132a by Mark Mitchell Committed by Mark Mitchell

re PR c++/16273 (Memory exhausted when using nested classes and virtual functions)

	PR c++/16273
	* class.c (count_depth_data): New type.
	(dfs_depth_post): New function.
	(dfs_depth_q): Likewise.
	(find_final_overrider_data_s): Change type of vpath.
	Add vpath_list.
	(dfs_find_final_overrider_1): New function.
	(dfs_find_final_overrider): Use it.
	(dfs_find_final_overrider_q): Adjust use of vpath.
	(dfs_find_final_overrider_post): Likewise.
	(find_final_overrider): Use dfs_depth.  Allocate and deallocate
	vpath_list.

From-SVN: r85886
parent 28e99c62
2004-08-12 Mark Mitchell <mark@codesourcery.com>
PR c++/16273
* class.c (count_depth_data): New type.
(dfs_depth_post): New function.
(dfs_depth_q): Likewise.
(find_final_overrider_data_s): Change type of vpath.
Add vpath_list.
(dfs_find_final_overrider_1): New function.
(dfs_find_final_overrider): Use it.
(dfs_find_final_overrider_q): Adjust use of vpath.
(dfs_find_final_overrider_post): Likewise.
(find_final_overrider): Use dfs_depth. Allocate and deallocate
vpath_list.
2004-08-12 Jan Beulich <jbeulich@novell.com> 2004-08-12 Jan Beulich <jbeulich@novell.com>
* parser.c (cp_parser_asm_definition): Properly consume scope operator * parser.c (cp_parser_asm_definition): Properly consume scope operator
......
...@@ -1842,6 +1842,36 @@ base_derived_from (tree derived, tree base) ...@@ -1842,6 +1842,36 @@ base_derived_from (tree derived, tree base)
return false; return false;
} }
typedef struct count_depth_data {
/* The depth of the current subobject, with "1" as the depth of the
most derived object in the hierarchy. */
size_t depth;
/* The maximum depth found so far. */
size_t max_depth;
} count_depth_data;
/* Called from find_final_overrider via dfs_walk. */
static tree
dfs_depth_post (tree binfo ATTRIBUTE_UNUSED, void *data)
{
count_depth_data *cd = (count_depth_data *) data;
if (cd->depth > cd->max_depth)
cd->max_depth = cd->depth;
cd->depth--;
return NULL_TREE;
}
/* Called from find_final_overrider via dfs_walk. */
static tree
dfs_depth_q (tree derived, int i, void *data)
{
count_depth_data *cd = (count_depth_data *) data;
cd->depth++;
return BINFO_BASE_BINFO (derived, i);
}
typedef struct find_final_overrider_data_s { typedef struct find_final_overrider_data_s {
/* The function for which we are trying to find a final overrider. */ /* The function for which we are trying to find a final overrider. */
tree fn; tree fn;
...@@ -1851,70 +1881,73 @@ typedef struct find_final_overrider_data_s { ...@@ -1851,70 +1881,73 @@ typedef struct find_final_overrider_data_s {
tree most_derived_type; tree most_derived_type;
/* The candidate overriders. */ /* The candidate overriders. */
tree candidates; tree candidates;
/* Binfos which inherited virtually on the current path. */ /* Each entry in this array is the next-most-derived class for a
tree vpath; virtual base class along the current path. */
tree *vpath_list;
/* A pointer one past the top of the VPATH_LIST. */
tree *vpath;
} find_final_overrider_data; } find_final_overrider_data;
/* Called from find_final_overrider via dfs_walk. */ /* Add the overrider along the current path to FFOD->CANDIDATES.
Returns true if an overrider was found; false otherwise. */
static tree static bool
dfs_find_final_overrider (tree binfo, void* data) dfs_find_final_overrider_1 (tree binfo,
tree *vpath,
find_final_overrider_data *ffod)
{ {
find_final_overrider_data *ffod = (find_final_overrider_data *) data; /* If BINFO is not the most derived type, try a more derived class.
A definition there will overrider a definition here. */
if (binfo == ffod->declaring_base) if (!same_type_p (BINFO_TYPE (binfo), ffod->most_derived_type))
{ {
/* We've found a path to the declaring base. Walk the path from tree derived;
derived to base, looking for an overrider for FN. */
tree path, probe, vpath;
/* Build the path, using the inheritance chain and record of if (BINFO_VIRTUAL_P (binfo))
virtual inheritance. */ derived = *--vpath;
for (path = NULL_TREE, probe = binfo, vpath = ffod->vpath;;) else
derived = BINFO_INHERITANCE_CHAIN (binfo);
if (dfs_find_final_overrider_1 (derived, vpath, ffod))
return true;
}
tree method = look_for_overrides_here (BINFO_TYPE (binfo), ffod->fn);
if (method)
{
tree *candidate = &ffod->candidates;
/* Remove any candidates overridden by this new function. */
while (*candidate)
{ {
path = tree_cons (NULL_TREE, probe, path); /* If *CANDIDATE overrides METHOD, then METHOD
if (same_type_p (BINFO_TYPE (probe), ffod->most_derived_type)) cannot override anything else on the list. */
break; if (base_derived_from (TREE_VALUE (*candidate), binfo))
if (BINFO_VIRTUAL_P (probe)) return true;
{ /* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */
probe = TREE_VALUE (vpath); if (base_derived_from (binfo, TREE_VALUE (*candidate)))
vpath = TREE_CHAIN (vpath); *candidate = TREE_CHAIN (*candidate);
}
else else
probe = BINFO_INHERITANCE_CHAIN (probe); candidate = &TREE_CHAIN (*candidate);
}
/* Now walk path, looking for overrides. */
for (; path; path = TREE_CHAIN (path))
{
tree method = look_for_overrides_here
(BINFO_TYPE (TREE_VALUE (path)), ffod->fn);
if (method)
{
tree *candidate = &ffod->candidates;
path = TREE_VALUE (path);
/* Remove any candidates overridden by this new function. */
while (*candidate)
{
/* If *CANDIDATE overrides METHOD, then METHOD
cannot override anything else on the list. */
if (base_derived_from (TREE_VALUE (*candidate), path))
return NULL_TREE;
/* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */
if (base_derived_from (path, TREE_VALUE (*candidate)))
*candidate = TREE_CHAIN (*candidate);
else
candidate = &TREE_CHAIN (*candidate);
}
/* Add the new function. */
ffod->candidates = tree_cons (method, path, ffod->candidates);
break;
}
} }
/* Add the new function. */
ffod->candidates = tree_cons (method, binfo, ffod->candidates);
return true;
} }
return false;
}
/* Called from find_final_overrider via dfs_walk. */
static tree
dfs_find_final_overrider (tree binfo, void* data)
{
find_final_overrider_data *ffod = (find_final_overrider_data *) data;
if (binfo == ffod->declaring_base)
dfs_find_final_overrider_1 (binfo, ffod->vpath, ffod);
return NULL_TREE; return NULL_TREE;
} }
...@@ -1925,7 +1958,7 @@ dfs_find_final_overrider_q (tree derived, int ix, void *data) ...@@ -1925,7 +1958,7 @@ dfs_find_final_overrider_q (tree derived, int ix, void *data)
find_final_overrider_data *ffod = (find_final_overrider_data *) data; find_final_overrider_data *ffod = (find_final_overrider_data *) data;
if (BINFO_VIRTUAL_P (binfo)) if (BINFO_VIRTUAL_P (binfo))
ffod->vpath = tree_cons (NULL_TREE, derived, ffod->vpath); *ffod->vpath++ = derived;
return binfo; return binfo;
} }
...@@ -1935,8 +1968,8 @@ dfs_find_final_overrider_post (tree binfo, void *data) ...@@ -1935,8 +1968,8 @@ dfs_find_final_overrider_post (tree binfo, void *data)
{ {
find_final_overrider_data *ffod = (find_final_overrider_data *) data; find_final_overrider_data *ffod = (find_final_overrider_data *) data;
if (BINFO_VIRTUAL_P (binfo) && TREE_CHAIN (ffod->vpath)) if (BINFO_VIRTUAL_P (binfo))
ffod->vpath = TREE_CHAIN (ffod->vpath); ffod->vpath--;
return NULL_TREE; return NULL_TREE;
} }
...@@ -1950,6 +1983,7 @@ static tree ...@@ -1950,6 +1983,7 @@ static tree
find_final_overrider (tree derived, tree binfo, tree fn) find_final_overrider (tree derived, tree binfo, tree fn)
{ {
find_final_overrider_data ffod; find_final_overrider_data ffod;
count_depth_data cd;
/* Getting this right is a little tricky. This is valid: /* Getting this right is a little tricky. This is valid:
...@@ -1971,12 +2005,18 @@ find_final_overrider (tree derived, tree binfo, tree fn) ...@@ -1971,12 +2005,18 @@ find_final_overrider (tree derived, tree binfo, tree fn)
different overriders along any two, then there is a problem. */ different overriders along any two, then there is a problem. */
if (DECL_THUNK_P (fn)) if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn); fn = THUNK_TARGET (fn);
/* Determine the depth of the hierarchy. */
cd.depth = 0;
cd.max_depth = 0;
dfs_walk (derived, dfs_depth_post, dfs_depth_q, &cd);
ffod.fn = fn; ffod.fn = fn;
ffod.declaring_base = binfo; ffod.declaring_base = binfo;
ffod.most_derived_type = BINFO_TYPE (derived); ffod.most_derived_type = BINFO_TYPE (derived);
ffod.candidates = NULL_TREE; ffod.candidates = NULL_TREE;
ffod.vpath = NULL_TREE; ffod.vpath_list = (tree *) xcalloc (cd.max_depth, sizeof (tree));
ffod.vpath = ffod.vpath_list;
dfs_walk_real (derived, dfs_walk_real (derived,
dfs_find_final_overrider, dfs_find_final_overrider,
...@@ -1984,6 +2024,8 @@ find_final_overrider (tree derived, tree binfo, tree fn) ...@@ -1984,6 +2024,8 @@ find_final_overrider (tree derived, tree binfo, tree fn)
dfs_find_final_overrider_q, dfs_find_final_overrider_q,
&ffod); &ffod);
free (ffod.vpath_list);
/* If there was no winner, issue an error message. */ /* If there was no winner, issue an error message. */
if (!ffod.candidates || TREE_CHAIN (ffod.candidates)) if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment