summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h13
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp24
-rw-r--r--clang/test/SemaCXX/anonymous-union.cpp9
3 files changed, 31 insertions, 15 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6b4079e36e5..6edb9ddbc24 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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,
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 7151fc55041..29e91e173df 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -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
@@ -799,14 +800,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
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());
-
+ DeclAccessPair fakeFoundDecl =
+ DeclAccessPair::make(field, field->getAccess());
+
result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
- (FI == FEnd? SS : EmptySS), field,
- foundDecl, memberNameInfo).take();
+ (FI == FEnd? SS : EmptySS), field,
+ 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.
diff --git a/clang/test/SemaCXX/anonymous-union.cpp b/clang/test/SemaCXX/anonymous-union.cpp
index 9c2cf24a83f..fde27b049d8 100644
--- a/clang/test/SemaCXX/anonymous-union.cpp
+++ b/clang/test/SemaCXX/anonymous-union.cpp
@@ -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'}}
+ }
+}
OpenPOWER on IntegriCloud