From 3a08be01b5ebf53fdae13a6dd9c208e344a4665c Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 21 Jan 2014 16:02:31 +0000 Subject: [PATCH] MFC r260332; gcc: backport some fixes from llvm-gcc MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit llvm-gcc backported some patches from gcc trunk: http://gcc.gnu.org/ml/gcc-cvs/2007-05/msg00662.html http://gcc.gnu.org/ml/gcc-cvs/2007-07/msg00019.html http://gcc.gnu.org/ml/gcc-cvs/2007-08/msg00240.html http://gcc.gnu.org/ml/gcc-cvs/2007-08/msg00493.html The first two were always GPL2. The last two were added after the GPL3 transition, but were written by aaw@google.com and Rafael Espíndola got permission to relicense them under the GPL2 for inclusion in llvm-gcc. This fixes GCC-PR c++/31749 Obtained from: llvm-gcc (rev. 75463; GPLv2) git-svn-id: svn://svn.freebsd.org/base/stable/8@260985 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- contrib/gcc/cp/decl.c | 6 + contrib/gcc/cp/name-lookup.c | 318 ++++++++++++++++++----------------- contrib/gcc/cp/parser.c | 8 +- 3 files changed, 180 insertions(+), 152 deletions(-) diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c index 8b7a4880a..1897a74e3 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -9726,6 +9726,12 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, | DECL_SELF_REFERENCE_P (decl)); return t; } + else if (decl && TREE_CODE (decl) == TREE_LIST) + { + error ("reference to %qD is ambiguous", name); + print_candidates (decl); + return error_mark_node; + } else return NULL_TREE; } diff --git a/contrib/gcc/cp/name-lookup.c b/contrib/gcc/cp/name-lookup.c index 744dd5c48..ccea65ab8 100644 --- a/contrib/gcc/cp/name-lookup.c +++ b/contrib/gcc/cp/name-lookup.c @@ -42,7 +42,6 @@ struct scope_binding { #define EMPTY_SCOPE_BINDING { NULL_TREE, NULL_TREE } static cxx_scope *innermost_nonclass_level (void); -static tree select_decl (const struct scope_binding *, int); static cxx_binding *binding_for_name (cxx_scope *, tree); static tree lookup_name_innermost_nonclass_level (tree); static tree push_overloaded_decl (tree, int, bool); @@ -2082,6 +2081,22 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, return; } + /* LLVM LOCAL begin mainline */ + /* Shift the old and new bindings around so we're comparing class and + enumeration names to each other. */ + if (oldval && DECL_IMPLICIT_TYPEDEF_P (oldval)) + { + oldtype = oldval; + oldval = NULL_TREE; + } + + if (decls.value && DECL_IMPLICIT_TYPEDEF_P (decls.value)) + { + decls.type = decls.value; + decls.value = NULL_TREE; + } + /* LLVM LOCAL end mainline */ + /* It is impossible to overload a built-in function; any explicit declaration eliminates the built-in declaration. So, if OLDVAL is a built-in, then we can just pretend it isn't there. */ @@ -2091,95 +2106,112 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, && !DECL_HIDDEN_FRIEND_P (oldval)) oldval = NULL_TREE; - /* Check for using functions. */ - if (decls.value && is_overloaded_fn (decls.value)) + /* LLVM LOCAL begin mainline */ + if (decls.value) { - tree tmp, tmp1; - - if (oldval && !is_overloaded_fn (oldval)) - { - if (!DECL_IMPLICIT_TYPEDEF_P (oldval)) - error ("%qD is already declared in this scope", name); - oldval = NULL_TREE; - } - - *newval = oldval; - for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) + /* Check for using functions. */ + if (is_overloaded_fn (decls.value)) { - tree new_fn = OVL_CURRENT (tmp); + tree tmp, tmp1; - /* [namespace.udecl] + if (oldval && !is_overloaded_fn (oldval)) + { + error ("%qD is already declared in this scope", name); + oldval = NULL_TREE; + } - If a function declaration in namespace scope or block - scope has the same name and the same parameter types as a - function introduced by a using declaration the program is - ill-formed. */ - for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) + *newval = oldval; + for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) { - tree old_fn = OVL_CURRENT (tmp1); - - if (new_fn == old_fn) - /* The function already exists in the current namespace. */ - break; - else if (OVL_USED (tmp1)) - continue; /* this is a using decl */ - else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), - TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) + tree new_fn = OVL_CURRENT (tmp); + + /* [namespace.udecl] + + If a function declaration in namespace scope or block + scope has the same name and the same parameter types as a + function introduced by a using declaration the program is + ill-formed. */ + for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) { - gcc_assert (!DECL_ANTICIPATED (old_fn) - || DECL_HIDDEN_FRIEND_P (old_fn)); + tree old_fn = OVL_CURRENT (tmp1); - /* There was already a non-using declaration in - this scope with the same parameter types. If both - are the same extern "C" functions, that's ok. */ - if (decls_match (new_fn, old_fn)) + if (new_fn == old_fn) + /* The function already exists in the current namespace. */ break; - else + else if (OVL_USED (tmp1)) + continue; /* this is a using decl */ + else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), + TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) { - error ("%qD is already declared in this scope", name); - break; + gcc_assert (!DECL_ANTICIPATED (old_fn) + || DECL_HIDDEN_FRIEND_P (old_fn)); + + /* There was already a non-using declaration in + this scope with the same parameter types. If both + are the same extern "C" functions, that's ok. */ + if (decls_match (new_fn, old_fn)) + break; + else + { + error ("%qD is already declared in this scope", name); + break; + } } } - } - /* If we broke out of the loop, there's no reason to add - this function to the using declarations for this - scope. */ - if (tmp1) - continue; - - /* If we are adding to an existing OVERLOAD, then we no - longer know the type of the set of functions. */ - if (*newval && TREE_CODE (*newval) == OVERLOAD) - TREE_TYPE (*newval) = unknown_type_node; - /* Add this new function to the set. */ - *newval = build_overload (OVL_CURRENT (tmp), *newval); - /* If there is only one function, then we use its type. (A - using-declaration naming a single function can be used in - contexts where overload resolution cannot be - performed.) */ - if (TREE_CODE (*newval) != OVERLOAD) - { - *newval = ovl_cons (*newval, NULL_TREE); - TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp)); + /* If we broke out of the loop, there's no reason to add + this function to the using declarations for this + scope. */ + if (tmp1) + continue; + + /* If we are adding to an existing OVERLOAD, then we no + longer know the type of the set of functions. */ + if (*newval && TREE_CODE (*newval) == OVERLOAD) + TREE_TYPE (*newval) = unknown_type_node; + /* Add this new function to the set. */ + *newval = build_overload (OVL_CURRENT (tmp), *newval); + /* If there is only one function, then we use its type. (A + using-declaration naming a single function can be used in + contexts where overload resolution cannot be + performed.) */ + if (TREE_CODE (*newval) != OVERLOAD) + { + *newval = ovl_cons (*newval, NULL_TREE); + TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp)); + } + OVL_USED (*newval) = 1; } - OVL_USED (*newval) = 1; + } + else + { + *newval = decls.value; + if (oldval && !decls_match (*newval, oldval)) + error ("%qD is already declared in this scope", name); } } else + *newval = oldval; + + if (decls.type && TREE_CODE (decls.type) == TREE_LIST) { - *newval = decls.value; - if (oldval && !decls_match (*newval, oldval)) - error ("%qD is already declared in this scope", name); + error ("reference to %qD is ambiguous", name); + print_candidates (decls.type); } - - *newtype = decls.type; - if (oldtype && *newtype && !same_type_p (oldtype, *newtype)) + else { - error ("using declaration %qD introduced ambiguous type %qT", - name, oldtype); - return; + *newtype = decls.type; + if (oldtype && *newtype && !decls_match (oldtype, *newtype)) + error ("%qD is already declared in this scope", name); } + + /* If *newval is empty, shift any class or enumeration name down. */ + if (!*newval) + { + *newval = *newtype; + *newtype = NULL_TREE; + } + /* LLVM LOCAL end mainline */ } /* Process a using-declaration at function scope. */ @@ -3477,43 +3509,63 @@ merge_functions (tree s1, tree s2) XXX In what way should I treat extern declarations? XXX I don't want to repeat the entire duplicate_decls here */ +/* LLVM LOCAL begin mainline */ static void -ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new, - int flags) +ambiguous_decl (struct scope_binding *old, cxx_binding *new, int flags) { tree val, type; gcc_assert (old != NULL); + + /* Copy the type. */ + type = new->type; + if (LOOKUP_NAMESPACES_ONLY (flags) + || (type && hidden_name_p (type) && !(flags & LOOKUP_HIDDEN))) + type = NULL_TREE; + /* Copy the value. */ val = new->value; if (val) - switch (TREE_CODE (val)) - { - case TEMPLATE_DECL: - /* If we expect types or namespaces, and not templates, - or this is not a template class. */ - if ((LOOKUP_QUALIFIERS_ONLY (flags) - && !DECL_CLASS_TEMPLATE_P (val)) - || hidden_name_p (val)) - val = NULL_TREE; - break; - case TYPE_DECL: - if (LOOKUP_NAMESPACES_ONLY (flags) || hidden_name_p (val)) - val = NULL_TREE; - break; - case NAMESPACE_DECL: - if (LOOKUP_TYPES_ONLY (flags)) - val = NULL_TREE; - break; - case FUNCTION_DECL: - /* Ignore built-in functions that are still anticipated. */ - if (LOOKUP_QUALIFIERS_ONLY (flags) || hidden_name_p (val)) - val = NULL_TREE; - break; - default: - if (LOOKUP_QUALIFIERS_ONLY (flags)) - val = NULL_TREE; - } + { + if (hidden_name_p (val) && !(flags & LOOKUP_HIDDEN)) + val = NULL_TREE; + else + switch (TREE_CODE (val)) + { + case TEMPLATE_DECL: + /* If we expect types or namespaces, and not templates, + or this is not a template class. */ + if ((LOOKUP_QUALIFIERS_ONLY (flags) + && !DECL_CLASS_TEMPLATE_P (val))) + val = NULL_TREE; + break; + case TYPE_DECL: + if (LOOKUP_NAMESPACES_ONLY (flags) + || (type && (flags & LOOKUP_PREFER_TYPES))) + val = NULL_TREE; + break; + case NAMESPACE_DECL: + if (LOOKUP_TYPES_ONLY (flags)) + val = NULL_TREE; + break; + case FUNCTION_DECL: + /* Ignore built-in functions that are still anticipated. */ + if (LOOKUP_QUALIFIERS_ONLY (flags)) + val = NULL_TREE; + break; + default: + if (LOOKUP_QUALIFIERS_ONLY (flags)) + val = NULL_TREE; + } + } + + /* If val is hidden, shift down any class or enumeration name. */ + if (!val) + { + val = type; + type = NULL_TREE; + } +/* LLVM LOCAL end mainline */ if (!old->value) old->value = val; else if (val && val != old->value) @@ -3523,25 +3575,21 @@ ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new, else { old->value = tree_cons (NULL_TREE, old->value, - build_tree_list (NULL_TREE, new->value)); + build_tree_list (NULL_TREE, val)); TREE_TYPE (old->value) = error_mark_node; } } - /* ... and copy the type. */ - type = new->type; - if (LOOKUP_NAMESPACES_ONLY (flags)) - type = NULL_TREE; + + /* LLVM LOCAL begin mainline */ if (!old->type) old->type = type; else if (type && old->type != type) { - if (flags & LOOKUP_COMPLAIN) - { - error ("%qD denotes an ambiguous type",name); - error ("%J first type here", TYPE_MAIN_DECL (old->type)); - error ("%J other type here", TYPE_MAIN_DECL (type)); - } + old->type = tree_cons (NULL_TREE, old->type, + build_tree_list (NULL_TREE, type)); + TREE_TYPE (old->type) = error_mark_node; } + /* LLVM LOCAL end mainline */ } /* Return the declarations that are members of the namespace NS. */ @@ -3630,36 +3678,6 @@ remove_hidden_names (tree fns) return fns; } -/* Select the right _DECL from multiple choices. */ - -static tree -select_decl (const struct scope_binding *binding, int flags) -{ - tree val; - val = binding->value; - - timevar_push (TV_NAME_LOOKUP); - if (LOOKUP_NAMESPACES_ONLY (flags)) - { - /* We are not interested in types. */ - if (val && (TREE_CODE (val) == NAMESPACE_DECL - || TREE_CODE (val) == TREE_LIST)) - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); - } - - /* If looking for a type, or if there is no non-type binding, select - the value binding. */ - if (binding->type && (!val || (flags & LOOKUP_PREFER_TYPES))) - val = binding->type; - /* Don't return non-types if we really prefer types. */ - else if (val && LOOKUP_TYPES_ONLY (flags) - && ! DECL_DECLARES_TYPE_P (val)) - val = NULL_TREE; - - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val); -} - /* Unscoped lookup of a global: iterate over current namespaces, considering using-directives. */ @@ -3671,22 +3689,18 @@ unqualified_namespace_lookup (tree name, int flags) tree siter; struct cp_binding_level *level; tree val = NULL_TREE; - struct scope_binding binding = EMPTY_SCOPE_BINDING; timevar_push (TV_NAME_LOOKUP); for (; !val; scope = CP_DECL_CONTEXT (scope)) { + struct scope_binding binding = EMPTY_SCOPE_BINDING; cxx_binding *b = cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name); if (b) - { - if (b->value - && ((flags & LOOKUP_HIDDEN) || !hidden_name_p (b->value))) - binding.value = b->value; - binding.type = b->type; - } + /* LLVM LOCAL mainline */ + ambiguous_decl (&binding, b, flags); /* Add all _DECLs seen through local using-directives. */ for (level = current_binding_level; @@ -3711,7 +3725,7 @@ unqualified_namespace_lookup (tree name, int flags) siter = CP_DECL_CONTEXT (siter); } - val = select_decl (&binding, flags); + val = binding.value; if (scope == global_namespace) break; } @@ -3741,7 +3755,7 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain) if (is_type_p) flags |= LOOKUP_PREFER_TYPES; if (qualified_lookup_using_namespace (name, scope, &binding, flags)) - t = select_decl (&binding, flags); + t = binding.value; } else if (is_aggr_type (scope, complain)) t = lookup_member (scope, name, 2, is_type_p); @@ -3774,7 +3788,8 @@ lookup_using_namespace (tree name, struct scope_binding *val, cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name); /* Resolve ambiguities. */ if (val1) - ambiguous_decl (name, val, val1, flags); + /* LLVM LOCAL mainline */ + ambiguous_decl (val, val1, flags); } POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val->value != error_mark_node); } @@ -3803,7 +3818,8 @@ qualified_lookup_using_namespace (tree name, tree scope, cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name); seen = tree_cons (scope, NULL_TREE, seen); if (binding) - ambiguous_decl (name, result, binding, flags); + /* LLVM LOCAL mainline */ + ambiguous_decl (result, binding, flags); /* Consider strong using directives always, and non-strong ones if we haven't found a binding yet. ??? Shouldn't we consider diff --git a/contrib/gcc/cp/parser.c b/contrib/gcc/cp/parser.c index edbd37aa8..f66424bae 100644 --- a/contrib/gcc/cp/parser.c +++ b/contrib/gcc/cp/parser.c @@ -10312,13 +10312,19 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (parser->scope) { tree decl; + tree ambiguous_decls; decl = cp_parser_lookup_name (parser, identifier, tag_type, /*is_template=*/false, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_decls=*/NULL); + &ambiguous_decls); + + /* If the lookup was ambiguous, an error will already have been + issued. */ + if (ambiguous_decls) + return error_mark_node; /* If we are parsing friend declaration, DECL may be a TEMPLATE_DECL tree node here. However, we need to check -- 2.45.0