From db422ace3f052fe6c078db73c3699769e4ddde38 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Wed, 9 Nov 2011 17:19:12 +0000 Subject: [PATCH] re PR c++/51047 ([C++0x] SFINAE does not handle errors of ambiguous base members) /cp 2011-11-09 Paolo Carlini PR c++/51047 * search.c (lookup_member): Change to take also a tsubst_flags_t parameter. (lookup_field, lookup_fnfields): Adjust calls. * typeck.c (lookup_destructor, finish_class_member_access_expr, build_ptrmemfunc_access_expr): Likewise. * class.c (handle_using_decl, maybe_note_name_used_in_class): Likewise. * pt.c (resolve_typename_type): Likewise. * semantics.c (lambda_function): Likewise. * parser.c (cp_parser_perform_range_for_lookup, cp_parser_lookup_name): Likewise. * friend.c (make_friend_class): Likewise. * name-lookup.c (pushdecl_maybe_friend_1, get_class_binding, do_class_using_decl, lookup_qualified_name): Likewise. * cp-tree.h (lookup_member): Adjust declaration. /testsuite 2011-11-09 Paolo Carlini PR c++/51047 * g++.dg/cpp0x/sfinae29.C: New. From-SVN: r181213 --- gcc/cp/class.c | 5 +++-- gcc/cp/cp-tree.h | 3 ++- gcc/cp/friend.c | 2 +- gcc/cp/name-lookup.c | 13 ++++++++----- gcc/cp/parser.c | 9 ++++++--- gcc/cp/pt.c | 3 ++- gcc/cp/search.c | 18 ++++++++++++------ gcc/cp/semantics.c | 3 ++- gcc/cp/typeck.c | 7 ++++--- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp0x/sfinae29.C | 17 +++++++++++++++++ 11 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae29.C diff --git a/gcc/cp/class.c b/gcc/cp/class.c index be632be64c8..f10a749032d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1167,7 +1167,8 @@ handle_using_decl (tree using_decl, tree t) gcc_assert (!processing_template_decl && decl); - old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false); + old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false, + tf_warning_or_error); if (old_value) { if (is_overloaded_fn (old_value)) @@ -7290,7 +7291,7 @@ maybe_note_name_used_in_class (tree name, tree decl) /* If there's already a binding for this NAME, then we don't have anything to worry about. */ if (lookup_member (current_class_type, name, - /*protect=*/0, /*want_type=*/false)) + /*protect=*/0, /*want_type=*/false, tf_warning_or_error)) return; if (!current_class_stack[current_class_depth - 1].names_used) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 32d08caf9cc..5ba18856d16 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5367,7 +5367,8 @@ extern tree lookup_fnfields_slot (tree, tree); extern tree lookup_fnfields_slot_nolazy (tree, tree); extern int class_method_index_for_fn (tree, tree); extern tree lookup_fnfields (tree, tree, int); -extern tree lookup_member (tree, tree, int, bool); +extern tree lookup_member (tree, tree, int, bool, + tsubst_flags_t); extern int look_for_overrides (tree, tree); extern void get_pure_virtuals (tree); extern void maybe_suppress_debug_info (tree); diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index b6bd387b829..e532a30e3a3 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -314,7 +314,7 @@ make_friend_class (tree type, tree friend_type, bool complain) } else { - decl = lookup_member (ctype, name, 0, true); + decl = lookup_member (ctype, name, 0, true, tf_warning_or_error); if (!decl) { error ("%qT is not a member of %qT", name, ctype); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 7b61d68208a..044a97f7157 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1121,7 +1121,8 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) member = lookup_member (current_class_type, name, /*protect=*/0, - /*want_type=*/false); + /*want_type=*/false, + tf_warning_or_error); else member = NULL_TREE; @@ -2891,10 +2892,12 @@ get_class_binding (tree name, cp_binding_level *scope) /* Get the type binding. */ type_binding = lookup_member (class_type, name, - /*protect=*/2, /*want_type=*/true); + /*protect=*/2, /*want_type=*/true, + tf_warning_or_error); /* Get the value binding. */ value_binding = lookup_member (class_type, name, - /*protect=*/2, /*want_type=*/false); + /*protect=*/2, /*want_type=*/false, + tf_warning_or_error); if (value_binding && (TREE_CODE (value_binding) == TYPE_DECL @@ -3193,7 +3196,7 @@ do_class_using_decl (tree scope, tree name) } else if (!name_dependent_p) { - decl = lookup_member (binfo, name, 0, false); + decl = lookup_member (binfo, name, 0, false, tf_warning_or_error); if (!decl) { error ("no members matching %<%T::%D%> in %q#T", scope, name, @@ -4258,7 +4261,7 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain) else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE) t = lookup_enumerator (scope, name); else if (is_class_type (scope, complain)) - t = lookup_member (scope, name, 2, is_type_p); + t = lookup_member (scope, name, 2, is_type_p, tf_warning_or_error); if (!t) return error_mark_node; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1376a3af0bd..931c593a447 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -9495,9 +9495,11 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end) id_begin = get_identifier ("begin"); id_end = get_identifier ("end"); member_begin = lookup_member (TREE_TYPE (range), id_begin, - /*protect=*/2, /*want_type=*/false); + /*protect=*/2, /*want_type=*/false, + tf_warning_or_error); member_end = lookup_member (TREE_TYPE (range), id_end, - /*protect=*/2, /*want_type=*/false); + /*protect=*/2, /*want_type=*/false, + tf_warning_or_error); if (member_begin != NULL_TREE || member_end != NULL_TREE) { @@ -20398,7 +20400,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, object_decl = lookup_member (object_type, name, /*protect=*/0, - tag_type != none_type); + tag_type != none_type, + tf_warning_or_error); /* Look it up in the enclosing context, too. */ decl = lookup_name_real (name, tag_type != none_type, /*nonclass=*/0, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8c91a9ed021..e53e90ffbed 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19861,7 +19861,8 @@ resolve_typename_type (tree type, bool only_current_p) longer be considered a dependent type. */ pushed_scope = push_scope (scope); /* Look up the declaration. */ - decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true); + decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true, + tf_warning_or_error); result = NULL_TREE; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 40af661e953..7d9551c28bf 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1155,7 +1155,8 @@ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype) If nothing can be found return NULL_TREE and do not issue an error. */ tree -lookup_member (tree xbasetype, tree name, int protect, bool want_type) +lookup_member (tree xbasetype, tree name, int protect, bool want_type, + tsubst_flags_t complain) { tree rval, rval_binfo = NULL_TREE; tree type = NULL_TREE, basetype_path = NULL_TREE; @@ -1250,9 +1251,12 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type) if (errstr && protect) { - error (errstr, name, type); - if (lfi.ambiguous) - print_candidates (lfi.ambiguous); + if (complain & tf_error) + { + error (errstr, name, type); + if (lfi.ambiguous) + print_candidates (lfi.ambiguous); + } rval = error_mark_node; } @@ -1269,7 +1273,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type) tree lookup_field (tree xbasetype, tree name, int protect, bool want_type) { - tree rval = lookup_member (xbasetype, name, protect, want_type); + tree rval = lookup_member (xbasetype, name, protect, want_type, + tf_warning_or_error); /* Ignore functions, but propagate the ambiguity list. */ if (!error_operand_p (rval) @@ -1285,7 +1290,8 @@ lookup_field (tree xbasetype, tree name, int protect, bool want_type) tree lookup_fnfields (tree xbasetype, tree name, int protect) { - tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false); + tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false, + tf_warning_or_error); /* Ignore non-functions, but propagate the ambiguity list. */ if (!error_operand_p (rval) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 508e2529fbe..e9da3817577 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8621,7 +8621,8 @@ lambda_function (tree lambda) && !COMPLETE_OR_OPEN_TYPE_P (type)) return NULL_TREE; lambda = lookup_member (type, ansi_opname (CALL_EXPR), - /*protect=*/0, /*want_type=*/false); + /*protect=*/0, /*want_type=*/false, + tf_warning_or_error); if (lambda) lambda = BASELINK_FUNCTIONS (lambda); return lambda; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index aed28918db8..2964952241a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2397,7 +2397,8 @@ lookup_destructor (tree object, tree scope, tree dtor_name) return error_mark_node; } expr = lookup_member (dtor_type, complete_dtor_identifier, - /*protect=*/1, /*want_type=*/false); + /*protect=*/1, /*want_type=*/false, + tf_warning_or_error); expr = (adjust_result_of_qualified_name_lookup (expr, dtor_type, object_type)); return expr; @@ -2607,7 +2608,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, { /* Look up the member. */ member = lookup_member (access_path, name, /*protect=*/1, - /*want_type=*/false); + /*want_type=*/false, complain); if (member == NULL_TREE) { if (complain & tf_error) @@ -2681,7 +2682,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) ptrmem_type = TREE_TYPE (ptrmem); gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type)); member = lookup_member (ptrmem_type, member_name, /*protect=*/0, - /*want_type=*/false); + /*want_type=*/false, tf_warning_or_error); member_type = cp_build_qualified_type (TREE_TYPE (member), cp_type_quals (ptrmem_type)); return fold_build3_loc (input_location, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 83ef1714d20..03691b51c0d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-11-09 Paolo Carlini + + PR c++/51047 + * g++.dg/cpp0x/sfinae29.C: New. + 2011-11-09 Janus Weil PR fortran/50960 diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae29.C b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C new file mode 100644 index 00000000000..a2e10b41d3e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C @@ -0,0 +1,17 @@ +// PR c++/51047 +// { dg-options -std=c++0x } + +template T &&declval(); +template decltype(declval().x) f(T *); +template char f(T); +struct B1{ int x; }; +struct B2{ int x; }; +struct D : public B1, B2{}; +struct S { int x; }; +int main() +{ + S *p = nullptr; + static_assert(sizeof(f(p)) == sizeof(int), ""); + D *q = nullptr; + static_assert(sizeof(f(q)) == 1u, ""); +}