summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-29 17:44:32 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-29 17:44:32 +0000
commit0202cb406ee64be15636ba7b9435a9a83f9d4996 (patch)
tree0658b765f90c92a584ef4bb103822df89b310785
parent5169570e28a556cb9af0951eac1697442d26fa19 (diff)
downloadbcm5719-llvm-0202cb406ee64be15636ba7b9435a9a83f9d4996.tar.gz
bcm5719-llvm-0202cb406ee64be15636ba7b9435a9a83f9d4996.zip
Introduce a new expression node, ImplicitValueInitExpr, that
represents an implicit value-initialization of a subobject of a particular type. This replaces the (ab)use of CXXZeroValueInitExpr within initializer lists for the "holes" that occur due to the use of C99 designated initializers. The new test case is currently XFAIL'd, because CodeGen's ConstExprEmitter (in lib/CodeGen/CGExprConstant.cpp) needs to be taught to value-initialize when it sees ImplicitValueInitExprs. llvm-svn: 63317
-rw-r--r--clang/include/clang/AST/Expr.h27
-rw-r--r--clang/include/clang/AST/StmtNodes.def1
-rw-r--r--clang/lib/AST/Expr.cpp13
-rw-r--r--clang/lib/AST/StmtPrinter.cpp4
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp6
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp6
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp5
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp10
-rw-r--r--clang/lib/Sema/SemaInit.cpp28
-rw-r--r--clang/test/CodeGen/designated-initializers.c17
11 files changed, 97 insertions, 23 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 10b877ac891..c6ac007a131 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/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/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def
index e8d4a56c507..18b8dbebfed 100644
--- a/clang/include/clang/AST/StmtNodes.def
+++ b/clang/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/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index c1c8084cd59..8a041982936 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 7a558ab8dd7..27bab206a4e 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/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/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index b487bacc711..f985763b5c3 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/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/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 73fceedee5f..387635cb064 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/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/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index e523ab3acf2..3aedf9bc7f7 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/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/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index dd8b30041e7..f855e23ba03 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7572560be19..1559213fcb8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 527f965dc3f..5d7f705edb1 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/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/clang/test/CodeGen/designated-initializers.c b/clang/test/CodeGen/designated-initializers.c
new file mode 100644
index 00000000000..0605b24b1c5
--- /dev/null
+++ b/clang/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,
+ };
+}
+
OpenPOWER on IntegriCloud