Skip to content

Commit 12e455a

Browse files
Merge pull request swiftlang#27353 from ravikandhadai/constexpr-test
[Constant Evaluator][Test] Add tests to check whether fatal errors are detected
2 parents bacbdb8 + 8f96e8f commit 12e455a

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

lib/SILOptimizer/UtilityPasses/ConstantEvaluableSubsetChecker.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ class ConstantEvaluableSubsetChecker : public SILModuleTransform {
7474
if (isa<ReturnInst>(inst))
7575
break;
7676

77-
assert(!previousEvaluationHadFatalError &&
78-
"cannot continue evaluation of test driver as previous call "
79-
"resulted in non-skippable evaluation error.");
80-
8177
auto *applyInst = dyn_cast<ApplyInst>(inst);
8278
SILFunction *callee = nullptr;
8379
if (applyInst) {
@@ -89,6 +85,16 @@ class ConstantEvaluableSubsetChecker : public SILModuleTransform {
8985

9086
if (!applyInst || !callee ||
9187
!callee->hasSemanticsAttr(constantEvaluableSemanticsAttr)) {
88+
89+
// Ignore these instructions if we had a fatal error already.
90+
if (previousEvaluationHadFatalError) {
91+
if (isa<TermInst>(inst)) {
92+
assert(false && "non-constant control flow in the test driver");
93+
}
94+
++currI;
95+
continue;
96+
}
97+
9298
std::tie(nextInstOpt, errorVal) =
9399
stepEvaluator.tryEvaluateOrElseMakeEffectsNonConstant(currI);
94100
if (!nextInstOpt) {
@@ -100,6 +106,10 @@ class ConstantEvaluableSubsetChecker : public SILModuleTransform {
100106
continue;
101107
}
102108

109+
assert(!previousEvaluationHadFatalError &&
110+
"cannot continue evaluation of test driver as previous call "
111+
"resulted in non-skippable evaluation error.");
112+
103113
// Here, a function annotated as "constant_evaluable" is called.
104114
llvm::errs() << "@" << demangleSymbolName(callee->getName()) << "\n";
105115
std::tie(nextInstOpt, errorVal) =

test/SILOptimizer/constant_evaluable_subset_test.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,19 @@ func interpretDivideByZero() -> Int {
350350
return testDivideByZero(127, 0)
351351
}
352352

353+
// CHECK-LABEL: @testDividingFullWidthByZero
354+
// CHECK: error: not constant evaluable
355+
@_semantics("constant_evaluable")
356+
func testDividingFullWidthByZero(_ x: Int, _ y: Int, _ z: UInt) -> Int {
357+
return x.dividingFullWidth((y, z)).1
358+
} // CHECK: note: {{.*}}: Division by zero
359+
// CHECK: note: operation performed during this call traps
360+
361+
@_semantics("test_driver")
362+
func interpretDividingFullWidthByZero() -> Int {
363+
return testDividingFullWidthByZero(0, 1, 1)
364+
}
365+
353366
// CHECK-LABEL: @testDivideOverflow
354367
// CHECK: error: not constant evaluable
355368
@_semantics("constant_evaluable")
@@ -364,6 +377,20 @@ func interpretDivideOverflow() -> Int8 {
364377
return testDivideOverflow(-128, -1)
365378
}
366379

380+
// CHECK-LABEL: @testDistance
381+
// CHECK: error: not constant evaluable
382+
@_semantics("constant_evaluable")
383+
func testDistance(_ x: UInt, _ y: UInt) -> Int {
384+
return x.distance(to: y)
385+
// CHECK: note: {{.*}}: Distance is not representable in Int
386+
// CHECK: note: operation performed during this call traps
387+
}
388+
389+
@_semantics("test_driver")
390+
func interpretDistanceTest() -> Int {
391+
return testDistance(0, UInt.max)
392+
}
393+
367394
// CHECK-LABEL: @testInOut
368395
// CHECK-NOT: error:
369396
@_semantics("constant_evaluable")

0 commit comments

Comments
 (0)