aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-05-23 21:15:48 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2017-05-23 21:15:48 +0000
commit3a9cc6853ad1a1889c98c3ae6ab7628d09ca9d8f (patch)
treeb4b066822cc13a858257666c679cd732a8234af8 /gcc
parentf0c1ade45a7488e97c8d6c3aababec5c9d04f609 (diff)
downloadgcc-3a9cc6853ad1a1889c98c3ae6ab7628d09ca9d8f.zip
gcc-3a9cc6853ad1a1889c98c3ae6ab7628d09ca9d8f.tar.gz
gcc-3a9cc6853ad1a1889c98c3ae6ab7628d09ca9d8f.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/name-lookup.c718
3 files changed, 292 insertions, 444 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2f15c9b..4a72b65 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 98ef023..2ed9e5a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1202421..89d4e2a 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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);
- else
- t = lookup_name_innermost_nonclass_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 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 (level->kind == sk_namespace)
{
- tree match;
-
- 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;
+ /* 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
+ binding = find_local_binding (level, name);
- if (t && t != error_mark_node)
- {
- if (TREE_CODE (t) == PARM_DECL)
- {
- /* 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));
+ if (binding)
+ old = binding->value;
- 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.
+ if (current_function_decl && VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_EXTERNAL (decl))
+ set_local_extern_decl_linkage (decl, old != NULL_TREE);
- [basic.start.main]
+ if (old == error_mark_node)
+ old = NULL_TREE;
- 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;
- }
- }
- }
+ 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;
- check_template_shadow (x);
+ /* We are pushing a new decl. */
- /* 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);
- SET_DECL_LANGUAGE (x, lang_c);
- }
+ /* 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;
- 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);
- }
+ check_template_shadow (decl);
- if (DECL_DECLARES_FUNCTION_P (t))
+ if (DECL_DECLARES_FUNCTION_P (decl))
{
- check_default_args (t);
+ check_default_args (decl);
- if (is_friend && t == x && !flag_friend_injection)
+ if (is_friend)
{
- /* 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 (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;
}
}
- 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)
+ if (level->kind != sk_namespace)
{
- 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);
- }
-
- /* Multiple external decls of the same identifier ought to match.
+ check_local_shadow (decl);
- We get warnings about inline functions where they are defined.
- We get warnings about other functions from push_overloaded_decl.
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ /* A local namespace alias. */
+ set_identifier_type_value (name, NULL_TREE);
- 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);
- }
+ if (!binding)
+ binding = create_local_binding (level, name);
}
-
- /* This name is new in its binding level.
- Install the new declaration and return it. */
- if (namespace_bindings_p ())
+ else if (!binding)
{
- /* 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);
+ ns = current_namespace;
+ binding = find_namespace_binding (ns, name, true);
}
- 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);
+ old = update_binding (level, binding, old, decl, is_friend);
- /* 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 (old != decl)
+ /* An existing decl matched, use it. */
+ decl = old;
+ else if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ tree type = TREE_TYPE (decl);
- if (oldlocal)
+ if (type != error_mark_node)
{
- 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 (TYPE_NAME (type) != decl)
+ set_underlying_type (decl);
- /* 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 */;
+ if (!ns)
+ set_identifier_type_value_with_scope (name, decl, level);
else
- {
- warning (0, "extern declaration of %q#D doesn%'t match", x);
- warning_at (DECL_SOURCE_LOCATION (oldglobal), 0,
- "global declaration %q#D", oldglobal);
- }
+ SET_IDENTIFIER_TYPE_VALUE (name, global_type_node);
}
- /* 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);
+ /* 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 (decl);
+ }
+ 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. */