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.
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<FieldDecl *, 4> Path;
- SemaRef.BuildAnonymousStructUnionMemberPath(Field, Path);
+ BuildRelativeAnonymousStructUnionMemberPath(Field, Path, BaseDC);
// Build the replacement designators.
llvm::SmallVector<Designator, 4> Replacements;
if (Field->isUnnamedBitfield())
continue;
- if (KnownField == *Field || Field->getIdentifier() == FieldName)
+ if (KnownField && KnownField == *Field)
+ break;
+ if (FieldName && FieldName == Field->getIdentifier())
break;
++FieldIndex;
cast<RecordDecl>((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
++FieldIndex;
}
}
- } else if (!KnownField &&
- cast<RecordDecl>((*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
[1] = 22
};
+// PR6955
+
+struct ds {
+ struct {
+ struct {
+ short a;
+ };
+ short b;
+ struct {
+ short c;
+ };
+ };
+};
+
+// Traditional C anonymous member init
+struct ds ds0 = { { { .a = 0 } } };
+// C1X lookup-based anonymous member init cases
+struct ds ds1 = { { .a = 1 } };
+struct ds ds2 = { { .b = 1 } };
+struct ds ds3 = { .a = 0 };
+// CHECK: @ds4 = global %3 { %4 { %struct.anon zeroinitializer, i16 0, %struct.anon { i16 1 } } }
+struct ds ds4 = { .c = 1 };
+struct ds ds5 = { { { .a = 0 } }, .b = 1 };
+struct ds ds6 = { { .a = 0, .b = 1 } };
+// CHECK: @ds7 = global %3 { %4 { %struct.anon { i16 2 }, i16 3, %struct.anon zeroinitializer } }
+struct ds ds7 = {
+ { {
+ .a = 1
+ } },
+ .a = 2,
+ .b = 3
+};
+
void test1(int argc, char **argv)
{
// CHECK: internal global %struct.foo { i8* null, i32 1024 }