Commit ccb05613 by Jason Merrill Committed by Jason Merrill

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
parent 6728ee79
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> 2009-10-07 Gabriel Dos Reis <gdr@cs.tamu.edu>
* cp-tree.h: Fix location of documentation for DECL_LANG_FLAG_7. * cp-tree.h: Fix location of documentation for DECL_LANG_FLAG_7.
......
...@@ -4845,7 +4845,9 @@ bool template_template_parameter_p (const_tree); ...@@ -4845,7 +4845,9 @@ bool template_template_parameter_p (const_tree);
extern tree get_primary_template_innermost_parameters (const_tree); extern tree get_primary_template_innermost_parameters (const_tree);
extern tree get_template_innermost_arguments (const_tree); extern tree get_template_innermost_arguments (const_tree);
extern tree get_template_argument_pack_elems (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 */ /* in repo.c */
extern void init_repo (void); extern void init_repo (void);
extern int repo_emit_p (tree); extern int repo_emit_p (tree);
......
...@@ -956,6 +956,7 @@ convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain) ...@@ -956,6 +956,7 @@ convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain)
default:; default:;
} }
expr = resolve_nondeduced_context (expr);
{ {
tree probe = expr; tree probe = expr;
......
...@@ -8461,6 +8461,7 @@ tsubst_default_arguments (tree fn) ...@@ -8461,6 +8461,7 @@ tsubst_default_arguments (tree fn)
static tree static tree
tsubst_decl (tree t, tree args, tsubst_flags_t complain) tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{ {
#define RETURN(EXP) do { r = (EXP); goto out; } while(0)
location_t saved_loc; location_t saved_loc;
tree r = NULL_TREE; tree r = NULL_TREE;
tree in_decl = t; tree in_decl = t;
...@@ -8486,7 +8487,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8486,7 +8487,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Template template parameter is treated here. */ /* Template template parameter is treated here. */
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (new_type == error_mark_node) if (new_type == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
r = copy_decl (t); r = copy_decl (t);
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
...@@ -8517,12 +8518,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8517,12 +8518,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
complain, in_decl); complain, in_decl);
--processing_template_decl; --processing_template_decl;
if (full_args == error_mark_node) if (full_args == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
/* If this is a default template template argument, /* If this is a default template template argument,
tsubst might not have changed anything. */ tsubst might not have changed anything. */
if (full_args == tmpl_args) if (full_args == tmpl_args)
return t; RETURN (t);
hash = hash_tmpl_and_args (t, full_args); hash = hash_tmpl_and_args (t, full_args);
spec = retrieve_specialization (t, full_args, hash); spec = retrieve_specialization (t, full_args, hash);
...@@ -8550,7 +8551,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8550,7 +8551,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
--processing_template_decl; --processing_template_decl;
if (new_type == error_mark_node) if (new_type == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
TREE_TYPE (r) = new_type; TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r; CLASSTYPE_TI_TEMPLATE (new_type) = r;
...@@ -8565,7 +8566,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8565,7 +8566,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
new_decl = tsubst (decl, args, complain, in_decl); new_decl = tsubst (decl, args, complain, in_decl);
--processing_template_decl; --processing_template_decl;
if (new_decl == error_mark_node) if (new_decl == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
DECL_TEMPLATE_RESULT (r) = new_decl; DECL_TEMPLATE_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = r; DECL_TI_TEMPLATE (new_decl) = r;
...@@ -8623,7 +8624,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8623,7 +8624,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
dependent_p = value_dependent_expression_p (t); dependent_p = value_dependent_expression_p (t);
--processing_template_decl; --processing_template_decl;
if (!dependent_p) if (!dependent_p)
return t; RETURN (t);
/* Calculate the most general template of which R is a /* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to specialization, and the complete set of arguments used to
...@@ -8714,7 +8715,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8714,7 +8715,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
} }
type = tsubst (TREE_TYPE (t), args, complain, in_decl); type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
/* We do NOT check for matching decls pushed separately at this /* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this point, as they may not represent instantiations of this
...@@ -8757,6 +8758,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8757,6 +8758,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* We'll re-clone as appropriate in instantiate_template. */ /* We'll re-clone as appropriate in instantiate_template. */
DECL_CLONED_FUNCTION (r) = NULL_TREE; 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 /* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
this in the special friend case mentioned above where this in the special friend case mentioned above where
GEN_TMPL is NULL. */ GEN_TMPL is NULL. */
...@@ -8808,9 +8816,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8808,9 +8816,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (PRIMARY_TEMPLATE_P (gen_tmpl)) if (PRIMARY_TEMPLATE_P (gen_tmpl))
clone_function_decl (r, /*update_method_vec_p=*/0); clone_function_decl (r, /*update_method_vec_p=*/0);
} }
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)) else if ((complain & tf_error) != 0
&& !grok_op_properties (r, (complain & tf_error) != 0)) && IDENTIFIER_OPNAME_P (DECL_NAME (r))
return error_mark_node; && !grok_op_properties (r, /*complain=*/true))
RETURN (error_mark_node);
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t)) if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r, SET_DECL_FRIEND_CONTEXT (r,
...@@ -8851,7 +8860,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8851,7 +8860,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (spec if (spec
&& TREE_CODE (spec) == PARM_DECL && TREE_CODE (spec) == PARM_DECL
&& TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION) && TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
return spec; RETURN (spec);
/* Expand the TYPE_PACK_EXPANSION that provides the types for /* Expand the TYPE_PACK_EXPANSION that provides the types for
the parameters in this function parameter pack. */ the parameters in this function parameter pack. */
...@@ -8864,8 +8873,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8864,8 +8873,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Zero-length parameter packs are boring. Just substitute /* Zero-length parameter packs are boring. Just substitute
into the chain. */ into the chain. */
if (len == 0) if (len == 0)
return tsubst (TREE_CHAIN (t), args, complain, RETURN (tsubst (TREE_CHAIN (t), args, complain,
TREE_CHAIN (t)); TREE_CHAIN (t)));
} }
else else
{ {
...@@ -8955,7 +8964,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8955,7 +8964,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
r = copy_decl (t); r = copy_decl (t);
type = tsubst (TREE_TYPE (t), args, complain, in_decl); type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r); 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) ...@@ -9018,7 +9027,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
we've copied the type for a typedef. */ we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl); type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
r = TYPE_NAME (type); r = TYPE_NAME (type);
break; break;
} }
...@@ -9091,7 +9100,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -9091,7 +9100,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_INITIALIZED_P (r) = 0; DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0; DECL_TEMPLATE_INSTANTIATED (r) = 0;
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; RETURN (error_mark_node);
if (TREE_CODE (type) == FUNCTION_TYPE) if (TREE_CODE (type) == FUNCTION_TYPE)
{ {
/* It may seem that this case cannot occur, since: /* It may seem that this case cannot occur, since:
...@@ -9111,7 +9120,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -9111,7 +9120,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* R is not yet sufficiently initialized, so we /* R is not yet sufficiently initialized, so we
just use its name. */ just use its name. */
DECL_NAME (r)); DECL_NAME (r));
return error_mark_node; RETURN (error_mark_node);
} }
type = complete_type (type); type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
...@@ -9207,7 +9216,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -9207,7 +9216,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
#undef RETURN
out:
/* Restore the file and line information. */ /* Restore the file and line information. */
input_location = saved_loc; input_location = saved_loc;
...@@ -13307,6 +13318,105 @@ resolve_overloaded_unification (tree tparms, ...@@ -13307,6 +13318,105 @@ resolve_overloaded_unification (tree tparms,
return false; 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 /* Subroutine of resolve_overloaded_unification; does deduction for a single
overload. Fills TARGS with any deduced arguments, or error_mark_node if overload. Fills TARGS with any deduced arguments, or error_mark_node if
different overloads deduce different arguments for a given parm. different overloads deduce different arguments for a given parm.
......
...@@ -4741,6 +4741,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) ...@@ -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: */ /* The type denoted by decltype(e) is defined as follows: */
expr = resolve_nondeduced_context (expr);
if (id_expression_or_member_access_p) if (id_expression_or_member_access_p)
{ {
/* If e is an id-expression or a class member access (5.2.5 /* 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) ...@@ -4766,9 +4767,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
/* See through BASELINK nodes to the underlying functions. */ /* See through BASELINK nodes to the underlying functions. */
expr = BASELINK_FUNCTIONS (expr); expr = BASELINK_FUNCTIONS (expr);
if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
expr = TREE_OPERAND (expr, 0);
if (TREE_CODE (expr) == OVERLOAD) 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); error ("%qE refers to a set of overloaded functions", orig_expr);
return error_mark_node; return error_mark_node;
......
...@@ -1613,6 +1613,7 @@ decay_conversion (tree exp) ...@@ -1613,6 +1613,7 @@ decay_conversion (tree exp)
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
exp = resolve_nondeduced_context (exp);
if (type_unknown_p (exp)) if (type_unknown_p (exp))
{ {
cxx_incomplete_type_error (exp, TREE_TYPE (exp)); cxx_incomplete_type_error (exp, TREE_TYPE (exp));
......
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> 2009-10-08 Michael Matz <matz@suse.de>
PR middle-end/41573 PR middle-end/41573
......
...@@ -8,7 +8,7 @@ template<int M, int N> struct pair ...@@ -8,7 +8,7 @@ template<int M, int N> struct pair
template<int... M> struct S 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; return 1;
} }
...@@ -21,5 +21,5 @@ int bar () ...@@ -21,5 +21,5 @@ int bar ()
int wibble() int wibble()
{ {
return S<0, 1, 2>::foo<0, 1> (); return S<0, 1, 2>::foo<0, 1> (); // { dg-error "no matching" }
} }
// 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;
}
// 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" }
}
...@@ -15,16 +15,16 @@ struct MatrixC ...@@ -15,16 +15,16 @@ struct MatrixC
{ {
void foo () { void foo () {
EManip::do_assign<T> (0); EManip::do_assign<T> (0);
&EManip::do_assign<T>; // { dg-error "" } unresolved &EManip::do_assign<T>; // { dg-bogus "" } unresolved
&do_assign<T>; // { dg-error "" } unresolved &do_assign<T>; // { dg-bogus "" } unresolved
EManip::do_assign<T>; // { dg-error "" } unresolved EManip::do_assign<T>; // { dg-bogus "" } unresolved
do_assign<T>; // { dg-error "" } unresolved do_assign<T>; // { dg-bogus "" } unresolved
} }
}; };
void foo(MatrixC <double> *ptr) void foo(MatrixC <double> *ptr)
{ {
EManip::do_assign<double>; // { dg-error "" } unresolved EManip::do_assign<double>; // { dg-bogus "" } unresolved
&EManip::do_assign<double>; // { dg-error "" } unresolved &EManip::do_assign<double>; // { dg-bogus "" } unresolved
ptr->foo (); ptr->foo ();
void (*p1) (int *) = &do_assign<double>; // { dg-error "" } cannot convert void (*p1) (int *) = &do_assign<double>; // { dg-error "" } cannot convert
void (*p2) (int *) = &EManip::do_assign<double>; // { dg-error "" } cannot convert void (*p2) (int *) = &EManip::do_assign<double>; // { dg-error "" } cannot convert
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment