diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 10b877ac89..c6ac007a13 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1645,7 +1645,7 @@ public: /// initializations into the subobject they initialize. Additionally, /// any "holes" in the initialization, where no initializer has been /// specified for a particular subobject, will be replaced with -/// implicitly-generated CXXZeroInitValueExpr expressions that +/// implicitly-generated ImplicitValueInitExpr expressions that /// value-initialize the subobjects. Note, however, that the /// initializer lists may still have fewer initializers than there are /// elements to initialize within the object. @@ -1987,6 +1987,31 @@ public: virtual child_iterator child_end(); }; +/// \brief Represents an implicitly-generated value initialization of +/// an object of a given type. +/// +/// Implicit value initializations occur within semantic initialize +/// list expressions (\see InitListExpr) as placeholders for subobject +/// initializations not explicitly specified by the user. +class ImplicitValueInitExpr : public Expr { +public: + explicit ImplicitValueInitExpr(QualType ty) + : Expr(ImplicitValueInitExprClass, ty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ImplicitValueInitExprClass; + } + static bool classof(const ImplicitValueInitExpr *) { return true; } + + virtual SourceRange getSourceRange() const { + return SourceRange(); + } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index e8d4a56c50..18b8dbebfe 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -86,6 +86,7 @@ STMT(CompoundLiteralExpr , Expr) STMT(ExtVectorElementExpr , Expr) STMT(InitListExpr , Expr) STMT(DesignatedInitExpr , Expr) +STMT(ImplicitValueInitExpr , Expr) STMT(VAArgExpr , Expr) // GNU Extensions. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c1c8084cd5..8a04198293 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -735,6 +735,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const { } return true; } + case ImplicitValueInitExprClass: + return true; case ParenExprClass: { return cast(this)->getSubExpr()->isConstantInitializer(Ctx); } @@ -1672,7 +1674,7 @@ Stmt::child_iterator InitListExpr::child_end() { return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0; } -/// DesignatedInitExpr +// DesignatedInitExpr Stmt::child_iterator DesignatedInitExpr::child_begin() { char* Ptr = static_cast(static_cast(this)); Ptr += sizeof(DesignatedInitExpr); @@ -1683,6 +1685,15 @@ Stmt::child_iterator DesignatedInitExpr::child_end() { return child_iterator(&*child_begin() + NumSubExprs); } +// ImplicitValueInitExpr +Stmt::child_iterator ImplicitValueInitExpr::child_begin() { + return child_iterator(); +} + +Stmt::child_iterator ImplicitValueInitExpr::child_end() { + return child_iterator(); +} + // ObjCStringLiteral Stmt::child_iterator ObjCStringLiteral::child_begin() { return child_iterator(); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 7a558ab8dd..27bab206a4 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -906,6 +906,10 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { PrintExpr(Node->getInit()); } +void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) { + OS << "/*implicit*/" << Node->getType().getAsString() << "()"; +} + void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << "va_arg("; PrintExpr(Node->getSubExpr()); diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index b487bacc71..f985763b5c 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -339,10 +339,10 @@ void AggExprEmitter::EmitNonConstInit(InitListExpr *E) { void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { // FIXME: Are initializers affected by volatile? - if (E->getType()->isComplexType()) { - CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); - } else if (isa(E)) { + if (isa(E)) { EmitNullInitializationToLValue(LV, E->getType()); + } else if (E->getType()->isComplexType()) { + CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); } else if (CGF.hasAggregateLLVMType(E->getType())) { CGF.EmitAnyExpr(E, LV.getAddress(), false); } else { diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 73fceedee5..387635cb06 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -130,6 +130,12 @@ public: llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem)); return ComplexPairTy(Null, Null); } + ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { + assert(E->getType()->isAnyComplexType() && "Expected complex type!"); + QualType Elem = E->getType()->getAsComplexType()->getElementType(); + llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem)); + return ComplexPairTy(Null, Null); + } struct BinOpInfo { ComplexPairTy LHS; diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index e523ab3acf..3aedf9bc7f 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -248,11 +248,6 @@ public: FieldDecl* curField = ILE->getInitializedFieldInUnion(); if (!curField) { -#ifndef NDEBUG -#endif - } - - if (!curField) { // There's no field to initialize, so value-initialize the union. #ifndef NDEBUG // Make sure that it's really an empty and not a failure of diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index dd8b30041e..f855e23ba0 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -200,6 +200,9 @@ public: return V; } + Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { + return llvm::Constant::getNullValue(ConvertType(E->getType())); + } Value *VisitImplicitCastExpr(const ImplicitCastExpr *E); Value *VisitCastExpr(const CastExpr *E) { return EmitCastExpr(E->getSubExpr(), E->getType()); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7572560be1..1559213fcb 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2220,17 +2220,17 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { if (CompoundLiteralExpr *e = dyn_cast(Init)) return CheckForConstantInitializer(e->getInitializer(), DclT); + if (isa(Init)) { + // FIXME: In C++, check for non-POD types. + return false; + } + if (InitListExpr *Exp = dyn_cast(Init)) { unsigned numInits = Exp->getNumInits(); for (unsigned i = 0; i < numInits; i++) { // FIXME: Need to get the type of the declaration for C++, // because it could be a reference? - // Implicitly-generated value initializations are okay. - if (isa(Exp->getInit(i)) && - cast(Exp->getInit(i))->isImplicit()) - continue; - if (CheckForConstantInitializer(Exp->getInit(i), Exp->getInit(i)->getType())) return true; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 527f965dc3..5d7f705edb 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -17,7 +17,6 @@ #include "clang/Parse/Designator.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" #include using namespace clang; @@ -137,10 +136,9 @@ static void fillInValueInitializations(ASTContext &Context, InitListExpr *ILE) { // FIXME: Check for fields with reference type in C++? if (!ILE->getInit(Init)) ILE->setInit(Init, - new (Context) CXXZeroInitValueExpr(Field->getType(), - SourceLocation(), - SourceLocation())); - else if (InitListExpr *InnerILE = dyn_cast(ILE->getInit(Init))) + new (Context) ImplicitValueInitExpr(Field->getType())); + else if (InitListExpr *InnerILE + = dyn_cast(ILE->getInit(Init))) fillInValueInitializations(Context, InnerILE); ++Init; } @@ -160,9 +158,7 @@ static void fillInValueInitializations(ASTContext &Context, InitListExpr *ILE) { for (unsigned Init = 0, NumInits = ILE->getNumInits(); Init != NumInits; ++Init) { if (!ILE->getInit(Init)) - ILE->setInit(Init, new (Context) CXXZeroInitValueExpr(ElementType, - SourceLocation(), - SourceLocation())); + ILE->setInit(Init, new (Context) ImplicitValueInitExpr(ElementType)); else if (InitListExpr *InnerILE =dyn_cast(ILE->getInit(Init))) fillInValueInitializations(Context, InnerILE); } @@ -550,6 +546,22 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, hadError = true; return; } + + if (DeclType->isUnionType() && IList->getNumInits() == 0) { + // Value-initialize the first named member of the union. + RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); + for (RecordDecl::field_iterator FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Field->getDeclName()) { + StructuredList->setInitializedFieldInUnion(*Field); + break; + } + } + 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 diff --git a/test/CodeGen/designated-initializers.c b/test/CodeGen/designated-initializers.c new file mode 100644 index 0000000000..0605b24b1c --- /dev/null +++ b/test/CodeGen/designated-initializers.c @@ -0,0 +1,17 @@ +// RUN: clang %s -emit-llvm -o - +// XFAIL +struct foo { + void *a; + int b; +}; + +union { int i; float f; } u = { }; + +int main(int argc, char **argv) +{ + union { int i; float f; } u2 = { }; + static struct foo foo = { + .b = 1024, + }; +} +