aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h27
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--lib/AST/Expr.cpp13
-rw-r--r--lib/AST/StmtPrinter.cpp4
-rw-r--r--lib/CodeGen/CGExprAgg.cpp6
-rw-r--r--lib/CodeGen/CGExprComplex.cpp6
-rw-r--r--lib/CodeGen/CGExprConstant.cpp5
-rw-r--r--lib/CodeGen/CGExprScalar.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp10
-rw-r--r--lib/Sema/SemaInit.cpp28
-rw-r--r--test/CodeGen/designated-initializers.c17
11 files changed, 97 insertions, 23 deletions
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<ParenExpr>(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<char*>(static_cast<void *>(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<CXXZeroInitValueExpr>(E)) {
+ if (isa<ImplicitValueInitExpr>(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<CompoundLiteralExpr>(Init))
return CheckForConstantInitializer(e->getInitializer(), DclT);
+ if (isa<ImplicitValueInitExpr>(Init)) {
+ // FIXME: In C++, check for non-POD types.
+ return false;
+ }
+
if (InitListExpr *Exp = dyn_cast<InitListExpr>(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<CXXZeroInitValueExpr>(Exp->getInit(i)) &&
- cast<CXXZeroInitValueExpr>(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 <map>
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<InitListExpr>(ILE->getInit(Init)))
+ new (Context) ImplicitValueInitExpr(Field->getType()));
+ else if (InitListExpr *InnerILE
+ = dyn_cast<InitListExpr>(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<InitListExpr>(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,
+ };
+}
+