Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? Now that I'm posting this patch, I think you'll probably want me to use ba_any unconditionally. That works too; g++.dg/tc1/dr52.C just needs a trivial testsuite tweak: 'C' is not an accessible base of 'X' v. 'C' is an inaccessible base of 'X' We should probably unify those messages...
-- >8 -- Given struct A { constexpr static int a = 0; }; struct B : A {}; struct C : A {}; struct D : B, C {}; we give the "'A' is an ambiguous base of 'D'" error for D{}.A::a; which seems wrong: 'a' is a static data member so there is only one copy so it can be unambiguously referred to even if there are multiple A objects. clang++/MSVC/icx agree. PR c++/112744 gcc/cp/ChangeLog: * typeck.cc (finish_class_member_access_expr): When accessing a static data member, use ba_any for lookup_base. gcc/testsuite/ChangeLog: * g++.dg/lookup/scoped11.C: New test. * g++.dg/lookup/scoped12.C: New test. * g++.dg/lookup/scoped13.C: New test. --- gcc/cp/typeck.cc | 21 ++++++++++++++++++--- gcc/testsuite/g++.dg/lookup/scoped11.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/lookup/scoped12.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/lookup/scoped13.C | 14 ++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/scoped11.C create mode 100644 gcc/testsuite/g++.dg/lookup/scoped12.C create mode 100644 gcc/testsuite/g++.dg/lookup/scoped13.C diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index e995fb6ddd7..c4de8bb2616 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -3476,7 +3476,7 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p, name, scope); return error_mark_node; } - + if (TREE_SIDE_EFFECTS (object)) val = build2 (COMPOUND_EXPR, TREE_TYPE (val), object, val); return val; @@ -3493,9 +3493,24 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p, return error_mark_node; } + /* NAME may refer to a static data member, in which case there is + one copy of the data member that is shared by all the objects of + the class. So NAME can be unambiguously referred to even if + there are multiple indirect base classes containing NAME. */ + const base_access ba = [scope, name] () + { + if (identifier_p (name)) + { + tree m = lookup_member (scope, name, /*protect=*/0, + /*want_type=*/false, tf_none); + if (!m || VAR_P (m)) + return ba_any; + } + return ba_check; + } (); + /* Find the base of OBJECT_TYPE corresponding to SCOPE. */ - access_path = lookup_base (object_type, scope, ba_check, - NULL, complain); + access_path = lookup_base (object_type, scope, ba, NULL, complain); if (access_path == error_mark_node) return error_mark_node; if (!access_path) diff --git a/gcc/testsuite/g++.dg/lookup/scoped11.C b/gcc/testsuite/g++.dg/lookup/scoped11.C new file mode 100644 index 00000000000..be743522fce --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/scoped11.C @@ -0,0 +1,14 @@ +// PR c++/112744 +// { dg-do compile } + +struct A { const static int a = 0; }; +struct B : A {}; +struct C : A {}; +struct D : B, C {}; + +int main() +{ + D d; + (void) d.a; + (void) d.A::a; +} diff --git a/gcc/testsuite/g++.dg/lookup/scoped12.C b/gcc/testsuite/g++.dg/lookup/scoped12.C new file mode 100644 index 00000000000..ffa145598fd --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/scoped12.C @@ -0,0 +1,14 @@ +// PR c++/112744 +// { dg-do compile } + +class A { const static int a = 0; }; +struct B : A {}; +struct C : A {}; +struct D : B, C {}; + +int main() +{ + D d; + (void) d.a; // { dg-error "private" } + (void) d.A::a; // { dg-error "private" } +} diff --git a/gcc/testsuite/g++.dg/lookup/scoped13.C b/gcc/testsuite/g++.dg/lookup/scoped13.C new file mode 100644 index 00000000000..970e1aa833e --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/scoped13.C @@ -0,0 +1,14 @@ +// PR c++/112744 +// { dg-do compile } + +struct A { const static int a = 0; }; +struct B : A {}; +struct C : A {}; +struct D : B, C {}; + +int main() +{ + D d; + (void) d.x; // { dg-error ".struct D. has no member named .x." } + (void) d.A::x; // { dg-error ".struct A. has no member named .x." } +} base-commit: 3d104d93a7011146b0870ab160613147adb8d9b3 -- 2.42.0