cp-tree.h (PUSH_GLOBAL, [...]): Delete.
* cp-tree.h (PUSH_GLOBAL, PUSH_LOCAL, PUSH_USING): Delete. * name-lookup.c (create_local_binding): New. (update_binding): New. (pushdecl_maybe_friend_1): Rename to ... (do_pushdecl): ... this. Reimplement. (pushdecl): Adjust. (push_overloaded_decl_1, push_overloaded_decl): Delete. From-SVN: r248387
This commit is contained in:
parent
f0c1ade45a
commit
3a9cc6853a
@ -1,3 +1,13 @@
|
||||
2017-05-23 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* cp-tree.h (PUSH_GLOBAL, PUSH_LOCAL, PUSH_USING): Delete.
|
||||
* name-lookup.c (create_local_binding): New.
|
||||
(update_binding): New.
|
||||
(pushdecl_maybe_friend_1): Rename to ...
|
||||
(do_pushdecl): ... this. Reimplement.
|
||||
(pushdecl): Adjust.
|
||||
(push_overloaded_decl_1, push_overloaded_decl): Delete.
|
||||
|
||||
2017-05-23 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/80396 - built-in for make_integer_sequence.
|
||||
|
@ -5312,14 +5312,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
|
||||
will be identical to
|
||||
COMPARE_STRICT. */
|
||||
|
||||
/* Used with push_overloaded_decl. */
|
||||
#define PUSH_GLOBAL 0 /* Push the DECL into namespace scope,
|
||||
regardless of the current scope. */
|
||||
#define PUSH_LOCAL 1 /* Push the DECL into the current
|
||||
scope. */
|
||||
#define PUSH_USING 2 /* We are pushing this DECL as the
|
||||
result of a using declaration. */
|
||||
|
||||
/* Used with start function. */
|
||||
#define SF_DEFAULT 0 /* No flags. */
|
||||
#define SF_PRE_PARSED 1 /* The function declaration has
|
||||
|
@ -48,7 +48,6 @@ struct scope_binding {
|
||||
};
|
||||
#define EMPTY_SCOPE_BINDING { NULL_TREE, NULL_TREE }
|
||||
|
||||
static tree push_overloaded_decl (tree, int, bool);
|
||||
static bool lookup_using_namespace (tree, struct scope_binding *, tree,
|
||||
tree, int);
|
||||
static bool qualified_lookup_using_namespace (tree, tree,
|
||||
@ -61,6 +60,23 @@ static void consider_binding_level (tree name,
|
||||
static tree push_using_directive (tree);
|
||||
static void diagnose_name_conflict (tree, tree);
|
||||
|
||||
/* Create a local binding level for NAME. */
|
||||
|
||||
static cxx_binding *
|
||||
create_local_binding (cp_binding_level *level, tree name)
|
||||
{
|
||||
cxx_binding *binding = cxx_binding_make (NULL, NULL);
|
||||
|
||||
INHERITED_VALUE_BINDING_P (binding) = false;
|
||||
LOCAL_BINDING_P (binding) = true;
|
||||
binding->scope = level;
|
||||
binding->previous = IDENTIFIER_BINDING (name);
|
||||
|
||||
IDENTIFIER_BINDING (name) = binding;
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
/* Find the binding for NAME in namespace NS. If CREATE_P is true,
|
||||
make an empty binding if there wasn't one. */
|
||||
|
||||
@ -1281,6 +1297,173 @@ matching_fn_p (tree one, tree two)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Push DECL into nonclass LEVEL BINDING. OLD is the current
|
||||
binding value (possibly with anticipated builtins stripped).
|
||||
Diagnose conflicts and return updated decl. */
|
||||
|
||||
static tree
|
||||
update_binding (cp_binding_level *level, cxx_binding *binding,
|
||||
tree old, tree decl, bool is_friend)
|
||||
{
|
||||
tree to_val = decl;
|
||||
tree to_type = NULL_TREE;
|
||||
|
||||
gcc_assert (level->kind != sk_class);
|
||||
if (old == error_mark_node)
|
||||
old = NULL_TREE;
|
||||
|
||||
if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
|
||||
{
|
||||
/* Slide the tdef out of the way. We'll undo this below, if
|
||||
we're pushing a matching tdef. */
|
||||
to_type = old;
|
||||
old = NULL_TREE;
|
||||
}
|
||||
|
||||
if (DECL_DECLARES_FUNCTION_P (decl))
|
||||
{
|
||||
if (!old)
|
||||
;
|
||||
else if (OVL_P (old))
|
||||
{
|
||||
for (ovl_iterator iter (old); iter; ++iter)
|
||||
{
|
||||
tree fn = *iter;
|
||||
|
||||
if (iter.using_p () && matching_fn_p (fn, decl))
|
||||
{
|
||||
/* If a function declaration in namespace scope or
|
||||
block scope has the same name and the same
|
||||
parameter-type- list (8.3.5) as a function
|
||||
introduced by a using-declaration, and the
|
||||
declarations do not declare the same function,
|
||||
the program is ill-formed. [namespace.udecl]/14 */
|
||||
if (tree match = duplicate_decls (decl, fn, is_friend))
|
||||
return match;
|
||||
else
|
||||
/* FIXME: To preserve existing error behavior, we
|
||||
still push the decl. This might change. */
|
||||
diagnose_name_conflict (decl, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
goto conflict;
|
||||
|
||||
to_val = ovl_insert (decl, old);
|
||||
}
|
||||
else if (to_type && TREE_CODE (decl) == TYPE_DECL)
|
||||
{
|
||||
/* We thought we wanted to slide an artificial typedef out of
|
||||
the way, to make way for another typedef. That's not always
|
||||
what we want to do. */
|
||||
if (!DECL_ARTIFICIAL (decl))
|
||||
; /* Slide. */
|
||||
else if (same_type_p (TREE_TYPE (to_type), TREE_TYPE (decl)))
|
||||
/* Two artificial decls to same type. Do nothing. */
|
||||
return to_type;
|
||||
else
|
||||
goto conflict;
|
||||
}
|
||||
else if (!old)
|
||||
;
|
||||
else if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
|
||||
{
|
||||
/* Slide DECL into the type slot. */
|
||||
to_type = decl;
|
||||
to_val = old;
|
||||
}
|
||||
else if (TREE_CODE (old) != TREE_CODE (decl))
|
||||
/* Different kinds of decls conflict. */
|
||||
goto conflict;
|
||||
else if (TREE_CODE (old) == TYPE_DECL)
|
||||
{
|
||||
if (DECL_ARTIFICIAL (decl))
|
||||
{
|
||||
/* Slide DECL into the type slot instead. */
|
||||
to_type = decl;
|
||||
to_val = old;
|
||||
}
|
||||
else if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
|
||||
/* Two type decls to the same type. Do nothing. */
|
||||
return old;
|
||||
else
|
||||
goto conflict;
|
||||
}
|
||||
else if (TREE_CODE (old) == NAMESPACE_DECL)
|
||||
{
|
||||
if (DECL_NAMESPACE_ALIAS (old) && DECL_NAMESPACE_ALIAS (decl)
|
||||
&& ORIGINAL_NAMESPACE (old) == ORIGINAL_NAMESPACE (decl))
|
||||
/* 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
|
||||
refers. [namespace.alias] */
|
||||
return old;
|
||||
else
|
||||
goto conflict;
|
||||
}
|
||||
else if (TREE_CODE (old) == VAR_DECL)
|
||||
{
|
||||
/* There can be two block-scope declarations of the same
|
||||
variable, so long as they are `extern' declarations. */
|
||||
if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl))
|
||||
goto conflict;
|
||||
else if (tree match = duplicate_decls (decl, old, false))
|
||||
return match;
|
||||
else
|
||||
goto conflict;
|
||||
}
|
||||
else
|
||||
{
|
||||
conflict:
|
||||
diagnose_name_conflict (decl, old);
|
||||
to_val = NULL_TREE;
|
||||
}
|
||||
|
||||
if (to_val)
|
||||
{
|
||||
if (level->kind != sk_namespace
|
||||
&& !to_type && binding->value && OVL_P (to_val))
|
||||
update_local_overload (binding, to_val);
|
||||
else
|
||||
{
|
||||
tree to_add = to_val;
|
||||
|
||||
if (level->kind == sk_namespace)
|
||||
to_add = decl;
|
||||
else if (to_type == decl)
|
||||
to_add = decl;
|
||||
else if (TREE_CODE (to_add) == OVERLOAD)
|
||||
to_add = build_tree_list (NULL_TREE, to_add);
|
||||
|
||||
add_decl_to_level (level, to_add);
|
||||
}
|
||||
|
||||
if (to_type == binding->type)
|
||||
to_type = NULL_TREE;
|
||||
|
||||
if (to_type)
|
||||
{
|
||||
gcc_checking_assert (TREE_CODE (to_type) == TYPE_DECL
|
||||
&& DECL_ARTIFICIAL (to_type));
|
||||
|
||||
tree type = TREE_TYPE (to_type);
|
||||
if (to_type != decl
|
||||
&& MAYBE_CLASS_TYPE_P (type) && warn_shadow
|
||||
&& (!DECL_IN_SYSTEM_HEADER (decl)
|
||||
|| !DECL_IN_SYSTEM_HEADER (to_type)))
|
||||
warning (OPT_Wshadow, "%q#D hides constructor for %q#T",
|
||||
decl, type);
|
||||
}
|
||||
|
||||
if (to_type)
|
||||
binding->type = to_type;
|
||||
binding->value = to_val;
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Map of identifiers to extern C functions (or LISTS thereof). */
|
||||
|
||||
static GTY(()) hash_map<lang_identifier *, tree> *extern_c_fns;
|
||||
@ -1690,338 +1873,146 @@ set_local_extern_decl_linkage (tree decl, bool shadowed)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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). IS_FRIEND is true if X is
|
||||
/* Record DECL 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). IS_FRIEND is true if DECL 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. */
|
||||
Returns either DECL or an old decl for the same name. If an old
|
||||
decl is returned, it may have been smashed to agree with what DECL
|
||||
says. */
|
||||
|
||||
static tree
|
||||
pushdecl_maybe_friend_1 (tree x, bool is_friend)
|
||||
do_pushdecl (tree decl, bool is_friend)
|
||||
{
|
||||
tree t;
|
||||
tree name;
|
||||
int need_new_binding;
|
||||
|
||||
if (x == error_mark_node)
|
||||
if (decl == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
need_new_binding = 1;
|
||||
if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl)
|
||||
set_decl_context_in_fn (current_function_decl, decl);
|
||||
|
||||
if (!DECL_TEMPLATE_PARM_P (x) && current_function_decl)
|
||||
set_decl_context_in_fn (current_function_decl, x);
|
||||
/* The binding level we will be pushing into. During local class
|
||||
pushing, we want to push to the containing scope. */
|
||||
cp_binding_level *level = current_binding_level;
|
||||
while (level->kind == sk_class)
|
||||
level = level->level_chain;
|
||||
|
||||
name = DECL_NAME (x);
|
||||
if (name)
|
||||
if (tree name = DECL_NAME (decl))
|
||||
{
|
||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
||||
name = TREE_OPERAND (name, 0);
|
||||
cxx_binding *binding = NULL;
|
||||
tree ns = NULL_TREE; /* Searched namespace. */
|
||||
tree old = NULL_TREE;
|
||||
|
||||
/* In case this decl was explicitly namespace-qualified, look it
|
||||
up in its namespace context. */
|
||||
if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
|
||||
t = get_namespace_binding (CP_DECL_CONTEXT (x), name);
|
||||
if (level->kind == sk_namespace)
|
||||
{
|
||||
/* We look in the decl's namespace for an existing
|
||||
declaration, even though we push into the current
|
||||
namespace. */
|
||||
ns = (DECL_NAMESPACE_SCOPE_P (decl)
|
||||
? CP_DECL_CONTEXT (decl) : current_namespace);
|
||||
/* Create the binding, if this is current namespace, because
|
||||
that's where we'll be pushing anyway. */
|
||||
binding = find_namespace_binding (ns, name, ns == current_namespace);
|
||||
}
|
||||
else
|
||||
t = lookup_name_innermost_nonclass_level (name);
|
||||
binding = find_local_binding (level, name);
|
||||
|
||||
if (current_function_decl && VAR_OR_FUNCTION_DECL_P (x)
|
||||
&& DECL_EXTERNAL (x))
|
||||
set_local_extern_decl_linkage (x, t != NULL_TREE);
|
||||
if (binding)
|
||||
old = binding->value;
|
||||
|
||||
/* If we are declaring a function, and the result of name-lookup
|
||||
was an OVERLOAD, look for an overloaded instance that is
|
||||
actually the same as the function we are declaring. (If
|
||||
there is one, we have to merge our declaration with the
|
||||
previous declaration.) */
|
||||
if (t && TREE_CODE (t) == OVERLOAD)
|
||||
if (current_function_decl && VAR_OR_FUNCTION_DECL_P (decl)
|
||||
&& DECL_EXTERNAL (decl))
|
||||
set_local_extern_decl_linkage (decl, old != NULL_TREE);
|
||||
|
||||
if (old == error_mark_node)
|
||||
old = NULL_TREE;
|
||||
|
||||
for (ovl_iterator iter (old); iter; ++iter)
|
||||
if (iter.using_p ())
|
||||
; /* Ignore using decls here. */
|
||||
else if (tree match = duplicate_decls (decl, *iter, is_friend))
|
||||
return match;
|
||||
|
||||
/* We are pushing a new decl. */
|
||||
|
||||
/* Skip a hidden builtin we failed to match already. */
|
||||
if (old && TREE_CODE (old) == FUNCTION_DECL
|
||||
&& DECL_ANTICIPATED (old)
|
||||
&& !DECL_HIDDEN_FRIEND_P (old))
|
||||
old = NULL_TREE;
|
||||
|
||||
check_template_shadow (decl);
|
||||
|
||||
if (DECL_DECLARES_FUNCTION_P (decl))
|
||||
{
|
||||
tree match;
|
||||
check_default_args (decl);
|
||||
|
||||
if (TREE_CODE (x) == FUNCTION_DECL)
|
||||
for (match = t; match; match = OVL_NEXT (match))
|
||||
{
|
||||
if (decls_match (OVL_CURRENT (match), x))
|
||||
break;
|
||||
}
|
||||
else
|
||||
/* Just choose one. */
|
||||
match = t;
|
||||
|
||||
if (match)
|
||||
t = OVL_CURRENT (match);
|
||||
else
|
||||
t = NULL_TREE;
|
||||
}
|
||||
|
||||
if (t && t != error_mark_node)
|
||||
{
|
||||
if (TREE_CODE (t) == PARM_DECL)
|
||||
if (is_friend)
|
||||
{
|
||||
/* Check for duplicate params. */
|
||||
tree d = duplicate_decls (x, t, is_friend);
|
||||
if (d)
|
||||
return d;
|
||||
}
|
||||
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|
||||
|| DECL_FUNCTION_TEMPLATE_P (x))
|
||||
&& is_overloaded_fn (t))
|
||||
/* Don't do anything just yet. */;
|
||||
else if (t == wchar_decl_node)
|
||||
{
|
||||
if (! DECL_IN_SYSTEM_HEADER (x))
|
||||
pedwarn (input_location, OPT_Wpedantic, "redeclaration of %<wchar_t%> as %qT",
|
||||
TREE_TYPE (x));
|
||||
|
||||
/* Throw away the redeclaration. */
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree olddecl = duplicate_decls (x, t, is_friend);
|
||||
|
||||
/* If the redeclaration failed, we can stop at this
|
||||
point. */
|
||||
if (olddecl == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (olddecl)
|
||||
{
|
||||
if (TREE_CODE (t) == TYPE_DECL)
|
||||
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
|
||||
|
||||
return t;
|
||||
}
|
||||
else if (DECL_MAIN_P (x) && TREE_CODE (t) == FUNCTION_DECL)
|
||||
{
|
||||
/* A redeclaration of main, but not a duplicate of the
|
||||
previous one.
|
||||
|
||||
[basic.start.main]
|
||||
|
||||
This function shall not be overloaded. */
|
||||
error ("invalid redeclaration of %q+D", t);
|
||||
error ("as %qD", x);
|
||||
/* We don't try to push this declaration since that
|
||||
causes a crash. */
|
||||
return x;
|
||||
}
|
||||
if (level->kind != sk_namespace)
|
||||
/* In a local class, a friend function declaration must
|
||||
find a matching decl in the innermost non-class scope.
|
||||
[class.friend/11] */
|
||||
error ("friend declaration %qD in local class without "
|
||||
"prior local declaration", decl);
|
||||
else if (!flag_friend_injection)
|
||||
/* Hide it from ordinary lookup. */
|
||||
DECL_ANTICIPATED (decl) = DECL_HIDDEN_FRIEND_P (decl) = true;
|
||||
}
|
||||
}
|
||||
|
||||
check_template_shadow (x);
|
||||
|
||||
/* If this is a function conjured up by the back end, massage it
|
||||
so it looks friendly. */
|
||||
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
|
||||
if (level->kind != sk_namespace)
|
||||
{
|
||||
retrofit_lang_decl (x);
|
||||
SET_DECL_LANGUAGE (x, lang_c);
|
||||
check_local_shadow (decl);
|
||||
|
||||
if (TREE_CODE (decl) == NAMESPACE_DECL)
|
||||
/* A local namespace alias. */
|
||||
set_identifier_type_value (name, NULL_TREE);
|
||||
|
||||
if (!binding)
|
||||
binding = create_local_binding (level, name);
|
||||
}
|
||||
else if (!binding)
|
||||
{
|
||||
ns = current_namespace;
|
||||
binding = find_namespace_binding (ns, name, true);
|
||||
}
|
||||
|
||||
t = x;
|
||||
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
|
||||
{
|
||||
t = push_overloaded_decl (x, PUSH_LOCAL, is_friend);
|
||||
if (!namespace_bindings_p ())
|
||||
/* We do not need to create a binding for this name;
|
||||
push_overloaded_decl will have already done so if
|
||||
necessary. */
|
||||
need_new_binding = 0;
|
||||
}
|
||||
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
|
||||
{
|
||||
t = push_overloaded_decl (x, PUSH_GLOBAL, is_friend);
|
||||
if (t == x)
|
||||
add_decl_to_level (NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)), x);
|
||||
}
|
||||
old = update_binding (level, binding, old, decl, is_friend);
|
||||
|
||||
if (DECL_DECLARES_FUNCTION_P (t))
|
||||
if (old != decl)
|
||||
/* An existing decl matched, use it. */
|
||||
decl = old;
|
||||
else if (TREE_CODE (decl) == TYPE_DECL)
|
||||
{
|
||||
check_default_args (t);
|
||||
tree type = TREE_TYPE (decl);
|
||||
|
||||
if (is_friend && t == x && !flag_friend_injection)
|
||||
if (type != error_mark_node)
|
||||
{
|
||||
/* This is a new friend declaration of a function or a
|
||||
function template, so hide it from ordinary function
|
||||
lookup. */
|
||||
DECL_ANTICIPATED (t) = 1;
|
||||
DECL_HIDDEN_FRIEND_P (t) = 1;
|
||||
if (TYPE_NAME (type) != decl)
|
||||
set_underlying_type (decl);
|
||||
|
||||
if (!ns)
|
||||
set_identifier_type_value_with_scope (name, decl, level);
|
||||
else
|
||||
SET_IDENTIFIER_TYPE_VALUE (name, global_type_node);
|
||||
}
|
||||
}
|
||||
|
||||
if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
|
||||
return t;
|
||||
|
||||
/* If declaring a type as a typedef, copy the type (unless we're
|
||||
at line 0), and install this TYPE_DECL as the new type's typedef
|
||||
name. See the extensive comment of set_underlying_type (). */
|
||||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
{
|
||||
tree type = TREE_TYPE (x);
|
||||
|
||||
if (DECL_IS_BUILTIN (x)
|
||||
|| (TREE_TYPE (x) != 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))))
|
||||
set_underlying_type (x);
|
||||
|
||||
if (type != error_mark_node
|
||||
&& TYPE_IDENTIFIER (type))
|
||||
set_identifier_type_value (DECL_NAME (x), x);
|
||||
|
||||
/* If this is a locally defined typedef in a function that
|
||||
is not a template instantation, record it to implement
|
||||
-Wunused-local-typedefs. */
|
||||
if (!instantiating_current_function_p ())
|
||||
record_locally_defined_typedef (x);
|
||||
record_locally_defined_typedef (decl);
|
||||
}
|
||||
|
||||
/* Multiple external decls of the same identifier ought to match.
|
||||
|
||||
We get warnings about inline functions where they are defined.
|
||||
We get warnings about other functions from push_overloaded_decl.
|
||||
|
||||
Avoid duplicate warnings where they are used. */
|
||||
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
|
||||
{
|
||||
tree decl;
|
||||
|
||||
decl = get_namespace_binding (current_namespace, name);
|
||||
if (decl && TREE_CODE (decl) == OVERLOAD)
|
||||
decl = OVL_FUNCTION (decl);
|
||||
|
||||
if (decl && decl != error_mark_node
|
||||
&& (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
|
||||
/* If different sort of thing, we already gave an error. */
|
||||
&& TREE_CODE (decl) == TREE_CODE (x)
|
||||
&& !comptypes (TREE_TYPE (x), TREE_TYPE (decl),
|
||||
COMPARE_REDECLARATION))
|
||||
{
|
||||
if (permerror (input_location, "type mismatch with previous "
|
||||
"external decl of %q#D", x))
|
||||
inform (DECL_SOURCE_LOCATION (decl),
|
||||
"previous external decl of %q#D", decl);
|
||||
}
|
||||
}
|
||||
|
||||
/* This name is new in its binding level.
|
||||
Install the new declaration and return it. */
|
||||
if (namespace_bindings_p ())
|
||||
{
|
||||
/* Install a global value. */
|
||||
|
||||
/* If the first global decl has external linkage,
|
||||
warn if we later see static one. */
|
||||
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
|
||||
|| VAR_P (x)
|
||||
|| TREE_CODE (x) == NAMESPACE_DECL
|
||||
|| TREE_CODE (x) == CONST_DECL
|
||||
|| TREE_CODE (x) == TEMPLATE_DECL))
|
||||
set_namespace_binding (current_namespace, name, x);
|
||||
|
||||
/* If new decl is `static' and an `extern' was seen previously,
|
||||
warn about it. */
|
||||
if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
|
||||
warn_extern_redeclared_static (x, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Here to install a non-global value. */
|
||||
tree oldglobal = get_namespace_binding (current_namespace, name);
|
||||
tree oldlocal = NULL_TREE;
|
||||
cxx_binding *oldbinding = outer_binding (name, NULL, true);
|
||||
if (oldbinding)
|
||||
oldlocal = oldbinding->value;
|
||||
|
||||
check_local_shadow (x);
|
||||
|
||||
if (need_new_binding)
|
||||
{
|
||||
push_local_binding (name, x, false);
|
||||
/* Because push_local_binding will hook X on to the
|
||||
current_binding_level's name list, we don't want to
|
||||
do that again below. */
|
||||
need_new_binding = 0;
|
||||
}
|
||||
|
||||
/* If this is a TYPE_DECL, push it into the type value slot. */
|
||||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
set_identifier_type_value (name, x);
|
||||
|
||||
/* Clear out any TYPE_DECL shadowed by a namespace so that
|
||||
we won't think this is a type. The C struct hack doesn't
|
||||
go through namespaces. */
|
||||
if (TREE_CODE (x) == NAMESPACE_DECL)
|
||||
set_identifier_type_value (name, NULL_TREE);
|
||||
|
||||
if (oldlocal)
|
||||
{
|
||||
tree d = oldlocal;
|
||||
|
||||
while (oldlocal
|
||||
&& VAR_P (oldlocal)
|
||||
&& DECL_DEAD_FOR_LOCAL (oldlocal))
|
||||
oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
|
||||
|
||||
if (oldlocal == NULL_TREE)
|
||||
oldlocal
|
||||
= get_namespace_binding (current_namespace, DECL_NAME (d));
|
||||
}
|
||||
|
||||
/* If this is an extern function declaration, see if we
|
||||
have a global definition or declaration for the function. */
|
||||
if (oldlocal == NULL_TREE
|
||||
&& DECL_EXTERNAL (x)
|
||||
&& oldglobal != NULL_TREE
|
||||
&& TREE_CODE (x) == FUNCTION_DECL
|
||||
&& TREE_CODE (oldglobal) == FUNCTION_DECL)
|
||||
{
|
||||
/* We have one. Their types must agree. */
|
||||
if (decls_match (x, oldglobal))
|
||||
/* OK */;
|
||||
else
|
||||
{
|
||||
warning (0, "extern declaration of %q#D doesn%'t match", x);
|
||||
warning_at (DECL_SOURCE_LOCATION (oldglobal), 0,
|
||||
"global declaration %q#D", oldglobal);
|
||||
}
|
||||
}
|
||||
/* If we have a local external declaration,
|
||||
and no file-scope declaration has yet been seen,
|
||||
then if we later have a file-scope decl it must not be static. */
|
||||
if (oldlocal == NULL_TREE
|
||||
&& oldglobal == NULL_TREE
|
||||
&& DECL_EXTERNAL (x)
|
||||
&& TREE_PUBLIC (x))
|
||||
TREE_PUBLIC (name) = 1;
|
||||
}
|
||||
|
||||
if (VAR_P (x))
|
||||
maybe_register_incomplete_var (x);
|
||||
if (TREE_CODE (x) == FUNCTION_DECL && DECL_EXTERN_C_P (x))
|
||||
/* We need to check and register the fn now. */
|
||||
check_extern_c_conflict (x);
|
||||
else if (VAR_P (decl))
|
||||
maybe_register_incomplete_var (decl);
|
||||
else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_EXTERN_C_P (decl))
|
||||
check_extern_c_conflict (decl);
|
||||
}
|
||||
else
|
||||
add_decl_to_level (level, decl);
|
||||
|
||||
if (need_new_binding)
|
||||
add_decl_to_level (DECL_NAMESPACE_SCOPE_P (x)
|
||||
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
|
||||
: current_binding_level, x);
|
||||
|
||||
return x;
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Record a decl-node X as belonging to the current lexical scope.
|
||||
@ -2032,7 +2023,7 @@ pushdecl (tree x, bool is_friend)
|
||||
{
|
||||
tree ret;
|
||||
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
|
||||
ret = pushdecl_maybe_friend_1 (x, is_friend);
|
||||
ret = do_pushdecl (x, is_friend);
|
||||
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
|
||||
return ret;
|
||||
}
|
||||
@ -2924,151 +2915,6 @@ pushdecl_outermost_localscope (tree x)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* DECL is a FUNCTION_DECL for a non-member function, which may have
|
||||
other definitions already in place. We get around this by making
|
||||
the value of the identifier point to a list of all the things that
|
||||
want to be referenced by that name. It is then up to the users of
|
||||
that name to decide what to do with that list.
|
||||
|
||||
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its
|
||||
DECL_TEMPLATE_RESULT. It is dealt with the same way.
|
||||
|
||||
FLAGS is a bitwise-or of the following values:
|
||||
PUSH_LOCAL: Bind DECL in the current scope, rather than at
|
||||
namespace scope.
|
||||
PUSH_USING: DECL is being pushed as the result of a using
|
||||
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_1 (tree decl, int flags, bool is_friend)
|
||||
{
|
||||
tree name = DECL_NAME (decl);
|
||||
tree old;
|
||||
tree new_binding;
|
||||
int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
|
||||
|
||||
if (doing_global)
|
||||
old = get_namespace_binding (CP_DECL_CONTEXT (decl), name);
|
||||
else
|
||||
old = lookup_name_innermost_nonclass_level (name);
|
||||
|
||||
if (old)
|
||||
{
|
||||
if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
|
||||
{
|
||||
tree t = TREE_TYPE (old);
|
||||
if (MAYBE_CLASS_TYPE_P (t) && warn_shadow
|
||||
&& (! DECL_IN_SYSTEM_HEADER (decl)
|
||||
|| ! DECL_IN_SYSTEM_HEADER (old)))
|
||||
warning (OPT_Wshadow, "%q#D hides constructor for %q#T", decl, t);
|
||||
old = NULL_TREE;
|
||||
}
|
||||
else if (is_overloaded_fn (old))
|
||||
{
|
||||
tree tmp;
|
||||
|
||||
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
|
||||
{
|
||||
tree fn = OVL_CURRENT (tmp);
|
||||
tree dup;
|
||||
|
||||
if (TREE_CODE (tmp) == OVERLOAD && OVL_USING_P (tmp)
|
||||
&& !(flags & PUSH_USING)
|
||||
&& matching_fn_p (fn, decl)
|
||||
&& ! decls_match (fn, decl))
|
||||
diagnose_name_conflict (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)
|
||||
return 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
|
||||
{
|
||||
error ("previous non-function declaration %q+#D", old);
|
||||
error ("conflicts with function declaration %q#D", decl);
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
new_binding = ovl_insert (decl, old, flags & PUSH_USING);
|
||||
|
||||
if (doing_global)
|
||||
set_namespace_binding (current_namespace, name, new_binding);
|
||||
else
|
||||
{
|
||||
/* We only create an OVERLOAD if there was a previous binding at
|
||||
this level, or if decl is a template. In the former case, we
|
||||
need to remove the old binding and replace it with the new
|
||||
binding. We must also run through the NAMES on the binding
|
||||
level where the name was bound to update the chain. */
|
||||
|
||||
if (TREE_CODE (new_binding) == OVERLOAD && old)
|
||||
{
|
||||
tree *d;
|
||||
|
||||
for (d = &IDENTIFIER_BINDING (name)->scope->names;
|
||||
*d;
|
||||
d = &TREE_CHAIN (*d))
|
||||
if (*d == old
|
||||
|| (TREE_CODE (*d) == TREE_LIST
|
||||
&& TREE_VALUE (*d) == old))
|
||||
{
|
||||
if (TREE_CODE (*d) == TREE_LIST)
|
||||
/* Just replace the old binding with the new. */
|
||||
TREE_VALUE (*d) = new_binding;
|
||||
else
|
||||
/* Build a TREE_LIST to wrap the OVERLOAD. */
|
||||
*d = tree_cons (NULL_TREE, new_binding,
|
||||
TREE_CHAIN (*d));
|
||||
|
||||
/* And update the cxx_binding node. */
|
||||
IDENTIFIER_BINDING (name)->value = new_binding;
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* We should always find a previous binding in this case. */
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Install the new binding. */
|
||||
push_local_binding (name, new_binding, flags);
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Wrapper for push_overloaded_decl_1. */
|
||||
|
||||
static tree
|
||||
push_overloaded_decl (tree decl, int flags, bool is_friend)
|
||||
{
|
||||
tree ret;
|
||||
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
|
||||
ret = push_overloaded_decl_1 (decl, flags, is_friend);
|
||||
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check a non-member using-declaration. Return the name and scope
|
||||
being used, and the USING_DECL, or NULL_TREE on failure. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user