Commit 02ed62dd by Mark Mitchell Committed by Mark Mitchell

re PR c++/22137 (Internal error: Segmentation fault (program cc1plus))

	PR c++/22137
	* cp-tree.h (QUALIFIED_NAME_IS_TEMPLATE): New macro.
	(check_template_keyword): New function.
	(finish_id_expression): Change prototoype.
	(finish_qualified_id_expr): Change prototype.
	(build_qualified_name): New function.
	(finish_class_member_access_expr): Change prototype.
	* init.c (build_offset_ref): Use build_qualified_name.
	* mangle.c (write_expression): Likewise.
	* parser.c (cp_parser_primary_expression): Remove qualifying_class
	parameter.  Add address_p and template_arg_p.  Use
	build_qualified_name.
	(cp_parser_id_expression): Default *template_p to
	template_keyword_p.  Check for invalid uses of the template
	keyword.
	(cp_parser_postfix_expression): Eliminate special handling for
	qualified names.  Adjust call to cp_parser_primary_expression.
	(cp_parser_postfix_dot_deref_expression): Adjust call to
	cp_parser_id_expression and finish_class_member_access_expr.
	(cp_parser_template_argument_list): Add comment.
	(cp_parser_template_argument): Adjust use of
	cp_parser_primary_expression.  Remove call to
	finish_qualified_id_expr.
	(cp_parser_lookup_name): Use build_qualified_name.
	* pt.c (tsubst): Use build_qualified_name.
	(tsubst_qualified_id): Likewise.  Adjust call to
	finish_qualified_id_expr.
	(tsubst_copy): Use build_qualified_name.
	(tsubst_copy_and_build): Adjusts call to finish_id_expression and
	finish_class_member_access_expr.
	* semantics.c (finish_non_static_data_member): Use
	build_qualified_name.
	(finish_qualified_id_expr): Add template_p and template_arg_p
	parameters.
	(finish_id_expression): Remove qualifiying_class parameter.  Add
	template_p, done, address_p, and template_arg_p.  Use
	build_qualified_name.  Adjust calls to
	finish_class_member_acess_expr.
	* tree.c (build_qualified_name): New function.
	* typeck.c (check_template_keyword): New function.
	(finish_class_member_access_expr): Add template_p argument.  Check
	for invalid uses of the template keyword.

	PR c++/22137
	* g++.dg/parse/template18.C: New test.
	* g++.dg/template/nontype15.C: Likewise.

