In this testcase, the only returns are inside a constexpr if, and when we're partially instantiating a generic lambda we don't mess with a constexpr if with a dependent condition, so we don't see the returns. Fixed by copying the relevant flags from the uninstantiated lambda.
Tested x86_64-pc-linux-gnu, applying to trunk and 8.
commit 788c94f8dc670e61c97654d3c42a0af4356ca88d Author: Jason Merrill <ja...@redhat.com> Date: Thu May 24 10:50:08 2018 -0400 PR c++/85842 - -Wreturn-type, constexpr if and generic lambda. * pt.c (tsubst_lambda_expr): Copy current_function_returns_* to generic lambda. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d1181055af4..01a3ad92439 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17636,6 +17636,17 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) register_parameter_specializations (oldfn, fn); + if (oldtmpl) + { + /* We might not partially instantiate some parts of the function, so + copy these flags from the original template. */ + language_function *ol = DECL_STRUCT_FUNCTION (oldfn)->language; + current_function_returns_value = ol->returns_value; + current_function_returns_null = ol->returns_null; + current_function_returns_abnormally = ol->returns_abnormally; + current_function_infinite_loop = ol->infinite_loop; + } + tsubst_expr (DECL_SAVED_TREE (oldfn), args, complain, r, /*constexpr*/false); diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if23.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if23.C new file mode 100644 index 00000000000..8e31db3e863 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if23.C @@ -0,0 +1,13 @@ +// PR c++/85842 +// { dg-additional-options -std=c++17 } + +template<class T> +auto f = [](auto&& arg) -> T* { + if constexpr (sizeof(arg) == 1) { + return nullptr; + } else { + return static_cast<T*>(&arg); + } +}; + +auto p = f<int>(0);