From 0ef08a81174e8a46e59cc2e1811f03e6754a4eba Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 8 Jul 2013 23:19:36 -0400 Subject: [PATCH] re PR c++/57550 (bogus "error ... is private") PR c++/57550 * pt.c (fn_type_unification): Only defer during substitution. (type_unification_real): Defer during defarg substitution, add checks parm to pass back deferred checks. (unify, do_auto_deduction): Adjust. * semantics.c (reopen_deferring_access_checks): New. * cp-tree.h: Declare it. From-SVN: r200808 --- gcc/cp/ChangeLog | 10 +++++ gcc/cp/cp-tree.h | 1 + gcc/cp/pt.c | 48 ++++++++++++++++-------- gcc/cp/semantics.c | 11 ++++++ gcc/testsuite/g++.dg/template/access27.C | 17 +++++++++ 5 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/access27.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 333249a4bd1..33f6562f1a4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2013-07-08 Jason Merrill + + PR c++/57550 + * pt.c (fn_type_unification): Only defer during substitution. + (type_unification_real): Defer during defarg substitution, + add checks parm to pass back deferred checks. + (unify, do_auto_deduction): Adjust. + * semantics.c (reopen_deferring_access_checks): New. + * cp-tree.h: Declare it. + 2013-07-06 Paolo Carlini PR c++/28262 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1b0b2435c53..1971bc5386c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5637,6 +5637,7 @@ extern void resume_deferring_access_checks (void); extern void stop_deferring_access_checks (void); extern void pop_deferring_access_checks (void); extern vec *get_deferred_access_checks (void); +extern void reopen_deferring_access_checks (vec *); extern void pop_to_parent_deferring_access_checks (void); extern bool perform_access_checks (vec *, tsubst_flags_t); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3847a1d6154..26d5a1c5daa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -138,6 +138,7 @@ static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*, tree); static int type_unification_real (tree, tree, tree, const tree *, unsigned int, int, unification_kind_t, int, + vec **, bool); static void note_template_header (int); static tree convert_nontype_argument_function (tree, tree); @@ -15052,7 +15053,6 @@ fn_type_unification (tree fn, return error_mark_node; tinst = build_tree_list (fn, NULL_TREE); ++deduction_depth; - push_deferring_access_checks (dk_deferred); gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL); @@ -15144,8 +15144,13 @@ fn_type_unification (tree fn, } processing_template_decl += incomplete; input_location = DECL_SOURCE_LOCATION (fn); + /* Ignore any access checks; we'll see them again in + instantiate_template and they might have the wrong + access path at this point. */ + push_deferring_access_checks (dk_deferred); fntype = tsubst (TREE_TYPE (fn), explicit_targs, complain | tf_partial, NULL_TREE); + pop_deferring_access_checks (); input_location = loc; processing_template_decl -= incomplete; pop_tinst_level (); @@ -15153,12 +15158,6 @@ fn_type_unification (tree fn, if (fntype == error_mark_node) goto fail; - /* Throw away these access checks; we'll see them again in - instantiate_template and they might have the wrong - access path at this point. */ - pop_deferring_access_checks (); - push_deferring_access_checks (dk_deferred); - /* Place the explicitly specified arguments in TARGS. */ for (i = NUM_TMPL_ARGS (explicit_targs); i--;) TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (explicit_targs, i); @@ -15194,9 +15193,15 @@ fn_type_unification (tree fn, excessive_deduction_depth = true; goto fail; } + + /* type_unification_real will pass back any access checks from default + template argument substitution. */ + vec *checks; + checks = NULL; + ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn), targs, parms, args, nargs, /*subr=*/0, - strict, flags, explain_p); + strict, flags, &checks, explain_p); if (!explain_p) pop_tinst_level (); if (!ok) @@ -15245,16 +15250,23 @@ fn_type_unification (tree fn, excessive_deduction_depth = true; goto fail; } + + /* Also collect access checks from the instantiation. */ + reopen_deferring_access_checks (checks); + decl = instantiate_template (fn, targs, complain); + + checks = get_deferred_access_checks (); + pop_deferring_access_checks (); + pop_tinst_level (); if (decl == error_mark_node) goto fail; - /* Now perform any access checks encountered during deduction, such as - for default template arguments. */ + /* Now perform any access checks encountered during substitution. */ push_access_scope (decl); - ok = perform_deferred_access_checks (complain); + ok = perform_access_checks (checks, complain); pop_access_scope (decl); if (!ok) goto fail; @@ -15283,7 +15295,6 @@ fn_type_unification (tree fn, r = decl; fail: - pop_deferring_access_checks (); --deduction_depth; if (excessive_deduction_depth) { @@ -15684,7 +15695,10 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, If SUBR is 1, we're being called recursively (to unify the arguments of a function or method parameter of a function - template). */ + template). + + CHECKS is a pointer to a vector of access checks encountered while + substituting default template arguments. */ static int type_unification_real (tree tparms, @@ -15695,6 +15709,7 @@ type_unification_real (tree tparms, int subr, unification_kind_t strict, int flags, + vec **checks, bool explain_p) { tree parm, arg; @@ -15834,6 +15849,7 @@ type_unification_real (tree tparms, { tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i)); tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i)); + reopen_deferring_access_checks (*checks); location_t save_loc = input_location; if (DECL_P (parm)) input_location = DECL_SOURCE_LOCATION (parm); @@ -15841,6 +15857,8 @@ type_unification_real (tree tparms, arg = convert_template_argument (parm, arg, targs, complain, i, NULL_TREE); input_location = save_loc; + *checks = get_deferred_access_checks (); + pop_deferring_access_checks (); if (arg == error_mark_node) return 1; else @@ -17307,7 +17325,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), args, nargs, 1, DEDUCE_EXACT, - LOOKUP_NORMAL, explain_p); + LOOKUP_NORMAL, NULL, explain_p); } case OFFSET_TYPE: @@ -20914,7 +20932,7 @@ do_auto_deduction (tree type, tree init, tree auto_node) = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); val = type_unification_real (tparms, targs, parms, &init, 1, 0, DEDUCE_CALL, LOOKUP_NORMAL, - /*explain_p=*/false); + NULL, /*explain_p=*/false); if (val > 0) { if (processing_template_decl) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f8217546b6b..0a6c77541a6 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -155,6 +155,17 @@ push_deferring_access_checks (deferring_kind deferring) } } +/* Save the current deferred access states and start deferred access + checking, continuing the set of deferred checks in CHECKS. */ + +void +reopen_deferring_access_checks (vec * checks) +{ + push_deferring_access_checks (dk_deferred); + if (!deferred_access_no_check) + deferred_access_stack->last().deferred_access_checks = checks; +} + /* Resume deferring access checks again after we stopped doing this previously. */ diff --git a/gcc/testsuite/g++.dg/template/access27.C b/gcc/testsuite/g++.dg/template/access27.C new file mode 100644 index 00000000000..967e10f6a5b --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access27.C @@ -0,0 +1,17 @@ +// PR c++/57550 + +template bool Wrapper(double); +template void MakeHandler(bool (T)); + +class Handler +{ +public: + template static void SetPrimitiveHandlers() + { + MakeHandler(Wrapper >); + } +private : + template static bool Append(T); +}; + +template void Handler::SetPrimitiveHandlers();