]> granicus.if.org Git - clang/commitdiff
Fix up EmitMemberInitializer to handle many more cases.
authorEli Friedman <eli.friedman@gmail.com>
Mon, 16 Nov 2009 23:53:01 +0000 (23:53 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 16 Nov 2009 23:53:01 +0000 (23:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88999 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/member-init-struct.cpp [new file with mode: 0644]

index 442d4fc30e12ffc2c9b51d316a8aad2e2554745a..97e1868f55f51b69c53ce41b7fb3998d7853fa82 100644 (file)
@@ -1543,6 +1543,18 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
   if (Array)
     FieldType = CGF.getContext().getBaseElementType(FieldType);
 
+  // We lose the constructor for anonymous union members, so handle them
+  // explicitly.
+  // FIXME: This is somwhat ugly.
+  if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) {
+    if (MemberInit->getNumArgs())
+      CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(),
+                      LHS.isVolatileQualified());
+    else
+      CGF.EmitAggregateClear(LHS.getAddress(), Field->getType());
+    return;
+  }
+
   if (FieldType->getAs<RecordType>()) {
     assert(MemberInit->getConstructor() &&
            "EmitCtorPrologue - no constructor to initialize member");
@@ -1565,21 +1577,22 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
   assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only");
   Expr *RhsExpr = *MemberInit->arg_begin();
   RValue RHS;
-  if (FieldType->isReferenceType())
+  if (FieldType->isReferenceType()) {
     RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType,
                                     /*IsInitializer=*/true);
-  else if (FieldType->isMemberFunctionPointerType())
-    RHS = RValue::get(CGF.CGM.EmitConstantExpr(RhsExpr, FieldType, &CGF));
-  else
+    CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+  } else if (Array) {
+    CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
+  } else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) {
     RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true));
-  if (Array && !FieldType->getAs<RecordType>()) {
-    // value initialize a non-class array data member using arr() syntax in
-    // initializer list.
-    QualType Ty = CGF.getContext().getCanonicalType((Field)->getType());
-    CGF.EmitMemSetToZero(LHS.getAddress(), Ty);
-  }
-  else
     CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+  } else if (RhsExpr->getType()->isAnyComplexType()) {
+    CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(),
+                                LHS.isVolatileQualified());
+  } else {
+    // Handle member function pointers; other aggregates shouldn't get this far.
+    CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified());
+  }
 }
 
 /// EmitCtorPrologue - This routine generates necessary code to initialize
diff --git a/test/CodeGenCXX/member-init-struct.cpp b/test/CodeGenCXX/member-init-struct.cpp
new file mode 100644 (file)
index 0000000..9c0c391
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: clang-cc %s -emit-llvm-only -verify
+
+struct A {int a;};
+struct B {float a;};
+struct C {
+  union {
+    A a;
+    B b[10];
+  };
+  _Complex float c;
+  int d[10];
+  void (C::*e)();
+  C() : a(), c(), d(), e() {}
+  C(A x) : a(x) {}
+  C(void (C::*x)(), int y) : b(), c(y), e(x) {}
+};
+A x;
+C a, b(x), c(0, 2);