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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119919 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Francois Pichet 2010-11-21 06:08:52 +00:00
Родитель a4c2475961
Коммит 87c2e121cf
17 изменённых файлов: 247 добавлений и 117 удалений

Просмотреть файл

@ -1794,6 +1794,45 @@ public:
friend class StmtIteratorBase;
};
/// IndirectFieldDecl - An instance of this class is created to represent a
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
class IndirectFieldDecl : public ValueDecl {
NamedDecl **Chaining;
int ChainingSize;
IndirectFieldDecl(DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
NamedDecl **CH, int CHS)
: ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
public:
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, NamedDecl **CH, int CHS);
typedef NamedDecl * const *chain_iterator;
chain_iterator chain_begin() const { return Chaining; }
chain_iterator chain_end() const { return Chaining+ChainingSize; }
int getChainingSize() const { return ChainingSize; }
FieldDecl *getAnonField() const {
assert(ChainingSize >= 2);
return cast<FieldDecl>(Chaining[ChainingSize - 1]);
}
VarDecl *getVarDecl() const {
assert(ChainingSize >= 2);
return dyn_cast<VarDecl>(*chain_begin());
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const IndirectFieldDecl *D) { return true; }
static bool classofKind(Kind K) { return K == IndirectField; }
friend class ASTDeclReader;
};
/// TypeDecl - Represents a declaration of a type.
///

Просмотреть файл

@ -1381,6 +1381,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
})
DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));

Просмотреть файл

@ -29,6 +29,7 @@ def Named : Decl<1>;
def Value : DDecl<Named, 1>;
def EnumConstant : DDecl<Value>;
def UnresolvedUsingValue : DDecl<Value>;
def IndirectField : DDecl<Value>;
def Declarator : DDecl<Value, 1>;
def Function : DDecl<Declarator>, DeclContext;
def CXXMethod : DDecl<Function>;

Просмотреть файл

@ -139,7 +139,8 @@ namespace clang {
class VarDecl;
class VisibilityAttr;
class VisibleDeclConsumer;
class IndirectFieldDecl;
namespace sema {
class AccessedEntity;
class BlockScopeInfo;
@ -1739,11 +1740,9 @@ public:
ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS = 0);
VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
llvm::SmallVectorImpl<FieldDecl *> &Path);
ExprResult
BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
FieldDecl *Field,
IndirectFieldDecl *IndirectField,
Expr *BaseObjectExpr = 0,
SourceLocation OpLoc = SourceLocation());
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,

Просмотреть файл

@ -269,6 +269,7 @@ namespace clang {
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
Decl *VisitEnumConstantDecl(EnumConstantDecl *D);

Просмотреть файл

@ -718,7 +718,9 @@ namespace clang {
/// \brief A StaticAssertDecl record.
DECL_STATIC_ASSERT,
/// \brief A record containing CXXBaseSpecifiers.
DECL_CXX_BASE_SPECIFIERS
DECL_CXX_BASE_SPECIFIERS,
/// \brief A IndirectFieldDecl record.
DECL_INDIRECTFIELD,
};
/// \brief Record codes for each kind of statement or expression.

Просмотреть файл

@ -98,6 +98,7 @@ namespace {
Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
@ -2020,6 +2021,42 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
return ToField;
}
Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
// Import the major distinguishing characteristics of a variable.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
return 0;
NamedDecl **NamedChain =
new (Importer.getToContext())NamedDecl*[D->getChainingSize()];
unsigned i = 0;
for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(),
PE = D->chain_end(); PI != PE; ++PI) {
Decl* D = Importer.Import(*PI);
if (!D)
return 0;
NamedChain[i++] = cast<NamedDecl>(D);
}
IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create(
Importer.getToContext(), DC,
Loc, Name.getAsIdentifierInfo(), T,
NamedChain, D->getChainingSize());
ToIndirectField->setAccess(D->getAccess());
ToIndirectField->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIndirectField);
LexicalDC->addDecl(ToIndirectField);
return ToIndirectField;
}
Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Import the major distinguishing characteristics of an ivar.
DeclContext *DC, *LexicalDC;

