Introduce a method to get from an anonymous struct or union record declaration

to the associated object declaration.

llvm-svn: 104309
This commit is contained in:
John McCall 2010-05-21 01:17:40 +00:00
parent b3b9c8ac48
commit 61925b03cc
3 changed files with 17 additions and 30 deletions

View File

@ -2021,6 +2021,11 @@ public:
AnonymousStructOrUnion = Anon;
}
ValueDecl *getAnonymousStructOrUnionObject();
const ValueDecl *getAnonymousStructOrUnionObject() const {
return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject();
}
bool hasObjectMember() const { return HasObjectMember; }
void setHasObjectMember (bool val) { HasObjectMember = val; }

View File

@ -1627,6 +1627,17 @@ void RecordDecl::completeDefinition() {
TagDecl::completeDefinition();
}
ValueDecl *RecordDecl::getAnonymousStructOrUnionObject() {
// Force the decl chain to come into existence properly.
if (!getNextDeclInContext()) getParent()->decls_begin();
assert(isAnonymousStructOrUnion());
ValueDecl *D = cast<ValueDecl>(getNextDeclInContext());
assert(D->getType()->isRecordType());
assert(D->getType()->getAs<RecordType>()->getDecl() == this);
return D;
}
//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//

View File

@ -496,35 +496,6 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
D, Loc, Ty));
}
/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
/// variable corresponding to the anonymous union or struct whose type
/// is Record.
static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context,
RecordDecl *Record) {
assert(Record->isAnonymousStructOrUnion() &&
"Record must be an anonymous struct or union!");
// FIXME: Once Decls are directly linked together, this will be an O(1)
// operation rather than a slow walk through DeclContext's vector (which
// itself will be eliminated). DeclGroups might make this even better.
DeclContext *Ctx = Record->getDeclContext();
for (DeclContext::decl_iterator D = Ctx->decls_begin(),
DEnd = Ctx->decls_end();
D != DEnd; ++D) {
if (*D == Record) {
// The object for the anonymous struct/union directly
// follows its type in the list of declarations.
++D;
assert(D != DEnd && "Missing object for anonymous record");
assert(!cast<NamedDecl>(*D)->getDeclName() && "Decl should be unnamed");
return *D;
}
}
assert(false && "Missing object for anonymous record");
return 0;
}
/// \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.
@ -549,7 +520,7 @@ VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
DeclContext *Ctx = Field->getDeclContext();
do {
RecordDecl *Record = cast<RecordDecl>(Ctx);
Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record);
ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject();
if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject))
Path.push_back(AnonField);
else {