Skip to content

Commit 138def7

Browse files
authored
Merge pull request #65922 from hyp/eng/excp-cons-spec
[cxx-interop] evaluate default constructor's unevaluated exception sp…
2 parents bfad6af + b0dab0b commit 138def7

File tree

6 files changed

+87
-15
lines changed

6 files changed

+87
-15
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "clang/Basic/TargetInfo.h"
2929
#include "clang/CodeGen/CodeGenABITypes.h"
3030
#include "clang/CodeGen/ModuleBuilder.h"
31+
#include "clang/Sema/Sema.h"
3132
#include "llvm/IR/GlobalPtrAuthInfo.h"
3233
#include "llvm/IR/GlobalValue.h"
3334
#include "llvm/Support/Compiler.h"
@@ -4555,6 +4556,23 @@ bool IRGenModule::isForeignExceptionHandlingEnabled() const {
45554556
!clangLangOpts.IgnoreExceptions;
45564557
}
45574558

4559+
bool IRGenModule::isCxxNoThrow(clang::FunctionDecl *fd, bool defaultNoThrow) {
4560+
auto *fpt = fd->getType()->getAs<clang::FunctionProtoType>();
4561+
if (!fpt)
4562+
return defaultNoThrow;
4563+
if (fpt->getExceptionSpecType() ==
4564+
clang::ExceptionSpecificationType::EST_Unevaluated) {
4565+
// Clang might not have evaluated the exception spec for
4566+
// a constructor, so force the evaluation of it.
4567+
auto &clangSema = Context.getClangModuleLoader()->getClangSema();
4568+
clangSema.EvaluateImplicitExceptionSpec(fd->getLocation(), fd);
4569+
fpt = fd->getType()->getAs<clang::FunctionProtoType>();
4570+
if (!fpt)
4571+
return defaultNoThrow;
4572+
}
4573+
return fpt->isNothrow();
4574+
}
4575+
45584576
/// Emit the epilogue for the function.
45594577
void IRGenFunction::emitEpilogue() {
45604578
if (EarliestIP != AllocaIP)

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3343,11 +3343,9 @@ llvm::CallBase *swift::irgen::emitCXXConstructorCall(
33433343
IRGenFunction &IGF, const clang::CXXConstructorDecl *ctor,
33443344
llvm::FunctionType *ctorFnType, llvm::Constant *ctorAddress,
33453345
llvm::ArrayRef<llvm::Value *> args) {
3346-
bool canThrow = IGF.IGM.isForeignExceptionHandlingEnabled();
3347-
if (auto *fpt = ctor->getType()->getAs<clang::FunctionProtoType>()) {
3348-
if (fpt->isNothrow())
3349-
canThrow = false;
3350-
}
3346+
bool canThrow =
3347+
IGF.IGM.isForeignExceptionHandlingEnabled() &&
3348+
!IGF.IGM.isCxxNoThrow(const_cast<clang::CXXConstructorDecl *>(ctor));
33513349
if (!canThrow)
33523350
return IGF.Builder.CreateCall(ctorFnType, ctorAddress, args);
33533351
llvm::CallBase *result;

lib/IRGen/GenStruct.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -721,11 +721,8 @@ namespace {
721721
}
722722
bool canThrow = false;
723723
if (IGF.IGM.isForeignExceptionHandlingEnabled()) {
724-
if (auto *fpt =
725-
destructor->getType()->getAs<clang::FunctionProtoType>()) {
726-
if (!fpt->isNothrow())
727-
canThrow = true;
728-
}
724+
if (!IGF.IGM.isCxxNoThrow(destructor, /*defaultNoThrow=*/true))
725+
canThrow = true;
729726
}
730727
if (canThrow) {
731728
IGF.createExceptionTrapScope([&](llvm::BasicBlock *invokeNormalDest,

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,9 @@ private: \
18311831

18321832
bool isForeignExceptionHandlingEnabled() const;
18331833

1834+
/// Returns true if the given Clang function does not throw exceptions.
1835+
bool isCxxNoThrow(clang::FunctionDecl *fd, bool defaultNoThrow = false);
1836+
18341837
private:
18351838
llvm::Constant *
18361839
getAddrOfSharedContextDescriptor(LinkEntity entity,

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,12 +2890,10 @@ void IRGenSILFunction::visitFunctionRefBaseInst(FunctionRefBaseInst *i) {
28902890
FunctionPointer fp =
28912891
FunctionPointer::forDirect(fpKind, value, secondaryValue, sig, useSignature);
28922892
// Update the foreign no-throw information if needed.
2893-
if (const auto *cd = fn->getClangDecl()) {
2893+
if (auto *cd = fn->getClangDecl()) {
28942894
if (auto *cfd = dyn_cast<clang::FunctionDecl>(cd)) {
2895-
if (auto *cft = cfd->getType()->getAs<clang::FunctionProtoType>()) {
2896-
if (cft->isNothrow())
2897-
fp.setForeignNoThrow();
2898-
}
2895+
if (IGM.isCxxNoThrow(const_cast<clang::FunctionDecl *>(cfd)))
2896+
fp.setForeignNoThrow();
28992897
}
29002898
if (IGM.emittedForeignFunctionThunksWithExceptionTraps.count(fnPtr))
29012899
fp.setForeignCallCatchesExceptionInThunk();

test/Interop/Cxx/exceptions/trap-on-exception-irgen-itanium.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,33 @@ public:
131131
inline ClassWithNoThrowingConstructor() noexcept {}
132132
};
133133

134+
struct StructWithDefaultConstructor {
135+
StructWithDefaultConstructor() = default;
136+
137+
int m = 0;
138+
};
139+
140+
141+
struct NonTrivial {
142+
~NonTrivial() {}
143+
};
144+
145+
struct StructWithDefaultCopyConstructor {
146+
StructWithDefaultCopyConstructor() noexcept {}
147+
StructWithDefaultCopyConstructor(const StructWithDefaultCopyConstructor &) = default;
148+
149+
int m = 0;
150+
NonTrivial _nonTrivialPoison;
151+
};
152+
153+
struct StructWithDefaultDestructor {
154+
StructWithDefaultDestructor() noexcept {}
155+
~StructWithDefaultDestructor() = default;
156+
157+
int m = 0;
158+
NonTrivial _nonTrivialPoison;
159+
};
160+
134161
//--- test.swift
135162

136163
import CxxModule
@@ -227,6 +254,22 @@ func testClassWithNoThrowingConstructor() -> CInt {
227254
return obj.m
228255
}
229256

257+
func testStructWithDefaultConstructor() -> StructWithDefaultConstructor {
258+
return StructWithDefaultConstructor()
259+
}
260+
261+
func testStructWithDefaultCopyConstructor() -> CInt {
262+
var s = StructWithDefaultCopyConstructor()
263+
let copy = s
264+
return s.m
265+
}
266+
267+
func testStructWithDefaultDestructor() -> CInt {
268+
let s = StructWithDefaultDestructor()
269+
let result = s.m
270+
return result
271+
}
272+
230273
let _ = testFreeFunctionNoThrowOnly()
231274
let _ = testFreeFunctionCalls()
232275
let _ = testMethodCalls()
@@ -241,6 +284,9 @@ let _ = testClassWithCopyConstructor()
241284
let _ = testClassWithThrowingCopyConstructor()
242285
let _ = testClassWithThrowingConstructor()
243286
let _ = testClassWithNoThrowingConstructor()
287+
let _ = testStructWithDefaultConstructor()
288+
let _ = testStructWithDefaultCopyConstructor()
289+
let _ = testStructWithDefaultDestructor()
244290

245291
// CHECK: define {{.*}} @"$s4test0A23FreeFunctionNoThrowOnlys5Int32VyF"() #[[#SWIFTMETA:]] {
246292
// CHECK-NEXT: :
@@ -393,6 +439,18 @@ let _ = testClassWithNoThrowingConstructor()
393439
// CHECK-NOT: invoke
394440
// CHECK: }
395441

442+
// CHECK: define {{.*}} @"$s4test0A28StructWithDefaultConstructorSo0bcdE0VyF"() #[[#SWIFTMETA]] {
443+
// CHECK-NOT: invoke
444+
// CHECK: }
445+
446+
// CHECK: define {{.*}} @"$s4test0A32StructWithDefaultCopyConstructors5Int32VyF"() #[[#SWIFTMETA]] {
447+
// CHECK-NOT: invoke
448+
// CHECK: }
449+
450+
// CHECK: define {{.*}} @"$s4test0A27StructWithDefaultDestructors5Int32VyF"() #[[#SWIFTMETA]] {
451+
// CHECK-NOT: invoke
452+
// CHECK: }
453+
396454
// CHECK: i32 @__gxx_personality_v0(...)
397455

398456
// CHECK: attributes #[[#SWIFTMETA]] = {

0 commit comments

Comments
 (0)