mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-24 07:30:31 +08:00
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
This commit is contained in:
parent
6728ee7987
commit
ccb05613cf
gcc
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
144
gcc/cp/pt.c
144
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.
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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" }
|
||||
}
|
||||
|
38
gcc/testsuite/g++.dg/template/explicit-args2.C
Normal file
38
gcc/testsuite/g++.dg/template/explicit-args2.C
Normal file
@ -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;
|
||||
}
|
12
gcc/testsuite/g++.dg/template/explicit-args3.C
Normal file
12
gcc/testsuite/g++.dg/template/explicit-args3.C
Normal file
@ -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" }
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user