decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.

1998-05-25  Mark Mitchell  <mark@markmitchell.com>
	* decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
	* cp-tree.h (processing_template_parmlist): Declare.
	* decl.c (pushtag): Don't call push_template_decl when we
	shouldn't.
	* pt.c (processing_template_parmlist): New variable.
	(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
	(complete_template_args): Use it.
	(add_to_template_args): Likewise.
	(innermost_args): Likewise.
	(tsubst): Likewise.
	(begin_template_parm_list): Use processing_template_parmlist.
	(end_template_parm_list): Likewise.
	* cp-tree.h (ANON_UNION_TYPE_P): New macro.
	* decl.c (grokdeclarator): Use it.
	* decl2.c (grok_x_components): Likewise.
	* init.c (initializing_context): Likewise.
	* method.c (do_build_copy_constructor): Likewise.
	(do_build_assign_ref): Likewise.
	* search.c (compute_access): Likewise.
	* typeck.c (build_component_ref): Likewise.
	* decl.c (grokdeclarator): Don't give a cv-qualified version of an
	unnamed type a typedef name "for linkage purposes".
	* pt.c (lookup_template_class): Don't look at
	IDENTIFIER_CLASS_VALUE when there's no current_class_type.
	* method.c (build_overload_int): Handle error cases gracefully.
	* pt.c (instantiate_decl): Handle static member variables
	correctly.
	* pt.c (tsubst): Use the tsubst'd type when producing new
	TEMPLATE_PARM_INDEX nodes.

From-SVN: r20045
This commit is contained in:
Mark Mitchell 1998-05-25 10:28:16 +00:00 committed by Mark Mitchell
parent c21f27a762
commit 67ffc8124f
14 changed files with 215 additions and 52 deletions

View File

@ -1,3 +1,42 @@
1998-05-25 Mark Mitchell <mark@markmitchell.com>
* decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
* cp-tree.h (processing_template_parmlist): Declare.
* decl.c (pushtag): Don't call push_template_decl when we
shouldn't.
* pt.c (processing_template_parmlist): New variable.
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
(complete_template_args): Use it.
(add_to_template_args): Likewise.
(innermost_args): Likewise.
(tsubst): Likewise.
(begin_template_parm_list): Use processing_template_parmlist.
(end_template_parm_list): Likewise.
* cp-tree.h (ANON_UNION_TYPE_P): New macro.
* decl.c (grokdeclarator): Use it.
* decl2.c (grok_x_components): Likewise.
* init.c (initializing_context): Likewise.
* method.c (do_build_copy_constructor): Likewise.
(do_build_assign_ref): Likewise.
* search.c (compute_access): Likewise.
* typeck.c (build_component_ref): Likewise.
* decl.c (grokdeclarator): Don't give a cv-qualified version of an
unnamed type a typedef name "for linkage purposes".
* pt.c (lookup_template_class): Don't look at
IDENTIFIER_CLASS_VALUE when there's no current_class_type.
* method.c (build_overload_int): Handle error cases gracefully.
* pt.c (instantiate_decl): Handle static member variables
correctly.
* pt.c (tsubst): Use the tsubst'd type when producing new
TEMPLATE_PARM_INDEX nodes.
1998-05-24 Mark Mitchell <mark@markmitchell.com>
* tree.c (cp_tree_equal): Handle pointers to member functions.

View File

@ -1452,6 +1452,11 @@ extern int flag_new_for_scope;
#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0)
/* Nonzero if TYPE is an anonymous union type. */
#define ANON_UNION_TYPE_P(TYPE) \
(TREE_CODE (TYPE) == UNION_TYPE \
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TYPE)))
#define UNKNOWN_TYPE LANG_TYPE
/* Define fields and accessors for nodes representing declared names. */
@ -2644,6 +2649,7 @@ extern int comp_template_args PROTO((tree, tree));
extern int processing_specialization;
extern int processing_explicit_instantiation;
extern int processing_template_parmlist;
/* in repo.c */
extern void repo_template_used PROTO((tree));

View File

