re PR c++/54191 ([C++11] SFINAE does not handle conversion to inaccessible base)
/cp 2012-09-05 Paolo Carlini <paolo.carlini@oracle.com> PR c++/54191 * search.c (lookup_base): Add tsubst_flags_t parameter. (adjust_result_of_qualified_name_lookup, check_final_overrider): Adjust. * name-lookup.c (do_class_using_decl): Adjust. * typeck2.c (binfo_or_else, build_scoped_ref, build_m_component_ref): Likewise. * cvt.c (cp_convert_to_pointer, convert_to_pointer_force, build_up_reference): Likewise. * rtti.c (build_dynamic_cast_1): Likewise. * tree.c (maybe_dummy_object): Likewise. * call.c (build_conditional_expr_1, build_over_call): Likewise. * cp-tree.h (UNIQUELY_DERIVED_FROM_P, PUBLICLY_UNIQUELY_DERIVED_P): Remove. (enum base_access_flags, ba_quiet): Remove. (uniquely_derived_from_p, publicly_uniquely_derived_p): Declare. * except.c (can_convert_eh): Adjust. * decl.c (grokdeclarator): Likewise. * typeck.c (comp_except_types, build_class_member_access_expr, finish_class_member_access_expr, get_member_function_from_ptrfunc, build_static_cast_1, get_delta_difference_1): Likewise. * class.c (build_base_path, convert_to_base, build_vtbl_ref_1, warn_about_ambiguous_bases): Likewise. (uniquely_derived_from_p, publicly_uniquely_derived_p): Define. /testsuite 2012-09-05 Paolo Carlini <paolo.carlini@oracle.com> PR c++/54191 * g++.dg/cpp0x/sfinae39.C: New. From-SVN: r190969
This commit is contained in:
parent
b588ae3074
commit
22854930b9
|
@ -1,3 +1,30 @@
|
|||
2012-09-05 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/54191
|
||||
* search.c (lookup_base): Add tsubst_flags_t parameter.
|
||||
(adjust_result_of_qualified_name_lookup, check_final_overrider):
|
||||
Adjust.
|
||||
* name-lookup.c (do_class_using_decl): Adjust.
|
||||
* typeck2.c (binfo_or_else, build_scoped_ref, build_m_component_ref):
|
||||
Likewise.
|
||||
* cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
|
||||
build_up_reference): Likewise.
|
||||
* rtti.c (build_dynamic_cast_1): Likewise.
|
||||
* tree.c (maybe_dummy_object): Likewise.
|
||||
* call.c (build_conditional_expr_1, build_over_call): Likewise.
|
||||
* cp-tree.h (UNIQUELY_DERIVED_FROM_P, PUBLICLY_UNIQUELY_DERIVED_P):
|
||||
Remove.
|
||||
(enum base_access_flags, ba_quiet): Remove.
|
||||
(uniquely_derived_from_p, publicly_uniquely_derived_p): Declare.
|
||||
* except.c (can_convert_eh): Adjust.
|
||||
* decl.c (grokdeclarator): Likewise.
|
||||
* typeck.c (comp_except_types, build_class_member_access_expr,
|
||||
finish_class_member_access_expr, get_member_function_from_ptrfunc,
|
||||
build_static_cast_1, get_delta_difference_1): Likewise.
|
||||
* class.c (build_base_path, convert_to_base, build_vtbl_ref_1,
|
||||
warn_about_ambiguous_bases): Likewise.
|
||||
(uniquely_derived_from_p, publicly_uniquely_derived_p): Define.
|
||||
|
||||
2012-09-04 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/54441
|
||||
|
|
|
@ -4758,6 +4758,9 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (arg2 == error_mark_node || arg3 == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
valid_operands:
|
||||
result = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
|
||||
if (!cp_unevaluated_operand)
|
||||
|
@ -6608,7 +6611,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
will be to the derived class, not the base declaring fn. We
|
||||
must convert from derived to base. */
|
||||
base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
|
||||
TREE_TYPE (parmtype), ba_unique, NULL);
|
||||
TREE_TYPE (parmtype), ba_unique,
|
||||
NULL, complain);
|
||||
converted_arg = build_base_path (PLUS_EXPR, converted_arg,
|
||||
base_binfo, 1, complain);
|
||||
|
||||
|
@ -6852,7 +6856,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
tree t;
|
||||
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
|
||||
DECL_CONTEXT (fn),
|
||||
ba_any, NULL);
|
||||
ba_any, NULL, complain);
|
||||
gcc_assert (binfo && binfo != error_mark_node);
|
||||
|
||||
/* Warn about deprecated virtual functions now, since we're about
|
||||
|
|
|
@ -275,7 +275,7 @@ build_base_path (enum tree_code code,
|
|||
if (complain & tf_error)
|
||||
{
|
||||
tree base = lookup_base (probe, BINFO_TYPE (d_binfo),
|
||||
ba_unique, NULL);
|
||||
ba_unique, NULL, complain);
|
||||
gcc_assert (base == error_mark_node);
|
||||
}
|
||||
return error_mark_node;
|
||||
|
@ -544,7 +544,6 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull,
|
|||
{
|
||||
tree binfo;
|
||||
tree object_type;
|
||||
base_access access;
|
||||
|
||||
if (TYPE_PTR_P (TREE_TYPE (object)))
|
||||
{
|
||||
|
@ -554,12 +553,8 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull,
|
|||
else
|
||||
object_type = TREE_TYPE (object);
|
||||
|
||||
access = check_access ? ba_check : ba_unique;
|
||||
if (!(complain & tf_error))
|
||||
access |= ba_quiet;
|
||||
binfo = lookup_base (object_type, type,
|
||||
access,
|
||||
NULL);
|
||||
binfo = lookup_base (object_type, type, check_access ? ba_check : ba_unique,
|
||||
NULL, complain);
|
||||
if (!binfo || binfo == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
|
@ -652,8 +647,8 @@ build_vtbl_ref_1 (tree instance, tree idx)
|
|||
if (fixed_type && !cdtorp)
|
||||
{
|
||||
tree binfo = lookup_base (fixed_type, basetype,
|
||||
ba_unique | ba_quiet, NULL);
|
||||
if (binfo)
|
||||
ba_unique, NULL, tf_none);
|
||||
if (binfo && binfo != error_mark_node)
|
||||
vtbl = unshare_expr (BINFO_VTABLE (binfo));
|
||||
}
|
||||
|
||||
|
@ -5483,7 +5478,7 @@ warn_about_ambiguous_bases (tree t)
|
|||
{
|
||||
basetype = BINFO_TYPE (base_binfo);
|
||||
|
||||
if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
|
||||
if (!uniquely_derived_from_p (basetype, t))
|
||||
warning (0, "direct base %qT inaccessible in %qT due to ambiguity",
|
||||
basetype, t);
|
||||
}
|
||||
|
@ -5495,9 +5490,9 @@ warn_about_ambiguous_bases (tree t)
|
|||
{
|
||||
basetype = BINFO_TYPE (binfo);
|
||||
|
||||
if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
|
||||
warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due to ambiguity",
|
||||
basetype, t);
|
||||
if (!uniquely_derived_from_p (basetype, t))
|
||||
warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due "
|
||||
"to ambiguity", basetype, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8933,4 +8928,24 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
|
|||
CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, init);
|
||||
}
|
||||
|
||||
/* TRUE iff TYPE is uniquely derived from PARENT. Ignores
|
||||
accessibility. */
|
||||
|
||||
bool
|
||||
uniquely_derived_from_p (tree parent, tree type)
|
||||
{
|
||||
tree base = lookup_base (type, parent, ba_unique, NULL, tf_none);
|
||||
return base && base != error_mark_node;
|
||||
}
|
||||
|
||||
/* TRUE iff TYPE is publicly & uniquely derived from PARENT. */
|
||||
|
||||
bool
|
||||
publicly_uniquely_derived_p (tree parent, tree type)
|
||||
{
|
||||
tree base = lookup_base (type, parent, ba_ignore_scope | ba_check,
|
||||
NULL, tf_none);
|
||||
return base && base != error_mark_node;
|
||||
}
|
||||
|
||||
#include "gt-cp-class.h"
|
||||
|
|
|
@ -1278,15 +1278,8 @@ enum languages { lang_c, lang_cplusplus, lang_java };
|
|||
/* Nonzero iff TYPE is derived from PARENT. Ignores accessibility and
|
||||
ambiguity issues. */
|
||||
#define DERIVED_FROM_P(PARENT, TYPE) \
|
||||
(lookup_base ((TYPE), (PARENT), ba_any, NULL) != NULL_TREE)
|
||||
/* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
|
||||
accessibility. */
|
||||
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
|
||||
(lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL) != NULL_TREE)
|
||||
/* Nonzero iff TYPE is publicly & uniquely derived from PARENT. */
|
||||
#define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
|
||||
(lookup_base ((TYPE), (PARENT), ba_ignore_scope | ba_check | ba_quiet, \
|
||||
NULL) != NULL_TREE)
|
||||
(lookup_base ((TYPE), (PARENT), ba_any, NULL, tf_warning_or_error)\
|
||||
!= NULL_TREE)
|
||||
|
||||
/* Gives the visibility specification for a class type. */
|
||||
#define CLASSTYPE_VISIBILITY(TYPE) \
|
||||
|
@ -4187,8 +4180,7 @@ enum base_access_flags {
|
|||
ba_unique = 1 << 0, /* Must be a unique base. */
|
||||
ba_check_bit = 1 << 1, /* Check access. */
|
||||
ba_check = ba_unique | ba_check_bit,
|
||||
ba_ignore_scope = 1 << 2, /* Ignore access allowed by local scope. */
|
||||
ba_quiet = 1 << 3 /* Do not issue error messages. */
|
||||
ba_ignore_scope = 1 << 2 /* Ignore access allowed by local scope. */
|
||||
};
|
||||
|
||||
/* This type is used for parameters and variables which hold
|
||||
|
@ -5003,6 +4995,8 @@ extern void clone_function_decl (tree, int);
|
|||
extern void adjust_clone_args (tree);
|
||||
extern void deduce_noexcept_on_destructor (tree);
|
||||
extern void insert_late_enum_def_into_classtype_sorted_fields (tree, tree);
|
||||
extern bool uniquely_derived_from_p (tree, tree);
|
||||
extern bool publicly_uniquely_derived_p (tree, tree);
|
||||
|
||||
/* in cvt.c */
|
||||
extern tree convert_to_reference (tree, tree, int, int, tree,
|
||||
|
@ -5438,8 +5432,8 @@ extern bool emit_tinfo_decl (tree);
|
|||
|
||||
/* in search.c */
|
||||
extern bool accessible_base_p (tree, tree, bool);
|
||||
extern tree lookup_base (tree, tree, base_access,
|
||||
base_kind *);
|
||||
extern tree lookup_base (tree, tree, base_access,
|
||||
base_kind *, tsubst_flags_t);
|
||||
extern tree dcast_base_hint (tree, tree);
|
||||
extern int accessible_p (tree, tree, bool);
|
||||
extern tree lookup_field_1 (tree, tree, bool);
|
||||
|
|
13
gcc/cp/cvt.c
13
gcc/cp/cvt.c
|
@ -149,11 +149,13 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
|
|||
binfo = NULL_TREE;
|
||||
/* Try derived to base conversion. */
|
||||
if (!same_p)
|
||||
binfo = lookup_base (intype_class, type_class, ba_check, NULL);
|
||||
binfo = lookup_base (intype_class, type_class, ba_check,
|
||||
NULL, complain);
|
||||
if (!same_p && !binfo)
|
||||
{
|
||||
/* Try base to derived conversion. */
|
||||
binfo = lookup_base (type_class, intype_class, ba_check, NULL);
|
||||
binfo = lookup_base (type_class, intype_class, ba_check,
|
||||
NULL, complain);
|
||||
code = MINUS_EXPR;
|
||||
}
|
||||
if (binfo == error_mark_node)
|
||||
|
@ -279,11 +281,11 @@ convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain)
|
|||
tree binfo;
|
||||
|
||||
binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
|
||||
ba_unique, NULL);
|
||||
ba_unique, NULL, complain);
|
||||
if (!binfo)
|
||||
{
|
||||
binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
|
||||
ba_unique, NULL);
|
||||
ba_unique, NULL, complain);
|
||||
code = MINUS_EXPR;
|
||||
}
|
||||
if (binfo == error_mark_node)
|
||||
|
@ -352,7 +354,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl,
|
|||
&& MAYBE_CLASS_TYPE_P (target_type))
|
||||
{
|
||||
/* We go through lookup_base for the access control. */
|
||||
tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
|
||||
tree binfo = lookup_base (argtype, target_type, ba_check,
|
||||
NULL, complain);
|
||||
if (binfo == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (binfo == NULL_TREE)
|
||||
|
|
|
@ -8524,7 +8524,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
}
|
||||
else if (innermost_code != cdk_function
|
||||
&& current_class_type
|
||||
&& !UNIQUELY_DERIVED_FROM_P (ctype,
|
||||
&& !uniquely_derived_from_p (ctype,
|
||||
current_class_type))
|
||||
{
|
||||
error ("type %qT is not derived from type %qT",
|
||||
|
|
|
@ -1052,7 +1052,7 @@ can_convert_eh (tree to, tree from)
|
|||
}
|
||||
|
||||
if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
|
||||
&& PUBLICLY_UNIQUELY_DERIVED_P (to, from))
|
||||
&& publicly_uniquely_derived_p (to, from))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3264,7 +3264,8 @@ do_class_using_decl (tree scope, tree name)
|
|||
if (!scope_dependent_p)
|
||||
{
|
||||
base_kind b_kind;
|
||||
binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
|
||||
binfo = lookup_base (current_class_type, scope, ba_any, &b_kind,
|
||||
tf_warning_or_error);
|
||||
if (b_kind < bk_proper_base)
|
||||
{
|
||||
if (!bases_dependent_p)
|
||||
|
|
|
@ -615,7 +615,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
|
|||
tree binfo;
|
||||
|
||||
binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type),
|
||||
ba_check, NULL);
|
||||
ba_check, NULL, complain);
|
||||
|
||||
if (binfo)
|
||||
{
|
||||
|
|
|
@ -179,13 +179,13 @@ accessible_base_p (tree t, tree base, bool consider_local_p)
|
|||
non-NULL, fill with information about what kind of base we
|
||||
discovered.
|
||||
|
||||
If the base is inaccessible, or ambiguous, and the ba_quiet bit is
|
||||
not set in ACCESS, then an error is issued and error_mark_node is
|
||||
returned. If the ba_quiet bit is set, then no error is issued and
|
||||
NULL_TREE is returned. */
|
||||
If the base is inaccessible, or ambiguous, then error_mark_node is
|
||||
returned. If the tf_error bit of COMPLAIN is not set, no error
|
||||
is issued. */
|
||||
|
||||
tree
|
||||
lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
|
||||
lookup_base (tree t, tree base, base_access access,
|
||||
base_kind *kind_ptr, tsubst_flags_t complain)
|
||||
{
|
||||
tree binfo;
|
||||
tree t_binfo;
|
||||
|
@ -251,11 +251,9 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
|
|||
break;
|
||||
|
||||
case bk_ambig:
|
||||
if (!(access & ba_quiet))
|
||||
{
|
||||
error ("%qT is an ambiguous base of %qT", base, t);
|
||||
binfo = error_mark_node;
|
||||
}
|
||||
if (complain & tf_error)
|
||||
error ("%qT is an ambiguous base of %qT", base, t);
|
||||
binfo = error_mark_node;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -269,13 +267,9 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
|
|||
&& COMPLETE_TYPE_P (base)
|
||||
&& !accessible_base_p (t, base, !(access & ba_ignore_scope)))
|
||||
{
|
||||
if (!(access & ba_quiet))
|
||||
{
|
||||
error ("%qT is an inaccessible base of %qT", base, t);
|
||||
binfo = error_mark_node;
|
||||
}
|
||||
else
|
||||
binfo = NULL_TREE;
|
||||
if (complain & tf_error)
|
||||
error ("%qT is an inaccessible base of %qT", base, t);
|
||||
binfo = error_mark_node;
|
||||
bk = bk_inaccessible;
|
||||
}
|
||||
break;
|
||||
|
@ -1537,14 +1531,13 @@ adjust_result_of_qualified_name_lookup (tree decl,
|
|||
or ambiguity -- in either case, the choice of a static member
|
||||
function might make the usage valid. */
|
||||
base = lookup_base (context_class, qualifying_scope,
|
||||
ba_unique | ba_quiet, NULL);
|
||||
if (base)
|
||||
ba_unique, NULL, tf_none);
|
||||
if (base && base != error_mark_node)
|
||||
{
|
||||
BASELINK_ACCESS_BINFO (decl) = base;
|
||||
BASELINK_BINFO (decl)
|
||||
= lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
|
||||
ba_unique | ba_quiet,
|
||||
NULL);
|
||||
ba_unique, NULL, tf_none);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1875,12 +1868,13 @@ check_final_overrider (tree overrider, tree basefn)
|
|||
/* Strictly speaking, the standard requires the return type to be
|
||||
complete even if it only differs in cv-quals, but that seems
|
||||
like a bug in the wording. */
|
||||
if (!same_type_ignoring_top_level_qualifiers_p (base_return, over_return))
|
||||
if (!same_type_ignoring_top_level_qualifiers_p (base_return,
|
||||
over_return))
|
||||
{
|
||||
tree binfo = lookup_base (over_return, base_return,
|
||||
ba_check | ba_quiet, NULL);
|
||||
ba_check, NULL, tf_none);
|
||||
|
||||
if (!binfo)
|
||||
if (!binfo || binfo == error_mark_node)
|
||||
fail = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2772,7 +2772,8 @@ maybe_dummy_object (tree type, tree* binfop)
|
|||
tree current = current_nonlambda_class_type ();
|
||||
|
||||
if (current
|
||||
&& (binfo = lookup_base (current, type, ba_any, NULL)))
|
||||
&& (binfo = lookup_base (current, type, ba_any, NULL,
|
||||
tf_warning_or_error)))
|
||||
context = current;
|
||||
else
|
||||
{
|
||||
|
|
|
@ -975,7 +975,7 @@ comp_except_types (tree a, tree b, bool exact)
|
|||
|| TREE_CODE (b) != RECORD_TYPE)
|
||||
return false;
|
||||
|
||||
if (PUBLICLY_UNIQUELY_DERIVED_P (a, b))
|
||||
if (publicly_uniquely_derived_p (a, b))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -2247,7 +2247,7 @@ build_class_member_access_expr (tree object, tree member,
|
|||
base_kind kind;
|
||||
|
||||
binfo = lookup_base (access_path ? access_path : object_type,
|
||||
member_scope, ba_unique, &kind);
|
||||
member_scope, ba_unique, &kind, complain);
|
||||
if (binfo == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
|
@ -2630,7 +2630,8 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
|
|||
}
|
||||
|
||||
/* Find the base of OBJECT_TYPE corresponding to SCOPE. */
|
||||
access_path = lookup_base (object_type, scope, ba_check, NULL);
|
||||
access_path = lookup_base (object_type, scope, ba_check,
|
||||
NULL, complain);
|
||||
if (access_path == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!access_path)
|
||||
|
@ -3151,7 +3152,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
|
|||
(basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
|
||||
{
|
||||
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
|
||||
basetype, ba_check, NULL);
|
||||
basetype, ba_check, NULL, complain);
|
||||
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
|
||||
1, complain);
|
||||
if (instance_ptr == error_mark_node)
|
||||
|
@ -5997,7 +5998,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
|
|||
not considered. */
|
||||
base = lookup_base (TREE_TYPE (type), intype,
|
||||
c_cast_p ? ba_unique : ba_check,
|
||||
NULL);
|
||||
NULL, complain);
|
||||
|
||||
/* Convert from "B*" to "D*". This function will check that "B"
|
||||
is not a virtual base of "D". */
|
||||
|
@ -6121,7 +6122,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
|
|||
return error_mark_node;
|
||||
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
|
||||
c_cast_p ? ba_unique : ba_check,
|
||||
NULL);
|
||||
NULL, complain);
|
||||
expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
|
||||
complain);
|
||||
return cp_fold_convert(type, expr);
|
||||
|
@ -7181,16 +7182,11 @@ get_delta_difference_1 (tree from, tree to, bool c_cast_p,
|
|||
{
|
||||
tree binfo;
|
||||
base_kind kind;
|
||||
base_access access = c_cast_p ? ba_unique : ba_check;
|
||||
|
||||
/* Note: ba_quiet does not distinguish between access control and
|
||||
ambiguity. */
|
||||
if (!(complain & tf_error))
|
||||
access |= ba_quiet;
|
||||
binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check,
|
||||
&kind, complain);
|
||||
|
||||
binfo = lookup_base (to, from, access, &kind);
|
||||
|
||||
if (kind == bk_inaccessible || kind == bk_ambig)
|
||||
if (binfo == error_mark_node)
|
||||
{
|
||||
if (!(complain & tf_error))
|
||||
return error_mark_node;
|
||||
|
|
|
@ -57,7 +57,8 @@ error_not_base_type (tree basetype, tree type)
|
|||
tree
|
||||
binfo_or_else (tree base, tree type)
|
||||
{
|
||||
tree binfo = lookup_base (type, base, ba_unique, NULL);
|
||||
tree binfo = lookup_base (type, base, ba_unique,
|
||||
NULL, tf_warning_or_error);
|
||||
|
||||
if (binfo == error_mark_node)
|
||||
return NULL_TREE;
|
||||
|
@ -1447,7 +1448,8 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
|
|||
if (*binfo_p)
|
||||
binfo = *binfo_p;
|
||||
else
|
||||
binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
|
||||
binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check,
|
||||
NULL, tf_warning_or_error);
|
||||
|
||||
if (!binfo || binfo == error_mark_node)
|
||||
{
|
||||
|
@ -1600,7 +1602,7 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain)
|
|||
}
|
||||
else
|
||||
{
|
||||
binfo = lookup_base (objtype, ctype, ba_check, NULL);
|
||||
binfo = lookup_base (objtype, ctype, ba_check, NULL, complain);
|
||||
|
||||
if (!binfo)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2012-09-05 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/54191
|
||||
* g++.dg/cpp0x/sfinae39.C: New.
|
||||
|
||||
2012-09-04 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/54441
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
// PR c++/54191
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct B
|
||||
{};
|
||||
|
||||
struct D
|
||||
: private B
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
T &&declval();
|
||||
|
||||
|
||||
template<typename From, typename = decltype(B{declval<From>()})>
|
||||
constexpr bool test_braced_cast_to_base(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename>
|
||||
constexpr bool test_braced_cast_to_base(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_braced_cast_to_base<D>(0), "");
|
||||
|
||||
|
||||
template<typename From, typename = decltype(D{declval<From>()})>
|
||||
constexpr bool test_braced_cast_to_derived(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename>
|
||||
constexpr bool test_braced_cast_to_derived(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_braced_cast_to_derived<B>(0), "");
|
||||
|
||||
|
||||
typedef B *PB;
|
||||
|
||||
template<typename From, typename = decltype(PB{declval<From>()})>
|
||||
constexpr bool test_braced_cast_to_ptr_to_base(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename>
|
||||
constexpr bool test_braced_cast_to_ptr_to_base(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_braced_cast_to_ptr_to_base<D *>(0), "");
|
||||
|
||||
|
||||
typedef D *PD;
|
||||
|
||||
template<typename From, typename = decltype(PD{declval<From>()})>
|
||||
constexpr bool test_braced_cast_to_ptr_to_derived(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename>
|
||||
constexpr bool test_braced_cast_to_ptr_to_derived(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_braced_cast_to_ptr_to_derived<B *>(0), "");
|
||||
|
||||
|
||||
template<typename From, typename To,
|
||||
typename = decltype(static_cast<To>(declval<From>()))>
|
||||
constexpr bool test_static_cast(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename, typename>
|
||||
constexpr bool test_static_cast(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_static_cast<B &, D &>(0), "");
|
||||
static_assert(!test_static_cast<B *, D *>(0), "");
|
||||
|
||||
|
||||
template<typename From, typename To,
|
||||
typename = decltype(dynamic_cast<To>(declval<From>()))>
|
||||
constexpr bool test_dynamic_cast(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename, typename>
|
||||
constexpr bool test_dynamic_cast(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_dynamic_cast<D &, B &>(0), "");
|
||||
static_assert(!test_dynamic_cast<D *, B *>(0), "");
|
||||
|
||||
|
||||
int B::*pm = 0;
|
||||
|
||||
template<typename T, typename = decltype(declval<T>().*pm)>
|
||||
constexpr bool test_member_ptr_dot(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename>
|
||||
constexpr bool test_member_ptr_dot(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_member_ptr_dot<D>(0), "");
|
||||
|
||||
|
||||
template<typename T, typename = decltype(declval<T>()->*pm)>
|
||||
constexpr bool test_member_ptr_arrow(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename>
|
||||
constexpr bool test_member_ptr_arrow(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_member_ptr_arrow<D *>(0), "");
|
||||
|
||||
|
||||
template<typename T, typename U,
|
||||
typename = decltype(declval<T>() < declval<U>())>
|
||||
constexpr bool test_rel_op(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename, typename>
|
||||
constexpr bool test_rel_op(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_rel_op<D *, B *>(0), "");
|
||||
|
||||
|
||||
template<typename T, typename U,
|
||||
typename = decltype(declval<T>() == declval<U>())>
|
||||
constexpr bool test_eq(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename, typename>
|
||||
constexpr bool test_eq(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_eq<D *, B *>(0), "");
|
||||
|
||||
|
||||
template<typename T, typename U,
|
||||
typename = decltype(false ? declval<T>() : declval<U>())>
|
||||
constexpr bool test_cond_op(int)
|
||||
{ return true; }
|
||||
|
||||
template<typename, typename>
|
||||
constexpr bool test_cond_op(bool)
|
||||
{ return false; }
|
||||
|
||||
static_assert(!test_cond_op<B *, D *>(0), "");
|
Loading…
Reference in New Issue