This revision was automatically updated to reflect the committed changes.
Closed by commit rL242127: Fix for clang memcpyizer bugs 23911 and 23924 (patch 
by Denis Zobnin) (authored by ABataev).

Changed prior to commit:
  http://reviews.llvm.org/D10990?vs=29540&id=29651#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D10990

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

Index: cfe/trunk/test/CodeGenCXX/eh-aggregated-inits.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/eh-aggregated-inits.cpp
+++ cfe/trunk/test/CodeGenCXX/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;
+}
Index: cfe/trunk/test/CodeGenCXX/eh-aggregated-inits-unwind.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/eh-aggregated-inits-unwind.cpp
+++ cfe/trunk/test/CodeGenCXX/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: cfe/trunk/lib/CodeGen/CGClass.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp
+++ cfe/trunk/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
@@ -1072,6 +1077,7 @@
           CopyingValueRepresentation CVR(CGF);
           EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
                                 AggregatedInits[0], ConstructorDecl, Args);
+          AggregatedInits.clear();
         }
         reset();
         return;
@@ -1088,10 +1094,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);
       }
     }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to