[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