aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-10-08 12:09:22 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-10-08 12:09:22 -0400
commitccb05613cfd1d37ce6473244e28c56e75d1d0e66 (patch)
tree0b5aca150e69844718e291632a5913000e0f6868
parent6728ee79872ffd3dbcf858dab076c96c71ec95e5 (diff)
downloadgcc-ccb05613cfd1d37ce6473244e28c56e75d1d0e66.zip
gcc-ccb05613cfd1d37ce6473244e28c56e75d1d0e66.tar.gz
gcc-ccb05613cfd1d37ce6473244e28c56e75d1d0e66.tar.bz2
re PR c++/37177 ([c++0x] ICE on decltype(rel_ops::operator><int>);)
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
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/cvt.c1
-rw-r--r--gcc/cp/pt.c144
-rw-r--r--gcc/cp/semantics.c7
-rw-r--r--gcc/cp/typeck.c1
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-throw.C4
-rw-r--r--gcc/testsuite/g++.dg/template/explicit-args2.C38
-rw-r--r--gcc/testsuite/g++.dg/template/explicit-args3.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash58.C12
11 files changed, 214 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5cf2373..5f67204 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 208bbe2..3d826b9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index aff002d..8c5b001 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9ef3f79..19d8c9a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 391228b..6cf2220 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 79b0201..526e706 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bf7e5ba..edfbe1d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C b/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
index f2ff652..ee85bf2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
@@ -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
index 0000000..cd53b45
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-args2.C
@@ -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
index 0000000..c095e66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-args3.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash58.C b/gcc/testsuite/g++.old-deja/g++.pt/crash58.C
index 315f3e0..0ce3d81 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash58.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash58.C
@@ -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