Commit 015c2c66 by Mark Mitchell Committed by Mark Mitchell

re PR c++/28341 (ICE with references as template parameters)

	PR c++/28341
	* tree.c (cast_valid_in_integral_constant_expression_p): New
	function.
	* cp-tree.h (tsubst_copy_and_build): Adjust prototype.
	* pt.c (tsubst_expr): Add integral_constant_expression_p
	parameter.
	(fold_non_dependent_expr): Adjust callers of
	tsubst_{expr,copy_and_build}.
	(tsubst_friend_function): Likewise.
	(tsubst_template_arg): Likewise.
	(tsubst_default_argument): Likewise.
	(tsubst_decl): Likewise.
	(tsubst): Likewise.
	(tsubst_omp_clasuses): Likewise.
	(regenerate_decl_fromp_template): Likewise.
	(instantiate_decl): Likewise.
	(tsubst_initializer_list): Likewise.
	(tsubst_enum): Likewise.
	(tsubst_expr): Use RECUR throughout.
	(tsubst_copy_and_build): Change definition of RECUR.  Do not allow
	invalid casts in integral constant expressions.
	* parser.c (cp_parser_postfix_expression): Use
	cast_valid_in_integral_constant_expression_p.
	(cp_parser_cast_expression): Likewise.
	(cp_parser_functional_cast): Likewise.

	PR c++/28346
	* pt.c (tsubst_qualified_id): Do not strip references from
	OFFSET_REFs. 

2006-08-20  Mark Mitchell  <mark@codesourcery.com>

	PR c++/28341
	* g++.dg/template/ref3.C: New test.
	* g++.dg/template/nontype13.C: New test.

	PR c++/28346
	* g++.dg/template/ptrmem17.C: New test.


2006-08-20  Mark Mitchell  <mark@codesourcery.com>

	* objcp-lang.c (objcp_tsubst_copy_and_build): Adjust call to
	tsubst_copy_and_build.

