diff options
-rw-r--r-- | include/clang/AST/Decl.h | 5 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 6 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 98 |
4 files changed, 32 insertions, 88 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 39468dcfb1..e3fb20b83c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2405,11 +2405,6 @@ 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; } diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 97ff44d479..435ebc65ea 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1306,11 +1306,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( RecordDecl *D) { // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the source. - // - // The anonymous struct or union object is the variable or field - // whose type is the anonymous struct or union. We shouldn't - // traverse D->getAnonymousStructOrUnionObject(), as it's not - // something that is explicitly written in the source. + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); return true; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7a35c74873..08272e76ca 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2005,17 +2005,6 @@ 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; -} - void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 555166076d..3cca42e48b 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1194,55 +1194,29 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, StructuredList, StructuredIndex); } -/// \brief Similar to Sema::BuildAnonymousStructUnionMemberPath() but builds a -/// relative path and has strict checks. -static void BuildRelativeAnonymousStructUnionMemberPath(FieldDecl *Field, - llvm::SmallVectorImpl<FieldDecl *> &Path, - DeclContext *BaseDC) { - Path.push_back(Field); - for (DeclContext *Ctx = Field->getDeclContext(); - !Ctx->Equals(BaseDC); - Ctx = Ctx->getParent()) { - ValueDecl *AnonObject = - cast<RecordDecl>(Ctx)->getAnonymousStructOrUnionObject(); - FieldDecl *AnonField = cast<FieldDecl>(AnonObject); - Path.push_back(AnonField); - } -} - /// \brief Expand a field designator that refers to a member of an /// anonymous struct or union into a series of field designators that /// refers to the field within the appropriate subobject. /// -/// Field/FieldIndex will be updated to point to the (new) -/// currently-designated field. static void ExpandAnonymousFieldDesignator(Sema &SemaRef, DesignatedInitExpr *DIE, unsigned DesigIdx, - FieldDecl *Field, - RecordDecl::field_iterator &FieldIter, - unsigned &FieldIndex, - DeclContext *BaseDC) { + IndirectFieldDecl *IndirectField) { typedef DesignatedInitExpr::Designator Designator; - // Build the path from the current object to the member of the - // anonymous struct/union (backwards). - llvm::SmallVector<FieldDecl *, 4> Path; - BuildRelativeAnonymousStructUnionMemberPath(Field, Path, BaseDC); - // Build the replacement designators. llvm::SmallVector<Designator, 4> Replacements; - for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator - FI = Path.rbegin(), FIEnd = Path.rend(); - FI != FIEnd; ++FI) { - if (FI + 1 == FIEnd) + for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(), + PE = IndirectField->chain_end(); PI != PE; ++PI) { + if (PI + 1 == PE) Replacements.push_back(Designator((IdentifierInfo *)0, DIE->getDesignator(DesigIdx)->getDotLoc(), DIE->getDesignator(DesigIdx)->getFieldLoc())); else Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(), SourceLocation())); - Replacements.back().setField(*FI); + assert(isa<FieldDecl>(*PI)); + Replacements.back().setField(cast<FieldDecl>(*PI)); } // Expand the current designator into the set of replacement @@ -1250,23 +1224,20 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef, // member of the anonymous struct/union is actually stored. DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0], &Replacements[0] + Replacements.size()); +} - // Update FieldIter/FieldIndex; - RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext()); - FieldIter = Record->field_begin(); - FieldIndex = 0; - for (RecordDecl::field_iterator FEnd = Record->field_end(); - FieldIter != FEnd; ++FieldIter) { - if (FieldIter->isUnnamedBitfield()) - continue; - - if (*FieldIter == Path.back()) - return; - - ++FieldIndex; +/// \brief Given an implicit anonymous field, search the IndirectField that +/// corresponds to FieldName. +static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField, + IdentifierInfo *FieldName) { + assert(AnonField->isAnonymousStructOrUnion()); + Decl *NextDecl = AnonField->getNextDeclInContext(); + while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) { + if (FieldName && FieldName == IF->getAnonField()->getIdentifier()) + return IF; + NextDecl = NextDecl->getNextDeclInContext(); } - - assert(false && "Unable to find anonymous struct/union field"); + return 0; } /// @brief Check the well-formedness of a C99 designated initializer. @@ -1386,7 +1357,17 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, for (; Field != FieldEnd; ++Field) { if (Field->isUnnamedBitfield()) continue; - + + // If we find a field representing an anonymous field, look in the + // IndirectFieldDecl that follow for the designated initializer. + if (!KnownField && Field->isAnonymousStructOrUnion()) { + if (IndirectFieldDecl *IF = + FindIndirectFieldDesignator(*Field, FieldName)) { + ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF); + D = DIE->getDesignator(DesigIdx); + break; + } + } if (KnownField && KnownField == *Field) break; if (FieldName && FieldName == Field->getIdentifier()) @@ -1427,16 +1408,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, ++Index; return true; } - } 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) { // Name lookup found something, but it wasn't a field. SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) @@ -1447,16 +1420,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, return true; } - if (!KnownField && - cast<RecordDecl>((ReplacementField)->getDeclContext()) - ->isAnonymousStructOrUnion()) { - // Handle an field designator that refers to a member of an - // anonymous struct or union. This is a C1X feature. - ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, - ReplacementField, - Field, FieldIndex, RT->getDecl()); - D = DIE->getDesignator(DesigIdx); - } else if (!KnownField) { + if (!KnownField) { // The replacement field comes from typo correction; find it // in the list of fields. FieldIndex = 0; |