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:
parent
c21f27a762
commit
67ffc8124f
|
@ -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>
|
1998-05-24 Mark Mitchell <mark@markmitchell.com>
|
||||||
|
|
||||||
* tree.c (cp_tree_equal): Handle pointers to member functions.
|
* tree.c (cp_tree_equal): Handle pointers to member functions.
|
||||||
|
|
|
@ -1452,6 +1452,11 @@ extern int flag_new_for_scope;
|
||||||
|
|
||||||
#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0)
|
#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 UNKNOWN_TYPE LANG_TYPE
|
||||||
|
|
||||||
/* Define fields and accessors for nodes representing declared names. */
|
/* 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_specialization;
|
||||||
extern int processing_explicit_instantiation;
|
extern int processing_explicit_instantiation;
|
||||||
|
extern int processing_template_parmlist;
|
||||||
|
|
||||||
/* in repo.c */
|
/* in repo.c */
|
||||||
extern void repo_template_used PROTO((tree));
|
extern void repo_template_used PROTO((tree));
|
||||||
|
|
|
@ -2291,9 +2291,15 @@ pushtag (name, type, globalize)
|
||||||
friend class S2;
|
friend class S2;
|
||||||
};
|
};
|
||||||
|
|
||||||
declares S2 to be at global scope. */
|
declares S2 to be at global scope. We must be
|
||||||
|| (processing_template_decl >
|
careful, however, of the following case:
|
||||||
template_class_depth (current_class_type))))
|
|
||||||
|
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);
|
d = push_template_decl_real (d, globalize);
|
||||||
/* If the current binding level is the binding level for
|
/* 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. */
|
/* Static anonymous unions are dealt with here. */
|
||||||
if (staticp && decl_context == TYPENAME
|
if (staticp && decl_context == TYPENAME
|
||||||
&& TREE_CODE (declspecs) == TREE_LIST
|
&& TREE_CODE (declspecs) == TREE_LIST
|
||||||
&& TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
|
&& ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
|
|
||||||
decl_context = FIELD;
|
decl_context = FIELD;
|
||||||
|
|
||||||
/* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
|
/* 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.
|
refer to it, so nothing needs know about the name change.
|
||||||
The TYPE_NAME field was filled in by build_struct_xref. */
|
The TYPE_NAME field was filled in by build_struct_xref. */
|
||||||
if (type != error_mark_node
|
if (type != error_mark_node
|
||||||
|
&& !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
|
||||||
&& TYPE_NAME (type)
|
&& TYPE_NAME (type)
|
||||||
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
|
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
|
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
|
||||||
|
|
|
@ -865,8 +865,7 @@ grok_x_components (specs, components)
|
||||||
{
|
{
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
/* Static anonymous unions come out as VAR_DECLs. */
|
/* Static anonymous unions come out as VAR_DECLs. */
|
||||||
if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
|
if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (t))))
|
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
/* We return SPECS here, because in the parser it was ending
|
/* We return SPECS here, because in the parser it was ending
|
||||||
|
@ -904,8 +903,7 @@ grok_x_components (specs, components)
|
||||||
tcode = enum_type_node;
|
tcode = enum_type_node;
|
||||||
|
|
||||||
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
|
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
|
||||||
if (TREE_CODE (t) == UNION_TYPE
|
if (ANON_UNION_TYPE_P (t))
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
|
|
||||||
{
|
{
|
||||||
/* See also shadow_tag. */
|
/* 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
|
if (DECL_NAME (field) == NULL_TREE
|
||||||
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
|
&& 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
|
else
|
||||||
{
|
{
|
||||||
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
|
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
|
||||||
|
|
|
@ -866,7 +866,7 @@ initializing_context (field)
|
||||||
|
|
||||||
/* Anonymous union members can be initialized in the first enclosing
|
/* Anonymous union members can be initialized in the first enclosing
|
||||||
non-anonymous union context. */
|
non-anonymous union context. */
|
||||||
while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
|
while (t && ANON_UNION_TYPE_P (t))
|
||||||
t = TYPE_CONTEXT (t);
|
t = TYPE_CONTEXT (t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,7 +515,13 @@ build_overload_int (value, in_template)
|
||||||
id = ansi_opname [(int) TREE_CODE (value)];
|
id = ansi_opname [(int) TREE_CODE (value)];
|
||||||
my_friendly_assert (id != NULL_TREE, 0);
|
my_friendly_assert (id != NULL_TREE, 0);
|
||||||
name = IDENTIFIER_POINTER (id);
|
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)
|
for (i = 0; i < operands; ++i)
|
||||||
{
|
{
|
||||||
|
@ -553,6 +559,7 @@ build_overload_int (value, in_template)
|
||||||
This should cause assembler errors we'll notice. */
|
This should cause assembler errors we'll notice. */
|
||||||
|
|
||||||
static int n;
|
static int n;
|
||||||
|
bad_value:
|
||||||
sprintf (digit_buffer, " *%d", n++);
|
sprintf (digit_buffer, " *%d", n++);
|
||||||
OB_PUTCP (digit_buffer);
|
OB_PUTCP (digit_buffer);
|
||||||
}
|
}
|
||||||
|
@ -2180,8 +2187,7 @@ do_build_copy_constructor (fndecl)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ((t = TREE_TYPE (field)) != NULL_TREE
|
else if ((t = TREE_TYPE (field)) != NULL_TREE
|
||||||
&& TREE_CODE (t) == UNION_TYPE
|
&& ANON_UNION_TYPE_P (t)
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
|
||||||
&& TYPE_FIELDS (t) != NULL_TREE)
|
&& TYPE_FIELDS (t) != NULL_TREE)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
|
@ -2190,8 +2196,7 @@ do_build_copy_constructor (fndecl)
|
||||||
field = largest_union_member (t);
|
field = largest_union_member (t);
|
||||||
}
|
}
|
||||||
while ((t = TREE_TYPE (field)) != NULL_TREE
|
while ((t = TREE_TYPE (field)) != NULL_TREE
|
||||||
&& TREE_CODE (t) == UNION_TYPE
|
&& ANON_UNION_TYPE_P (t)
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
|
||||||
&& TYPE_FIELDS (t) != NULL_TREE);
|
&& TYPE_FIELDS (t) != NULL_TREE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2290,8 +2295,7 @@ do_build_assign_ref (fndecl)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ((t = TREE_TYPE (field)) != NULL_TREE
|
else if ((t = TREE_TYPE (field)) != NULL_TREE
|
||||||
&& TREE_CODE (t) == UNION_TYPE
|
&& ANON_UNION_TYPE_P (t)
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
|
||||||
&& TYPE_FIELDS (t) != NULL_TREE)
|
&& TYPE_FIELDS (t) != NULL_TREE)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
|
@ -2301,8 +2305,7 @@ do_build_assign_ref (fndecl)
|
||||||
field = largest_union_member (t);
|
field = largest_union_member (t);
|
||||||
}
|
}
|
||||||
while ((t = TREE_TYPE (field)) != NULL_TREE
|
while ((t = TREE_TYPE (field)) != NULL_TREE
|
||||||
&& TREE_CODE (t) == UNION_TYPE
|
&& ANON_UNION_TYPE_P (t)
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
|
||||||
&& TYPE_FIELDS (t) != NULL_TREE);
|
&& TYPE_FIELDS (t) != NULL_TREE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
51
gcc/cp/pt.c
51
gcc/cp/pt.c
|
@ -63,6 +63,7 @@ int minimal_parse_mode;
|
||||||
|
|
||||||
int processing_specialization;
|
int processing_specialization;
|
||||||
int processing_explicit_instantiation;
|
int processing_explicit_instantiation;
|
||||||
|
int processing_template_parmlist;
|
||||||
static int template_header_count;
|
static int template_header_count;
|
||||||
|
|
||||||
static tree saved_trees;
|
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 tree tsubst_template_arg_vector PROTO((tree, tree));
|
||||||
static void regenerate_decl_from_template 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
|
/* Do any processing required when DECL (a member template declaration
|
||||||
using TEMPLATE_PARAMETERS as its innermost parameter list) is
|
using TEMPLATE_PARAMETERS as its innermost parameter list) is
|
||||||
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
|
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 (tmpl) == TEMPLATE_DECL, 0);
|
||||||
my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 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);
|
extra_arg_depth = TREE_VEC_LENGTH (extra_args);
|
||||||
else
|
else
|
||||||
extra_arg_depth = 1;
|
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
|
TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
|
||||||
all the bound template arguments. */
|
all the bound template arguments. */
|
||||||
args = DECL_TI_ARGS (tmpl);
|
args = DECL_TI_ARGS (tmpl);
|
||||||
if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
|
if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||||
depth = 1;
|
depth = 1;
|
||||||
else
|
else
|
||||||
depth = TREE_VEC_LENGTH (args);
|
depth = TREE_VEC_LENGTH (args);
|
||||||
|
@ -485,7 +494,7 @@ add_to_template_args (args, extra_args)
|
||||||
{
|
{
|
||||||
tree new_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);
|
new_args = make_tree_vec (2);
|
||||||
TREE_VEC_ELT (new_args, 0) = args;
|
TREE_VEC_ELT (new_args, 0) = args;
|
||||||
|
@ -529,6 +538,7 @@ begin_template_parm_list ()
|
||||||
pushlevel (0);
|
pushlevel (0);
|
||||||
declare_pseudo_global_level ();
|
declare_pseudo_global_level ();
|
||||||
++processing_template_decl;
|
++processing_template_decl;
|
||||||
|
++processing_template_parmlist;
|
||||||
note_template_header (0);
|
note_template_header (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1452,6 +1462,8 @@ end_template_parm_list (parms)
|
||||||
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
|
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
|
||||||
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
|
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
|
||||||
|
|
||||||
|
--processing_template_parmlist;
|
||||||
|
|
||||||
return saved_parmlist;
|
return saved_parmlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2858,6 +2870,7 @@ lookup_template_class (d1, arglist, in_decl, context)
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
push_decl_namespace (context);
|
push_decl_namespace (context);
|
||||||
|
if (current_class_type != NULL_TREE)
|
||||||
template =
|
template =
|
||||||
maybe_get_template_decl_from_type_decl
|
maybe_get_template_decl_from_type_decl
|
||||||
(IDENTIFIER_CLASS_VALUE (d1));
|
(IDENTIFIER_CLASS_VALUE (d1));
|
||||||
|
@ -3993,7 +4006,7 @@ innermost_args (args, is_spec)
|
||||||
tree args;
|
tree args;
|
||||||
int is_spec;
|
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 TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
@ -4189,8 +4202,7 @@ tsubst (t, args, in_decl)
|
||||||
{
|
{
|
||||||
tree arg = NULL_TREE;
|
tree arg = NULL_TREE;
|
||||||
|
|
||||||
if (TREE_VEC_ELT (args, 0) != NULL_TREE
|
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||||
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
|
|
||||||
{
|
{
|
||||||
levels = TREE_VEC_LENGTH (args);
|
levels = TREE_VEC_LENGTH (args);
|
||||||
if (level <= levels)
|
if (level <= levels)
|
||||||
|
@ -4275,7 +4287,7 @@ tsubst (t, args, in_decl)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEMPLATE_PARM_INDEX:
|
case TEMPLATE_PARM_INDEX:
|
||||||
r = reduce_template_parm_level (t, TREE_TYPE (t), levels);
|
r = reduce_template_parm_level (t, type, levels);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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
|
/* The PARM is not one we're trying to unify. Just check
|
||||||
to see if it matches ARG. */
|
to see if it matches ARG. */
|
||||||
return (TREE_CODE (arg) == TREE_CODE (parm)
|
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);
|
idx = TEMPLATE_PARM_IDX (parm);
|
||||||
targ = TREE_VEC_ELT (targs, idx);
|
targ = TREE_VEC_ELT (targs, idx);
|
||||||
|
|
||||||
if (targ)
|
if (targ)
|
||||||
{
|
{
|
||||||
int i = cp_tree_equal (targ, arg);
|
int i = (cp_tree_equal (targ, arg) > 0);
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
return 0;
|
return 0;
|
||||||
else if (i == 0)
|
else if (i == 0)
|
||||||
|
@ -7082,17 +7094,6 @@ instantiate_decl (d)
|
||||||
lineno = DECL_SOURCE_LINE (d);
|
lineno = DECL_SOURCE_LINE (d);
|
||||||
input_filename = DECL_SOURCE_FILE (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)
|
if (pattern_defined)
|
||||||
{
|
{
|
||||||
repo_template_used (d);
|
repo_template_used (d);
|
||||||
|
@ -7123,11 +7124,17 @@ instantiate_decl (d)
|
||||||
&& ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
|
&& ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Defer all templates except inline functions used in another function. */
|
if (TREE_CODE (d) == VAR_DECL
|
||||||
if (! pattern_defined
|
&& 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)
|
|| (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
|
||||||
&& ! at_eof))
|
&& ! at_eof))
|
||||||
{
|
{
|
||||||
|
/* Defer all templates except inline functions used in another
|
||||||
|
function. */
|
||||||
lineno = line;
|
lineno = line;
|
||||||
input_filename = file;
|
input_filename = file;
|
||||||
|
|
||||||
|
|
|
@ -969,8 +969,7 @@ compute_access (basetype_path, field)
|
||||||
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
|
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
|
||||||
slot set to the union type rather than the record type containing
|
slot set to the union type rather than the record type containing
|
||||||
the anonymous union. */
|
the anonymous union. */
|
||||||
if (context && TREE_CODE (context) == UNION_TYPE
|
if (context && ANON_UNION_TYPE_P (context))
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
|
|
||||||
context = TYPE_CONTEXT (context);
|
context = TYPE_CONTEXT (context);
|
||||||
|
|
||||||
/* Virtual function tables are never private. But we should know that
|
/* Virtual function tables are never private. But we should know that
|
||||||
|
|
|
@ -2065,8 +2065,8 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||||
{
|
{
|
||||||
tree context = DECL_FIELD_CONTEXT (field);
|
tree context = DECL_FIELD_CONTEXT (field);
|
||||||
tree base = context;
|
tree base = context;
|
||||||
while (base != basetype && TYPE_NAME (base)
|
while (!comptypes (base, basetype,1) && TYPE_NAME (base)
|
||||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (base)))
|
&& ANON_UNION_TYPE_P (base))
|
||||||
{
|
{
|
||||||
base = TYPE_CONTEXT (base);
|
base = TYPE_CONTEXT (base);
|
||||||
}
|
}
|
||||||
|
@ -2096,7 +2096,7 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||||
basetype = base;
|
basetype = base;
|
||||||
|
|
||||||
/* Handle things from anon unions here... */
|
/* 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 subfield = lookup_anon_field (basetype, context);
|
||||||
tree subdatum = build_component_ref (datum, subfield,
|
tree subdatum = build_component_ref (datum, subfield,
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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> >;
|
Loading…
Reference in New Issue