From-SVN: r105463
parent c2b27658
2005-10-16 Mark Mitchell <mark@codesourcery.com>
PR c++/22137
* cp-tree.h (QUALIFIED_NAME_IS_TEMPLATE): New macro.
(check_template_keyword): New function.
(finish_id_expression): Change prototoype.
(finish_qualified_id_expr): Change prototype.
(build_qualified_name): New function.
(finish_class_member_access_expr): Change prototype.
* init.c (build_offset_ref): Use build_qualified_name.
* mangle.c (write_expression): Likewise.
* parser.c (cp_parser_primary_expression): Remove qualifying_class
parameter. Add address_p and template_arg_p. Use
build_qualified_name.
(cp_parser_id_expression): Default *template_p to
template_keyword_p. Check for invalid uses of the template
keyword.
(cp_parser_postfix_expression): Eliminate special handling for
qualified names. Adjust call to cp_parser_primary_expression.
(cp_parser_postfix_dot_deref_expression): Adjust call to
cp_parser_id_expression and finish_class_member_access_expr.
(cp_parser_template_argument_list): Add comment.
(cp_parser_template_argument): Adjust use of
cp_parser_primary_expression. Remove call to
finish_qualified_id_expr.
(cp_parser_lookup_name): Use build_qualified_name.
* pt.c (tsubst): Use build_qualified_name.
(tsubst_qualified_id): Likewise. Adjust call to
finish_qualified_id_expr.
(tsubst_copy): Use build_qualified_name.
(tsubst_copy_and_build): Adjusts call to finish_id_expression and
finish_class_member_access_expr.
* semantics.c (finish_non_static_data_member): Use
build_qualified_name.
(finish_qualified_id_expr): Add template_p and template_arg_p
parameters.
(finish_id_expression): Remove qualifiying_class parameter. Add
template_p, done, address_p, and template_arg_p. Use
build_qualified_name. Adjust calls to
finish_class_member_acess_expr.
* tree.c (build_qualified_name): New function.
* typeck.c (check_template_keyword): New function.
(finish_class_member_access_expr): Add template_p argument. Check
for invalid uses of the template keyword.
2005-10-15 Mark Mitchell <mark@codesourcery.com> 2005-10-15 Mark Mitchell <mark@codesourcery.com>
PR c++/21347 PR c++/21347
......
...@@ -51,6 +51,7 @@ struct diagnostic_context; ...@@ -51,6 +51,7 @@ struct diagnostic_context;
BIND_EXPR_TRY_BLOCK (in BIND_EXPR) BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE) TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
REFERENCE_REF_P (in INDIRECT_EXPR) REFERENCE_REF_P (in INDIRECT_EXPR)
QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -2933,6 +2934,11 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -2933,6 +2934,11 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define THUNK_TARGET(NODE) \ #define THUNK_TARGET(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
/* True for a SCOPE_REF iff the "template" keyword was used to
indicate that the qualified name denotes a template. */
#define QUALIFIED_NAME_IS_TEMPLATE(NODE) \
(TREE_LANG_FLAG_0 (SCOPE_REF_CHECK (NODE)))
/* These macros provide convenient access to the various _STMT nodes /* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */ created when parsing template declarations. */
#define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0) #define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
...@@ -4200,9 +4206,11 @@ extern tree finish_template_type (tree, tree, int); ...@@ -4200,9 +4206,11 @@ extern tree finish_template_type (tree, tree, int);
extern tree finish_base_specifier (tree, tree, bool); extern tree finish_base_specifier (tree, tree, bool);
extern void finish_member_declaration (tree); extern void finish_member_declaration (tree);
extern void qualified_name_lookup_error (tree, tree, tree); extern void qualified_name_lookup_error (tree, tree, tree);
extern void check_template_keyword (tree);
extern tree finish_id_expression (tree, tree, tree, extern tree finish_id_expression (tree, tree, tree,
cp_id_kind *, tree *, cp_id_kind *,
bool, bool, bool *, bool, bool, bool *,
bool, bool, bool, bool,
const char **); const char **);
extern tree finish_typeof (tree); extern tree finish_typeof (tree);
extern void finish_decl_cleanup (tree, tree); extern void finish_decl_cleanup (tree, tree);
...@@ -4212,7 +4220,8 @@ extern void finish_mem_initializers (tree); ...@@ -4212,7 +4220,8 @@ extern void finish_mem_initializers (tree);
extern tree check_template_template_default_arg (tree); extern tree check_template_template_default_arg (tree);
extern void expand_or_defer_fn (tree); extern void expand_or_defer_fn (tree);
extern void check_accessibility_of_qualified_id (tree, tree, tree); extern void check_accessibility_of_qualified_id (tree, tree, tree);
extern tree finish_qualified_id_expr (tree, tree, bool, bool); extern tree finish_qualified_id_expr (tree, tree, bool, bool,
bool, bool);
extern void simplify_aggr_init_expr (tree *); extern void simplify_aggr_init_expr (tree *);
extern void finalize_nrv (tree *, tree, tree); extern void finalize_nrv (tree *, tree, tree);
extern void note_decl_for_pch (tree); extern void note_decl_for_pch (tree);
...@@ -4242,6 +4251,7 @@ extern tree get_target_expr (tree); ...@@ -4242,6 +4251,7 @@ extern tree get_target_expr (tree);
extern tree build_cplus_array_type (tree, tree); extern tree build_cplus_array_type (tree, tree);
extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree); extern tree hash_tree_chain (tree, tree);
extern tree build_qualified_name (tree, tree, tree, bool);
extern int is_overloaded_fn (tree); extern int is_overloaded_fn (tree);
extern tree get_first_fn (tree); extern tree get_first_fn (tree);
extern tree ovl_cons (tree, tree); extern tree ovl_cons (tree, tree);
...@@ -4305,7 +4315,7 @@ extern tree inline_conversion (tree); ...@@ -4305,7 +4315,7 @@ extern tree inline_conversion (tree);
extern tree decay_conversion (tree); extern tree decay_conversion (tree);
extern tree default_conversion (tree); extern tree default_conversion (tree);
extern tree build_class_member_access_expr (tree, tree, tree, bool); extern tree build_class_member_access_expr (tree, tree, tree, bool);
extern tree finish_class_member_access_expr (tree, tree); extern tree finish_class_member_access_expr (tree, tree, bool);
extern tree build_x_indirect_ref (tree, const char *); extern tree build_x_indirect_ref (tree, const char *);
extern tree build_indirect_ref (tree, const char *); extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree); extern tree build_array_ref (tree, tree);
......
...@@ -1344,7 +1344,8 @@ build_offset_ref (tree type, tree name, bool address_p) ...@@ -1344,7 +1344,8 @@ build_offset_ref (tree type, tree name, bool address_p)
return name; return name;
if (dependent_type_p (type) || type_dependent_expression_p (name)) if (dependent_type_p (type) || type_dependent_expression_p (name))
return build_min_nt (SCOPE_REF, type, name); return build_qualified_name (NULL_TREE, type, name,
/*template_p=*/false);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR) if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{ {
......
...@@ -2008,9 +2008,10 @@ write_expression (tree expr) ...@@ -2008,9 +2008,10 @@ write_expression (tree expr)
if (code == PTRMEM_CST) if (code == PTRMEM_CST)
{ {
expr = build_nt (ADDR_EXPR, expr = build_nt (ADDR_EXPR,
build_nt (SCOPE_REF, build_qualified_name (/*type=*/NULL_TREE,
PTRMEM_CST_CLASS (expr), PTRMEM_CST_CLASS (expr),
PTRMEM_CST_MEMBER (expr))); PTRMEM_CST_MEMBER (expr),
/*template_p=*/false));
code = TREE_CODE (expr); code = TREE_CODE (expr);
} }
...@@ -2186,7 +2187,7 @@ write_expression (tree expr) ...@@ -2186,7 +2187,7 @@ write_expression (tree expr)
for (i = 0; i < TREE_CODE_LENGTH (code); ++i) for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
{ {
tree operand = TREE_OPERAND (expr, i); tree operand = TREE_OPERAND (expr, i);
/* As a GNU expression, the middle operand of a /* As a GNU extension, the middle operand of a
conditional may be omitted. Since expression conditional may be omitted. Since expression
manglings are supposed to represent the input token manglings are supposed to represent the input token
stream, there's no good way to mangle such an stream, there's no good way to mangle such an
......
...@@ -7544,7 +7544,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7544,7 +7544,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (e1 == error_mark_node || e2 == error_mark_node) if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node; return error_mark_node;
return build_nt (TREE_CODE (t), e1, e2); return build_qualified_name (/*type=*/NULL_TREE,
e1, e2, QUALIFIED_NAME_IS_TEMPLATE (t));
} }
case TYPEOF_TYPE: case TYPEOF_TYPE:
...@@ -7675,7 +7676,9 @@ tsubst_qualified_id (tree qualified_id, tree args, ...@@ -7675,7 +7676,9 @@ tsubst_qualified_id (tree qualified_id, tree args,
expr = name; expr = name;
if (dependent_type_p (scope)) if (dependent_type_p (scope))
return build_nt (SCOPE_REF, scope, expr); return build_qualified_name (/*type=*/NULL_TREE,
scope, expr,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
if (!BASELINK_P (name) && !DECL_P (expr)) if (!BASELINK_P (name) && !DECL_P (expr))
{ {
...@@ -7725,7 +7728,10 @@ tsubst_qualified_id (tree qualified_id, tree args, ...@@ -7725,7 +7728,10 @@ tsubst_qualified_id (tree qualified_id, tree args,
{ {
expr = (adjust_result_of_qualified_name_lookup expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type)); (expr, scope, current_class_type));
expr = finish_qualified_id_expr (scope, expr, done, address_p); expr = (finish_qualified_id_expr
(scope, expr, done, address_p,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id),
/*template_arg_p=*/false));
} }
if (TREE_CODE (expr) != SCOPE_REF) if (TREE_CODE (expr) != SCOPE_REF)
...@@ -7912,7 +7918,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7912,7 +7918,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
name = tsubst_copy (TREE_OPERAND (name, 0), args, name = tsubst_copy (TREE_OPERAND (name, 0), args,
complain, in_decl); complain, in_decl);
name = build1 (BIT_NOT_EXPR, NULL_TREE, name); name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
name = build_nt (SCOPE_REF, base, name); name = build_qualified_name (/*type=*/NULL_TREE,
base, name,
/*template_p=*/false);
} }
else if (TREE_CODE (name) == BASELINK) else if (TREE_CODE (name) == BASELINK)
name = tsubst_baselink (name, name = tsubst_baselink (name,
...@@ -7954,7 +7962,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7954,7 +7962,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case LT_EXPR: case LT_EXPR:
case GT_EXPR: case GT_EXPR:
case COMPOUND_EXPR: case COMPOUND_EXPR:
case SCOPE_REF:
case DOTSTAR_EXPR: case DOTSTAR_EXPR:
case MEMBER_REF: case MEMBER_REF:
case PREDECREMENT_EXPR: case PREDECREMENT_EXPR:
...@@ -7965,6 +7972,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7965,6 +7972,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl)); tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
case SCOPE_REF:
return build_qualified_name (/*type=*/NULL_TREE,
tsubst_copy (TREE_OPERAND (t, 0),
args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1),
args, complain, in_decl),
QUALIFIED_NAME_IS_TEMPLATE (t));
case ARRAY_REF: case ARRAY_REF:
return build_nt return build_nt
(ARRAY_REF, (ARRAY_REF,
...@@ -8438,7 +8453,6 @@ tsubst_copy_and_build (tree t, ...@@ -8438,7 +8453,6 @@ tsubst_copy_and_build (tree t,
{ {
tree decl; tree decl;
cp_id_kind idk; cp_id_kind idk;
tree qualifying_class;
bool non_integral_constant_expression_p; bool non_integral_constant_expression_p;
const char *error_msg; const char *error_msg;
...@@ -8458,10 +8472,13 @@ tsubst_copy_and_build (tree t, ...@@ -8458,10 +8472,13 @@ tsubst_copy_and_build (tree t,
decl = finish_id_expression (t, decl, NULL_TREE, decl = finish_id_expression (t, decl, NULL_TREE,
&idk, &idk,
&qualifying_class,
/*integral_constant_expression_p=*/false, /*integral_constant_expression_p=*/false,
/*allow_non_integral_constant_expression_p=*/false, /*allow_non_integral_constant_expression_p=*/false,
&non_integral_constant_expression_p, &non_integral_constant_expression_p,
/*template_p=*/false,
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
&error_msg); &error_msg);
if (error_msg) if (error_msg)
error (error_msg); error (error_msg);
...@@ -8872,7 +8889,8 @@ tsubst_copy_and_build (tree t, ...@@ -8872,7 +8889,8 @@ tsubst_copy_and_build (tree t,
else if (TREE_CODE (member) == FIELD_DECL) else if (TREE_CODE (member) == FIELD_DECL)
return finish_non_static_data_member (member, object, NULL_TREE); return finish_non_static_data_member (member, object, NULL_TREE);
return finish_class_member_access_expr (object, member); return finish_class_member_access_expr (object, member,
/*template_p=*/false);
} }
case THROW_EXPR: case THROW_EXPR:
......
...@@ -1407,8 +1407,10 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) ...@@ -1407,8 +1407,10 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF
for now. */ for now. */
if (processing_template_decl) if (processing_template_decl)
return build_min (SCOPE_REF, TREE_TYPE (decl), return build_qualified_name (TREE_TYPE (decl),
qualifying_scope, DECL_NAME (decl)); qualifying_scope,
DECL_NAME (decl),
/*template_p=*/false);
perform_or_defer_access_check (TYPE_BINFO (access_type), decl); perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
...@@ -1494,15 +1496,24 @@ check_accessibility_of_qualified_id (tree decl, ...@@ -1494,15 +1496,24 @@ check_accessibility_of_qualified_id (tree decl,
class named to the left of the "::" operator. DONE is true if this class named to the left of the "::" operator. DONE is true if this
expression is a complete postfix-expression; it is false if this expression is a complete postfix-expression; it is false if this
expression is followed by '->', '[', '(', etc. ADDRESS_P is true expression is followed by '->', '[', '(', etc. ADDRESS_P is true
iff this expression is the operand of '&'. */ iff this expression is the operand of '&'. TEMPLATE_P is true iff
the qualified-id was of the form "A::template B". TEMPLATE_ARG_P
is true iff this qualified name appears as a template argument. */
tree tree
finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, finish_qualified_id_expr (tree qualifying_class,
bool address_p) tree expr,
bool done,
bool address_p,
bool template_p,
bool template_arg_p)
{ {
if (error_operand_p (expr)) if (error_operand_p (expr))
return error_mark_node; return error_mark_node;
if (template_p)
check_template_keyword (expr);
/* If EXPR occurs as the operand of '&', use special handling that /* If EXPR occurs as the operand of '&', use special handling that
permits a pointer-to-member. */ permits a pointer-to-member. */
if (address_p && done) if (address_p && done)
...@@ -1514,7 +1525,13 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, ...@@ -1514,7 +1525,13 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
return expr; return expr;
} }
if (TREE_CODE (expr) == FIELD_DECL) /* Within the scope of a class, turn references to non-static
members into expression of the form "this->...". */
if (template_arg_p)
/* But, within a template argument, we do not want make the
transformation, as there is no "this" pointer. */
;
else if (TREE_CODE (expr) == FIELD_DECL)
expr = finish_non_static_data_member (expr, current_class_ref, expr = finish_non_static_data_member (expr, current_class_ref,
qualifying_class); qualifying_class);
else if (BASELINK_P (expr) && !processing_template_decl) else if (BASELINK_P (expr) && !processing_template_decl)
...@@ -2383,6 +2400,13 @@ qualified_name_lookup_error (tree scope, tree name, tree decl) ...@@ -2383,6 +2400,13 @@ qualified_name_lookup_error (tree scope, tree name, tree decl)
constant-expression, but a non-constant expression is also constant-expression, but a non-constant expression is also
permissible. permissible.
DONE is true if this expression is a complete postfix-expression;
it is false if this expression is followed by '->', '[', '(', etc.
ADDRESS_P is true iff this expression is the operand of '&'.
TEMPLATE_P is true iff the qualified-id was of the form
"A::template B". TEMPLATE_ARG_P is true iff this qualified name
appears as a template argument.
If an error occurs, and it is the kind of error that might cause If an error occurs, and it is the kind of error that might cause
the parser to abort a tentative parse, *ERROR_MSG is filled in. It the parser to abort a tentative parse, *ERROR_MSG is filled in. It
is the caller's responsibility to issue the message. *ERROR_MSG is the caller's responsibility to issue the message. *ERROR_MSG
...@@ -2401,10 +2425,13 @@ finish_id_expression (tree id_expression, ...@@ -2401,10 +2425,13 @@ finish_id_expression (tree id_expression,
tree decl, tree decl,
tree scope, tree scope,
cp_id_kind *idk, cp_id_kind *idk,
tree *qualifying_class,
bool integral_constant_expression_p, bool integral_constant_expression_p,
bool allow_non_integral_constant_expression_p, bool allow_non_integral_constant_expression_p,
bool *non_integral_constant_expression_p, bool *non_integral_constant_expression_p,
bool template_p,
bool done,
bool address_p,
bool template_arg_p,
const char **error_msg) const char **error_msg)
{ {
/* Initialize the output parameters. */ /* Initialize the output parameters. */
...@@ -2610,20 +2637,32 @@ finish_id_expression (tree id_expression, ...@@ -2610,20 +2637,32 @@ finish_id_expression (tree id_expression,
dependent. */ dependent. */
if (scope) if (scope)
{ {
if (TYPE_P (scope))
*qualifying_class = scope;
/* Since this name was dependent, the expression isn't /* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it might constant -- yet. No error is issued because it might
be constant when things are instantiated. */ be constant when things are instantiated. */
if (integral_constant_expression_p) if (integral_constant_expression_p)
*non_integral_constant_expression_p = true; *non_integral_constant_expression_p = true;
if (TYPE_P (scope) && dependent_type_p (scope)) if (TYPE_P (scope))
return build_nt (SCOPE_REF, scope, id_expression); {
else if (TYPE_P (scope) && DECL_P (decl)) if (address_p && done)
return convert_from_reference decl = finish_qualified_id_expr (scope, decl,
(build2 (SCOPE_REF, TREE_TYPE (decl), scope, id_expression)); done, address_p,
else template_p,
return convert_from_reference (decl); template_arg_p);
else if (dependent_type_p (scope))
decl = build_qualified_name (/*type=*/NULL_TREE,
scope,
id_expression,
template_p);
else if (DECL_P (decl))
decl = build_qualified_name (TREE_TYPE (decl),
scope,
id_expression,
template_p);
}
if (TREE_TYPE (decl))
decl = convert_from_reference (decl);
return decl;
} }
/* A TEMPLATE_ID already contains all the information we /* A TEMPLATE_ID already contains all the information we
need. */ need. */
...@@ -2703,14 +2742,20 @@ finish_id_expression (tree id_expression, ...@@ -2703,14 +2742,20 @@ finish_id_expression (tree id_expression,
mark_used (decl); mark_used (decl);
if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl)) if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
*qualifying_class = scope; decl = finish_qualified_id_expr (scope,
decl,
done,
address_p,
template_p,
template_arg_p);
else else
{ {
tree r = convert_from_reference (decl); tree r = convert_from_reference (decl);
if (processing_template_decl if (processing_template_decl && TYPE_P (scope))
&& TYPE_P (scope)) r = build_qualified_name (TREE_TYPE (r),
r = build2 (SCOPE_REF, TREE_TYPE (r), scope, decl); scope, decl,
template_p);
decl = r; decl = r;
} }
} }
...@@ -2734,13 +2779,15 @@ finish_id_expression (tree id_expression, ...@@ -2734,13 +2779,15 @@ finish_id_expression (tree id_expression,
if (!really_overloaded_fn (decl)) if (!really_overloaded_fn (decl))
mark_used (first_fn); mark_used (first_fn);
if (TREE_CODE (first_fn) == FUNCTION_DECL if (!template_arg_p
&& TREE_CODE (first_fn) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (first_fn) && DECL_FUNCTION_MEMBER_P (first_fn)
&& !shared_member_p (decl)) && !shared_member_p (decl))
{ {
/* A set of member functions. */ /* A set of member functions. */
decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0); decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
return finish_class_member_access_expr (decl, id_expression); return finish_class_member_access_expr (decl, id_expression,
/*template_p=*/false);
} }
} }
else else
......
...@@ -805,6 +805,23 @@ debug_binfo (tree elem) ...@@ -805,6 +805,23 @@ debug_binfo (tree elem)
} }
} }
/* Build a representation for the qualified name SCOPE::NAME. TYPE is
the type of the result expression, if known, or NULL_TREE if the
resulting expression is type-dependent. If TEMPLATE_P is true,
NAME is known to be a template because the user explicitly used the
"template" keyword after the "::".
All SCOPE_REFs should be built by use of this function. */
tree
build_qualified_name (tree type, tree scope, tree name, bool template_p)
{
tree t;
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
return t;
}
int int
is_overloaded_fn (tree x) is_overloaded_fn (tree x)
{ {
......
...@@ -1841,16 +1841,69 @@ lookup_destructor (tree object, tree scope, tree dtor_name) ...@@ -1841,16 +1841,69 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
return expr; return expr;
} }
/* An expression of the form "A::template B" has been resolved to
DECL. Issue a diagnostic if B is not a template or template
specialization. */
void
check_template_keyword (tree decl)
{
/* The standard says:
[temp.names]
If a name prefixed by the keyword template is not a member
template, the program is ill-formed.
DR 228 removed the restriction that the template be a member
template.
DR 96, if accepted would add the further restriction that explcit
template arguments must be provided if the template keyword is
used, but, as of 2005-10-16, that DR is still in "drafting". If
this DR is accepted, then the semantic checks here can be
simplified, as the entity named must in fact be a template
specialization, rather than, as at present, a set of overloaded
functions containing at least one template function. */
if (TREE_CODE (decl) != TEMPLATE_DECL
&& TREE_CODE (decl) != TEMPLATE_ID_EXPR)
{
if (!is_overloaded_fn (decl))
pedwarn ("%qD is not a template", decl);
else
{
tree fns;
if (BASELINK_P (decl))
fns = BASELINK_FUNCTIONS (decl);
while (fns)
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL
|| TREE_CODE (fn) == TEMPLATE_ID_EXPR)
break;
if (TREE_CODE (fn) == FUNCTION_DECL
&& DECL_USE_TEMPLATE (fn)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
break;
fns = OVL_NEXT (fns);
}
if (!fns)
pedwarn ("%qD is not a template", decl);
}
}
}
/* This function is called by the parser to process a class member /* This function is called by the parser to process a class member
access expression of the form OBJECT.NAME. NAME is a node used by access expression of the form OBJECT.NAME. NAME is a node used by
the parser to represent a name; it is not yet a DECL. It may, the parser to represent a name; it is not yet a DECL. It may,
however, be a BASELINK where the BASELINK_FUNCTIONS is a however, be a BASELINK where the BASELINK_FUNCTIONS is a
TEMPLATE_ID_EXPR. Templates must be looked up by the parser, and TEMPLATE_ID_EXPR. Templates must be looked up by the parser, and
there is no reason to do the lookup twice, so the parser keeps the there is no reason to do the lookup twice, so the parser keeps the
BASELINK. */ BASELINK. TEMPLATE_P is true iff NAME was explicitly declared to
be a template via the use of the "A::template B" syntax. */
tree tree
finish_class_member_access_expr (tree object, tree name) finish_class_member_access_expr (tree object, tree name, bool template_p)
{ {
tree expr; tree expr;
tree object_type; tree object_type;
...@@ -1995,6 +2048,9 @@ finish_class_member_access_expr (tree object, tree name) ...@@ -1995,6 +2048,9 @@ finish_class_member_access_expr (tree object, tree name)
if (TREE_DEPRECATED (member)) if (TREE_DEPRECATED (member))
warn_deprecated_use (member); warn_deprecated_use (member);
if (template_p)
check_template_keyword (member);
expr = build_class_member_access_expr (object, member, access_path, expr = build_class_member_access_expr (object, member, access_path,
/*preserve_reference=*/false); /*preserve_reference=*/false);
if (processing_template_decl && expr != error_mark_node) if (processing_template_decl && expr != error_mark_node)
......
2005-10-16 Mark Mitchell <mark@codesourcery.com>
PR c++/22137
* g++.dg/parse/template18.C: New test.
* g++.dg/template/nontype15.C: Likewise.
2005-10-16 Erik Edelmann <erik.edelmann@iki.fi> 2005-10-16 Erik Edelmann <erik.edelmann@iki.fi>
PR fortran/22273 PR fortran/22273
// PR c++/22137
struct A
{
static void a1();
template <typename T>
static void b1(T);
template <int I>
struct B {
static void b1();
template <typename T>
static void b2(T);
};
struct C {
static void c1();
};
};
template<int I> void f1()
{
A* p;
A::template a1(); // { dg-error "template" }
A::template b1(0);
p->template a1(); // { dg-error "template" }
p->template b1('a');
A::template B<0>::b1();
A::template B<0>::template b1(); // { dg-error "template" }
A::template B<0>::template b2(0);
A::template B<0>::template b2<double>(0);
// Because B<I> is dependent, none of these are errors, as this
// function is not instantiated.
A::template B<I>::b1();
A::template B<I>::template b1();
A::template B<I>::template b2(0);
A::template B<I>::template b2<double>(0);
A::template C::c1(); // { dg-error "template" }
}
template<int I> void f2()
{
// These are copies of lines from f1, but this function is
// instantiated, so we should get errors here.
A::template B<I>::b1();
A::template B<I>::template b1(); // { dg-error "template" }
A::template B<I>::template b2(0);
A::template B<I>::template b2<double>(0);
}
template void f2<0>(); // { dg-error "instantiated" }
struct foo {
typedef int (*fun)(int);
static int f(int); // overload between static & non-static
int f();
static int g(int); // non-overloaded static
};
template<foo::fun>
struct f_obj {
// something ..
};
int foo::f() {
f_obj<f> f1;
f_obj<g> f2;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment