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
This commit is contained in:
Mark Mitchell 1998-01-19 22:41:40 +00:00 committed by Jason Merrill
parent 685885b773
commit 7565064686
14 changed files with 1892 additions and 600 deletions

View File

@ -1,3 +1,136 @@
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.

View File

@ -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. */;

View File

@ -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));
}

View File

@ -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));

View File

@ -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;
}

View File

@ -2529,7 +2529,9 @@ duplicate_decls (newdecl, olddecl)
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3))
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3)
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@ -2563,19 +2565,31 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
else if ((TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| (DECL_TI_TEMPLATE (newdecl)
!= DECL_TI_TEMPLATE (olddecl))))
|| (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (newdecl)
&& (!DECL_TEMPLATE_SPECIALIZATION (olddecl)
|| (DECL_TI_TEMPLATE (olddecl) != DECL_TI_TEMPLATE
(newdecl)))))
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_INFO (newdecl)
|| (DECL_TI_TEMPLATE (newdecl)
!= DECL_TI_TEMPLATE (olddecl))))
|| (DECL_TEMPLATE_SPECIALIZATION (newdecl)
&& (!DECL_TEMPLATE_INFO (olddecl)
|| (DECL_TI_TEMPLATE (olddecl)
!= DECL_TI_TEMPLATE (newdecl))))))
/* It's OK to have a template specialization and a non-template
with the same type, or to have specializations of two
different templates with the same type. */
different templates with the same type. Note that if one is a
specialization, and the other is an instantiation of the same
template, that we do not exit at this point. That situation
can occur if we instantiate a template class, and then
specialize one of its methods. This situation is legal, but
the declarations must be merged in the usual way. */
return 0;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl))
|| (DECL_TEMPLATE_INSTANTIATION (newdecl)
&& !DECL_USE_TEMPLATE (olddecl))))
/* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */
return 0;
else
{
@ -2860,9 +2874,29 @@ duplicate_decls (newdecl, olddecl)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_TEMPLATE_INSTANTIATION (olddecl) &&
!DECL_TEMPLATE_INSTANTIATION (newdecl))
DECL_USE_TEMPLATE (olddecl) = DECL_USE_TEMPLATE (newdecl);
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_TEMPLATE_INSTANTIATION (newdecl))
{
/* If newdecl is not a specialization, then it is not a
template-related function at all. And that means that we
shoud have exited above, returning 0. */
my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
0);
if (TREE_USED (olddecl))
/* From [temp.expl.spec]:
If a template, a member template or the member of a class
template is explicitly specialized then that
specialization shall be declared before the first use of
that specialization that would cause an implicit
instantiation to take place, in every translation unit in
which such a use occurs. */
cp_error ("explicit specialization of %D after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
}
DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
/* If either decl says `inline', this fn is inline, unless its
@ -2922,8 +2956,8 @@ duplicate_decls (newdecl, olddecl)
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
DECL_TEMPLATE_INSTANTIATIONS (newdecl)
= DECL_TEMPLATE_INSTANTIATIONS (olddecl);
DECL_TEMPLATE_SPECIALIZATIONS (newdecl)
= DECL_TEMPLATE_SPECIALIZATIONS (olddecl);
if (DECL_CHAIN (newdecl) == NULL_TREE)
DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
}
@ -2965,6 +2999,38 @@ duplicate_decls (newdecl, olddecl)
#define ROUND(x) ((x + obstack_alignment_mask (&permanent_obstack)) \
& ~ obstack_alignment_mask (&permanent_obstack))
if (DECL_TEMPLATE_INSTANTIATION (newdecl))
{
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
o A friend function was declared in a class template. The
class template was instantiated.
o The instantiation of the friend declaration was
recorded on the instantiation list, and is newdecl.
o Later, however, instantiate_class_template called pushdecl
on the newdecl to perform name injection. But, pushdecl in
turn called duplicate_decls when it discovered that another
declaration of a global function with the same name already
existed.
o Here, in duplicate_decls, we decided to clobber newdecl.
If we're going to do that, we'd better make sure that
olddecl, and not newdecl, is on the list of
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
tree tmpl = DECL_TI_TEMPLATE (newdecl);
tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
for (; decls; decls = TREE_CHAIN (decls))
if (TREE_VALUE (decls) == newdecl)
TREE_VALUE (decls) = olddecl;
}
if ((char *)newdecl + ROUND (function_size)
+ ROUND (sizeof (struct lang_decl))
== obstack_next_free (&permanent_obstack))
@ -6024,6 +6090,13 @@ start_decl (declarator, declspecs, initialized)
context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
}
/* Static data member are tricky; an in-class initialization
still doesn't provide a definition, so the in-class
declaration will have DECL_EXTERNAL set, but will have an
initialization. Thus, duplicate_decls won't warn
about this situation, and so we check here. */
if (DECL_INITIAL (decl) && DECL_INITIAL (field))
cp_error ("duplicate initialization of %D", decl);
if (duplicate_decls (decl, field))
decl = field;
}
@ -6056,7 +6129,13 @@ start_decl (declarator, declspecs, initialized)
if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !global_bindings_p ())
|| TREE_CODE (type) == LANG_TYPE)
|| TREE_CODE (type) == LANG_TYPE
/* The declaration of template specializations does not affect
the functions available for overload resolution, so we do not
call pushdecl. */
|| (!flag_guiding_decls
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (decl)))
tem = decl;
else
tem = pushdecl (decl);
@ -6397,9 +6476,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
{
tree stmt = DECL_VINDEX (decl);
DECL_VINDEX (decl) = NULL_TREE;
TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
add_tree (stmt);
if (stmt != NULL_TREE)
{
DECL_VINDEX (decl) = NULL_TREE;
TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
add_tree (stmt);
}
}
goto finish_end0;
@ -6685,7 +6767,11 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|| TREE_CODE (decl) == RESULT_DECL)
{
/* ??? FIXME: What about nested classes? */
int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
/* We check for FUNCTION_DECL here so that member functions of
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
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
@ -7367,12 +7453,12 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
break;
}
/* Caller will do the rest of this. */
check_explicit_specialization (orig_declarator, decl,
template_count,
funcdef_flag ? 2 :
(friendp ? 3 : 0));
if (friendp &&
TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
/* A friend declaration of the form friend void f<>(). */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
/* Caller will do the rest of this. */
if (check < 0)
return decl;
@ -7391,6 +7477,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
grokclassfn (ctype, declarator, decl, flags, quals);
check_explicit_specialization (orig_declarator, decl,
template_count,
funcdef_flag ? 2 :
(friendp ? 3 : 0));
if (check)
{
tmp = check_classfn (ctype, decl);
@ -7433,12 +7524,17 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype != NULL_TREE)
grokclassfn (ctype, cname, decl, flags, quals);
check_explicit_specialization (orig_declarator, decl,
template_count,
funcdef_flag ? 2 :
(friendp ? 3 : 0));
if (ctype != NULL_TREE && check)
{
tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT(tmp);
tmp = DECL_TEMPLATE_RESULT (tmp);
if (tmp && DECL_STATIC_FUNCTION_P (tmp)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
@ -7466,19 +7562,27 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
methods, though. */
if (! current_function_decl)
{
/* FIXME: this should only need to look at
IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
if (!DECL_TEMPLATE_SPECIALIZATION (decl))
{
duplicate_decls (decl, tmp);
decl = tmp;
/* avoid creating circularities. */
DECL_CHAIN (decl) = NULL_TREE;
/* We don't do this for specializations since the
equivalent checks will be done later. Also, at this
point the DECL_ASSEMBLER_NAME is not yet fully
accurate. */
/* FIXME: this should only need to look at
IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
/* avoid creating circularities. */
DECL_CHAIN (decl) = NULL_TREE;
}
}
if (attrlist)
@ -9169,7 +9273,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
t = ctype;
while (t != NULL_TREE)
{
if (CLASSTYPE_TEMPLATE_INFO (t))
if (CLASSTYPE_TEMPLATE_INFO (t) &&
!CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
template_count += 1;
t = TYPE_MAIN_DECL (t);
if (DECL_LANG_SPECIFIC (t))
@ -9595,7 +9700,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (! friendp || ! staticp);
publicp = (! friendp || ! staticp) && !is_local_class (ctype);
decl = grokfndecl (ctype, type,
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
@ -9811,7 +9916,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
decl = grokfndecl (ctype, type, original_name, declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? 2 : 1, friendp,
1, friendp,
publicp, inlinep, funcdef_flag,
template_count);
if (decl == NULL_TREE)
@ -10926,8 +11031,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
}
#if 1
/* This code replaces similar code in layout_basetypes. */
else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
&& ! (current_template_parms && uses_template_parms (basetype)))
else if (! (current_template_parms && uses_template_parms (basetype))
&& TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
@ -11506,7 +11611,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
push_template_decl (decl1);
else if (pre_parsed_p == 0)
{
decl1 = pushdecl (decl1);
/* A specialization is not used to guide overload resolution. */
if (flag_guiding_decls
|| !DECL_TEMPLATE_SPECIALIZATION (decl1))
decl1 = pushdecl (decl1);
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
@ -11637,7 +11745,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (processing_template_decl)
{
extern tree last_tree;
++minimal_parse_mode;
last_tree = DECL_SAVED_TREE (decl1)
= build_nt (EXPR_STMT, void_zero_node);
@ -12361,9 +12468,21 @@ finish_function (lineno, call_poplevel, nested)
if (! processing_template_decl)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
if (DECL_CONTEXT (fndecl) != NULL_TREE
&& is_local_class (DECL_CONTEXT (fndecl)))
/* Trick rest_of_compilation into not deferring output of this
function, even if it is inline, since the rtl_obstack for
this function is the function_obstack of the enclosing
function and will be deallocated when the enclosing
function is gone. See save_tree_status. */
flag_keep_inline_functions = 1;
/* Run the optimizers and output the assembler code for this
function. */
@ -12384,6 +12503,8 @@ finish_function (lineno, call_poplevel, nested)
else
rest_of_compilation (fndecl);
flag_keep_inline_functions = saved_flag_keep_inline_functions;
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
{
/* Set DECL_EXTERNAL so that assemble_external will be called as
@ -12529,7 +12650,7 @@ start_method (declspecs, declarator)
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_decl && ! current_function_decl)
if (processing_template_decl)
push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,

View File

@ -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)));

View File

@ -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;
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)
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)
OB_PUTC ('<');
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
{
tree arg;
int need_comma = 0;
for (arg = args; arg; arg = TREE_CHAIN (arg))
if (TREE_CODE (args) == TREE_LIST)
{
tree a = TREE_VALUE (arg);
tree arg;
int need_comma = 0;
if (need_comma)
OB_PUTS (", ");
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;
}
}
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++)
{
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;
}
}
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,
TREE_VEC_LENGTH (args) - 1);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
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;
}
}
}
OB_PUTC ('>');
}
OB_PUTC ('>');
}
}

View File

@ -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)

View File

@ -56,7 +56,6 @@ extern int errno;
extern int end_of_file;
extern int current_class_depth;
extern tree last_tree;
/* FSF LOCAL dje prefix attributes */
extern tree strip_attrs PROTO((tree));
@ -73,6 +72,7 @@ extern tree strip_attrs PROTO((tree));
static char *cond_stmt_keyword;
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. */
int have_extern_spec;
@ -94,6 +94,32 @@ empty_parms ()
parms = NULL_TREE;
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
@ -260,7 +286,7 @@ empty_parms ()
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm
%type <code> template_close_bracket
%type <ttype> template_type template_arg_list template_arg
%type <ttype> template_type template_arg_list template_arg_list_opt template_arg
%type <ttype> condition xcond paren_cond_or_null
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
%type <ttype> complete_type_name notype_identifier nonnested_type
@ -716,26 +742,7 @@ fn.def2:
| constructor_declarator
{ $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
| template_header fn.def2
{
if ($1)
end_template_decl ();
else
end_specialization ();
if ($2 && DECL_TEMPLATE_INFO ($2)
&& !DECL_TEMPLATE_SPECIALIZATION ($2))
{
$$ = DECL_TI_TEMPLATE ($2);
check_member_template ($$);
}
else if ($2)
$$ = $2;
else
{
cp_error("invalid member template declaration");
$$ = NULL_TREE;
}
}
{ $$ = finish_member_template_decl ($1, $2); }
;
return_id:
@ -848,54 +855,57 @@ identifier_defn:
;
explicit_instantiation:
TEMPLATE typespec ';'
{ do_type_instantiation ($2.t, NULL_TREE);
TEMPLATE begin_explicit_instantiation typespec ';'
{ do_type_instantiation ($3.t, NULL_TREE);
yyungetc (';', 1); }
| TEMPLATE typed_declspecs declarator
{ tree specs = strip_attrs ($2.t);
do_decl_instantiation (specs, $3, NULL_TREE); }
| TEMPLATE notype_declarator
{ do_decl_instantiation (NULL_TREE, $2, NULL_TREE); }
| TEMPLATE constructor_declarator
{ do_decl_instantiation (NULL_TREE, $2, NULL_TREE); }
| SCSPEC TEMPLATE typespec ';'
{ do_type_instantiation ($3.t, $1);
yyungetc (';', 1); }
| SCSPEC TEMPLATE typed_declspecs declarator
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation typed_declspecs declarator
{ tree specs = strip_attrs ($3.t);
do_decl_instantiation (specs, $4, $1); }
| SCSPEC TEMPLATE notype_declarator
{ do_decl_instantiation (NULL_TREE, $3, $1); }
| SCSPEC TEMPLATE constructor_declarator
{ do_decl_instantiation (NULL_TREE, $3, $1); }
do_decl_instantiation (specs, $4, NULL_TREE); }
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation notype_declarator
{ do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation constructor_declarator
{ do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
end_explicit_instantiation
| SCSPEC TEMPLATE begin_explicit_instantiation typespec ';'
{ do_type_instantiation ($4.t, $1);
yyungetc (';', 1); }
end_explicit_instantiation
| SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
declarator
{ tree specs = strip_attrs ($4.t);
do_decl_instantiation (specs, $5, $1); }
end_explicit_instantiation
| SCSPEC TEMPLATE begin_explicit_instantiation notype_declarator
{ do_decl_instantiation (NULL_TREE, $4, $1); }
end_explicit_instantiation
| SCSPEC TEMPLATE begin_explicit_instantiation constructor_declarator
{ do_decl_instantiation (NULL_TREE, $4, $1); }
end_explicit_instantiation
;
begin_explicit_instantiation:
{ begin_explicit_instantiation(); }
end_explicit_instantiation:
{ end_explicit_instantiation(); }
/* The TYPENAME expansions are to deal with use of a template class name as
a template within the class itself, where the template decl is hidden by
a type decl. Got all that? */
template_type:
PTYPENAME '<' template_arg_list template_close_bracket
PTYPENAME '<' template_arg_list_opt template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE);
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| PTYPENAME '<' template_close_bracket
| TYPENAME '<' template_arg_list_opt template_close_bracket
{
$$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| TYPENAME '<' template_arg_list template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| TYPENAME '<' template_close_bracket
{
$$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
@ -903,15 +913,9 @@ template_type:
;
self_template_type:
SELFNAME '<' template_arg_list template_close_bracket
SELFNAME '<' template_arg_list_opt template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| SELFNAME '<' template_close_bracket
{
$$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
@ -927,8 +931,14 @@ template_close_bracket:
}
;
template_arg_list_opt:
/* empty */
{ $$ = NULL_TREE; }
| template_arg_list
;
template_arg_list:
template_arg
template_arg
{ $$ = build_tree_list (NULL_TREE, $$); }
| template_arg_list ',' template_arg
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); }
@ -1297,22 +1307,19 @@ do_id:
{ $$ = do_identifier ($<ttype>-1, 1); }
template_id:
PFUNCNAME '<' do_id template_arg_list template_close_bracket
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($3, $4); }
| PFUNCNAME '<' do_id template_close_bracket
{ $$ = lookup_template_function ($3, NULL_TREE); }
| operator_name '<' do_id template_arg_list template_close_bracket
| operator_name '<' do_id template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($3, $4); }
| operator_name '<' do_id template_close_bracket
{ $$ = lookup_template_function ($3, NULL_TREE); }
;
object_template_id:
TEMPLATE identifier '<' template_arg_list template_close_bracket
TEMPLATE identifier '<' template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
| TEMPLATE PFUNCNAME '<' template_arg_list template_close_bracket
| TEMPLATE PFUNCNAME '<' template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
| TEMPLATE operator_name '<' template_arg_list template_close_bracket
| TEMPLATE operator_name '<' template_arg_list_opt
template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
;
@ -1333,7 +1340,7 @@ expr_or_declarator:
;
notype_template_declarator:
IDENTIFIER '<' template_arg_list template_close_bracket
IDENTIFIER '<' template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
| NSNAME '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
@ -2261,7 +2268,6 @@ structsp:
$$.new_type_flag = 0; }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly
{ reset_specialization(); }
opt.component_decl_list '}' maybe_attribute
{
int semi;
@ -2285,7 +2291,7 @@ structsp:
;
else
{
$<ttype>$ = finish_struct ($1, $4, $6, semi);
$<ttype>$ = finish_struct ($1, $3, $5, semi);
if (semi) note_got_semicolon ($<ttype>$);
}
@ -2304,10 +2310,13 @@ structsp:
}
pending_inlines
{
$$.t = $<ttype>7;
$$.t = $<ttype>6;
$$.new_type_flag = 1;
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
/* Undo the begin_tree in left_curly. */
end_tree ();
}
| class_head %prec EMPTY
{
@ -2670,6 +2679,12 @@ left_curly:
if (t && IDENTIFIER_TEMPLATE (t))
overload_template_name (t, 1);
#endif
reset_specialization();
/* In case this is a local class within a template
function, we save the current tree structure so
that we can get it back later. */
begin_tree ();
}
;
@ -2791,26 +2806,7 @@ component_decl_1:
| using_decl
{ $$ = do_class_using_decl ($1); }
| template_header component_decl_1
{
if ($1)
end_template_decl ();
else
end_specialization ();
if ($2 && DECL_TEMPLATE_INFO ($2)
&& !DECL_TEMPLATE_SPECIALIZATION ($2))
{
$$ = DECL_TI_TEMPLATE ($2);
check_member_template ($$);
}
else if ($2)
$$ = $2;
else
{
cp_error("invalid member template declaration");
$$ = NULL_TREE;
}
}
{ $$ = finish_member_template_decl ($1, $2); }
/* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */

File diff suppressed because it is too large Load Diff

View File

@ -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:
{

View File

@ -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)
{

View File

@ -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);
}