]> granicus.if.org Git - clang/commitdiff
Introduce a new expression node, ImplicitValueInitExpr, that
authorDouglas Gregor <dgregor@apple.com>
Thu, 29 Jan 2009 17:44:32 +0000 (17:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 29 Jan 2009 17:44:32 +0000 (17:44 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63317 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/AST/StmtNodes.def
lib/AST/Expr.cpp
lib/AST/StmtPrinter.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGExprComplex.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaInit.cpp
test/CodeGen/designated-initializers.c [new file with mode: 0644]

index 10b877ac891f3fb6b11129e818b25b67e6db821e..c6ac007a1316ddf8740f812a6e73dff3cc3e99da 100644 (file)
@@ -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
 //===----------------------------------------------------------------------===//
index e8d4a56c5075ecf3fc162ccc282ed628217f4b4b..18b8dbebfedefb49a2f47c7671cc6abdd8ebd37f 100644 (file)
@@ -86,6 +86,7 @@ STMT(CompoundLiteralExpr   , Expr)
 STMT(ExtVectorElementExpr  , Expr)
 STMT(InitListExpr          , Expr)
 STMT(DesignatedInitExpr    , Expr)
+STMT(ImplicitValueInitExpr , Expr)
 STMT(VAArgExpr             , Expr)
 
 // GNU Extensions.
index c1c8084cd59999b10635d902247253128d9c9a66..8a041982936cd5c92bdff4d92f35168c23ae50fd 100644 (file)
@@ -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();
index 7a558ab8dd7b8907b6167e07585de60baaf6d5da..27bab206a4e8fb6a974d62cfe8ee5d5c60d4a1e3 100644 (file)
@@ -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());
index b487bacc711070169a89917935497ea31ecce1a9..f985763b5c39478b91c2fe0c657829597cd5b341 100644 (file)
@@ -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 {
index 73fceedee5fe0e8c0bf2bf39359500e9a24e15ff..387635cb064a9d6eab6dd18ffca148f42572dac6 100644 (file)
@@ -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;
index e523ab3acf2e119432d07ab294026fc45d3c0ad0..3aedf9bc7f7839eb217f5a447a456c49e483a208 100644 (file)
@@ -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
index dd8b30041e707cea9291817d1ef4b889a993916b..f855e23ba03f9f2261417550a17955890eaf4b47 100644 (file)
@@ -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());
index 7572560be1952b1c7297b4e28bbab07714e76bc2..1559213fcb8e8bc2a5013d858f67c9f5867c856d 100644 (file)
@@ -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;
index 527f965dc3f6118b58e9b88055e037c5c0cb06c9..5d7f705edb120d3a919cc29ce95da938d0c5165c 100644 (file)
@@ -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 (file)
index 0000000..0605b24
--- /dev/null
@@ -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,
+    };
+}
+