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:
parent
685885b773
commit
7565064686
133
gcc/cp/ChangeLog
133
gcc/cp/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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. */;
|
||||
|
|
136
gcc/cp/class.c
136
gcc/cp/class.c
|
@ -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));
|
||||
|
|
131
gcc/cp/cvt.c
131
gcc/cp/cvt.c
|
@ -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;
|
||||
}
|
||||
|
|
217
gcc/cp/decl.c
217
gcc/cp/decl.c
|
@ -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,
|
||||
|
|
|
@ -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)));
|
||||
|
|
126
gcc/cp/error.c
126
gcc/cp/error.c
|
@ -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 ('>');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
192
gcc/cp/parse.y
192
gcc/cp/parse.y
|
@ -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? ^^^ */
|
||||
|
|
1487
gcc/cp/pt.c
1487
gcc/cp/pt.c
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue