From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31728 invoked by alias); 16 Nov 2009 22:11:43 -0000 Received: (qmail 31720 invoked by uid 22791); 16 Nov 2009 22:11:42 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS 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; Mon, 16 Nov 2009 22:10:38 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nAGMAaXV011431 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 16 Nov 2009 17:10:37 -0500 Received: from adjoa.torimasen.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nAGMAW7P020725 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Mon, 16 Nov 2009 17:10:35 -0500 Date: Mon, 16 Nov 2009 22:13:00 -0000 From: Dodji Seketeli To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com Subject: PR c++/141777 Message-ID: <20091116221032.GF23086@adjoa.torimasen.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.19 (2009-01-05) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2009-11/txt/msg00814.txt.bz2 Hello, In the example of the patch below we forget to perform access check of a typedef declared in a template. check_accessibility_of_qualified_id is the place where we mark template typedefs members in order to check their access at template instantiation time. I thought we should necessarily hit this function at parsing time (through cp_parser_lookup_name), but that was not correct. When the typedef is used through a typename like in the example of the patch, a typename is created directly using cp_parser_make_typename_type from e.g. cp_parser_elaborated_type_specifier and cp_parser_lookup_name is not called. This patch closes the gap by marking template typedefs members used through typename for access check. Tested against trunk on x86_64_unknown_linux_gnu. Dodji commit 21265331cd9714c849a1008c64febf5a239a7ed7 Author: Dodji Seketeli Date: Mon Nov 16 22:29:06 2009 +0100 Fix PR c++/14777 gcc/cp/ChangeLog: PR c++/14777 * gcc/cp/semantics.c (add_typedef_to_current_template_for_access_check): Split from ... (check_accessibility_of_qualified_id): ... here. * gcc/cp/cp-tree.h (add_typedef_to_current_template_for_access_check)): Declare. * cp/decl.c (make_typename_type): Use it. gcc/testsuite/ChangeLog: PR c++/14777 * g++.dg/template/typedef22.C: New test. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a71dc73..8c5cd59 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5038,6 +5038,7 @@ extern void emit_associated_thunks (tree); extern void finish_mem_initializers (tree); extern tree check_template_template_default_arg (tree); extern void expand_or_defer_fn (tree); +extern void add_typedef_to_current_template_for_access_check (tree, tree); extern void check_accessibility_of_qualified_id (tree, tree, tree); extern tree finish_qualified_id_expr (tree, tree, bool, bool, bool, bool); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 73bf995..1786f29 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3075,6 +3075,11 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, if (complain & tf_error) perform_or_defer_access_check (TYPE_BINFO (context), t, t); + /* If we are currently parsing a template and if T is a typedef accessed + through CONTEXT then we need to remember and check access of T at + template instantiation time. */ + add_typedef_to_current_template_for_access_check (t, context); + if (want_template) return lookup_template_class (t, TREE_OPERAND (fullname, 1), NULL_TREE, context, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c1df24b..a99b1ea 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1531,6 +1531,34 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) } } +/* If we are currently parsing a template and we encountered a typedef + TYPEDEF_DECL that is being accessed though CONTEXT, this function + adds the typedef to a list tied to the current template. + At tempate instantiatin time, that list is walked and access check + performed for each typedef. */ + +void +add_typedef_to_current_template_for_access_check (tree typedef_decl, + tree context) +{ + tree template_info = NULL; + tree cs = current_scope (); + + if (!is_typedef_decl (typedef_decl) + || !context + || !CLASS_TYPE_P (context) + || !cs) + return; + + if (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL) + template_info = get_template_info (cs); + + if (template_info + && TI_TEMPLATE (template_info) + && !currently_open_class (context)) + append_type_to_template_for_access_check (cs, typedef_decl, context); +} + /* DECL was the declaration to which a qualified-id resolved. Issue an error message if it is not accessible. If OBJECT_TYPE is non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the @@ -1549,27 +1577,10 @@ check_accessibility_of_qualified_id (tree decl, add it to a list tied to the template. At template instantiation time, that list will be walked and access check performed. */ - if (is_typedef_decl (decl)) - { - /* This the scope through which type_decl is accessed. - It will be useful information later to do access check for - type_decl usage. */ - tree scope = nested_name_specifier - ? nested_name_specifier - : DECL_CONTEXT (decl); - tree templ_info = NULL; - tree cs = current_scope (); - - if (cs && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)) - templ_info = get_template_info (cs); - - if (templ_info - && TI_TEMPLATE (templ_info) - && scope - && CLASS_TYPE_P (scope) - && !currently_open_class (scope)) - append_type_to_template_for_access_check (current_scope (), decl, scope); - } + add_typedef_to_current_template_for_access_check (decl, + nested_name_specifier + ? nested_name_specifier + : DECL_CONTEXT (decl)); /* If we're not checking, return immediately. */ if (deferred_access_no_check) diff --git a/gcc/testsuite/g++.dg/template/typedef22.C b/gcc/testsuite/g++.dg/template/typedef22.C new file mode 100644 index 0000000..8c6edc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef22.C @@ -0,0 +1,18 @@ +// Contributed by Dodji Seketeli +// Origin: PR c++/14777 +// { dg-do compile } + +template +struct B +{ +protected: + typedef int M; // { dg-error "protected" } +}; + +template +struct A : B { // { dg-error "context" } + typedef typename B::M N; + A (int = N ()); +}; + +A a = A ();