From 559c9fb134623e73e8c46d15b15a72fb3d350ec1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 8 Oct 2010 20:44:28 +0000 Subject: This patch fixes multiple issues in clang's designated init builder and completes support for C1X anonymous struct/union init features: * Indexed anonymous member initializers should not be expanded. Doing so makes little sense and would cause unresolvable semantic ambiguity in valid code (regression introduced by r69153). * Subobject initialization of (possibly nested) anonymous members are now referred to with paths relative to the naming record context, eliminating the synthesis of incorrect implicit InitListExprs that caused CodeGen to assert. * Field lookup was missing a null check in IdentifierInfo comparison which caused lookup for a known (already resolved) field to match the first unnamed data member it encountered leading to silent miscompilation. * Subobject paths are no longer built using the general purpose Sema::BuildAnonymousStructUnionMemberPath(). If any corner cases crop up, we will now assert earlier in Sema instead of passing invalid InitListExprs through to CodeGen. Fixes PR6955, from Alp Toker! llvm-svn: 116098 --- clang/lib/Sema/SemaInit.cpp | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'clang/lib/Sema/SemaInit.cpp') diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 6fd1d68dcd0..bac9f8fa755 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1167,6 +1167,22 @@ 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 &Path, + DeclContext *BaseDC) { + Path.push_back(Field); + for (DeclContext *Ctx = Field->getDeclContext(); + !Ctx->Equals(BaseDC); + Ctx = Ctx->getParent()) { + ValueDecl *AnonObject = + cast(Ctx)->getAnonymousStructOrUnionObject(); + FieldDecl *AnonField = cast(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. @@ -1178,13 +1194,14 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef, unsigned DesigIdx, FieldDecl *Field, RecordDecl::field_iterator &FieldIter, - unsigned &FieldIndex) { + unsigned &FieldIndex, + DeclContext *BaseDC) { typedef DesignatedInitExpr::Designator Designator; // Build the path from the current object to the member of the // anonymous struct/union (backwards). llvm::SmallVector Path; - SemaRef.BuildAnonymousStructUnionMemberPath(Field, Path); + BuildRelativeAnonymousStructUnionMemberPath(Field, Path, BaseDC); // Build the replacement designators. llvm::SmallVector Replacements; @@ -1343,7 +1360,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (Field->isUnnamedBitfield()) continue; - if (KnownField == *Field || Field->getIdentifier() == FieldName) + if (KnownField && KnownField == *Field) + break; + if (FieldName && FieldName == Field->getIdentifier()) break; ++FieldIndex; @@ -1400,10 +1419,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, cast((ReplacementField)->getDeclContext()) ->isAnonymousStructOrUnion()) { // Handle an field designator that refers to a member of an - // anonymous struct or union. + // anonymous struct or union. This is a C1X feature. ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, ReplacementField, - Field, FieldIndex); + Field, FieldIndex, RT->getDecl()); D = DIE->getDesignator(DesigIdx); } else if (!KnownField) { // The replacement field comes from typo correction; find it @@ -1421,12 +1440,6 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, ++FieldIndex; } } - } else if (!KnownField && - cast((*Field)->getDeclContext()) - ->isAnonymousStructOrUnion()) { - ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, *Field, - Field, FieldIndex); - D = DIE->getDesignator(DesigIdx); } // All of the fields of a union are located at the same place in -- cgit v1.2.3