From dfb5e597e033c8fa09c0e178bd93cfcdf060862e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 12 Feb 2009 19:00:39 +0000 Subject: [PATCH] Fix a bug with designated initializers where we were stepping out of a union subobject initialization before checking whether the next initiailizer was actually a designated initializer. This led to spurious "excess elements in union initializer" errors. Thanks to rdivacky for reporting the bug! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64392 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 15 +++++++-------- test/Sema/designated-initializers.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 27d8d5aa2e..b54a8d674b 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -742,14 +742,13 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, return; } - - // If structDecl is a forward declaration, this loop won't do // anything except look at designated initializers; That's okay, // because an error should get printed out elsewhere. It might be // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); + bool InitializedSomething = false; while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); @@ -768,11 +767,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, true, TopLevelObject)) hadError = true; - // Abort early for unions: the designator handled the - // initialization of the appropriate field. - if (DeclType->isUnionType()) - break; - + InitializedSomething = true; continue; } @@ -781,6 +776,10 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, break; } + // We've already initialized a member of a union. We're done. + if (InitializedSomething && DeclType->isUnionType()) + break; + // If we've hit the flexible array member at the end, we're done. if (Field->getType()->isIncompleteArrayType()) break; @@ -793,11 +792,11 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, CheckSubElementType(IList, Field->getType(), Index, StructuredList, StructuredIndex); + InitializedSomething = true; if (DeclType->isUnionType()) { // Initialize the first field within the union. StructuredList->setInitializedFieldInUnion(*Field); - break; } ++Field; diff --git a/test/Sema/designated-initializers.c b/test/Sema/designated-initializers.c index 9c4429d02d..7c6ddca8ef 100644 --- a/test/Sema/designated-initializers.c +++ b/test/Sema/designated-initializers.c @@ -172,3 +172,17 @@ struct bar saloon = { .f.arr[3] = 1, .arr = { &f } }; + +typedef unsigned char u_char; +typedef unsigned short u_short; + +union wibble { + u_char arr1[6]; + u_short arr2[3]; +}; + +const union wibble wobble = { .arr2[0] = 0xffff, + .arr2[1] = 0xffff, + .arr2[2] = 0xffff }; + +const union wibble wobble2 = { .arr2 = {4, 5, 6}, 7 }; // expected-error{{excess elements in union initializer}} -- 2.40.0