From patchwork Tue Jul 22 00:49:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ed Smith-Rowland <3dw4rd@verizon.net> X-Patchwork-Id: 372313 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 A648214014B for ; Tue, 22 Jul 2014 10:49:46 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=WDrK5Bi+GWgQUWuGT3OL+T/Kak/MEia6RhgL4XnOyxQj5V k8BglECGSskKC9MYJd1TUPayOCCCXMQxuojob8MGnRRCeumA+C/zmrkX/JALCeWj K/YAfdWAJk5Br1bo1pbGA69cm4G7jI0nAhOzEXJKBvzfmrhT2UG8kM9tIe5Lo= 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 :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=AL4gh+GWWyd2PPZ8xzRvopXZZS4=; b=dBgCRpMF2J6AWs0u0pnE qGclyTsh4Ji1YbikrZpqeuBb80K1WabcG7KRxSR3yukpVwrylHpg9MNSqPnNBNlE hsyeBlb1mZ13y33rFXpIYlmWoJOuYPW4L8VfT/r0UC2Zl+OeUIdm6ikxgpM3axXi AUIqZXthYArBrqAKGc/viS4= Received: (qmail 964 invoked by alias); 22 Jul 2014 00:49:37 -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 949 invoked by uid 89); 22 Jul 2014 00:49:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: vms173013pub.verizon.net Received: from vms173013pub.verizon.net (HELO vms173013pub.verizon.net) (206.46.173.13) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 22 Jul 2014 00:49:35 +0000 Received: from [192.168.1.4] ([unknown] [173.69.187.216]) by vms173013.mailsrvcs.net (Sun Java(tm) System Messaging Server 7u2-7.02 32bit (built Apr 16 2009)) with ESMTPA id <0N9300F468Y57J20@vms173013.mailsrvcs.net> for gcc-patches@gcc.gnu.org; Mon, 21 Jul 2014 19:49:18 -0500 (CDT) Message-id: <53CDB50D.5050306@verizon.net> Date: Mon, 21 Jul 2014 20:49:17 -0400 From: Ed Smith-Rowland <3dw4rd@verizon.net> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-version: 1.0 To: gcc-patches , Jason Merrill Subject: Implement N4051 - Allow typename in a template template parameter Content-type: multipart/mixed; boundary=------------090505060100010107020003 This little annoyance has bugged me a couple of times over the years: template struct A {}; template using B = int; template class X> struct C; C ca; // ok C cb; // ok, not a class template template typename X> struct D; // error, cannot use typename here C++17 it seems allows typename in template template parms. Built and tested on x86_64-linux. Allowed with std=gnu/c++1z of course. OK? cp/ 2014-07-22 Edward Smith-Rowland <3dw4rd@verizon.net> Implement N4051 - Allow typename in a template template parameter * parser.c (enum required_token): Add RT_TYPE_PARAMETER_KEY; (cp_parser_type_parameter_key): New funtion; (cp_parser_token_is_type_parameter_key): Ditto; (cp_parser_type_parameter): Look for type-parameter-key for cxx1z or or greater; (cp_parser_required_error): Error for RT_TYPE_PARAMETER_KEY. testsuite/ 2014-07-22 Edward Smith-Rowland <3dw4rd@verizon.net> Implement N4051 - Allow typename in a template template parameter * g++.dg/cpp1z/typename-tmpl-tmpl-parm.C: New. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 178114d..7fef8fc 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -177,6 +177,7 @@ typedef enum required_token { RT_INTERATION, /* iteration-statement */ RT_JUMP, /* jump-statement */ RT_CLASS_KEY, /* class-key */ + RT_TYPE_PARAMETER_KEY, /* type-parameter-key */ RT_CLASS_TYPENAME_TEMPLATE, /* class, typename, or template */ RT_TRANSACTION_ATOMIC, /* __transaction_atomic */ RT_TRANSACTION_RELAXED, /* __transaction_relaxed */ @@ -2151,6 +2152,8 @@ static tree cp_parser_class_head (cp_parser *, bool *); static enum tag_types cp_parser_class_key (cp_parser *); +static enum tag_types cp_parser_type_parameter_key + (cp_parser* parser); static void cp_parser_member_specification_opt (cp_parser *); static void cp_parser_member_declaration @@ -2409,6 +2412,8 @@ static bool cp_parser_nth_token_starts_template_argument_list_p (cp_parser *, size_t); static enum tag_types cp_parser_token_is_class_key (cp_token *); +static enum tag_types cp_parser_token_is_type_parameter_key + (cp_token *); static void cp_parser_check_class_key (enum tag_types, tree type); static void cp_parser_check_access_in_redeclaration @@ -13375,8 +13380,18 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) cp_parser_template_parameter_list (parser); /* Look for the `>'. */ cp_parser_require (parser, CPP_GREATER, RT_GREATER); - /* Look for the `class' keyword. */ - cp_parser_require_keyword (parser, RID_CLASS, RT_CLASS); + if (cxx_dialect < cxx1z) + { + /* Look for the `class' keyword. */ + cp_parser_require_keyword (parser, RID_CLASS, RT_CLASS); + } + else + { + /* Look for the `class' or 'typename' keywords. */ + enum tag_types tag_type = cp_parser_type_parameter_key (parser); + if (tag_type == none_type) + return error_mark_node; + } /* If the next token is an ellipsis, we have a template argument pack. */ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) @@ -20258,6 +20273,33 @@ cp_parser_class_key (cp_parser* parser) return tag_type; } +/* Parse a type-parameter-key. + + type-parameter-key: + class + typedef + + Returns the kind of type-parameter-key specified, or none_type to indicate + error. */ + +static enum tag_types +cp_parser_type_parameter_key (cp_parser* parser) +{ + cp_token *token; + enum tag_types tag_type; + + /* Look for the type-parameter-key. */ + token = cp_parser_require (parser, CPP_KEYWORD, RT_TYPE_PARAMETER_KEY); + if (!token) + return none_type; + + /* Check to see if the TOKEN is a type-parameter-key. */ + tag_type = cp_parser_token_is_type_parameter_key (token); + if (!tag_type) + cp_parser_error (parser, "expected type-parameter-key"); + return tag_type; +} + /* Parse an (optional) member-specification. member-specification: @@ -24543,6 +24585,9 @@ cp_parser_required_error (cp_parser *parser, case RT_CLASS_KEY: cp_parser_error (parser, "expected class-key"); return; + case RT_TYPE_PARAMETER_KEY: + cp_parser_error (parser, "expected % or %"); + return; case RT_CLASS_TYPENAME_TEMPLATE: cp_parser_error (parser, "expected %, %, or %"); @@ -24776,6 +24821,24 @@ cp_parser_token_is_class_key (cp_token* token) } } +/* Returns the kind of tag indicated by TOKEN, if it is a type-parameter-key, + or none_type otherwise. */ + +static enum tag_types +cp_parser_token_is_type_parameter_key (cp_token* token) +{ + switch (token->keyword) + { + case RID_CLASS: + return class_type; + case RID_TYPENAME: + return typename_type; + + default: + return none_type; + } +} + /* Issue an error message if the CLASS_KEY does not match the TYPE. */ static void diff --git a/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C new file mode 100644 index 0000000..0a4e26f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C @@ -0,0 +1,21 @@ +// { dg-options "-std=c++1z" } + +template + struct A {}; + +template + using B = int; + +template class X> + struct C {}; + +C ca; + +C cb; + +template typename X> + struct D {}; + +D da; + +D db;