public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Jason Merrill <jason@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: [PATCH] c++: Implement P1102R2 - Down with ()!
Date: Thu, 25 Feb 2021 19:44:21 +0100	[thread overview]
Message-ID: <20210225184421.GL4020736@tucnak> (raw)

Hi!

The following patch implements P1102R2.
For attributes, we have already attribute parsing before the parameter
declarations and so when that is omitted, if the attributes are first we
already accept it.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Or defer for GCC 12?

2021-02-25  Jakub Jelinek  <jakub@redhat.com>

	P1102R2 - Down with ()!
	* parser.c (cp_parser_lambda_declarator_opt): Make ()s
	optional before lambda specifiers for -std={c,gnu}++2b or
	with pedwarn in earlier versions.

	* g++.dg/cpp23/lambda-specifiers1.C: New test.

--- gcc/cp/parser.c.jj	2021-02-12 09:58:25.341506456 +0100
+++ gcc/cp/parser.c	2021-02-25 14:28:37.525431561 +0100
@@ -11223,12 +11223,12 @@ cp_parser_lambda_introducer (cp_parser*
 /* Parse the (optional) middle of a lambda expression.
 
    lambda-declarator:
-     ( parameter-declaration-clause )
-       decl-specifier-seq [opt]
-       noexcept-specifier [opt]
-       attribute-specifier-seq [opt]
-       trailing-return-type [opt]
-       requires-clause [opt]
+     ( parameter-declaration-clause ) lambda-specifiers requires-clause [opt]
+     lambda-specifiers (C++23)
+
+   lambda-specifiers:
+     decl-specifier-seq [opt] noexcept-specifier [opt]
+       attribute-specifier-seq [opt] trailing-return-type [opt]
 
    LAMBDA_EXPR is the current representation of the lambda expression.  */
 
@@ -11248,6 +11248,8 @@ cp_parser_lambda_declarator_opt (cp_pars
   tree tx_qual = NULL_TREE;
   tree return_type = NULL_TREE;
   tree trailing_requires_clause = NULL_TREE;
+  bool has_param_list = false;
+  location_t lambda_specifiers_loc = UNKNOWN_LOCATION;
   cp_decl_specifier_seq lambda_specs;
   clear_decl_specs (&lambda_specs);
   /* A lambda op() is const unless explicitly 'mutable'.  */
@@ -11334,47 +11336,88 @@ cp_parser_lambda_declarator_opt (cp_pars
 		     "default argument specified for lambda parameter");
 
       parens.require_close (parser);
+      has_param_list = true;
+    }
+  else if (cxx_dialect < cxx23)
+    lambda_specifiers_loc = cp_lexer_peek_token (parser->lexer)->location;
 
-      /* In the decl-specifier-seq of the lambda-declarator, each
-	 decl-specifier shall either be mutable or constexpr.  */
-      int declares_class_or_enum;
-      if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
-	  && !cp_next_tokens_can_be_gnu_attribute_p (parser))
-	cp_parser_decl_specifier_seq (parser,
-				      CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
-				      &lambda_specs, &declares_class_or_enum);
-      if (lambda_specs.storage_class == sc_mutable)
-	{
-	  LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
-	  quals = TYPE_UNQUALIFIED;
-	  if (lambda_specs.conflicting_specifiers_p)
-	    error_at (lambda_specs.locations[ds_storage_class],
-		      "duplicate %<mutable%>");
-	}
+  /* In the decl-specifier-seq of the lambda-declarator, each
+     decl-specifier shall either be mutable or constexpr.  */
+  int declares_class_or_enum;
+  if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
+      && !cp_next_tokens_can_be_gnu_attribute_p (parser))
+    cp_parser_decl_specifier_seq (parser,
+				  CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
+				  &lambda_specs, &declares_class_or_enum);
+
+  if (lambda_specifiers_loc
+      && (lambda_specs.storage_class == sc_mutable
+	  || lambda_specs.locations[ds_constexpr]
+	  || lambda_specs.locations[ds_consteval]))
+    {
+      pedwarn (lambda_specifiers_loc, 0,
+	       "parameter declaration before lambda declaration "
+	       "specifiers only optional with %<-std=c++2b%> or "
+	       "%<-std=gnu++2b%>");
+      lambda_specifiers_loc = UNKNOWN_LOCATION;
+    }
+
+  if (lambda_specs.storage_class == sc_mutable)
+    {
+      LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
+      quals = TYPE_UNQUALIFIED;
+      if (lambda_specs.conflicting_specifiers_p)
+	error_at (lambda_specs.locations[ds_storage_class],
+		  "duplicate %<mutable%>");
+    }
+
+  tx_qual = cp_parser_tx_qualifier_opt (parser);
+  if (lambda_specifiers_loc && tx_qual)
+    {
+      pedwarn (lambda_specifiers_loc, 0,
+	       "parameter declaration before lambda transaction "
+	       "qualifier only optional with %<-std=c++2b%> or "
+	       "%<-std=gnu++2b%>");
+      lambda_specifiers_loc = UNKNOWN_LOCATION;
+    }
+
+  /* Parse optional exception specification.  */
+  exception_spec
+    = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE);
+
+  if (lambda_specifiers_loc && exception_spec)
+    {
+      pedwarn (lambda_specifiers_loc, 0,
+	       "parameter declaration before lambda exception "
+	       "specification only optional with %<-std=c++2b%> or "
+	       "%<-std=gnu++2b%>");
+      lambda_specifiers_loc = UNKNOWN_LOCATION;
+    }
 
