aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.cc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2022-03-31 16:18:58 -0400
committerJason Merrill <jason@redhat.com>2022-05-02 15:52:23 -0400
commitdcb4bd0789d13dd4d07428bff712d01d3ea71ebe (patch)
tree4a9e2c4fe3ce95215ddca92f77ec9122c97e46a6 /gcc/cp/class.cc
parent7e1f30d7edd433ca0fc28ae9ac1ce9b522790baf (diff)
downloadgcc-dcb4bd0789d13dd4d07428bff712d01d3ea71ebe.zip
gcc-dcb4bd0789d13dd4d07428bff712d01d3ea71ebe.tar.gz
gcc-dcb4bd0789d13dd4d07428bff712d01d3ea71ebe.tar.bz2
c++: also note name used in enclosing class
While looking at PR96645 I noticed that while we were diagnosing names changing meaning in the full class context, we weren't doing this for lookups in nested class bodies. Note that this breaks current range-v3; I've submitted a pull request to fix its violation of the rule. gcc/cp/ChangeLog: * class.cc (maybe_note_name_used_in_class): Note in all enclosing classes. Remember location of use. (note_name_declared_in_class): Adjust. gcc/testsuite/ChangeLog: * g++.dg/lookup/name-clash13.C: New test. * g++.dg/lookup/name-clash14.C: New test. * g++.dg/lookup/name-clash15.C: New test. * g++.dg/lookup/name-clash16.C: New test.
Diffstat (limited to 'gcc/cp/class.cc')
-rw-r--r--gcc/cp/class.cc61
1 files changed, 43 insertions, 18 deletions
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index bfda006..bc94ed4 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -8931,32 +8931,53 @@ is_really_empty_class (tree type, bool ignore_vptr)
void
maybe_note_name_used_in_class (tree name, tree decl)
{
- splay_tree names_used;
-
/* If we're not defining a class, there's nothing to do. */
if (!(innermost_scope_kind() == sk_class
&& TYPE_BEING_DEFINED (current_class_type)
&& !LAMBDA_TYPE_P (current_class_type)))
return;
- /* If there's already a binding for this NAME, then we don't have
- anything to worry about. */
- if (lookup_member (current_class_type, name,
- /*protect=*/0, /*want_type=*/false, tf_warning_or_error))
- return;
+ const cp_binding_level *blev = nullptr;
+ if (const cxx_binding *binding = IDENTIFIER_BINDING (name))
+ blev = binding->scope;
+ const cp_binding_level *lev = current_binding_level;
- if (!current_class_stack[current_class_depth - 1].names_used)
- current_class_stack[current_class_depth - 1].names_used
- = splay_tree_new (splay_tree_compare_pointers, 0, 0);
- names_used = current_class_stack[current_class_depth - 1].names_used;
+ /* Record the binding in the names_used tables for classes inside blev. */
+ for (int i = current_class_depth; i > 0; --i)
+ {
+ tree type = (i == current_class_depth
+ ? current_class_type
+ : current_class_stack[i].type);
- splay_tree_insert (names_used,
- (splay_tree_key) name,
- (splay_tree_value) decl);
+ for (; lev; lev = lev->level_chain)
+ {
+ if (lev == blev)
+ /* We found the declaration. */
+ return;
+ if (lev->kind == sk_class && lev->this_entity == type)
+ /* This class is inside the declaration scope. */
+ break;
+ }
+
+ auto &names_used = current_class_stack[i-1].names_used;
+ if (!names_used)
+ names_used = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+
+ tree use = build1_loc (input_location, VIEW_CONVERT_EXPR,
+ TREE_TYPE (decl), decl);
+ EXPR_LOCATION_WRAPPER_P (use) = 1;
+ splay_tree_insert (names_used,
+ (splay_tree_key) name,
+ (splay_tree_value) use);
+ }
}
/* Note that NAME was declared (as DECL) in the current class. Check
- to see that the declaration is valid. */
+ to see that the declaration is valid under [class.member.lookup]:
+
+ If [the result of a search in T for N at point P] differs from the result of
+ a search in T for N from immediately after the class-specifier of T, the
+ program is ill-formed, no diagnostic required. */
void
note_name_declared_in_class (tree name, tree decl)
@@ -8979,6 +9000,9 @@ note_name_declared_in_class (tree name, tree decl)
n = splay_tree_lookup (names_used, (splay_tree_key) name);
if (n)
{
+ tree use = (tree) n->value;
+ location_t loc = EXPR_LOCATION (use);
+ tree olddecl = OVL_FIRST (TREE_OPERAND (use, 0));
/* [basic.scope.class]
A name N used in a class S shall refer to the same declaration
@@ -8987,9 +9011,10 @@ note_name_declared_in_class (tree name, tree decl)
if (permerror (location_of (decl),
"declaration of %q#D changes meaning of %qD",
decl, OVL_NAME (decl)))
- inform (location_of ((tree) n->value),
- "%qD declared here as %q#D",
- OVL_NAME (decl), (tree) n->value);
+ {
+ inform (loc, "used here to mean %q#D", olddecl);
+ inform (location_of (olddecl), "declared here" );
+ }
}
}