return isDeletingDtor(GD);
}
-static bool isTrivialForAArch64MSVC(const CXXRecordDecl *RD) {
- // For AArch64, we use the C++14 definition of an aggregate, so we also
+static bool isTrivialForMSVC(const CXXRecordDecl *RD) {
+ // We use the C++14 definition of an aggregate, so we also
// check for:
// No private or protected non static data members.
// No base classes
if (!RD)
return false;
- // Normally, the C++ concept of "is trivially copyable" is used to determine
- // if a struct can be returned directly. However, as MSVC and the language
- // have evolved, the definition of "trivially copyable" has changed, while the
- // ABI must remain stable. AArch64 uses the C++14 concept of an "aggregate",
- // while other ISAs use the older concept of "plain old data".
- bool isTrivialForABI = RD->isPOD();
- bool isAArch64 = CGM.getTarget().getTriple().isAArch64();
- if (isAArch64)
- isTrivialForABI = RD->canPassInRegisters() && isTrivialForAArch64MSVC(RD);
+ bool isTrivialForABI = RD->canPassInRegisters() && isTrivialForMSVC(RD);
// MSVC always returns structs indirectly from C++ instance methods.
bool isIndirectReturn = !isTrivialForABI || FI.isInstanceMethod();
// On AArch64, use the `inreg` attribute if the object is considered to not
// be trivially copyable, or if this is an instance method struct return.
- FI.getReturnInfo().setInReg(isAArch64);
+ FI.getReturnInfo().setInReg(CGM.getTarget().getTriple().isAArch64());
return true;
}
// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 %s
+// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 --check-prefix WIN %s
+// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA --check-prefix WIN %s
+// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 --check-prefix WIN %s
+// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 --check-prefix WIN %s
struct Empty {};
int i;
};
+struct SmallWithSmallWithPrivate {
+ SmallWithPrivate p;
+};
+
// WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
// WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca(<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>)
// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret(%struct.SmallWithPrivate) align 4 %agg.result, i64 %s.coerce) {{.*}} {
SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+// WOA64: define dso_local i32 @"?small_arg_with_small_struct_with_private_member@@YA?AUSmallWithSmallWithPrivate@@U1@@Z"(i64 %s.coerce) {{.*}} {
+// WIN64: define dso_local i32 @"?small_arg_with_small_struct_with_private_member@@YA?AUSmallWithSmallWithPrivate@@U1@@Z"(i32 %s.coerce) {{.*}} {
+SmallWithSmallWithPrivate small_arg_with_small_struct_with_private_member(SmallWithSmallWithPrivate s) { return s; }
+
void call_small_arg_with_dtor() {
small_arg_with_dtor(SmallWithDtor());
}
// WIN64-LABEL: define dso_local void @"?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* {{[^,]*}} %this)
// WIN64: declare dso_local void @"?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8* noundef, i32)
}
+
+namespace protected_member_of_member {
+struct field { protected: int i; };
+struct t1 {
+ field f;
+};
+extern const t1& v1;
+t1 f1() { return v1; }
+// WIN: define dso_local {{.*}}i32 @"?f1@protected_member_of_member@@YA?AUt1@1@XZ"()
+}
+
+namespace default_member_initializer {
+struct t1 {
+ int i = 3;
+};
+extern const t1& v1;
+t1 f1() { return v1; }
+// WIN: define dso_local {{.*}}i32 @"?f1@default_member_initializer@@YA?AUt1@1@XZ"()
+}
+
+namespace defaulted_copy_ctor {
+struct t1 {
+ int i;
+ t1(const t1&) = default;
+};
+extern const t1& v1;
+t1 f1() { return v1; }
+// WIN: define dso_local {{.*}}i32 @"?f1@defaulted_copy_ctor@@YA?AUt1@1@XZ"()
+}