forked from OSchip/llvm-project
Fix member refs with using decl + anonymous union.
Make sure we call BuildFieldReferenceExpr with the appropriate decl when a member of an anonymous union is made public with a using decl. Also, fix a crash on invalid field access into an anonymous union. Fixes PR16630. llvm-svn: 186367
This commit is contained in:
parent
66c0a65ba1
commit
cccd06487d
|
@ -3150,11 +3150,14 @@ public:
|
|||
const CXXScopeSpec *SS = 0,
|
||||
NamedDecl *FoundD = 0);
|
||||
ExprResult
|
||||
BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
|
||||
SourceLocation nameLoc,
|
||||
IndirectFieldDecl *indirectField,
|
||||
Expr *baseObjectExpr = 0,
|
||||
SourceLocation opLoc = SourceLocation());
|
||||
BuildAnonymousStructUnionMemberReference(
|
||||
const CXXScopeSpec &SS,
|
||||
SourceLocation nameLoc,
|
||||
IndirectFieldDecl *indirectField,
|
||||
DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_none),
|
||||
Expr *baseObjectExpr = 0,
|
||||
SourceLocation opLoc = SourceLocation());
|
||||
|
||||
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
LookupResult &R,
|
||||
|
|
|
@ -703,6 +703,7 @@ ExprResult
|
|||
Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
|
||||
SourceLocation loc,
|
||||
IndirectFieldDecl *indirectField,
|
||||
DeclAccessPair foundDecl,
|
||||
Expr *baseObjectExpr,
|
||||
SourceLocation opLoc) {
|
||||
// First, build the expression that refers to the base object.
|
||||
|
@ -780,15 +781,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
|
|||
if (!baseVariable) {
|
||||
FieldDecl *field = cast<FieldDecl>(*FI);
|
||||
|
||||
// FIXME: use the real found-decl info!
|
||||
DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
|
||||
|
||||
// Make a nameInfo that properly uses the anonymous name.
|
||||
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
|
||||
|
||||
result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
|
||||
EmptySS, field, foundDecl,
|
||||
memberNameInfo).take();
|
||||
if (!result)
|
||||
return ExprError();
|
||||
|
||||
baseObjectIsPointer = false;
|
||||
|
||||
// FIXME: check qualified member access
|
||||
|
@ -802,11 +803,12 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
|
|||
|
||||
// FIXME: these are somewhat meaningless
|
||||
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
|
||||
DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
|
||||
DeclAccessPair fakeFoundDecl =
|
||||
DeclAccessPair::make(field, field->getAccess());
|
||||
|
||||
result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
|
||||
(FI == FEnd? SS : EmptySS), field,
|
||||
foundDecl, memberNameInfo).take();
|
||||
fakeFoundDecl, memberNameInfo).take();
|
||||
}
|
||||
|
||||
return Owned(result);
|
||||
|
@ -990,7 +992,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
|
|||
// We may have found a field within an anonymous union or struct
|
||||
// (C++ [class.union]).
|
||||
return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
|
||||
BaseExpr, OpLoc);
|
||||
FoundDecl, BaseExpr,
|
||||
OpLoc);
|
||||
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
|
||||
return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
|
||||
|
@ -1688,7 +1691,8 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
|
|||
// (C++ [class.union]).
|
||||
// FIXME: template-ids inside anonymous structs?
|
||||
if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
|
||||
return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
|
||||
return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD,
|
||||
R.begin().getPair());
|
||||
|
||||
// If this is known to be an instance access, go ahead and build an
|
||||
// implicit 'this' expression now.
|
||||
|
|
|
@ -197,3 +197,12 @@ namespace PR8326 {
|
|||
|
||||
Foo<int> baz;
|
||||
}
|
||||
|
||||
namespace PR16630 {
|
||||
struct A { union { int x; float y; }; }; // expected-note {{member is declared here}}
|
||||
struct B : private A { using A::x; } b; // expected-note 2 {{private}}
|
||||
void foo () {
|
||||
b.x = 10;
|
||||
b.y = 0; // expected-error {{cannot cast 'struct B' to its private base class 'PR16630::A'}} expected-error {{'y' is a private member of 'PR16630::A'}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue