https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111352

Egas  Ribeiro <egas.g.ribeiro at tecnico dot ulisboa.pt> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |egas.g.ribeiro at tecnico dot 
ulis
                   |                            |boa.pt

--- Comment #5 from Egas  Ribeiro <egas.g.ribeiro at tecnico dot ulisboa.pt> ---
I attempted a fix by adding cp_parser_simulate_error check before the error in
cp_parser_parameter_declaration_clause (see patch below). This fixes the
original test case, but causes a regression in g++.dg/cpp23/auto-fncast15.C.
The issue is that my fix prevents the error from being emitted during tentative
parsing, but in auto-fncast15.C, the code like A b4(auto(a), auto(a2)) should
error because it's attempting an implicit function template declaration at
block scope (which isn't allowed). After my change, GCC incorrectly treats this
as a constructor call instead of recognizing it as an invalid function
declaration.
This appears to conflict with the fix for PR112482 (commit 1ae71269), which
moved the auto parameter check to cp_parser_parameter_declaration_clause
specifically to handle these block-scope cases. The challenge is distinguishing
between:

Valid: AA aa(Constructor([&](auto& p) {...})) - constructor with lambda
Invalid: A b4(auto(a), auto(a2)) - implicit function template at block scope


I need to understand why the tentative parse path is treating b4 differently
after my change. It seems that by suppressing the error during tentative
parsing, GCC is recognizing this as a constructor call rather than as an
invalid function declaration.

Hope this helps someone.

---
        PR c++/111352

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_parameter_declaration_clause): Suppress
          auto parameter error during tentative parsing.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp1z/lambda-pr111352.C: New test.
---
 gcc/cp/parser.cc                             |  5 +-
 gcc/testsuite/g++.dg/cpp1z/lambda-pr111352.C | 50 ++++++++++++++++++++
 2 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/lambda-pr111352.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9280632d47b..e4bd35e0def 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -26820,8 +26820,9 @@ cp_parser_parameter_declaration_clause (cp_parser*
parser,
        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");
+             if (!cp_parser_simulate_error (parser))
+               error_at (location_of (TREE_VALUE (p)),
+                         "%<auto%> parameter not permitted in this context");
              TREE_TYPE (TREE_VALUE (p)) = error_mark_node;
            }
     }
diff --git a/gcc/testsuite/g++.dg/cpp1z/lambda-pr111352.C
b/gcc/testsuite/g++.dg/cpp1z/lambda-pr111352.C
new file mode 100644
index 00000000000..46832c33697
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/lambda-pr111352.C
@@ -0,0 +1,50 @@
+// PR c++/111352
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+    int x;
+};
+
+template <typename L> struct Constructor
+{
+    const L& lambda;
+    Constructor(const L& lambda) :
+        lambda(lambda)
+    {
+    }
+    operator A () const
+    {
+        A out;
+        lambda(out);
+        return out;
+    }
+};
+
+
+struct AA
+{
+    int x{0};
+
+    AA()
+    {
+    }
+
+    AA(A op) :
+        x(op.x)
+    {
+    }
+};
+
+template <typename L> Constructor<L> 
+make_constructor(const L& lambda)
+{
+    return Constructor<L>(lambda);
+}
+
+int main()
+{
+    AA aa (make_constructor([&](auto& p) { p.x = 1; }));
+    AA bb = AA( make_constructor([&](auto& p) { p.x = 1; }));
+}
+
-- 
2.51.0

Reply via email to