c++: Fix ICE with lambda in member operator (PR93279)
authorJason Merrill <jason@redhat.com>
Fri, 24 Jan 2020 23:20:56 +0000 (18:20 -0500)
committerJason Merrill <jason@redhat.com>
Sat, 25 Jan 2020 03:18:46 +0000 (22:18 -0500)
Here the problem was that we were remembering the lookup in template scope,
and then trying to reuse that lookup in the instantiation without
substituting into it at all.  The simplest solution is to not try to
remember a lookup that finds a class-scope declaration, as in that case
doing the normal lookup again at instantiation time will always find the
right declarations.

PR c++/93279 - ICE with lambda in member operator.
* name-lookup.c (maybe_save_operator_binding): Don't remember
class-scope bindings.

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template16.C [new file with mode: 0644]

index cddf169ea5bf5081acc51fd0917c3e50328f65c8..764b9ccffa384d668a4c250a2d2cb4c1ee6a8b0e 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-24  Jason Merrill  <jason@redhat.com>
+
+       PR c++/93279 - ICE with lambda in member operator.
+       * name-lookup.c (maybe_save_operator_binding): Don't remember
+       class-scope bindings.
+
 2020-01-24  Jason Merrill  <jason@redhat.com>
 
        PR c++/93377 - ICE with member alias in constraint.
index cd7a5816e463c116a04c88a1731f0daaaed423e4..572100766cb345deb8967f9866331ca43eef25ca 100644 (file)
@@ -7616,6 +7616,12 @@ maybe_save_operator_binding (tree e)
 
   if (!fns && (fns = op_unqualified_lookup (fnname)))
     {
+      tree fn = get_first_fn (fns);
+      if (DECL_CLASS_SCOPE_P (fn))
+       /* We don't need to remember class-scope functions, normal unqualified
+          lookup will find them again.  */
+       return;
+
       bindings = tree_cons (fnname, fns, bindings);
       if (attr)
        TREE_VALUE (attr) = bindings;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template16.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template16.C
new file mode 100644 (file)
index 0000000..faaff68
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/93279
+// { dg-do compile { target c++11 } }
+
+template <typename T> struct B { using f = int; };
+template <typename T, int N> struct E {
+  template <typename U, typename B<E>::f = 0>
+  void operator*(U l) { [l](T m) { m * l; }; }
+};
+
+int
+main ()
+{
+  E<E<float, 4>, 1> n;
+  n * 4.f;
+}