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.
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 *);
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;
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);
}
}
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)
{
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;
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);
default:;
}
- expr = resolve_nondeduced_context (expr);
+ expr = resolve_nondeduced_context (expr, complain);
{
tree probe = expr;
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,
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);
}
}
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;
{
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;
}
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))
{
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));
/* 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;
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)
--- /dev/null
+// 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
+}