]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/37177 ([c++0x] ICE on decltype(rel_ops::operator><int>);)
authorJason Merrill <jason@redhat.com>
Thu, 8 Oct 2009 16:09:22 +0000 (12:09 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 8 Oct 2009 16:09:22 +0000 (12:09 -0400)
PR c++/37177
* pt.c (resolve_nondeduced_context): New.
* cvt.c (convert_to_void): Call it.
* semantics.c (finish_decltype_type): Likewise.
* typeck.c (decay_conversion): Here too.
* pt.c (tsubst_decl): Don't clobber input_location.
Don't register a bad specialization.

From-SVN: r152564

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
gcc/testsuite/g++.dg/template/explicit-args2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/explicit-args3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/crash58.C

index 5cf2373b1b23651148c2f3a3dcf2bd1d9552a054..5f672041fffa1da174bf03612e8b4767cd29f5e3 100644 (file)
@@ -1,3 +1,13 @@
+2009-10-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/37177
+       * pt.c (resolve_nondeduced_context): New.
+       * cvt.c (convert_to_void): Call it.
+       * semantics.c (finish_decltype_type): Likewise.
+       * typeck.c (decay_conversion): Here too.
+       * pt.c (tsubst_decl): Don't clobber input_location.
+       Don't register a bad specialization.
+
 2009-10-07  Gabriel Dos Reis  <gdr@cs.tamu.edu>
 
        * cp-tree.h: Fix location of documentation for DECL_LANG_FLAG_7.
index 208bbe2b106c874559630c83275ebd853216ddbb..3d826b9ad92257f197fd532f8db3b679b7200984 100644 (file)
@@ -4845,7 +4845,9 @@ bool template_template_parameter_p                (const_tree);
 extern tree get_primary_template_innermost_parameters  (const_tree);
 extern tree get_template_innermost_arguments   (const_tree);
 extern tree get_template_argument_pack_elems   (const_tree);
-extern tree get_function_template_decl (const_tree);
+extern tree get_function_template_decl         (const_tree);
+extern tree resolve_nondeduced_context         (tree);
+
 /* in repo.c */
 extern void init_repo                          (void);
 extern int repo_emit_p                         (tree);
index aff002dc6666a79ed94df2cc8171710c8fc1bb35..8c5b001dd15c2107f5ee9f321cf64d307730fb06 100644 (file)
@@ -956,6 +956,7 @@ convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain)
 
     default:;
     }
+  expr = resolve_nondeduced_context (expr);
   {
     tree probe = expr;
 
index 9ef3f79a599af0a7f5c8a92948d849288534f554..19d8c9a87df25d9d00be4fa3119bc8e83559b40a 100644 (file)
@@ -8461,6 +8461,7 @@ tsubst_default_arguments (tree fn)
 static tree
 tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 {
+#define RETURN(EXP) do { r = (EXP); goto out; } while(0)
   location_t saved_loc;
   tree r = NULL_TREE;
   tree in_decl = t;
@@ -8486,7 +8487,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            /* Template template parameter is treated here.  */
            tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
            if (new_type == error_mark_node)
-             return error_mark_node;
+             RETURN (error_mark_node);
 
            r = copy_decl (t);
            TREE_CHAIN (r) = NULL_TREE;
@@ -8517,12 +8518,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                                          complain, in_decl);
        --processing_template_decl;
        if (full_args == error_mark_node)
-         return error_mark_node;
+         RETURN (error_mark_node);
 
        /* If this is a default template template argument,
           tsubst might not have changed anything.  */
        if (full_args == tmpl_args)
-         return t;
+         RETURN (t);
 
        hash = hash_tmpl_and_args (t, full_args);
        spec = retrieve_specialization (t, full_args, hash);
@@ -8550,7 +8551,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
            --processing_template_decl;
            if (new_type == error_mark_node)
-             return error_mark_node;
+             RETURN (error_mark_node);
 
            TREE_TYPE (r) = new_type;
            CLASSTYPE_TI_TEMPLATE (new_type) = r;
@@ -8565,7 +8566,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            new_decl = tsubst (decl, args, complain, in_decl);
            --processing_template_decl;
            if (new_decl == error_mark_node)
-             return error_mark_node;
+             RETURN (error_mark_node);
 
            DECL_TEMPLATE_RESULT (r) = new_decl;
            DECL_TI_TEMPLATE (new_decl) = r;
@@ -8623,7 +8624,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            dependent_p = value_dependent_expression_p (t);
            --processing_template_decl;
            if (!dependent_p)
-             return t;
+             RETURN (t);
 
            /* Calculate the most general template of which R is a
               specialization, and the complete set of arguments used to
@@ -8714,7 +8715,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
          }
        type = tsubst (TREE_TYPE (t), args, complain, in_decl);
        if (type == error_mark_node)
-         return error_mark_node;
+         RETURN (error_mark_node);
 
        /* We do NOT check for matching decls pushed separately at this
           point, as they may not represent instantiations of this
@@ -8757,6 +8758,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        /* We'll re-clone as appropriate in instantiate_template.  */
        DECL_CLONED_FUNCTION (r) = NULL_TREE;
 
+       /* If we aren't complaining now, return on error before we register
+          the specialization so that we'll complain eventually.  */
+       if ((complain & tf_error) == 0
+           && IDENTIFIER_OPNAME_P (DECL_NAME (r))
+           && !grok_op_properties (r, /*complain=*/false))
+         RETURN (error_mark_node);
+
        /* Set up the DECL_TEMPLATE_INFO for R.  There's no need to do
           this in the special friend case mentioned above where
           GEN_TMPL is NULL.  */
@@ -8808,9 +8816,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            if (PRIMARY_TEMPLATE_P (gen_tmpl))
              clone_function_decl (r, /*update_method_vec_p=*/0);
          }