@ -2291,9 +2291,15 @@ pushtag (name, type, globalize)
friend class S2;
};
declares S2 to be at global scope. */
|| (processing_template_decl >
template_class_depth (current_class_type))))
declares S2 to be at global scope. We must be
careful, however, of the following case:
template <class A*> struct S;
which declares a non-template class `A'. */
|| (!processing_template_parmlist
&& (processing_template_decl >
template_class_depth (current_class_type)))))
{
d = push_template_decl_real (d, globalize);
/* If the current binding level is the binding level for
@ -8750,8 +8756,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
&& TREE_CODE (declspecs) == TREE_LIST
&& TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
&& ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
decl_context = FIELD;
/* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
@ -9659,6 +9664,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
refer to it, so nothing needs know about the name change.
The TYPE_NAME field was filled in by build_struct_xref. */
if (type != error_mark_node
&& !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))

View File

@ -865,8 +865,7 @@ grok_x_components (specs, components)
{
case VAR_DECL:
/* Static anonymous unions come out as VAR_DECLs. */
if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (t))))
if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
return t;
/* We return SPECS here, because in the parser it was ending
@ -904,8 +903,7 @@ grok_x_components (specs, components)
tcode = enum_type_node;
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
if (TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
if (ANON_UNION_TYPE_P (t))
{
/* See also shadow_tag. */
@ -2176,7 +2174,11 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
decl = build_anon_union_vars (field, elems, static_p, external_p);
{
decl = build_anon_union_vars (field, elems, static_p, external_p);
if (!decl)
continue;
}
else
{
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));

View File

@ -866,7 +866,7 @@ initializing_context (field)
/* Anonymous union members can be initialized in the first enclosing
non-anonymous union context. */
while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
while (t && ANON_UNION_TYPE_P (t))
t = TYPE_CONTEXT (t);
return t;
}

View File

@ -515,7 +515,13 @@ build_overload_int (value, in_template)
id = ansi_opname [(int) TREE_CODE (value)];
my_friendly_assert (id != NULL_TREE, 0);
name = IDENTIFIER_POINTER (id);
my_friendly_assert (name[0] == '_' && name[1] == '_', 0);
if (name[0] != '_' || name[1] != '_')
/* On some erroneous inputs, we can get here with VALUE a
LOOKUP_EXPR. In that case, the NAME will be the
identifier for "<invalid operator>". We must survive
this routine in order to issue a sensible error
message, so we fall through to the case below. */
goto bad_value;
for (i = 0; i < operands; ++i)
{
@ -553,6 +559,7 @@ build_overload_int (value, in_template)
This should cause assembler errors we'll notice. */
static int n;
bad_value:
sprintf (digit_buffer, " *%d", n++);
OB_PUTCP (digit_buffer);
}
@ -2180,8 +2187,7 @@ do_build_copy_constructor (fndecl)
continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
&& ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
{
do
@ -2190,8 +2196,7 @@ do_build_copy_constructor (fndecl)
field = largest_union_member (t);
}
while ((t = TREE_TYPE (field)) != NULL_TREE
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
&& ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE);
}
else
@ -2290,8 +2295,7 @@ do_build_assign_ref (fndecl)
continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
&& ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
{
do
@ -2301,8 +2305,7 @@ do_build_assign_ref (fndecl)
field = largest_union_member (t);
}
while ((t = TREE_TYPE (field)) != NULL_TREE
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
&& ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE);
}
else

View File

@ -63,6 +63,7 @@ int minimal_parse_mode;
int processing_specialization;
int processing_explicit_instantiation;
int processing_template_parmlist;
static int template_header_count;
static tree saved_trees;
@ -115,6 +116,14 @@ static int check_cv_quals_for_unify PROTO((int, tree, tree));
static tree tsubst_template_arg_vector PROTO((tree, tree));
static void regenerate_decl_from_template PROTO((tree, tree));
/* Nonzero if ARGVEC contains multiple levels of template arguments. */
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
(NODE != NULL_TREE \
&& TREE_CODE (NODE) == TREE_VEC \
&& TREE_VEC_LENGTH (NODE) > 0 \
&& TREE_VEC_ELT (NODE, 0) != NULL_TREE \
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
/* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
@ -388,7 +397,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
if (TREE_CODE (TREE_VEC_ELT (extra_args, 0)) == TREE_VEC)
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args))
extra_arg_depth = TREE_VEC_LENGTH (extra_args);
else
extra_arg_depth = 1;
@ -411,7 +420,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
all the bound template arguments. */
args = DECL_TI_ARGS (tmpl);
if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
depth = 1;
else
depth = TREE_VEC_LENGTH (args);
@ -485,7 +494,7 @@ add_to_template_args (args, extra_args)
{
tree new_args;
if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
{
new_args = make_tree_vec (2);
TREE_VEC_ELT (new_args, 0) = args;
@ -529,6 +538,7 @@ begin_template_parm_list ()
pushlevel (0);
declare_pseudo_global_level ();
++processing_template_decl;
++processing_template_parmlist;
note_template_header (0);
}
@ -1452,6 +1462,8 @@ end_template_parm_list (parms)
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
--processing_template_parmlist;
return saved_parmlist;
}
@ -2858,9 +2870,10 @@ lookup_template_class (d1, arglist, in_decl, context)
{
if (context)
push_decl_namespace (context);
template =
maybe_get_template_decl_from_type_decl
(IDENTIFIER_CLASS_VALUE (d1));
if (current_class_type != NULL_TREE)
template =
maybe_get_template_decl_from_type_decl
(IDENTIFIER_CLASS_VALUE (d1));
if (template == NULL_TREE)
template = lookup_name_nonclass (d1);
if (context)
@ -3993,7 +4006,7 @@ innermost_args (args, is_spec)
tree args;
int is_spec;
{
if (args != NULL_TREE && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
return args;
}
@ -4189,8 +4202,7 @@ tsubst (t, args, in_decl)
{
tree arg = NULL_TREE;
if (TREE_VEC_ELT (args, 0) != NULL_TREE
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
{
levels = TREE_VEC_LENGTH (args);
if (level <= levels)
@ -4275,7 +4287,7 @@ tsubst (t, args, in_decl)
break;
case TEMPLATE_PARM_INDEX:
r = reduce_template_parm_level (t, TREE_TYPE (t), levels);
r = reduce_template_parm_level (t, type, levels);
break;
default:
@ -6220,14 +6232,14 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
/* The PARM is not one we're trying to unify. Just check
to see if it matches ARG. */
return (TREE_CODE (arg) == TREE_CODE (parm)
&& cp_tree_equal (parm, arg)) ? 0 : 1;
&& cp_tree_equal (parm, arg) > 0) ? 0 : 1;
idx = TEMPLATE_PARM_IDX (parm);
targ = TREE_VEC_ELT (targs, idx);
if (targ)
{
int i = cp_tree_equal (targ, arg);
int i = (cp_tree_equal (targ, arg) > 0);
if (i == 1)
return 0;
else if (i == 0)
@ -7082,17 +7094,6 @@ instantiate_decl (d)
lineno = DECL_SOURCE_LINE (d);
input_filename = DECL_SOURCE_FILE (d);
/* We need to set up DECL_INITIAL regardless of pattern_defined if the
variable is a static const initialized in the class body. */
if (TREE_CODE (d) == VAR_DECL
&& ! DECL_INITIAL (d) && DECL_INITIAL (code_pattern))
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (d) = tsubst_expr (DECL_INITIAL (code_pattern), args,
tmpl);
cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0, LOOKUP_NORMAL);
}
if (pattern_defined)
{
repo_template_used (d);
@ -7123,11 +7124,17 @@ instantiate_decl (d)
&& ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
goto out;
/* Defer all templates except inline functions used in another function. */
if (! pattern_defined
|| (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
&& ! at_eof))
if (TREE_CODE (d) == VAR_DECL
&& DECL_INITIAL (d) == NULL_TREE
&& DECL_INITIAL (code_pattern) != NULL_TREE)
/* We need to set up DECL_INITIAL regardless of pattern_defined if
the variable is a static const initialized in the class body. */;
else if (! pattern_defined
|| (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
&& ! at_eof))
{
/* Defer all templates except inline functions used in another
function. */
lineno = line;
input_filename = file;

View File

@ -969,8 +969,7 @@ compute_access (basetype_path, field)
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
slot set to the union type rather than the record type containing
the anonymous union. */
if (context && TREE_CODE (context) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
if (context && ANON_UNION_TYPE_P (context))
context = TYPE_CONTEXT (context);
/* Virtual function tables are never private. But we should know that

View File

@ -2065,8 +2065,8 @@ build_component_ref (datum, component, basetype_path, protect)
{
tree context = DECL_FIELD_CONTEXT (field);
tree base = context;
while (base != basetype && TYPE_NAME (base)
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (base)))
while (!comptypes (base, basetype,1) && TYPE_NAME (base)
&& ANON_UNION_TYPE_P (base))
{
base = TYPE_CONTEXT (base);
}
@ -2096,7 +2096,7 @@ build_component_ref (datum, component, basetype_path, protect)
basetype = base;
/* Handle things from anon unions here... */
if (TYPE_NAME (context) && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context))
{
tree subfield = lookup_anon_field (basetype, context);
tree subdatum = build_component_ref (datum, subfield,

View File

@ -0,0 +1,13 @@
// Build don't link:
typedef const struct {
int x;
} Test;
void foo(Test);
void foo(Test t)
{
t.x = 0; // ERROR - assignment of read-only member
return;
}

View File

@ -0,0 +1,12 @@
// Build don't link:
template <class T, int i>
struct K {
void f();
};
template <class T>
void
K<T, i>::f()
{ // ERROR - template parameters
}

View File

@ -0,0 +1,25 @@
// Build don't link:
void
print(const int& i)
{
}
template<class A>
class bar
{
public:
template<void (*B)(const A& a)>
void doit(const A& a)
{
B(a);
}
};
int
main()
{
bar<int> b;
b.template doit<print>(2);
}

View File

@ -0,0 +1,30 @@
// Build don't link:
template<class A, class B>
void foo(const A& a, const B& b)
{
}
template<class A, class B>
void foo(const A& a, const int& b)
{
}
template<class A*, class B>
void foo(const A*& a, const B& b)
{
}
template<>
void foo(const int&, const double&)
{
}
int
main()
{
foo("98239", 23);
foo(232, 1.022);
}

View File

@ -0,0 +1,21 @@
// Build don't link:
template <class A>
class TEST
{
public:
TEST (A) {}
};
template <class A>
class TEST2
{
static A i;
};
template <class A>
A TEST2 <A>::i (0);
TEST2 <TEST <int> > a;
template class TEST2 <TEST <int> >;