DR 1321 clarified that two dependent names are equivalent if the names are
the same, even if the result of name lookup is different.  So template
argument hashing should treat a lookup set like a plain identifier.
Mangling already does.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * pt.c (iterative_hash_template_arg): Hash all overload sets like an
        identifier.
---
 gcc/cp/pt.c                               | 10 +++++-----
 gcc/testsuite/g++.dg/cpp0x/fntmp-equiv1.C | 23 +++++++++++++++++++++++
 gcc/cp/ChangeLog                          |  7 +++++++
 3 files changed, 35 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/fntmp-equiv1.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f3faa89f671..ea1976bd0f5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1757,6 +1757,11 @@ iterative_hash_template_arg (tree arg, hashval_t val)
   code = TREE_CODE (arg);
   tclass = TREE_CODE_CLASS (code);
 
+  if (code == FUNCTION_DECL || code == OVERLOAD)
+    /* DR 1321: Hash a dependent name as the name, not the lookup result.  */
+    return iterative_hash_template_arg (DECL_NAME (get_first_fn (arg)),
+                                       val);
+
   val = iterative_hash_object (code, val);
 
   switch (code)
@@ -1789,11 +1794,6 @@ iterative_hash_template_arg (tree arg, hashval_t val)
        val = iterative_hash_template_arg (TREE_VALUE (arg), val);
       return val;
 
-    case OVERLOAD:
-      for (lkp_iterator iter (arg); iter; ++iter)
-       val = iterative_hash_template_arg (*iter, val);
-      return val;
-
     case CONSTRUCTOR:
       {
        tree field, value;
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmp-equiv1.C 
b/gcc/testsuite/g++.dg/cpp0x/fntmp-equiv1.C
new file mode 100644
index 00000000000..833ae6fc85c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmp-equiv1.C
@@ -0,0 +1,23 @@
+// PR c++/86946, DR 1321
+// { dg-do compile { target c++11 } }
+
+int d(int, int);
+template <long> class e {};
+template <unsigned long f, unsigned b, typename> e<sizeof(d(f, b))> d();
+template <unsigned long f, unsigned b, typename> e<d(f, b)> d();
+
+template <class T, class U> constexpr T d2(T, U) { return 42; }
+template <unsigned long f, unsigned b, typename> e<d2(f, b)> d2();
+template <unsigned long f, unsigned b, typename> e<d2(f, b)> d2();
+
+template <typename a, typename c> a d3(a, c);
+template <unsigned long f, unsigned b, typename> e<sizeof(d3(f, b))> d3();
+template <unsigned long f, unsigned b, typename> e<sizeof(d3(f, b))> d3();
+
+
+int main()
+{
+  d<1,2,int>();
+  d2<1,2,int>();
+  d3<1,2,int>();
+}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8c6e9931db1..805237cb17b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2019-04-01  Jason Merrill  <ja...@redhat.com>
+
+       PR c++/86946 - ICE with function call in template argument.
+       DR 1321
+       * pt.c (iterative_hash_template_arg): Hash all overload sets like an
+       identifier.
+
 2019-03-31  Marek Polacek  <pola...@redhat.com>
 
        PR c++/89852 - ICE with C++11 functional cast with { }.

base-commit: 9c2fddaf0c9fded1e3788fdf4bc15f2435b84df5
-- 
2.20.1

Reply via email to