Commit 75650646 by Mark Mitchell Committed by Jason Merrill

decl.c (start_decl): Don't allow duplicate definitions of static data members.

	* decl.c (start_decl): Don't allow duplicate definitions of static
	data members.
	* call.c (build_user_type_conversion_1): Handle user-defined
	template conversion operators correctly.
	* decl2.c (build_expr_from_tree): Issue an error message if the
	object in a COMPONENT_REF is a TEMPLATE_DECL.
	* typeck.c (incomplete_type_error): Handle TEMPLATE_TYPE_PARMs.
	* class.c (is_local_class): New function.
	* cp-tree.h (is_local_class): Declare it.
	(last_tree): Likewise.
	(begin_tree): Likewise.
	(end_tree): Likewise.
	(lookup_template_class): Change prototype.
	* decl.c (cp_finish_decl): Check for NULL where necesary.
	Consider FUNCTION_DECLS to declare objects with top-level binding,
	when calling make_decl_rtl.
	(grokdeclarator): Give members of local classes internal linkage.
	(start_function): Remove declaration of last_tree.
	(finish_function): Set flag_keep_inline_functions around call to
	rest_of_compilation if we are processing a member function in a
	local class.
	(start_method): Call push_template_decl for member functions of
	local classes in template functions.
	* decl2.c (import_export_decl): Don't give external linkage to
	instantiations of templates with internal linkage.
	* parse.y (last_tree): Remove declaration.
	(template_type): Pass extra parameter to lookup_template_class.
	(self_template_type): Likewise.
	(structsp): Move call to reset_specialization into left_curly.
	(left_curly): Call reset_specialization, and begin_tree.
	* pt.c (saved_trees): New variable.
	(mangle_class_name_for_template): Change prototype.  Use
	additional function context to name local classes in templates
	correctly.
	(classtype_mangled_name): Pass the context.
	(push_template_decl): Handle local classes and templates, and
	member functions for such classes.
	(convert_nontype_parameter): Fix handling of pointer-to-member
	constants.
	(lookup_template_class): Handle local classes in templates.
	(tsubst): Likewise.  Don't assume that template instantiations
	have external linkage; pay attention to the template declaration.
	(mark_decl_instantiated): Likewise.
	(begin_tree): New function.
	(end_tree): Likewise.
	* decl.c (xref_basetypes): Don't call complete_type for basetypes
	that involve template parameters; that can lead to infinite
	recursion unnecessarily.
	* pt.c (register_specialization): Do not register specializations
	that aren't ready to be registered yet.
	(check_explicit_specialization): Handle explicit specialization of
	constructors and destructors.
	(build_template_decl): New function.
	(push_template_delc): Handle out-of-class specializations of
	member templates.
        * pt.c (check_explicit_specialization): Set up the template
        information before registering the specialization.
        (coerce_template_parms): Fix thinko.
        (tsubst): Handle specializations of member templates correctly.
	* class.c (finish_struct_methods): Remove calls to
	check_explicit_specialization from here.
	(finish_struct): And insert them here.
	* cp-tree.h (perform_qualification_conversions): New function.
	(perform_array_to_pointer_conversion): Likewise.
	(begin_explicit_instantiation): Likewise.
	(end_explicit_instantiation): Likewise.
	(determine_specialization): Renamed from
	determine_explicit_specialization.
	(comp_template_parms): New function.
	(processing_explicit_instantiation): New variable.
	* cvt.c (perform_qualification_conversions): New function.
	(perform_array_to_pointer_conversion): Likewise.
	* decl.c (duplicate_decls): Don't consider template functions
	alike unless they have the same parameters.  Refine handling of
	instantiation/specialization mismatches.
	(start_decl): Don't call pushdecl for template specializations,
	since they don't affect overloading.
	(start_function): Likewise
	(grokfndecl): Call check_explicit_specialization a little later.
	Don't call duplicate_decls for memberm template specializations.
	(grokdeclarator): Don't update template_count for classes that are
	themselves specializations.  Remove use of `2' as parameter to
	grokfndecl since that value isn't used.
	* lex.c (cons_up_default_function): Save and restore
	processing_explicit_instantiation around calls to grokfield.
	* parse.y (finish_member_template_decl): New function.
	(component_decl_1): Use it.
	(fn.def2): Likewise.
	(template_arg_list_opt): New nonterminal.
	(template_type): Use it.
	(self_template_type): Likewise.
	(template_id): Likewise.
	(object_template_id): Likewise.
	(notype_template_declarator): Likwise.
	(begin_explicit_instantiation): Likewise.
	(end_explicit_instantiation): Likewise.
	(explicit_instantiation): Use them.
	* pt.c (coerce_template_parms): Add parameters.
	(processing_explicit_instantiation): New variable.
	(convert_nontype_parameter): New function.
	(determine_overloaded_function): Likewise.
	(begin_explicit_instantiation): Likewise.
	(end_explicit_instantiation): Likewise.
	(retrieve_specialization): Likewise.
	(register_specialization): Likewise.
	(processing_explicit_specialization): Removed.
	(determine_specialization): Handle specializations of member
	functions of template class instantiations.
	(check_explicit_specialization): Refine to conform to standard.
	(comp_template_parms): New function.
	(coerce_template_parms): Call convert_nontype_parameter.
	(tsubst): Refine handling of member templates.  Use
	register_specialization.
	(instantiate_template): Use retrieve_specialization.
	(do_decl_instantiation): Likewise.
	(instantiate_decl): Likewise.
	(type_unification): Improve handling of explict template
	arguments.
	* tree.c (mapcar): Return error_mark_node, rather than aborting,
	on VAR_DECLS, FUNCTION_DECLS, and CONST_DECLS.
	* typeck.c (build_unary_op): Call determine_specialization, rather
	than determine_explicit_specialization.

From-SVN: r17426
parent 685885b7
Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* decl.c (start_decl): Don't allow duplicate definitions of static
data members.
* call.c (build_user_type_conversion_1): Handle user-defined
template conversion operators correctly.
* decl2.c (build_expr_from_tree): Issue an error message if the
object in a COMPONENT_REF is a TEMPLATE_DECL.
* typeck.c (incomplete_type_error): Handle TEMPLATE_TYPE_PARMs.
* class.c (is_local_class): New function.
* cp-tree.h (is_local_class): Declare it.
(last_tree): Likewise.
(begin_tree): Likewise.
(end_tree): Likewise.
(lookup_template_class): Change prototype.
* decl.c (cp_finish_decl): Check for NULL where necesary.
Consider FUNCTION_DECLS to declare objects with top-level binding,
when calling make_decl_rtl.
(grokdeclarator): Give members of local classes internal linkage.
(start_function): Remove declaration of last_tree.
(finish_function): Set flag_keep_inline_functions around call to
rest_of_compilation if we are processing a member function in a
local class.
(start_method): Call push_template_decl for member functions of
local classes in template functions.
* decl2.c (import_export_decl): Don't give external linkage to
instantiations of templates with internal linkage.
* parse.y (last_tree): Remove declaration.
(template_type): Pass extra parameter to lookup_template_class.
(self_template_type): Likewise.
(structsp): Move call to reset_specialization into left_curly.
(left_curly): Call reset_specialization, and begin_tree.
* pt.c (saved_trees): New variable.
(mangle_class_name_for_template): Change prototype. Use
additional function context to name local classes in templates
correctly.
(classtype_mangled_name): Pass the context.
(push_template_decl): Handle local classes and templates, and
member functions for such classes.
(convert_nontype_parameter): Fix handling of pointer-to-member
constants.
(lookup_template_class): Handle local classes in templates.
(tsubst): Likewise. Don't assume that template instantiations
have external linkage; pay attention to the template declaration.
(mark_decl_instantiated): Likewise.
(begin_tree): New function.
(end_tree): Likewise.
* decl.c (xref_basetypes): Don't call complete_type for basetypes
that involve template parameters; that can lead to infinite
recursion unnecessarily.
* pt.c (register_specialization): Do not register specializations
that aren't ready to be registered yet.
(check_explicit_specialization): Handle explicit specialization of
constructors and destructors.
(build_template_decl): New function.
(push_template_delc): Handle out-of-class specializations of
member templates.
* pt.c (check_explicit_specialization): Set up the template
information before registering the specialization.
(coerce_template_parms): Fix thinko.
(tsubst): Handle specializations of member templates correctly.
* class.c (finish_struct_methods): Remove calls to
check_explicit_specialization from here.
(finish_struct): And insert them here.
* cp-tree.h (perform_qualification_conversions): New function.
(perform_array_to_pointer_conversion): Likewise.
(begin_explicit_instantiation): Likewise.
(end_explicit_instantiation): Likewise.
(determine_specialization): Renamed from
determine_explicit_specialization.
(comp_template_parms): New function.
(processing_explicit_instantiation): New variable.
* cvt.c (perform_qualification_conversions): New function.
(perform_array_to_pointer_conversion): Likewise.
* decl.c (duplicate_decls): Don't consider template functions
alike unless they have the same parameters. Refine handling of
instantiation/specialization mismatches.
(start_decl): Don't call pushdecl for template specializations,
since they don't affect overloading.
(start_function): Likewise
(grokfndecl): Call check_explicit_specialization a little later.
Don't call duplicate_decls for memberm template specializations.
(grokdeclarator): Don't update template_count for classes that are
themselves specializations. Remove use of `2' as parameter to
grokfndecl since that value isn't used.
* lex.c (cons_up_default_function): Save and restore
processing_explicit_instantiation around calls to grokfield.
* parse.y (finish_member_template_decl): New function.
(component_decl_1): Use it.
(fn.def2): Likewise.
(template_arg_list_opt): New nonterminal.
(template_type): Use it.
(self_template_type): Likewise.
(template_id): Likewise.
(object_template_id): Likewise.
(notype_template_declarator): Likwise.
(begin_explicit_instantiation): Likewise.
(end_explicit_instantiation): Likewise.
(explicit_instantiation): Use them.
* pt.c (coerce_template_parms): Add parameters.
(processing_explicit_instantiation): New variable.
(convert_nontype_parameter): New function.
(determine_overloaded_function): Likewise.
(begin_explicit_instantiation): Likewise.
(end_explicit_instantiation): Likewise.
(retrieve_specialization): Likewise.
(register_specialization): Likewise.
(processing_explicit_specialization): Removed.
(determine_specialization): Handle specializations of member
functions of template class instantiations.
(check_explicit_specialization): Refine to conform to standard.
(comp_template_parms): New function.
(coerce_template_parms): Call convert_nontype_parameter.
(tsubst): Refine handling of member templates. Use
register_specialization.
(instantiate_template): Use retrieve_specialization.
(do_decl_instantiation): Likewise.
(instantiate_decl): Likewise.
(type_unification): Improve handling of explict template
arguments.
* tree.c (mapcar): Return error_mark_node, rather than aborting,
on VAR_DECLS, FUNCTION_DECLS, and CONST_DECLS.
* typeck.c (build_unary_op): Call determine_specialization, rather
than determine_explicit_specialization.
Mon Jan 19 13:18:51 1998 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (build_up_reference): A TARGET_EXPR has side effects.
......
......@@ -4356,8 +4356,11 @@ build_user_type_conversion_1 (totype, expr, flags)
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags);
if (TREE_CODE (fn) != TEMPLATE_DECL)
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags);
else
ics = implicit_conversion (totype, totype, 0, convflags);
if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
/* ignore the near match. */;
......
......@@ -2107,53 +2107,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
obstack_free (current_obstack, baselink_vec);
}
/* Now, figure out what any member template specializations were
specializing. */
for (i = 0; i < TREE_VEC_LENGTH (method_vec); ++i)
{
tree fn;
for (fn = TREE_VEC_ELT (method_vec, i);
fn != NULL_TREE;
fn = DECL_CHAIN (fn))
if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
tree f;
tree spec_args;
/* If there is a template, and t uses template parms, we
are dealing with a specialization of a member
template in a template class, and we must grab the
template, rather than the function. */
if (DECL_TI_TEMPLATE (fn) && uses_template_parms (t))
f = DECL_TI_TEMPLATE (fn);
else
f = fn;
/* We want the specialization arguments, which will be the
innermost ones. */
if (DECL_TI_ARGS (f)
&& TREE_CODE (DECL_TI_ARGS (f)) == TREE_VEC)
spec_args
= TREE_VEC_ELT (DECL_TI_ARGS (f), 0);
else
spec_args = DECL_TI_ARGS (f);
check_explicit_specialization
(lookup_template_function (DECL_NAME (f), spec_args),
f, 0, 1);
/* Now, the assembler name will be correct for fn, so we
make its RTL. */
DECL_RTL (f) = 0;
make_decl_rtl (f, NULL_PTR, 1);
if (f != fn)
{
DECL_RTL (fn) = 0;
make_decl_rtl (fn, NULL_PTR, 1);
}
}
}
return method_vec;
}
......@@ -4350,10 +4303,13 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
{
tree fields = NULL_TREE;
tree *tail = &TYPE_METHODS (t);
tree specializations = NULL_TREE;
tree *specialization_tail = &specializations;
tree name = TYPE_NAME (t);
tree x, last_x = NULL_TREE;
tree access;
tree dummy = NULL_TREE;
tree next_x = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
......@@ -4402,8 +4358,10 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
access = access_private_node;
}
for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
for (x = TREE_VALUE (list_of_fieldlists); x; x = next_x)
{
next_x = TREE_CHAIN (x);
TREE_PRIVATE (x) = access == access_private_node;
TREE_PROTECTED (x) = access == access_protected_node;
......@@ -4441,8 +4399,23 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|| DECL_FUNCTION_TEMPLATE_P (x))
{
DECL_CLASS_CONTEXT (x) = t;
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
TREE_CHAIN (last_x) = next_x;
if (DECL_TEMPLATE_SPECIALIZATION (x))
/* We don't enter the specialization into the class
method vector since specializations don't affect
overloading. Instead we keep track of the
specializations, and process them after the method
vector is complete. */
{
*specialization_tail = x;
specialization_tail = &TREE_CHAIN (x);
TREE_CHAIN (x) = NULL_TREE;
continue;
}
/* Link x onto end of TYPE_METHODS. */
*tail = x;
tail = &TREE_CHAIN (x);
......@@ -4525,6 +4498,53 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
TYPE_BEING_DEFINED (t) = 0;
/* Now, figure out what any member template specializations were
specializing. */
for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
{
tree spec_args;
tree fn;
if (uses_template_parms (t))
/* If t is a template class, and x is a specialization, then x
is itself really a template. Due to the vagaries of the
parser, however, we will have a handle to a function
declaration, rather than the template declaration, at this
point. */
{
my_friendly_assert (DECL_TEMPLATE_INFO (x) != NULL_TREE, 0);
my_friendly_assert (DECL_TI_TEMPLATE (x) != NULL_TREE, 0);
fn = DECL_TI_TEMPLATE (x);
}
else
fn = x;
/* We want the specialization arguments, which will be the
innermost ones. */
if (DECL_TI_ARGS (fn) && TREE_CODE (DECL_TI_ARGS (fn)) == TREE_VEC)
spec_args
= TREE_VEC_ELT (DECL_TI_ARGS (fn), 0);
else
spec_args = DECL_TI_ARGS (fn);
check_explicit_specialization
(lookup_template_function (DECL_NAME (fn), spec_args),
fn, 0, 1 | (8 * (int) TREE_CHAIN (DECL_TEMPLATE_INFO (fn))));
TREE_CHAIN (DECL_TEMPLATE_INFO (fn)) = NULL_TREE;
/* Now, the assembler name will be correct for fn, so we
make its RTL. */
DECL_RTL (fn) = 0;
make_decl_rtl (fn, NULL_PTR, 1);
if (x != fn)
{
DECL_RTL (x) = 0;
make_decl_rtl (x, NULL_PTR, 1);
}
}
if (current_class_type)
popclass (0);
else
......@@ -5484,3 +5504,21 @@ build_self_reference ()
pushdecl_class_level (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));
}
......@@ -1539,6 +1539,7 @@ extern tree null_node;
extern tree current_template_parms;
extern HOST_WIDE_INT processing_template_decl;
extern tree last_tree;
/* The template currently being instantiated, and where the instantiation
was triggered. */
......@@ -1983,6 +1984,7 @@ extern void maybe_push_cache_obstack PROTO((void));
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
extern tree build_self_reference PROTO((void));
extern void warn_hidden PROTO((tree));
extern int is_local_class PROTO((tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
......@@ -1998,6 +2000,8 @@ extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
extern tree build_expr_type_conversion PROTO((int, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern tree type_promotes_to PROTO((tree));
extern tree perform_qualification_conversions PROTO((tree, tree));
extern tree perform_array_to_pointer_conversion PROTO((tree));
/* decl.c */
/* resume_binding_level */
......@@ -2317,14 +2321,16 @@ extern void begin_template_parm_list PROTO((void));
extern void begin_specialization PROTO((void));
extern void reset_specialization PROTO((void));
extern void end_specialization PROTO((void));
extern tree determine_explicit_specialization PROTO((tree, tree, tree *, int, int));
extern int check_explicit_specialization PROTO((tree, tree, int, int));
extern void begin_explicit_instantiation PROTO((void));
extern void end_explicit_instantiation PROTO((void));
extern tree determine_specialization PROTO((tree, tree, tree *, int, int));
extern int check_explicit_specialization PROTO((tree, tree, int, int));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((void));
extern tree current_template_args PROTO((void));
extern void push_template_decl PROTO((tree));
extern tree lookup_template_class PROTO((tree, tree, tree));
extern tree lookup_template_class PROTO((tree, tree, tree, tree));
extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree));
......@@ -2344,6 +2350,8 @@ extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree));
/* CONT ... */
extern void add_tree PROTO((tree));
extern void begin_tree PROTO((void));
extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void));
extern tree most_specialized PROTO((tree, tree));
......@@ -2351,7 +2359,9 @@ extern tree most_specialized_class PROTO((tree, tree));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
extern int comp_template_parms PROTO((tree, tree));
extern int processing_specialization;
extern int processing_explicit_instantiation;
/* in repo.c */
extern void repo_template_used PROTO((tree));
......
......@@ -1682,3 +1682,134 @@ type_promotes_to (type)
return cp_build_type_variant (type, constp, volatilep);
}
/* The routines below this point are carefully written to conform to
the standard. They use the same terminology, and follow the rules
closely. Although they are used only in pt.c at the moment, they
should presumably be used everywhere in the future. */
tree
perform_qualification_conversions (type, expr)
tree type;
tree expr;
{
tree expr_type = TREE_TYPE (expr);
tree t1;
tree t2;
int j;
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;
}
......@@ -2785,7 +2785,11 @@ import_export_decl (decl)
if (DECL_IMPLICIT_INSTANTIATION (decl)
&& (flag_implicit_templates || DECL_THIS_INLINE (decl)))
{
if (TREE_CODE (decl) == FUNCTION_DECL)
if (!TREE_PUBLIC (decl))
/* Templates are allowed to have internal linkage. See
[basic.link]. */
;
else if (TREE_CODE (decl) == FUNCTION_DECL)
comdat_linkage (decl);
else
DECL_COMDAT (decl) = 1;
......@@ -3600,9 +3604,20 @@ build_expr_from_tree (t)
}
case COMPONENT_REF:
return build_x_component_ref
(build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_OPERAND (t, 1), NULL_TREE, 1);
{
tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
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:
return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
......
......@@ -952,71 +952,89 @@ dump_function_name (t)
else
dump_decl (name, 0);
if (DECL_LANG_SPECIFIC (t)
&& (DECL_TEMPLATE_SPECIALIZATION (t) || DECL_IMPLICIT_INSTANTIATION (t))
&& (DECL_CLASS_CONTEXT (t) == NULL_TREE || is_member_template (t)))
if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t))
{
tree args = DECL_TEMPLATE_INFO (t)
? DECL_TI_ARGS (t) : NULL_TREE;
OB_PUTC ('<');
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE;
if (args != NULL_TREE
&& DECL_CONTEXT (t) != NULL_TREE
&& uses_template_parms (DECL_CONTEXT (t))
/* This next clause checks that there is only one level of
template arguments. In that case, they are the
arguments for the class context. */
&& (TREE_CODE (args) == TREE_LIST
|| (TREE_CODE (args) == TREE_VEC
&& TREE_VEC_ELT (args, 0) != NULL_TREE
&& TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)))
/* We have something like this:
template <class T> struct S { void f(); };
and we are printing S<int>::f(). This is a template
instantiation, but we don't print anything after the f. */
;
else
{
if (TREE_CODE (args) == TREE_LIST)
{
tree arg;
int need_comma = 0;
OB_PUTC ('<');
for (arg = args; arg; arg = TREE_CHAIN (arg))
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
{
if (TREE_CODE (args) == TREE_LIST)
{
tree a = TREE_VALUE (arg);
if (need_comma)
OB_PUTS (", ");
tree arg;
int need_comma = 0;
if (a)
for (arg = args; arg; arg = TREE_CHAIN (arg))
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
dump_type (a, 0);
else
dump_expr (a, 0);
}
tree a = TREE_VALUE (arg);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1;
need_comma = 1;
}
}
}
else if (TREE_CODE (args) == TREE_VEC)
{
int i;
int need_comma = 0;
if (TREE_VEC_LENGTH (args) > 0
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args, 0);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
else if (TREE_CODE (args) == TREE_VEC)
{
tree a = TREE_VEC_ELT (args, i);
int i;
int need_comma = 0;
if (need_comma)
OB_PUTS (", ");
if (TREE_VEC_LENGTH (args) > 0
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args,
TREE_VEC_LENGTH (args) - 1);
if (a)
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
dump_type (a, 0);
else
dump_expr (a, 0);
}
tree a = TREE_VEC_ELT (args, i);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1;
need_comma = 1;
}
}
}
OB_PUTC ('>');
}
OB_PUTC ('>');
}
}
......
......@@ -1995,15 +1995,21 @@ cons_up_default_function (type, full_name, kind)
{
tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
int saved_processing_specialization;
int saved_processing_explicit_instantiation;
if (retref)
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);
processing_specialization = saved_processing_specialization;
processing_explicit_instantiation =
saved_processing_explicit_instantiation;
}
if (fn == void_type_node)
......
......@@ -1464,7 +1464,11 @@ mapcar (t, func)
case VAR_DECL:
case FUNCTION_DECL:
case CONST_DECL:
break;
/* Rather than aborting, return error_mark_node. This allows us
to report a sensible error message on code like this:
void g() { int i; f<i>(7); } */
return error_mark_node;
case PARM_DECL:
{
......
......@@ -4481,9 +4481,11 @@ build_unary_op (code, xarg, noconvert)
/* We don't require a match here; it's possible that the
context (like a cast to a particular type) will resolve
the particular choice of template. */
fn = determine_explicit_specialization (arg, NULL_TREE,
&targs,
0, 0);
fn = determine_specialization (arg,
NULL_TREE,
&targs,
0,
0);
if (fn)
{
......
......@@ -247,6 +247,10 @@ incomplete_type_error (value, type)
error ("invalid use of member type (did you forget the `&' ?)");
return;
case TEMPLATE_TYPE_PARM:
error ("invalid use of template type parameter");
return;
default:
my_friendly_abort (108);
}
......
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