-       else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))
-                && !grok_op_properties (r, (complain & tf_error) != 0))
-         return error_mark_node;
+       else if ((complain & tf_error) != 0
+                && IDENTIFIER_OPNAME_P (DECL_NAME (r))
+                && !grok_op_properties (r, /*complain=*/true))
+         RETURN (error_mark_node);
 
        if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
          SET_DECL_FRIEND_CONTEXT (r,
@@ -8851,7 +8860,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
             if (spec 
                 && TREE_CODE (spec) == PARM_DECL
                 && TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
-              return spec;
+              RETURN (spec);
 
             /* Expand the TYPE_PACK_EXPANSION that provides the types for
                the parameters in this function parameter pack.  */
@@ -8864,8 +8873,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                 /* Zero-length parameter packs are boring. Just substitute
                    into the chain.  */
                 if (len == 0)
-                  return tsubst (TREE_CHAIN (t), args, complain, 
-                                 TREE_CHAIN (t));
+                  RETURN (tsubst (TREE_CHAIN (t), args, complain,
+                                 TREE_CHAIN (t)));
               }
             else
               {
@@ -8955,7 +8964,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        r = copy_decl (t);
        type = tsubst (TREE_TYPE (t), args, complain, in_decl);
        if (type == error_mark_node)
-         return error_mark_node;
+         RETURN (error_mark_node);
        TREE_TYPE (r) = type;
        cp_apply_type_quals_to_decl (cp_type_quals (type), r);
 
@@ -9018,7 +9027,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
               we've copied the type for a typedef.  */
            type = tsubst (TREE_TYPE (t), args, complain, in_decl);
            if (type == error_mark_node)
-             return error_mark_node;
+             RETURN (error_mark_node);
            r = TYPE_NAME (type);
            break;
          }
@@ -9091,7 +9100,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            DECL_INITIALIZED_P (r) = 0;
            DECL_TEMPLATE_INSTANTIATED (r) = 0;
            if (type == error_mark_node)
-             return error_mark_node;
+             RETURN (error_mark_node);
            if (TREE_CODE (type) == FUNCTION_TYPE)
              {
                /* It may seem that this case cannot occur, since:
@@ -9111,7 +9120,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                       /* R is not yet sufficiently initialized, so we
                          just use its name.  */
                       DECL_NAME (r));
-               return error_mark_node;
+               RETURN (error_mark_node);
              }
            type = complete_type (type);
            DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
@@ -9207,7 +9216,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
     default:
       gcc_unreachable ();
     }
+#undef RETURN
 
+ out:
   /* Restore the file and line information.  */
   input_location = saved_loc;
 
@@ -13307,6 +13318,105 @@ resolve_overloaded_unification (tree tparms,
   return false;
 }
 
