From 6bab4c63c4277ce8831c9d1cb6161f12f557f7f6 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 16 Feb 2016 19:50:23 -0500 Subject: [PATCH] re PR c++/10200 (Weird clash with same names in different scopes) PR c++/10200 PR c++/69753 * call.c, cp-tree.h, name-lookup.c, pt.c, search.c, semantics.c, tree.c, typeck2.c: Revert earlier changes. * parser.c (cp_parser_lookup_name): Ignore namespace-scope non-type templates after -> or . From-SVN: r233481 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/call.c | 5 +- gcc/cp/cp-tree.h | 2 +- gcc/cp/name-lookup.c | 13 ++++- gcc/cp/parser.c | 52 +++++++++++-------- gcc/cp/pt.c | 13 ++--- gcc/cp/search.c | 18 ------- gcc/cp/semantics.c | 23 +++++++- gcc/cp/tree.c | 17 ++++++ gcc/cp/typeck2.c | 5 +- .../g++.dg/template/dependent-expr9.C | 10 ++++ 11 files changed, 107 insertions(+), 60 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/dependent-expr9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d12cb73e2da..b76f85d8f36 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2016-02-16 Jason Merrill + + PR c++/10200 + PR c++/69753 + * call.c, cp-tree.h, name-lookup.c, pt.c, search.c, semantics.c, + tree.c, typeck2.c: Revert earlier changes. + * parser.c (cp_parser_lookup_name): Ignore namespace-scope + non-type templates after -> or . + 2016-02-16 Jakub Jelinek PR c/69835 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index db406543522..cb71176c6ca 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8160,7 +8160,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, if (permerror (input_location, "cannot call constructor %<%T::%D%> directly", - BINFO_TYPE (access_binfo), name)) + basetype, name)) inform (input_location, "for a function-style cast, remove the " "redundant %<::%D%>", name); call = build_functional_cast (basetype, build_tree_list_vec (user_args), @@ -8377,9 +8377,6 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, we know we really need it. */ cand->first_arg = instance; } - else if (any_dependent_bases_p ()) - /* We can't tell until instantiation time whether we can use - *this as the implicit object argument. */; else { if (complain & tf_error) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b7d7bc68502..3b91089f50d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6252,7 +6252,6 @@ extern tree adjust_result_of_qualified_name_lookup extern tree copied_binfo (tree, tree); extern tree original_binfo (tree, tree); extern int shared_member_p (tree); -extern bool any_dependent_bases_p (tree = current_nonlambda_class_type ()); /* The representation of a deferred access check. */ @@ -6543,6 +6542,7 @@ extern tree get_first_fn (tree); extern tree ovl_cons (tree, tree); extern tree build_overload (tree, tree); extern tree ovl_scope (tree); +extern bool non_static_member_function_p (tree); extern const char *cxx_printable_name (tree, int); extern const char *cxx_printable_name_translate (tree, int); extern tree build_exception_variant (tree, tree); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index b73f3f7345f..89d84d7b1c3 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3333,6 +3333,8 @@ do_class_using_decl (tree scope, tree name) /* True if any of the bases of CURRENT_CLASS_TYPE are dependent. */ bool bases_dependent_p; tree binfo; + tree base_binfo; + int i; if (name == error_mark_node) return NULL_TREE; @@ -3369,7 +3371,16 @@ do_class_using_decl (tree scope, tree name) || (IDENTIFIER_TYPENAME_P (name) && dependent_type_p (TREE_TYPE (name)))); - bases_dependent_p = any_dependent_bases_p (current_class_type); + bases_dependent_p = false; + if (processing_template_decl) + for (binfo = TYPE_BINFO (current_class_type), i = 0; + BINFO_BASE_ITERATE (binfo, i, base_binfo); + i++) + if (dependent_type_p (TREE_TYPE (base_binfo))) + { + bases_dependent_p = true; + break; + } decl = NULL_TREE; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b8d823787ec..18f390206d0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7184,16 +7184,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, if (token_type == CPP_DEREF) postfix_expression = build_x_arrow (location, postfix_expression, tf_warning_or_error); - /* According to the standard, no expression should ever have - reference type. Unfortunately, we do not currently match - the standard in this respect in that our internal representation - of an expression may have reference type even when the standard - says it does not. Therefore, we have to manually obtain the - underlying type here. */ - scope = non_reference (TREE_TYPE (postfix_expression)); - /* Check to see whether or not the expression is type-dependent and - not the current instantiation. */ - dependent_p = !scope || dependent_scope_p (scope); + /* Check to see whether or not the expression is type-dependent. */ + dependent_p = type_dependent_expression_p (postfix_expression); /* The identifier following the `->' or `.' is not qualified. */ parser->scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; @@ -7202,8 +7194,16 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, /* Enter the scope corresponding to the type of the object given by the POSTFIX_EXPRESSION. */ - if (!dependent_p) - { + if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE) + { + scope = TREE_TYPE (postfix_expression); + /* According to the standard, no expression should ever have + reference type. Unfortunately, we do not currently match + the standard in this respect in that our internal representation + of an expression may have reference type even when the standard + says it does not. Therefore, we have to manually obtain the + underlying type here. */ + scope = non_reference (scope); /* The type of the POSTFIX_EXPRESSION must be complete. */ if (scope == unknown_type_node) { @@ -7215,10 +7215,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, required to be of complete type for purposes of class member access (5.2.5) outside the member function body. */ else if (postfix_expression != current_class_ref - && !(processing_template_decl - && current_class_type - && (same_type_ignoring_top_level_qualifiers_p - (scope, current_class_type)))) + && !(processing_template_decl && scope == current_class_type)) scope = complete_type_or_else (scope, NULL_TREE); /* Let the name lookup machinery know that we are processing a class member access expression. */ @@ -24727,11 +24724,24 @@ cp_parser_lookup_name (cp_parser *parser, tree name, decl = NULL_TREE; if (!decl) - /* Look it up in the enclosing context. DR 141: When looking for a - template-name after -> or ., only consider class templates. */ - decl = lookup_name_real (name, tag_type != none_type || is_template, - /*nonclass=*/0, - /*block_p=*/true, is_namespace, 0); + { + /* Look it up in the enclosing context. */ + decl = lookup_name_real (name, tag_type != none_type, + /*nonclass=*/0, + /*block_p=*/true, is_namespace, 0); + /* DR 141 says when looking for a template-name after -> or ., only + consider class templates. We need to fix our handling of + dependent expressions to implement that properly, but for now + let's ignore namespace-scope function templates. */ + if (decl && is_template && !DECL_TYPE_TEMPLATE_P (decl)) + { + tree d = decl; + if (is_overloaded_fn (d)) + d = get_first_fn (d); + if (DECL_P (d) && !DECL_CLASS_SCOPE_P (d)) + decl = NULL_TREE; + } + } if (object_type == unknown_type_node) /* The object is type-dependent, so we can't look anything up; we used this to get the DR 141 behavior. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 52e60b948b4..a55dc10fdfc 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -22904,16 +22904,9 @@ type_dependent_expression_p (tree expression) && DECL_TEMPLATE_INFO (expression)) return any_dependent_template_arguments_p (DECL_TI_ARGS (expression)); - if (TREE_CODE (expression) == TEMPLATE_DECL) - { - if (DECL_CLASS_SCOPE_P (expression) - && dependent_type_p (DECL_CONTEXT (expression))) - /* A template's own parameters don't make it dependent, since those can - be deduced, but the enclosing class does. */ - return true; - if (!DECL_TEMPLATE_TEMPLATE_PARM_P (expression)) - return false; - } + if (TREE_CODE (expression) == TEMPLATE_DECL + && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression)) + return false; if (TREE_CODE (expression) == STMT_EXPR) expression = stmt_expr_value_expr (expression); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 49f3bc5ed80..79246118915 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2842,21 +2842,3 @@ original_binfo (tree binfo, tree here) return result; } -/* True iff TYPE has any dependent bases (and therefore we can't say - definitively that another class is not a base of an instantiation of - TYPE). */ - -bool -any_dependent_bases_p (tree type) -{ - if (!type || !CLASS_TYPE_P (type) || !processing_template_decl) - return false; - - unsigned i; - tree base_binfo; - FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_BINFOS (TYPE_BINFO (type)), i, base_binfo) - if (BINFO_DEPENDENT_BASE_P (base_binfo)) - return true; - - return false; -} diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 70a7aa5bdf5..f0288eae09d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2264,7 +2264,17 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, with no type; type_dependent_expression_p recognizes expressions with no type as being dependent. */ if (type_dependent_expression_p (fn) - || any_type_dependent_arguments_p (*args)) + || any_type_dependent_arguments_p (*args) + /* For a non-static member function that doesn't have an + explicit object argument, we need to specifically + test the type dependency of the "this" pointer because it + is not included in *ARGS even though it is considered to + be part of the list of arguments. Note that this is + related to CWG issues 515 and 1005. */ + || (TREE_CODE (fn) != COMPONENT_REF + && non_static_member_function_p (fn) + && current_class_ref + && type_dependent_expression_p (current_class_ref))) { result = build_nt_call_vec (fn, *args); SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location)); @@ -2344,6 +2354,17 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), NULL); + if (processing_template_decl) + { + if (type_dependent_expression_p (object)) + { + tree ret = build_nt_call_vec (orig_fn, orig_args); + release_tree_vector (orig_args); + return ret; + } + object = build_non_dependent_expr (object); + } + result = build_new_method_call (object, fn, args, NULL_TREE, (disallow_virtual ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 041facda96a..3203acaff9e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2071,6 +2071,23 @@ ovl_scope (tree ovl) ovl = OVL_CHAIN (ovl); return CP_DECL_CONTEXT (OVL_CURRENT (ovl)); } + +/* Return TRUE if FN is a non-static member function, FALSE otherwise. + This function looks into BASELINK and OVERLOAD nodes. */ + +bool +non_static_member_function_p (tree fn) +{ + if (fn == NULL_TREE) + return false; + + if (is_overloaded_fn (fn)) + fn = get_first_fn (fn); + + return (DECL_P (fn) + && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)); +} + #define PRINT_RING_SIZE 4 diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 54a432f256f..2a76c96c7d4 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1694,10 +1694,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain) if (processing_template_decl) { - if (type && TREE_CODE (type) == POINTER_TYPE - && !dependent_scope_p (TREE_TYPE (type))) - /* Pointer to current instantiation, don't treat as dependent. */; - else if (type_dependent_expression_p (expr)) + if (type_dependent_expression_p (expr)) return build_min_nt_loc (loc, ARROW_EXPR, expr); expr = build_non_dependent_expr (expr); } diff --git a/gcc/testsuite/g++.dg/template/dependent-expr9.C b/gcc/testsuite/g++.dg/template/dependent-expr9.C new file mode 100644 index 00000000000..7da060d4bb6 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-expr9.C @@ -0,0 +1,10 @@ +// PR c++/69753 + +class A { +public: + template void m_fn1(); +}; +A *fn1(int *); +template class B : A { + static int *m_fn2() { fn1(m_fn2())->m_fn1(); } +}; -- 2.30.2