mirror of git://gcc.gnu.org/git/gcc.git
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>
|
2017-05-23 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
PR c++/80396 - built-in for make_integer_sequence.
|
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
|
will be identical to
|
||||||
COMPARE_STRICT. */
|
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. */
|
/* Used with start function. */
|
||||||
#define SF_DEFAULT 0 /* No flags. */
|
#define SF_DEFAULT 0 /* No flags. */
|
||||||
#define SF_PRE_PARSED 1 /* The function declaration has
|
#define SF_PRE_PARSED 1 /* The function declaration has
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ struct scope_binding {
|
||||||
};
|
};
|
||||||
#define EMPTY_SCOPE_BINDING { NULL_TREE, NULL_TREE }
|
#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,
|
static bool lookup_using_namespace (tree, struct scope_binding *, tree,
|
||||||
tree, int);
|
tree, int);
|
||||||
static bool qualified_lookup_using_namespace (tree, tree,
|
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 tree push_using_directive (tree);
|
||||||
static void diagnose_name_conflict (tree, 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,
|
/* Find the binding for NAME in namespace NS. If CREATE_P is true,
|
||||||
make an empty binding if there wasn't one. */
|
make an empty binding if there wasn't one. */
|
||||||
|
|
||||||
|
|
@ -1281,6 +1297,173 @@ matching_fn_p (tree one, tree two)
|
||||||
return true;
|
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). */
|
/* Map of identifiers to extern C functions (or LISTS thereof). */
|
||||||
|
|
||||||
static GTY(()) hash_map<lang_identifier *, tree> *extern_c_fns;
|
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.
|
/* Record DECL as belonging to the current lexical scope. Check for
|
||||||
Check for errors (such as an incompatible declaration for the same
|
errors (such as an incompatible declaration for the same name
|
||||||
name already seen in the same scope). IS_FRIEND is true if X is
|
already seen in the same scope). IS_FRIEND is true if DECL is
|
||||||
declared as a friend.
|
declared as a friend.
|
||||||
|
|
||||||
Returns either X or an old decl for the same name.
|
Returns either DECL or an old decl for the same name. If an old
|
||||||
If an old decl is returned, it may have been smashed
|
decl is returned, it may have been smashed to agree with what DECL
|
||||||
to agree with what X says. */
|
says. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
pushdecl_maybe_friend_1 (tree x, bool is_friend)
|
do_pushdecl (tree decl, bool is_friend)
|
||||||
{
|
{
|
||||||
tree t;
|
if (decl == error_mark_node)
|
||||||
tree name;
|
|
||||||
int need_new_binding;
|
|
||||||
|
|
||||||
if (x == error_mark_node)
|
|
||||||
return 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)
|
/* The binding level we will be pushing into. During local class
|
||||||
set_decl_context_in_fn (current_function_decl, x);
|
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 (tree name = DECL_NAME (decl))
|
||||||
if (name)
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
cxx_binding *binding = NULL;
|
||||||
name = TREE_OPERAND (name, 0);
|
tree ns = NULL_TREE; /* Searched namespace. */
|
||||||
|
tree old = NULL_TREE;
|
||||||
|
|
||||||
/* In case this decl was explicitly namespace-qualified, look it
|
if (level->kind == sk_namespace)
|
||||||
up in its namespace context. */
|
{
|
||||||
if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
|
/* We look in the decl's namespace for an existing
|
||||||
t = get_namespace_binding (CP_DECL_CONTEXT (x), name);
|
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
|
else
|
||||||
t = lookup_name_innermost_nonclass_level (name);
|
binding = find_local_binding (level, name);
|
||||||
|
|
||||||
if (current_function_decl && VAR_OR_FUNCTION_DECL_P (x)
|
if (binding)
|
||||||
&& DECL_EXTERNAL (x))
|
old = binding->value;
|
||||||
set_local_extern_decl_linkage (x, t != NULL_TREE);
|
|
||||||
|
|
||||||
/* If we are declaring a function, and the result of name-lookup
|
if (current_function_decl && VAR_OR_FUNCTION_DECL_P (decl)
|
||||||
was an OVERLOAD, look for an overloaded instance that is
|
&& DECL_EXTERNAL (decl))
|
||||||
actually the same as the function we are declaring. (If
|
set_local_extern_decl_linkage (decl, old != NULL_TREE);
|
||||||
there is one, we have to merge our declaration with the
|
|
||||||
previous declaration.) */
|
if (old == error_mark_node)
|
||||||
if (t && TREE_CODE (t) == OVERLOAD)
|
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)
|
if (is_friend)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
/* Check for duplicate params. */
|
if (level->kind != sk_namespace)
|
||||||
tree d = duplicate_decls (x, t, is_friend);
|
/* In a local class, a friend function declaration must
|
||||||
if (d)
|
find a matching decl in the innermost non-class scope.
|
||||||
return d;
|
[class.friend/11] */
|
||||||
}
|
error ("friend declaration %qD in local class without "
|
||||||
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|
"prior local declaration", decl);
|
||||||
|| DECL_FUNCTION_TEMPLATE_P (x))
|
else if (!flag_friend_injection)
|
||||||
&& is_overloaded_fn (t))
|
/* Hide it from ordinary lookup. */
|
||||||
/* Don't do anything just yet. */;
|
DECL_ANTICIPATED (decl) = DECL_HIDDEN_FRIEND_P (decl) = true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_template_shadow (x);
|
if (level->kind != sk_namespace)
|
||||||
|
|
||||||
/* 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))
|
|
||||||
{
|
{
|
||||||
retrofit_lang_decl (x);
|
check_local_shadow (decl);
|
||||||
SET_DECL_LANGUAGE (x, lang_c);
|
|
||||||
|
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;
|
old = update_binding (level, binding, old, decl, is_friend);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
if (TYPE_NAME (type) != decl)
|
||||||
function template, so hide it from ordinary function
|
set_underlying_type (decl);
|
||||||
lookup. */
|
|
||||||
DECL_ANTICIPATED (t) = 1;
|
if (!ns)
|
||||||
DECL_HIDDEN_FRIEND_P (t) = 1;
|
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
|
/* If this is a locally defined typedef in a function that
|
||||||
is not a template instantation, record it to implement
|
is not a template instantation, record it to implement
|
||||||
-Wunused-local-typedefs. */
|
-Wunused-local-typedefs. */
|
||||||
if (!instantiating_current_function_p ())
|
if (!instantiating_current_function_p ())
|
||||||
record_locally_defined_typedef (x);
|
record_locally_defined_typedef (decl);
|
||||||
}
|
}
|
||||||
|
else if (VAR_P (decl))
|
||||||
/* Multiple external decls of the same identifier ought to match.
|
maybe_register_incomplete_var (decl);
|
||||||
|
else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_EXTERN_C_P (decl))
|
||||||
We get warnings about inline functions where they are defined.
|
check_extern_c_conflict (decl);
|
||||||
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
|
||||||
|
add_decl_to_level (level, decl);
|
||||||
|
|
||||||
if (need_new_binding)
|
return decl;
|
||||||
add_decl_to_level (DECL_NAMESPACE_SCOPE_P (x)
|
|
||||||
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
|
|
||||||
: current_binding_level, x);
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record a decl-node X as belonging to the current lexical scope.
|
/* Record a decl-node X as belonging to the current lexical scope.
|
||||||
|
|
@ -2032,7 +2023,7 @@ pushdecl (tree x, bool is_friend)
|
||||||
{
|
{
|
||||||
tree ret;
|
tree ret;
|
||||||
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
|
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);
|
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -2924,151 +2915,6 @@ pushdecl_outermost_localscope (tree x)
|
||||||
return ret;
|
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
|
/* Check a non-member using-declaration. Return the name and scope
|
||||||
being used, and the USING_DECL, or NULL_TREE on failure. */
|
being used, and the USING_DECL, or NULL_TREE on failure. */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue