re PR c++/60167 (Bogus error: conflicting declaration)
authorJason Merrill <jason@redhat.com>
Fri, 21 Feb 2014 14:00:44 +0000 (09:00 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 21 Feb 2014 14:00:44 +0000 (09:00 -0500)
PR c++/60167
PR c++/60222
PR c++/58606
* parser.c (cp_parser_template_argument): Restore dereference.
* pt.c (template_parm_to_arg): Dereference non-pack expansions too.
(process_partial_specialization): Handle deref.
(unify): Likewise.

From-SVN: r207994

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/ref7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/ref8.C [new file with mode: 0644]

index 7d4af6d..be248e1 100644 (file)
@@ -1,3 +1,13 @@
+2014-02-21  Jason Merrill  <jason@redhat.com>
+
+       PR c++/60167
+       PR c++/60222
+       PR c++/58606
+       * parser.c (cp_parser_template_argument): Restore dereference.
+       * pt.c (template_parm_to_arg): Dereference non-pack expansions too.
+       (process_partial_specialization): Handle deref.
+       (unify): Likewise.
+
 2014-02-21  Adam Butcher  <adam@jessamine.co.uk>
 
        PR c++/60052
index 1e4e3df..e067a02 100644 (file)
@@ -13937,6 +13937,7 @@ cp_parser_template_argument (cp_parser* parser)
 
          if (INDIRECT_REF_P (argument))
            {
+             /* Strip the dereference temporarily.  */
              gcc_assert (REFERENCE_REF_P (argument));
              argument = TREE_OPERAND (argument, 0);
            }
@@ -13975,6 +13976,8 @@ cp_parser_template_argument (cp_parser* parser)
              if (address_p)
                argument = build_x_unary_op (loc, ADDR_EXPR, argument,
                                             tf_warning_or_error);
+             else
+               argument = convert_from_reference (argument);
              return argument;
            }
        }
index 6477fce..4cf387a 100644 (file)
@@ -3861,6 +3861,8 @@ template_parm_to_arg (tree t)
          SET_ARGUMENT_PACK_ARGS (t, vec);
          TREE_TYPE (t) = type;
        }
+      else
+       t = convert_from_reference (t);
     }
   return t;
 }
@@ -4218,10 +4220,12 @@ process_partial_specialization (tree decl)
           if (/* These first two lines are the `non-type' bit.  */
               !TYPE_P (arg)
               && TREE_CODE (arg) != TEMPLATE_DECL
-              /* This next line is the `argument expression is not just a
+              /* This next two lines are the `argument expression is not just a
                  simple identifier' condition and also the `specialized
                  non-type argument' bit.  */
-              && TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
+              && TREE_CODE (arg) != TEMPLATE_PARM_INDEX
+             && !(REFERENCE_REF_P (arg)
+                  && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_PARM_INDEX))
             {
               if ((!packed_args && tpd.arg_uses_template_parms[i])
                   || (packed_args && uses_template_parms (arg)))
@@ -17893,6 +17897,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
       /* Unification fails if we hit an error node.  */
       return unify_invalid (explain_p);
 
+    case INDIRECT_REF:
+      if (REFERENCE_REF_P (parm))
+       return unify (tparms, targs, TREE_OPERAND (parm, 0), arg,
+                     strict, explain_p);
+      /* FALLTHRU */
+
     default:
       /* An unresolved overload is a nondeduced context.  */
       if (is_overloaded_fn (parm) || type_unknown_p (parm))
diff --git a/gcc/testsuite/g++.dg/template/ref7.C b/gcc/testsuite/g++.dg/template/ref7.C
new file mode 100644 (file)
index 0000000..f6395e2
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/60167
+
+template <int& F>
+struct Foo {
+  typedef int Bar;
+
+  static Bar cache;
+};
+
+template <int& F> typename Foo<F>::Bar Foo<F>::cache;
diff --git a/gcc/testsuite/g++.dg/template/ref8.C b/gcc/testsuite/g++.dg/template/ref8.C
new file mode 100644 (file)
index 0000000..a2fc847
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/60222
+
+template<int&> struct A
+{
+  template<typename> struct B;
+
+  template<typename T> struct B<T*> {};
+};