The answer is clang is correct. However, the code could also fail as ambiguous according to the standard.
If you look at 11.2p5 it has a relevant note (yes, I know notes are non-normative):
[ Note: This class can be explicit, e.g., when a qualified-id is used,
or implicit, e.g., when a class member access operator (5.2.5) is used
(including cases where an implicit “this->” is added). If both a class
member access operator and a qualified-id are used to name the member
(as in p->T::m), the class naming the member is the class denoted by
the nested-name-specifier of the qualified-id (that is, T). —end note
]
What this note means, is that if you add this-> to C::x = 2; then C is the class naming the member and gcc 4.7.2 correctly fails when this is the case.
Now the question is Who is the class naming the member for C::x?
The naming class is specified by the same 11.2p5:
The access to a member is affected by the class in which the member is
named. This naming class is the class in which the member name was
looked up and found.
Now, name lookup for class members is specified in 10.2, and after reading all of it, I have concluded that x is the union of subobject sets as per:
Otherwise, the new S(f, C) is a lookup set with the shared set of
declarations and the union of the subobject sets.
Which means that according to member lookup rules x can be either from B or A! This makes the code ill-formed as: Name
lookup can result in an ambiguity, in which case the program is ill-formed.
However, this ambiguity can be resolved as per 10.2p8:
Ambiguities can often be resolved by qualifying a name with its class
name.
And from the Clang source, we can see that is what they chose to do:
// If the member was a qualified name and the qualified referred to a
// specific base subobject type, we'll cast to that intermediate type
// first and then to the object in which the member is declared. That allows
// one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as:
//
// class Base { public: int x; };
// class Derived1 : public Base { };
// class Derived2 : public Base { };
// class VeryDerived : public Derived1, public Derived2 { void f(); };
// void VeryDerived::f() {
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
However, note the can in the wording of the above quote: often can be resolved. This means that they do not necessarily have to be resolved. So, I think according to the standard the code should fail as ambiguous or as a private member access failure.
EDIT
There is some contention about the interpretation of can and as to whether a ambiguity occurs here. I found Defect report 39. Conflicting ambiguity rules talks about this issue.