diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2012-09-05 10:14:37 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2012-09-05 10:14:37 +0000 |
commit | 22854930b945f09487ca7947326d741ff6328377 (patch) | |
tree | 2f95f089c2fa4d79dab5770ad9a8b5fa4956d54b /gcc | |
parent | b588ae3074e258f5c736034c212e7499a565746f (diff) | |
download | gcc-22854930b945f09487ca7947326d741ff6328377.zip gcc-22854930b945f09487ca7947326d741ff6328377.tar.gz gcc-22854930b945f09487ca7947326d741ff6328377.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 27 | ||||
-rw-r--r-- | gcc/cp/call.c | 8 | ||||
-rw-r--r-- | gcc/cp/class.c | 43 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 20 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 13 | ||||
-rw-r--r-- | gcc/cp/decl.c | 2 | ||||
-rw-r--r-- | gcc/cp/except.c | 2 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 3 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 2 | ||||
-rw-r--r-- | gcc/cp/search.c | 42 | ||||
-rw-r--r-- | gcc/cp/tree.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 24 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/sfinae39.C | 146 |
15 files changed, 268 insertions, 80 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 629ab57..41c0160 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4d65b3e..159be6b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 3b1906a..13d9c76 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index fa3d7b0..3e0fc3f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.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); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 9550f15..86f01ab 100644 --- a/gcc/cp/cvt.c +++ b/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) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b665fe8..f86c54f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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", diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 2339b9c..ff967de 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 0211d4f..9392c01 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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) diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 51cb5ee..e619180 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -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) { diff --git a/gcc/cp/search.c b/gcc/cp/search.c index dc802e4..7d358ef 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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; } } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7cc2457..ce1af73 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 25f37e8..f625321 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 2180535..6faebb5 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 62dfe13..26a82db 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae39.C b/gcc/testsuite/g++.dg/cpp0x/sfinae39.C new file mode 100644 index 0000000..8183bda --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae39.C @@ -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), ""); |