]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implement N4051 - Allow typename in a template template parameter
authorEdward Smith-Rowland <3dw4rd@verizon.net>
Fri, 25 Jul 2014 22:35:24 +0000 (22:35 +0000)
committerEdward Smith-Rowland <emsr@gcc.gnu.org>
Fri, 25 Jul 2014 22:35:24 +0000 (22:35 +0000)
cp/

2014-07-25  Edward Smith-Rowland  <3dw4rd@verizon.net>

Implement N4051 - Allow typename in a template template parameter
* parser.c (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 all versions
but pedwarn for less than cxx1z.

testsuite/

2014-07-25  Edward Smith-Rowland  <3dw4rd@verizon.net>

Implement N4051 - Allow typename in a template template parameter
* lib/target-supports.exp (check_effective_target_c++1y): Now
means C++1y and up.
(check_effective_target_c++1y_down): New.
(check_effective_target_c++1z_only): New.
(check_effective_target_c++1z): New.
* g++.dg/cpp1z/typename-tmpl-tmpl-parm.C: New.
* g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C: New.
* g++.dg/cpp1z/typename-tmpl-tmpl-parm-.C: New.

From-SVN: r213065

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index 779e087e4441898472d934fbe5b554cf335cb86b..cfe0a48082487f5081f75f10145e3722a4da91a4 100644 (file)
@@ -1,3 +1,11 @@
+2014-07-25  Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+       Implement N4051 - Allow typename in a template template parameter
+       * parser.c (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 all versions
+       but pedwarn for less than cxx1z.
+
 2014-07-17  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/50961
index 178114d2c840880ec3648fcdb7225c52633f6947..32c7a3fe1469531c18536e74ff52c890335bc757 100644 (file)
@@ -2151,6 +2151,8 @@ static tree cp_parser_class_head
   (cp_parser *, bool *);
 static enum tag_types cp_parser_class_key
   (cp_parser *);
+static void 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 +2411,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 +13379,8 @@ 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);
+       /* Look for the `class' or 'typename' keywords.  */
+       cp_parser_type_parameter_key (parser);
         /* 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 +20262,35 @@ cp_parser_class_key (cp_parser* parser)
   return tag_type;
 }
 
+/* Parse a type-parameter-key.
+
+   type-parameter-key:
+     class
+     typename
+ */
+
+static void
+cp_parser_type_parameter_key (cp_parser* parser)
+{
+  /* Look for the type-parameter-key.  */
+  enum tag_types tag_type = none_type;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  if ((tag_type = cp_parser_token_is_type_parameter_key (token)) != none_type)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      if (pedantic && tag_type == typename_type && cxx_dialect < cxx1z)
+       /* typename is not allowed in a template template parameter
+          by the standard until C++1Z.  */
+       pedwarn (token->location, OPT_Wpedantic, 
+                "ISO C++ forbids typename key in template template parameter;"
+                " use -std=c++1z or -std=gnu++1z");
+    }
+  else
+    cp_parser_error (parser, "expected %<class%> or %<typename%>");
+
+  return;
+}
+
 /* Parse an (optional) member-specification.
 
    member-specification:
@@ -24776,6 +24809,27 @@ 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 or if the token is null.  */
+
+static enum tag_types
+cp_parser_token_is_type_parameter_key (cp_token* token)
+{
+  if (!token)
+    return none_type;
+
+  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
index ebf7badad8272993bb0fa00344c2d85cf14737a0..92d1f9693d7918e0c3d15c2aa9dcc049c91eb2a4 100644 (file)
@@ -1,3 +1,15 @@
+2014-07-25  Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+       Implement N4051 - Allow typename in a template template parameter
+       * lib/target-supports.exp (check_effective_target_c++1y): Now
+       means C++1y and up.
+       (check_effective_target_c++1y_down): New.
+       (check_effective_target_c++1z_only): New.
+       (check_effective_target_c++1z): New.
+       * g++.dg/cpp1z/typename-tmpl-tmpl-parm.C: New.
+       * g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C: New.
+       * g++.dg/cpp1z/typename-tmpl-tmpl-parm-.C: New.
+
 2014-07-25  Tobias Burnus  <burnus@net-b.de>
 
        * gfortran.dg/storage_size_5.f90: New.
diff --git a/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C
new file mode 100644 (file)
index 0000000..29c699d
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile }
+// { dg-options "" }
+
+template<template<typename> struct X> // { dg-error "expected .class. or .typename. before" }
+  struct D {};
+
+template<template<typename> X> // { dg-error "expected .class. or .typename. before" }
+  struct E {};
+
+// { dg-error "expected identifier" "expected" { target *-*-* } 4 }
+// { dg-error "expected .>." "expected" { target *-*-* } 4 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C
new file mode 100644 (file)
index 0000000..48cb8ab
--- /dev/null
@@ -0,0 +1,28 @@
+// { dg-do compile { target c++1y_down } }
+// { dg-options "-pedantic" }
+
+template<typename T>
+  struct A {};
+
+#if __cplusplus >= 201103L
+template<typename T>
+  using B = int;
+#endif
+
+template<template<typename> class X>
+  struct C {};
+
+C<A> ca;
+
+#if __cplusplus >= 201103L
+C<B> cb;
+#endif
+
+template<template<typename> typename X> // { dg-warning "ISO C.. forbids typename key in template template parameter" }
+  struct D {};
+
+D<A> da;
+
+#if __cplusplus >= 201103L
+D<B> db;
+#endif
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 (file)
index 0000000..4c3eae1
--- /dev/null
@@ -0,0 +1,28 @@
+// { dg-do compile }
+// { dg-options "" }
+
+template<typename T>
+  struct A {};
+
+#if __cplusplus >= 201103L
+template<typename T>
+  using B = int;
+#endif
+
+template<template<typename> class X>
+  struct C {};
+
+C<A> ca;
+
+#if __cplusplus >= 201103L
+C<B> cb;
+#endif
+
+template<template<typename> typename X>
+  struct D {};
+
+D<A> da;
+
+#if __cplusplus >= 201103L
+D<B> db;
+#endif
index ade3cad1b90a3a2b816abe33e5e9a7dcbddf6e43..fa5137ea472e1773be60759caad32bbc7ab4c551 100644 (file)
@@ -5707,7 +5707,16 @@ proc check_effective_target_c++1y_only { } {
     return [check-flags { { } { } { -std=c++1y -std=gnu++1y -std=c++14 -std=gnu++14 } }]
 }
 proc check_effective_target_c++1y { } {
-    return [check_effective_target_c++1y_only]
+    if [check_effective_target_c++1y_only] {
+       return 1
+    }
+    return [check_effective_target_c++1z]
+}
+proc check_effective_target_c++1y_down { } {
+    if ![check_effective_target_c++] {
+       return 0
+    }
+    return ![check_effective_target_c++1z]
 }
 
 proc check_effective_target_c++98_only { } {
@@ -5717,6 +5726,16 @@ proc check_effective_target_c++98_only { } {
     return ![check_effective_target_c++11]
 }
 
+proc check_effective_target_c++1z_only { } {
+    if ![check_effective_target_c++] {
+       return 0
+    }
+    return [check-flags { { } { } { -std=c++1z -std=gnu++1z } }]
+}
+proc check_effective_target_c++1z { } {
+    return [check_effective_target_c++1z_only]
+}
+
 # Return 1 if expensive testcases should be run.
 
 proc check_effective_target_run_expensive_tests { } {