d.zobnin.bugzilla removed rL LLVM as the repository for this revision.
d.zobnin.bugzilla updated this revision to Diff 29540.
d.zobnin.bugzilla added a comment.

A function to emit lvalue for any field initialization was added (it also 
drills down to the field of anonymous unions). The code was adapted to work 
with this new function.
In previous review there was a request to add a method to CXXCtorInitializer to 
get the type of the initialized member. I realized that this can be done simply 
by getAnyMember()->getType() and decided not to add this method, because the 
new code looks pretty straightforward, I think.


http://reviews.llvm.org/D10990

Files:
  lib/CodeGen/CGClass.cpp
  test/CodeGen/eh-aggregated-inits-unwind.cpp
  test/CodeGen/eh-aggregated-inits.cpp

Index: lib/CodeGen/CGClass.cpp
===================================================================
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -554,6 +554,20 @@
   return false;
 }
 
+static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF,
+                                                CXXCtorInitializer *MemberInit,
+                                                LValue &LHS) {
+  FieldDecl *Field = MemberInit->getAnyMember();
+  if (MemberInit->isIndirectMemberInitializer()) {
+    // If we are initializing an anonymous union field, drill down to the field.
+    IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
+    for (const auto *I : IndirectField->chain())
+      LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
+  } else {
+    LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
+  }
+}
+
 static void EmitMemberInitializer(CodeGenFunction &CGF,
                                   const CXXRecordDecl *ClassDecl,
                                   CXXCtorInitializer *MemberInit,
@@ -572,16 +586,7 @@
   QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
   LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
 
-  if (MemberInit->isIndirectMemberInitializer()) {
-    // If we are initializing an anonymous union field, drill down to
-    // the field.
-    IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
-    for (const auto *I : IndirectField->chain())
-      LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
-    FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
-  } else {
-    LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
-  }
+  EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS);
 
   // Special case: if we are in a copy or move constructor, and we are copying
   // an array of PODs or classes with trivial copy constructors, ignore the
@@ -1076,6 +1081,7 @@
           CopyingValueRepresentation CVR(CGF);
           EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
                                 AggregatedInits[0], ConstructorDecl, Args);
+          AggregatedInits.clear();
         }
         reset();
         return;
@@ -1092,10 +1098,14 @@
       LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
 
       for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
-        QualType FieldType = AggregatedInits[i]->getMember()->getType();
+        CXXCtorInitializer *MemberInit = AggregatedInits[i];
+        QualType FieldType = MemberInit->getAnyMember()->getType();
         QualType::DestructionKind dtorKind = FieldType.isDestructedType();
-        if (CGF.needsEHCleanup(dtorKind))
-          CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
+        if (!CGF.needsEHCleanup(dtorKind))
+          continue;
+        LValue FieldLHS = LHS;
+        EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
+        CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
       }
     }
 
Index: test/CodeGen/eh-aggregated-inits-unwind.cpp
===================================================================
--- test/CodeGen/eh-aggregated-inits-unwind.cpp
+++ test/CodeGen/eh-aggregated-inits-unwind.cpp
@@ -0,0 +1,47 @@
+// Check that destructors of memcpy-able struct members are called properly
+// during stack unwinding after an exception.
+//
+// Check that destructor's argument (address of member to be destroyed) is
+// obtained by taking offset from struct, not by bitcasting pointers.
+//
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -O0 -fno-elide-constructors -emit-llvm %s -o - | FileCheck %s
+
+struct ImplicitCopy {
+  int id;
+  ImplicitCopy() { id = 10; }
+  ~ImplicitCopy() { id = 20; }
+};
+
+struct ThrowCopy {
+  int id;
+  ThrowCopy() { id = 15; }
+  ThrowCopy(const ThrowCopy &x) {
+    id = 25;
+    throw 1;
+  }
+  ~ThrowCopy() { id = 35; }
+};
+
+struct Container {
+  int id;
+  ImplicitCopy o1;
+  ThrowCopy o2;
+
+  Container() { id = 1000; }
+  ~Container() { id = 2000; }
+};
+
+int main() {
+  try {
+    Container c1;
+    // CHECK-LABEL: main
+    // CHECK: %{{.+}} = getelementptr inbounds %struct.Container, %struct.Container* %{{.+}}, i32 0, i32 1
+    // CHECK-NOT: %{{.+}} = bitcast %struct.Container* %{{.+}} to %struct.ImplicitCopy*
+    Container c2(c1);
+
+    return 2;
+  } catch (...) {
+    return 1;
+  }
+  return 0;
+}
Index: test/CodeGen/eh-aggregated-inits.cpp
===================================================================
--- test/CodeGen/eh-aggregated-inits.cpp
+++ test/CodeGen/eh-aggregated-inits.cpp
@@ -0,0 +1,46 @@
+// Check that initialization of the only one memcpy-able struct member will not
+// be performed twice after successful non-trivial initializtion of the second
+// member.
+//
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -O0 -fno-elide-constructors -emit-llvm %s -o - | FileCheck %s
+
+int globId = 0;
+
+struct ImplicitCopy {
+  int id;
+
+  ImplicitCopy() { id = 10; }
+  ~ImplicitCopy() { id = 20; }
+};
+
+struct ExplicitCopy {
+  int id;
+
+  ExplicitCopy() { id = 15; }
+  ExplicitCopy(const ExplicitCopy &x) { id = 25; }
+  ~ExplicitCopy() { id = 35; }
+};
+
+struct Container {
+  ImplicitCopy o1; // memcpy-able member.
+  ExplicitCopy o2; // non-trivial initialization.
+
+  Container() { globId = 1000; }
+  ~Container() { globId = 2000; }
+};
+
+int main() {
+  try {
+    Container c1;
+    // CHECK-DAG: call void @llvm.memcpy
+    // CHECK-DAG: declare void @llvm.memcpy
+    // CHECK-NOT: @llvm.memcpy
+    Container c2(c1);
+
+    return 2;
+  }
+  catch (...) {
+    return 1;
+  }
+  return 0;
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to