diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 49e3bb41f0cc..15374e767648 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -1178,8 +1178,10 @@ bool CIRGenModule::MayDropFunctionReturn(const ASTContext &astContext, QualType ReturnType) { // We can't just disard the return value for a record type with a complex // destructor or a non-trivially copyable type. - if (ReturnType.getCanonicalType()->getAs()) { - llvm_unreachable("NYI"); + if (const RecordType *rt = + ReturnType.getCanonicalType()->getAs()) { + if (const auto *classDecl = dyn_cast(rt->getDecl())) + return classDecl->hasTrivialDestructor(); } return ReturnType.isTriviallyCopyableType(astContext); diff --git a/clang/test/CIR/CodeGen/return.cpp b/clang/test/CIR/CodeGen/return.cpp index e77dd5e1ac04..06aff8e38cf9 100644 --- a/clang/test/CIR/CodeGen/return.cpp +++ b/clang/test/CIR/CodeGen/return.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fno-strict-return -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-NOSTRICT +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fno-strict-return -emit-llvm %s -o - | FileCheck %s --check-prefix=OGCG-CHECK-NOSTRICT int &ret0(int &x) { return x; @@ -31,3 +33,34 @@ int unreachable_after_return() { // CHECK-NEXT: cir.store{{.*}} %3, %0 : !s32i, !cir.ptr // CHECK-NEXT: cir.br ^bb1 // CHECK-NEXT: } + +struct NonTrivialDefaultConstructor { + int x; + + NonTrivialDefaultConstructor() { } +}; + +// CHECK-NOSTRICT-LABEL: @_Z28nonTrivialDefaultConstructorv +// OGCG-CHECK-NOSTRICT-LABEL: @_Z28nonTrivialDefaultConstructorv +NonTrivialDefaultConstructor nonTrivialDefaultConstructor() { + // CHECK-NOSTRICT-NOT: call void @llvm.trap + // CHECK-NOSTRICT-NOT: unreachable + // OGCG-CHECK-NOSTRICT-NOT: call void @llvm.trap + // OGCG-CHECK-NOSTRICT-NOT: unreachable +} + +// Functions that return records with non-trivial destructors should always use +// the -fstrict-return optimization. + +struct NonTrivialDestructor { + ~NonTrivialDestructor(); +}; + +// CHECK-NOSTRICT-LABEL: @_Z20nonTrivialDestructorv +// OGCG-CHECK-NOSTRICT-LABEL: @_Z20nonTrivialDestructorv +NonTrivialDestructor nonTrivialDestructor() { + // CHECK-NOSTRICT: call void @llvm.trap + // CHECK-NOSTRICT-NEXT: unreachable + // OGCG-CHECK-NOSTRICT: call void @llvm.trap + // OGCG-CHECK-NOSTRICT-NEXT: unreachable +}