From bde9ebf7cf3d5d60b007f9fd1bce8b04eb32dd68 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Sun, 20 Aug 2006 23:53:10 +0000 Subject: [PATCH] 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 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 * objcp-lang.c (objcp_tsubst_copy_and_build): Adjust call to tsubst_copy_and_build. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116276 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 32 +++++ gcc/cp/cp-tree.h | 3 +- gcc/cp/parser.c | 20 +-- gcc/cp/pt.c | 231 ++++++++++++++++++------------ gcc/cp/tree.c | 11 ++ gcc/objcp/ChangeLog | 5 + gcc/objcp/objcp-lang.c | 6 +- gcc/testsuite/ChangeLog | 9 ++ gcc/testsuite/g++.dg/template/nontype13.C | 2 +- gcc/testsuite/g++.dg/template/ptrmem17.C | 10 ++ gcc/testsuite/g++.dg/template/ref3.C | 11 ++ 11 files changed, 230 insertions(+), 110 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/ptrmem17.C create mode 100644 gcc/testsuite/g++.dg/template/ref3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8f767b06cd9..6fd125ab1d4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,35 @@ +2006-08-20 Mark Mitchell + + 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 PR c++/28606 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 040dd90dff8..79018a40878 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4117,7 +4117,7 @@ extern void print_candidates (tree); extern void instantiate_pending_templates (int); extern tree tsubst_default_argument (tree, tree, tree); extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, - tree, bool); + tree, bool, bool); extern tree most_general_template (tree); extern tree get_mostly_instantiated_function_type (tree); extern int problematic_instantiation_changed (void); @@ -4391,6 +4391,7 @@ extern tree fold_if_not_in_template (tree); extern tree rvalue (tree); extern tree convert_bitfield_to_declared_type (tree); extern tree cp_save_expr (tree); +extern bool cast_valid_in_integral_constant_expression_p (tree); /* in typeck.c */ extern int string_conv_p (tree, tree, int); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 78e6eb69d55..d015ae1d7a1 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 can be used in constant-expressions. */ - if (parser->integral_constant_expression_p - && !dependent_type_p (type) - && !INTEGRAL_OR_ENUMERATION_TYPE_P (type) + if (!cast_valid_in_integral_constant_expression_p (type) && (cp_parser_non_integral_constant_expression (parser, "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) /* Only type conversions to integral or enumeration types can be used in constant-expressions. */ - if (parser->integral_constant_expression_p - && !dependent_type_p (type) - && !INTEGRAL_OR_ENUMERATION_TYPE_P (type) + if (!cast_valid_in_integral_constant_expression_p (type) && (cp_parser_non_integral_constant_expression (parser, "a cast to a type other than an integral or " @@ -15695,13 +15691,11 @@ cp_parser_functional_cast (cp_parser* parser, tree type) conversions to integral or enumeration type can be used". */ if (TREE_CODE (type) == TYPE_DECL) type = TREE_TYPE (type); - if (cast != error_mark_node && !dependent_type_p (type) - && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)) - { - if (cp_parser_non_integral_constant_expression - (parser, "a call to a constructor")) - return error_mark_node; - } + if (cast != error_mark_node + && !cast_valid_in_integral_constant_expression_p (type) + && (cp_parser_non_integral_constant_expression + (parser, "a call to a constructor"))) + return error_mark_node; return cast; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c9e28c85b1c..4a58ef3cb6d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 bool dependent_type_p_r (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); /* Make the current scope suitable for access checking when we are @@ -3400,7 +3400,8 @@ fold_non_dependent_expr (tree expr) /*args=*/NULL_TREE, tf_error, /*in_decl=*/NULL_TREE, - /*function_p=*/false); + /*function_p=*/false, + /*integral_constant_expression_p=*/true); processing_template_decl = saved_processing_template_decl; } return expr; @@ -5225,7 +5226,8 @@ tsubst_friend_function (tree decl, tree args) current cless with same name. */ push_nested_namespace (ns); 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); arglist = tsubst (DECL_TI_ARGS (decl), args, tf_warning_or_error, NULL_TREE); @@ -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); 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); } return r; @@ -6260,7 +6263,8 @@ tsubst_default_argument (tree fn, tree type, tree arg) stack. */ ++function_depth; 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; pop_deferring_access_checks(); @@ -6721,10 +6725,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) TREE_TYPE (r) = type; 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 finish_member_declaration. */ - DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, - complain, in_decl); TREE_CHAIN (r) = NULL_TREE; if (VOID_TYPE_P (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) if (DECL_HAS_VALUE_EXPR_P (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); } } @@ -7658,7 +7666,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) case ARRAY_REF: { 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) return error_mark_node; @@ -7680,8 +7689,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { tree type; - type = finish_typeof (tsubst_expr (TYPEOF_TYPE_EXPR (t), args, - complain, in_decl)); + type = finish_typeof (tsubst_expr + (TYPEOF_TYPE_EXPR (t), args, + complain, in_decl, + /*integral_constant_expression_p=*/false)); return cp_build_qualified_type_real (type, cp_type_quals (t) | cp_type_quals (type), @@ -7867,7 +7878,11 @@ tsubst_qualified_id (tree qualified_id, tree args, /*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); return expr; @@ -8276,7 +8291,8 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain, case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_SCHEDULE: 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; case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: @@ -8305,7 +8321,8 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain, if (TREE_CODE (t) != TREE_LIST) 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) return t; @@ -8327,8 +8344,13 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain, processing. */ 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; 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) { tree_stmt_iterator 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; } @@ -8355,12 +8377,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) break; case RETURN_EXPR: - finish_return_stmt (tsubst_expr (TREE_OPERAND (t, 0), - args, complain, in_decl)); + finish_return_stmt (RECUR (TREE_OPERAND (t, 0))); break; 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)) finish_stmt_expr_expr (tmp, cur_stmt_expr); else @@ -8368,8 +8389,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) break; case USING_STMT: - do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t), - args, complain, in_decl)); + do_using_directive (RECUR (USING_STMT_NAMESPACE (t))); break; case DECL_EXPR: @@ -8386,7 +8406,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree name = DECL_NAME (decl); tree decl; - scope = tsubst_expr (scope, args, complain, in_decl); + scope = RECUR (scope); decl = lookup_qualified_name (scope, name, /*is_type_p=*/false, /*complain=*/false); @@ -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)); } else - init = tsubst_expr (init, args, complain, in_decl); + init = RECUR (init); finish_decl (decl, init, NULL_TREE); } } @@ -8438,43 +8458,43 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case 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); - tmp = tsubst_expr (FOR_COND (t), args, complain, in_decl); + tmp = RECUR (FOR_COND (t)); 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); - tsubst_expr (FOR_BODY (t), args, complain, in_decl); + RECUR (FOR_BODY (t)); finish_for_stmt (stmt); break; case 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); - tsubst_expr (WHILE_BODY (t), args, complain, in_decl); + RECUR (WHILE_BODY (t)); finish_while_stmt (stmt); break; case DO_STMT: stmt = begin_do_stmt (); - tsubst_expr (DO_BODY (t), args, complain, in_decl); + RECUR (DO_BODY (t)); finish_do_body (stmt); - tmp = tsubst_expr (DO_COND (t), args, complain, in_decl); + tmp = RECUR (DO_COND (t)); finish_do_stmt (tmp, stmt); break; case 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); - tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl); + RECUR (THEN_CLAUSE (t)); finish_then_clause (stmt); if (ELSE_CLAUSE (t)) { begin_else_clause (stmt); - tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl); + RECUR (ELSE_CLAUSE (t)); finish_else_clause (stmt); } @@ -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) ? 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)) finish_function_body (stmt); @@ -8506,16 +8526,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case 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); - tsubst_expr (SWITCH_STMT_BODY (t), args, complain, in_decl); + RECUR (SWITCH_STMT_BODY (t)); finish_switch_stmt (stmt); break; case CASE_LABEL_EXPR: - finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl), - tsubst_expr (CASE_HIGH (t), args, complain, - in_decl)); + finish_case_label (RECUR (CASE_LOW (t)), + RECUR (CASE_HIGH (t))); break; case LABEL_EXPR: @@ -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, non-computed gotos must not be; the identifier in question will have no binding. */ - tmp = tsubst_expr (tmp, args, complain, in_decl); + tmp = RECUR (tmp); else tmp = DECL_NAME (tmp); finish_goto_stmt (tmp); @@ -8537,7 +8556,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case ASM_EXPR: tmp = finish_asm_stmt (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_INPUTS (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) if (CLEANUP_P (t)) { stmt = begin_try_block (); - tsubst_expr (TRY_STMTS (t), args, complain, in_decl); + RECUR (TRY_STMTS (t)); finish_cleanup_try_block (stmt); - finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args, - complain, in_decl), - stmt); + finish_cleanup (RECUR (TRY_HANDLERS (t)), stmt); } else { @@ -8568,14 +8585,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) else stmt = begin_try_block (); - tsubst_expr (TRY_STMTS (t), args, complain, in_decl); + RECUR (TRY_STMTS (t)); if (FN_TRY_BLOCK_P (t)) finish_function_try_block (stmt); else finish_try_block (stmt); - tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl); + RECUR (TRY_HANDLERS (t)); if (FN_TRY_BLOCK_P (t)) finish_function_handler_sequence (stmt, compound_stmt); else @@ -8598,7 +8615,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) } stmt = begin_handler (); finish_handler_parms (decl, stmt); - tsubst_expr (HANDLER_BODY (t), args, complain, in_decl); + RECUR (HANDLER_BODY (t)); finish_handler (stmt); } break; @@ -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), args, complain, in_decl); 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 (t); break; @@ -8624,19 +8641,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) args, complain, in_decl); init = OMP_FOR_INIT (t); gcc_assert (TREE_CODE (init) == MODIFY_EXPR); - decl = tsubst_expr (TREE_OPERAND (init, 0), args, complain, in_decl); - init = tsubst_expr (TREE_OPERAND (init, 1), args, complain, in_decl); - cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl); - incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl); + decl = RECUR (TREE_OPERAND (init, 0)); + init = RECUR (TREE_OPERAND (init, 1)); + cond = RECUR (OMP_FOR_COND (t)); + incr = RECUR (OMP_FOR_INCR (t)); stmt = begin_omp_structured_block (); 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); body = push_stmt_list (); - tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl); + RECUR (OMP_FOR_BODY (t)); body = pop_stmt_list (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) case OMP_SINGLE: tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl); stmt = push_stmt_list (); - tsubst_expr (OMP_BODY (t), args, complain, in_decl); + RECUR (OMP_BODY (t)); stmt = pop_stmt_list (stmt); t = copy_node (t); @@ -8666,7 +8683,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case OMP_MASTER: case OMP_ORDERED: stmt = push_stmt_list (); - tsubst_expr (OMP_BODY (t), args, complain, in_decl); + RECUR (OMP_BODY (t)); stmt = pop_stmt_list (stmt); t = copy_node (t); @@ -8677,8 +8694,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case OMP_ATOMIC: { tree op0, op1; - op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl); - op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl); + op0 = RECUR (TREE_OPERAND (t, 0)); + op1 = RECUR (TREE_OPERAND (t, 1)); finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1); } break; @@ -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))); return tsubst_copy_and_build (t, args, complain, in_decl, - /*function_p=*/false); + /*function_p=*/false, + integral_constant_expression_p); } return NULL_TREE; +#undef RECUR } /* 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, /*done=*/false, /*address_p=*/false); else t = tsubst_copy_and_build (t, args, complain, in_decl, - /*function_p=*/false); + /*function_p=*/false, + /*integral_constant_expression_p=*/false); return t; } @@ -8719,10 +8739,13 @@ tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, tree in_decl, - bool function_p) + bool function_p, + bool integral_constant_expression_p) { -#define RECUR(NODE) \ - tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false) +#define RECUR(NODE) \ + tsubst_copy_and_build (NODE, args, complain, in_decl, \ + /*function_p=*/false, \ + integral_constant_expression_p) tree op1; @@ -8757,7 +8780,7 @@ tsubst_copy_and_build (tree t, decl = finish_id_expression (t, decl, NULL_TREE, &idk, - /*integral_constant_expression_p=*/false, + integral_constant_expression_p, /*allow_non_integral_constant_expression_p=*/false, &non_integral_constant_expression_p, /*template_p=*/false, @@ -8820,29 +8843,41 @@ tsubst_copy_and_build (tree t, RECUR (TREE_OPERAND (t, 0))); case CAST_EXPR: - return build_functional_cast - (tsubst (TREE_TYPE (t), args, complain, in_decl), - RECUR (TREE_OPERAND (t, 0))); - 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: - return build_const_cast - (tsubst (TREE_TYPE (t), args, complain, in_decl), - RECUR (TREE_OPERAND (t, 0))); - case DYNAMIC_CAST_EXPR: - return build_dynamic_cast - (tsubst (TREE_TYPE (t), args, complain, in_decl), - RECUR (TREE_OPERAND (t, 0))); - case STATIC_CAST_EXPR: - return build_static_cast - (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: + return build_static_cast (type, op); + default: + gcc_unreachable (); + } + } case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: @@ -8933,7 +8968,9 @@ tsubst_copy_and_build (tree t, else { ++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; } if (TYPE_P (op1)) @@ -9018,7 +9055,9 @@ tsubst_copy_and_build (tree t, function = tsubst_copy_and_build (function, args, complain, in_decl, - !qualified_p); + !qualified_p, + integral_constant_expression_p); + if (BASELINK_P (function)) qualified_p = true; } @@ -9267,7 +9306,8 @@ tsubst_copy_and_build (tree t, tree stmt_expr = begin_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); cur_stmt_expr = old_stmt_expr; @@ -11751,7 +11791,8 @@ regenerate_decl_from_template (tree decl, tree tmpl) else if (TREE_CODE (decl) == VAR_DECL) DECL_INITIAL (decl) = 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 gcc_unreachable (); @@ -12000,7 +12041,8 @@ instantiate_decl (tree d, int defer_ok, push_nested_class (DECL_CONTEXT (d)); init = tsubst_expr (DECL_INITIAL (code_pattern), 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, /*asmspec_tree=*/NULL_TREE, LOOKUP_ONLYCONVERTING); @@ -12131,7 +12173,8 @@ instantiate_decl (tree d, int defer_ok, /* Substitute into the body of the function. */ 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. */ htab_delete (local_specializations); @@ -12285,7 +12328,8 @@ tsubst_initializer_list (tree t, tree argvec) in_base_initializer = 1; init = tsubst_expr (TREE_VALUE (t), argvec, tf_warning_or_error, - NULL_TREE); + NULL_TREE, + /*integral_constant_expression_p=*/false); in_base_initializer = 0; if (decl) @@ -12329,7 +12373,8 @@ tsubst_enum (tree tag, tree newtag, tree args) /* Note that in a template enum, the TREE_VALUE is the CONST_DECL, not the corresponding INTEGER_CST. */ 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. */ set_current_access_from_decl (decl); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 53d37beca68..90839b73ab3 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2376,6 +2376,17 @@ fold_if_not_in_template (tree 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) /* Complain that some language-specific thing hanging off a tree diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog index c16147658f3..38b9ffe63a4 100644 --- a/gcc/objcp/ChangeLog +++ b/gcc/objcp/ChangeLog @@ -1,3 +1,8 @@ +2006-08-20 Mark Mitchell + + * objcp-lang.c (objcp_tsubst_copy_and_build): Adjust call to + tsubst_copy_and_build. + 2006-07-28 Volker Reichelt * Make-lang.in: Use $(HEADER_H) instead of header.h in dependencies. diff --git a/gcc/objcp/objcp-lang.c b/gcc/objcp/objcp-lang.c index 35081852be9..19a865475a6 100644 --- a/gcc/objcp/objcp-lang.c +++ b/gcc/objcp/objcp-lang.c @@ -110,8 +110,10 @@ tree objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, tree in_decl, bool function_p ATTRIBUTE_UNUSED) { -#define RECURSE(NODE) \ - tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false) +#define RECURSE(NODE) \ + 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++. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index abaa9b7f856..bc920d07795 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2006-08-20 Mark Mitchell + + 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 PR target/28648 c: diff --git a/gcc/testsuite/g++.dg/template/nontype13.C b/gcc/testsuite/g++.dg/template/nontype13.C index 5ff697a933a..9b76d1aa65a 100644 --- a/gcc/testsuite/g++.dg/template/nontype13.C +++ b/gcc/testsuite/g++.dg/template/nontype13.C @@ -11,7 +11,7 @@ struct Dummy template void tester() { - bar()(); // { dg-error "argument" } + bar()(); // { dg-error "constant" } } template struct bar diff --git a/gcc/testsuite/g++.dg/template/ptrmem17.C b/gcc/testsuite/g++.dg/template/ptrmem17.C new file mode 100644 index 00000000000..154f17a8d86 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ptrmem17.C @@ -0,0 +1,10 @@ +// PR c++/28346 + +template struct A +{ + int& i; + A(); + ~A() { &A::i; } // { dg-error "reference" } +}; + +A<0> a; // { dg-error "instantiated" } diff --git a/gcc/testsuite/g++.dg/template/ref3.C b/gcc/testsuite/g++.dg/template/ref3.C new file mode 100644 index 00000000000..4390f71b407 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ref3.C @@ -0,0 +1,11 @@ +// PR c++/28341 + +template struct A {}; + +template struct B +{ + A<(T)0> b; // { dg-error "constant" } + A a; // { dg-error "constant" } +}; + +B b; -- 2.11.0