[gcc/devel/c++-modules] c++: Adjust pushdecl/duplicate_decls API (merge c74e6f7cfd7)
Nathan Sidwell
nathan@gcc.gnu.org
Wed Sep 30 20:27:11 GMT 2020
https://gcc.gnu.org/g:23841c9ab8477e0350afbe8c6723fd09ef64a700
commit 23841c9ab8477e0350afbe8c6723fd09ef64a700
Author: Nathan Sidwell <nathan@acm.org>
Date: Wed Sep 30 10:40:50 2020 -0700
c++: Adjust pushdecl/duplicate_decls API (merge c74e6f7cfd7)
Diff:
---
ChangeLog.modules | 3 +++
gcc/cp/cp-tree.h | 3 ++-
gcc/cp/decl.c | 66 +++++++++++++++++++++++++++----------------------
gcc/cp/friend.c | 8 +++---
gcc/cp/module.cc | 19 +++++++++++----
gcc/cp/name-lookup.c | 69 ++++++++++++++++++++++++++++++++--------------------
gcc/cp/name-lookup.h | 6 ++---
gcc/cp/pt.c | 12 ++++-----
gcc/cp/tree.c | 6 +++--
9 files changed, 116 insertions(+), 76 deletions(-)
diff --git a/ChangeLog.modules b/ChangeLog.modules
index 8f18657793f..377d976b9a5 100644
--- a/ChangeLog.modules
+++ b/ChangeLog.modules
@@ -1,5 +1,8 @@
2020-09-30 Nathan Sidwell <nathan@acm.org>
+ Merge trunk c74e6f7cfd7
+ c++: Adjust pushdecl/duplicate_decls API
+
gcc/cp/
* tree.h (ovl_insert): Make usingness unsigned.
* tree.c (ovl_insert): Make usingness unsigned, change semantics.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index eacc459da92..501ee64af88 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6656,7 +6656,8 @@ extern void determine_local_discriminator (tree);
extern int decls_match (tree, tree, bool = true);
extern bool maybe_version_functions (tree, tree, bool);
extern tree duplicate_decls (tree, tree,
- bool is_friend = false);
+ bool hiding = false,
+ bool was_hidden = false);
extern tree declare_local_label (tree);
extern tree define_label (location_t, tree);
extern void check_goto (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1bb539a24f0..d4f1e8b3691 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1341,17 +1341,16 @@ check_redeclaration_no_default_args (tree decl)
static void
check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl,
- bool olddecl_hidden_friend_p)
+ bool olddecl_hidden_p)
{
- if (!olddecl_hidden_friend_p && !DECL_FRIEND_P (newdecl))
+ if (!olddecl_hidden_p && !DECL_FRIEND_P (newdecl))
return;
- tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
- tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
-
- for (; t1 && t1 != void_list_node;
+ for (tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl),
+ t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
+ t1 && t1 != void_list_node;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
- if ((olddecl_hidden_friend_p && TREE_PURPOSE (t1))
+ if ((olddecl_hidden_p && TREE_PURPOSE (t1))
|| (DECL_FRIEND_P (newdecl) && TREE_PURPOSE (t2)))
{
auto_diagnostic_group d;
@@ -1435,10 +1434,14 @@ duplicate_function_template_decls (tree newdecl, tree olddecl)
If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
returned.
- NEWDECL_IS_FRIEND is true if NEWDECL was declared as a friend. */
+ HIDING is true if the new decl is being hidden. WAS_HIDDEN is true
+ if the old decl was hidden.
+
+ Hidden decls can be anticipated builtins, injected friends, or
+ (coming soon) injected from a local-extern decl. */
tree
-duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
+duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
@@ -1510,7 +1513,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
/* Avoid warnings redeclaring built-ins which have not been
explicitly declared. */
- if (DECL_ANTICIPATED (olddecl))
+ if (was_hidden)
{
tree t1, t2;
@@ -1550,7 +1553,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
types_match = decls_match (newdecl, olddecl);
if (types_match)
return duplicate_decls (newdecl, olddecl,
- newdecl_is_friend);
+ hiding, was_hidden);
TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs;
}
goto next_arg;
@@ -1985,7 +1988,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
declaration of the function or function template in the
translation unit." */
check_no_redeclaration_friend_default_args
- (olddecl, newdecl, DECL_HIDDEN_FRIEND_P (olddecl));
+ (olddecl, newdecl, was_hidden);
}
}
}
@@ -2008,7 +2011,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (modules_p ()
&& TREE_CODE (CP_DECL_CONTEXT (olddecl)) == NAMESPACE_DECL
&& TREE_CODE (olddecl) != NAMESPACE_DECL
- && !newdecl_is_friend)
+ && !hiding)
{
if (DECL_ARTIFICIAL (olddecl))
{
@@ -2112,8 +2115,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
- /* Don't warn about friends, let add_friend take care of it. */
- && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl))
+ /* Don't warn if at least one is/was hidden. */
+ && !(hiding || was_hidden)
/* Don't warn about declaration followed by specialization. */
&& (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| DECL_TEMPLATE_SPECIALIZATION (olddecl)))
@@ -2171,11 +2174,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (DECL_DECLARES_FUNCTION_P (olddecl))
{
- olddecl_friend = DECL_FRIEND_P (olddecl);
- olddecl_hidden_friend = DECL_HIDDEN_FRIEND_P (olddecl);
- hidden_friend = (DECL_ANTICIPATED (olddecl)
- && DECL_HIDDEN_FRIEND_P (olddecl)
- && newdecl_is_friend);
+ olddecl_friend = DECL_FRIEND_P (STRIP_TEMPLATE (olddecl));
+ olddecl_hidden_friend = olddecl_friend && was_hidden;
+ hidden_friend = olddecl_hidden_friend && hiding;
if (!hidden_friend)
{
DECL_ANTICIPATED (olddecl) = 0;
@@ -4786,16 +4787,23 @@ cxx_builtin_function (tree decl)
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
+ bool hiding = false;
if (name[0] != '_' || name[1] != '_')
- /* In the user's namespace, it must be declared before use. */
- DECL_ANTICIPATED (decl) = 1;
+ {
+ /* In the user's namespace, it must be declared before use. */
+ DECL_ANTICIPATED (decl) = 1;
+ hiding = true;
+ }
else if (IDENTIFIER_LENGTH (id) > strlen ("___chk")
&& 0 != strncmp (name + 2, "builtin_", strlen ("builtin_"))
&& 0 == memcmp (name + IDENTIFIER_LENGTH (id) - strlen ("_chk"),
"_chk", strlen ("_chk") + 1))
- /* Treat __*_chk fortification functions as anticipated as well,
- unless they are __builtin_*_chk. */
- DECL_ANTICIPATED (decl) = 1;
+ {
+ /* Treat __*_chk fortification functions as anticipated as well,
+ unless they are __builtin_*_chk. */
+ DECL_ANTICIPATED (decl) = 1;
+ hiding = true;
+ }
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
@@ -4805,12 +4813,12 @@ cxx_builtin_function (tree decl)
push_nested_namespace (std_node);
DECL_CONTEXT (std_decl) = FROB_CONTEXT (std_node);
- pushdecl (std_decl);
+ pushdecl (std_decl, hiding);
pop_nested_namespace (std_node);
}
- DECL_CONTEXT (decl) = FROB_CONTEXT (global_namespace);
- decl = pushdecl (decl);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+ decl = pushdecl (decl, hiding);
return decl;
}
@@ -9985,7 +9993,7 @@ grokfndecl (tree ctype,
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
pushed_scope = push_scope (ctype);
- ok = duplicate_decls (decl, old_decl, friendp);
+ ok = duplicate_decls (decl, old_decl);
if (pushed_scope)
pop_scope (pushed_scope);
if (!ok)
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index e9802b9e75c..f1e3d38b00d 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -611,8 +611,8 @@ do_friend (tree ctype, tree declarator, tree decl,
if (! DECL_USE_TEMPLATE (decl))
{
/* We must check whether the decl refers to template
- arguments before push_template_decl_real adds a
- reference to the containing template class. */
+ arguments before push_template_decl adds a reference to
+ the containing template class. */
int warn = (warn_nontemplate_friend
&& ! funcdef_flag && ! is_friend_template
&& current_template_parms
@@ -627,7 +627,7 @@ do_friend (tree ctype, tree declarator, tree decl,
decl = push_template_decl (decl, /*is_friend=*/true);
else if (current_function_decl)
/* pushdecl will check there's a local decl already. */
- decl = pushdecl (decl, /*is_friend=*/true);
+ decl = pushdecl (decl, /*hiding=*/true);
else
{
/* We can't use pushdecl, as we might be in a template
@@ -637,7 +637,7 @@ do_friend (tree ctype, tree declarator, tree decl,
tree ns = decl_namespace_context (decl);
push_nested_namespace (ns);
- decl = pushdecl_namespace_level (decl, /*is_friend=*/true);
+ decl = pushdecl_namespace_level (decl, /*hiding=*/true);
pop_nested_namespace (ns);
}
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 3316f9396e1..639ba1363a6 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -10890,11 +10890,20 @@ trees_in::is_matching_decl (tree existing, tree decl)
// FIXME: Might be template specialization from a module, not
// necessarily global module
mismatch:
- error_at (DECL_SOURCE_LOCATION (decl),
- "conflicting global module declaration %#qD", decl);
- inform (DECL_SOURCE_LOCATION (existing),
- "existing declaration %#qD", existing);
- return false;
+ if (DECL_IS_BUILTIN (existing))
+ // FIXME: it'd be nice if we had a way of determining
+ // whether this builtin had already met a proper decl. For
+ // now just copy the type. Perhaps we should update
+ // SOURCE_LOCATION in those cases?
+ TREE_TYPE (existing) = TREE_TYPE (decl);
+ else
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "conflicting global module declaration %#qD", decl);
+ inform (DECL_SOURCE_LOCATION (existing),
+ "existing declaration %#qD", existing);
+ return false;
+ }
}
if (DECL_IS_BUILTIN (existing) && DECL_ANTICIPATED (existing))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 0cac59d4a0d..ab31b191545 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2822,7 +2822,7 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
&& DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval)
&& !DECL_CLASS_SCOPE_P (target_decl))
{
- duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
+ duplicate_decls (decl, binding->value);
ok = false;
}
else if (TREE_CODE (decl) == NAMESPACE_DECL
@@ -2944,7 +2944,7 @@ matching_fn_p (tree one, tree two)
static tree
update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
- tree old, tree decl, bool is_friend)
+ tree old, tree decl, bool hiding = false)
{
tree to_val = decl;
tree old_type = slot ? MAYBE_STAT_TYPE (*slot) : binding->type;
@@ -3001,13 +3001,14 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
if (iter.using_p () && matching_fn_p (fn, decl))
{
+ gcc_checking_assert (!iter.hidden_p ());
/* 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))
+ if (tree match = duplicate_decls (decl, fn, hiding))
return match;
else
/* FIXME: To preserve existing error behavior, we
@@ -3059,7 +3060,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
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))
+ else if (tree match = duplicate_decls (decl, old))
return match;
else
goto conflict;
@@ -3767,12 +3768,12 @@ check_module_override (tree decl, tree mvec, bool is_friend,
says. */
static tree
-do_pushdecl (tree decl, bool is_friend)
+do_pushdecl (tree decl, bool hiding)
{
if (decl == error_mark_node)
return error_mark_node;
- if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl && !is_friend)
+ if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl && !hiding)
set_decl_context_in_fn (current_function_decl, decl);
/* The binding level we will be pushing into. During local class
@@ -3793,6 +3794,14 @@ do_pushdecl (tree decl, bool is_friend)
tree *mslot = NULL; /* Current module slot in namespace. */
tree old = NULL_TREE;
+ if (!hiding)
+ /* We should never unknownly push an anticipated decl. */
+ gcc_checking_assert (!((TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == TEMPLATE_DECL)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_ANTICIPATED (decl)));
+
if (level->kind == sk_namespace)
{
/* We look in the decl's namespace for an existing
@@ -3828,7 +3837,8 @@ do_pushdecl (tree decl, bool is_friend)
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))
+ else if (tree match
+ = duplicate_decls (decl, *iter, hiding, iter.hidden_p ()))
{
if (match == error_mark_node)
;
@@ -3836,7 +3846,7 @@ do_pushdecl (tree decl, bool is_friend)
/* The IDENTIFIER will have the type referring to the
now-smashed TYPE_DECL, because ...? Reset it. */
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (match));
- else if (iter.hidden_p () && !DECL_HIDDEN_P (match))
+ else if (iter.hidden_p () && !hiding)
{
/* Unhiding a previously hidden decl. */
tree head = iter.reveal_node (old);
@@ -3862,7 +3872,7 @@ do_pushdecl (tree decl, bool is_friend)
/* Check for redeclaring an import. */
if (slot && *slot && TREE_CODE (*slot) == MODULE_VECTOR)
if (tree match
- = check_module_override (decl, *slot, is_friend, ns, name))
+ = check_module_override (decl, *slot, hiding, ns, name))
{
if (match == error_mark_node)
return match;
@@ -3870,7 +3880,7 @@ do_pushdecl (tree decl, bool is_friend)
/* We found a decl in an interface, push it into this
binding. */
decl = update_binding (NULL, binding, mslot, old,
- match, is_friend);
+ match, hiding);
if (match == decl && DECL_MODULE_EXPORT_P (decl)
&& !DECL_MODULE_EXPORT_P (level->this_entity))
@@ -3892,7 +3902,7 @@ do_pushdecl (tree decl, bool is_friend)
{
check_default_args (decl);
- if (is_friend)
+ if (hiding)
{
if (level->kind != sk_namespace)
{
@@ -3931,7 +3941,7 @@ do_pushdecl (tree decl, bool is_friend)
old = MAYBE_STAT_DECL (*mslot);
}
- old = update_binding (level, binding, mslot, old, decl, is_friend);
+ old = update_binding (level, binding, mslot, old, decl, hiding);
if (old != decl)
/* An existing decl matched, use it. */
@@ -3964,10 +3974,10 @@ do_pushdecl (tree decl, bool is_friend)
we push it. */
tree
-pushdecl (tree x, bool is_friend)
+pushdecl (tree x, bool hiding)
{
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- tree ret = do_pushdecl (x, is_friend);
+ tree ret = do_pushdecl (x, hiding);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
@@ -4907,7 +4917,7 @@ set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b)
{
tree *slot = find_namespace_slot (current_namespace, id, true);
gcc_assert (decl);
- update_binding (b, NULL, slot, MAYBE_STAT_DECL (*slot), decl, false);
+ update_binding (b, NULL, slot, MAYBE_STAT_DECL (*slot), decl);
/* Store marker instead of real type. */
type = global_type_node;
@@ -4963,12 +4973,13 @@ constructor_name_p (tree name, tree type)
closer binding level than LEVEL. */
static tree
-do_pushdecl_with_scope (tree x, cp_binding_level *level, bool is_friend)
+do_pushdecl_with_scope (tree x, cp_binding_level *level, bool hiding = false)
{
cp_binding_level *b;
if (level->kind == sk_class)
{
+ gcc_checking_assert (!hiding);
b = class_binding_level;
class_binding_level = level;
pushdecl_class_level (x);
@@ -4981,7 +4992,7 @@ do_pushdecl_with_scope (tree x, cp_binding_level *level, bool is_friend)
current_function_decl = NULL_TREE;
b = current_binding_level;
current_binding_level = level;
- x = pushdecl (x, is_friend);
+ x = pushdecl (x, hiding);
current_binding_level = b;
current_function_decl = function_decl;
}
@@ -5001,7 +5012,7 @@ pushdecl_outermost_localscope (tree x)
n->kind != sk_function_parms; n = b->level_chain)
b = n;
- tree ret = b ? do_pushdecl_with_scope (x, b, false) : error_mark_node;
+ tree ret = b ? do_pushdecl_with_scope (x, b) : error_mark_node;
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
@@ -6248,14 +6259,13 @@ do_namespace_alias (tree alias, tree name_space)
if appropriate. */
tree
-pushdecl_namespace_level (tree x, bool is_friend)
+pushdecl_namespace_level (tree x, bool hiding)
{
cp_binding_level *b = current_binding_level;
tree t;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- t = do_pushdecl_with_scope
- (x, NAMESPACE_LEVEL (current_namespace), is_friend);
+ t = do_pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace), hiding);
/* Now, the type_shadowed stack may screw us. Munge it so it does
what we want. */
@@ -8610,15 +8620,13 @@ finish_using_directive (tree target, tree attribs)
/* Pushes X into the global namespace. */
tree
-pushdecl_top_level (tree x, tree *maybe_init)
+pushdecl_top_level (tree x)
{
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
do_push_to_top_level ();
if (!DECL_CONTEXT (x))
DECL_CONTEXT (x) = FROB_CONTEXT (global_namespace);
- x = pushdecl_namespace_level (x, false);
- if (maybe_init)
- cp_finish_decl (x, *maybe_init, false, NULL_TREE, 0);
+ x = pushdecl_namespace_level (x);
do_pop_from_top_level ();
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return x;
@@ -8630,7 +8638,16 @@ pushdecl_top_level (tree x, tree *maybe_init)
tree
pushdecl_top_level_and_finish (tree x, tree init)
{
- return pushdecl_top_level (x, &init);
+ bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
+ do_push_to_top_level ();
+ if (!DECL_CONTEXT (x))
+ // FIXME: Who is pushing with no context?
+ DECL_CONTEXT (x) = FROB_CONTEXT (global_namespace);
+ x = pushdecl_namespace_level (x);
+ cp_finish_decl (x, init, false, NULL_TREE, 0);
+ do_pop_from_top_level ();
+ timevar_cond_stop (TV_NAME_LOOKUP, subtime);
+ return x;
}
/* Enter the namespaces from current_namerspace to NS. */
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index b052ba8eb6b..7281008868d 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -377,7 +377,7 @@ extern tree lookup_qualified_name (tree scope, const char *name,
bool = true);
extern bool is_local_extern (tree);
extern bool pushdecl_class_level (tree);
-extern tree pushdecl_namespace_level (tree, bool is_friend = false);
+extern tree pushdecl_namespace_level (tree, bool hiding = false);
extern bool push_class_level_binding (tree, tree);
extern tree get_local_decls ();
extern int function_parm_depth (void);
@@ -403,9 +403,9 @@ extern void cp_emit_debug_info_for_using (tree, tree);
extern void finish_nonmember_using_decl (tree scope, tree name);
extern void finish_using_directive (tree target, tree attribs);
-extern tree pushdecl (tree, bool is_friend = false);
+extern tree pushdecl (tree, bool hiding = false);
extern tree pushdecl_outermost_localscope (tree);
-extern tree pushdecl_top_level (tree, tree *maybe_init = NULL);
+extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree);
extern tree pushtag (tree, tree, TAG_how = TAG_how::CURRENT_ONLY);
extern int push_namespace (tree, bool make_inline = false);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d5de4527058..4f859e59401 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1634,7 +1634,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
for the specialization, we want this to look as if
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
- duplicate_decls (spec, fn, is_friend);
+ duplicate_decls (spec, fn, /*hiding=*/is_friend);
/* The call to duplicate_decls will have applied
[temp.expl.spec]:
@@ -1661,7 +1661,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- tree dd = duplicate_decls (spec, fn, is_friend);
+ tree dd = duplicate_decls (spec, fn, /*hiding=*/is_friend);
if (dd == error_mark_node)
/* We've already complained in duplicate_decls. */
return error_mark_node;
@@ -1676,7 +1676,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
}
}
else if (fn)
- return duplicate_decls (spec, fn, is_friend);
+ return duplicate_decls (spec, fn, /*hiding=*/is_friend);
/* A specialization must be declared in the same namespace as the
template it is specializing. */
@@ -6032,7 +6032,7 @@ push_template_decl (tree decl, bool is_friend)
if (!ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
{
- tmpl = pushdecl_namespace_level (tmpl, is_friend);
+ tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
if (tmpl == error_mark_node)
return error_mark_node;
@@ -11120,7 +11120,7 @@ tsubst_friend_function (tree decl, tree args)
into the namespace of the template. */
ns = decl_namespace_context (new_friend);
push_nested_namespace (ns);
- old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
+ old_decl = pushdecl_namespace_level (new_friend, /*hiding=*/true);
pop_nested_namespace (ns);
if (old_decl == error_mark_node)
@@ -11365,7 +11365,7 @@ tsubst_friend_class (tree friend_tmpl, tree args)
}
/* Inject this template into the enclosing namspace scope. */
- tmpl = pushdecl_namespace_level (tmpl, true);
+ tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/true);
}
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c2816dd5321..4dbd4107393 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2323,8 +2323,10 @@ ovl_skip_hidden (tree ovl)
{
/* Any hidden functions should have been wrapped in an
overload, but injected friend classes will not. */
- gcc_checking_assert (!DECL_DECLARES_FUNCTION_P (ovl));
- ovl = NULL_TREE;
+ // FIXME: This is temporarily wrong -- consider builtin that is
+ // anticipated in current TU, but known by an import
+ if (!DECL_DECLARES_FUNCTION_P (ovl))
+ ovl = NULL_TREE;
}
return ovl;
More information about the Gcc-cvs
mailing list