/* Definitions for C++ name lookup routines.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
This file is part of GCC.
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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "toplev.h"
#include "diagnostic.h"
#include "debug.h"
+#include "c-pragma.h"
/* The bindings for a particular name in a particular scope. */
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_current_level (tree);
-static tree push_overloaded_decl (tree, int);
+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);
+ tree, int);
static bool qualified_lookup_using_namespace (tree, tree,
struct scope_binding *, int);
static tree lookup_type_current_level (tree);
static tree push_using_directive (tree);
-static void cp_emit_debug_info_for_using (tree, tree);
/* The :: namespace. */
}
/* Put ENTRY back on the free list. */
-
+#if 0
static inline void
binding_entry_free (binding_entry entry)
{
entry->chain = free_binding_entry;
free_binding_entry = entry;
}
+#endif
/* The datatype used to implement the mapping from names to types at
a given scope. */
}
/* Make TABLE's entries ready for reuse. */
-
+#if 0
static void
binding_table_free (binding_table table)
{
{
binding_entry temp = table->chain[i];
while (temp != NULL)
- {
- binding_entry entry = temp;
- temp = entry->chain;
- binding_entry_free (entry);
- }
+ {
+ binding_entry entry = temp;
+ temp = entry->chain;
+ binding_entry_free (entry);
+ }
table->chain[i] = NULL;
}
table->entry_count = 0;
}
+#endif
/* Allocate a table with CHAIN_COUNT, assumed to be a power of two. */
{
binding_entry entry = old_chains[i];
for (; entry != NULL; entry = old_chains[i])
- {
- const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
- const size_t j = ENTRY_INDEX (hash, new_chain_count);
-
- old_chains[i] = entry->chain;
- entry->chain = table->chain[j];
- table->chain[j] = entry;
- }
+ {
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
+ const size_t j = ENTRY_INDEX (hash, new_chain_count);
+
+ old_chains[i] = entry->chain;
+ entry->chain = table->chain[j];
+ table->chain[j] = entry;
+ }
}
table->entry_count = old_entry_count;
}
return entry;
}
-/* Return the binding_entry, if any, that maps NAME to an anonymous type. */
-
-static tree
-binding_table_find_anon_type (binding_table table, tree name)
-{
- const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
- binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
-
- while (entry != NULL && TYPE_IDENTIFIER (entry->type) != name)
- entry = entry->chain;
-
- return entry ? entry->type : NULL;
-}
-
-/* Return the binding_entry, if any, that has TYPE as target. If NAME
- is non-null, then set the domain and rehash that entry. */
-
-static binding_entry
-binding_table_reverse_maybe_remap (binding_table table, tree type, tree name)
-{
- const size_t chain_count = table->chain_count;
- binding_entry entry = NULL;
- binding_entry *p = NULL;
- size_t i;
-
- for (i = 0; i < chain_count && entry == NULL; ++i)
- {
- p = &table->chain[i];
- while (*p != NULL && entry == NULL)
- if ((*p)->type == type)
- entry = *p;
- else
- p = &(*p)->chain;
- }
-
- if (entry != NULL && name != NULL && entry->name != name)
- {
- /* Remove the bucket from the previous chain. */
- *p = (*p)->chain;
-
- /* Remap the name type to type. */
- i = ENTRY_INDEX (IDENTIFIER_HASH_VALUE (name), chain_count);
- entry->chain = table->chain[i];
- entry->name = name;
- table->chain[i] = entry;
- }
-
- return entry;
-}
-
-/* Remove from TABLE all entries that map to anonymous enums or
- class-types. */
-
-void
-binding_table_remove_anonymous_types (binding_table table)
-{
- const size_t chain_count = table->chain_count;
- size_t i;
-
- for (i = 0; i < chain_count; ++i)
- {
- binding_entry *p = &table->chain[i];
-
- while (*p != NULL)
- if (ANON_AGGRNAME_P ((*p)->name))
- {
- binding_entry e = *p;
- *p = (*p)->chain;
- --table->entry_count;
- binding_entry_free (e);
- }
- else
- p = &(*p)->chain;
- }
-}
-
/* Apply PROC -- with DATA -- to all entries in TABLE. */
void
{
binding_entry entry = table->chain[i];
for (; entry != NULL; entry = entry->chain)
- proc (entry, data);
+ proc (entry, data);
}
}
\f
{
cp_class_binding *cb;
cxx_binding *binding;
-
+
if (VEC_length (cp_class_binding, scope->class_shadowed))
{
cp_class_binding *old_base;
old_base = VEC_index (cp_class_binding, scope->class_shadowed, 0);
- if (VEC_reserve (cp_class_binding, scope->class_shadowed, -1))
+ if (VEC_reserve (cp_class_binding, gc, scope->class_shadowed, 1))
{
/* Fixup the current bindings, as they might have moved. */
size_t i;
-
+
for (i = 0;
VEC_iterate (cp_class_binding, scope->class_shadowed, i, cb);
i++)
cb = VEC_quick_push (cp_class_binding, scope->class_shadowed, NULL);
}
else
- cb = VEC_safe_push (cp_class_binding, scope->class_shadowed, NULL);
-
+ cb = VEC_safe_push (cp_class_binding, gc, scope->class_shadowed, NULL);
+
cb->identifier = name;
binding = &cb->base;
binding->scope = scope;
}
else
binding = new_class_binding (id, decl, /*type=*/NULL_TREE, level);
-
+
/* Now, fill in the binding information. */
binding->previous = IDENTIFIER_BINDING (id);
INHERITED_VALUE_BINDING_P (binding) = 0;
binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
- my_friendly_assert (binding != NULL, 0);
+ gcc_assert (binding != NULL);
/* The DECL will be either the ordinary binding or the type
binding for this identifier. Remove that binding. */
if (binding->value == decl)
binding->value = NULL_TREE;
- else if (binding->type == decl)
- binding->type = NULL_TREE;
else
- abort ();
+ {
+ gcc_assert (binding->type == decl);
+ binding->type = NULL_TREE;
+ }
if (!binding->value && !binding->type)
{
}
}
-/* BINDING records an existing declaration for a namein the current scope.
+/* BINDING records an existing declaration for a name in the current scope.
But, DECL is another declaration for that same identifier in the
same scope. This is the `struct stat' hack whereby a non-typedef
class name or enum-name can be bound at the same level as some other
else if (/* BVAL is null when push_class_level_binding moves an
inherited type-binding out of the way to make room for a
new value binding. */
- !bval
+ !bval
/* BVAL is error_mark_node when DECL's name has been used
in a non-class scope prior declaration. In that case,
we should have already issued a diagnostic; for graceful
error recovery purpose, pretend this was the intended
declaration for that name. */
|| bval == error_mark_node
- /* If BVAL is a built-in that has not yet been declared,
+ /* If BVAL is anticipated but has not yet been declared,
pretend it is not there at all. */
|| (TREE_CODE (bval) == FUNCTION_DECL
- && DECL_ANTICIPATED (bval)))
+ && DECL_ANTICIPATED (bval)
+ && !DECL_HIDDEN_FRIEND_P (bval)))
binding->value = decl;
else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval))
{
else if (TREE_CODE (bval) == TYPE_DECL
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_NAME (decl) == DECL_NAME (bval)
+ && binding->scope->kind != sk_class
&& (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
/* If either type involves template parameters, we must
wait until instantiation. */
|| uses_template_parms (TREE_TYPE (decl))
|| uses_template_parms (TREE_TYPE (bval))))
/* We have two typedef-names, both naming the same type to have
- the same name. This is OK because of:
+ the same name. In general, this is OK because of:
- [dcl.typedef]
+ [dcl.typedef]
In a given scope, a typedef specifier can be used to redefine
the name of any type declared in that scope to refer to the
- type to which it already refers. */
+ type to which it already refers.
+
+ However, in class scopes, this rule does not apply due to the
+ stricter language in [class.mem] prohibiting redeclarations of
+ members. */
ok = false;
/* There can be two block-scope declarations of the same variable,
so long as they are `extern' declarations. However, there cannot
&& DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
&& !DECL_CLASS_SCOPE_P (decl))
{
- duplicate_decls (decl, binding->value);
+ duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
ok = false;
}
else if (TREE_CODE (decl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (bval)
&& ORIGINAL_NAMESPACE (bval) == ORIGINAL_NAMESPACE (decl))
/* [namespace.alias]
-
+
In a declarative region, a namespace-alias-definition can be
used to redefine a namespace-alias declared in that declarative
region to refer only to the namespace to which it already
ok = false;
else
{
- error ("declaration of `%#D'", decl);
- cp_error_at ("conflicts with previous declaration `%#D'", bval);
+ error ("declaration of %q#D", decl);
+ error ("conflicts with previous declaration %q+#D", bval);
ok = false;
}
static void
add_decl_to_level (tree decl, cxx_scope *b)
{
- if (TREE_CODE (decl) == NAMESPACE_DECL
+ if (TREE_CODE (decl) == NAMESPACE_DECL
&& !DECL_NAMESPACE_ALIAS (decl))
{
TREE_CHAIN (decl) = b->namespaces;
TREE_CHAIN (decl) = b->vtables;
b->vtables = decl;
}
- else
+ else
{
/* We build up the list in reverse order, and reverse it later if
- necessary. */
+ necessary. */
TREE_CHAIN (decl) = b->names;
b->names = decl;
b->names_size++;
/* If appropriate, add decl to separate list of statics. We
- include extern variables because they might turn out to be
+ include extern variables because they might turn out to be
static later. It's OK for this list to contain a few false
positives. */
if (b->kind == sk_namespace)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|| (TREE_CODE (decl) == FUNCTION_DECL
&& (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
- VARRAY_PUSH_TREE (b->static_decls, decl);
+ VEC_safe_push (tree, gc, b->static_decls, decl);
}
}
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
- name already seen in the same scope).
+ name already seen in the same scope). IS_FRIEND is true if X is
+ declared as a friend.
Returns either X or an old decl for the same name.
If an old decl is returned, it may have been smashed
to agree with what X says. */
tree
-pushdecl (tree x)
+pushdecl_maybe_friend (tree x, bool is_friend)
{
tree t;
tree name;
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))
{
if (current_function_decl && x != current_function_decl
/* A local declaration for a function doesn't constitute
- nesting. */
+ nesting. */
&& TREE_CODE (x) != FUNCTION_DECL
/* A local declaration for an `extern' variable is in the
scope of the current namespace, not the current
{
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 (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
t = namespace_binding (name, DECL_CONTEXT (x));
else
- t = lookup_name_current_level (name);
+ t = lookup_name_innermost_nonclass_level (name);
/* [basic.link] If there is a visible declaration of an entity
with linkage having the same name and type, ignoring entities
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 (DECL_CONTEXT (t) == NULL_TREE)
- /* This is probably caused by too many errors, but calling
- abort will say that if errors have occurred. */
- abort ();
+ gcc_assert (DECL_CONTEXT (t));
/* Check for duplicate params. */
- if (duplicate_decls (x, t))
+ if (duplicate_decls (x, t, is_friend))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if ((DECL_EXTERN_C_FUNCTION_P (x)
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
- pedwarn ("redeclaration of `wchar_t' as `%T'",
- TREE_TYPE (x));
+ pedwarn ("redeclaration of %<wchar_t%> as %qT",
+ TREE_TYPE (x));
/* Throw away the redeclaration. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else
{
- tree olddecl = duplicate_decls (x, t);
-
+ tree olddecl = duplicate_decls (x, t, is_friend);
+
/* If the redeclaration failed, we can stop at this
point. */
if (olddecl == error_mark_node)
{
if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
- else if (TREE_CODE (t) == FUNCTION_DECL)
- check_default_args (t);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
{
/* A redeclaration of main, but not a duplicate of the
previous one.
-
+
[basic.start.main]
-
+
This function shall not be overloaded. */
- cp_error_at ("invalid redeclaration of `%D'", t);
- error ("as `%D'", x);
+ error ("invalid redeclaration of %q+D", t);
+ error ("as %qD", x);
/* We don't try to push this declaration since that
causes a crash. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
{
- t = push_overloaded_decl (x, PUSH_LOCAL);
+ t = push_overloaded_decl (x, PUSH_LOCAL, is_friend);
if (t != x)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
if (!namespace_bindings_p ())
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
{
- t = push_overloaded_decl (x, PUSH_GLOBAL);
+ t = push_overloaded_decl (x, PUSH_GLOBAL, is_friend);
if (t == x)
add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
{
tree type = TREE_TYPE (x);
if (DECL_IS_BUILTIN (x))
- {
+ {
if (TYPE_NAME (type) == 0)
- TYPE_NAME (type) = x;
- }
- else if (type != error_mark_node && TYPE_NAME (type) != x
+ TYPE_NAME (type) = x;
+ }
+ else if (type != error_mark_node && TYPE_NAME (type) != x
/* We don't want to copy the type when all we're
doing is making a TYPE_DECL for the purposes of
inlining. */
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
- {
+ {
DECL_ORIGINAL_TYPE (x) = type;
- type = build_type_copy (type);
+ type = build_variant_type_copy (type);
TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
- TYPE_NAME (type) = x;
- TREE_TYPE (x) = type;
- }
+ TYPE_NAME (type) = x;
+ TREE_TYPE (x) = type;
+ }
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
- set_identifier_type_value (DECL_NAME (x), x);
+ set_identifier_type_value (DECL_NAME (x), x);
}
/* Multiple external decls of the same identifier ought to match.
&& TREE_CODE (decl) == TREE_CODE (x)
&& !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
- pedwarn ("type mismatch with previous external decl of `%#D'", x);
- cp_pedwarn_at ("previous external decl of `%#D'", decl);
+ pedwarn ("type mismatch with previous external decl of %q#D", x);
+ pedwarn ("previous external decl of %q+#D", decl);
}
}
+ if (TREE_CODE (x) == FUNCTION_DECL
+ && is_friend
+ && !flag_friend_injection)
+ {
+ /* This is a new declaration of a friend function, so hide
+ it from ordinary function lookup. */
+ DECL_ANTICIPATED (x) = 1;
+ DECL_HIDDEN_FRIEND_P (x) = 1;
+ }
+
/* This name is new in its binding level.
Install the new declaration and return it. */
if (namespace_bindings_p ())
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- /* Bind the name for the entity. */
- if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
- && t != NULL_TREE)
- && (TREE_CODE (x) == TYPE_DECL
- || TREE_CODE (x) == VAR_DECL
- || TREE_CODE (x) == ALIAS_DECL
- || TREE_CODE (x) == NAMESPACE_DECL
- || TREE_CODE (x) == CONST_DECL
- || TREE_CODE (x) == TEMPLATE_DECL))
- SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
+ /* Bind the name for the entity. */
+ if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && t != NULL_TREE)
+ && (TREE_CODE (x) == TYPE_DECL
+ || TREE_CODE (x) == VAR_DECL
+ || TREE_CODE (x) == NAMESPACE_DECL
+ || TREE_CODE (x) == CONST_DECL
+ || TREE_CODE (x) == TEMPLATE_DECL))
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
/* OK */;
else
{
- warning ("extern declaration of `%#D' doesn't match", x);
- cp_warning_at ("global declaration `%#D'", oldglobal);
+ warning (0, "extern declaration of %q#D doesn't match", x);
+ warning (0, "global declaration %q+#D", oldglobal);
}
}
/* If we have a local external declaration,
them there. */
struct cp_binding_level *b = current_binding_level->level_chain;
- /* Skip the ctor/dtor cleanup level. */
- b = b->level_chain;
+ if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+ /* Skip the ctor/dtor cleanup level. */
+ b = b->level_chain;
/* ARM $8.3 */
if (b->kind == sk_function_parms)
{
- error ("declaration of '%#D' shadows a parameter", x);
+ error ("declaration of %q#D shadows a parameter", x);
err = true;
}
}
if (warn_shadow && !err)
{
- warning ("declaration of '%#D' shadows a parameter", x);
- warning ("%Jshadowed declaration is here", oldlocal);
+ warning (OPT_Wshadow, "declaration of %q#D shadows a parameter", x);
+ warning (OPT_Wshadow, "%Jshadowed declaration is here", oldlocal);
}
}
/*want_type=*/false);
else
member = NULL_TREE;
-
+
if (member && !TREE_STATIC (member))
{
/* Location of previous decl is not useful in this case. */
- warning ("declaration of '%D' shadows a member of 'this'",
+ warning (OPT_Wshadow, "declaration of %qD shadows a member of 'this'",
x);
}
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
{
- warning ("declaration of '%D' shadows a previous local", x);
- warning ("%Jshadowed declaration is here", oldlocal);
+ warning (OPT_Wshadow, "declaration of %qD shadows a previous local", x);
+ warning (OPT_Wshadow, "%Jshadowed declaration is here", oldlocal);
}
else if (oldglobal != NULL_TREE
&& TREE_CODE (oldglobal) == VAR_DECL)
/* XXX shadow warnings in outer-more namespaces */
{
- warning ("declaration of '%D' shadows a global declaration",
+ warning (OPT_Wshadow, "declaration of %qD shadows a global declaration",
x);
- warning ("%Jshadowed declaration is here", oldglobal);
+ warning (OPT_Wshadow, "%Jshadowed declaration is here", oldglobal);
}
}
}
- if (TREE_CODE (x) == FUNCTION_DECL)
- check_default_args (x);
-
if (TREE_CODE (x) == VAR_DECL)
maybe_register_incomplete_var (x);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
+/* Record a decl-node X as belonging to the current lexical scope. */
+
+tree
+pushdecl (tree x)
+{
+ return pushdecl_maybe_friend (x, false);
+}
+
/* Enter DECL into the symbol table, if that's appropriate. Returns
DECL, or a modified version thereof. */
push_local_binding with a friend decl of a local class. */
b = innermost_nonclass_level ();
- if (lookup_name_current_level (id))
+ if (lookup_name_innermost_nonclass_level (id))
{
/* Supplement the existing binding. */
if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl)))
return decl;
- shadowed = DECL_SHADOWED_FOR_VAR (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_SHADOWED_FOR_VAR (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 (shadowed)
{
if (!DECL_ERROR_REPORTED (decl))
{
- warning ("name lookup of `%D' changed",
- DECL_NAME (decl));
- cp_warning_at (" matches this `%D' under ISO standard rules",
- shadowed);
- cp_warning_at (" matches this `%D' under old rules", decl);
+ warning (0, "name lookup of %qD changed", DECL_NAME (decl));
+ warning (0, " matches this %q+D under ISO standard rules",
+ shadowed);
+ warning (0, " matches this %q+D under old rules", decl);
DECL_ERROR_REPORTED (decl) = 1;
}
return shadowed;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
{
- error ("name lookup of `%D' changed for new ISO `for' scoping",
+ error ("name lookup of %qD changed for new ISO %<for%> scoping",
DECL_NAME (decl));
- cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", decl);
+ error (" cannot use obsolete binding at %q+D because "
+ "it has a destructor", decl);
return error_mark_node;
}
else
{
- pedwarn ("name lookup of `%D' changed for new ISO `for' scoping",
+ pedwarn ("name lookup of %qD changed for new ISO %<for%> scoping",
DECL_NAME (decl));
- cp_pedwarn_at (" using obsolete binding at `%D'", decl);
+ pedwarn (" using obsolete binding at %q+D", decl);
}
return decl;
const char *desc = cxx_scope_descriptor (scope);
if (scope->this_entity)
verbatim ("%s %s(%E) %p %d\n", action, desc,
- scope->this_entity, (void *) scope, line);
+ scope->this_entity, (void *) scope, line);
else
verbatim ("%s %s %p %d\n", action, desc, (void *) scope, line);
}
begin_scope (scope_kind kind, tree entity)
{
cxx_scope *scope;
-
+
/* Reuse or create a struct for this binding level. */
if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
case sk_cleanup:
scope->keep = true;
break;
-
+
case sk_template_spec:
scope->explicit_spec_p = true;
kind = sk_template_parms;
case sk_for:
case sk_class:
case sk_function_parms:
+ case sk_omp:
scope->keep = keep_next_level_flag;
break;
case sk_namespace:
- scope->type_decls = binding_table_new (namespace_scope_ht_size (entity));
NAMESPACE_LEVEL (entity) = scope;
- VARRAY_TREE_INIT (scope->static_decls,
- DECL_NAME (entity) == std_identifier
- || DECL_NAME (entity) == global_scope_name
- ? 200 : 10,
- "Static declarations");
+ scope->static_decls =
+ VEC_alloc (tree, gc,
+ DECL_NAME (entity) == std_identifier
+ || DECL_NAME (entity) == global_scope_name
+ ? 200 : 10);
break;
default:
/* Should not happen. */
- my_friendly_assert (false, 20030922);
+ gcc_unreachable ();
break;
}
scope->kind = kind;
/* We cannot leave a scope, if there are none left. */
if (NAMESPACE_LEVEL (global_namespace))
- my_friendly_assert (!global_scope_p (scope), 20030527);
-
+ gcc_assert (!global_scope_p (scope));
+
if (ENABLE_SCOPE_CHECKING)
{
indent (--binding_depth);
cxx_scope_debug (scope, input_line, "leave");
if (is_class_level != (scope == class_binding_level))
- {
- indent (binding_depth);
- verbatim ("XXX is_class_level != (current_scope == class_scope)\n");
- }
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_scope == class_scope)\n");
+ }
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;
/* Namespace-scopes are left most probably temporarily, not
- completely; they can be reopen later, e.g. in namespace-extension
+ completely; they can be reopened later, e.g. in namespace-extension
or any name binding activity that requires us to resume a
namespace. For classes, we cache some binding levels. For other
scopes, we just make the structure available for reuse. */
&& scope->kind != sk_class)
{
scope->level_chain = free_binding_level;
- if (scope->kind == sk_class)
- scope->type_decls = NULL;
- else
- binding_table_free (scope->type_decls);
- my_friendly_assert (!ENABLE_SCOPE_CHECKING
- || scope->binding_depth == binding_depth,
- 20030529);
+ gcc_assert (!ENABLE_SCOPE_CHECKING
+ || scope->binding_depth == binding_depth);
free_binding_level = scope;
}
/* Find the innermost enclosing class scope, and reset
CLASS_BINDING_LEVEL appropriately. */
- for (scope = current_binding_level;
- scope && scope->kind != sk_class;
- scope = scope->level_chain)
- ;
- class_binding_level = scope && scope->kind == sk_class ? scope : NULL;
+ if (scope->kind == sk_class)
+ {
+ class_binding_level = NULL;
+ for (scope = current_binding_level; scope; scope = scope->level_chain)
+ if (scope->kind == sk_class)
+ {
+ class_binding_level = scope;
+ break;
+ }
+ }
return current_binding_level;
}
{
/* Resuming binding levels is meant only for namespaces,
and those cannot nest into classes. */
- my_friendly_assert(!class_binding_level, 386);
+ gcc_assert (!class_binding_level);
/* Also, resuming a non-directly nested namespace is a no-no. */
- my_friendly_assert(b->level_chain == current_binding_level, 386);
+ gcc_assert (b->level_chain == current_binding_level);
current_binding_level = b;
if (ENABLE_SCOPE_CHECKING)
{
{
return (current_binding_level->blocks != NULL_TREE
|| current_binding_level->keep
- || current_binding_level->kind == sk_cleanup
- || current_binding_level->names != NULL_TREE
- || current_binding_level->type_decls != NULL);
+ || current_binding_level->kind == sk_cleanup
+ || current_binding_level->names != NULL_TREE);
}
/* Returns the kind of the innermost scope. */
return current_binding_level->names;
}
-/* Set the current binding TABLE for type declarations.. This is a
- temporary workaround of the fact that the data structure classtypes
- does not currently carry its allocated cxx_scope structure. */
-void
-cxx_remember_type_decls (binding_table table)
-{
- current_binding_level->type_decls = table;
-}
-
/* For debugging. */
static int no_print_functions = 0;
static int no_print_builtins = 0;
-/* Called from print_binding_level through binding_table_foreach to
- print the content of binding ENTRY. DATA is a pointer to line offset
- marker. */
static void
-bt_print_entry (binding_entry entry, void *data)
-{
- int *p = (int *) data;
- int len;
-
- if (entry->name == NULL)
- len = 3;
- else if (entry->name == TYPE_IDENTIFIER (entry->type))
- len = 2;
- else
- len = 4;
- len = 4;
-
- *p += len;
-
- if (*p > 5)
- {
- fprintf (stderr, "\n\t");
- *p = len;
- }
- if (entry->name == NULL)
- {
- print_node_brief (stderr, "<unnamed-typedef", entry->type, 0);
- fprintf (stderr, ">");
- }
- else if (entry->name == TYPE_IDENTIFIER (entry->type))
- print_node_brief (stderr, "", entry->type, 0);
- else
- {
- print_node_brief (stderr, "<typedef", entry->name, 0);
- print_node_brief (stderr, "", entry->type, 0);
- fprintf (stderr, ">");
- }
-}
-
-void
print_binding_level (struct cp_binding_level* lvl)
{
tree t;
int i = 0, len;
- fprintf (stderr, " blocks=" HOST_PTR_PRINTF, (void *) lvl->blocks);
+ fprintf (stderr, " blocks=%p", (void *) lvl->blocks);
if (lvl->more_cleanups_ok)
fprintf (stderr, " more-cleanups-ok");
if (lvl->have_cleanups)
break;
}
if (i)
- fprintf (stderr, "\n");
- }
- if (lvl->type_decls)
- {
- fprintf (stderr, " tags:\t");
- i = 0;
- binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
- if (i)
fprintf (stderr, "\n");
}
if (VEC_length (cp_class_binding, lvl->class_shadowed))
size_t i;
cp_class_binding *b;
fprintf (stderr, " class-shadowed:");
- for (i = 0;
+ for (i = 0;
VEC_iterate(cp_class_binding, lvl->class_shadowed, i, b);
- ++i)
+ ++i)
fprintf (stderr, " %s ", IDENTIFIER_POINTER (b->identifier));
fprintf (stderr, "\n");
}
{
fprintf (stderr, " type-shadowed:");
for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t))
- {
+ {
fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
+ }
fprintf (stderr, "\n");
}
}
struct cp_binding_level *level;
for (level = stack; !global_scope_p (level); level = level->level_chain)
{
- fprintf (stderr, "binding level " HOST_PTR_PRINTF "\n", (void *) level);
+ fprintf (stderr, "binding level %p\n", (void *) level);
print_binding_level (level);
}
}
print_binding_stack (void)
{
struct cp_binding_level *b;
- fprintf (stderr, "current_binding_level=" HOST_PTR_PRINTF
- "\nclass_binding_level=" HOST_PTR_PRINTF
- "\nNAMESPACE_LEVEL (global_namespace)=" HOST_PTR_PRINTF "\n",
+ fprintf (stderr, "current_binding_level=%p\n"
+ "class_binding_level=%p\n"
+ "NAMESPACE_LEVEL (global_namespace)=%p\n",
(void *) current_binding_level, (void *) class_binding_level,
- (void *) NAMESPACE_LEVEL (global_namespace));
+ (void *) NAMESPACE_LEVEL (global_namespace));
if (class_binding_level)
{
for (b = class_binding_level; b; b = b->level_chain)
{
cxx_binding *binding =
binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
- if (decl)
- {
- if (binding->value)
- supplement_binding (binding, decl);
- else
- binding->value = decl;
- }
+ gcc_assert (decl);
+ if (binding->value)
+ supplement_binding (binding, decl);
else
- abort ();
+ binding->value = decl;
+
/* Store marker instead of real type. */
type = global_type_node;
}
specified class TYPE. When given a template, this routine doesn't
lose the specialization. */
-tree
+static inline tree
constructor_name_full (tree type)
{
return TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
if (!name)
return false;
-
+
if (TREE_CODE (name) != IDENTIFIER_NODE)
return false;
-
+
ctor_name = constructor_name_full (type);
if (name == ctor_name)
return true;
return get_identifier (buf);
}
-/* Clear the TREE_PURPOSE slot of UTDs which have anonymous typenames.
- This keeps dbxout from getting confused. */
-
-void
-clear_anon_tags (void)
-{
- struct cp_binding_level *b;
- static int last_cnt = 0;
-
- /* Fast out if no new anon names were declared. */
- if (last_cnt == anon_cnt)
- return;
-
- b = current_binding_level;
- while (b->kind == sk_cleanup)
- b = b->level_chain;
- if (b->type_decls != NULL)
- binding_table_remove_anonymous_types (b->type_decls);
- last_cnt = anon_cnt;
-}
-\f
-/* Return (from the stack of) the BINDING, if any, established at SCOPE. */
+/* Return (from the stack of) the BINDING, if any, established at SCOPE. */
static inline cxx_binding *
find_binding (cxx_scope *scope, cxx_binding *binding)
{
/* Fold-in case where NAME is used only once. */
if (scope == b->scope && b->previous == NULL)
- return b;
+ return b;
return find_binding (scope, b);
}
return NULL;
return NULL_TREE if this not in namespace scope (in namespace
scope, a using decl might extend any previous bindings). */
-tree
+static tree
push_using_decl (tree scope, tree name)
{
tree decl;
timevar_push (TV_NAME_LOOKUP);
- my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
+ gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL);
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
- if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
+ if (USING_DECL_SCOPE (decl) == scope && DECL_NAME (decl) == name)
break;
if (decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
- namespace_bindings_p () ? decl : NULL_TREE);
- decl = build_lang_decl (USING_DECL, name, void_type_node);
- DECL_INITIAL (decl) = scope;
+ namespace_bindings_p () ? decl : NULL_TREE);
+ decl = build_lang_decl (USING_DECL, name, NULL_TREE);
+ USING_DECL_SCOPE (decl) = scope;
TREE_CHAIN (decl) = current_binding_level->usings;
current_binding_level->usings = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
caller to set DECL_CONTEXT properly. */
tree
-pushdecl_with_scope (tree x, cxx_scope *level)
+pushdecl_with_scope (tree x, cxx_scope *level, bool is_friend)
{
struct cp_binding_level *b;
tree function_decl = current_function_decl;
{
b = current_binding_level;
current_binding_level = level;
- x = pushdecl (x);
+ x = pushdecl_maybe_friend (x, is_friend);
current_binding_level = b;
}
current_function_decl = function_decl;
FLAGS is a bitwise-or of the following values:
PUSH_LOCAL: Bind DECL in the current scope, rather than at
- namespace scope.
+ namespace scope.
PUSH_USING: DECL is being pushed as the result of a using
- declaration.
+ declaration.
+
+ IS_FRIEND is true if this is a friend declaration.
The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */
static tree
-push_overloaded_decl (tree decl, int flags)
+push_overloaded_decl (tree decl, int flags, bool is_friend)
{
tree name = DECL_NAME (decl);
tree old;
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
else
- old = lookup_name_current_level (name);
+ old = lookup_name_innermost_nonclass_level (name);
if (old)
{
if (IS_AGGR_TYPE (t) && warn_shadow
&& (! DECL_IN_SYSTEM_HEADER (decl)
|| ! DECL_IN_SYSTEM_HEADER (old)))
- warning ("`%#D' hides constructor for `%#T'", decl, t);
+ warning (0, "%q#D hides constructor for %q#T", decl, t);
old = NULL_TREE;
}
else if (is_overloaded_fn (old))
- {
- tree tmp;
+ {
+ tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
{
tree fn = OVL_CURRENT (tmp);
+ tree dup;
if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
&& !(flags & PUSH_USING)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
- TYPE_ARG_TYPES (TREE_TYPE (decl))))
- error ("`%#D' conflicts with previous using declaration `%#D'",
- decl, fn);
-
- if (duplicate_decls (decl, fn) == fn)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
+ TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ && ! decls_match (fn, decl))
+ error ("%q#D conflicts with previous using declaration %q#D",
+ decl, fn);
+
+ dup = duplicate_decls (decl, fn, is_friend);
+ /* If DECL was a redeclaration of FN -- even an invalid
+ one -- pass that information along to our caller. */
+ if (dup == fn || dup == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, dup);
}
+
+ /* 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;
}
else if (old == error_mark_node)
/* Ignore the undefined symbol marker. */
old = NULL_TREE;
else
{
- cp_error_at ("previous non-function declaration `%#D'", old);
- error ("conflicts with function declaration `%#D'", decl);
+ error ("previous non-function declaration %q+#D", old);
+ error ("conflicts with function declaration %q#D", decl);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
}
}
/* We should always find a previous binding in this case. */
- abort ();
+ gcc_unreachable ();
}
/* Install the new binding. */
member-declaration. */
if (TYPE_P (scope))
{
- error ("`%T' is not a namespace", scope);
+ error ("%qT is not a namespace", scope);
return NULL_TREE;
}
else if (scope == error_mark_node)
{
/* 7.3.3/5
A using-declaration shall not name a template-id. */
- error ("a using-declaration cannot specify a template-id. Try `using %D'", name);
+ error ("a using-declaration cannot specify a template-id. "
+ "Try %<using %D%>", name);
return NULL_TREE;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
{
- error ("namespace `%D' not allowed in using-declaration", decl);
+ error ("namespace %qD not allowed in using-declaration", decl);
return NULL_TREE;
}
{
/* It's a nested name with template parameter dependent scope.
This can only be using-declaration for class member. */
- error ("`%T' is not a namespace", TREE_OPERAND (decl, 0));
+ error ("%qT is not a namespace", TREE_OPERAND (decl, 0));
return NULL_TREE;
}
if (is_overloaded_fn (decl))
decl = get_first_fn (decl);
- my_friendly_assert (DECL_P (decl), 20020908);
+ gcc_assert (DECL_P (decl));
/* Make a USING_DECL. */
return push_using_decl (scope, name);
static void
do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
- tree *newval, tree *newtype)
+ tree *newval, tree *newtype)
{
struct scope_binding decls = EMPTY_SCOPE_BINDING;
if (!decls.value && !decls.type)
{
- error ("`%D' not declared", name);
+ error ("%qD not declared", name);
return;
}
+ /* 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. */
+ if (oldval
+ && TREE_CODE (oldval) == FUNCTION_DECL
+ && DECL_ANTICIPATED (oldval)
+ && !DECL_HIDDEN_FRIEND_P (oldval))
+ oldval = NULL_TREE;
+
/* Check for using functions. */
if (decls.value && is_overloaded_fn (decls.value))
{
if (oldval && !is_overloaded_fn (oldval))
{
if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
- error ("`%D' is already declared in this scope", name);
+ error ("%qD is already declared in this scope", name);
oldval = NULL_TREE;
}
{
tree old_fn = OVL_CURRENT (tmp1);
- if (new_fn == old_fn)
- /* The function already exists in the current namespace. */
- break;
+ 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 */
+ continue; /* this is a using decl */
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
- TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+ TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
- /* There was already a non-using declaration in
+ 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))
+ are the same extern "C" functions, that's ok. */
+ if (decls_match (new_fn, old_fn))
+ break;
+ else
{
- /* If the OLD_FN was a builtin, there is now a
- real declaration. */
- if (DECL_ANTICIPATED (old_fn))
- DECL_ANTICIPATED (old_fn) = 0;
+ error ("%qD is already declared in this scope", name);
break;
}
- else if (!DECL_ANTICIPATED (old_fn))
- {
- /* If the OLD_FN was really declared, the
- declarations don't match. */
- error ("`%D' is already declared in this scope", name);
- break;
- }
-
- /* If the OLD_FN was not really there, just ignore
- it and keep going. */
}
}
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)
OVL_USED (*newval) = 1;
}
}
- else
+ else
{
*newval = decls.value;
if (oldval && !decls_match (*newval, oldval))
- error ("`%D' is already declared in this scope", name);
+ error ("%qD is already declared in this scope", name);
}
*newtype = decls.type;
if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
{
- error ("using declaration `%D' introduced ambiguous type `%T'",
- name, oldtype);
+ error ("using declaration %qD introduced ambiguous type %qT",
+ name, oldtype);
return;
}
}
&& at_function_scope_p ())
add_decl_expr (decl);
- oldval = lookup_name_current_level (name);
+ oldval = lookup_name_innermost_nonclass_level (name);
oldtype = lookup_type_current_level (name);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
term = OVL_FUNCTION (oldval);
else
term = oldval;
- for (fn = newval; fn && OVL_CURRENT (fn) != term;
+ for (fn = newval; fn && OVL_CURRENT (fn) != term;
fn = OVL_NEXT (fn))
- push_overloaded_decl (OVL_CURRENT (fn),
- PUSH_LOCAL | PUSH_USING);
+ push_overloaded_decl (OVL_CURRENT (fn),
+ PUSH_LOCAL | PUSH_USING,
+ false);
}
else
push_local_binding (name, newval, PUSH_USING);
cp_emit_debug_info_for_using (orig_decl, current_scope());
}
-/* Return the type that should be used when TYPE's name is preceded
- by a tag such as 'struct' or 'union', or null if the name cannot
- be used in this way.
-
- For example, when processing the third line of:
-
- struct A;
- typedef struct A A;
- struct A;
-
- lookup of A will find the typedef. Given A's typedef, this function
- will return the type associated with "struct A". For the tag to be
- anything other than TYPE, TYPE must be a typedef whose original type
- has the same name and context as TYPE itself.
-
- It is not valid for a typedef of an anonymous type to be used with
- an explicit tag:
-
- typedef struct { ... } B;
- struct B;
-
- Return null for this case. */
-
-static tree
-follow_tag_typedef (tree type)
-{
- tree original;
-
- original = original_type (type);
- if (! TYPE_NAME (original))
- return NULL_TREE;
- if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type)
- && (CP_DECL_CONTEXT (TYPE_NAME (original))
- == CP_DECL_CONTEXT (TYPE_NAME (type)))
- && !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original)))
- return original;
- else
- return NULL_TREE;
-}
-
-/* Given NAME, an IDENTIFIER_NODE,
- return the structure (or union or enum) definition for that name.
- Searches binding levels from its SCOPE up to the global level.
- If THISLEVEL_ONLY is nonzero, searches only the specified context
- (but skips any sk_cleanup contexts to find one that is
- meaningful for tags).
- FORM says which kind of type the caller wants;
- it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
- If the wrong kind of type is found, and it's not a template, an error is
- reported. */
-
-tree
-lookup_tag (enum tree_code form, tree name,
- cxx_scope *binding_level, int thislevel_only)
-{
- struct cp_binding_level *level;
- /* Nonzero if, we should look past a template parameter level, even
- if THISLEVEL_ONLY. */
- int allow_template_parms_p = 1;
- bool type_is_anonymous = ANON_AGGRNAME_P (name);
-
- timevar_push (TV_NAME_LOOKUP);
- for (level = binding_level; level; level = level->level_chain)
- {
- tree tail;
- if (type_is_anonymous && level->type_decls != NULL)
- {
- tree type = binding_table_find_anon_type (level->type_decls, name);
- /* There is no need for error checking here, because
- anon names are unique throughout the compilation. */
- if (type != NULL)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
- }
- else if (level->kind == sk_namespace)
- /* Do namespace lookup. */
- for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
- {
- cxx_binding *binding =
- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);
-
- if (binding && (binding->type
- || (binding->value
- && DECL_DECLARES_TYPE_P (binding->value))))
- {
- tree old;
-
- /* If we just skipped past a template parameter level,
- even though THISLEVEL_ONLY, and we find a template
- class declaration, then we use the _TYPE node for the
- template. See the example below. */
- if (thislevel_only && !allow_template_parms_p
- && binding->value
- && DECL_CLASS_TEMPLATE_P (binding->value))
- old = binding->value;
- else
- old = binding->type ? binding->type : binding->value;
-
- /* We've found something at this binding level. If it is
- a typedef, extract the tag it refers to. Lookup fails
- if the typedef doesn't refer to a taggable type. */
- old = TREE_TYPE (old);
- old = follow_tag_typedef (old);
- if (!old)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
- if (TREE_CODE (old) != form
- && (form == ENUMERAL_TYPE
- || TREE_CODE (old) == ENUMERAL_TYPE))
- {
- error ("`%#D' redeclared as %C", old, form);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
- }
- if (thislevel_only || tail == global_namespace)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
- }
- else if (level->type_decls != NULL)
- {
- binding_entry entry = binding_table_find (level->type_decls, name);
- if (entry != NULL)
- {
- enum tree_code code = TREE_CODE (entry->type);
-
- if (code != form
- && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
- {
- /* Definition isn't the kind we were looking for. */
- error ("`%#D' redeclared as %C", entry->type, form);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
- }
- }
- if (thislevel_only && level->kind != sk_cleanup)
- {
- if (level->kind == sk_template_parms && allow_template_parms_p)
- {
- /* We must deal with cases like this:
-
- template <class T> struct S;
- template <class T> struct S {};
-
- When looking up `S', for the second declaration, we
- would like to find the first declaration. But, we
- are in the pseudo-global level created for the
- template parameters, rather than the (surrounding)
- namespace level. Thus, we keep going one more level,
- even though THISLEVEL_ONLY is nonzero. */
- allow_template_parms_p = 0;
- continue;
- }
- else
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
- }
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-}
-
-/* Given a type, find the tag that was defined for it and return the tag name.
- Otherwise return 0. However, the value can never be 0
- in the cases in which this is used.
-
- C++: If NAME is nonzero, this is the new name to install. This is
- done when replacing anonymous tags with real tag names. */
-
-tree
-lookup_tag_reverse (tree type, tree name)
-{
- struct cp_binding_level *level;
-
- timevar_push (TV_NAME_LOOKUP);
- for (level = current_binding_level; level; level = level->level_chain)
- {
- binding_entry entry = level->type_decls == NULL
- ? NULL
- : binding_table_reverse_maybe_remap (level->type_decls, type, name);
- if (entry)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->name);
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-}
-
/* Returns true if ROOT (a namespace, class, or function) encloses
CHILD. CHILD may be either a class type or a namespace. */
bool
is_ancestor (tree root, tree child)
{
- my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
- || TREE_CODE (root) == FUNCTION_DECL
- || CLASS_TYPE_P (root)), 20030307);
- my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
- || CLASS_TYPE_P (child)),
- 20030307);
-
+ gcc_assert ((TREE_CODE (root) == NAMESPACE_DECL
+ || TREE_CODE (root) == FUNCTION_DECL
+ || CLASS_TYPE_P (root)));
+ gcc_assert ((TREE_CODE (child) == NAMESPACE_DECL
+ || CLASS_TYPE_P (child)));
+
/* The global namespace encloses everything. */
if (root == global_namespace)
return true;
}
}
-/* Enter the class or namespace scope indicated by T. Returns TRUE iff
- pop_scope should be called later to exit this scope. */
+/* Enter the class or namespace scope indicated by T suitable for name
+ lookup. T can be arbitrary scope, not necessary nested inside the
+ current scope. Returns a non-null scope to pop iff pop_scope
+ should be called later to exit this scope. */
-bool
+tree
push_scope (tree t)
{
- bool pop = true;
-
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
else if (CLASS_TYPE_P (t))
need to re-enter the scope. Since we are not actually
pushing a new scope, our caller should not call
pop_scope. */
- pop = false;
+ t = NULL_TREE;
}
- return pop;
+ return t;
}
/* Leave scope pushed by push_scope. */
else if CLASS_TYPE_P (t)
pop_nested_class ();
}
+
+/* Subroutine of push_inner_scope. */
+
+static void
+push_inner_scope_r (tree outer, tree inner)
+{
+ tree prev;
+
+ if (outer == inner
+ || (TREE_CODE (inner) != NAMESPACE_DECL && !CLASS_TYPE_P (inner)))
+ return;
+
+ prev = CP_DECL_CONTEXT (TREE_CODE (inner) == NAMESPACE_DECL ? inner : TYPE_NAME (inner));
+ if (outer != prev)
+ push_inner_scope_r (outer, prev);
+ if (TREE_CODE (inner) == NAMESPACE_DECL)
+ {
+ struct cp_binding_level *save_template_parm = 0;
+ /* Temporary take out template parameter scopes. They are saved
+ in reversed order in save_template_parm. */
+ while (current_binding_level->kind == sk_template_parms)
+ {
+ struct cp_binding_level *b = current_binding_level;
+ current_binding_level = b->level_chain;
+ b->level_chain = save_template_parm;
+ save_template_parm = b;
+ }
+
+ resume_scope (NAMESPACE_LEVEL (inner));
+ current_namespace = inner;
+
+ /* Restore template parameter scopes. */
+ while (save_template_parm)
+ {
+ struct cp_binding_level *b = save_template_parm;
+ save_template_parm = b->level_chain;
+ b->level_chain = current_binding_level;
+ current_binding_level = b;
+ }
+ }
+ else
+ pushclass (inner);
+}
+
+/* Enter the scope INNER from current scope. INNER must be a scope
+ nested inside current scope. This works with both name lookup and
+ pushing name into scope. In case a template parameter scope is present,
+ namespace is pushed under the template parameter scope according to
+ name lookup rule in 14.6.1/6.
+
+ Return the former current scope suitable for pop_inner_scope. */
+
+tree
+push_inner_scope (tree inner)
+{
+ tree outer = current_scope ();
+ if (!outer)
+ outer = current_namespace;
+
+ push_inner_scope_r (outer, inner);
+ return outer;
+}
+
+/* Exit the current scope INNER back to scope OUTER. */
+
+void
+pop_inner_scope (tree outer, tree inner)
+{
+ if (outer == inner
+ || (TREE_CODE (inner) != NAMESPACE_DECL && !CLASS_TYPE_P (inner)))
+ return;
+
+ while (outer != inner)
+ {
+ if (TREE_CODE (inner) == NAMESPACE_DECL)
+ {
+ struct cp_binding_level *save_template_parm = 0;
+ /* Temporary take out template parameter scopes. They are saved
+ in reversed order in save_template_parm. */
+ while (current_binding_level->kind == sk_template_parms)
+ {
+ struct cp_binding_level *b = current_binding_level;
+ current_binding_level = b->level_chain;
+ b->level_chain = save_template_parm;
+ save_template_parm = b;
+ }
+
+ pop_namespace ();
+
+ /* Restore template parameter scopes. */
+ while (save_template_parm)
+ {
+ struct cp_binding_level *b = save_template_parm;
+ save_template_parm = b->level_chain;
+ b->level_chain = current_binding_level;
+ current_binding_level = b;
+ }
+ }
+ else
+ popclass ();
+
+ inner = CP_DECL_CONTEXT (TREE_CODE (inner) == NAMESPACE_DECL ? inner : TYPE_NAME (inner));
+ }
+}
\f
/* Do a pushlevel for class declarations. */
tree shadowed;
timevar_push (TV_NAME_LOOKUP);
- my_friendly_assert (level != 0, 354);
+ gcc_assert (level != 0);
/* If we're leaving a toplevel class, cache its binding level. */
if (current_class_depth == 1)
context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
else
{
- my_friendly_assert (DECL_P (decl), 0);
+ gcc_assert (DECL_P (decl));
context = context_for_name_lookup (decl);
}
input_location = save_location;
}
}
- timevar_pop (TV_NAME_LOOKUP);
-
- return is_valid;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, is_valid);
}
/* Return the BINDING (if any) for NAME in SCOPE, which is a class
;
else if (value_binding)
{
- if (TREE_CODE (value_binding) == TREE_LIST
+ if (TREE_CODE (value_binding) == TREE_LIST
&& TREE_TYPE (value_binding) == error_mark_node)
/* NAME is ambiguous. */
;
new binding object. */
if (type_binding || value_binding)
{
- binding = new_class_binding (name,
- value_binding,
+ binding = new_class_binding (name,
+ value_binding,
type_binding,
scope);
/* This is a class-scope binding, not a block-scope binding. */
return binding;
}
-
+
/* Make the declaration(s) of X appear in CLASS scope under the name
NAME. Returns true if the binding is valid. */
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. */
- my_friendly_assert (TYPE_BEING_DEFINED (current_class_type), 20040713);
+ gcc_assert (TYPE_BEING_DEFINED (current_class_type));
/* We could have been passed a tree list if this is an ambiguous
declaration. If so, pull the declaration out because
- check_template_shadow will not handle a TREE_LIST. */
- if (TREE_CODE (decl) == TREE_LIST
+ check_template_shadow will not handle a TREE_LIST. */
+ if (TREE_CODE (decl) == TREE_LIST
&& TREE_TYPE (decl) == error_mark_node)
decl = TREE_VALUE (decl);
tree scope = context_for_name_lookup (x);
if (TYPE_P (scope) && same_type_p (scope, current_class_type))
{
- error ("`%D' has the same name as the class in which it is "
+ error ("%qD has the same name as the class in which it is "
"declared",
x);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
if (INHERITED_VALUE_BINDING_P (binding))
{
/* If the old binding was from a base class, and was for a
- tag name, slide it over to make room for the new binding.
- The old binding is still visible if explicitly qualified
- with a class-key. */
+ tag name, slide it over to make room for the new binding.
+ The old binding is still visible if explicitly qualified
+ with a class-key. */
if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
&& !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
{
INHERITED_VALUE_BINDING_P (binding) = 0;
}
else
- old_decl = bval;
+ {
+ old_decl = bval;
+ /* Any inherited type declaration is hidden by the type
+ declaration in the derived class. */
+ if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
+ binding->type = NULL_TREE;
+ }
}
else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
old_decl = bval;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
+/* Process "using SCOPE::NAME" in a class scope. Return the
+ USING_DECL created. */
+
tree
-do_class_using_decl (tree decl)
+do_class_using_decl (tree scope, tree name)
{
- tree name, value, scope, type;
-
- if (TREE_CODE (decl) != SCOPE_REF
- || !TREE_OPERAND (decl, 0)
- || !TYPE_P (TREE_OPERAND (decl, 0)))
- {
+ /* The USING_DECL returned by this function. */
+ tree value;
+ /* The declaration (or declarations) name by this using
+ declaration. NULL if we are in a template and cannot figure out
+ what has been named. */
+ tree decl;
+ /* True if SCOPE is a dependent type. */
+ bool scope_dependent_p;
+ /* True if SCOPE::NAME is dependent. */
+ bool name_dependent_p;
+ /* 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;
+
+ if (!scope || !TYPE_P (scope))
+ {
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
- scope = TREE_OPERAND (decl, 0);
- name = TREE_OPERAND (decl, 1);
+
+ /* Make sure the name is not invalid */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- error ("using-declaration cannot name destructor");
+ error ("%<%T::%D%> names destructor", scope, name);
return NULL_TREE;
}
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- else if (TREE_CODE (name) == TEMPLATE_DECL)
- name = DECL_NAME (name);
- else if (BASELINK_P (name))
+ if (constructor_name_p (name, scope))
{
- tree fns = BASELINK_FUNCTIONS (name);
- name = DECL_NAME (get_first_fn (fns));
+ error ("%<%T::%D%> names constructor", scope, name);
+ return NULL_TREE;
+ }
+ if (constructor_name_p (name, current_class_type))
+ {
+ error ("%<%T::%D%> names constructor in %qT",
+ scope, name, current_class_type);
+ return NULL_TREE;
}
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
+ scope_dependent_p = dependent_type_p (scope);
+ 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);
+ i++)
+ if (dependent_type_p (TREE_TYPE (base_binfo)))
+ {
+ bases_dependent_p = true;
+ break;
+ }
- /* Dependent using decls have a NULL type, non-dependent ones have a
- void type. */
- type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
- value = build_lang_decl (USING_DECL, name, type);
- DECL_INITIAL (value) = scope;
+ decl = NULL_TREE;
- if (scope && !processing_template_decl)
+ /* 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.
+
+ 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)
{
- tree r;
+ 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 (!name_dependent_p)
+ {
+ decl = lookup_member (binfo, name, 0, false);
+ if (!decl)
+ {
+ error ("no members matching %<%T::%D%> in %q#T", scope, name,
+ scope);
+ return NULL_TREE;
+ }
+ /* The binfo from which the functions came does not matter. */
+ if (BASELINK_P (decl))
+ decl = BASELINK_FUNCTIONS (decl);
+ }
+ }
+
+ value = build_lang_decl (USING_DECL, name, NULL_TREE);
+ USING_DECL_DECLS (value) = decl;
+ USING_DECL_SCOPE (value) = scope;
+ DECL_DEPENDENT_P (value) = !decl;
- r = lookup_qualified_name (scope, name, false, false);
- if (r && (DECL_P (r) || TREE_CODE (r) == OVERLOAD))
- cp_emit_debug_info_for_using (r, scope);
- }
return value;
}
if (scope == NULL)
scope = global_namespace;
- scope = ORIGINAL_NAMESPACE (scope);
+ else
+ /* Unnecessary for the global namespace because it can't be an alias. */
+ scope = ORIGINAL_NAMESPACE (scope);
+
binding = cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
return binding ? binding->value : NULL_TREE;
void
set_decl_namespace (tree decl, tree scope, bool friendp)
{
- tree old;
-
+ tree old, fn;
+
/* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
-
+
/* It is ok for friends to be qualified in parallel space. */
if (!friendp && !is_ancestor (current_namespace, scope))
- error ("declaration of `%D' not in a namespace surrounding `%D'",
- decl, scope);
+ error ("declaration of %qD not in a namespace surrounding %qD",
+ decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
- if (scope != current_namespace)
+
+ /* Writing "int N::i" to declare a variable within "N" is invalid. */
+ if (scope == current_namespace)
{
- /* See whether this has been declared in the namespace. */
- old = namespace_binding (DECL_NAME (decl), scope);
- if (!old)
- /* No old declaration at all. */
- goto complain;
- /* A template can be explicitly specialized in any namespace. */
- if (processing_explicit_instantiation)
- return;
- if (!is_overloaded_fn (decl))
- /* Don't compare non-function decls with decls_match here,
- since it can't check for the correct constness at this
- point. pushdecl will find those errors later. */
- return;
- /* Since decl is a function, old should contain a function decl. */
- if (!is_overloaded_fn (old))
- goto complain;
- if (processing_template_decl || processing_specialization)
- /* We have not yet called push_template_decl to turn a
- FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
- won't match. But, we'll check later, when we construct the
- template. */
- return;
- if (is_overloaded_fn (old))
- {
- for (; old; old = OVL_NEXT (old))
- if (decls_match (decl, OVL_CURRENT (old)))
- return;
- }
- else
- if (decls_match (decl, old))
- return;
+ if (at_namespace_scope_p ())
+ error ("explicit qualification in declaration of %qD",
+ decl);
+ return;
}
- else
+
+ /* See whether this has been declared in the namespace. */
+ old = lookup_qualified_name (scope, DECL_NAME (decl), false, true);
+ if (!old)
+ /* No old declaration at all. */
+ goto complain;
+ if (!is_overloaded_fn (decl))
+ /* Don't compare non-function decls with decls_match here, since
+ it can't check for the correct constness at this
+ point. pushdecl will find those errors later. */
return;
+ /* Since decl is a function, old should contain a function decl. */
+ if (!is_overloaded_fn (old))
+ goto complain;
+ fn = OVL_CURRENT (old);
+ if (!is_associated_namespace (scope, CP_DECL_CONTEXT (fn)))
+ goto complain;
+ /* A template can be explicitly specialized in any namespace. */
+ if (processing_explicit_instantiation)
+ return;
+ if (processing_template_decl || processing_specialization)
+ /* We have not yet called push_template_decl to turn a
+ FUNCTION_DECL into a TEMPLATE_DECL, so the declarations won't
+ match. But, we'll check later, when we construct the
+ template. */
+ return;
+ /* Instantiations or specializations of templates may be declared as
+ friends in any namespace. */
+ if (friendp && DECL_USE_TEMPLATE (decl))
+ return;
+ if (is_overloaded_fn (old))
+ {
+ for (; old; old = OVL_NEXT (old))
+ if (decls_match (decl, OVL_CURRENT (old)))
+ return;
+ }
+ else if (decls_match (decl, old))
+ return;
complain:
- error ("`%D' should have been declared inside `%D'",
- decl, scope);
-}
+ error ("%qD should have been declared inside %qD", decl, scope);
+}
/* Return the namespace where the current declaration is declared. */
-tree
+static tree
current_decl_namespace (void)
{
tree result;
result = decl_namespace_context (current_class_type);
else if (current_function_decl)
result = decl_namespace_context (current_function_decl);
- else
+ else
result = current_namespace;
return result;
}
void
push_namespace (tree name)
{
+ push_namespace_with_attribs (name, NULL_TREE);
+}
+
+/* Same, but specify attributes to apply to the namespace. The attributes
+ only apply to the current namespace-body, not to any later extensions. */
+
+void
+push_namespace_with_attribs (tree name, tree attributes)
+{
tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
bool anon = !name;
timevar_push (TV_NAME_LOOKUP);
-
+
/* We should not get here if the global_namespace is not yet constructed
nor if NAME designates the global namespace: The global scope is
constructed elsewhere. */
- my_friendly_assert (global_namespace != NULL && name != global_scope_name,
- 20030531);
+ gcc_assert (global_namespace != NULL && name != global_scope_name);
if (anon)
{
/* The name of anonymous namespace is unique for the translation
- unit. */
+ unit. */
if (!anonymous_namespace_name)
- anonymous_namespace_name = get_file_function_name ('N');
+ anonymous_namespace_name = get_file_function_name ('N');
name = anonymous_namespace_name;
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
- /* Reopening anonymous namespace. */
- need_new = 0;
+ /* Reopening anonymous namespace. */
+ need_new = 0;
implicit_use = 1;
}
else
/* Check whether this is an extended namespace definition. */
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
- {
- need_new = 0;
- if (DECL_NAMESPACE_ALIAS (d))
- {
- error ("namespace alias `%D' not allowed here, assuming `%D'",
- d, DECL_NAMESPACE_ALIAS (d));
- d = DECL_NAMESPACE_ALIAS (d);
- }
- }
+ {
+ need_new = 0;
+ if (DECL_NAMESPACE_ALIAS (d))
+ {
+ error ("namespace alias %qD not allowed here, assuming %qD",
+ d, DECL_NAMESPACE_ALIAS (d));
+ d = DECL_NAMESPACE_ALIAS (d);
+ }
+ }
}
if (need_new)
/* 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);
+ /* 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;
+ }
+ found:
+#endif
+
timevar_pop (TV_NAME_LOOKUP);
}
void
pop_namespace (void)
{
- my_friendly_assert (current_namespace != global_namespace, 20010801);
+ gcc_assert (current_namespace != global_namespace);
current_namespace = CP_DECL_CONTEXT (current_namespace);
/* The binding level is not popped, as it might be re-opened later. */
leave_scope ();
if (TREE_CODE (decl) != NAMESPACE_DECL)
decl = decl_namespace_context (decl);
decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
- NULL_TREE, decl_namespace_list);
+ NULL_TREE, decl_namespace_list);
}
/* [namespace.memdef]/2 */
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
-/* Return the namespace that is the common ancestor
+/* Return the namespace that is the common ancestor
of two given namespaces. */
static tree
if (is_ancestor (ns1, ns2))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
- namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
+ namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
}
/* Process a namespace-alias declaration. */
void
do_namespace_alias (tree alias, tree namespace)
{
- if (TREE_CODE (namespace) != NAMESPACE_DECL)
- {
- /* The parser did not find it, so it's not there. */
- error ("unknown namespace `%D'", namespace);
- return;
- }
+ if (namespace == error_mark_node)
+ return;
+
+ gcc_assert (TREE_CODE (namespace) == NAMESPACE_DECL);
namespace = ORIGINAL_NAMESPACE (namespace);
/* Build the alias. */
- alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
+ alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
DECL_EXTERNAL (alias) = 1;
+ DECL_CONTEXT (alias) = FROB_CONTEXT (current_scope ());
pushdecl (alias);
/* Emit debug info for namespace alias. */
if appropriate. */
tree
-pushdecl_namespace_level (tree x)
+pushdecl_namespace_level (tree x, bool is_friend)
{
struct cp_binding_level *b = current_binding_level;
tree t;
timevar_push (TV_NAME_LOOKUP);
- t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
+ t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace), is_friend);
/* Now, the type_shadowed stack may screw us. Munge it so it does
what we want. */
- if (TREE_CODE (x) == TYPE_DECL)
+ if (TREE_CODE (t) == TYPE_DECL)
{
- tree name = DECL_NAME (x);
+ tree name = DECL_NAME (t);
tree newval;
tree *ptr = (tree *)0;
for (; !global_scope_p (b); b = b->level_chain)
- {
- tree shadowed = b->type_shadowed;
- for (; shadowed; shadowed = TREE_CHAIN (shadowed))
- if (TREE_PURPOSE (shadowed) == name)
- {
+ {
+ tree shadowed = b->type_shadowed;
+ for (; shadowed; shadowed = TREE_CHAIN (shadowed))
+ if (TREE_PURPOSE (shadowed) == name)
+ {
ptr = &TREE_VALUE (shadowed);
/* Can't break out of the loop here because sometimes
a binding level will have duplicate bindings for
PT names. It's gross, but I haven't time to fix it. */
- }
- }
- newval = TREE_TYPE (x);
+ }
+ }
+ newval = TREE_TYPE (t);
if (ptr == (tree *)0)
- {
- /* @@ This shouldn't be needed. My test case "zstring.cc" trips
- up here if this is changed to an assertion. --KR */
- SET_IDENTIFIER_TYPE_VALUE (name, x);
+ {
+ /* @@ This shouldn't be needed. My test case "zstring.cc" trips
+ up here if this is changed to an assertion. --KR */
+ SET_IDENTIFIER_TYPE_VALUE (name, t);
}
else
- {
+ {
*ptr = newval;
- }
+ }
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Insert USED into the using list of USER. Set INDIRECT_flag if this
directive is not directly from the source. Also find the common
ancestor and let our users know about the new namespace */
-static void
+static void
add_using_namespace (tree user, tree used, bool indirect)
{
tree t;
timevar_pop (TV_NAME_LOOKUP);
return;
}
- my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
- my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
+ gcc_assert (TREE_CODE (user) == NAMESPACE_DECL);
+ gcc_assert (TREE_CODE (used) == NAMESPACE_DECL);
/* Check if we already have this. */
t = purpose_member (used, DECL_NAMESPACE_USING (user));
if (t != NULL_TREE)
}
/* Add used to the user's using list. */
- DECL_NAMESPACE_USING (user)
- = tree_cons (used, namespace_ancestor (user, used),
+ DECL_NAMESPACE_USING (user)
+ = tree_cons (used, namespace_ancestor (user, used),
DECL_NAMESPACE_USING (user));
TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
decl = validate_nonmember_using_decl (decl, scope, name);
if (decl == NULL_TREE)
return;
-
+
binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), name);
oldval = binding->value;
binding->value = newval;
if (newtype)
binding->type = newtype;
- return;
}
/* Process a using-directive. */
{
tree context = NULL_TREE;
+ if (namespace == error_mark_node)
+ return;
+
+ gcc_assert (TREE_CODE (namespace) == NAMESPACE_DECL);
+
if (building_stmt_tree ())
add_stmt (build_stmt (USING_STMT, namespace));
-
- /* using namespace A::B::C; */
- if (TREE_CODE (namespace) == SCOPE_REF)
- namespace = TREE_OPERAND (namespace, 1);
- if (TREE_CODE (namespace) == IDENTIFIER_NODE)
- {
- /* Lookup in lexer did not find a namespace. */
- if (!processing_template_decl)
- error ("namespace `%T' undeclared", namespace);
- return;
- }
- if (TREE_CODE (namespace) != NAMESPACE_DECL)
- {
- if (!processing_template_decl)
- error ("`%T' is not a namespace", namespace);
- return;
- }
namespace = ORIGINAL_NAMESPACE (namespace);
+
if (!toplevel_bindings_p ())
{
push_using_directive (namespace);
if (current_namespace != global_namespace)
context = current_namespace;
}
-
+
/* Emit debugging info. */
if (!processing_template_decl)
(*debug_hooks->imported_module_or_decl) (namespace, context);
{
if (!toplevel_bindings_p ())
error ("strong using only meaningful at namespace scope");
- else
- DECL_NAMESPACE_ASSOCIATIONS (namespace)
- = tree_cons (current_namespace, 0,
- DECL_NAMESPACE_ASSOCIATIONS (namespace));
+ else if (namespace != error_mark_node)
+ {
+ if (!is_ancestor (current_namespace, namespace))
+ error ("current namespace %qD does not enclose strongly used namespace %qD",
+ current_namespace, namespace);
+ DECL_NAMESPACE_ASSOCIATIONS (namespace)
+ = tree_cons (current_namespace, 0,
+ DECL_NAMESPACE_ASSOCIATIONS (namespace));
+ }
}
else
- warning ("`%D' attribute directive ignored", name);
+ warning (OPT_Wattributes, "%qD attribute directive ignored", name);
}
}
*INIT, if INIT is non-NULL. */
static tree
-pushdecl_top_level_1 (tree x, tree *init)
+pushdecl_top_level_1 (tree x, tree *init, bool is_friend)
{
timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
- x = pushdecl_namespace_level (x);
+ x = pushdecl_namespace_level (x, is_friend);
if (init)
- cp_finish_decl (x, *init, NULL_TREE, 0);
+ finish_decl (x, *init, NULL_TREE);
pop_from_top_level ();
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
tree
pushdecl_top_level (tree x)
{
- return pushdecl_top_level_1 (x, NULL);
+ return pushdecl_top_level_1 (x, NULL, false);
+}
+
+/* Like pushdecl_top_level, but adding the IS_FRIEND parameter. */
+
+tree
+pushdecl_top_level_maybe_friend (tree x, bool is_friend)
+{
+ return pushdecl_top_level_1 (x, NULL, is_friend);
}
/* Like pushdecl, only it places X in the global scope if
tree
pushdecl_top_level_and_finish (tree x, tree init)
{
- return pushdecl_top_level_1 (x, &init);
+ return pushdecl_top_level_1 (x, &init, false);
}
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
need to add it again. For `extern "C"' functions, we
might have two FUNCTION_DECLs for the same function, in
different namespaces; again, we only need one of them. */
- if (fn1 == fn2
+ if (fn1 == fn2
|| (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
&& DECL_NAME (fn1) == DECL_NAME (fn2)))
break;
}
-
+
/* If we exhausted all of the functions in S1, FN2 is new. */
if (!fns1)
s1 = build_overload (fn2, s1);
int flags)
{
tree val, type;
- my_friendly_assert (old != NULL, 393);
+ gcc_assert (old != NULL);
/* 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))
- val = NULL_TREE;
- break;
+ /* 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))
- val = NULL_TREE;
- break;
+ 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;
+ 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) || DECL_ANTICIPATED (val))
- val = NULL_TREE;
- break;
+ /* 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 (LOOKUP_QUALIFIERS_ONLY (flags))
+ val = NULL_TREE;
}
-
+
if (!old->value)
old->value = val;
else if (val && val != old->value)
{
if (is_overloaded_fn (old->value) && is_overloaded_fn (val))
- old->value = merge_functions (old->value, val);
+ old->value = merge_functions (old->value, val);
else
{
- /* Some declarations are functions, some are not. */
- if (flags & LOOKUP_COMPLAIN)
- {
- /* If we've already given this error for this lookup,
- old->value is error_mark_node, so let's not
- repeat ourselves. */
- if (old->value != error_mark_node)
- {
- error ("use of `%D' is ambiguous", name);
- cp_error_at (" first declared as `%#D' here",
- old->value);
- }
- cp_error_at (" also declared as `%#D' here", val);
- }
- old->value = error_mark_node;
+ old->value = tree_cons (NULL_TREE, old->value,
+ build_tree_list (NULL_TREE, new->value));
+ TREE_TYPE (old->value) = error_mark_node;
}
}
/* ... and copy the type. */
else if (type && old->type != type)
{
if (flags & LOOKUP_COMPLAIN)
- {
- error ("`%D' denotes an ambiguous type",name);
- error ("%J first type here", TYPE_MAIN_DECL (old->type));
- error ("%J other type here", TYPE_MAIN_DECL (type));
- }
+ {
+ 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));
+ }
}
}
}
/* Given a lookup that returned VAL, use FLAGS to decide if we want to
- ignore it or not. Subroutine of lookup_name_real. */
+ ignore it or not. Subroutine of lookup_name_real and
+ lookup_type_scope. */
-static tree
+static bool
qualify_lookup (tree val, int flags)
{
if (val == NULL_TREE)
- return val;
+ return false;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
- return val;
+ return true;
if ((flags & LOOKUP_PREFER_TYPES)
&& (TREE_CODE (val) == TYPE_DECL || TREE_CODE (val) == TEMPLATE_DECL))
- return val;
+ return true;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
- return NULL_TREE;
- return val;
+ return false;
+ return true;
}
-/* Look up NAME in the NAMESPACE. */
+/* Given a lookup that returned VAL, decide if we want to ignore it or
+ not based on DECL_ANTICIPATED. */
-tree
-lookup_namespace_name (tree namespace, tree name)
+bool
+hidden_name_p (tree val)
{
- tree val;
- tree template_id = NULL_TREE;
- struct scope_binding binding = EMPTY_SCOPE_BINDING;
-
- timevar_push (TV_NAME_LOOKUP);
- my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
-
- if (TREE_CODE (name) == NAMESPACE_DECL)
- /* This happens for A::B<int> when B is a namespace. */
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
- else if (TREE_CODE (name) == TEMPLATE_DECL)
- {
- /* This happens for A::B where B is a template, and there are no
- template arguments. */
- error ("invalid use of `%D'", name);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- }
-
- namespace = ORIGINAL_NAMESPACE (namespace);
-
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- template_id = name;
- name = TREE_OPERAND (name, 0);
- if (TREE_CODE (name) == OVERLOAD)
- name = DECL_NAME (OVL_CURRENT (name));
- else if (DECL_P (name))
- name = DECL_NAME (name);
- }
+ if (DECL_P (val)
+ && DECL_LANG_SPECIFIC (val)
+ && DECL_ANTICIPATED (val))
+ return true;
+ return false;
+}
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
+/* Remove any hidden friend functions from a possibly overloaded set
+ of functions. */
- if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+tree
+remove_hidden_names (tree fns)
+{
+ if (!fns)
+ return fns;
- if (binding.value)
+ if (TREE_CODE (fns) == FUNCTION_DECL && hidden_name_p (fns))
+ fns = NULL_TREE;
+ else if (TREE_CODE (fns) == OVERLOAD)
{
- val = binding.value;
+ tree o;
- if (template_id)
+ for (o = fns; o; o = OVL_NEXT (o))
+ if (hidden_name_p (OVL_CURRENT (o)))
+ break;
+ if (o)
{
- if (DECL_CLASS_TEMPLATE_P (val))
- val = lookup_template_class (val,
- TREE_OPERAND (template_id, 1),
- /*in_decl=*/NULL_TREE,
- /*context=*/NULL_TREE,
- /*entering_scope=*/0,
- tf_error | tf_warning);
- else if (DECL_FUNCTION_TEMPLATE_P (val)
- || TREE_CODE (val) == OVERLOAD)
- val = lookup_template_function (val,
- TREE_OPERAND (template_id, 1));
- else
- {
- error ("`%D::%D' is not a template",
- namespace, name);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- }
- }
-
- /* If we have a single function from a using decl, pull it out. */
- if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
- val = OVL_FUNCTION (val);
+ tree n = NULL_TREE;
- /* Ignore built-in functions that haven't been prototyped yet. */
- if (!val || !DECL_P(val)
- || !DECL_LANG_SPECIFIC(val)
- || !DECL_ANTICIPATED (val))
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ for (o = fns; o; o = OVL_NEXT (o))
+ if (!hidden_name_p (OVL_CURRENT (o)))
+ n = build_overload (OVL_CURRENT (o), n);
+ fns = n;
+ }
}
- error ("`%D' undeclared in namespace `%D'", name, namespace);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ return fns;
}
/* Select the right _DECL from multiple choices. */
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
- if (val && TREE_CODE (val) == NAMESPACE_DECL)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ 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 (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)
+ else if (val && LOOKUP_TYPES_ONLY (flags)
&& ! DECL_DECLARES_TYPE_P (val))
val = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
cxx_binding *b =
- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
if (b)
{
- if (b->value && DECL_P (b->value)
- && DECL_LANG_SPECIFIC (b->value)
- && DECL_ANTICIPATED (b->value))
- /* Ignore anticipated built-in functions. */
+ if (b->value && hidden_name_p (b->value))
+ /* Ignore anticipated built-in functions and friends. */
;
else
binding.value = b->value;
level->kind != sk_namespace;
level = level->level_chain)
if (!lookup_using_namespace (name, &binding, level->using_directives,
- scope, flags))
+ scope, flags))
/* Give up because of error. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
while (1)
{
if (!lookup_using_namespace (name, &binding,
- DECL_NAMESPACE_USING (siter),
+ DECL_NAMESPACE_USING (siter),
scope, flags))
/* Give up because of error. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
or a class TYPE). If IS_TYPE_P is TRUE, then ignore non-type
- bindings.
+ bindings.
Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. If no suitable declaration can be found,
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 = select_decl (&binding, flags);
}
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:
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
- tree used = ORIGINAL_NAMESPACE (TREE_PURPOSE (iter));
- cxx_binding *val1 =
- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
- /* Resolve ambiguities. */
- if (val1)
- ambiguous_decl (name, val, val1, flags);
+ tree used = ORIGINAL_NAMESPACE (TREE_PURPOSE (iter));
+ cxx_binding *val1 =
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
+ /* Resolve ambiguities. */
+ if (val1)
+ ambiguous_decl (name, 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 (name, result, binding, flags);
/* Consider strong using directives always, and non-strong ones
if we haven't found a binding yet. ??? Shouldn't we consider
CLASS_P is false, then class bindings are ignored. */
cxx_binding *
-outer_binding (tree name,
+outer_binding (tree name,
cxx_binding *binding,
bool class_p)
{
if (class_p)
while (scope && scope != outer_scope && scope->kind != sk_namespace)
{
- if (scope->kind == sk_class)
+ if (scope->kind == sk_class)
{
cxx_binding *class_binding;
-
+
class_binding = get_class_binding (name, scope);
if (class_binding)
{
node of some kind representing its definition if there is only one
such declaration, or return a TREE_LIST with all the overloaded
definitions if there are many, or return 0 if it is undefined.
+ Hidden name, either friend declaration or built-in function, are
+ not ignored.
If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
/* Conversion operators are handled specially because ordinary
unqualified name lookup will not find template conversion
operators. */
- if (IDENTIFIER_TYPENAME_P (name))
+ if (IDENTIFIER_TYPENAME_P (name))
{
struct cp_binding_level *level;
- for (level = current_binding_level;
+ for (level = current_binding_level;
level && level->kind != sk_namespace;
level = level->level_chain)
{
tree class_type;
tree operators;
-
- /* A conversion operator can only be declared in a class
+
+ /* A conversion operator can only be declared in a class
scope. */
if (level->kind != sk_class)
continue;
-
+
/* Lookup the conversion operator in the class. */
class_type = level->this_entity;
operators = lookup_fnfields (class_type, name, /*protect=*/0);
iter = outer_binding (name, iter, !nonclass))
{
tree binding;
-
+
/* Skip entities we don't want. */
if (LOCAL_BINDING_P (iter) ? !block_p : nonclass)
continue;
-
+
/* If this is the kind of thing we're looking for, we're done. */
- if (qualify_lookup (iter->value, flags))
+ if (qualify_lookup (iter->value, flags)
+ && !hidden_name_p (iter->value))
binding = iter->value;
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (iter->type, flags))
+ && qualify_lookup (iter->type, flags)
+ && !hidden_name_p (iter->type))
binding = iter->type;
else
binding = NULL_TREE;
-
+
if (binding)
{
val = binding;
/* Now lookup in namespace scopes. */
if (!val)
- {
- tree t = unqualified_namespace_lookup (name, flags);
- if (t)
- val = t;
- }
+ val = unqualified_namespace_lookup (name, flags);
- if (val)
- {
- /* If we have a single function from a using decl, pull it out. */
- if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
- val = OVL_FUNCTION (val);
- }
+ /* If we have a single function from a using decl, pull it out. */
+ if (val && TREE_CODE (val) == OVERLOAD && !really_overloaded_fn (val))
+ val = OVL_FUNCTION (val);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
tree
lookup_function_nonclass (tree name, tree args, bool block_p)
{
- return
- lookup_arg_dependent (name,
- lookup_name_real (name, 0, 1, block_p, 0,
+ return
+ lookup_arg_dependent (name,
+ lookup_name_real (name, 0, 1, block_p, 0,
LOOKUP_COMPLAIN),
args);
}
tree
-lookup_name (tree name, int prefer_type)
+lookup_name (tree name)
{
- return lookup_name_real (name, prefer_type, 0, /*block_p=*/true,
+ return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, LOOKUP_COMPLAIN);
+}
+
+tree
+lookup_name_prefer_type (tree name, int prefer_type)
+{
+ return lookup_name_real (name, prefer_type, 0, /*block_p=*/true,
0, LOOKUP_COMPLAIN);
}
+/* Look up NAME for type used in elaborated name specifier in
+ the scopes given by SCOPE. SCOPE can be either TS_CURRENT or
+ TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the
+ name, more scopes are checked if cleanup or template parameter
+ scope is encountered.
+
+ Unlike lookup_name_real, we make sure that NAME is actually
+ declared in the desired scope, not from inheritance, nor using
+ directive. For using declaration, there is DR138 still waiting
+ to be resolved. Hidden name coming from an earlier friend
+ declaration is also returned.
+
+ A TYPE_DECL best matching the NAME is returned. Catching error
+ and issuing diagnostics are caller's responsibility. */
+
+tree
+lookup_type_scope (tree name, tag_scope scope)
+{
+ cxx_binding *iter = NULL;
+ tree val = NULL_TREE;
+
+ timevar_push (TV_NAME_LOOKUP);
+
+ /* Look in non-namespace scope first. */
+ if (current_binding_level->kind != sk_namespace)
+ iter = outer_binding (name, NULL, /*class_p=*/ true);
+ for (; iter; iter = outer_binding (name, iter, /*class_p=*/ true))
+ {
+ /* Check if this is the kind of thing we're looking for.
+ If SCOPE is TS_CURRENT, also make sure it doesn't come from
+ base class. For ITER->VALUE, we can simply use
+ INHERITED_VALUE_BINDING_P. For ITER->TYPE, we have to use
+ our own check.
+
+ We check ITER->TYPE before ITER->VALUE in order to handle
+ typedef struct C {} C;
+ correctly. */
+
+ if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)
+ && (scope != ts_current
+ || LOCAL_BINDING_P (iter)
+ || DECL_CONTEXT (iter->type) == iter->scope->this_entity))
+ val = iter->type;
+ else if ((scope != ts_current
+ || !INHERITED_VALUE_BINDING_P (iter))
+ && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+ val = iter->value;
+
+ if (val)
+ break;
+ }
+
+ /* Look in namespace scope. */
+ if (!val)
+ {
+ iter = cxx_scope_find_binding_for_name
+ (NAMESPACE_LEVEL (current_decl_namespace ()), name);
+
+ if (iter)
+ {
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
+ val = iter->type;
+ else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+ val = iter->value;
+ }
+
+ }
+
+ /* Type found, check if it is in the allowed scopes, ignoring cleanup
+ and template parameter scopes. */
+ if (val)
+ {
+ struct cp_binding_level *b = current_binding_level;
+ while (b)
+ {
+ if (iter->scope == b)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+
+ if (b->kind == sk_cleanup || b->kind == sk_template_parms)
+ b = b->level_chain;
+ else if (b->kind == sk_class
+ && scope == ts_within_enclosing_non_class)
+ b = b->level_chain;
+ else
+ break;
+ }
+ }
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+}
+
/* Similar to `lookup_name' but look only in the innermost non-class
binding level. */
static tree
-lookup_name_current_level (tree name)
+lookup_name_innermost_nonclass_level (tree name)
{
struct cp_binding_level *b;
tree t = NULL_TREE;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-/* Like lookup_name_current_level, but for types. */
+/* Like lookup_name_innermost_nonclass_level, but for types. */
static tree
lookup_type_current_level (tree name)
tree t = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
- my_friendly_assert (current_binding_level->kind != sk_namespace,
- 980716);
+ gcc_assert (current_binding_level->kind != sk_namespace);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
&& REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
{
if (purpose_member (name, b->type_shadowed))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
- REAL_IDENTIFIER_TYPE_VALUE (name));
+ REAL_IDENTIFIER_TYPE_VALUE (name));
if (b->kind == sk_cleanup)
b = b->level_chain;
else
struct arg_lookup
{
tree name;
+ tree args;
tree namespaces;
tree classes;
tree functions;
case. */
/* We must find only functions, or exactly one non-function. */
- if (!k->functions)
+ if (!k->functions)
k->functions = fn;
else if (fn == k->functions)
;
{
fn = f1; f1 = f2; f2 = fn;
}
- cp_error_at ("`%D' is not a function,", f1);
- cp_error_at (" conflict with `%D'", f2);
- error (" in call to `%D'", k->name);
+ error ("%q+D is not a function,", f1);
+ error (" conflict with %q+D", f2);
+ error (" in call to %qD", k->name);
return true;
}
}
}
+/* Return whether FN is a friend of an associated class of ARG. */
+
+static bool
+friend_of_associated_class_p (tree arg, tree fn)
+{
+ tree type;
+
+ if (TYPE_P (arg))
+ type = arg;
+ else if (type_unknown_p (arg))
+ return false;
+ else
+ type = TREE_TYPE (arg);
+
+ /* If TYPE is a class, the class itself and all base classes are
+ associated classes. */
+ if (CLASS_TYPE_P (type))
+ {
+ if (is_friend (type, fn))
+ return true;
+
+ if (TYPE_BINFO (type))
+ {
+ tree binfo, base_binfo;
+ int i;
+
+ for (binfo = TYPE_BINFO (type), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo);
+ i++)
+ if (is_friend (BINFO_TYPE (base_binfo), fn))
+ return true;
+ }
+ }
+
+ /* If TYPE is a class member, the class of which it is a member is
+ an associated class. */
+ if ((CLASS_TYPE_P (type)
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ && TYPE_CONTEXT (type)
+ && CLASS_TYPE_P (TYPE_CONTEXT (type))
+ && is_friend (TYPE_CONTEXT (type), fn))
+ return true;
+
+ return false;
+}
+
/* Add functions of a namespace to the lookup structure.
Returns true on error. */
value = TREE_CHAIN (value))
if (arg_assoc_namespace (k, TREE_PURPOSE (value)))
return true;
-
+
value = namespace_binding (k->name, scope);
if (!value)
return false;
for (; value; value = OVL_NEXT (value))
- if (add_function (k, OVL_CURRENT (value)))
- return true;
-
+ {
+ /* We don't want to find arbitrary hidden functions via argument
+ dependent lookup. We only want to find friends of associated
+ classes. */
+ if (hidden_name_p (OVL_CURRENT (value)))
+ {
+ tree args;
+
+ for (args = k->args; args; args = TREE_CHAIN (args))
+ if (friend_of_associated_class_p (TREE_VALUE (args),
+ OVL_CURRENT (value)))
+ break;
+ if (!args)
+ continue;
+ }
+
+ if (add_function (k, OVL_CURRENT (value)))
+ return true;
+ }
+
return false;
}
/* It's not a member template. */
if (TREE_CODE (ctx) == NAMESPACE_DECL)
- return arg_assoc_namespace (k, ctx);
+ return arg_assoc_namespace (k, ctx);
/* Otherwise, it must be member template. */
- else
- return arg_assoc_class (k, ctx);
+ else
+ return arg_assoc_class (k, ctx);
}
/* It's not a template template argument, but it is a type template
argument. */
{
tree list, friends, context;
int i;
-
+
/* Backend build structures, such as __builtin_va_list, aren't
affected by all this. */
if (!CLASS_TYPE_P (type))
if (purpose_member (type, k->classes))
return false;
k->classes = tree_cons (type, NULL_TREE, k->classes);
-
+
context = decl_namespace_context (type);
if (arg_assoc_namespace (k, context))
return true;
{
/* Process baseclasses. */
tree binfo, base_binfo;
-
+
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
if (arg_assoc_class (k, BINFO_TYPE (base_binfo)))
return true;
}
-
+
/* Process friends. */
- for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
+ for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == FRIEND_NAME (list))
- for (friends = FRIEND_DECLS (list); friends;
+ for (friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
{
tree fn = TREE_VALUE (friends);
}
/* Process template arguments. */
- if (CLASSTYPE_TEMPLATE_INFO (type)
+ if (CLASSTYPE_TEMPLATE_INFO (type)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
{
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
- for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
- arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
+ for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
+ arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
}
return false;
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
- case CHAR_TYPE:
case BOOLEAN_TYPE:
return false;
case RECORD_TYPE:
case TYPENAME_TYPE:
return false;
case LANG_TYPE:
- if (type == unknown_type_node)
- return false;
- /* else fall through */
+ gcc_assert (type == unknown_type_node);
+ return false;
default:
- abort ();
+ gcc_unreachable ();
}
return false;
}
int ix;
if (TREE_CODE (template) == COMPONENT_REF)
- template = TREE_OPERAND (template, 1);
-
+ template = TREE_OPERAND (template, 1);
+
/* First, the template. There may actually be more than one if
this is an overloaded function template. But, in that case,
we only need the first; all the functions will be in the same
template = OVL_CURRENT (template);
ctx = CP_DECL_CONTEXT (template);
-
+
if (TREE_CODE (ctx) == NAMESPACE_DECL)
{
if (arg_assoc_namespace (k, ctx) == 1)
return true;
/* Now the arguments. */
- for (ix = TREE_VEC_LENGTH (args); ix--;)
- if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, ix)) == 1)
- return true;
+ if (args)
+ for (ix = TREE_VEC_LENGTH (args); ix--;)
+ if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, ix)) == 1)
+ return true;
}
else if (TREE_CODE (n) == OVERLOAD)
{
lookup_arg_dependent (tree name, tree fns, tree args)
{
struct arg_lookup k;
- tree fn = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
+
+ /* Remove any hidden friend functions from the list of functions
+ found so far. They will be added back by arg_assoc_class as
+ appropriate. */
+ fns = remove_hidden_names (fns);
+
k.name = name;
+ k.args = args;
k.functions = fns;
k.classes = NULL_TREE;
- /* We've already looked at some namespaces during normal unqualified
- lookup -- but we don't know exactly which ones. If the functions
- we found were brought into the current namespace via a using
- declaration, we have not really checked the namespace from which
- they came. Therefore, we check all namespaces here -- unless the
- function we have is from the current namespace. Even then, we
- must check all namespaces if the function is a local
- declaration; any other declarations present at namespace scope
- should be visible during argument-dependent lookup. */
- if (fns)
- fn = OVL_CURRENT (fns);
- if (fn && TREE_CODE (fn) == FUNCTION_DECL
- && (CP_DECL_CONTEXT (fn) != current_decl_namespace ()
- || DECL_LOCAL_FUNCTION_P (fn)))
- k.namespaces = NULL_TREE;
- else
- /* Setting NAMESPACES is purely an optimization; it prevents
- adding functions which are already in FNS. Adding them would
- be safe -- "joust" will eliminate the duplicates -- but
- wasteful. */
- k.namespaces = build_tree_list (current_decl_namespace (), NULL_TREE);
+ /* We previously performed an optimization here by setting
+ NAMESPACES to the current namespace when it was safe. However, DR
+ 164 says that namespaces that were already searched in the first
+ stage of template processing are searched again (potentially
+ picking up later definitions) in the second stage. */
+ k.namespaces = NULL_TREE;
arg_assoc_args (&k, args);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
processing. */
static tree
-maybe_process_template_type_declaration (tree type, int globalize,
- cxx_scope *b)
+maybe_process_template_type_declaration (tree type, int is_friend,
+ cxx_scope *b)
{
tree decl = TYPE_NAME (type);
/* You can't declare a new template type in a template parameter
list. But, you can declare a non-template type:
- template <class A*> struct S;
+ template <class A*> struct S;
is a forward-declaration of `A'. */
;
+ else if (b->kind == sk_namespace
+ && current_binding_level->kind != sk_namespace)
+ /* If this new type is being injected into a containing scope,
+ then it's not a template type. */
+ ;
else
{
- maybe_check_template_type (type);
-
- my_friendly_assert (IS_AGGR_TYPE (type)
- || TREE_CODE (type) == ENUMERAL_TYPE, 0);
-
+ gcc_assert (IS_AGGR_TYPE (type) || TREE_CODE (type) == ENUMERAL_TYPE);
if (processing_template_decl)
{
push_template_decl_real, but we want the original value. */
tree name = DECL_NAME (decl);
- decl = push_template_decl_real (decl, globalize);
+ decl = push_template_decl_real (decl, is_friend);
/* If the current binding level is the binding level for the
template parameters (see the comment in
begin_template_parm_list) and the enclosing level is a class
friend case, push_template_decl will already have put the
friend into global scope, if appropriate. */
if (TREE_CODE (type) != ENUMERAL_TYPE
- && !globalize && b->kind == sk_template_parms
+ && !is_friend && b->kind == sk_template_parms
&& b->level_chain->kind == sk_class)
{
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
- /* Put this UDT in the table of UDTs for the class, since
- that won't happen below because B is not the class
- binding level, but is instead the pseudo-global level. */
- if (b->level_chain->type_decls == NULL)
- b->level_chain->type_decls =
- binding_table_new (SCOPE_DEFAULT_HT_SIZE);
- binding_table_insert (b->level_chain->type_decls, name, type);
+
if (!COMPLETE_TYPE_P (current_class_type))
{
maybe_add_class_template_decl_list (current_class_type,
type, /*friend_p=*/0);
- CLASSTYPE_NESTED_UTDS (current_class_type) =
- b->level_chain->type_decls;
+ /* Put this UTD in the table of UTDs for the class. */
+ 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);
}
}
}
return decl;
}
-/* Push a tag name NAME for struct/class/union/enum type TYPE.
- Normally put it into the inner-most non-sk_cleanup scope,
- but if GLOBALIZE is true, put it in the inner-most non-class scope.
- The latter is needed for implicit declarations. */
+/* Push a tag name NAME for struct/class/union/enum type TYPE. In case
+ that the NAME is a class template, the tag is processed but not pushed.
-void
-pushtag (tree name, tree type, int globalize)
+ The pushed scope depend on the SCOPE parameter:
+ - When SCOPE is TS_CURRENT, put it into the inner-most non-sk_cleanup
+ scope.
+ - When SCOPE is TS_GLOBAL, put it in the inner-most non-class and
+ non-template-parameter scope. This case is needed for forward
+ declarations.
+ - When SCOPE is TS_WITHIN_ENCLOSING_NON_CLASS, this is similar to
+ TS_GLOBAL case except that names within template-parameter scopes
+ are not pushed at all.
+
+ Returns TYPE upon success and ERROR_MARK_NODE otherwise. */
+
+tree
+pushtag (tree name, tree type, tag_scope scope)
{
struct cp_binding_level *b;
+ tree decl;
timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
/* Neither are the scopes used to hold template parameters
for an explicit specialization. For an ordinary template
declaration, these scopes are not scopes from the point of
- view of the language -- but we need a place to stash
- things that will go in the containing namespace when the
- template is instantiated. */
- || (b->kind == sk_template_parms && b->explicit_spec_p)
+ view of the language. */
+ || (b->kind == sk_template_parms
+ && (b->explicit_spec_p || scope == ts_global))
|| (b->kind == sk_class
- && (globalize
+ && (scope != ts_current
/* We may be defining a new type in the initializer
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
|| COMPLETE_TYPE_P (b->this_entity))))
b = b->level_chain;
- if (b->type_decls == NULL)
- b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
- binding_table_insert (b->type_decls, name, type);
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
- if (name)
+ /* Do C++ gratuitous typedefing. */
+ if (IDENTIFIER_TYPE_VALUE (name) != type)
{
- /* Do C++ gratuitous typedefing. */
- if (IDENTIFIER_TYPE_VALUE (name) != type)
- {
- tree d = NULL_TREE;
- int in_class = 0;
- tree context = TYPE_CONTEXT (type);
-
- if (! context)
- {
- tree cs = current_scope ();
-
- if (! globalize)
- context = cs;
- else if (cs != NULL_TREE && TYPE_P (cs))
- /* When declaring a friend class of a local class, we want
- to inject the newly named class into the scope
- containing the local class, not the namespace scope. */
- context = decl_function_context (get_type_decl (cs));
- }
- if (!context)
- context = current_namespace;
+ tree tdef;
+ int in_class = 0;
+ tree context = TYPE_CONTEXT (type);
- if (b->kind == sk_class
- || (b->kind == sk_template_parms
- && b->level_chain->kind == sk_class))
- in_class = 1;
+ if (! context)
+ {
+ tree cs = current_scope ();
+
+ if (scope == ts_current)
+ context = cs;
+ else if (cs != NULL_TREE && TYPE_P (cs))
+ /* When declaring a friend class of a local class, we want
+ to inject the newly named class into the scope
+ containing the local class, not the namespace
+ scope. */
+ context = decl_function_context (get_type_decl (cs));
+ }
+ if (!context)
+ context = current_namespace;
- if (current_lang_name == lang_name_java)
- TYPE_FOR_JAVA (type) = 1;
+ if (b->kind == sk_class
+ || (b->kind == sk_template_parms
+ && b->level_chain->kind == sk_class))
+ in_class = 1;
- d = create_implicit_typedef (name, type);
- DECL_CONTEXT (d) = FROB_CONTEXT (context);
- if (! in_class)
- set_identifier_type_value_with_scope (name, d, b);
+ if (current_lang_name == lang_name_java)
+ TYPE_FOR_JAVA (type) = 1;
- d = maybe_process_template_type_declaration (type,
- globalize, b);
+ tdef = create_implicit_typedef (name, type);
+ DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
+ if (scope == ts_within_enclosing_non_class)
+ {
+ /* This is a friend. Make this TYPE_DECL node hidden from
+ ordinary name lookup. Its corresponding TEMPLATE_DECL
+ will be marked in push_template_decl_real. */
+ retrofit_lang_decl (tdef);
+ DECL_ANTICIPATED (tdef) = 1;
+ DECL_FRIEND_P (tdef) = 1;
+ }
- if (b->kind == sk_class)
- {
- if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
- /* Put this TYPE_DECL on the TYPE_FIELDS list for the
- class. But if it's a member template class, we
- want the TEMPLATE_DECL, not the TYPE_DECL, so this
- is done later. */
- finish_member_declaration (d);
- else
- pushdecl_class_level (d);
- }
+ decl = maybe_process_template_type_declaration
+ (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)
+ {
+ if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
+ /* Put this TYPE_DECL on the TYPE_FIELDS list for the
+ class. But if it's a member template class, we want
+ the TEMPLATE_DECL, not the TYPE_DECL, so this is done
+ later. */
+ finish_member_declaration (decl);
else
- d = pushdecl_with_scope (d, b);
-
- /* FIXME what if it gets a name from typedef? */
- if (ANON_AGGRNAME_P (name))
- DECL_IGNORED_P (d) = 1;
-
- TYPE_CONTEXT (type) = DECL_CONTEXT (d);
-
- /* If this is a local class, keep track of it. We need this
- information for name-mangling, and so that it is possible to find
- all function definitions in a translation unit in a convenient
- way. (It's otherwise tricky to find a member function definition
- it's only pointed to from within a local class.) */
- if (TYPE_CONTEXT (type)
- && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL
- && !processing_template_decl)
- VARRAY_PUSH_TREE (local_classes, type);
- }
- if (b->kind == sk_class
- && !COMPLETE_TYPE_P (current_class_type))
+ pushdecl_class_level (decl);
+ }
+ else if (b->kind != sk_template_parms)
{
- maybe_add_class_template_decl_list (current_class_type,
- type, /*friend_p=*/0);
- CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;
+ decl = pushdecl_with_scope (decl, b, /*is_friend=*/false);
+ if (decl == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
- }
- if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
- /* Use the canonical TYPE_DECL for this node. */
- TYPE_STUB_DECL (type) = TYPE_NAME (type);
- else
+ TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
+
+ /* If this is a local class, keep track of it. We need this
+ information for name-mangling, and so that it is possible to
+ find all function definitions in a translation unit in a
+ convenient way. (It's otherwise tricky to find a member
+ function definition it's only pointed to from within a local
+ class.) */
+ if (TYPE_CONTEXT (type)
+ && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL)
+ VEC_safe_push (tree, gc, local_classes, type);
+ }
+ if (b->kind == sk_class
+ && !COMPLETE_TYPE_P (current_class_type))
{
- /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE
- will be the tagged type we just added to the current
- binding level. This fake NULL-named TYPE_DECL node helps
- dwarfout.c to know when it needs to output a
- representation of a tagged type, and it also gives us a
- convenient place to record the "scope start" address for
- the tagged type. */
-
- tree d = build_decl (TYPE_DECL, NULL_TREE, type);
- TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
+ 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);
}
- timevar_pop (TV_NAME_LOOKUP);
+
+ decl = 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
/* Subroutines for reverting temporarily to top-level for instantiation
*OLD_BINDINGS. */
static void
-store_binding (tree id, VEC(cxx_saved_binding) **old_bindings)
+store_binding (tree id, VEC(cxx_saved_binding,gc) **old_bindings)
{
cxx_saved_binding *saved;
if (IDENTIFIER_MARKED (id))
return;
-
+
IDENTIFIER_MARKED (id) = 1;
- saved = VEC_safe_push (cxx_saved_binding, *old_bindings, NULL);
+ saved = VEC_safe_push (cxx_saved_binding, gc, *old_bindings, NULL);
saved->identifier = id;
saved->binding = IDENTIFIER_BINDING (id);
saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
}
static void
-store_bindings (tree names, VEC(cxx_saved_binding) **old_bindings)
+store_bindings (tree names, VEC(cxx_saved_binding,gc) **old_bindings)
{
tree t;
objects, rather than a TREE_LIST. */
static void
-store_class_bindings (VEC(cp_class_binding) *names,
- VEC(cxx_saved_binding) **old_bindings)
+store_class_bindings (VEC(cp_class_binding,gc) *names,
+ VEC(cxx_saved_binding,gc) **old_bindings)
{
size_t i;
cp_class_binding *cb;
s->bindings = b;
s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl;
+ s->skip_evaluation = skip_evaluation;
scope_chain = s;
current_function_decl = NULL_TREE;
- VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
+ current_lang_base = VEC_alloc (tree, gc, 10);
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
+ push_class_stack ();
+ skip_evaluation = 0;
timevar_pop (TV_NAME_LOOKUP);
}
cxx_saved_binding *saved;
size_t i;
- timevar_push (TV_NAME_LOOKUP);
+ timevar_push (TV_NAME_LOOKUP);
/* Clear out class-level bindings cache. */
if (previous_class_level)
invalidate_class_lookup_cache ();
+ pop_class_stack ();
current_lang_base = 0;
if (s->need_pop_function_context)
pop_function_context_from (NULL_TREE);
current_function_decl = s->function_decl;
+ skip_evaluation = s->skip_evaluation;
timevar_pop (TV_NAME_LOOKUP);
}
}
/* Emit debugging information for using declarations and directives.
- If input tree is overloaded fn then emit debug info for all
+ If input tree is overloaded fn then emit debug info for all
candidates. */
-static void
+void
cp_emit_debug_info_for_using (tree t, tree context)
{
- /* Ignore this FUNCTION_DECL if it refers to a builtin declaration
+ /* Don't try to emit any debug information if we have errors. */
+ if (sorrycount || errorcount)
+ return;
+
+ /* Ignore this FUNCTION_DECL if it refers to a builtin declaration
of a builtin function. */
- if (TREE_CODE (t) == FUNCTION_DECL
+ if (TREE_CODE (t) == FUNCTION_DECL
&& DECL_EXTERNAL (t)
&& DECL_BUILT_IN (t))
return;
it is a global namespace. */
if (context == global_namespace)
context = NULL_TREE;
-
+
if (BASELINK_P (t))
t = BASELINK_FUNCTIONS (t);
-
+
/* FIXME: Handle TEMPLATE_DECLs. */
for (t = OVL_CURRENT (t); t; t = OVL_NEXT (t))
if (TREE_CODE (t) != TEMPLATE_DECL)
(*debug_hooks->imported_module_or_decl) (t, context);
- }
+}
#include "gt-cp-name-lookup.h"