Bootstrapped and regtested on x86_64-pc-linux-gnu, are one of both of these fixes OK for trunk?
-- >8 -- Here during ahead of time checking of the non-dependent new-expr we synthesize B's copy constructor, which should be defined as deleted due to A's inaccessible copy constructor. But enforce_access incorrectly decides to defer the (silent) access check for A::A(const A&) during synthesization since current_template_parms is still set (before r14-557 it checked processing_template_decl which got cleared from implicitly_declare_fn), which leads to the access check leaking out to the template context that needed the synthesization. This patch narrowly fixes this regression in two sufficient ways: 1. Clear current_template_parms alongside processing_template_decl in implicitly_declare_fn so that it's more independent of context. 2. Don't defer a silent access check when in a template context, since such deferred checks will be replayed noisily at instantiation time which may not be what the caller intended. We need to adjust cp_parser_make_typename_type since otherwise the diagnostic for typedef22.C regresses because cp_parser_invalid_type_name otherwise will emit "invalid combination of multiple type-specifiers" for what is an inaccessible qualified-id. PR c++/113908 gcc/cp/ChangeLog: * method.cc (implicitly_declare_fn): Clear current_template_parms alongside processing_template_decl. * parser.cc (cp_parser_make_typename_type): Temporarily defer access checks around the tf_none call to make_typename_type. * semantics.cc (enforce_access): Don't defer silent access checks from a template context. gcc/testsuite/ChangeLog: * g++.dg/template/non-dependent31.C: New test. --- gcc/cp/method.cc | 8 +++++++- gcc/cp/parser.cc | 2 ++ gcc/cp/semantics.cc | 1 + .../g++.dg/template/non-dependent31.C | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/non-dependent31.C diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 957496d3e18..17d42143299 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -3088,6 +3088,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, tree this_parm; tree name; HOST_WIDE_INT saved_processing_template_decl; + tree saved_current_template_parms; bool deleted_p = false; bool constexpr_p = false; tree inherited_ctor = (kind == sfk_inheriting_constructor @@ -3132,6 +3133,10 @@ implicitly_declare_fn (special_function_kind kind, tree type, when not in a template. */ saved_processing_template_decl = processing_template_decl; processing_template_decl = 0; + /* Also clear CURRENT_TEMPLATE_PARMS so enforce_access immediately checks + access even in a template context. */ + saved_current_template_parms = current_template_parms; + current_template_parms = NULL_TREE; type = TYPE_MAIN_VARIANT (type); @@ -3341,8 +3346,9 @@ implicitly_declare_fn (special_function_kind kind, tree type, set_constraints (fn, new_ci); } - /* Restore PROCESSING_TEMPLATE_DECL. */ + /* Restore PROCESSING_TEMPLATE_DECL and CURRENT_TEMPLATE_PARMS. */ processing_template_decl = saved_processing_template_decl; + current_template_parms = saved_current_template_parms; if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL) fn = add_inherited_template_parms (fn, inherited_ctor); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index c4292c49ce2..29120995449 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -4350,8 +4350,10 @@ cp_parser_make_typename_type (cp_parser *parser, tree id, tree result; if (identifier_p (id)) { + push_deferring_access_checks (dk_deferred); result = make_typename_type (parser->scope, id, typename_type, /*complain=*/tf_none); + pop_to_parent_deferring_access_checks (); if (result == error_mark_node) cp_parser_diagnose_invalid_type_name (parser, id, id_location); return result; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 3299e270446..0a18eaf9c2e 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -346,6 +346,7 @@ enforce_access (tree basetype_path, tree decl, tree diag_decl, tree cs = current_scope (); if (in_template_context + && (complain & tf_error) && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)) if (tree template_info = get_template_info (cs)) { diff --git a/gcc/testsuite/g++.dg/template/non-dependent31.C b/gcc/testsuite/g++.dg/template/non-dependent31.C new file mode 100644 index 00000000000..3fa68f40fe1 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-dependent31.C @@ -0,0 +1,18 @@ +// PR c++/113908 +// { dg-do compile { target c++11 } } + +struct A { + A(); +private: + A(const A&); +}; + +struct B { + A a; + + template<class T> + static void f() { new B(); } +}; + +template void B::f<int>(); +static_assert(!__is_constructible(B, const B&), ""); -- 2.44.0.rc0.46.g2996f11c1d