name, scope);
return error_mark_node;
}
-
+
if (TREE_SIDE_EFFECTS (object))
val = build2 (COMPOUND_EXPR, TREE_TYPE (val), object, val);
return val;
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 || shared_member_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)
--- /dev/null
+// 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." }
+}
--- /dev/null
+// PR c++/112744
+// { dg-do compile { target c++11 } }
+
+struct A { int a = 0; };
+struct B : A {};
+struct C : A {};
+struct D : B, C {};
+
+int main()
+{
+ D d;
+ (void) d.a; // { dg-error "request for member .a. is ambiguous" }
+ (void) d.A::a; // { dg-error ".A. is an ambiguous base of .D." }
+}
--- /dev/null
+// PR c++/112744
+// { dg-do compile { target c++11 } }
+
+struct A { constexpr static int a = 0; };
+struct D : private A {};
+
+// The injected-class-name of A is private when named in D, but if A is named
+// some other way, there is no requirement in [class.access.base] for static data
+// members that it be an accessible base.
+
+void f() {
+ D{}.A::a; // { dg-error "inaccessible" }
+ D{}.::A::a;
+}
+
+template<class T>
+void g() {
+ D{}.T::a;
+}
+
+template void g<A>();