+/* Core DR 115: In contexts where deduction is done and fails, or in
+   contexts where deduction is not done, if a template argument list is
+   specified and it, along with any default template arguments, identifies
+   a single function template specialization, then the template-id is an
+   lvalue for the function template specialization.  */
+
+tree
+resolve_nondeduced_context (tree orig_expr)
+{
+  tree expr, offset, baselink;
+  bool addr;
+
+  if (!type_unknown_p (orig_expr))
+    return orig_expr;
+
+  expr = orig_expr;
+  addr = false;
+  offset = NULL_TREE;
+  baselink = NULL_TREE;
+
+  if (TREE_CODE (expr) == ADDR_EXPR)
+    {
+      expr = TREE_OPERAND (expr, 0);
+      addr = true;
+    }
+  if (TREE_CODE (expr) == OFFSET_REF)
+    {
+      offset = expr;
+      expr = TREE_OPERAND (expr, 1);
+    }
+  if (TREE_CODE (expr) == BASELINK)
+    {
+      baselink = expr;
+      expr = BASELINK_FUNCTIONS (expr);
+    }
+
+  if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+    {
+      int good = 0;
+      tree goodfn = NULL_TREE;
+
+      /* If we got some explicit template args, we need to plug them into
+        the affected templates before we try to unify, in case the
+        explicit args will completely resolve the templates in question.  */
+
+      tree expl_subargs = TREE_OPERAND (expr, 1);
+      tree arg = TREE_OPERAND (expr, 0);
+      tree badfn = NULL_TREE;
+      tree badargs = NULL_TREE;
+
+      for (; arg; arg = OVL_NEXT (arg))
+       {
+         tree fn = OVL_CURRENT (arg);
+         tree subargs, elem;
+
+         if (TREE_CODE (fn) != TEMPLATE_DECL)
+           continue;
+
+         ++processing_template_decl;
+         subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
+                                 expl_subargs, /*check_ret=*/false);
+         if (subargs && !any_dependent_template_arguments_p (subargs))
+           {
+             elem = instantiate_template (fn, subargs, tf_none);
+             if (elem == error_mark_node)
+               {
+                 badfn = fn;
+                 badargs = subargs;
+               }
+             else if (elem && (!goodfn || !decls_match (goodfn, elem)))
+               {
+                 goodfn = elem;
+                 ++good;
+               }
+           }
+         --processing_template_decl;
+       }
+      if (good == 1)
+       {
+         expr = goodfn;
+         if (baselink)
+           expr = build_baselink (BASELINK_BINFO (baselink),
+                                  BASELINK_ACCESS_BINFO (baselink),
+                                  expr, BASELINK_OPTYPE (baselink));
+         if (offset)
+           expr = build2 (OFFSET_REF, TREE_TYPE (expr),
+                          TREE_OPERAND (offset, 0), expr);
+         if (addr)
+           expr = build_address (expr);
+         return expr;
+       }
+      else if (good == 0 && badargs)
+       /* There were no good options and at least one bad one, so let the
+          user know what the problem is.  */
+       instantiate_template (badfn, badargs, tf_warning_or_error);
+    }
+  return orig_expr;
+}
+
 /* Subroutine of resolve_overloaded_unification; does deduction for a single
    overload.  Fills TARGS with any deduced arguments, or error_mark_node if
    different overloads deduce different arguments for a given parm.
index 391228b02a63f578def4a41a1e5677a3af3f5996..6cf22204a5e0bf2c93a1bca3b1a04aa5ce53af5d 100644 (file)
@@ -4741,6 +4741,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
 
   /* The type denoted by decltype(e) is defined as follows:  */
 
