diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 965ee6ee73b7..d2dbe4ea2e81 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2011-04-25 Jason Merrill + + PR c++/48707 + * decl.c (type_dependent_init_p): New. + (cp_finish_decl): Check it. + * pt.c (any_type_dependent_elements_p): New. + * cp-tree.h: Declare it. + 2011-04-20 Jason Merrill * semantics.c (finish_compound_literal): Don't put an array diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e5388259ae68..66ac4e8d26dc 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5105,6 +5105,7 @@ extern bool dependent_template_p (tree); extern bool dependent_template_id_p (tree, tree); extern bool type_dependent_expression_p (tree); extern bool any_type_dependent_arguments_p (const VEC(tree,gc) *); +extern bool any_type_dependent_elements_p (const_tree); extern bool type_dependent_expression_p_push (tree); extern bool value_dependent_expression_p (tree); extern bool any_value_dependent_elements_p (const_tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index cf4a40efed39..dcd18ab5b888 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5700,6 +5700,36 @@ initialize_artificial_var (tree decl, VEC(constructor_elt,gc) *v) make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL); } +/* INIT is the initializer for a variable, as represented by the + parser. Returns true iff INIT is type-dependent. */ + +static bool +type_dependent_init_p (tree init) +{ + if (TREE_CODE (init) == TREE_LIST) + /* A parenthesized initializer, e.g.: int i (3, 2); ? */ + return any_type_dependent_elements_p (init); + else if (TREE_CODE (init) == CONSTRUCTOR) + /* A brace-enclosed initializer, e.g.: int i = { 3 }; ? */ + { + VEC(constructor_elt, gc) *elts; + size_t nelts; + size_t i; + + elts = CONSTRUCTOR_ELTS (init); + nelts = VEC_length (constructor_elt, elts); + for (i = 0; i < nelts; ++i) + if (type_dependent_init_p (VEC_index (constructor_elt, + elts, i)->value)) + return true; + } + else + /* It must be a simple expression, e.g., int i = 3; */ + return type_dependent_expression_p (init); + + return false; +} + /* INIT is the initializer for a variable, as represented by the parser. Returns true iff INIT is value-dependent. */ @@ -5876,19 +5906,25 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, template is instantiated. But, if DECL is a variable constant then it can be used in future constant expressions, so its value must be available. */ - if (init - && init_const_expr_p - && !type_dependent_p - && decl_maybe_constant_var_p (decl) - && !value_dependent_init_p (init)) + + if (TREE_CODE (decl) != VAR_DECL || dependent_type_p (type)) + /* We can't do anything if the decl has dependent type. */; + else if (init + && init_const_expr_p + && !type_dependent_p + && decl_maybe_constant_var_p (decl) + && !type_dependent_init_p (init) + && !value_dependent_init_p (init)) { + /* This variable seems to be a non-dependent constant, so process + its initializer. If check_initializer returns non-null the + initialization wasn't constant after all. */ tree init_code = check_initializer (decl, init, flags, &cleanup); if (init_code == NULL_TREE) init = NULL_TREE; } - else if (TREE_CODE (decl) == VAR_DECL - && !DECL_PRETTY_FUNCTION_P (decl) - && !type_dependent_p) + else if (!DECL_PRETTY_FUNCTION_P (decl)) + /* Deduce array size even if the initializer is dependent. */ maybe_deduce_size_from_array_init (decl, init); if (init) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fc69a0c11e0e..70fcbba73955 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18456,6 +18456,19 @@ any_type_dependent_arguments_p (const VEC(tree,gc) *args) return false; } +/* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are + expressions) contains any type-dependent expressions. */ + +bool +any_type_dependent_elements_p (const_tree list) +{ + for (; list; list = TREE_CHAIN (list)) + if (value_dependent_expression_p (TREE_VALUE (list))) + return true; + + return false; +} + /* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are expressions) contains any value-dependent expressions. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 793c8266ca46..cd361e7e18c7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-04-25 Jason Merrill + + * g++.dg/cpp0x/regress/template-const2.C: New. + 2011-04-25 Jeff Law * gcc.dg/tree-ssa/vrp56.c: new test. diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C new file mode 100644 index 000000000000..25354b3a54a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C @@ -0,0 +1,14 @@ +// PR c++/48707 +// { dg-options -std=c++0x } + +struct A { + static int a(); +}; + +template +struct B: A { + static int const b; +}; + +template +int const B::b=B::a();