From: Mark Mitchell Date: Wed, 4 Feb 2004 18:35:18 +0000 (+0000) Subject: re PR c++/13969 (static const value rejected as template parameter) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9baa27a975e184773ffb8ec4297db8ce34291246;p=platform%2Fupstream%2Fgcc.git re PR c++/13969 (static const value rejected as template parameter) PR c++/13969 * g++.dg/template/static6.C: New test. PR c++/13969 * cp-tree.h (fold_non_dependent_expr): New function. * parser.c (cp_parser_fold_non_dependent_expr): Remove. (cp_parser_template_argument): Use fold_non_dependent_expr. (cp_parser_direct_declarator): Likewise. * pt.c (fold_non_dependent_expr): New function. (convert_nontype_argument): Use it. (tsubst_qualified_id): Simplify. (tsubst_copy_and_build): Likewise. From-SVN: r77260 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4ef866f..ec034bc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ 2004-02-04 Mark Mitchell + PR c++/13969 + * cp-tree.h (fold_non_dependent_expr): New function. + * parser.c (cp_parser_fold_non_dependent_expr): Remove. + (cp_parser_template_argument): Use fold_non_dependent_expr. + (cp_parser_direct_declarator): Likewise. + * pt.c (fold_non_dependent_expr): New function. + (convert_nontype_argument): Use it. + (tsubst_qualified_id): Simplify. + (tsubst_copy_and_build): Likewise. + +2004-02-04 Mark Mitchell + * decl.c (cxx_push_function_context): Do not set current_function_is_thunk. * method.c (use_thunk): Set CALL_FROM_THUNK on the call to the diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5e64578..64b9549 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3927,6 +3927,7 @@ extern tree template_for_substitution (tree); extern tree build_non_dependent_expr (tree); extern tree build_non_dependent_args (tree); extern bool reregister_specialization (tree, tree, tree); +extern tree fold_non_dependent_expr (tree); /* in repo.c */ extern void repo_template_used (tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4905b94..4ee1aa6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1669,8 +1669,6 @@ static tree cp_parser_sizeof_operand (cp_parser *, enum rid); static bool cp_parser_declares_only_class_p (cp_parser *); -static tree cp_parser_fold_non_dependent_expr - (tree); static bool cp_parser_friend_p (tree); static cp_token *cp_parser_require @@ -8411,7 +8409,7 @@ cp_parser_template_argument (cp_parser* parser) argument = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, /*non_constant_p=*/NULL); - argument = cp_parser_fold_non_dependent_expr (argument); + argument = fold_non_dependent_expr (argument); if (!maybe_type_id) return argument; if (!cp_parser_next_token_ends_template_argument_p (parser)) @@ -10417,7 +10415,7 @@ cp_parser_direct_declarator (cp_parser* parser, /*allow_non_constant=*/true, &non_constant_p); if (!non_constant_p) - bounds = cp_parser_fold_non_dependent_expr (bounds); + bounds = fold_non_dependent_expr (bounds); } else bounds = NULL_TREE; @@ -14734,37 +14732,6 @@ cp_parser_declares_only_class_p (cp_parser *parser) || cp_lexer_next_token_is (parser->lexer, CPP_COMMA)); } -/* Simplify EXPR if it is a non-dependent expression. Returns the - (possibly simplified) expression. */ - -static tree -cp_parser_fold_non_dependent_expr (tree expr) -{ - /* If we're in a template, but EXPR isn't value dependent, simplify - it. We're supposed to treat: - - template void f(T[1 + 1]); - template void f(T[2]); - - as two declarations of the same function, for example. */ - if (processing_template_decl - && !type_dependent_expression_p (expr) - && !value_dependent_expression_p (expr)) - { - HOST_WIDE_INT saved_processing_template_decl; - - saved_processing_template_decl = processing_template_decl; - processing_template_decl = 0; - expr = tsubst_copy_and_build (expr, - /*args=*/NULL_TREE, - tf_error, - /*in_decl=*/NULL_TREE, - /*function_p=*/false); - processing_template_decl = saved_processing_template_decl; - } - return expr; -} - /* DECL_SPECIFIERS is the representation of a decl-specifier-seq. Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7040138..b7d794e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3099,20 +3099,60 @@ redeclare_class_template (tree type, tree parms) } } +/* Simplify EXPR if it is a non-dependent expression. Returns the + (possibly simplified) expression. */ + +tree +fold_non_dependent_expr (tree expr) +{ + /* If we're in a template, but EXPR isn't value dependent, simplify + it. We're supposed to treat: + + template void f(T[1 + 1]); + template void f(T[2]); + + as two declarations of the same function, for example. */ + if (processing_template_decl + && !type_dependent_expression_p (expr) + && !value_dependent_expression_p (expr)) + { + HOST_WIDE_INT saved_processing_template_decl; + + saved_processing_template_decl = processing_template_decl; + processing_template_decl = 0; + expr = tsubst_copy_and_build (expr, + /*args=*/NULL_TREE, + tf_error, + /*in_decl=*/NULL_TREE, + /*function_p=*/false); + processing_template_decl = saved_processing_template_decl; + } + return expr; +} + /* Attempt to convert the non-type template parameter EXPR to the indicated TYPE. If the conversion is successful, return the converted value. If the conversion is unsuccessful, return NULL_TREE if we issued an error message, or error_mark_node if we did not. We issue error messages for out-and-out bad template parameters, but not simply because the conversion failed, since we - might be just trying to do argument deduction. By the time this - function is called, neither TYPE nor EXPR may make use of template - parameters. */ + might be just trying to do argument deduction. Both TYPE and EXPR + must be non-dependent. */ static tree convert_nontype_argument (tree type, tree expr) { - tree expr_type = TREE_TYPE (expr); + tree expr_type; + + /* If we are in a template, EXPR may be non-dependent, but still + have a syntactic, rather than semantic, form. For example, EXPR + might be a SCOPE_REF, rather than the VAR_DECL to which the + SCOPE_REF refers. Preserving the qualifying scope is necessary + so that access checking can be performed when the template is + instantiated -- but here we need the resolved form so that we can + convert the argument. */ + expr = fold_non_dependent_expr (expr); + expr_type = TREE_TYPE (expr); /* A template-argument for a non-type, non-template template-parameter shall be one of: @@ -3136,12 +3176,31 @@ convert_nontype_argument (tree type, tree expr) --a pointer to member expressed as described in _expr.unary.op_. */ /* An integral constant-expression can include const variables or - enumerators. Simplify things by folding them to their values, +. enumerators. Simplify things by folding them to their values, unless we're about to bind the declaration to a reference parameter. */ - if (INTEGRAL_TYPE_P (expr_type) - && TREE_CODE (type) != REFERENCE_TYPE) - expr = decl_constant_value (expr); + if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE) + while (true) + { + tree const_expr = decl_constant_value (expr); + /* In a template, the initializer for a VAR_DECL may not be + marked as TREE_CONSTANT, in which case decl_constant_value + will not return the initializer. Handle that special case + here. */ + if (expr == const_expr + && TREE_CODE (expr) == VAR_DECL + && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr) + && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr)) + /* DECL_INITIAL can be NULL if we are processing a + variable initialized to an expression involving itself. + We know it is initialized to a constant -- but not what + constant, yet. */ + && DECL_INITIAL (expr)) + const_expr = DECL_INITIAL (expr); + if (expr == const_expr) + break; + expr = fold_non_dependent_expr (const_expr); + } if (is_overloaded_fn (expr)) /* OK for now. We'll check that it has external linkage later. @@ -7279,11 +7338,7 @@ tsubst_qualified_id (tree qualified_id, tree args, /* Remember that there was a reference to this entity. */ if (DECL_P (expr)) - { - mark_used (expr); - if (!args && TREE_CODE (expr) == VAR_DECL) - expr = DECL_INITIAL (expr); - } + mark_used (expr); if (is_template) expr = lookup_template_function (expr, template_args); @@ -8485,11 +8540,6 @@ tsubst_copy_and_build (tree t, case VAR_DECL: if (args) t = tsubst_copy (t, args, complain, in_decl); - else - /* If there are no ARGS, then we are evaluating a - non-dependent expression. If the expression is - non-dependent, the variable must be a constant. */ - t = DECL_INITIAL (t); return convert_from_reference (t); case VA_ARG_EXPR: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 28dc9cf..def7ad68 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-02-04 Mark Mitchell + + PR c++/13969 + * g++.dg/template/static6.C: New test. + 2004-02-04 Ian Lance Taylor * gcc.dg/arm-mmx-1.c: Don't look for ldmfd if -mthumb. diff --git a/gcc/testsuite/g++.dg/template/static6.C b/gcc/testsuite/g++.dg/template/static6.C new file mode 100644 index 0000000..30ecae9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static6.C @@ -0,0 +1,14 @@ +// PR c++/13969 + +struct B { + static const int N=10; +}; + +template struct X {}; + +template struct S { + static const int N = B::N; + X x; +}; + +template class S;