In this testcase, N is only used in the lambda for its constant value,
so it should not be captured.  The problem was that we didn't call
mark_rvalue_use on N when instantiating the lambda, because it was
wrapped in a NOP_EXPR converting it to the type of the template
argument.  Rather than try to add mark_rvalue_use everywhere that
calls build_nop, let's make mark_rvalue_use look through all NOP_EXPR,
not just location wrappers.

Tested x86_64-pc-linux-gnu, applying to trunk and 8.
commit 6f0db97dbb4a43a69bc4ea4c32960cbd77b104a0
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Jun 15 17:05:39 2018 -0400

            PR c++/86147 - wrong capture for template argument.
    
            * expr.c (mark_use): Look through NOP_EXPR.

diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 9780b75d1cd..133a01b8a51 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -186,12 +186,15 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
 	    expr = convert_from_reference (r);
 	}
       break;
-    default:
+
+    CASE_CONVERT:
+    case VIEW_CONVERT_EXPR:
       if (location_wrapper_p (expr))
-	{
-	  loc = EXPR_LOCATION (expr);
-	  recurse_op[0] = true;
-	}
+	loc = EXPR_LOCATION (expr);
+      recurse_op[0] = true;
+      break;
+
+    default:
       break;
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const9.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const9.C
new file mode 100644
index 00000000000..0724ae15d88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const9.C
@@ -0,0 +1,17 @@
+// PR c++/86147
+// { dg-do compile { target c++11 } }
+
+template <class T, T N> struct X { };
+
+struct A { static constexpr int value = 0; };
+
+template<class C>
+void foo() {
+    constexpr int N = C::value;
+    auto f = [&]{  X<int, N> a; };
+}
+
+int main() { 
+    foo<A>();
+    return 0;
+}

Reply via email to