The use_partial_inst_tmpl code in lookup_template_class didn't work as
intended because when converting the ref-to-fn parameter to the same
type we wrapped it in a couple of extra NOP_EXPR.

Tested x86_64-pc-linux-gnu, applying to trunk and 7.
commit ac1c39476b98ab4b6b52952df5baa07cf923d4e0
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Feb 16 13:34:24 2018 -0500

            PR c++/82664 - ICE with reference to function template parm.
    
            * pt.c (convert_nontype_argument_function): Avoid obfuscationg
            NOP_EXPRs.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 268cfe5a454..89790717eca 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6143,7 +6143,12 @@ convert_nontype_argument_function (tree type, tree expr,
 
  accept:
   if (TREE_CODE (type) == REFERENCE_TYPE)
-    fn = build_address (fn);
+    {
+      if (REFERENCE_REF_P (fn))
+       fn = TREE_OPERAND (fn, 0);
+      else
+       fn = build_address (fn);
+    }
   if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (fn)))
     fn = build_nop (type, fn);
 
diff --git a/gcc/testsuite/g++.dg/template/nontype-fn1.C 
b/gcc/testsuite/g++.dg/template/nontype-fn1.C
new file mode 100644
index 00000000000..12d29a91a54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/nontype-fn1.C
@@ -0,0 +1,11 @@
+// PR c++/82664
+
+template < typename > struct target_disambiguator;
+template < typename R, typename A1 > struct target_disambiguator< R(A1) > {
+  typedef A1 type;
+  template < R (&)() > struct layout;
+};
+
+int main() {
+  typedef target_disambiguator< void (int) > ::type target_type ;
+}

Reply via email to