summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-31 07:04:29 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-31 07:04:29 +0000
commit8322b426a56db0ecaf99c565746ed04448cd29b1 (patch)
treea5875acdc108a99080e43bc3ab6ea57f1ea62bce /clang/lib/Sema/SemaExpr.cpp
parent1ce7755c350a5c02da00b1873cb6515d1c8e7e84 (diff)
downloadbcm5719-llvm-8322b426a56db0ecaf99c565746ed04448cd29b1.tar.gz
bcm5719-llvm-8322b426a56db0ecaf99c565746ed04448cd29b1.zip
Amazing that there are still issues with the fields of anonymous struct/unions..
Allow taking the address of such a field for a pointer-to-member constant. Fixes rdar://8818236. llvm-svn: 124575
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp30
1 files changed, 21 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 098f5396bb0..2429c75880e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -853,6 +853,7 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
ExprResult
Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
+ const CXXScopeSpec &SS,
IndirectFieldDecl *IndirectField,
Expr *BaseObjectExpr,
SourceLocation OpLoc) {
@@ -911,9 +912,21 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
}
- if (!BaseObjectExpr)
- return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use)
- << IndirectField->getDeclName());
+ if (!BaseObjectExpr) {
+ // The field is referenced for a pointer-to-member expression, e.g:
+ //
+ // struct S {
+ // union {
+ // char c;
+ // };
+ // };
+ // char S::*foo = &S::c;
+ //
+ FieldDecl *field = IndirectField->getAnonField();
+ DeclarationNameInfo NameInfo(field->getDeclName(), Loc);
+ return BuildDeclRefExpr(field, field->getType().getNonReferenceType(),
+ VK_LValue, NameInfo, &SS);
+ }
}
// Build the implicit member references to the field of the
@@ -929,9 +942,6 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
for (; FI != FEnd; FI++) {
FieldDecl *Field = cast<FieldDecl>(*FI);
- // FIXME: the first access can be qualified
- CXXScopeSpec SS;
-
// FIXME: these are somewhat meaningless
DeclarationNameInfo MemberNameInfo(Field->getDeclName(), Loc);
DeclAccessPair FoundDecl = DeclAccessPair::make(Field, Field->getAccess());
@@ -2035,7 +2045,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
// FIXME: This needs to happen post-isImplicitMemberReference?
// FIXME: template-ids inside anonymous structs?
if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
- return BuildAnonymousStructUnionMemberReference(Loc, FD);
+ return BuildAnonymousStructUnionMemberReference(Loc, SS, FD);
// If this is known to be an instance access, go ahead and build a
@@ -2228,7 +2238,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// Handle anonymous.
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(VD))
- return BuildAnonymousStructUnionMemberReference(Loc, FD);
+ return BuildAnonymousStructUnionMemberReference(Loc, SS, FD);
ExprValueKind VK = getValueKindForDecl(Context, VD);
@@ -3400,7 +3410,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
- return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
+ return BuildAnonymousStructUnionMemberReference(MemberLoc, SS, FD,
BaseExpr, OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
@@ -7346,6 +7356,8 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
return QualType();
}
+ while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
+ Ctx = Ctx->getParent();
return S.Context.getMemberPointerType(op->getType(),
S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
}
OpenPOWER on IntegriCloud