+  expr = resolve_nondeduced_context (expr);
   if (id_expression_or_member_access_p)
     {
       /* If e is an id-expression or a class member access (5.2.5
@@ -4766,9 +4767,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
         /* See through BASELINK nodes to the underlying functions.  */
         expr = BASELINK_FUNCTIONS (expr);
 
+      if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+       expr = TREE_OPERAND (expr, 0);
+
       if (TREE_CODE (expr) == OVERLOAD)
         {
-          if (OVL_CHAIN (expr))
+          if (OVL_CHAIN (expr)
+             || TREE_CODE (OVL_FUNCTION (expr)) == TEMPLATE_DECL)
             {
               error ("%qE refers to a set of overloaded functions", orig_expr);
               return error_mark_node;
index 79b0201b77ad3c684eebe9c71a252e3332a1038f..526e7066a60c0e07c7fc3b81ac1240207f6189a6 100644 (file)
@@ -1613,6 +1613,7 @@ decay_conversion (tree exp)
   if (type == error_mark_node)
     return error_mark_node;
 
+  exp = resolve_nondeduced_context (exp);
   if (type_unknown_p (exp))
     {
       cxx_incomplete_type_error (exp, TREE_TYPE (exp));
index bf7e5ba08f4d2ca8ea59a58814144014369cecc8..edfbe1df6739662956836f32ce646bce5551a589 100644 (file)
@@ -1,3 +1,11 @@
+2009-10-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/37177
+       * g++.dg/cpp0x/variadic-throw.C: Adjust errors.
+       * g++.dg/template/explicit-args2.C: New.
+       * g++.dg/template/explicit-args3.C: New.
+       * g++.old-deja/g++.pt/crash58.C: Remove some errors.
+
 2009-10-08  Michael Matz  <matz@suse.de>
 
        PR middle-end/41573
index f2ff652d8a0fcec86a101449fa5b1e9bc7174d9f..ee85bf2a5692c7ff45a38c20301574484d742792 100644 (file)
@@ -8,7 +8,7 @@ template<int M, int N> struct pair
 
 template<int... M> struct S
 {
-  template<int... N> static int foo() throw (pair <M, N>...) // { dg-error "mismatched|no matching" }
+  template<int... N> static int foo() throw (pair <M, N>...) // { dg-error "mismatched" }
   {
     return 1;
   }
@@ -21,5 +21,5 @@ int bar ()
 
 int wibble()
 {
-  return S<0, 1, 2>::foo<0, 1> ();
+  return S<0, 1, 2>::foo<0, 1> (); // { dg-error "no matching" }
 }
diff --git a/gcc/testsuite/g++.dg/template/explicit-args2.C b/gcc/testsuite/g++.dg/template/explicit-args2.C
new file mode 100644 (file)
index 0000000..cd53b45
--- /dev/null
@@ -0,0 +1,38 @@
+// PR c++/37177
+// { dg-options -std=c++0x }
+
+namespace N1
+{
+  template<class T> bool foo();
+}
+
+struct S
+{
+  template <class T>
+  static bool foo();
+
+  template <class T>
+  bool bar();
+};
+
+template<class T> bool foo();
+
+int main()
+{
+  (void)(&S::bar<int>);
+  decltype(&S::bar<int>) a;
+
+  (void*)(&S::foo<int>);
+  (void)(&S::foo<int>);
+  decltype(&S::foo<int>) b;
+
+  (void*)(&N1::foo<int>);
+  (void)(&N1::foo<int>);
+  decltype(&N1::foo<int>) c;
+
+  (void*)(&foo<int>);
+  (void)(&foo<int>);
+  decltype(&foo<int>) d;
+
+  &foo<int> == 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/explicit-args3.C b/gcc/testsuite/g++.dg/template/explicit-args3.C
new file mode 100644 (file)
index 0000000..c095e66
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/37177
+
+template <class T>
+struct A { };
+
+template <class T>
+void operator+(T, T);          // { dg-error "class or enum" }
+
+int main()
+{
+  operator+<int>;              // { dg-error "cannot resolve" }
+}
index 315f3e02896b4f03f60082281df1098da33bec92..0ce3d81723d5465fca6579e1b01115cb01c84f3f 100644 (file)
@@ -15,16 +15,16 @@ struct MatrixC
 {
   void foo () {
     EManip::do_assign<T> (0);
-    &EManip::do_assign<T>;     // { dg-error "" } unresolved
-    &do_assign<T>;             // { dg-error "" } unresolved
-    EManip::do_assign<T>;       // { dg-error "" } unresolved
-    do_assign<T>;               // { dg-error "" } unresolved
+    &EManip::do_assign<T>;     // { dg-bogus "" } unresolved
+    &do_assign<T>;             // { dg-bogus "" } unresolved
+    EManip::do_assign<T>;       // { dg-bogus "" } unresolved
+    do_assign<T>;               // { dg-bogus "" } unresolved
   }
 };
 void foo(MatrixC <double> *ptr)
 {
-  EManip::do_assign<double>;    // { dg-error "" } unresolved
-  &EManip::do_assign<double>;  // { dg-error "" } unresolved
+  EManip::do_assign<double>;    // { dg-bogus "" } unresolved
+  &EManip::do_assign<double>;  // { dg-bogus "" } unresolved
   ptr->foo ();
   void (*p1) (int *) = &do_assign<double>;       // { dg-error "" } cannot convert
   void (*p2) (int *) = &EManip::do_assign<double>; // { dg-error "" } cannot convert