c++: template-id dependence wrt local static arg [PR117792]

Message ID 20241127172919.2614652-1-ppalka@redhat.com
State New
Headers
Series c++: template-id dependence wrt local static arg [PR117792] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Patrick Palka Nov. 27, 2024, 5:29 p.m. UTC
  Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk/14/13?

-- >8 --

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.
---
 gcc/cp/pt.cc                          | 10 ++++++++--
 gcc/testsuite/g++.dg/cpp1z/nontype7.C | 22 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype7.C
  

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 564e368ff43..2f2ec39b083 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -28864,9 +28864,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 00000000000..b03c643c987
--- /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, class T>
+void f(...) = delete;
+
+template<const int& N> int v;
+
+template<const int& N> struct A { static const int value = 0; };
+
+template<class T>
+void g() {
+  static const int local_static = 0;
+  auto x = v<local_static>; // OK
+  auto y = A<local_static>::value; // OK
+  f<local_static>(0); // ICE
+}
+
+template void g<int>();