mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-24 15:46:04 +08:00
re PR c++/68926 (decltype and sfinae to check for template instance availability fails to compile)
PR c++/68926 * pt.c (resolve_nondeduced_context): Add complain parm. (do_auto_deduction): Pass it. * cvt.c (convert_to_void): Likewise. * decl.c (cp_finish_decl): Likewise. * init.c (build_new): Likewise. * rtti.c (get_tinfo_decl_dynamic): Likewise. * semantics.c (finish_decltype_type): Likewise. * typeck.c (decay_conversion): Likewise. * cp-tree.h: Adjust declaration. * call.c (standard_conversion): Add complain parm, pass it along. (implicit_conversion): Pass it. From-SVN: r233304
This commit is contained in:
parent
4b48faf548
commit
46f0d909aa
@ -1,5 +1,18 @@
|
||||
2016-02-10 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/68926
|
||||
* pt.c (resolve_nondeduced_context): Add complain parm.
|
||||
(do_auto_deduction): Pass it.
|
||||
* cvt.c (convert_to_void): Likewise.
|
||||
* decl.c (cp_finish_decl): Likewise.
|
||||
* init.c (build_new): Likewise.
|
||||
* rtti.c (get_tinfo_decl_dynamic): Likewise.
|
||||
* semantics.c (finish_decltype_type): Likewise.
|
||||
* typeck.c (decay_conversion): Likewise.
|
||||
* cp-tree.h: Adjust declaration.
|
||||
* call.c (standard_conversion): Add complain parm, pass it along.
|
||||
(implicit_conversion): Pass it.
|
||||
|
||||
PR c++/69657
|
||||
* name-lookup.c (ambiguous_decl): Call remove_hidden_names.
|
||||
(lookup_name_real_1): Likewise.
|
||||
|
@ -190,7 +190,6 @@ static struct z_candidate *add_function_candidate
|
||||
tree, int, tsubst_flags_t);
|
||||
static conversion *implicit_conversion (tree, tree, tree, bool, int,
|
||||
tsubst_flags_t);
|
||||
static conversion *standard_conversion (tree, tree, tree, bool, int);
|
||||
static conversion *reference_binding (tree, tree, tree, bool, int,
|
||||
tsubst_flags_t);
|
||||
static conversion *build_conv (conversion_kind, tree, conversion *);
|
||||
@ -1080,7 +1079,7 @@ strip_top_quals (tree t)
|
||||
|
||||
static conversion *
|
||||
standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
||||
int flags)
|
||||
int flags, tsubst_flags_t complain)
|
||||
{
|
||||
enum tree_code fcode, tcode;
|
||||
conversion *conv;
|
||||
@ -1110,7 +1109,7 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
||||
else if (TREE_CODE (to) == BOOLEAN_TYPE)
|
||||
{
|
||||
/* Necessary for eg, TEMPLATE_ID_EXPRs (c++/50961). */
|
||||
expr = resolve_nondeduced_context (expr);
|
||||
expr = resolve_nondeduced_context (expr, complain);
|
||||
from = TREE_TYPE (expr);
|
||||
}
|
||||
}
|
||||
@ -1149,7 +1148,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
||||
the standard conversion sequence to perform componentwise
|
||||
conversion. */
|
||||
conversion *part_conv = standard_conversion
|
||||
(TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags);
|
||||
(TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags,
|
||||
complain);
|
||||
|
||||
if (part_conv)
|
||||
{
|
||||
@ -1799,7 +1799,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
||||
if (TREE_CODE (to) == REFERENCE_TYPE)
|
||||
conv = reference_binding (to, from, expr, c_cast_p, flags, complain);
|
||||
else
|
||||
conv = standard_conversion (to, from, expr, c_cast_p, flags);
|
||||
conv = standard_conversion (to, from, expr, c_cast_p, flags, complain);
|
||||
|
||||
if (conv)
|
||||
return conv;
|
||||
|
@ -6180,7 +6180,7 @@ extern tree get_template_parms_at_level (tree, int);
|
||||
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 resolve_nondeduced_context (tree);
|
||||
extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
|
||||
extern hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
|
||||
extern tree coerce_template_parms (tree, tree, tree);
|
||||
extern tree coerce_template_parms (tree, tree, tree, tsubst_flags_t);
|
||||
|
@ -1253,7 +1253,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
|
||||
|
||||
default:;
|
||||
}
|
||||
expr = resolve_nondeduced_context (expr);
|
||||
expr = resolve_nondeduced_context (expr, complain);
|
||||
{
|
||||
tree probe = expr;
|
||||
|
||||
|
@ -6575,7 +6575,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
|
||||
if (TREE_CODE (d_init) == TREE_LIST)
|
||||
d_init = build_x_compound_expr_from_list (d_init, ELK_INIT,
|
||||
tf_warning_or_error);
|
||||
d_init = resolve_nondeduced_context (d_init);
|
||||
d_init = resolve_nondeduced_context (d_init, tf_warning_or_error);
|
||||
type = TREE_TYPE (decl) = do_auto_deduction (type, d_init,
|
||||
auto_node,
|
||||
tf_warning_or_error,
|
||||
|
@ -3364,7 +3364,7 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
|
||||
if (auto_node)
|
||||
{
|
||||
tree d_init = (**init)[0];
|
||||
d_init = resolve_nondeduced_context (d_init);
|
||||
d_init = resolve_nondeduced_context (d_init, complain);
|
||||
type = do_auto_deduction (type, d_init, auto_node);
|
||||
}
|
||||
}
|
||||
|
12
gcc/cp/pt.c
12
gcc/cp/pt.c
@ -18575,7 +18575,7 @@ resolve_overloaded_unification (tree tparms,
|
||||
lvalue for the function template specialization. */
|
||||
|
||||
tree
|
||||
resolve_nondeduced_context (tree orig_expr)
|
||||
resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain)
|
||||
{
|
||||
tree expr, offset, baselink;
|
||||
bool addr;
|
||||
@ -18658,16 +18658,16 @@ resolve_nondeduced_context (tree orig_expr)
|
||||
{
|
||||
tree base
|
||||
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (offset, 0)));
|
||||
expr = build_offset_ref (base, expr, addr, tf_warning_or_error);
|
||||
expr = build_offset_ref (base, expr, addr, complain);
|
||||
}
|
||||
if (addr)
|
||||
expr = cp_build_addr_expr (expr, tf_warning_or_error);
|
||||
expr = cp_build_addr_expr (expr, complain);
|
||||
return expr;
|
||||
}
|
||||
else if (good == 0 && badargs)
|
||||
else if (good == 0 && badargs && (complain & tf_error))
|
||||
/* 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);
|
||||
instantiate_template (badfn, badargs, complain);
|
||||
}
|
||||
return orig_expr;
|
||||
}
|
||||
@ -23880,7 +23880,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
|
||||
if (type == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
init = resolve_nondeduced_context (init);
|
||||
init = resolve_nondeduced_context (init, complain);
|
||||
|
||||
if (AUTO_IS_DECLTYPE (auto_node))
|
||||
{
|
||||
|
@ -242,7 +242,7 @@ get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain)
|
||||
if (error_operand_p (exp))
|
||||
return error_mark_node;
|
||||
|
||||
exp = resolve_nondeduced_context (exp);
|
||||
exp = resolve_nondeduced_context (exp, complain);
|
||||
|
||||
/* peel back references, so they match. */
|
||||
type = non_reference (TREE_TYPE (exp));
|
||||
|
@ -8699,7 +8699,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);
|
||||
expr = resolve_nondeduced_context (expr, complain);
|
||||
|
||||
if (invalid_nonstatic_memfn_p (input_location, expr, complain))
|
||||
return error_mark_node;
|
||||
|
@ -1932,7 +1932,7 @@ decay_conversion (tree exp,
|
||||
if (type == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
exp = resolve_nondeduced_context (exp);
|
||||
exp = resolve_nondeduced_context (exp, complain);
|
||||
if (type_unknown_p (exp))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
|
26
gcc/testsuite/g++.dg/cpp0x/sfinae56.C
Normal file
26
gcc/testsuite/g++.dg/cpp0x/sfinae56.C
Normal file
@ -0,0 +1,26 @@
|
||||
// PR c++/68926
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct true_type { static constexpr bool value = true; };
|
||||
struct false_type { static constexpr bool value = false; };
|
||||
|
||||
template<bool Cond> struct enable_if { using type = void; };
|
||||
template<> struct enable_if<false> { };
|
||||
|
||||
template<typename T, typename U> struct is_same : false_type { };
|
||||
template<typename T> struct is_same<T, T> : true_type { };
|
||||
|
||||
template<typename T>
|
||||
typename enable_if<is_same<int, T>::value>::type
|
||||
func();
|
||||
|
||||
template<typename T, typename = decltype(func<T>)>
|
||||
true_type test(T);
|
||||
|
||||
false_type test(...);
|
||||
|
||||
int main()
|
||||
{
|
||||
decltype(test(0))::value; // ok
|
||||
decltype(test(0.f))::value; // error
|
||||
}
|
Loading…
Reference in New Issue
Block a user