Просмотреть файл

@ -768,7 +768,7 @@ bool NamedDecl::isCXXInstanceMember() const {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (isa<FieldDecl>(D))
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))
return true;
if (isa<CXXMethodDecl>(D))
return cast<CXXMethodDecl>(D)->isInstance();
@ -2030,6 +2030,12 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
}
IndirectFieldDecl *IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, NamedDecl **CH, int CHS) {
return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS);
}
SourceRange EnumConstantDecl::getSourceRange() const {
SourceLocation End = getLocation();
if (Init)

Просмотреть файл

@ -249,6 +249,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCProperty:
return IDNS_Ordinary;
case IndirectField:
return IDNS_Ordinary | IDNS_Member;
case ObjCCompatibleAlias:
case ObjCInterface:
return IDNS_Ordinary | IDNS_Type;
@ -524,8 +527,6 @@ bool DeclContext::isTransparentContext() const {
return !cast<EnumDecl>(this)->isScoped();
else if (DeclKind == Decl::LinkageSpec)
return true;
else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord)
return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
return false;
}

Просмотреть файл

@ -333,6 +333,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
islvalue = NTTParm->getType()->isReferenceType();
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
(Ctx.getLangOptions().CPlusPlus &&
(isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)));

Просмотреть файл

@ -1748,7 +1748,8 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
DeclContext *Owner,
RecordDecl *AnonRecord,
AccessSpecifier AS) {
AccessSpecifier AS,
llvm::SmallVector<NamedDecl*, 2> &Chaining) {
unsigned diagKind
= AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
: diag::err_anonymous_struct_member_redecl;
@ -1771,20 +1772,37 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
// definition, the members of the anonymous union are
// considered to have been defined in the scope in which the
// anonymous union is declared.
Owner->makeDeclVisibleInContext(*F);
S->AddDecl(*F);
SemaRef.IdResolver.AddDecl(*F);
Chaining.push_back(*F);
assert(Chaining.size() >= 2);
NamedDecl **NamedChain =
new (SemaRef.Context)NamedDecl*[Chaining.size()];
for (unsigned i = 0; i < Chaining.size(); i++)
NamedChain[i] = Chaining[i];
IndirectFieldDecl* IndirectField =
IndirectFieldDecl::Create(SemaRef.Context, Owner, F->getLocation(),
F->getIdentifier(), F->getType(),
NamedChain, Chaining.size());
IndirectField->setAccess(AS);
IndirectField->setImplicit();
SemaRef.PushOnScopeChains(IndirectField, S);
// That includes picking up the appropriate access specifier.
if (AS != AS_none) (*F)->setAccess(AS);
Chaining.pop_back();
}
} else if (const RecordType *InnerRecordType
= (*F)->getType()->getAs<RecordType>()) {
RecordDecl *InnerRecord = InnerRecordType->getDecl();
Chaining.push_back(*F);
if (InnerRecord->isAnonymousStructOrUnion())
Invalid = Invalid ||
InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner,
InnerRecord, AS);
InnerRecord, AS, Chaining);
Chaining.pop_back();
}
}
@ -1999,7 +2017,10 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Inject the members of the anonymous struct/union into the owning
// context and into the identifier resolver chain for name lookup
// purposes.
if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS))
llvm::SmallVector<NamedDecl*, 2> Chain;
Chain.push_back(Anon);
if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, Chain))
Invalid = true;
// Mark this as an anonymous struct/union type. Note that we do not

Просмотреть файл

