From e78fac5126cfab4c9bf35d3a478239b38825b17b Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 5 Apr 2018 20:52:58 +0000 Subject: PR36992: do not store beyond the dsize of a class object unless we know the tail padding is not reused. We track on the AggValueSlot (and through a couple of other initialization actions) whether we're dealing with an object that might share its tail padding with some other object, so that we can avoid emitting stores into the tail padding if that's the case. We still widen stores into tail padding when we can do so. Differential Revision: https://reviews.llvm.org/D45306 llvm-svn: 329342 --- clang/test/CodeGenCXX/tail-padding.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 clang/test/CodeGenCXX/tail-padding.cpp (limited to 'clang/test/CodeGenCXX/tail-padding.cpp') diff --git a/clang/test/CodeGenCXX/tail-padding.cpp b/clang/test/CodeGenCXX/tail-padding.cpp new file mode 100644 index 00000000000..c3089bfe5e6 --- /dev/null +++ b/clang/test/CodeGenCXX/tail-padding.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s + +// PR36992 +namespace Implicit { + struct A { char c; A(const A&); }; + struct B { int n; char c[3]; ~B(); }; + struct C : B, virtual A {}; + static_assert(sizeof(C) == sizeof(void*) + 8); + C f(C c) { return c; } + + // CHECK: define {{.*}} @_ZN8Implicit1CC1EOS0_ + // CHECK: call void @_ZN8Implicit1AC2ERKS0_( + // Note: this must memcpy 7 bytes, not 8, to avoid trampling over the virtual base class. + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 7, i1 false) + // CHECK: store i32 {{.*}} @_ZTVN8Implicit1CE +} + +namespace InitWithinNVSize { + // This is the same as the previous test, except that the A base lies + // entirely within the nvsize of C. This makes it valid to copy at the + // full width. + struct A { char c; A(const A&); }; + struct B { int n; char c[3]; ~B(); }; + struct C : B, virtual A { char x; }; + static_assert(sizeof(C) > sizeof(void*) + 8); + C f(C c) { return c; } + + // CHECK: define {{.*}} @_ZN16InitWithinNVSize1CC1EOS0_ + // CHECK: call void @_ZN16InitWithinNVSize1AC2ERKS0_( + // This copies over the 'C::x' member, but that's OK because we've not initialized it yet. + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i1 false) + // CHECK: store i32 {{.*}} @_ZTVN16InitWithinNVSize1CE + // CHECK: store i8 +} -- cgit v1.2.3