diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 145 |
1 files changed, 52 insertions, 93 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index bc811d0e77b..37561028c26 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -795,59 +795,18 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, D, NameInfo, Ty, VK)); } -/// \brief Given a field that represents a member of an anonymous -/// struct/union, build the path from that field's context to the -/// actual member. -/// -/// Construct the sequence of field member references we'll have to -/// perform to get to the field in the anonymous union/struct. The -/// list of members is built from the field outward, so traverse it -/// backwards to go from an object in the current context to the field -/// we found. -/// -/// \returns The variable from which the field access should begin, -/// for an anonymous struct/union that is not a member of another -/// class. Otherwise, returns NULL. -VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field, - llvm::SmallVectorImpl<FieldDecl *> &Path) { - assert(Field->getDeclContext()->isRecord() && - cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion() - && "Field must be stored inside an anonymous struct or union"); - - Path.push_back(Field); - VarDecl *BaseObject = 0; - DeclContext *Ctx = Field->getDeclContext(); - do { - RecordDecl *Record = cast<RecordDecl>(Ctx); - ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject(); - if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject)) - Path.push_back(AnonField); - else { - BaseObject = cast<VarDecl>(AnonObject); - break; - } - Ctx = Ctx->getParent(); - } while (Ctx->isRecord() && - cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()); - - return BaseObject; -} - ExprResult Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, - FieldDecl *Field, + IndirectFieldDecl *IndirectField, Expr *BaseObjectExpr, SourceLocation OpLoc) { - llvm::SmallVector<FieldDecl *, 4> AnonFields; - VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field, - AnonFields); - // Build the expression that refers to the base object, from // which we will build a sequence of member references to each // of the anonymous union objects and, eventually, the field we // found via name lookup. bool BaseObjectIsPointer = false; Qualifiers BaseQuals; + VarDecl *BaseObject = IndirectField->getVarDecl(); if (BaseObject) { // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). @@ -877,7 +836,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, if (!MD->isStatic()) { QualType AnonFieldType = Context.getTagDeclType( - cast<RecordDecl>(AnonFields.back()->getDeclContext())); + cast<RecordDecl>( + (*IndirectField->chain_begin())->getDeclContext())); QualType ThisType = Context.getTagDeclType(MD->getParent()); if ((Context.getCanonicalType(AnonFieldType) == Context.getCanonicalType(ThisType)) || @@ -890,24 +850,29 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, } } else { return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method) - << Field->getDeclName()); + << IndirectField->getDeclName()); } BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers()); } if (!BaseObjectExpr) return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use) - << Field->getDeclName()); + << IndirectField->getDeclName()); } // Build the implicit member references to the field of the // anonymous struct/union. Expr *Result = BaseObjectExpr; Qualifiers ResultQuals = BaseQuals; - for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator - FI = AnonFields.rbegin(), FIEnd = AnonFields.rend(); - FI != FIEnd; ++FI) { - FieldDecl *Field = *FI; + + IndirectFieldDecl::chain_iterator FI = IndirectField->chain_begin(), + FEnd = IndirectField->chain_end(); + + // Skip the first VarDecl if present. + if (BaseObject) + FI++; + for (; FI != FEnd; FI++) { + FieldDecl *Field = cast<FieldDecl>(*FI); QualType MemberType = Field->getType(); Qualifiers MemberTypeQuals = Context.getCanonicalType(MemberType).getQualifiers(); @@ -930,8 +895,9 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, MarkDeclarationReferenced(Loc, *FI); PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI); // FIXME: Might this end up being a qualified name? - Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, - OpLoc, MemberType, VK_LValue, + Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, + cast<FieldDecl>(*FI), OpLoc, + MemberType, VK_LValue, Field->isBitField() ? OK_BitField : OK_Ordinary); BaseObjectIsPointer = false; @@ -1048,10 +1014,6 @@ enum IMAKind { /// context is not an instance method. IMA_Unresolved_StaticContext, - /// The reference is to a member of an anonymous structure in a - /// non-class context. - IMA_AnonymousMember, - /// All possible referrents are instance members and the current /// context is not an instance method. IMA_Error_StaticContext, @@ -1084,16 +1046,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes; for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; + if (D->isCXXInstanceMember()) { CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); - - // If this is a member of an anonymous record, move out to the - // innermost non-anonymous struct or union. If there isn't one, - // that's a special case. - while (R->isAnonymousStructOrUnion()) { - R = dyn_cast<CXXRecordDecl>(R->getParent()); - if (!R) return IMA_AnonymousMember; - } Classes.insert(R->getCanonicalDecl()); } else @@ -1577,7 +1532,8 @@ ExprResult Sema::ActOnIdExpression(Scope *S, else if (R.isUnresolvableResult()) MightBeImplicitMember = true; else - MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()); + MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || + isa<IndirectFieldDecl>(R.getFoundDecl()); if (MightBeImplicitMember) return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); @@ -1598,11 +1554,6 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, case IMA_Instance: return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); - case IMA_AnonymousMember: - assert(R.isSingleResult()); - return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), - R.getAsSingle<FieldDecl>()); - case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: @@ -1959,9 +1910,9 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // (C++ [class.union]). // FIXME: This needs to happen post-isImplicitMemberReference? // FIXME: template-ids inside anonymous structs? - if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) - if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) - return BuildAnonymousStructUnionMemberReference(Loc, FD); + if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>()) + return BuildAnonymousStructUnionMemberReference(Loc, FD); + // If this is known to be an instance access, go ahead and build a // 'this' expression now. @@ -2153,6 +2104,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (VD->isInvalidDecl()) return ExprError(); + // Handle anonymous. + if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(VD)) + return BuildAnonymousStructUnionMemberReference(Loc, FD); + ExprValueKind VK = getValueKindForDecl(Context, VD); // If the identifier reference is inside a block, and it refers to a value @@ -3308,12 +3263,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { - // We may have found a field within an anonymous union or struct - // (C++ [class.union]). - if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion() && - !BaseType->getAs<RecordType>()->getDecl()->isAnonymousStructOrUnion()) - return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, - BaseExpr, OpLoc); // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note @@ -3356,6 +3305,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, MemberType, VK, OK)); } + 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, + BaseExpr, OpLoc); + if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, Var); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, @@ -7956,6 +7911,12 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); LookupQualifiedName(R, RD); FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>(); + IndirectFieldDecl *IndirectMemberDecl = 0; + if (!MemberDecl) { + if (IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()) + MemberDecl = IndirectMemberDecl->getAnonField(); + } + if (!MemberDecl) return ExprError(Diag(BuiltinLoc, diag::err_no_member) << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, @@ -7974,12 +7935,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, } RecordDecl *Parent = MemberDecl->getParent(); - bool AnonStructUnion = Parent->isAnonymousStructOrUnion(); - if (AnonStructUnion) { - do { - Parent = cast<RecordDecl>(Parent->getParent()); - } while (Parent->isAnonymousStructOrUnion()); - } + if (IndirectMemberDecl) + Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext()); // If the member was found in a base class, introduce OffsetOfNodes for // the base class indirections. @@ -7992,15 +7949,17 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, Comps.push_back(OffsetOfNode(B->Base)); } - if (AnonStructUnion) { - llvm::SmallVector<FieldDecl*, 4> Path; - BuildAnonymousStructUnionMemberPath(MemberDecl, Path); - unsigned n = Path.size(); - for (int j = n - 1; j > -1; --j) - Comps.push_back(OffsetOfNode(OC.LocStart, Path[j], OC.LocEnd)); - } else { + if (IndirectMemberDecl) { + for (IndirectFieldDecl::chain_iterator FI = + IndirectMemberDecl->chain_begin(), + FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) { + assert(isa<FieldDecl>(*FI)); + Comps.push_back(OffsetOfNode(OC.LocStart, + cast<FieldDecl>(*FI), OC.LocEnd)); + } + } else Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd)); - } + CurrentType = MemberDecl->getType().getNonReferenceType(); } |