From-SVN: r116276
parent 1057fc81
2006-08-20 Mark Mitchell <mark@codesourcery.com>
PR c++/28341
* tree.c (cast_valid_in_integral_constant_expression_p): New
function.
* cp-tree.h (tsubst_copy_and_build): Adjust prototype.
* pt.c (tsubst_expr): Add integral_constant_expression_p
parameter.
(fold_non_dependent_expr): Adjust callers of
tsubst_{expr,copy_and_build}.
(tsubst_friend_function): Likewise.
(tsubst_template_arg): Likewise.
(tsubst_default_argument): Likewise.
(tsubst_decl): Likewise.
(tsubst): Likewise.
(tsubst_omp_clasuses): Likewise.
(regenerate_decl_fromp_template): Likewise.
(instantiate_decl): Likewise.
(tsubst_initializer_list): Likewise.
(tsubst_enum): Likewise.
(tsubst_expr): Use RECUR throughout.
(tsubst_copy_and_build): Change definition of RECUR. Do not allow
invalid casts in integral constant expressions.
* parser.c (cp_parser_postfix_expression): Use
cast_valid_in_integral_constant_expression_p.
(cp_parser_cast_expression): Likewise.
(cp_parser_functional_cast): Likewise.
PR c++/28346
* pt.c (tsubst_qualified_id): Do not strip references from
OFFSET_REFs.
2006-08-17 Volker Reichelt <reichelt@igpm.rwth-aachen.de> 2006-08-17 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/28606 PR c++/28606
......
...@@ -4117,7 +4117,7 @@ extern void print_candidates (tree); ...@@ -4117,7 +4117,7 @@ extern void print_candidates (tree);
extern void instantiate_pending_templates (int); extern void instantiate_pending_templates (int);
extern tree tsubst_default_argument (tree, tree, tree); extern tree tsubst_default_argument (tree, tree, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool); tree, bool, bool);
extern tree most_general_template (tree); extern tree most_general_template (tree);
extern tree get_mostly_instantiated_function_type (tree); extern tree get_mostly_instantiated_function_type (tree);
extern int problematic_instantiation_changed (void); extern int problematic_instantiation_changed (void);
...@@ -4391,6 +4391,7 @@ extern tree fold_if_not_in_template (tree); ...@@ -4391,6 +4391,7 @@ extern tree fold_if_not_in_template (tree);
extern tree rvalue (tree); extern tree rvalue (tree);
extern tree convert_bitfield_to_declared_type (tree); extern tree convert_bitfield_to_declared_type (tree);
extern tree cp_save_expr (tree); extern tree cp_save_expr (tree);
extern bool cast_valid_in_integral_constant_expression_p (tree);
/* in typeck.c */ /* in typeck.c */
extern int string_conv_p (tree, tree, int); extern int string_conv_p (tree, tree, int);
......
...@@ -4004,9 +4004,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) ...@@ -4004,9 +4004,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
/* Only type conversions to integral or enumeration types /* Only type conversions to integral or enumeration types
can be used in constant-expressions. */ can be used in constant-expressions. */
if (parser->integral_constant_expression_p if (!cast_valid_in_integral_constant_expression_p (type)
&& !dependent_type_p (type)
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
&& (cp_parser_non_integral_constant_expression && (cp_parser_non_integral_constant_expression
(parser, (parser,
"a cast to a type other than an integral or " "a cast to a type other than an integral or "
...@@ -5490,9 +5488,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) ...@@ -5490,9 +5488,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
/* Only type conversions to integral or enumeration types /* Only type conversions to integral or enumeration types
can be used in constant-expressions. */ can be used in constant-expressions. */
if (parser->integral_constant_expression_p if (!cast_valid_in_integral_constant_expression_p (type)
&& !dependent_type_p (type)
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
&& (cp_parser_non_integral_constant_expression && (cp_parser_non_integral_constant_expression
(parser, (parser,
"a cast to a type other than an integral or " "a cast to a type other than an integral or "
...@@ -15695,13 +15691,11 @@ cp_parser_functional_cast (cp_parser* parser, tree type) ...@@ -15695,13 +15691,11 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
conversions to integral or enumeration type can be used". */ conversions to integral or enumeration type can be used". */
if (TREE_CODE (type) == TYPE_DECL) if (TREE_CODE (type) == TYPE_DECL)
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (cast != error_mark_node && !dependent_type_p (type) if (cast != error_mark_node
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type)) && !cast_valid_in_integral_constant_expression_p (type)
{ && (cp_parser_non_integral_constant_expression
if (cp_parser_non_integral_constant_expression (parser, "a call to a constructor")))
(parser, "a call to a constructor"))
return error_mark_node; return error_mark_node;
}
return cast; return cast;
} }
......
...@@ -159,7 +159,7 @@ static int invalid_nontype_parm_type_p (tree, tsubst_flags_t); ...@@ -159,7 +159,7 @@ static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
static int eq_local_specializations (const void *, const void *); static int eq_local_specializations (const void *, const void *);
static bool dependent_type_p_r (tree); static bool dependent_type_p_r (tree);
static tree tsubst (tree, tree, tsubst_flags_t, tree); static tree tsubst (tree, tree, tsubst_flags_t, tree);
static tree tsubst_expr (tree, tree, tsubst_flags_t, tree); static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree); static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are /* Make the current scope suitable for access checking when we are
...@@ -3400,7 +3400,8 @@ fold_non_dependent_expr (tree expr) ...@@ -3400,7 +3400,8 @@ fold_non_dependent_expr (tree expr)
/*args=*/NULL_TREE, /*args=*/NULL_TREE,
tf_error, tf_error,
/*in_decl=*/NULL_TREE, /*in_decl=*/NULL_TREE,
/*function_p=*/false); /*function_p=*/false,
/*integral_constant_expression_p=*/true);
processing_template_decl = saved_processing_template_decl; processing_template_decl = saved_processing_template_decl;
} }
return expr; return expr;
...@@ -5225,7 +5226,8 @@ tsubst_friend_function (tree decl, tree args) ...@@ -5225,7 +5226,8 @@ tsubst_friend_function (tree decl, tree args)
current cless with same name. */ current cless with same name. */
push_nested_namespace (ns); push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args, fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
tf_warning_or_error, NULL_TREE); tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/false);
pop_nested_namespace (ns); pop_nested_namespace (ns);
arglist = tsubst (DECL_TI_ARGS (decl), args, arglist = tsubst (DECL_TI_ARGS (decl), args,
tf_warning_or_error, NULL_TREE); tf_warning_or_error, NULL_TREE);
...@@ -6035,7 +6037,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -6035,7 +6037,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
r = tsubst (t, args, complain, in_decl); r = tsubst (t, args, complain, in_decl);
else else
{ {
r = tsubst_expr (t, args, complain, in_decl); r = tsubst_expr (t, args, complain, in_decl,
/*integral_constant_expression_p=*/true);
r = fold_non_dependent_expr (r); r = fold_non_dependent_expr (r);
} }
return r; return r;
...@@ -6260,7 +6263,8 @@ tsubst_default_argument (tree fn, tree type, tree arg) ...@@ -6260,7 +6263,8 @@ tsubst_default_argument (tree fn, tree type, tree arg)
stack. */ stack. */
++function_depth; ++function_depth;
arg = tsubst_expr (arg, DECL_TI_ARGS (fn), arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_warning_or_error, NULL_TREE); tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/false);
--function_depth; --function_depth;
pop_deferring_access_checks(); pop_deferring_access_checks();
...@@ -6721,10 +6725,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -6721,10 +6725,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r); cp_apply_type_quals_to_decl (cp_type_quals (type), r);
/* DECL_INITIAL gives the number of bits in a bit-field. */
DECL_INITIAL (r)
= tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
/* We don't have to set DECL_CONTEXT here; it is set by /* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */ finish_member_declaration. */
DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl);
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type)) if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type); error ("instantiation of %q+D as type %qT", r, type);
...@@ -6852,7 +6859,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -6852,7 +6859,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (DECL_HAS_VALUE_EXPR_P (t)) if (DECL_HAS_VALUE_EXPR_P (t))
{ {
tree ve = DECL_VALUE_EXPR (t); tree ve = DECL_VALUE_EXPR (t);
ve = tsubst_expr (ve, args, complain, in_decl); ve = tsubst_expr (ve, args, complain, in_decl,
/*constant_expression_p=*/false);
SET_DECL_VALUE_EXPR (r, ve); SET_DECL_VALUE_EXPR (r, ve);
} }
} }
...@@ -7658,7 +7666,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7658,7 +7666,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case ARRAY_REF: case ARRAY_REF:
{ {
tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl); tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl); tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl,
/*integral_constant_expression_p=*/false);
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;
...@@ -7680,8 +7689,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7680,8 +7689,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{ {
tree type; tree type;
type = finish_typeof (tsubst_expr (TYPEOF_TYPE_EXPR (t), args, type = finish_typeof (tsubst_expr
complain, in_decl)); (TYPEOF_TYPE_EXPR (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/false));
return cp_build_qualified_type_real (type, return cp_build_qualified_type_real (type,
cp_type_quals (t) cp_type_quals (t)
| cp_type_quals (type), | cp_type_quals (type),
...@@ -7867,7 +7878,11 @@ tsubst_qualified_id (tree qualified_id, tree args, ...@@ -7867,7 +7878,11 @@ tsubst_qualified_id (tree qualified_id, tree args,
/*template_arg_p=*/false)); /*template_arg_p=*/false));
} }
if (TREE_CODE (expr) != SCOPE_REF) /* Expressions do not generally have reference type. */
if (TREE_CODE (expr) != SCOPE_REF
/* However, if we're about to form a pointer-to-member, we just
want the referenced member referenced. */
&& TREE_CODE (expr) != OFFSET_REF)
expr = convert_from_reference (expr); expr = convert_from_reference (expr);
return expr; return expr;
...@@ -8276,7 +8291,8 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain, ...@@ -8276,7 +8291,8 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE: case OMP_CLAUSE_SCHEDULE:
OMP_CLAUSE_OPERAND (nc, 0) OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl); = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break; break;
case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_ORDERED:
...@@ -8305,7 +8321,8 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain, ...@@ -8305,7 +8321,8 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
if (TREE_CODE (t) != TREE_LIST) if (TREE_CODE (t) != TREE_LIST)
return tsubst_copy_and_build (t, args, complain, in_decl, return tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false); /*function_p=*/false,
/*integral_constant_expression_p=*/false);
if (t == void_list_node) if (t == void_list_node)
return t; return t;
...@@ -8327,8 +8344,13 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain, ...@@ -8327,8 +8344,13 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
processing. */ processing. */
static tree static tree
tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
bool integral_constant_expression_p)
{ {
#define RECUR(NODE) \
tsubst_expr ((NODE), args, complain, in_decl, \
integral_constant_expression_p)
tree stmt, tmp; tree stmt, tmp;
if (t == NULL_TREE || t == error_mark_node) if (t == NULL_TREE || t == error_mark_node)
...@@ -8345,7 +8367,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8345,7 +8367,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{ {
tree_stmt_iterator i; tree_stmt_iterator i;
for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
tsubst_expr (tsi_stmt (i), args, complain, in_decl); RECUR (tsi_stmt (i));
break; break;
} }
...@@ -8355,12 +8377,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8355,12 +8377,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break; break;
case RETURN_EXPR: case RETURN_EXPR:
finish_return_stmt (tsubst_expr (TREE_OPERAND (t, 0), finish_return_stmt (RECUR (TREE_OPERAND (t, 0)));
args, complain, in_decl));
break; break;
case EXPR_STMT: case EXPR_STMT:
tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl); tmp = RECUR (EXPR_STMT_EXPR (t));
if (EXPR_STMT_STMT_EXPR_RESULT (t)) if (EXPR_STMT_STMT_EXPR_RESULT (t))
finish_stmt_expr_expr (tmp, cur_stmt_expr); finish_stmt_expr_expr (tmp, cur_stmt_expr);
else else
...@@ -8368,8 +8389,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8368,8 +8389,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break; break;
case USING_STMT: case USING_STMT:
do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t), do_using_directive (RECUR (USING_STMT_NAMESPACE (t)));
args, complain, in_decl));
break; break;
case DECL_EXPR: case DECL_EXPR:
...@@ -8386,7 +8406,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8386,7 +8406,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tree name = DECL_NAME (decl); tree name = DECL_NAME (decl);
tree decl; tree decl;
scope = tsubst_expr (scope, args, complain, in_decl); scope = RECUR (scope);
decl = lookup_qualified_name (scope, name, decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false, /*is_type_p=*/false,
/*complain=*/false); /*complain=*/false);
...@@ -8425,7 +8445,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8425,7 +8445,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
init = cp_fname_init (name, &TREE_TYPE (decl)); init = cp_fname_init (name, &TREE_TYPE (decl));
} }
else else
init = tsubst_expr (init, args, complain, in_decl); init = RECUR (init);
finish_decl (decl, init, NULL_TREE); finish_decl (decl, init, NULL_TREE);
} }
} }
...@@ -8438,43 +8458,43 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8438,43 +8458,43 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case FOR_STMT: case FOR_STMT:
stmt = begin_for_stmt (); stmt = begin_for_stmt ();
tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl); RECUR (FOR_INIT_STMT (t));
finish_for_init_stmt (stmt); finish_for_init_stmt (stmt);
tmp = tsubst_expr (FOR_COND (t), args, complain, in_decl); tmp = RECUR (FOR_COND (t));
finish_for_cond (tmp, stmt); finish_for_cond (tmp, stmt);
tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl); tmp = RECUR (FOR_EXPR (t));
finish_for_expr (tmp, stmt); finish_for_expr (tmp, stmt);
tsubst_expr (FOR_BODY (t), args, complain, in_decl); RECUR (FOR_BODY (t));
finish_for_stmt (stmt); finish_for_stmt (stmt);
break; break;
case WHILE_STMT: case WHILE_STMT:
stmt = begin_while_stmt (); stmt = begin_while_stmt ();
tmp = tsubst_expr (WHILE_COND (t), args, complain, in_decl); tmp = RECUR (WHILE_COND (t));
finish_while_stmt_cond (tmp, stmt); finish_while_stmt_cond (tmp, stmt);
tsubst_expr (WHILE_BODY (t), args, complain, in_decl); RECUR (WHILE_BODY (t));
finish_while_stmt (stmt); finish_while_stmt (stmt);
break; break;
case DO_STMT: case DO_STMT:
stmt = begin_do_stmt (); stmt = begin_do_stmt ();
tsubst_expr (DO_BODY (t), args, complain, in_decl); RECUR (DO_BODY (t));
finish_do_body (stmt); finish_do_body (stmt);
tmp = tsubst_expr (DO_COND (t), args, complain, in_decl); tmp = RECUR (DO_COND (t));
finish_do_stmt (tmp, stmt); finish_do_stmt (tmp, stmt);
break; break;
case IF_STMT: case IF_STMT:
stmt = begin_if_stmt (); stmt = begin_if_stmt ();
tmp = tsubst_expr (IF_COND (t), args, complain, in_decl); tmp = RECUR (IF_COND (t));
finish_if_stmt_cond (tmp, stmt); finish_if_stmt_cond (tmp, stmt);
tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl); RECUR (THEN_CLAUSE (t));
finish_then_clause (stmt); finish_then_clause (stmt);
if (ELSE_CLAUSE (t)) if (ELSE_CLAUSE (t))
{ {
begin_else_clause (stmt); begin_else_clause (stmt);
tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl); RECUR (ELSE_CLAUSE (t));
finish_else_clause (stmt); finish_else_clause (stmt);
} }
...@@ -8488,7 +8508,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8488,7 +8508,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
stmt = begin_compound_stmt (BIND_EXPR_TRY_BLOCK (t) stmt = begin_compound_stmt (BIND_EXPR_TRY_BLOCK (t)
? BCS_TRY_BLOCK : 0); ? BCS_TRY_BLOCK : 0);
tsubst_expr (BIND_EXPR_BODY (t), args, complain, in_decl); RECUR (BIND_EXPR_BODY (t));
if (BIND_EXPR_BODY_BLOCK (t)) if (BIND_EXPR_BODY_BLOCK (t))
finish_function_body (stmt); finish_function_body (stmt);
...@@ -8506,16 +8526,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8506,16 +8526,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case SWITCH_STMT: case SWITCH_STMT:
stmt = begin_switch_stmt (); stmt = begin_switch_stmt ();
tmp = tsubst_expr (SWITCH_STMT_COND (t), args, complain, in_decl); tmp = RECUR (SWITCH_STMT_COND (t));
finish_switch_cond (tmp, stmt); finish_switch_cond (tmp, stmt);
tsubst_expr (SWITCH_STMT_BODY (t), args, complain, in_decl); RECUR (SWITCH_STMT_BODY (t));
finish_switch_stmt (stmt); finish_switch_stmt (stmt);
break; break;
case CASE_LABEL_EXPR: case CASE_LABEL_EXPR:
finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl), finish_case_label (RECUR (CASE_LOW (t)),
tsubst_expr (CASE_HIGH (t), args, complain, RECUR (CASE_HIGH (t)));
in_decl));
break; break;
case LABEL_EXPR: case LABEL_EXPR:
...@@ -8528,7 +8547,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8528,7 +8547,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* Computed goto's must be tsubst'd into. On the other hand, /* Computed goto's must be tsubst'd into. On the other hand,
non-computed gotos must not be; the identifier in question non-computed gotos must not be; the identifier in question
will have no binding. */ will have no binding. */
tmp = tsubst_expr (tmp, args, complain, in_decl); tmp = RECUR (tmp);
else else
tmp = DECL_NAME (tmp); tmp = DECL_NAME (tmp);
finish_goto_stmt (tmp); finish_goto_stmt (tmp);
...@@ -8537,7 +8556,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8537,7 +8556,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case ASM_EXPR: case ASM_EXPR:
tmp = finish_asm_stmt tmp = finish_asm_stmt
(ASM_VOLATILE_P (t), (ASM_VOLATILE_P (t),
tsubst_expr (ASM_STRING (t), args, complain, in_decl), RECUR (ASM_STRING (t)),
tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl), tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl), tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl)); tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl));
...@@ -8553,11 +8572,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8553,11 +8572,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (CLEANUP_P (t)) if (CLEANUP_P (t))
{ {
stmt = begin_try_block (); stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl); RECUR (TRY_STMTS (t));
finish_cleanup_try_block (stmt); finish_cleanup_try_block (stmt);
finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args, finish_cleanup (RECUR (TRY_HANDLERS (t)), stmt);
complain, in_decl),
stmt);
} }
else else
{ {
...@@ -8568,14 +8585,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8568,14 +8585,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else else
stmt = begin_try_block (); stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl); RECUR (TRY_STMTS (t));
if (FN_TRY_BLOCK_P (t)) if (FN_TRY_BLOCK_P (t))
finish_function_try_block (stmt); finish_function_try_block (stmt);
else else
finish_try_block (stmt); finish_try_block (stmt);
tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl); RECUR (TRY_HANDLERS (t));
if (FN_TRY_BLOCK_P (t)) if (FN_TRY_BLOCK_P (t))
finish_function_handler_sequence (stmt, compound_stmt); finish_function_handler_sequence (stmt, compound_stmt);
else else
...@@ -8598,7 +8615,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8598,7 +8615,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
} }
stmt = begin_handler (); stmt = begin_handler ();
finish_handler_parms (decl, stmt); finish_handler_parms (decl, stmt);
tsubst_expr (HANDLER_BODY (t), args, complain, in_decl); RECUR (HANDLER_BODY (t));
finish_handler (stmt); finish_handler (stmt);
} }
break; break;
...@@ -8611,7 +8628,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8611,7 +8628,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
args, complain, in_decl); args, complain, in_decl);
stmt = begin_omp_parallel (); stmt = begin_omp_parallel ();
tsubst_expr (OMP_PARALLEL_BODY (t), args, complain, in_decl); RECUR (OMP_PARALLEL_BODY (t));
OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt)) OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt))
= OMP_PARALLEL_COMBINED (t); = OMP_PARALLEL_COMBINED (t);
break; break;
...@@ -8624,19 +8641,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8624,19 +8641,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
args, complain, in_decl); args, complain, in_decl);
init = OMP_FOR_INIT (t); init = OMP_FOR_INIT (t);
gcc_assert (TREE_CODE (init) == MODIFY_EXPR); gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
decl = tsubst_expr (TREE_OPERAND (init, 0), args, complain, in_decl); decl = RECUR (TREE_OPERAND (init, 0));
init = tsubst_expr (TREE_OPERAND (init, 1), args, complain, in_decl); init = RECUR (TREE_OPERAND (init, 1));
cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl); cond = RECUR (OMP_FOR_COND (t));
incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl); incr = RECUR (OMP_FOR_INCR (t));
stmt = begin_omp_structured_block (); stmt = begin_omp_structured_block ();
pre_body = push_stmt_list (); pre_body = push_stmt_list ();
tsubst_expr (OMP_FOR_PRE_BODY (t), args, complain, in_decl); RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body); pre_body = pop_stmt_list (pre_body);
body = push_stmt_list (); body = push_stmt_list ();
tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl); RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body); body = pop_stmt_list (body);
t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body, t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
...@@ -8652,7 +8669,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8652,7 +8669,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case OMP_SINGLE: case OMP_SINGLE:
tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl); tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
stmt = push_stmt_list (); stmt = push_stmt_list ();
tsubst_expr (OMP_BODY (t), args, complain, in_decl); RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt); stmt = pop_stmt_list (stmt);
t = copy_node (t); t = copy_node (t);
...@@ -8666,7 +8683,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8666,7 +8683,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case OMP_MASTER: case OMP_MASTER:
case OMP_ORDERED: case OMP_ORDERED:
stmt = push_stmt_list (); stmt = push_stmt_list ();
tsubst_expr (OMP_BODY (t), args, complain, in_decl); RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt); stmt = pop_stmt_list (stmt);
t = copy_node (t); t = copy_node (t);
...@@ -8677,8 +8694,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8677,8 +8694,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case OMP_ATOMIC: case OMP_ATOMIC:
{ {
tree op0, op1; tree op0, op1;
op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl); op0 = RECUR (TREE_OPERAND (t, 0));
op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl); op1 = RECUR (TREE_OPERAND (t, 1));
finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1); finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
} }
break; break;
...@@ -8687,10 +8704,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8687,10 +8704,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t))); gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
return tsubst_copy_and_build (t, args, complain, in_decl, return tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false); /*function_p=*/false,
integral_constant_expression_p);
} }
return NULL_TREE; return NULL_TREE;
#undef RECUR
} }
/* T is a postfix-expression that is not being used in a function /* T is a postfix-expression that is not being used in a function
...@@ -8706,7 +8725,8 @@ tsubst_non_call_postfix_expression (tree t, tree args, ...@@ -8706,7 +8725,8 @@ tsubst_non_call_postfix_expression (tree t, tree args,
/*done=*/false, /*address_p=*/false); /*done=*/false, /*address_p=*/false);
else else
t = tsubst_copy_and_build (t, args, complain, in_decl, t = tsubst_copy_and_build (t, args, complain, in_decl,
/*function_p=*/false); /*function_p=*/false,
/*integral_constant_expression_p=*/false);
return t; return t;
} }
...@@ -8719,10 +8739,13 @@ tsubst_copy_and_build (tree t, ...@@ -8719,10 +8739,13 @@ tsubst_copy_and_build (tree t,
tree args, tree args,
tsubst_flags_t complain, tsubst_flags_t complain,
tree in_decl, tree in_decl,
bool function_p) bool function_p,
bool integral_constant_expression_p)
{ {
#define RECUR(NODE) \ #define RECUR(NODE) \
tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false) tsubst_copy_and_build (NODE, args, complain, in_decl, \
/*function_p=*/false, \
integral_constant_expression_p)
tree op1; tree op1;
...@@ -8757,7 +8780,7 @@ tsubst_copy_and_build (tree t, ...@@ -8757,7 +8780,7 @@ tsubst_copy_and_build (tree t,
decl = finish_id_expression (t, decl, NULL_TREE, decl = finish_id_expression (t, decl, NULL_TREE,
&idk, &idk,
/*integral_constant_expression_p=*/false, integral_constant_expression_p,
/*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, /*template_p=*/false,
...@@ -8820,29 +8843,41 @@ tsubst_copy_and_build (tree t, ...@@ -8820,29 +8843,41 @@ tsubst_copy_and_build (tree t,
RECUR (TREE_OPERAND (t, 0))); RECUR (TREE_OPERAND (t, 0)));
case CAST_EXPR: case CAST_EXPR:
return build_functional_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
RECUR (TREE_OPERAND (t, 0)));
case REINTERPRET_CAST_EXPR: case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
RECUR (TREE_OPERAND (t, 0)));
case CONST_CAST_EXPR: case CONST_CAST_EXPR:
return build_const_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
RECUR (TREE_OPERAND (t, 0)));
case DYNAMIC_CAST_EXPR: case DYNAMIC_CAST_EXPR:
return build_dynamic_cast case STATIC_CAST_EXPR:
(tsubst (TREE_TYPE (t), args, complain, in_decl), {
RECUR (TREE_OPERAND (t, 0))); tree type;
tree op;
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (integral_constant_expression_p
&& !cast_valid_in_integral_constant_expression_p (type))
{
error ("a cast to a type other than an integral or "
"enumeration type cannot appear in a constant-expression");
return error_mark_node;
}
op = RECUR (TREE_OPERAND (t, 0));
switch (TREE_CODE (t))
{
case CAST_EXPR:
return build_functional_cast (type, op);
case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast (type, op);
case CONST_CAST_EXPR:
return build_const_cast (type, op);
case DYNAMIC_CAST_EXPR:
return build_dynamic_cast (type, op);
case STATIC_CAST_EXPR: case STATIC_CAST_EXPR:
return build_static_cast return build_static_cast (type, op);
(tsubst (TREE_TYPE (t), args, complain, in_decl), default:
RECUR (TREE_OPERAND (t, 0))); gcc_unreachable ();
}
}
case POSTDECREMENT_EXPR: case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR: case POSTINCREMENT_EXPR:
...@@ -8933,7 +8968,9 @@ tsubst_copy_and_build (tree t, ...@@ -8933,7 +8968,9 @@ tsubst_copy_and_build (tree t,
else else
{ {
++skip_evaluation; ++skip_evaluation;
op1 = RECUR (op1); op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
/*function_p=*/false,
/*integral_constant_expression_p=*/false);
--skip_evaluation; --skip_evaluation;
} }
if (TYPE_P (op1)) if (TYPE_P (op1))
...@@ -9018,7 +9055,9 @@ tsubst_copy_and_build (tree t, ...@@ -9018,7 +9055,9 @@ tsubst_copy_and_build (tree t,
function = tsubst_copy_and_build (function, args, complain, function = tsubst_copy_and_build (function, args, complain,
in_decl, in_decl,
!qualified_p); !qualified_p,
integral_constant_expression_p);
if (BASELINK_P (function)) if (BASELINK_P (function))
qualified_p = true; qualified_p = true;
} }
...@@ -9267,7 +9306,8 @@ tsubst_copy_and_build (tree t, ...@@ -9267,7 +9306,8 @@ tsubst_copy_and_build (tree t,
tree stmt_expr = begin_stmt_expr (); tree stmt_expr = begin_stmt_expr ();
cur_stmt_expr = stmt_expr; cur_stmt_expr = stmt_expr;
tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl); tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
integral_constant_expression_p);
stmt_expr = finish_stmt_expr (stmt_expr, false); stmt_expr = finish_stmt_expr (stmt_expr, false);
cur_stmt_expr = old_stmt_expr; cur_stmt_expr = old_stmt_expr;
...@@ -11751,7 +11791,8 @@ regenerate_decl_from_template (tree decl, tree tmpl) ...@@ -11751,7 +11791,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
else if (TREE_CODE (decl) == VAR_DECL) else if (TREE_CODE (decl) == VAR_DECL)
DECL_INITIAL (decl) = DECL_INITIAL (decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args, tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl)); tf_error, DECL_TI_TEMPLATE (decl),
/*integral_constant_expression_p=*/false);
else else
gcc_unreachable (); gcc_unreachable ();
...@@ -12000,7 +12041,8 @@ instantiate_decl (tree d, int defer_ok, ...@@ -12000,7 +12041,8 @@ instantiate_decl (tree d, int defer_ok,
push_nested_class (DECL_CONTEXT (d)); push_nested_class (DECL_CONTEXT (d));
init = tsubst_expr (DECL_INITIAL (code_pattern), init = tsubst_expr (DECL_INITIAL (code_pattern),
args, args,
tf_warning_or_error, NULL_TREE); tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/false);
cp_finish_decl (d, init, /*init_const_expr_p=*/false, cp_finish_decl (d, init, /*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
LOOKUP_ONLYCONVERTING); LOOKUP_ONLYCONVERTING);
...@@ -12131,7 +12173,8 @@ instantiate_decl (tree d, int defer_ok, ...@@ -12131,7 +12173,8 @@ instantiate_decl (tree d, int defer_ok,
/* Substitute into the body of the function. */ /* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args, tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
tf_warning_or_error, tmpl); tf_warning_or_error, tmpl,
/*integral_constant_expression_p=*/false);
/* We don't need the local specializations any more. */ /* We don't need the local specializations any more. */
htab_delete (local_specializations); htab_delete (local_specializations);
...@@ -12285,7 +12328,8 @@ tsubst_initializer_list (tree t, tree argvec) ...@@ -12285,7 +12328,8 @@ tsubst_initializer_list (tree t, tree argvec)
in_base_initializer = 1; in_base_initializer = 1;
init = tsubst_expr (TREE_VALUE (t), argvec, tf_warning_or_error, init = tsubst_expr (TREE_VALUE (t), argvec, tf_warning_or_error,
NULL_TREE); NULL_TREE,
/*integral_constant_expression_p=*/false);
in_base_initializer = 0; in_base_initializer = 0;
if (decl) if (decl)
...@@ -12329,7 +12373,8 @@ tsubst_enum (tree tag, tree newtag, tree args) ...@@ -12329,7 +12373,8 @@ tsubst_enum (tree tag, tree newtag, tree args)
/* Note that in a template enum, the TREE_VALUE is the /* Note that in a template enum, the TREE_VALUE is the
CONST_DECL, not the corresponding INTEGER_CST. */ CONST_DECL, not the corresponding INTEGER_CST. */
value = tsubst_expr (DECL_INITIAL (decl), value = tsubst_expr (DECL_INITIAL (decl),
args, tf_warning_or_error, NULL_TREE); args, tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/true);
/* Give this enumeration constant the correct access. */ /* Give this enumeration constant the correct access. */
set_current_access_from_decl (decl); set_current_access_from_decl (decl);
......
...@@ -2376,6 +2376,17 @@ fold_if_not_in_template (tree expr) ...@@ -2376,6 +2376,17 @@ fold_if_not_in_template (tree expr)
return fold (expr); return fold (expr);
} }
/* Returns true if a cast to TYPE may appear in an integral constant
expression. */
bool
cast_valid_in_integral_constant_expression_p (tree type)
{
return (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
|| dependent_type_p (type)
|| type == error_mark_node);
}
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree /* Complain that some language-specific thing hanging off a tree
......
2006-08-20 Mark Mitchell <mark@codesourcery.com>
* objcp-lang.c (objcp_tsubst_copy_and_build): Adjust call to
tsubst_copy_and_build.
2006-07-28 Volker Reichelt <reichelt@igpm.rwth-aachen.de> 2006-07-28 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
* Make-lang.in: Use $(HEADER_H) instead of header.h in dependencies. * Make-lang.in: Use $(HEADER_H) instead of header.h in dependencies.
......
...@@ -111,7 +111,9 @@ objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, ...@@ -111,7 +111,9 @@ objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain,
tree in_decl, bool function_p ATTRIBUTE_UNUSED) tree in_decl, bool function_p ATTRIBUTE_UNUSED)
{ {
#define RECURSE(NODE) \ #define RECURSE(NODE) \
tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false) tsubst_copy_and_build (NODE, args, complain, in_decl, \
/*function_p=*/false, \
/*integral_constant_expression_p=*/false)
/* The following two can only occur in Objective-C++. */ /* The following two can only occur in Objective-C++. */
......
2006-08-20 Mark Mitchell <mark@codesourcery.com>
PR c++/28341
* g++.dg/template/ref3.C: New test.
* g++.dg/template/nontype13.C: New test.
PR c++/28346
* g++.dg/template/ptrmem17.C: New test.
2006-08-20 Danny Smith <dannysmith@users.sourceforge.net> 2006-08-20 Danny Smith <dannysmith@users.sourceforge.net>
PR target/28648 c: PR target/28648 c:
...@@ -11,7 +11,7 @@ struct Dummy ...@@ -11,7 +11,7 @@ struct Dummy
template<bool B> template<bool B>
void tester() void tester()
{ {
bar<evil>()(); // { dg-error "argument" } bar<evil>()(); // { dg-error "constant" }
} }
template<bool B> template<bool B>
struct bar struct bar
......
// PR c++/28346
template<int> struct A
{
int& i;
A();
~A() { &A::i; } // { dg-error "reference" }
};
A<0> a; // { dg-error "instantiated" }
// PR c++/28341
template<const int&> struct A {};
template<typename T> struct B
{
A<(T)0> b; // { dg-error "constant" }
A<T(0)> a; // { dg-error "constant" }
};
B<const int&> b;
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