/* Definitions for C++ name lookup routines.
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#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);
static bool lookup_using_namespace (tree, struct scope_binding *, tree,
tree, int);
unit. */
static GTY(()) tree anonymous_namespace_name;
+/* Initialize anonymous_namespace_name if necessary, and return it. */
+
+static tree
+get_anonymous_namespace_name(void)
+{
+ if (!anonymous_namespace_name)
+ {
+ /* The anonymous namespace has to have a unique name
+ if typeinfo objects are being compared by name. */
+ if (! flag_weak || ! SUPPORTS_ONE_ONLY)
+ anonymous_namespace_name = get_file_function_name ("N");
+ else
+ /* The demangler expects anonymous namespaces to be called
+ something starting with '_GLOBAL__N_'. */
+ anonymous_namespace_name = get_identifier ("_GLOBAL__N_1");
+ }
+ return anonymous_namespace_name;
+}
/* Compute the chain index of a binding_entry given the HASH value of its
name and the total COUNT of chains. COUNT is assumed to be a power
static void
add_decl_to_level (tree decl, cxx_scope *b)
{
+ /* We used to record virtual tables as if they were ordinary
+ variables, but no longer do so. */
+ gcc_assert (!(TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl)));
+
if (TREE_CODE (decl) == NAMESPACE_DECL
&& !DECL_NAMESPACE_ALIAS (decl))
{
TREE_CHAIN (decl) = b->namespaces;
b->namespaces = decl;
}
- else if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
- {
- TREE_CHAIN (decl) = b->vtables;
- b->vtables = decl;
- }
else
{
/* We build up the list in reverse order, and reverse it later if
timevar_push (TV_NAME_LOOKUP);
+ if (x == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+
need_new_binding = 1;
if (DECL_TEMPLATE_PARM_P (x))
{
int different_binding_level = 0;
- if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
- check_default_args (x);
-
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
if (decls_match (x, t))
/* The standard only says that the local extern
inherits linkage from the previous decl; in
- particular, default args are not shared. We must
- also tell cgraph to treat these decls as the same,
- or we may neglect to emit an "unused" static - we
- do this by making the DECL_UIDs equal, which should
- be viewed as a kludge. FIXME. */
+ particular, default args are not shared. Add
+ the decl into a hash table to make sure only
+ the previous decl in this case is seen by the
+ middle end. */
{
+ struct cxx_int_tree_map *h;
+ void **loc;
+
TREE_PUBLIC (x) = TREE_PUBLIC (t);
- DECL_UID (x) = DECL_UID (t);
+
+ if (cp_function_chain->extern_decl_map == NULL)
+ cp_function_chain->extern_decl_map
+ = htab_create_ggc (20, cxx_int_tree_map_hash,
+ cxx_int_tree_map_eq, NULL);
+
+ h = GGC_NEW (struct cxx_int_tree_map);
+ h->uid = DECL_UID (x);
+ h->to = t;
+ loc = htab_find_slot_with_hash
+ (cp_function_chain->extern_decl_map, h,
+ h->uid, INSERT);
+ *(struct cxx_int_tree_map **) loc = h;
}
}
else if (TREE_CODE (t) == PARM_DECL)
}
}
+ if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
+ check_default_args (x);
+
check_template_shadow (x);
- /* If this is a function conjured up by the backend, massage it
+ /* If this is a function conjured up by the back end, massage it
so it looks friendly. */
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
{
if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl)))
return decl;
- shadowed = DECL_HAS_SHADOWED_FOR_VAR_P (decl)
+ shadowed = DECL_HAS_SHADOWED_FOR_VAR_P (decl)
? DECL_SHADOWED_FOR_VAR (decl) : NULL_TREE ;
while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
&& DECL_DEAD_FOR_LOCAL (shadowed))
- shadowed = DECL_HAS_SHADOWED_FOR_VAR_P (shadowed)
+ shadowed = DECL_HAS_SHADOWED_FOR_VAR_P (shadowed)
? DECL_SHADOWED_FOR_VAR (shadowed) : NULL_TREE;
if (!shadowed)
shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (decl));
if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
scope = free_binding_level;
+ memset (scope, 0, sizeof (cxx_scope));
free_binding_level = scope->level_chain;
}
else
- scope = GGC_NEW (cxx_scope);
- memset (scope, 0, sizeof (cxx_scope));
+ scope = GGC_CNEW (cxx_scope);
scope->this_entity = entity;
scope->more_cleanups_ok = true;
is_class_level = 0;
}
-#ifdef HANDLE_PRAGMA_VISIBILITY
- if (scope->has_visibility)
- pop_visibility ();
-#endif
-
/* Move one nesting level up. */
current_binding_level = scope->level_chain;
return name;
}
-/* Returns TRUE if NAME is the name for the constructor for TYPE. */
+/* Returns TRUE if NAME is the name for the constructor for TYPE,
+ which must be a class type. */
bool
constructor_name_p (tree name, tree type)
{
tree ctor_name;
+ gcc_assert (IS_AGGR_TYPE (type));
+
if (!name)
return false;
return;
}
+ /* 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;
+ }
+
/* 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. */
&& !DECL_HIDDEN_FRIEND_P (oldval))
oldval = NULL_TREE;
- /* Check for using functions. */
- if (decls.value && is_overloaded_fn (decls.value))
+ 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)
+ {
+ error ("reference to %qD is ambiguous", name);
+ print_candidates (decls.type);
}
else
{
- *newval = decls.value;
- if (oldval && !decls_match (*newval, oldval))
+ *newtype = decls.type;
+ if (oldtype && *newtype && !decls_match (oldtype, *newtype))
error ("%qD is already declared in this scope", name);
}
- *newtype = decls.type;
- if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
- {
- error ("using declaration %qD introduced ambiguous type %qT",
- name, oldtype);
- return;
- }
+ /* If *newval is empty, shift any class or enumeration name down. */
+ if (!*newval)
+ {
+ *newval = *newtype;
+ *newtype = NULL_TREE;
+ }
}
/* Process a using-declaration at function scope. */
if (!class_binding_level)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+ if (name == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
+
/* Check for invalid member names. */
gcc_assert (TYPE_BEING_DEFINED (current_class_type));
/* We could have been passed a tree list if this is an ambiguous
tree base_binfo;
int i;
+ if (name == error_mark_node)
+ return NULL_TREE;
+
if (!scope || !TYPE_P (scope))
{
error ("using-declaration for non-member at class scope");
error ("%<%T::%D%> names destructor", scope, name);
return NULL_TREE;
}
- if (constructor_name_p (name, scope))
+ if (IS_AGGR_TYPE (scope) && constructor_name_p (name, scope))
{
error ("%<%T::%D%> names constructor", scope, name);
return NULL_TREE;
}
scope_dependent_p = dependent_type_p (scope);
- name_dependent_p = (scope_dependent_p
+ name_dependent_p = (scope_dependent_p
|| (IDENTIFIER_TYPENAME_P (name)
&& dependent_type_p (TREE_TYPE (name))));
bases_dependent_p = false;
if (processing_template_decl)
for (binfo = TYPE_BINFO (current_class_type), i = 0;
- BINFO_BASE_ITERATE (binfo, i, base_binfo);
+ BINFO_BASE_ITERATE (binfo, i, base_binfo);
i++)
if (dependent_type_p (TREE_TYPE (base_binfo)))
{
/* From [namespace.udecl]:
A using-declaration used as a member-declaration shall refer to a
- member of a base class of the class being defined.
-
+ member of a base class of the class being defined.
+
In general, we cannot check this constraint in a template because
we do not know the entire set of base classes of the current
class type. However, if all of the base classes are
non-dependent, then we can avoid delaying the check until
instantiation. */
- if (!scope_dependent_p && !bases_dependent_p)
+ if (!scope_dependent_p)
{
base_kind b_kind;
- tree binfo;
binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
if (b_kind < bk_proper_base)
{
- error_not_base_type (scope, current_class_type);
- return NULL_TREE;
+ if (!bases_dependent_p)
+ {
+ error_not_base_type (scope, current_class_type);
+ return NULL_TREE;
+ }
}
-
- if (!name_dependent_p)
+ else if (!name_dependent_p)
{
decl = lookup_member (binfo, name, 0, false);
if (!decl)
{
- error ("no members matching %<%T::%D%> in %q#T", scope, name,
+ error ("no members matching %<%T::%D%> in %q#T", scope, name,
scope);
return NULL_TREE;
}
/* See whether this has been declared in the namespace. */
old = lookup_qualified_name (scope, DECL_NAME (decl), false, true);
- if (!old)
+ if (old == error_mark_node)
/* No old declaration at all. */
goto complain;
if (!is_overloaded_fn (decl))
return result;
}
-/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
- select a name that is unique to this compilation unit. */
+/* Process any ATTRIBUTES on a namespace definition. Currently only
+ attribute visibility is meaningful, which is a property of the syntactic
+ block rather than the namespace as a whole, so we don't touch the
+ NAMESPACE_DECL at all. Returns true if attribute visibility is seen. */
-void
-push_namespace (tree name)
+bool
+handle_namespace_attrs (tree ns, tree attributes)
{
- push_namespace_with_attribs (name, NULL_TREE);
-}
+ tree d;
+ bool saw_vis = false;
+
+ for (d = attributes; d; d = TREE_CHAIN (d))
+ {
+ tree name = TREE_PURPOSE (d);
+ tree args = TREE_VALUE (d);
+
+#ifdef HANDLE_PRAGMA_VISIBILITY
+ if (is_attribute_p ("visibility", name))
+ {
+ tree x = args ? TREE_VALUE (args) : NULL_TREE;
+ if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
+ {
+ warning (OPT_Wattributes,
+ "%qD attribute requires a single NTBS argument",
+ name);
+ continue;
+ }
+
+ if (!TREE_PUBLIC (ns))
+ warning (OPT_Wattributes,
+ "%qD attribute is meaningless since members of the "
+ "anonymous namespace get local symbols", name);
+
+ push_visibility (TREE_STRING_POINTER (x));
+ saw_vis = true;
+ }
+ else
+#endif
+ {
+ warning (OPT_Wattributes, "%qD attribute directive ignored",
+ name);
+ continue;
+ }
+ }
-/* Same, but specify attributes to apply to the namespace. The attributes
- only apply to the current namespace-body, not to any later extensions. */
+ return saw_vis;
+}
+
+/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
+ select a name that is unique to this compilation unit. */
void
-push_namespace_with_attribs (tree name, tree attributes)
+push_namespace (tree name)
{
tree d = NULL_TREE;
int need_new = 1;
if (anon)
{
- /* The name of anonymous namespace is unique for the translation
- unit. */
- if (!anonymous_namespace_name)
- anonymous_namespace_name = get_file_function_name ('N');
- name = anonymous_namespace_name;
+ name = get_anonymous_namespace_name();
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
/* Reopening anonymous namespace. */
/* Make a new namespace, binding the name to it. */
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
- TREE_PUBLIC (d) = 1;
+ /* The name of this namespace is not visible to other translation
+ units if it is an anonymous namespace or member thereof. */
+ if (anon || decl_anon_ns_mem_p (current_namespace))
+ TREE_PUBLIC (d) = 0;
+ else
+ TREE_PUBLIC (d) = 1;
pushdecl (d);
if (anon)
{
/* Enter the name space. */
current_namespace = d;
-#ifdef HANDLE_PRAGMA_VISIBILITY
- /* Clear has_visibility in case a previous namespace-definition had a
- visibility attribute and this one doesn't. */
- current_binding_level->has_visibility = 0;
- for (d = attributes; d; d = TREE_CHAIN (d))
- {
- tree name = TREE_PURPOSE (d);
- tree args = TREE_VALUE (d);
- tree x;
-
- if (! is_attribute_p ("visibility", name))
- {
- warning (OPT_Wattributes, "%qs attribute directive ignored",
- IDENTIFIER_POINTER (name));
- continue;
- }
-
- x = args ? TREE_VALUE (args) : NULL_TREE;
- if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
- {
- warning (OPT_Wattributes, "%qs attribute requires a single NTBS argument",
- IDENTIFIER_POINTER (name));
- continue;
- }
-
- current_binding_level->has_visibility = 1;
- push_visibility (TREE_STRING_POINTER (x));
- goto found;
- }
- if (anon)
- {
- /* Anonymous namespaces default to hidden visibility. This might
- change once we implement export. */
- current_binding_level->has_visibility = 1;
- push_visibility ("hidden");
- }
- found:
-#endif
-
timevar_pop (TV_NAME_LOOKUP);
}
XXX I don't want to repeat the entire duplicate_decls here */
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;
+ }
if (!old->value)
old->value = val;
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;
+
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;
}
}
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. */
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 && hidden_name_p (b->value))
- /* Ignore anticipated built-in functions and friends. */
- ;
- else
- binding.value = b->value;
- binding.type = b->type;
- }
+ ambiguous_decl (&binding, b, flags);
/* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
siter = CP_DECL_CONTEXT (siter);
}
- val = select_decl (&binding, flags);
+ val = binding.value;
if (scope == global_namespace)
break;
}
lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
{
int flags = 0;
+ tree t = NULL_TREE;
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
if (is_type_p)
flags |= LOOKUP_PREFER_TYPES;
if (qualified_lookup_using_namespace (name, scope, &binding, flags))
- return select_decl (&binding, flags);
+ t = binding.value;
}
else if (is_aggr_type (scope, complain))
- {
- tree t;
- t = lookup_member (scope, name, 2, is_type_p);
- if (t)
- return t;
- }
+ t = lookup_member (scope, name, 2, is_type_p);
- return error_mark_node;
+ if (!t)
+ return error_mark_node;
+ return t;
}
/* Subroutine of unqualified_namespace_lookup:
cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
/* Resolve ambiguities. */
if (val1)
- ambiguous_decl (name, val, val1, flags);
+ ambiguous_decl (val, val1, flags);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val->value != error_mark_node);
}
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);
+ 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
continue;
/* If this is the kind of thing we're looking for, we're done. */
- if (qualify_lookup (iter->value, flags)
- && !hidden_name_p (iter->value))
+ if (qualify_lookup (iter->value, flags))
binding = iter->value;
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (iter->type, flags)
- && !hidden_name_p (iter->type))
+ && qualify_lookup (iter->type, flags))
binding = iter->type;
else
binding = NULL_TREE;
if (binding)
{
+ if (hidden_name_p (binding))
+ {
+ /* A non namespace-scope binding can only be hidden if
+ we are in a local class, due to friend declarations.
+ In particular, consider:
+
+ void f() {
+ struct A {
+ friend struct B;
+ void g() { B* b; } // error: B is hidden
+ }
+ struct B {};
+ }
+
+ The standard says that "B" is a local class in "f"
+ (but not nested within "A") -- but that name lookup
+ for "B" does not find this declaration until it is
+ declared directly with "f".
+
+ In particular:
+
+ [class.friend]
+
+ If a friend declaration appears in a local class and
+ the name specified is an unqualified name, a prior
+ declaration is looked up without considering scopes
+ that are outside the innermost enclosing non-class
+ scope. For a friend class declaration, if there is no
+ prior declaration, the class that is specified
+ belongs to the innermost enclosing non-class scope,
+ but if it is subsequently referenced, its name is not
+ found by name lookup until a matching declaration is
+ provided in the innermost enclosing nonclass scope.
+ */
+ gcc_assert (current_class_type &&
+ LOCAL_CLASS_P (current_class_type));
+
+ /* This binding comes from a friend declaration in the local
+ class. The standard (11.4.8) states that the lookup can
+ only succeed if there is a non-hidden declaration in the
+ current scope, which is not the case here. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
val = binding;
break;
}
/* Similar to `lookup_name' but look only in the innermost non-class
binding level. */
-static tree
+tree
lookup_name_innermost_nonclass_level (tree name)
{
struct cp_binding_level *b;
else
return arg_assoc_class (k, ctx);
}
+ /* It's an argument pack; handle it recursively. */
+ else if (ARGUMENT_PACK_P (arg))
+ {
+ tree args = ARGUMENT_PACK_ARGS (arg);
+ int i, len = TREE_VEC_LENGTH (args);
+ for (i = 0; i < len; ++i)
+ if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, i)))
+ return true;
+
+ return false;
+ }
/* It's not a template template argument, but it is a type template
argument. */
else if (TYPE_P (arg))
case LANG_TYPE:
gcc_assert (type == unknown_type_node);
return false;
+ case TYPE_PACK_EXPANSION:
+ return arg_assoc_type (k, PACK_EXPANSION_PATTERN (type));
+
default:
gcc_unreachable ();
}
k.namespaces = NULL_TREE;
arg_assoc_args (&k, args);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
+
+ fns = k.functions;
+
+ if (fns
+ && TREE_CODE (fns) != VAR_DECL
+ && !is_overloaded_fn (fns))
+ {
+ error ("argument dependent lookup finds %q+D", fns);
+ error (" in call to %qD", name);
+ fns = error_mark_node;
+ }
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fns);
}
/* Add namespace to using_directives. Return NULL_TREE if nothing was
b = b->level_chain;
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-
+
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
if (! context)
{
tree cs = current_scope ();
-
+
if (scope == ts_current)
context = cs;
else if (cs != NULL_TREE && TYPE_P (cs))
(type, scope == ts_within_enclosing_non_class, b);
if (decl == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
-
- if (! in_class)
- set_identifier_type_value_with_scope (name, tdef, b);
if (b->kind == sk_class)
{
pushdecl_class_level (decl);
}
else if (b->kind != sk_template_parms)
- decl = pushdecl_with_scope (decl, b, /*is_friend=*/false);
+ {
+ decl = pushdecl_with_scope (decl, b, /*is_friend=*/false);
+ if (decl == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
+ }
+
+ if (! in_class)
+ set_identifier_type_value_with_scope (name, tdef, b);
TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
{
maybe_add_class_template_decl_list (current_class_type,
type, /*friend_p=*/0);
-
+
if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
CLASSTYPE_NESTED_UTDS (current_class_type)
= binding_table_new (SCOPE_DEFAULT_HT_SIZE);
-
+
binding_table_insert
(CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
}
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
TYPE_STUB_DECL (type) = decl;
+ /* Set type visibility now if this is a forward declaration. */
+ TREE_PUBLIC (decl) = 1;
+ determine_visibility (decl);
+
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
}
\f
struct cp_binding_level *b;
cxx_saved_binding *sb;
size_t i;
- int need_pop;
+ bool need_pop;
timevar_push (TV_NAME_LOOKUP);
s = GGC_CNEW (struct saved_scope);
/* If we're in the middle of some function, save our state. */
if (cfun)
{
- need_pop = 1;
+ need_pop = true;
push_function_context_to (NULL_TREE);
}
else
- need_pop = 0;
+ need_pop = false;
if (scope_chain && previous_class_level)
store_class_bindings (previous_class_level->class_shadowed,