Correct construction of bindings for overloaded symbols.
Index: gcc/testsuite/ChangeLog.pph 2011-01-20 Lawrence Crowl <cr...@google.com> * g++.dg/pph/x4overset1.cc: Make passing. * g++.dg/pph/x4overset2.cc: Make wanted assembly diff. * g++.dg/pph/x4overset3.cc: Make passing. * g++.dg/pph/x4overset4.cc: Make wanted assembly diff. * g++.dg/pph/x6dynarray3.cc: Change xfail signature. Index: gcc/cp/ChangeLog.pph 2012-01-20 Lawrence Crowl <cr...@google.com> * parser.c (cp_debug_parser_where): Protect against null pointers. * name-lookup.c (cxx_binding_make_for_name): New. (binding_for_name): Factor construction into the above. (modify_binding_for_overload): New. (push_overloaded_decl_1): Factor out above function. (pph_foreach_on_chain_bl): Add filter parameter. (pph_set_identifier_bindings): Likewise. (pph_set_chain_identifier_bindings): Likewise. (pph_set_chain_namespace_bindings): Likewise. (pph_set_namespace_bindings): Likewise. Correct overloading. (pph_set_namespace_namespace_bindings): Add filter parameter in calls. (pph_set_global_identifier_bindings): Likewise. Index: gcc/testsuite/g++.dg/pph/x6dynarray3.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x6dynarray3.cc (revision 183345) +++ gcc/testsuite/g++.dg/pph/x6dynarray3.cc (working copy) @@ -1,8 +1,6 @@ -// { dg-bogus "a0dynarray-dfn1b.hi:8:13: error: no matching function for call to 'operator new" "" { xfail *-*-* } 0 } // { dg-bogus "a0dynarray-dfn1b.hi:22:5: error: no suitable 'operator delete" "" { xfail *-*-* } 0 } -// { dg-bogus "a0dynarray-dfn2b.hi:8:13: error: no matching function for call to 'operator new" "" { xfail *-*-* } 0 } // { dg-bogus "a0dynarray-dfn2b.hi:13:9: error: no suitable 'operator delete" "" { xfail *-*-* } 0 } -// { dg-bogus "a0dynarray-dcl3.hi:11:60: warning: no corresponding deallocation function for 'void. operator new" "" { xfail *-*-* } 0 } +// { dg-bogus "a0dynarray-dcl3.hi:11:60: error: call of overloaded 'operator new" "" { xfail *-*-* } 0 } #include "x5dynarray3.h" Index: gcc/testsuite/g++.dg/pph/x4overset1.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4overset1.cc (revision 183345) +++ gcc/testsuite/g++.dg/pph/x4overset1.cc (working copy) @@ -1,5 +1,3 @@ -// pph asm xdiff 56596 - #include "x1overset1.h" #include "x1overset2.h" Index: gcc/testsuite/g++.dg/pph/x4overset2.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4overset2.cc (revision 183345) +++ gcc/testsuite/g++.dg/pph/x4overset2.cc (working copy) @@ -1,5 +1,4 @@ -// pph asm xdiff 01525 -// wanted 57625 +// pph asm xwant 19882 // This test produces overload differences because the declaration and // call orders are different between pph and textual parsing. Index: gcc/testsuite/g++.dg/pph/x4overset3.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4overset3.cc (revision 183345) +++ gcc/testsuite/g++.dg/pph/x4overset3.cc (working copy) @@ -1,5 +1,3 @@ -// pph asm xdiff 56596 - #include "x1overset1.h" #include "x1overset2.h" #include "x1overset1.h" Index: gcc/testsuite/g++.dg/pph/x4overset4.cc =================================================================== --- gcc/testsuite/g++.dg/pph/x4overset4.cc (revision 183345) +++ gcc/testsuite/g++.dg/pph/x4overset4.cc (working copy) @@ -1,5 +1,4 @@ -// pph asm xdiff 01525 -// wanted 57625 +// pph asm xwant 19882 // This test produces overload differences because the declaration and // call orders are different between pph and textual parsing. Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 183345) +++ gcc/cp/parser.c (working copy) @@ -471,12 +471,34 @@ void cp_debug_parser_where (FILE *file, cp_parser *parser) { const size_t window_size = 20; - cp_token *token = parser->lexer->next_token; - expanded_location eloc = expand_location (token->location); + cp_lexer *lexer; + cp_token *token; + expanded_location eloc; if (file == NULL) file = stderr; + if (parser == NULL) + { + fprintf (file, "No parser available.\n"); + return; + } + + lexer = parser->lexer; + if (lexer == NULL) + { + fprintf (file, "No lexer available.\n"); + return; + } + + token = lexer->next_token; + if (token == NULL) + { + fprintf (file, "No token available.\n"); + return; + } + + eloc = expand_location (token->location); fprintf (file, "%s:%d:%d ", eloc.file, eloc.line, eloc.column); cp_debug_parser_tokens (file, parser, window_size); } Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 183345) +++ gcc/cp/name-lookup.c (working copy) @@ -2035,19 +2035,12 @@ cp_binding_level_find_binding_for_name ( return NULL; } -/* Always returns a binding for name in scope. If no binding is - found, make a new one. */ +/* Return an new cxx_binding initialized for a NAME in SCOPE. */ static cxx_binding * -binding_for_name (cp_binding_level *scope, tree name) +cxx_binding_make_for_name (cp_binding_level *scope, tree name) { - cxx_binding *result; - - result = cp_binding_level_find_binding_for_name (scope, name); - if (result) - return result; - /* Not found, make a new one. */ - result = cxx_binding_make (NULL, NULL); + cxx_binding *result = cxx_binding_make (NULL, NULL); result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name); result->scope = scope; result->is_local = false; @@ -2056,6 +2049,18 @@ binding_for_name (cp_binding_level *scop return result; } +/* Always returns a binding for name in scope. If no binding is + found, make a new one. */ + +static cxx_binding * +binding_for_name (cp_binding_level *scope, tree name) +{ + cxx_binding *result = cp_binding_level_find_binding_for_name (scope, name); + if (!result) + result = cxx_binding_make_for_name (scope, name); + return result; +} + /* Walk through the bindings associated to the name of FUNCTION, and return the first declaration of a function with a "C" linkage specification, a.k.a 'extern "C"'. @@ -2205,6 +2210,29 @@ pushdecl_with_scope (tree x, cp_binding_ return ret; } +static tree +modify_binding_for_overload (tree decl, tree old, int flags) +{ + tree new_binding; + if (old || TREE_CODE (decl) == TEMPLATE_DECL + /* If it's a using declaration, we always need to build an OVERLOAD, + because it's the only way to remember that the declaration comes + from 'using', and have the lookup behave correctly. */ + || (flags & PUSH_USING)) + { + if (old && TREE_CODE (old) != OVERLOAD) + new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE)); + else + new_binding = ovl_cons (decl, old); + if (flags & PUSH_USING) + OVL_USED (new_binding) = 1; + } + else + /* NAME is not ambiguous. */ + new_binding = decl; + return new_binding; +} + /* DECL is a FUNCTION_DECL for a non-member function, which may have other definitions already in place. We get around this by making @@ -2294,22 +2322,7 @@ push_overloaded_decl_1 (tree decl, int f } } - if (old || TREE_CODE (decl) == TEMPLATE_DECL - /* If it's a using declaration, we always need to build an OVERLOAD, - because it's the only way to remember that the declaration comes - from 'using', and have the lookup behave correctly. */ - || (flags & PUSH_USING)) - { - if (old && TREE_CODE (old) != OVERLOAD) - new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE)); - else - new_binding = ovl_cons (decl, old); - if (flags & PUSH_USING) - OVL_USED (new_binding) = 1; - } - else - /* NAME is not ambiguous. */ - new_binding = decl; + new_binding = modify_binding_for_overload (decl, old, flags); if (doing_global) set_namespace_binding (name, current_namespace, new_binding); @@ -6114,14 +6127,14 @@ pph_debug_binding_inaction (const char * with argument BL. */ static void -pph_foreach_on_chain_bl (tree first, cp_binding_level *bl, - void (*function)(tree, cp_binding_level *)) +pph_foreach_on_chain_bl (tree first, cp_binding_level *bl, int flags, + void (*function)(tree, cp_binding_level *, int)) { unsigned i; tree decl; VEC(tree,heap) *w = chain2vec (first); FOR_EACH_VEC_ELT_REVERSE (tree, w, i, decl) - (*function) (decl, bl); + (*function) (decl, bl, flags); VEC_free (tree, heap, w); } @@ -6129,7 +6142,8 @@ pph_foreach_on_chain_bl (tree first, cp_ /* Set a identifier binding. */ static void -pph_set_identifier_bindings (tree decl, cp_binding_level *bl) +pph_set_identifier_bindings (tree decl, cp_binding_level *bl, + int flags ATTRIBUTE_UNUSED) { /* Set the identifier binding for a single decl. */ tree id = DECL_NAME (decl); @@ -6141,48 +6155,88 @@ pph_set_identifier_bindings (tree decl, } -/* Set the identifier bindings for an individual chain. */ +/* Set the identifier bindings for an individual chain. */ static void -pph_set_chain_identifier_bindings (tree first, cp_binding_level *bl) +pph_set_chain_identifier_bindings (tree first, cp_binding_level *bl, int flags) { - pph_foreach_on_chain_bl (first, bl, pph_set_identifier_bindings); + pph_foreach_on_chain_bl (first, bl, flags, pph_set_identifier_bindings); +} + + +#if 0 +/* Add an overload to a binding. */ + +static tree +pph_add_overload (tree decl, tree older) +{ + tree newer; + if (older && TREE_CODE (older) != OVERLOAD) + newer = ovl_cons (decl, ovl_cons (older, NULL_TREE)); + else + newer = ovl_cons (decl, older); + return newer; } +#endif /* Set a namespace identifier binding. */ static void -pph_set_namespace_bindings (tree decl, cp_binding_level *bl) +pph_set_namespace_bindings (tree decl, cp_binding_level *bl, int flags) { /* Set the namespace identifier binding for a single decl. */ tree id = DECL_NAME (decl); if (id) { - /* This code plagarizes from set_namespace_binding. + /* FIXME pph: This code plagarizes from push_overloaded_decl_1 and + binding_for_name. It may be incomplete. */ + cxx_binding *b = cp_binding_level_find_binding_for_name (bl, id); + if (b) + { + tree old = b->value; + if (is_overloaded_fn (old)) + { + /* We don't overload implicit built-ins. duplicate_decls() + may fail to merge the decls if the new decl is e.g. a + template function. */ + if (TREE_CODE (old) == FUNCTION_DECL + && DECL_ANTICIPATED (old) + && !DECL_HIDDEN_FRIEND_P (old)) + old = NULL; + decl = modify_binding_for_overload (decl, old, flags); + } + } + else + b = cxx_binding_make_for_name (bl, id); + + /* FIXME pph: This code plagarizes from set_namespace_binding. It has trouble with supplement_binding, methinks. */ - /* FIXME pph: we should do more merging here. */ - cxx_binding *b = binding_for_name (bl, id); if (!b->value) { b->value = decl; - pph_debug_binding_action ("v-bind", decl); + pph_debug_binding_action ("new bind", decl); + } + if (TREE_CODE (decl) == OVERLOAD) + { + b->value = decl; + pph_debug_binding_action ("ovl bind", decl); } else if (TREE_CODE (b->value) == TYPE_DECL && TREE_CODE (decl) != TYPE_DECL) { b->type = b->value; b->value = decl; - pph_debug_binding_action ("p-bind", decl); + pph_debug_binding_action ("t/v bind", decl); } else if (TREE_CODE (b->value) != TYPE_DECL && TREE_CODE (decl) == TYPE_DECL) { b->type = decl; - pph_debug_binding_action ("t-bind", decl); + pph_debug_binding_action ("v/t bind", decl); } else - pph_debug_binding_inaction ("n-bind", decl); + pph_debug_binding_inaction ("not bind", decl); } } @@ -6190,9 +6244,9 @@ pph_set_namespace_bindings (tree decl, c /* Set the namespace identifier bindings. */ static void -pph_set_chain_namespace_bindings (tree first, cp_binding_level *bl) +pph_set_chain_namespace_bindings (tree first, cp_binding_level *bl, int flags) { - pph_foreach_on_chain_bl (first, bl, pph_set_namespace_bindings); + pph_foreach_on_chain_bl (first, bl, flags, pph_set_namespace_bindings); } @@ -6234,10 +6288,12 @@ pph_set_namespace_namespace_binding (tre static void pph_set_namespace_namespace_bindings (cp_binding_level *bl) { - pph_set_chain_namespace_bindings (bl->names, bl); - pph_set_chain_namespace_bindings (bl->namespaces, bl); - pph_set_chain_namespace_bindings (bl->usings, bl); - /* FIXME pph: pph_set_chain_namespace_bindings (bl->using_directives, bl); */ + pph_set_chain_namespace_bindings (bl->names, bl, 0); + pph_set_chain_namespace_bindings (bl->namespaces, bl, 0); + pph_set_chain_namespace_bindings (bl->usings, bl, PUSH_USING); + /* FIXME pph: + pph_set_chain_namespace_bindings (bl->using_directives, bl, 0); + */ pph_foreach_on_chain (bl->namespaces, pph_set_namespace_namespace_binding); } @@ -6249,10 +6305,10 @@ void pph_set_global_identifier_bindings (void) { cp_binding_level *bl = scope_chain->bindings; - pph_set_chain_identifier_bindings (bl->names, bl); - pph_set_chain_identifier_bindings (bl->namespaces, bl); - pph_set_chain_identifier_bindings (bl->usings, bl); - pph_set_chain_identifier_bindings (bl->using_directives, bl); + pph_set_chain_identifier_bindings (bl->names, bl, 0); + pph_set_chain_identifier_bindings (bl->namespaces, bl, 0); + pph_set_chain_identifier_bindings (bl->usings, bl, PUSH_USING); + pph_set_chain_identifier_bindings (bl->using_directives, bl, 0); pph_set_namespace_namespace_bindings (bl); } -- This patch is available for review at http://codereview.appspot.com/5555059