зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
a4c2475961
Коммит
87c2e121cf
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче