]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: fix parsing with auto(x) at block scope [PR112482]
authorMarek Polacek <polacek@redhat.com>
Thu, 14 Dec 2023 17:01:21 +0000 (12:01 -0500)
committerMarek Polacek <polacek@redhat.com>
Thu, 14 Dec 2023 21:39:51 +0000 (16:39 -0500)
This is sort of like r14-5514, but at block scope.  Consider

  struct A { A(int, int); };
  void
  g (int a)
  {
    A bar(auto(a), 42); // not a fn decl
  }

where we emit error: 'auto' parameter not permitted in this context
which is bogus -- bar doesn't declare a function, so the auto is OK,
but we don't know it till we've seen the second argument.  The error
comes from grokdeclarator invoked just after we've parsed the auto(a).

A possible approach seems to be to delay the auto parameter checking
and only check once we know we are indeed dealing with a function
declaration.  For tparms, we should still emit the error right away.

PR c++/112482

gcc/cp/ChangeLog:

* decl.cc (grokdeclarator): Do not issue the auto parameter error while
tentatively parsing a function parameter.
* parser.cc (cp_parser_parameter_declaration_clause): Check it here.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/auto-fncast15.C: New test.

gcc/cp/decl.cc
gcc/cp/parser.cc
gcc/testsuite/g++.dg/cpp23/auto-fncast15.C [new file with mode: 0644]

index 4d17ead123ac84bbfef5160d137bc74a025cc5bf..1ffe4c82748a07c342256b5d2b5ae1dde0dd93fb 100644 (file)
@@ -14203,6 +14203,7 @@ grokdeclarator (const cp_declarator *declarator,
       tree auto_node = type_uses_auto (type);
       if (auto_node && !(cxx_dialect >= cxx17 && template_parm_flag))
        {
+         bool err_p = true;
          if (cxx_dialect >= cxx14)
            {
              if (decl_context == PARM && AUTO_IS_DECLTYPE (auto_node))
@@ -14221,13 +14222,21 @@ grokdeclarator (const cp_declarator *declarator,
                            "abbreviated function template");
                  inform (DECL_SOURCE_LOCATION (c), "%qD declared here", c);
                }
-             else
+             else if (decl_context == CATCHPARM || template_parm_flag)
                error_at (typespec_loc,
                          "%<auto%> parameter not permitted in this context");
+             else
+               /* Do not issue an error while tentatively parsing a function
+                  parameter: for T t(auto(a), 42);, when we just saw the 1st
+                  parameter, we don't know yet that this construct won't be
+                  a function declaration.  Defer the checking to
+                  cp_parser_parameter_declaration_clause.  */
+               err_p = false;
            }
          else
            error_at (typespec_loc, "parameter declared %<auto%>");
-         type = error_mark_node;
+         if (err_p)
+           type = error_mark_node;
        }
 
       /* A parameter declared as an array of T is really a pointer to T.
index 58e910d64afe7830cbca6493fd22c43b7f134a01..e4fbab1bab5b8c90a17aaf38e8b8a39578c7478e 100644 (file)
@@ -25102,8 +25102,21 @@ cp_parser_parameter_declaration_clause (cp_parser* parser,
      committed yet, nor should we.  Pushing here will detect the error
      of redefining a parameter.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
-    for (tree p : pending_decls)
-      pushdecl (p);
+    {
+      for (tree p : pending_decls)
+       pushdecl (p);
+
+      /* Delayed checking of auto parameters.  */
+      if (!parser->auto_is_implicit_function_template_parm_p
+         && cxx_dialect >= cxx14)
+       for (tree p = parameters; p; p = TREE_CHAIN (p))
+         if (type_uses_auto (TREE_TYPE (TREE_VALUE (p))))
+           {
+             error_at (location_of (TREE_VALUE (p)),
+                       "%<auto%> parameter not permitted in this context");
+             TREE_TYPE (TREE_VALUE (p)) = error_mark_node;
+           }
+    }
 
   /* Finish the parameter list.  */
   if (!ellipsis_p)
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast15.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast15.C
new file mode 100644 (file)
index 0000000..deb1efc
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/112482
+// { dg-do compile { target c++23 } }
+// { dg-options "-Wno-vexing-parse" }
+
+void foo (auto i, auto j);
+
+struct A {
+   A(int,int);
+};
+
+void
+g (int a)
+{
+  A b1(auto(42), auto(42));
+  A b2(auto(a), auto(42));
+  A b3(auto(42), auto(a));
+  A b4(auto(a), // { dg-error "13:'auto' parameter" }
+       auto(a2)); // { dg-error "13:'auto' parameter" }
+  int v1(auto(42));
+  int fn1(auto(a)); // { dg-error "16:'auto' parameter" }
+}