diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-01-31 07:04:29 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-01-31 07:04:29 +0000 |
commit | 0413db4a26b0a1577b75c2979b0eb21f3490d17a (patch) | |
tree | 2b37d0d4244ef9ea4f370e6e2fa8149b008b7028 /lib/Sema/SemaExpr.cpp | |
parent | d4d3ce6ed8d4981a18d013f8694c762c47b44c77 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124575 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 098f5396bb..2429c75880 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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()); } |