@ -1067,10 +1067,15 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
FieldDecl *Member = 0;
DeclContext::lookup_result Result
= ClassDecl->lookup(MemberOrBase);
if (Result.first != Result.second)
if (Result.first != Result.second) {
Member = dyn_cast<FieldDecl>(*Result.first);
// FIXME: Handle members of an anonymous union.
// Handle anonymous union case.
if (!Member)
if (IndirectFieldDecl* IndirectField
= dyn_cast<IndirectFieldDecl>(*Result.first))
Member = IndirectField->getAnonField();
}
if (Member)
return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
@ -2600,15 +2605,15 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// In addition, if class T has a user-declared constructor (12.1), every
// non-static data member of class T shall have a name different from T.
for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
R.first != R.second; ++R.first)
if (FieldDecl *Field = dyn_cast<FieldDecl>(*R.first)) {
if (Record->hasUserDeclaredConstructor() ||
!Field->getDeclContext()->Equals(Record)) {
Diag(Field->getLocation(), diag::err_member_name_of_class)
<< Field->getDeclName();
R.first != R.second; ++R.first) {
NamedDecl *D = *R.first;
if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
isa<IndirectFieldDecl>(D)) {
Diag(D->getLocation(), diag::err_member_name_of_class)
<< D->getDeclName();
break;
}
}
}
}
}

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -1429,6 +1429,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
} else if (!KnownField) {
// Determine whether we found a field at all.
ReplacementField = dyn_cast<FieldDecl>(*Lookup.first);
// Check if ReplacementField is an anonymous field.
if (!ReplacementField)
if (IndirectFieldDecl* IField = dyn_cast<IndirectFieldDecl>(*Lookup.first))
ReplacementField = IField->getAnonField();
}
if (!ReplacementField) {

Просмотреть файл

@ -456,6 +456,29 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
return Field;
}
Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
NamedDecl **NamedChain =
new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
int i = 0;
for (IndirectFieldDecl::chain_iterator PI =
D->chain_begin(), PE = D->chain_end();
PI != PE; ++PI)
NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(),
*PI, TemplateArgs));
IndirectFieldDecl* IndirectField
= IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getIdentifier(), D->getType(),
NamedChain, D->getChainingSize());
IndirectField->setImplicit(D->isImplicit());
IndirectField->setAccess(D->getAccess());
Owner->addDecl(IndirectField);
return IndirectField;
}
Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
// Handle friend type expressions by simply substituting template
// parameters into the pattern type and checking the result.

Просмотреть файл

@ -107,6 +107,7 @@ namespace clang {
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
void VisitCXXConversionDecl(CXXConversionDecl *D);
void VisitFieldDecl(FieldDecl *FD);
void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
void VisitVarDecl(VarDecl *VD);
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
@ -635,6 +636,17 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
}
}
void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
VisitValueDecl(FD);
FD->ChainingSize = Record[Idx++];
assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2");
FD->Chaining = new (*Reader.getContext())NamedDecl*[FD->ChainingSize];
for (unsigned I = 0; I != FD->ChainingSize; ++I)
FD->Chaining[I] = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
}
void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
VisitDeclaratorDecl(VD);
VisitRedeclarable(VD);
@ -1475,6 +1487,10 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,
false);
break;
case DECL_INDIRECTFIELD:
D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
0, 0);
break;
case DECL_VAR:
D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
SC_None, SC_None);

Просмотреть файл

@ -72,6 +72,7 @@ namespace clang {
void VisitCXXDestructorDecl(CXXDestructorDecl *D);
void VisitCXXConversionDecl(CXXConversionDecl *D);
void VisitFieldDecl(FieldDecl *D);
void VisitIndirectFieldDecl(IndirectFieldDecl *D);
void VisitVarDecl(VarDecl *D);
void VisitImplicitParamDecl(ImplicitParamDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
@ -528,6 +529,17 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
Code = serialization::DECL_FIELD;
}
void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
VisitValueDecl(D);
Record.push_back(D->getChainingSize());
for (IndirectFieldDecl::chain_iterator
P = D->chain_begin(),
PEnd = D->chain_end(); P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
Code = serialization::DECL_INDIRECTFIELD;
}
void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VisitDeclaratorDecl(D);
VisitRedeclarable(D);