Commit e1467ff2 by Mark Mitchell Committed by Jason Merrill

call.c (add_template_candidate_real): New function.

	* call.c (add_template_candidate_real): New function.
	(add_template_candidate): Use it.
	(add_template_conv_candidate): Likewise.
	(joust): Pass extra argument to more_specialized.
	* class.c (instantiate_type): Handle a single FUNCTION_DECL.
	(is_local_class): Remove.
	(finish_struct): Check TI_PENDING_SPECIALIZATION_FLAG.
	* cp-tree.h (is_local_class): Remove.
	(perform_array_to_pointer_conversion): Likewise.
	(finish_member_template_decl): Add.
	(check_explicit_specialization): Return a tree, not an int.
	(more_specialized): Take additional argument.
	(get_bindings): Likewise.
	(TI_PENDING_SPECIALIZATION_FLAG): New macro.
	* cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes.
	(perform_array_to_pointer_conversion): Remove.
	* decl.c (saved_scope): Add processing_specialization,
	processing_explicit_instantiation fields.
	(maybe_push_to_top_level): Save them.
	(pop_from_top_level): Restore them.
	(grokfndecl): Use new return value from
	check_explicit_specialization.
	(start_decl): Don't check flag_guiding_decls before pushing
	decls.
	(cp_finish_decl): Remove previous (bogus) change.
	(grok_declarator): Use decl_function_context rather than
	is_local_class.
	* decl2.c (finish_file): Pass extra argument to get_bindings.
	(build_expr_from_tree): Let build_x_component_ref check
	validity of arguments rather than doing it here.
	* lex.c (cons_up_default_function): Remove code fooling with
	processing_specialization, processing_explicit_instantiation
	flags, as that is now done in {maybe_push_top,pop_from}_top_level.
	* method.c (build_overload_identifier): Mangle local classes in
	template functions correctly.
	* parse.y (finish_member_template_decl): Move to pt.c.
	* pt.c (finish_member_template_decl): Moved here from parse.y.
	(print_candidates): New function.
	(determine_specialization): Change interface.  Properly look for
	most specialized versions of template candidates.
	(check_explicit_specialization): Fully process explicit
	instantiations.
	(push_template_decl): Avoid looking at CLASSTYPE fields in
	FUNCTION_DECLS.
	(determine_overloaded_function): Remove.
	(convert_nontype_argument): Change name from
	convert_nontype_parameter.  Use determine_overloaded_function
	instead of instantiate_type.
	(mangle_class_name_for_template): Handle type contexts as well as
	function contexts.
	(classtype_mangled_name): Likewise.
	(lookup_template_class): Likewise.
	(tsubst): Likewise.
	(more_specialized): Take explict template arguments as a
	parameter.
	(most_specialized): Likewise.
	(get_bindings): Likewise.  Check that return types match before
	proclaiming a function a match.
	(do_decl_instantiation): Remove code searching for function to
	instantiate; that is now done in check_explicit_specialization.
	(add_maybe_template): Pass extra argument to get_bindings.
	* tree.c (really_overloaded_fn): Use is_overloaded_fn to simplify
	implementation.
	* typeck.c (build_component_ref): Check for invalid arguments.

