summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorFrancois Pichet <pichet2000@gmail.com>2010-11-21 06:08:52 +0000
committerFrancois Pichet <pichet2000@gmail.com>2010-11-21 06:08:52 +0000
commit783dd6ece4d1cacbbe9c5790c5a0b6cf9a4b7c9c (patch)
tree835aace2ba6a248986b02e383139a1f63bfb80fa /clang/lib/Sema/SemaExpr.cpp
parente040a46eb354d1eb3d2102b416620e869a10883b (diff)
downloadbcm5719-llvm-783dd6ece4d1cacbbe9c5790c5a0b6cf9a4b7c9c.tar.gz
bcm5719-llvm-783dd6ece4d1cacbbe9c5790c5a0b6cf9a4b7c9c.zip
Major anonymous union/struct redesign.
A new AST node is introduced: def IndirectField : DDecl<Value>; IndirectFields are injected into the anonymous's parent scope and chain back to the original field. Name lookup for anonymous entities now result in an IndirectFieldDecl instead of a FieldDecl. There is no functionality change, the code generated should be the same. llvm-svn: 119919
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp145
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();
}
OpenPOWER on IntegriCloud