From patchwork Tue May 24 20:24:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 97220 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 37B0DB6F9D for ; Wed, 25 May 2011 06:24:57 +1000 (EST) Received: (qmail 29801 invoked by alias); 24 May 2011 20:24:43 -0000 Received: (qmail 29771 invoked by uid 22791); 24 May 2011 20:24:39 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 24 May 2011 20:24:21 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4OKOLaF015762 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 24 May 2011 16:24:21 -0400 Received: from [127.0.0.1] ([10.3.113.3]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p4OKOKON028694 for ; Tue, 24 May 2011 16:24:21 -0400 Message-ID: <4DDC13F4.5010409@redhat.com> Date: Tue, 24 May 2011 16:24:20 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/48884 (access control and deduction) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org In this PR, we had a problem with hitting access control violations during the substitution of template arguments in the context of template argument deduction. If we're going to be doing access checking at all during deduction substitution, we need to do it in the context of the function we're doing deduction for. In C++98 mode we just disable access checking. Tested x86_64-pc-linux-gnu, applying to trunk. commit ffb9b449d208ef324c092df35460d9e0b34eacfd Author: Jason Merrill Date: Mon May 23 16:02:45 2011 -0400 PR c++/48884 * class.c (pushclass): Accept NULL argument. (popclass): Deal with popping null class. * pt.c (push_access_scope, pop_access_scope): Use them rather than push_to_top_level/pop_from_top_level. (push_deduction_access_scope, pop_defarg_context): New. (fn_type_unification): Use them. * name-lookup.c (lookup_name_real_1): Check current_class_type. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4e52b18..69627cb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6082,6 +6082,9 @@ restore_class_cache (void) So that we may avoid calls to lookup_name, we cache the _TYPE nodes of local TYPE_DECLs in the TREE_TYPE field of the name. + For use by push_access_scope, we allow TYPE to be null to temporarily + push out of class scope. This does not actually change binding levels. + For multiple inheritance, we perform a two-pass depth-first search of the type lattice. */ @@ -6090,8 +6093,6 @@ pushclass (tree type) { class_stack_node_t csn; - type = TYPE_MAIN_VARIANT (type); - /* Make sure there is enough room for the new entry on the stack. */ if (current_class_depth + 1 >= current_class_stack_size) { @@ -6110,6 +6111,15 @@ pushclass (tree type) csn->hidden = 0; current_class_depth++; + if (type == NULL_TREE) + { + current_class_name = current_class_type = NULL_TREE; + csn->hidden = true; + return; + } + + type = TYPE_MAIN_VARIANT (type); + /* Now set up the new type. */ current_class_name = TYPE_NAME (type); if (TREE_CODE (current_class_name) == TYPE_DECL) @@ -6154,7 +6164,11 @@ invalidate_class_lookup_cache (void) void popclass (void) { - poplevel_class (); + if (current_class_type) + poplevel_class (); + else + gcc_assert (current_class_depth + && current_class_stack[current_class_depth - 1].hidden); current_class_depth--; current_class_name = current_class_stack[current_class_depth].name; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 3d1c64d..bb6d4b9 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4469,7 +4469,7 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p, /* Conversion operators are handled specially because ordinary unqualified name lookup will not find template conversion operators. */ - if (IDENTIFIER_TYPENAME_P (name)) + if (IDENTIFIER_TYPENAME_P (name) && current_class_type) { struct cp_binding_level *level; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dbff91e..98844c3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -212,7 +212,7 @@ push_access_scope (tree t) else if (DECL_CLASS_SCOPE_P (t)) push_nested_class (DECL_CONTEXT (t)); else - push_to_top_level (); + pushclass (NULL_TREE); if (TREE_CODE (t) == FUNCTION_DECL) { @@ -237,7 +237,7 @@ pop_access_scope (tree t) if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) pop_nested_class (); else - pop_from_top_level (); + popclass (); } /* Do any processing required when DECL (a member template @@ -13820,6 +13820,30 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) return ret; } +/* We're going to do deduction substitution on the type of TMPL, a function + template. In C++11 mode, push into that access scope. In C++03 mode, + disable access checking. */ + +static void +push_deduction_access_scope (tree tmpl) +{ + if (cxx_dialect >= cxx0x) + push_access_scope (DECL_TEMPLATE_RESULT (tmpl)); + else + push_deferring_access_checks (dk_no_check); +} + +/* And pop back out. */ + +static void +pop_deduction_access_scope (tree tmpl) +{ + if (cxx_dialect >= cxx0x) + pop_access_scope (DECL_TEMPLATE_RESULT (tmpl)); + else + pop_deferring_access_checks (); +} + /* The FN is a TEMPLATE_DECL for a function. ARGS is an array with NARGS elements of the arguments that are being used when calling it. TARGS is a vector into which the deduced template arguments @@ -13958,7 +13982,9 @@ fn_type_unification (tree fn, incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs); processing_template_decl += incomplete; + push_deduction_access_scope (fn); fntype = deduction_tsubst_fntype (fn, converted_args); + pop_deduction_access_scope (fn); processing_template_decl -= incomplete; if (fntype == error_mark_node) @@ -14029,7 +14055,10 @@ fn_type_unification (tree fn, substitution results in an invalid type, as described above, type deduction fails. */ { - tree substed = deduction_tsubst_fntype (fn, targs); + tree substed; + push_deduction_access_scope (fn); + substed = deduction_tsubst_fntype (fn, targs); + pop_deduction_access_scope (fn); if (substed == error_mark_node) return 1; diff --git a/gcc/testsuite/g++.dg/template/access21.C b/gcc/testsuite/g++.dg/template/access21.C new file mode 100644 index 0000000..8414c43 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access21.C @@ -0,0 +1,23 @@ +// PR c++/48884 + +class X +{ + static const int I = 42; + friend struct Y; +}; + +template struct A { }; + +struct Y +{ + template + static A f(T t) + { + return A(); + } +}; + +int main() +{ + Y::f(X()); +} diff --git a/gcc/testsuite/g++.dg/template/access22.C b/gcc/testsuite/g++.dg/template/access22.C new file mode 100644 index 0000000..9ee28a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access22.C @@ -0,0 +1,15 @@ +template struct B { }; + +template +B f(); + +class A +{ + static const int I = 42; + template friend B f(); +}; + +int main() +{ + f(); +}