/// characters. This method does not work on incomplete types.
CharUnits getTypeAlignInChars(QualType T) const;
CharUnits getTypeAlignInChars(const Type *T) const;
+
+ // getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the
+ // type is a record, its data size is returned.
+ std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const;
std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
return toCharUnitsFromBits(Align);
}
+// getTypeInfoDataSizeInChars - Return the size of a type, in
+// chars. If the type is a record, its data size is returned. This is
+// the size of the memcpy that's performed when assigning this type
+// using a trivial copy/move assignment operator.
+std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
+ std::pair<CharUnits, CharUnits> sizeAndAlign = getTypeInfoInChars(T);
+
+ // In C++, objects can sometimes be allocated into the tail padding
+ // of a base-class subobject. We decide whether that's possible
+ // during class layout, so here we can just trust the layout results.
+ if (getLangOpts().CPlusPlus) {
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl());
+ sizeAndAlign.first = layout.getDataSize();
+ }
+ }
+
+ return sizeAndAlign;
+}
+
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
// implementation handles this case safely. If there is a libc that does not
// safely handle this, we can add a target hook.
- // Get size and alignment info for this aggregate.
+ // Get data size and alignment info for this aggregate.
std::pair<CharUnits, CharUnits> TypeInfo =
- getContext().getTypeInfoInChars(Ty);
+ getContext().getTypeInfoDataSizeInChars(Ty);
if (alignment.isZero())
alignment = TypeInfo.second;
-// RUN: %clang_cc1 -fobjc-gc -emit-llvm -triple x86_64-apple-darwin10.0.0 -fobjc-runtime=macosx-fragile-10.5 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fobjc-gc -emit-llvm -triple x86_64-apple-darwin10.0.0 -fobjc-runtime=macosx-fragile-10.5 -o - %s | FileCheck %s -check-prefix=CHECK-OBJ
+// RUN: %clang_cc1 -x c++ -emit-llvm -triple x86_64-apple-darwin10.0.0 -o - %s | FileCheck %s -check-prefix=CHECK-CPP
+#ifdef __OBJC__
struct A {
A &operator=(const A&);
A &operator=(A&);
d1 = d2;
}
-// CHECK: define linkonce_odr %struct.D* @_ZN1DaSERS_
-// CHECK: {{call.*_ZN1AaSERS_}}
-// CHECK: {{call.*_ZN1BaSERS_}}
-// CHECK: {{call.*_ZN1CaSERKS_}}
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
-// CHECK: {{call.*_ZN1BaSERS_}}
-// CHECK: br
-// CHECK: {{call.*_ZN1CaSERKS_}}
-// CHECK: {{call.*@objc_memmove_collectable}}
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}}
-// CHECK: call void @_ZN11CopyByValueC1ERKS_
-// CHECK: {{call.*_ZN11CopyByValueaSES_}}
-// CHECK: ret
+// CHECK-OBJ: define linkonce_odr %struct.D* @_ZN1DaSERS_
+// CHECK-OBJ: {{call.*_ZN1AaSERS_}}
+// CHECK-OBJ: {{call.*_ZN1BaSERS_}}
+// CHECK-OBJ: {{call.*_ZN1CaSERKS_}}
+// CHECK-OBJ: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
+// CHECK-OBJ: {{call.*_ZN1BaSERS_}}
+// CHECK-OBJ: br
+// CHECK-OBJ: {{call.*_ZN1CaSERKS_}}
+// CHECK-OBJ: {{call.*@objc_memmove_collectable}}
+// CHECK-OBJ: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}}
+// CHECK-OBJ: call void @_ZN11CopyByValueC1ERKS_
+// CHECK-OBJ: {{call.*_ZN11CopyByValueaSES_}}
+// CHECK-OBJ: ret
+#endif
+namespace PR13329 {
+#ifndef __OBJC__
+ typedef void* id;
+#endif
+ struct POD {
+ id i;
+ short s;
+ };
+
+ struct NonPOD {
+ id i;
+ short s;
+
+ NonPOD();
+ };
+
+ struct DerivedNonPOD: NonPOD {
+ char c;
+ };
+
+ struct DerivedPOD: POD {
+ char c;
+ };
+
+ void testPOD() {
+ POD a;
+ POD b;
+ // CHECK-OBJ: @objc_memmove_collectable{{.*}}i64 16
+ // CHECK-CPP: @llvm.memcpy{{.*}}i64 16
+ b = a;
+ }
+
+ void testNonPOD() {
+ NonPOD a;
+ NonPOD b;
+ // CHECK-OBJ: @objc_memmove_collectable{{.*}}i64 10
+ // CHECK-CPP: @llvm.memcpy{{.*}}i64 10
+ b = a;
+ }
+
+ void testDerivedNonPOD() {
+ DerivedNonPOD a;
+ NonPOD b;
+ DerivedNonPOD c;
+ // CHECK-OBJ: @objc_memmove_collectable{{.*}}i64 10
+ // CHECK-CPP: @llvm.memcpy{{.*}}i64 10
+ (NonPOD&) a = b;
+ // CHECK-OBJ: @objc_memmove_collectable{{.*}}i64 11
+ // CHECK-CPP: @llvm.memcpy{{.*}}i64 11
+ a = c;
+ };
+
+ void testDerivedPOD() {
+ DerivedPOD a;
+ POD b;
+ DerivedPOD c;
+ // CHECK-OBJ: @objc_memmove_collectable{{.*}}i64 16
+ // CHECK-CPP: @llvm.memcpy{{.*}}i64 16
+ (POD&) a = b;
+ // CHECK-OBJ: @objc_memmove_collectable{{.*}}i64 17
+ // CHECK-CPP: @llvm.memcpy{{.*}}i64 17
+ a = c;
+ };
+}