-      tx_qual = cp_parser_tx_qualifier_opt (parser);
+  std_attrs = cp_parser_std_attribute_spec_seq (parser);
 
-      /* Parse optional exception specification.  */
-      exception_spec
-	= cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE);
-
-      std_attrs = cp_parser_std_attribute_spec_seq (parser);
-
-      /* Parse optional trailing return type.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
-        {
-          cp_lexer_consume_token (parser->lexer);
-          return_type = cp_parser_trailing_type_id (parser);
-        }
+  /* Parse optional trailing return type.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+    {
+      if (lambda_specifiers_loc)
+	pedwarn (lambda_specifiers_loc, 0,
+		 "parameter declaration before lambda trailing "
+		 "return type only optional with %<-std=c++2b%> or "
+		 "%<-std=gnu++2b%>");
+      cp_lexer_consume_token (parser->lexer);
+      return_type = cp_parser_trailing_type_id (parser);
+    }
 
-      if (cp_next_tokens_can_be_gnu_attribute_p (parser))
-	gnu_attrs = cp_parser_gnu_attributes_opt (parser);
+  if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+    gnu_attrs = cp_parser_gnu_attributes_opt (parser);
 
+  if (has_param_list)
+    {
       /* Parse optional trailing requires clause.  */
       trailing_requires_clause = cp_parser_requires_clause_opt (parser, false);
 
-      /* The function parameters must be in scope all the way until after the
-         trailing-return-type in case of decltype.  */
+      /* The function parameters must be in scope all the way until after
+	 the trailing-return-type in case of decltype.  */
       pop_bindings_and_leave_scope ();
     }
 
--- gcc/testsuite/g++.dg/cpp23/lambda-specifiers1.C.jj	2021-02-25 14:55:14.719567663 +0100
+++ gcc/testsuite/g++.dg/cpp23/lambda-specifiers1.C	2021-02-25 15:00:36.608082855 +0100
@@ -0,0 +1,18 @@
+// P1102R2 - Down with ()!
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+void
+foo ()
+{
+  auto a = [] mutable {};	// { dg-warning "parameter declaration before lambda declaration specifiers only optional with" "" { target c++20_down } }
+#if __cpp_constexpr >= 201603L
+  auto b = [] constexpr {};	// { dg-warning "parameter declaration before lambda declaration specifiers only optional with" "" { target { c++17 && c++20_down } } }
+#endif
+#if __cpp_consteval >= 201811L
+  auto c = [] consteval {};	// { dg-warning "parameter declaration before lambda declaration specifiers only optional with" "" { target c++20_only } }
+#endif
+  auto d = [] throw() {};	// { dg-warning "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } }
+  auto e = [] noexcept {};	// { dg-warning "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } }
+  auto f = [] -> int { return 0; };	// { dg-warning "parameter declaration before lambda trailing return type only optional with" "" { target c++20_down } }
+}

	Jakub


             reply	other threads:[~2021-02-25 18:44 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-25 18:44 Jakub Jelinek [this message]
2021-02-25 21:22 ` Jason Merrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210225184421.GL4020736@tucnak \
    --to=jakub@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).