From patchwork Fri Jan 31 14:07:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fabien_Ch=C3=AAne?= X-Patchwork-Id: 315598 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id B522A2C00AE for ; Sat, 1 Feb 2014 01:08:08 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; q=dns; s=default; b=D1QYCBKnme94QTzrJd Ux/qMcGpJF0EaE3+/Wi1wZw5WeJUcTWDX1jq2sSzfzPQSS4Hz+BOKSbP/kEmBIWS wXcAEdS6y9LXa8MAq0ZNCYr/mGj4XiJTVkCU7Kj0vq3ElMVlI7UyWchxHnAX8EZG aTvUJJqzD7ZbqhkN0cHknxGuI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; s=default; bh=Gz6AS0HGAUtK815HpO7exxNy X0c=; b=nMU3L3VRtJYW0R43uY7ZPaJHNyYcQmP6Nl99rCcIyjOHTT1jFnLUO3rr ktVIFqCqubixgeZj1lWuKpBYMdnguuMcO6FC/8p7uYW6mnlEZui1+V/8MYgcDvxo lhnbZ5/lHzrryl4qFTpvLsrtgtJCzNlK8zA33/MIS+S/gv2SlbY= Received: (qmail 3479 invoked by alias); 31 Jan 2014 14:08:01 -0000 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 Received: (qmail 3467 invoked by uid 89); 31 Jan 2014 14:07:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-oa0-f45.google.com Received: from mail-oa0-f45.google.com (HELO mail-oa0-f45.google.com) (209.85.219.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 31 Jan 2014 14:07:58 +0000 Received: by mail-oa0-f45.google.com with SMTP id i11so5186221oag.4 for ; Fri, 31 Jan 2014 06:07:56 -0800 (PST) MIME-Version: 1.0 X-Received: by 10.182.29.33 with SMTP id g1mr1527216obh.59.1391177275968; Fri, 31 Jan 2014 06:07:55 -0800 (PST) Received: by 10.76.133.35 with HTTP; Fri, 31 Jan 2014 06:07:55 -0800 (PST) In-Reply-To: <52E736FB.5000705@redhat.com> References: <52E736FB.5000705@redhat.com> Date: Fri, 31 Jan 2014 15:07:55 +0100 Message-ID: Subject: Re: [C++ patch] for c++/37140 From: =?ISO-8859-1?Q?Fabien_Ch=EAne?= To: Jason Merrill Cc: GCC Patches X-IsSubscribed: yes 2014-01-28 Jason Merrill : > On 01/27/2014 04:28 PM, Fabien Chêne wrote: >> >> + if (DECL_DEPENDENT_P (decl) && USING_DECL_TYPENAME_P (decl)) >> + { >> + /* We have found a type introduced by a using >> + declaration at class scope that refers to a dependent >> + type. >> + >> + using typename :: [opt] nested-name-specifier unqualified-id ; >> + */ >> + decl = make_typename_type (TREE_TYPE (decl), >> + DECL_NAME (decl), >> + typename_type, tf_error); >> + if (decl != error_mark_node) >> + decl = TYPE_NAME (decl); >> + >> + return decl; >> + } >> + >> while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl)) >> decl = USING_DECL_DECLS (decl); > > > Shouldn't the new code be after the while loop? Actually, as a non-dependent USING_DECL may refer to a dependent one, that would make sense. I have failed however to find a testcase where the code above does not work, probably because as in the example below, a non-dependent USING_DECL refering to a dependent one implicitly requires the base class to be parsed before, so that the instanciation can be performed. Thus, the typename_type is already created. template struct B { typedef char type; }; template struct C : B { using typename B::type; }; struct D : C { using C::type; type z; }; Anyway, your suggestion makes sense to me, and I have successfully tested the attached patch on x86_64 linux. 2014-01-31 Fabien Chêne PR c++/37140 * parser.c (cp_parser_nonclass_name): Call strip_using_decl and move the code handling dependent USING_DECLs... * name-lookup.c (strip_using_decl): ...Here. 2014-01-31 Fabien Chêne PR c++/37140 * g++.dg/template/using27.C: New. * g++.dg/template/using28.C: New. * g++.dg/template/using29.C: New. Index: gcc/testsuite/g++.dg/template/using27.C =================================================================== --- gcc/testsuite/g++.dg/template/using27.C (revision 0) +++ gcc/testsuite/g++.dg/template/using27.C (revision 0) @@ -0,0 +1,33 @@ +// PR c++/37140 + +struct X +{ + typedef int nested_type; +}; + +template +struct A +{ + typedef X type; +}; + +template +struct B : A +{ + using typename A::type; + typename type::nested_type x; +}; + +template +struct C : B +{ + using typename B::type; + typename type::nested_type y; +}; + +struct D : C +{ + using C::type; + type::nested_type z; +}; + Index: gcc/testsuite/g++.dg/template/using29.C =================================================================== --- gcc/testsuite/g++.dg/template/using29.C (revision 0) +++ gcc/testsuite/g++.dg/template/using29.C (revision 0) @@ -0,0 +1,21 @@ +// PR c++/58047 + +template +struct print_arg { }; + +struct const_holder { + static const int CONSTANT = 42; +}; + +template +struct identity { + typedef T type; +}; + +template +struct test_case : public identity { + using typename identity::type; + print_arg printer; +}; + +template struct test_case; Index: gcc/testsuite/g++.dg/template/using28.C =================================================================== --- gcc/testsuite/g++.dg/template/using28.C (revision 0) +++ gcc/testsuite/g++.dg/template/using28.C (revision 0) @@ -0,0 +1,17 @@ +// PR c++/37140 + +struct C +{ + static const int block_size = 1; +}; + +template struct A { + typedef C type; +}; + +template struct B : public A { + using typename A::type; + static const int block_size = type::block_size; +}; + +template class B; Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 207035) +++ gcc/cp/name-lookup.c (working copy) @@ -406,7 +406,8 @@ pop_bindings_and_leave_scope (void) leave_scope (); } -/* Strip non dependent using declarations. */ +/* Strip non dependent using declarations. If DECL is dependent, + surreptitiously create a typename_type and return it. */ tree strip_using_decl (tree decl) @@ -416,6 +417,23 @@ strip_using_decl (tree decl) while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl)) decl = USING_DECL_DECLS (decl); + + if (TREE_CODE (decl) == USING_DECL && DECL_DEPENDENT_P (decl) + && USING_DECL_TYPENAME_P (decl)) + { + /* We have found a type introduced by a using + declaration at class scope that refers to a dependent + type. + + using typename :: [opt] nested-name-specifier unqualified-id ; + */ + decl = make_typename_type (TREE_TYPE (decl), + DECL_NAME (decl), + typename_type, tf_error); + if (decl != error_mark_node) + decl = TYPE_NAME (decl); + } + return decl; } Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 207035) +++ gcc/cp/parser.c (working copy) @@ -14824,25 +14824,7 @@ cp_parser_nonclass_name (cp_parser* pars /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); - if (TREE_CODE (type_decl) == USING_DECL) - { - if (!DECL_DEPENDENT_P (type_decl)) - type_decl = strip_using_decl (type_decl); - else if (USING_DECL_TYPENAME_P (type_decl)) - { - /* We have found a type introduced by a using - declaration at class scope that refers to a dependent - type. - - using typename :: [opt] nested-name-specifier unqualified-id ; - */ - type_decl = make_typename_type (TREE_TYPE (type_decl), - DECL_NAME (type_decl), - typename_type, tf_error); - if (type_decl != error_mark_node) - type_decl = TYPE_NAME (type_decl); - } - } + type_decl = strip_using_decl (type_decl); if (TREE_CODE (type_decl) != TYPE_DECL && (objc_is_id (identifier) || objc_is_class_name (identifier)))