On Fri, Jun 27, 2014 at 12:51 PM, Jason Merrill <ja...@redhat.com> wrote: > On 06/27/2014 11:04 AM, Paul Pluzhnikov wrote: >> >> Ok to backport r210653 (fix for PR58930) to gcc-4_9-branch? > > > OK, yes.
Thanks. Committed attached patch as r212207. Tested on Linux/x86_64, no regressions. -- Paul Pluzhnikov
Index: gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C (revision 212207) @@ -0,0 +1,30 @@ +// PR c++/58930 +// { dg-do compile { target c++11 } } + +struct SampleModule +{ + explicit SampleModule (int); +}; + +template < typename > +struct BaseHandler +{ + SampleModule module_ { 0 }; +}; + +BaseHandler<int> a; +// PR c++/58930 +// { dg-do compile { target c++11 } } + +struct SampleModule +{ + explicit SampleModule (int); +}; + +template < typename > +struct BaseHandler +{ + SampleModule module_ { 0 }; +}; + +BaseHandler<int> a; Index: gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C (revision 212207) @@ -0,0 +1,22 @@ +// PR c++/58704 +// { dg-do compile { target c++11 } } + +struct A {}; + +template<typename> struct B +{ + A a[1] = { }; +}; + +B<int> b; +// PR c++/58704 +// { dg-do compile { target c++11 } } + +struct A {}; + +template<typename> struct B +{ + A a[1] = { }; +}; + +B<int> b; Index: gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C (revision 212207) @@ -0,0 +1,34 @@ +// PR c++/58753 +// { dg-do compile { target c++11 } } + +#include <initializer_list> + +template <class T> +struct X {X(std::initializer_list<int>) {}}; + +template <class zomg> +class T { + X<T> x{1}; +}; + +int main() +{ + T<int> t; +} +// PR c++/58753 +// { dg-do compile { target c++11 } } + +#include <initializer_list> + +template <class T> +struct X {X(std::initializer_list<int>) {}}; + +template <class zomg> +class T { + X<T> x{1}; +}; + +int main() +{ + T<int> t; +} Index: gcc/cp/init.c =================================================================== --- gcc/cp/init.c (revision 212206) +++ gcc/cp/init.c (revision 212207) @@ -522,6 +522,49 @@ } } +/* Return the non-static data initializer for FIELD_DECL MEMBER. */ + +tree +get_nsdmi (tree member, bool in_ctor) +{ + tree init; + tree save_ccp = current_class_ptr; + tree save_ccr = current_class_ref; + if (!in_ctor) + inject_this_parameter (DECL_CONTEXT (member), TYPE_UNQUALIFIED); + if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member)) + { + /* Do deferred instantiation of the NSDMI. */ + init = (tsubst_copy_and_build + (DECL_INITIAL (DECL_TI_TEMPLATE (member)), + DECL_TI_ARGS (member), + tf_warning_or_error, member, /*function_p=*/false, + /*integral_constant_expression_p=*/false)); + + init = digest_nsdmi_init (member, init); + } + else + { + init = DECL_INITIAL (member); + if (init && TREE_CODE (init) == DEFAULT_ARG) + { + error ("constructor required before non-static data member " + "for %qD has been parsed", member); + DECL_INITIAL (member) = error_mark_node; + init = NULL_TREE; + } + /* Strip redundant TARGET_EXPR so we don't need to remap it, and + so the aggregate init code below will see a CONSTRUCTOR. */ + if (init && TREE_CODE (init) == TARGET_EXPR + && !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (init)))) + init = TARGET_EXPR_INITIAL (init); + init = break_out_target_exprs (init); + } + current_class_ptr = save_ccp; + current_class_ref = save_ccr; + return init; +} + /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of arguments. If TREE_LIST is void_type_node, an empty initializer list was given; if NULL_TREE no initializer was given. */ @@ -535,31 +578,7 @@ /* Use the non-static data member initializer if there was no mem-initializer for this field. */ if (init == NULL_TREE) - { - if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member)) - /* Do deferred instantiation of the NSDMI. */ - init = (tsubst_copy_and_build - (DECL_INITIAL (DECL_TI_TEMPLATE (member)), - DECL_TI_ARGS (member), - tf_warning_or_error, member, /*function_p=*/false, - /*integral_constant_expression_p=*/false)); - else - { - init = DECL_INITIAL (member); - if (init && TREE_CODE (init) == DEFAULT_ARG) - { - error ("constructor required before non-static data member " - "for %qD has been parsed", member); - init = NULL_TREE; - } - /* Strip redundant TARGET_EXPR so we don't need to remap it, and - so the aggregate init code below will see a CONSTRUCTOR. */ - if (init && TREE_CODE (init) == TARGET_EXPR - && !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (init)))) - init = TARGET_EXPR_INITIAL (init); - init = break_out_target_exprs (init); - } - } + init = get_nsdmi (member, /*ctor*/true); if (init == error_mark_node) return; Index: gcc/cp/typeck2.c =================================================================== --- gcc/cp/typeck2.c (revision 212206) +++ gcc/cp/typeck2.c (revision 212207) @@ -1097,6 +1097,22 @@ { return digest_init_r (type, init, false, flags, tf_warning_or_error); } + +/* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL). */ +tree +digest_nsdmi_init (tree decl, tree init) +{ + gcc_assert (TREE_CODE (decl) == FIELD_DECL); + + int flags = LOOKUP_IMPLICIT; + if (DIRECT_LIST_INIT_P (init)) + flags = LOOKUP_NORMAL; + init = digest_init_flags (TREE_TYPE (decl), init, flags); + if (TREE_CODE (init) == TARGET_EXPR) + /* This represents the whole initialization. */ + TARGET_EXPR_DIRECT_INIT_P (init) = true; + return init; +} /* Set of flags used within process_init_constructor to describe the initializers. */ Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 212206) +++ gcc/cp/parser.c (revision 212207) @@ -17852,7 +17852,7 @@ /* Used by handling of trailing-return-types and NSDMI, in which 'this' is in scope even though it isn't real. */ -static void +void inject_this_parameter (tree ctype, cp_cv_quals quals) { tree this_parm; @@ -23686,16 +23686,7 @@ parsed_arg = check_default_argument (parmtype, parsed_arg, tf_warning_or_error); else - { - int flags = LOOKUP_IMPLICIT; - if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg) - && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg)) - flags = LOOKUP_NORMAL; - parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags); - if (TREE_CODE (parsed_arg) == TARGET_EXPR) - /* This represents the whole initialization. */ - TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true; - } + parsed_arg = digest_nsdmi_init (decl, parsed_arg); } /* If the token stream has not been completely used up, then Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 212206) +++ gcc/cp/cp-tree.h (revision 212207) @@ -3436,6 +3436,9 @@ B b{1,2}, not B b({1,2}) or B b = {1,2}. */ #define CONSTRUCTOR_IS_DIRECT_INIT(NODE) (TREE_LANG_FLAG_0 (CONSTRUCTOR_CHECK (NODE))) +#define DIRECT_LIST_INIT_P(NODE) \ + (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE)) + /* True if NODE represents a conversion for direct-initialization in a template. Set by perform_implicit_conversion_flags. */ #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \ @@ -4353,6 +4356,11 @@ PARM_DECLs in cp_tree_equal. */ extern int comparing_specializations; +/* A type-qualifier, or bitmask therefore, using the TYPE_QUAL + constants. */ + +typedef int cp_cv_quals; + /* In parser.c. */ /* Nonzero if we are parsing an unevaluated operand: an operand to @@ -4362,6 +4370,7 @@ extern int cp_unevaluated_operand; extern tree cp_convert_range_for (tree, tree, tree, bool); extern bool parsing_nsdmi (void); +extern void inject_this_parameter (tree, cp_cv_quals); /* in pt.c */ @@ -4741,11 +4750,6 @@ extern GTY(()) operator_name_info_t assignment_operator_name_info [(int) MAX_TREE_CODES]; -/* A type-qualifier, or bitmask therefore, using the TYPE_QUAL - constants. */ - -typedef int cp_cv_quals; - /* Non-static member functions have an optional virt-specifier-seq. There is a VIRT_SPEC value for each virt-specifier. They can be combined by bitwise-or to form the complete set of @@ -5421,6 +5425,7 @@ extern tree build_zero_init (tree, tree, bool); extern tree build_value_init (tree, tsubst_flags_t); extern tree build_value_init_noctor (tree, tsubst_flags_t); +extern tree get_nsdmi (tree, bool); extern tree build_offset_ref (tree, tree, bool, tsubst_flags_t); extern tree throw_bad_array_new_length (void); @@ -6157,6 +6162,7 @@ extern void check_narrowing (tree, tree); extern tree digest_init (tree, tree, tsubst_flags_t); extern tree digest_init_flags (tree, tree, int); +extern tree digest_nsdmi_init (tree, tree); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (location_t, tree, tsubst_flags_t);