c++: Better diagnostic for decltype(auto) in C++11 [PR96103]

Message ID 20200707224039.606120-1-polacek@redhat.com
State New
Headers show
Series
  • c++: Better diagnostic for decltype(auto) in C++11 [PR96103]
Related show

Commit Message

Patrick Palka via Gcc-patches July 7, 2020, 10:40 p.m.
If you try to use decltype(auto) in C++11, we emit obscure

  error: expected primary-expression before 'auto'

giving the user no hint as to what's wrong.  This patch improves that
diagnostic.  Since we've been giving an error, I'm also using error().

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

gcc/cp/ChangeLog:

	PR c++/96103
	* parser.c (cp_parser_decltype): Print error about using decltype(auto)
	in C++11.  Check that the token following "auto" is ")".

gcc/testsuite/ChangeLog:

	PR c++/96103
	* g++.dg/cpp0x/decltype77.C: New test.
---
 gcc/cp/parser.c                         | 22 +++++++++++++++-------
 gcc/testsuite/g++.dg/cpp0x/decltype77.C | 10 ++++++++++
 2 files changed, 25 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype77.C


base-commit: 7126583af5d29235584b51b3b05eeaba2adef024
-- 
2.26.2

Comments

Patrick Palka via Gcc-patches July 8, 2020, 4:58 a.m. | #1
On 7/7/20 6:40 PM, Marek Polacek wrote:
> +		    "%<decltype(auto)%> type specifier is a C++14 extension");


The usual phrasing is "...only available with %<-std=c++14%> or 
%<-std=gnu++14%>".  OK with that change.

Jason

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e58d8eb298c..8aaedaefb86 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14894,11 +14894,11 @@  cp_parser_decltype_expr (cp_parser *parser,
   return expr;
 }
 
-/* Parse a `decltype' type. Returns the type.
+/* Parse a `decltype' type.  Returns the type.
 
-   simple-type-specifier:
+   decltype-specifier:
      decltype ( expression )
-   C++14 proposal:
+   C++14:
      decltype ( auto )  */
 
 static tree
@@ -14938,10 +14938,18 @@  cp_parser_decltype (cp_parser *parser)
 
   tree expr = NULL_TREE;
 
-  if (cxx_dialect >= cxx14
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
-    /* decltype (auto) */
-    cp_lexer_consume_token (parser->lexer);
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)
+      && cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN))
+    {
+      /* decltype (auto) */
+      cp_lexer_consume_token (parser->lexer);
+      if (cxx_dialect < cxx14)
+	{
+	  error_at (start_token->location,
+		    "%<decltype(auto)%> type specifier is a C++14 extension");
+	  expr = error_mark_node;
+	}
+    }
   else
     {
       /* decltype (expression)  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype77.C b/gcc/testsuite/g++.dg/cpp0x/decltype77.C
new file mode 100644
index 00000000000..1f987118510
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype77.C
@@ -0,0 +1,10 @@ 
+// PR c++/96103
+// { dg-do compile { target c++11_only } }
+
+decltype(auto) foo () { return 4; } // { dg-error ".decltype\\(auto\\). type specifier is a C\\+\\+14 extension" }
+
+void
+bar ()
+{
+  decltype(auto) i = 0; // { dg-error ".decltype\\(auto\\). type specifier is a C\\+\\+14 extension" }
+}