https://gcc.gnu.org/g:40f0f6ab75a391906bed40cbdc098b0df3a91af7
commit r15-6736-g40f0f6ab75a391906bed40cbdc098b0df3a91af7 Author: Patrick Palka <ppa...@redhat.com> Date: Thu Jan 9 10:49:45 2025 -0500 c++: template-id dependence wrt local static arg [PR117792] Here we end up ICEing at instantiation time for the call to f<local_static> ultimately because we wrongly consider the call to be non-dependent, and so we specialize f ahead of time and then get confused when fully substituting this specialization. The call is dependent due to [temp.dep.temp]/3 and we miss that because function template-id arguments aren't coerced until overload resolution, and so the local static template argument lacks an implicit cast to reference type that value_dependent_expression_p looks for before considering dependence of the address. Other kinds of template-ids aren't affected since they're coerced ahead of time. So when considering dependence of a function template-id, we need to conservatively consider dependence of the address of each argument (if applicable). PR c++/117792 gcc/cp/ChangeLog: * pt.cc (type_dependent_expression_p): Consider the dependence of the address of each template argument of a function template-id. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/nontype7.C: New test. Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- gcc/cp/pt.cc | 10 ++++++++-- gcc/testsuite/g++.dg/cpp1z/nontype7.C | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dfaa8906a2cf..081285ef7209 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -29034,9 +29034,15 @@ type_dependent_expression_p (tree expression) if (TREE_CODE (expression) == TEMPLATE_ID_EXPR) { - if (any_dependent_template_arguments_p - (TREE_OPERAND (expression, 1))) + tree args = TREE_OPERAND (expression, 1); + if (any_dependent_template_arguments_p (args)) return true; + /* Arguments of a function template-id aren't necessarily coerced + yet so we must conservatively assume that the address (and not + just value) of the argument matters as per [temp.dep.temp]/3. */ + for (tree arg : tree_vec_range (args)) + if (has_value_dependent_address (arg)) + return true; expression = TREE_OPERAND (expression, 0); if (identifier_p (expression)) return true; diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype7.C b/gcc/testsuite/g++.dg/cpp1z/nontype7.C new file mode 100644 index 000000000000..f103d5a6888e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nontype7.C @@ -0,0 +1,22 @@ +// PR c++/117792 +// { dg-do compile { target c++17 } } + +template<const int& N, class T> +void f(T) { } + +template<int N, class T> +void f(...) = delete; + +template<const int& N> int v; + +template<const int& N> struct A { }; + +template<class T> +void g() { + static constexpr int local_static = 0; + auto x = v<local_static>; // OK + A<local_static> y; // OK + f<local_static>(0); // ICE +} + +template void g<int>();