From-SVN: r17512
parent c3499f00
Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
* call.c (add_template_candidate_real): New function.
(add_template_candidate): Use it.
(add_template_conv_candidate): Likewise.
(joust): Pass extra argument to more_specialized.
* class.c (instantiate_type): Handle a single FUNCTION_DECL.
(is_local_class): Remove.
(finish_struct): Check TI_PENDING_SPECIALIZATION_FLAG.
* cp-tree.h (is_local_class): Remove.
(perform_array_to_pointer_conversion): Likewise.
(finish_member_template_decl): Add.
(check_explicit_specialization): Return a tree, not an int.
(more_specialized): Take additional argument.
(get_bindings): Likewise.
* cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes.
(perform_array_to_pointer_conversion): Remove.
* decl.c (saved_scope): Add processing_specialization,
processing_explicit_instantiation fields.
(maybe_push_to_top_level): Save them.
(pop_from_top_level): Restore them.
(grokfndecl): Use new return value from
check_explicit_specialization.
(start_decl): Don't check flag_guiding_decls before pushing
decls.
(cp_finish_decl): Remove previous (bogus) change.
(grok_declarator): Use decl_function_context rather than
is_local_class.
* decl2.c (finish_file): Pass extra argument to get_bindings.
(build_expr_from_tree): Let build_x_component_ref check
validity of arguments rather than doing it here.
* lex.c (cons_up_default_function): Remove code fooling with
processing_specialization, processing_explicit_instantiation
flags, as that is now done in {maybe_push_top,pop_from}_top_level.
* method.c (build_overload_identifier): Mangle local classes in
template functions correctly.
* parse.y (finish_member_template_decl): Move to pt.c.
* pt.c (finish_member_template_decl): Moved here from parse.y.
(print_candidates): New function.
(determine_specialization): Change interface. Properly look for
most specialized versions of template candidates.
(check_explicit_specialization): Fully process explicit
instantiations.
(push_template_decl): Avoid looking at CLASSTYPE fields in
FUNCTION_DECLS.
(determine_overloaded_function): Remove.
(convert_nontype_argument): Change name from
convert_nontype_parameter. Use determine_overloaded_function
instead of instantiate_type.
(mangle_class_name_for_template): Handle type contexts as well as
function contexts.
(classtype_mangled_name): Likewise.
(lookup_template_class): Likewise.
(tsubst): Likewise.
(more_specialized): Take explict template arguments as a
parameter.
(most_specialized): Likewise.
(get_bindings): Likewise. Check that return types match before
proclaiming a function a match.
(do_decl_instantiation): Remove code searching for function to
instantiate; that is now done in check_explicit_specialization.
(add_maybe_template): Pass extra argument to get_bindings.
* tree.c (really_overloaded_fn): Use is_overloaded_fn to simplify
implementation.
* typeck.c (build_component_ref): Check for invalid arguments.
Tue Jan 27 01:44:02 1998 Jason Merrill <jason@yorick.cygnus.com> Tue Jan 27 01:44:02 1998 Jason Merrill <jason@yorick.cygnus.com>
* expr.c (cplus_expand_expr, AGGR_INIT_EXPR): Don't check that * expr.c (cplus_expand_expr, AGGR_INIT_EXPR): Don't check that
......
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
* The name of a class is now implicitly declared in its own scope; A::A * The name of a class is now implicitly declared in its own scope; A::A
refers to A. refers to A.
* Local classes are now supported, though not inside templates. * Local classes are now supported.
* __attribute__ can now be attached to types as well as declarations. * __attribute__ can now be attached to types as well as declarations.
......
...@@ -4149,20 +4149,25 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags) ...@@ -4149,20 +4149,25 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
return candidates; return candidates;
} }
/* If TMPL can be successfully instantiated as indicated by /* If TMPL can be successfully instantiated as indicated by
EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES. EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES.
TMPL is the template. EXPLICIT_TARGS are any explicit template arguments. TMPL is the template. EXPLICIT_TARGS are any explicit template
ARGLIST is the arguments provided at the call-site. The RETURN_TYPE arguments. ARGLIST is the arguments provided at the call-site.
is the desired type for conversion operators. FLAGS are as for The RETURN_TYPE is the desired type for conversion operators. If
add_function_candidate. */ OBJ is NULL_TREE, FLAGS are as for add_function_candidate. If an
OBJ is supplied, FLAGS are ignored, and OBJ is as for
static struct z_candidate * add_conv_candidate. */
add_template_candidate (candidates, tmpl, explicit_targs,
arglist, return_type, flags) static struct z_candidate*
add_template_candidate_real (candidates, tmpl, explicit_targs,
arglist, return_type, flags,
obj)
struct z_candidate *candidates; struct z_candidate *candidates;
tree tmpl, explicit_targs, arglist, return_type; tree tmpl, explicit_targs, arglist, return_type;
int flags; int flags;
tree obj;
{ {
int ntparms = DECL_NTPARMS (tmpl); int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_scratch_vec (ntparms); tree targs = make_scratch_vec (ntparms);
...@@ -4180,35 +4185,58 @@ add_template_candidate (candidates, tmpl, explicit_targs, ...@@ -4180,35 +4185,58 @@ add_template_candidate (candidates, tmpl, explicit_targs,
if (fn == error_mark_node) if (fn == error_mark_node)
return candidates; return candidates;
cand = add_function_candidate (candidates, fn, arglist, flags); if (obj != NULL_TREE)
cand->template = DECL_TEMPLATE_INFO (fn); /* Aha, this is a conversion function. */
cand = add_conv_candidate (candidates, fn, obj, arglist);
else
cand = add_function_candidate (candidates, fn, arglist, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
class is specialized. Then, instantiate_template might return
an instantiation of the specialization, in which case the
DECL_TI_TEMPLATE field will point at the original
specialization. For example:
template <class T> struct S { template <class U> void f(U);
template <> void f(int) {}; };
S<double> sd;
sd.f(3);
Here, TMPL will be template <class U> S<double>::f(U).
And, instantiate template will give us the specialization
template <> S<double>::f(int). But, the DECL_TI_TEMPLATE field
for this will point at template <class T> template <> S<T>::f(int),
so that we can find the definition. For the purposes of
overload resolution, however, we want the original TMPL. */
cand->template = tree_cons (tmpl, targs, NULL_TREE);
else
cand->template = DECL_TEMPLATE_INFO (fn);
return cand; return cand;
} }
static struct z_candidate * static struct z_candidate *
add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type) add_template_candidate (candidates, tmpl, explicit_targs,
arglist, return_type, flags)
struct z_candidate *candidates; struct z_candidate *candidates;
tree tmpl, obj, arglist, return_type; tree tmpl, explicit_targs, arglist, return_type;
int flags;
{ {
int ntparms = DECL_NTPARMS (tmpl); return
tree targs = make_scratch_vec (ntparms); add_template_candidate_real (candidates, tmpl, explicit_targs,
struct z_candidate *cand; arglist, return_type, flags, NULL_TREE);
int i; }
tree fn;
i = fn_type_unification (tmpl, NULL_TREE, targs, arglist, return_type, 0);
if (i != 0) static struct z_candidate *
return candidates; add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
struct z_candidate *candidates;
fn = instantiate_template (tmpl, targs); tree tmpl, obj, arglist, return_type;
if (fn == error_mark_node) {
return candidates; return
add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist,
cand = add_conv_candidate (candidates, fn, obj, arglist); return_type, 0, obj);
cand->template = DECL_TEMPLATE_INFO (fn);
return cand;
} }
...@@ -4360,6 +4388,12 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -4360,6 +4388,12 @@ build_user_type_conversion_1 (totype, expr, flags)
ics = implicit_conversion ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags); (totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags);
else else
/* Here, the template conversion operator result must
precisely match the TOTYPE. (FIXME: Actually, we're
supposed to do some simple conversions here; see
[temp.deduct.conv].). If the result of the conversion
operator is not actually TOTYPE, then
add_template_candidate will fail below. */
ics = implicit_conversion (totype, totype, 0, convflags); ics = implicit_conversion (totype, totype, 0, convflags);
if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics)) if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
...@@ -6273,7 +6307,8 @@ joust (cand1, cand2) ...@@ -6273,7 +6307,8 @@ joust (cand1, cand2)
return -1; return -1;
else if (cand1->template && cand2->template) else if (cand1->template && cand2->template)
winner = more_specialized winner = more_specialized
(TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template)); (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
NULL_TREE);
/* or, if not that, /* or, if not that,
the context is an initialization by user-defined conversion (see the context is an initialization by user-defined conversion (see
......
...@@ -4504,6 +4504,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4504,6 +4504,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
{ {
tree spec_args; tree spec_args;
tree fn; tree fn;
int pending_specialization;
if (uses_template_parms (t)) if (uses_template_parms (t))
/* If t is a template class, and x is a specialization, then x /* If t is a template class, and x is a specialization, then x
...@@ -4527,11 +4528,12 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4527,11 +4528,12 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
else else
spec_args = DECL_TI_ARGS (fn); spec_args = DECL_TI_ARGS (fn);
pending_specialization
= TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn));
check_explicit_specialization check_explicit_specialization
(lookup_template_function (DECL_NAME (fn), spec_args), (lookup_template_function (DECL_NAME (fn), spec_args),
fn, 0, 1 | (8 * (int) TREE_CHAIN (DECL_TEMPLATE_INFO (fn)))); fn, 0, 1 | (8 * pending_specialization));
TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)) = 0;
TREE_CHAIN (DECL_TEMPLATE_INFO (fn)) = NULL_TREE;
/* Now, the assembler name will be correct for fn, so we /* Now, the assembler name will be correct for fn, so we
make its RTL. */ make its RTL. */
...@@ -5423,6 +5425,16 @@ instantiate_type (lhstype, rhs, complain) ...@@ -5423,6 +5425,16 @@ instantiate_type (lhstype, rhs, complain)
case ERROR_MARK: case ERROR_MARK:
return error_mark_node; return error_mark_node;
case FUNCTION_DECL:
if (!comptypes (lhstype, TREE_TYPE (rhs), 1))
{
if (complain)
cp_error ("%D is not of type %T", rhs, lhstype);
return error_mark_node;
}
else
return rhs;
default: default:
my_friendly_abort (185); my_friendly_abort (185);
return error_mark_node; return error_mark_node;
...@@ -5505,21 +5517,3 @@ build_self_reference () ...@@ -5505,21 +5517,3 @@ build_self_reference ()
pushdecl_class_level (value); pushdecl_class_level (value);
return value; return value;
} }
/* Returns non-zero iff the TYPE is a local class; i.e., if it is
declared in a function context, or within a local class. */
int
is_local_class (type)
tree type;
{
if (type == NULL_TREE || TYPE_CONTEXT (type) == NULL_TREE)
return 0;
if (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL)
return 1;
return is_local_class (TYPE_CONTEXT (type));
}
...@@ -1098,6 +1098,10 @@ struct lang_decl ...@@ -1098,6 +1098,10 @@ struct lang_decl
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE)) #define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
#define TI_USES_TEMPLATE_PARMS(NODE) TREE_LANG_FLAG_0 (NODE) #define TI_USES_TEMPLATE_PARMS(NODE) TREE_LANG_FLAG_0 (NODE)
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
that the template is a specialization of a member template, but
that we don't yet know which one. */
#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE)) #define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE)) #define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE)) #define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
...@@ -1992,7 +1996,6 @@ extern void maybe_push_cache_obstack PROTO((void)); ...@@ -1992,7 +1996,6 @@ extern void maybe_push_cache_obstack PROTO((void));
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *)); extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
extern tree build_self_reference PROTO((void)); extern tree build_self_reference PROTO((void));
extern void warn_hidden PROTO((tree)); extern void warn_hidden PROTO((tree));
extern int is_local_class PROTO((tree));
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree)); extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
...@@ -2009,7 +2012,6 @@ extern tree build_expr_type_conversion PROTO((int, tree, int)); ...@@ -2009,7 +2012,6 @@ extern tree build_expr_type_conversion PROTO((int, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *)); extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern tree type_promotes_to PROTO((tree)); extern tree type_promotes_to PROTO((tree));
extern tree perform_qualification_conversions PROTO((tree, tree)); extern tree perform_qualification_conversions PROTO((tree, tree));
extern tree perform_array_to_pointer_conversion PROTO((tree));
/* decl.c */ /* decl.c */
/* resume_binding_level */ /* resume_binding_level */
...@@ -2325,6 +2327,7 @@ extern tree tsubst_copy PROTO ((tree, tree, int, tree)); ...@@ -2325,6 +2327,7 @@ extern tree tsubst_copy PROTO ((tree, tree, int, tree));
extern tree tsubst_chain PROTO((tree, tree)); extern tree tsubst_chain PROTO((tree, tree));
extern void begin_member_template_processing PROTO((tree)); extern void begin_member_template_processing PROTO((tree));
extern void end_member_template_processing PROTO((void)); extern void end_member_template_processing PROTO((void));
extern tree finish_member_template_decl PROTO((tree, tree));
extern void begin_template_parm_list PROTO((void)); extern void begin_template_parm_list PROTO((void));
extern void begin_specialization PROTO((void)); extern void begin_specialization PROTO((void));
extern void reset_specialization PROTO((void)); extern void reset_specialization PROTO((void));
...@@ -2332,7 +2335,7 @@ extern void end_specialization PROTO((void)); ...@@ -2332,7 +2335,7 @@ extern void end_specialization PROTO((void));
extern void begin_explicit_instantiation PROTO((void)); extern void begin_explicit_instantiation PROTO((void));
extern void end_explicit_instantiation PROTO((void)); extern void end_explicit_instantiation PROTO((void));
extern tree determine_specialization PROTO((tree, tree, tree *, int, int)); extern tree determine_specialization PROTO((tree, tree, tree *, int, int));
extern int check_explicit_specialization PROTO((tree, tree, int, int)); extern tree check_explicit_specialization PROTO((tree, tree, int, int));
extern tree process_template_parm PROTO((tree, tree)); extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree)); extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((void)); extern void end_template_decl PROTO((void));
...@@ -2348,21 +2351,21 @@ extern int fn_type_unification PROTO((tree, tree, tree, tree, t ...@@ -2348,21 +2351,21 @@ extern int fn_type_unification PROTO((tree, tree, tree, tree, t
extern int type_unification PROTO((tree, tree *, tree, tree, tree, int *, int, int)); extern int type_unification PROTO((tree, tree *, tree, tree, tree, int *, int, int));
struct tinst_level *tinst_for_decl PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int)); extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree)); extern int more_specialized PROTO((tree, tree, tree));
extern void mark_class_instantiated PROTO((tree, int)); extern void mark_class_instantiated PROTO((tree, int));
extern void do_decl_instantiation PROTO((tree, tree, tree)); extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree)); extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree)); extern tree instantiate_decl PROTO((tree));
extern tree lookup_nested_type_by_name PROTO((tree, tree)); extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void)); extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree)); extern tree get_bindings PROTO((tree, tree, tree));
/* CONT ... */ /* CONT ... */
extern void add_tree PROTO((tree)); extern void add_tree PROTO((tree));
extern void begin_tree PROTO((void)); extern void begin_tree PROTO((void));
extern void end_tree PROTO((void)); extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree)); extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void)); extern void pop_tinst_level PROTO((void));
extern tree most_specialized PROTO((tree, tree)); extern tree most_specialized PROTO((tree, tree, tree));
extern tree most_specialized_class PROTO((tree, tree)); extern tree most_specialized_class PROTO((tree, tree));
extern int more_specialized_class PROTO((tree, tree)); extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void)); extern void do_pushlevel PROTO((void));
......
...@@ -1689,127 +1689,17 @@ type_promotes_to (type) ...@@ -1689,127 +1689,17 @@ type_promotes_to (type)
closely. Although they are used only in pt.c at the moment, they closely. Although they are used only in pt.c at the moment, they
should presumably be used everywhere in the future. */ should presumably be used everywhere in the future. */
/* Attempt to perform qualification conversions on EXPR to convert it
to TYPE. Return the resulting expression, or error_mark_node if
the conversion was impossible. */
tree tree
perform_qualification_conversions (type, expr) perform_qualification_conversions (type, expr)
tree type; tree type;
tree expr; tree expr;
{ {
tree expr_type = TREE_TYPE (expr); if (comp_ptr_ttypes (type, TREE_TYPE(expr)))
tree t1; return build1 (NOP_EXPR, type, expr);
tree t2; else
int j; return error_mark_node;
int all_have_const = 1;
if (comptypes (type, expr_type, 1))
/* The two types are already the same, so there is nothing to do. */
return expr;
j = 0;
t1 = expr_type;
t2 = type;
while (1)
{
if (TREE_CODE (type) != TREE_CODE (expr_type))
return error_mark_node;
if (j > 0
&& TREE_CODE (type) == POINTER_TYPE)
{
if (TYPE_READONLY (t1) > TYPE_READONLY (t2)
|| TYPE_VOLATILE (t1) > TYPE_VOLATILE (t2))
/* For every j>0, if const is in cv1,j the const is in
cv2,j, and similarly for volatile. */
return error_mark_node;
}
if (!all_have_const
&& (TYPE_READONLY (t1) != TYPE_READONLY (t2)
|| TYPE_READONLY (t1) != TYPE_READONLY (t2)))
/* If the cv1,j and cv2,j are different, then const is in every
cv2,k for 0<k<j. */
return error_mark_node;
if (j > 0 && !TYPE_READONLY (t2))
all_have_const = 0;
if (TREE_CODE (type) != POINTER_TYPE)
{
if (j == 0)
/* The two things to be converted weren't even pointer
types. */
return error_mark_node;
if (TYPE_PTRMEMFUNC_P (type))
{
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
}
if (comptypes (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2), 1))
return build1 (NOP_EXPR, type, expr);
else
/* The pointers were not similar. */
return error_mark_node;
}
if (TYPE_PTRMEM_P (type)
&& !comptypes (TYPE_OFFSET_BASETYPE (TREE_TYPE (t1)),
TYPE_OFFSET_BASETYPE (TREE_TYPE (t2)),
1))
/* One type is X::* and the other is Y::*. */
return error_mark_node;
if (TYPE_PTRMEM_P (type))
{
t1 = TREE_TYPE (TREE_TYPE (t1));
t2 = TREE_TYPE (TREE_TYPE (t2));
}
else
{
t1 = TREE_TYPE (t1);
t2 = TREE_TYPE (t2);
}
}
}
/* Perform array-to-pointer conversion on EXPR, if appropriate.
Return the converted expression, or EXPR if no
conversion was performed, or error_mark_node if the conversion was
attempted, but failed. (For example, if an attempt is made to take
the address of a non-addressable object.) */
tree
perform_array_to_pointer_conversion (expr)
tree expr;
{
tree result = expr;
if (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE)
{
tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
/* This section is copied from decay_conversion. */
if (TREE_CODE (expr) == VAR_DECL)
{
/* ??? This is not really quite correct
in that the type of the operand of ADDR_EXPR
is not the target type of the type of the ADDR_EXPR itself.
Question is, can this lossage be avoided? */
result = build1 (ADDR_EXPR, type, expr);
if (mark_addressable (expr) == 0)
return error_mark_node;
TREE_CONSTANT (result) = staticp (expr);
TREE_SIDE_EFFECTS (result) = 0; /* Default would be, same as
EXPR. */
}
else
/* This way is better for a COMPONENT_REF since it can
simplify the offset for a component. */
result = build_unary_op (ADDR_EXPR, expr, 1);
}
return result;
} }
...@@ -1835,6 +1835,8 @@ struct saved_scope { ...@@ -1835,6 +1835,8 @@ struct saved_scope {
tree template_parms; tree template_parms;
HOST_WIDE_INT processing_template_decl; HOST_WIDE_INT processing_template_decl;
tree previous_class_type, previous_class_values; tree previous_class_type, previous_class_values;
int processing_specialization;
int processing_explicit_instantiation;
}; };
static struct saved_scope *current_saved_scope; static struct saved_scope *current_saved_scope;
...@@ -1933,6 +1935,8 @@ maybe_push_to_top_level (pseudo) ...@@ -1933,6 +1935,8 @@ maybe_push_to_top_level (pseudo)
s->processing_template_decl = processing_template_decl; s->processing_template_decl = processing_template_decl;
s->previous_class_type = previous_class_type; s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values; s->previous_class_values = previous_class_values;
s->processing_specialization = processing_specialization;
s->processing_explicit_instantiation = processing_explicit_instantiation;
current_class_name = current_class_type = NULL_TREE; current_class_name = current_class_type = NULL_TREE;
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
...@@ -1945,6 +1949,8 @@ maybe_push_to_top_level (pseudo) ...@@ -1945,6 +1949,8 @@ maybe_push_to_top_level (pseudo)
named_labels = NULL_TREE; named_labels = NULL_TREE;
minimal_parse_mode = 0; minimal_parse_mode = 0;
previous_class_type = previous_class_values = NULL_TREE; previous_class_type = previous_class_values = NULL_TREE;
processing_specialization = 0;
processing_explicit_instantiation = 0;
if (!pseudo) if (!pseudo)
{ {
current_template_parms = NULL_TREE; current_template_parms = NULL_TREE;
...@@ -2011,6 +2017,8 @@ pop_from_top_level () ...@@ -2011,6 +2017,8 @@ pop_from_top_level ()
processing_template_decl = s->processing_template_decl; processing_template_decl = s->processing_template_decl;
previous_class_type = s->previous_class_type; previous_class_type = s->previous_class_type;
previous_class_values = s->previous_class_values; previous_class_values = s->previous_class_values;
processing_specialization = s->processing_specialization;
processing_explicit_instantiation = s->processing_explicit_instantiation;
free (s); free (s);
...@@ -6144,8 +6152,7 @@ start_decl (declarator, declspecs, initialized) ...@@ -6144,8 +6152,7 @@ start_decl (declarator, declspecs, initialized)
/* The declaration of template specializations does not affect /* The declaration of template specializations does not affect
the functions available for overload resolution, so we do not the functions available for overload resolution, so we do not
call pushdecl. */ call pushdecl. */
|| (!flag_guiding_decls || (TREE_CODE (decl) == FUNCTION_DECL
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (decl))) && DECL_TEMPLATE_SPECIALIZATION (decl)))
tem = decl; tem = decl;
else else
...@@ -6487,6 +6494,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6487,6 +6494,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl)) if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
{ {
tree stmt = DECL_VINDEX (decl); tree stmt = DECL_VINDEX (decl);
/* If the decl is declaring a member of a local class (in a
template function), there will be no associated stmt. */
if (stmt != NULL_TREE) if (stmt != NULL_TREE)
{ {
DECL_VINDEX (decl) = NULL_TREE; DECL_VINDEX (decl) = NULL_TREE;
...@@ -6778,11 +6787,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6778,11 +6787,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|| TREE_CODE (decl) == RESULT_DECL) || TREE_CODE (decl) == RESULT_DECL)
{ {
/* ??? FIXME: What about nested classes? */ /* ??? FIXME: What about nested classes? */
/* We check for FUNCTION_DECL here so that member functions of int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
local classes, which will have internal linkage, are not
given bizarre names by make_decl_rtl. */
int toplev = toplevel_bindings_p () || pseudo_global_level_p ()
|| TREE_CODE (decl) == FUNCTION_DECL;
int was_temp int was_temp
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type) = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ()); && allocation_temporary_p ());
...@@ -7491,10 +7496,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, ...@@ -7491,10 +7496,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
grokclassfn (ctype, declarator, decl, flags, quals); grokclassfn (ctype, declarator, decl, flags, quals);
check_explicit_specialization (orig_declarator, decl, decl = check_explicit_specialization (orig_declarator, decl,
template_count, template_count,
funcdef_flag ? 2 : funcdef_flag ? 2 :
(friendp ? 3 : 0)); (friendp ? 3 : 0));
if (check) if (check)
{ {
...@@ -7538,10 +7543,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, ...@@ -7538,10 +7543,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype != NULL_TREE) if (ctype != NULL_TREE)
grokclassfn (ctype, cname, decl, flags, quals); grokclassfn (ctype, cname, decl, flags, quals);
check_explicit_specialization (orig_declarator, decl, decl = check_explicit_specialization (orig_declarator, decl,
template_count, template_count,
funcdef_flag ? 2 : funcdef_flag ? 2 :
(friendp ? 3 : 0)); (friendp ? 3 : 0));
if (ctype != NULL_TREE && check) if (ctype != NULL_TREE && check)
{ {
...@@ -9666,6 +9671,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9666,6 +9671,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else if (TREE_CODE (type) == FUNCTION_TYPE) else if (TREE_CODE (type) == FUNCTION_TYPE)
{ {
int publicp = 0; int publicp = 0;
tree function_context;
/* We catch the others as conflicts with the builtin /* We catch the others as conflicts with the builtin
typedefs. */ typedefs. */
...@@ -9715,7 +9721,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9715,7 +9721,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
} }
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (! friendp || ! staticp) && !is_local_class (ctype); function_context = (ctype != NULL_TREE) ?
hack_decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
publicp = (! friendp || ! staticp)
&& function_context == NULL_TREE;
decl = grokfndecl (ctype, type, decl = grokfndecl (ctype, type,
TREE_CODE (declarator) != TEMPLATE_ID_EXPR TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname, ? declarator : dname,
...@@ -9725,6 +9734,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9725,6 +9734,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
funcdef_flag, template_count); funcdef_flag, template_count);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
if (function_context != NULL_TREE
&& DECL_THIS_INLINE (function_context)
&& TREE_PUBLIC (function_context))
/* We just declared a member of a local class in an
extern inline function. Give such an entity comdat
linkage. */
{
comdat_linkage (decl);
DECL_INTERFACE_KNOWN (decl) = 1;
}
#if 0 #if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */ /* This clobbers the attrs stored in `decl' from `attrlist'. */
/* The decl and setting of decl_machine_attr is also turned off. */ /* The decl and setting of decl_machine_attr is also turned off. */
...@@ -12494,7 +12513,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -12494,7 +12513,7 @@ finish_function (lineno, call_poplevel, nested)
can_reach_end = 0; can_reach_end = 0;
if (DECL_CONTEXT (fndecl) != NULL_TREE if (DECL_CONTEXT (fndecl) != NULL_TREE
&& is_local_class (DECL_CONTEXT (fndecl))) && hack_decl_function_context (fndecl))
/* Trick rest_of_compilation into not deferring output of this /* Trick rest_of_compilation into not deferring output of this
function, even if it is inline, since the rtl_obstack for function, even if it is inline, since the rtl_obstack for
this function is the function_obstack of the enclosing this function is the function_obstack of the enclosing
......
...@@ -2940,7 +2940,7 @@ finish_file () ...@@ -2940,7 +2940,7 @@ finish_file ()
continue; continue;
fn = TREE_PURPOSE (fnname); fn = TREE_PURPOSE (fnname);
args = get_bindings (fn, decl); args = get_bindings (fn, decl, NULL_TREE);
fn = instantiate_template (fn, args); fn = instantiate_template (fn, args);
instantiate_decl (fn); instantiate_decl (fn);
} }
...@@ -3605,21 +3605,10 @@ build_expr_from_tree (t) ...@@ -3605,21 +3605,10 @@ build_expr_from_tree (t)
} }
case COMPONENT_REF: case COMPONENT_REF:
{ return build_x_component_ref
tree object = build_expr_from_tree (TREE_OPERAND (t, 0)); (build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_OPERAND (t, 1), NULL_TREE, 1);
if (object != NULL_TREE
&& TREE_CODE (object) == TEMPLATE_DECL)
{
cp_error ("invalid use of %D", object);
object = error_mark_node;
}
return build_x_component_ref
(object,
TREE_OPERAND (t, 1), NULL_TREE, 1);
}
case THROW_EXPR: case THROW_EXPR:
return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0))); return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
......
...@@ -1661,7 +1661,7 @@ fndecl_as_string (fndecl, print_ret_type_p) ...@@ -1661,7 +1661,7 @@ fndecl_as_string (fndecl, print_ret_type_p)
return decl_as_string (fndecl, print_ret_type_p); return decl_as_string (fndecl, print_ret_type_p);
} }
/* Same, but handtype a _TYPE. /* Same, but handle a _TYPE.
Called from convert_to_reference, mangle_class_name_for_template, Called from convert_to_reference, mangle_class_name_for_template,
build_unary_op, and GNU_xref_decl. */ build_unary_op, and GNU_xref_decl. */
......
...@@ -1998,22 +1998,10 @@ cons_up_default_function (type, full_name, kind) ...@@ -1998,22 +1998,10 @@ cons_up_default_function (type, full_name, kind)
{ {
tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE); tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
int saved_processing_specialization;
int saved_processing_explicit_instantiation;
if (retref) if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator); declarator = build_parse_node (ADDR_EXPR, declarator);
/* The following is in case we're generating the default
implementation in the midst of handling a specialization. */
saved_processing_specialization = processing_specialization;
saved_processing_explicit_instantiation =
processing_explicit_instantiation;
processing_specialization = 0;
processing_explicit_instantiation = 0;
fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
processing_specialization = saved_processing_specialization;
processing_explicit_instantiation =
saved_processing_explicit_instantiation;
} }
if (fn == void_type_node) if (fn == void_type_node)
......
...@@ -758,7 +758,10 @@ build_overload_identifier (name) ...@@ -758,7 +758,10 @@ build_overload_identifier (name)
if (TREE_CODE (name) == TYPE_DECL if (TREE_CODE (name) == TYPE_DECL
&& IS_AGGR_TYPE (TREE_TYPE (name)) && IS_AGGR_TYPE (TREE_TYPE (name))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)) && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name))
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)))) && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)))
|| (TREE_CODE (DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE
(TREE_TYPE (name))))
== FUNCTION_DECL)))
{ {
tree template, parmlist, arglist, tname; tree template, parmlist, arglist, tname;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -78,7 +78,6 @@ static int processing_template_arg; ...@@ -78,7 +78,6 @@ static int processing_template_arg;
extern int arg_looking_for_template; extern int arg_looking_for_template;
static tree empty_parms PROTO((void)); static tree empty_parms PROTO((void));
static tree finish_member_template_decl PROTO((tree, tree));
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */ /* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec; int have_extern_spec;
...@@ -101,31 +100,6 @@ empty_parms () ...@@ -101,31 +100,6 @@ empty_parms ()
return parms; return parms;
} }
static tree
finish_member_template_decl (template_arguments, decl)
tree template_arguments;
tree decl;
{
if (template_arguments)
end_template_decl();
else
end_specialization();
if (decl && DECL_TEMPLATE_INFO (decl) &&
!DECL_TEMPLATE_SPECIALIZATION (decl))
{
check_member_template (DECL_TI_TEMPLATE (decl));
return DECL_TI_TEMPLATE (decl);
}
if (decl)
return decl;
cp_error ("invalid member template declaration");
return NULL_TREE;
}
%} %}
%start program %start program
......
...@@ -1316,16 +1316,8 @@ int ...@@ -1316,16 +1316,8 @@ int
really_overloaded_fn (x) really_overloaded_fn (x)
tree x; tree x;
{ {
if (TREE_CODE (x) == TEMPLATE_ID_EXPR return TREE_CODE (x) != FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (x)) && is_overloaded_fn (x);
return 1;
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (TREE_VALUE (x))))
return 1;
return 0;
} }
tree tree
......
...@@ -1823,6 +1823,11 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1823,6 +1823,11 @@ build_component_ref (datum, component, basetype_path, protect)
build_component_ref (TREE_OPERAND (datum, 2), component, build_component_ref (TREE_OPERAND (datum, 2), component,
basetype_path, protect)); basetype_path, protect));
case TEMPLATE_DECL:
cp_error ("invalid use of %D", datum);
datum = error_mark_node;
break;
default: default:
break; break;
} }
......
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