From bc365c53606ab90537576cb48d93a54ce3fb0cb5 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 21 May 2010 01:17:40 +0000 Subject: [PATCH] Introduce a method to get from an anonymous struct or union record declaration to the associated object declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104309 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 5 +++++ lib/AST/Decl.cpp | 11 +++++++++++ lib/Sema/SemaExpr.cpp | 31 +------------------------------ 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index db23342b00..e95f697104 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2021,6 +2021,11 @@ public: AnonymousStructOrUnion = Anon; } + ValueDecl *getAnonymousStructOrUnionObject(); + const ValueDecl *getAnonymousStructOrUnionObject() const { + return const_cast(this)->getAnonymousStructOrUnionObject(); + } + bool hasObjectMember() const { return HasObjectMember; } void setHasObjectMember (bool val) { HasObjectMember = val; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 695a8b8b51..ffdcb471d0 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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(getNextDeclInContext()); + assert(D->getType()->isRecordType()); + assert(D->getType()->getAs()->getDecl() == this); + return D; +} + //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9d8fe9c85f..933a696bdc 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(*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(Ctx); - Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record); + ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject(); if (FieldDecl *AnonField = dyn_cast(AnonObject)) Path.push_back(AnonField); else { -- 2.40.0