Tested through compiler explorer with the version 6.0.0 (trunk 317548). Link of the example: https://godbolt.org/g/Q91sd1 code: struct A { constexpr A() {} }; template<class T> void func(T x) { constexpr auto y = x(); (void)[] { auto x = y; }; //with non literal: "error: variable 'y' cannot be implicitly captured in a lambda with no capture-default specified" struct A { decltype(y) value = y; }; //with non-literal: "error: reference to local variable 'y' declared in enclosing function ..." } int main() { func([]{return 3;}); //no error func([]{return A{}; }); //error } log: 7 : <source>:7:25: error: variable 'y' cannot be implicitly captured in a lambda with no capture-default specified (void)[] { auto x = y; }; ^ 14 : <source>:14:5: note: in instantiation of function template specialization 'func<(lambda at /tmp/compiler-explorer-compiler117108-60-mn1ptp.k9dm5i2j4i/example.cpp:14:10)>' requested here func([]{return A{}; }); ^ 6 : <source>:6:20: note: 'y' declared here constexpr auto y = x(); ^ 7 : <source>:7:11: note: lambda expression begins here (void)[] { auto x = y; }; ^ 8 : <source>:8:36: error: reference to local variable 'y' declared in enclosing function 'func<(lambda at /tmp/compiler-explorer-compiler117108-60-mn1ptp.k9dm5i2j4i/example.cpp:14:10)>' struct A { decltype(y) value = y; }; ^ 8 : <source>:8:12: note: in instantiation of default member initializer 'func((lambda at /tmp/compiler-explorer-compiler117108-60-mn1ptp.k9dm5i2j4i/example.cpp:14:10))::A::value' requested here struct A { decltype(y) value = y; }; ^ 14 : <source>:14:5: note: in instantiation of function template specialization 'func<(lambda at /tmp/compiler-explorer-compiler117108-60-mn1ptp.k9dm5i2j4i/example.cpp:14:10)>' requested here func([]{return A{}; }); ^ 6 : <source>:6:20: note: 'y' declared here constexpr auto y = x(); ^ version: clang version 6.0.0 (trunk 317548) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /opt/compiler-explorer/clang-trunk/bin Found candidate GCC installation: /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0 Selected GCC installation: /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0 Candidate multilib: .;@m64 Selected multilib: .;@m64 "/opt/compiler-explorer/clang-trunk-20171107/bin/clang-6.0" -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -disable-llvm-verifier -discard-value-names -main-file-name example.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -v -coverage-notes-file /tmp/compiler-explorer-compiler117108-60-ffz0kd.942tymn29/output.gcno -resource-dir /opt/compiler-explorer/clang-trunk-20171107/lib/clang/6.0.0 -c-isystem /usr/include/x86_64-linux-gnu -cxx-isystem /usr/include/x86_64-linux-gnu -internal-isystem /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0 -internal-isystem /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0/x86_64-linux-gnu -internal-isystem /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0/backward -internal-isystem /usr/local/include -internal-isystem /opt/compiler-explorer/clang-trunk-20171107/lib/clang/6.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++1z -fdeprecated-macro -fdebug-compilation-dir /compiler-explorer -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -mllvm --x86-asm-syntax=intel -o /tmp/compiler-explorer-compiler117108-60-ffz0kd.942tymn29/output.s -x c++ <source> clang -cc1 version 6.0.0 based upon LLVM 6.0.0svn default target x86_64-unknown-linux-gnu ignoring nonexistent directory "/include" ignoring duplicate directory "/usr/include/x86_64-linux-gnu" #include "..." search starts here: #include <...> search starts here: /usr/include/x86_64-linux-gnu /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0 /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0/x86_64-linux-gnu /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0/backward /usr/local/include /opt/compiler-explorer/clang-trunk-20171107/lib/clang/6.0.0/include /usr/include
It looks like you have two separate test cases here. The first test case can be reduced to ``` void a() { constexpr auto x = 0; [] { x; }; } ``` I believe clang is correct to reject this program. The second test case is ``` struct A { }; void g() { constexpr auto x = A(); struct B { A value = x; }; } ``` clang also rejects this program, and I agree that it's surprising that it is accepted if all of the `A` in `g` are replaced with `int`, but I also believe clang is correct to reject this program.
From: https://en.cppreference.com/w/cpp/language/lambda ` A lambda expression can read the value of a variable without capturing it if the variable has const non-volatile integral or enumeration type and has been initialized with a constant expression, or is constexpr and has no mutable members. ` So the example you've provided is actually a reject-valid here: ``` void a() { constexpr auto x = 0; [] { x; }; //error here } ``` but even if, it doesn't explain why being in a dependent scope (template) would turn it into a valid: ``` template<class T = int> void func() { constexpr auto y = 0; [] { auto x = y; }; //no longer an error here } int main() { func(); } ```