When building a qualified reference to a member of an anonymous struct

or union, place the qualifier on the outermost member reference
expression, which actually contains the entity name.

Fixes PR9188/<rdar://problem/8990184>.

llvm-svn: 125822
This commit is contained in:
Douglas Gregor 2011-02-18 02:44:58 +00:00
parent a7ced2cb4c
commit e10f36db2f
2 changed files with 28 additions and 6 deletions

View File

@ -1004,6 +1004,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
// Case 1: the base of the indirect field is not a field.
VarDecl *baseVariable = indirectField->getVarDecl();
CXXScopeSpec EmptySS;
if (baseVariable) {
assert(baseVariable->getType()->isRecordType());
@ -1017,7 +1018,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
ExprResult result =
BuildDeclarationNameExpr(SS, baseNameInfo, baseVariable);
BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
if (result.isInvalid()) return ExprError();
baseObjectExpr = result.take();
@ -1078,7 +1079,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
SS, field, foundDecl,
EmptySS, field, foundDecl,
memberNameInfo).take();
baseObjectIsPointer = false;
@ -1088,16 +1089,16 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
// In all cases, we should now skip the first declaration in the chain.
++FI;
for (; FI != FEnd; FI++) {
FieldDecl *field = cast<FieldDecl>(*FI);
while (FI != FEnd) {
FieldDecl *field = cast<FieldDecl>(*FI++);
// FIXME: these are somewhat meaningless
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
CXXScopeSpec memberSS;
result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
memberSS, field, foundDecl, memberNameInfo)
(FI == FEnd? SS : EmptySS), field,
foundDecl, memberNameInfo)
.take();
}

View File

@ -66,3 +66,24 @@ namespace PR7402 {
X x(42.0);
}
namespace PR9188 {
struct X0 {
union {
int member;
};
};
static union {
int global;
};
struct X1 : X0 {
template<typename T>
int f() {
return this->X0::member + PR9188::global;
}
};
template int X1::f<int>();
}