[cfe-commits] r91858 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/Sema/designated-initializers.c

Douglas Gregor dgregor at apple.com
Mon Dec 21 16:05:34 PST 2009


Author: dgregor
Date: Mon Dec 21 18:05:34 2009
New Revision: 91858

URL: http://llvm.org/viewvc/llvm-project?rev=91858&view=rev
Log:
When filling in value initializations within an initializer list, be
sure to fill in the initialized member of a union when a member was
explicitly designated. Fixes PR5843.

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Sema/designated-initializers.c

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=91858&r1=91857&r2=91858&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Dec 21 18:05:34 2009
@@ -345,6 +345,9 @@
   int numArrayElements(QualType DeclType);
   int numStructUnionElements(QualType DeclType);
 
+  void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+                               const InitializedEntity &ParentEntity,
+                               InitListExpr *ILE, bool &RequiresSecondPass);
   void FillInValueInitializations(const InitializedEntity &Entity,
                                   InitListExpr *ILE, bool &RequiresSecondPass);
 public:
@@ -358,6 +361,68 @@
 };
 } // end anonymous namespace
 
+void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+                                        const InitializedEntity &ParentEntity,
+                                              InitListExpr *ILE, 
+                                              bool &RequiresSecondPass) {
+  SourceLocation Loc = ILE->getSourceRange().getBegin();
+  unsigned NumInits = ILE->getNumInits();
+  InitializedEntity MemberEntity 
+    = InitializedEntity::InitializeMember(Field, &ParentEntity);
+  if (Init >= NumInits || !ILE->getInit(Init)) {
+    // FIXME: We probably don't need to handle references
+    // specially here, since value-initialization of references is
+    // handled in InitializationSequence.
+    if (Field->getType()->isReferenceType()) {
+      // C++ [dcl.init.aggr]p9:
+      //   If an incomplete or empty initializer-list leaves a
+      //   member of reference type uninitialized, the program is
+      //   ill-formed.
+      SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
+        << Field->getType()
+        << ILE->getSyntacticForm()->getSourceRange();
+      SemaRef.Diag(Field->getLocation(),
+                   diag::note_uninit_reference_member);
+      hadError = true;
+      return;
+    }
+    
+    InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+                                                              true);
+    InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
+    if (!InitSeq) {
+      InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
+      hadError = true;
+      return;
+    }
+    
+    Sema::OwningExprResult MemberInit
+      = InitSeq.Perform(SemaRef, MemberEntity, Kind, 
+                        Sema::MultiExprArg(SemaRef, 0, 0));
+    if (MemberInit.isInvalid()) {
+      hadError = true;
+      return;
+    }
+    
+    if (hadError) {
+      // Do nothing
+    } else if (Init < NumInits) {
+      ILE->setInit(Init, MemberInit.takeAs<Expr>());
+    } else if (InitSeq.getKind()
+                 == InitializationSequence::ConstructorInitialization) {
+      // Value-initialization requires a constructor call, so
+      // extend the initializer list to include the constructor
+      // call and make a note that we'll need to take another pass
+      // through the initializer list.
+      ILE->updateInit(Init, MemberInit.takeAs<Expr>());
+      RequiresSecondPass = true;
+    }
+  } else if (InitListExpr *InnerILE
+               = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+    FillInValueInitializations(MemberEntity, InnerILE, 
+                               RequiresSecondPass);  
+}
+
 /// Recursively replaces NULL values within the given initializer list
 /// with expressions that perform value-initialization of the
 /// appropriate type.
@@ -372,76 +437,32 @@
     Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
 
   if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
-    unsigned Init = 0, NumInits = ILE->getNumInits();
-    for (RecordDecl::field_iterator
-           Field = RType->getDecl()->field_begin(),
-           FieldEnd = RType->getDecl()->field_end();
-         Field != FieldEnd; ++Field) {
-      if (Field->isUnnamedBitfield())
-        continue;
-
-      if (hadError)
-        return;
+    if (RType->getDecl()->isUnion() &&
+        ILE->getInitializedFieldInUnion())
+      FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+                              Entity, ILE, RequiresSecondPass);
+    else {
+      unsigned Init = 0;
+      for (RecordDecl::field_iterator
+             Field = RType->getDecl()->field_begin(),
+             FieldEnd = RType->getDecl()->field_end();
+           Field != FieldEnd; ++Field) {
+        if (Field->isUnnamedBitfield())
+          continue;
 
-      InitializedEntity MemberEntity 
-        = InitializedEntity::InitializeMember(*Field, &Entity);
-      if (Init >= NumInits || !ILE->getInit(Init)) {
-        // FIXME: We probably don't need to handle references
-        // specially here, since value-initialization of references is
-        // handled in InitializationSequence.
-        if (Field->getType()->isReferenceType()) {
-          // C++ [dcl.init.aggr]p9:
-          //   If an incomplete or empty initializer-list leaves a
-          //   member of reference type uninitialized, the program is
-          //   ill-formed.
-          SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
-            << Field->getType()
-            << ILE->getSyntacticForm()->getSourceRange();
-          SemaRef.Diag(Field->getLocation(),
-                        diag::note_uninit_reference_member);
-          hadError = true;
-          return;
-        } 
-          
-        InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
-                                                                  true);
-        InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
-        if (!InitSeq) {
-          InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
-          hadError = true;
+        if (hadError)
           return;
-        }
 
-        Sema::OwningExprResult MemberInit
-          = InitSeq.Perform(SemaRef, MemberEntity, Kind, 
-                            Sema::MultiExprArg(SemaRef, 0, 0));
-        if (MemberInit.isInvalid()) {
-          hadError = true;
+        FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+        if (hadError)
           return;
-        }
 
-        if (hadError) {
-          // Do nothing
-        } else if (Init < NumInits) {
-          ILE->setInit(Init, MemberInit.takeAs<Expr>());
-        } else if (InitSeq.getKind()
-                         == InitializationSequence::ConstructorInitialization) {
-          // Value-initialization requires a constructor call, so
-          // extend the initializer list to include the constructor
-          // call and make a note that we'll need to take another pass
-          // through the initializer list.
-          ILE->updateInit(Init, MemberInit.takeAs<Expr>());
-          RequiresSecondPass = true;
-        }
-      } else if (InitListExpr *InnerILE
-                 = dyn_cast<InitListExpr>(ILE->getInit(Init)))
-          FillInValueInitializations(MemberEntity, InnerILE, 
-                                     RequiresSecondPass);
-      ++Init;
+        ++Init;
 
-      // Only look at the first initialization of a union.
-      if (RType->getDecl()->isUnion())
-        break;
+        // Only look at the first initialization of a union.
+        if (RType->getDecl()->isUnion())
+          break;
+      }
     }
 
     return;

Modified: cfe/trunk/test/Sema/designated-initializers.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/designated-initializers.c?rev=91858&r1=91857&r2=91858&view=diff

==============================================================================
--- cfe/trunk/test/Sema/designated-initializers.c (original)
+++ cfe/trunk/test/Sema/designated-initializers.c Mon Dec 21 18:05:34 2009
@@ -231,4 +231,21 @@
   [ 0 ? crazy_x : 4] = 1
 };
 
+// PR5843
+struct expr {
+  int nargs;
+  union {
+    unsigned long int num;
+    struct expr *args[3];
+  } val;
+};
 
+struct expr expr0 = { 
+  .nargs = 2,
+  .val = {
+    .args = { 
+      [0] = (struct expr *)0, 
+      [1] = (struct expr *)0 
+    }
+  }
+};





More information about the cfe-commits mailing list