Skip to content

Commit 4d65c34

Browse files
Merge pull request #29521 from ravikandhadai/constexpr-precondition-support
[Constant Evaluator] Add support for displaying assertion/precondition failure messages and fatalError messages
2 parents 39d28fc + 682bb31 commit 4d65c34

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

lib/SILOptimizer/Utils/ConstExpr.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,13 @@ extractStaticStringValue(SymbolicValue staticString) {
784784
return staticStringProps[0].getStringValue();
785785
}
786786

787+
static Optional<StringRef>
788+
extractStringOrStaticStringValue(SymbolicValue stringValue) {
789+
if (stringValue.getKind() == SymbolicValue::String)
790+
return stringValue.getStringValue();
791+
return extractStaticStringValue(stringValue);
792+
}
793+
787794
/// If the specified type is a Swift.Array of some element type, then return the
788795
/// element type. Otherwise, return a null Type.
789796
static Type getArrayElementType(Type ty) {
@@ -829,8 +836,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply,
829836
for (unsigned i = 0; i < apply->getNumArguments(); i++) {
830837
SILValue argument = apply->getArgument(i);
831838
SymbolicValue argValue = getConstantValue(argument);
832-
Optional<StringRef> stringOpt = extractStaticStringValue(argValue);
833-
839+
Optional<StringRef> stringOpt =
840+
extractStringOrStaticStringValue(argValue);
834841
// The first argument is a prefix that specifies the kind of failure
835842
// this is.
836843
if (i == 0) {
@@ -842,7 +849,6 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply,
842849
}
843850
continue;
844851
}
845-
846852
if (stringOpt) {
847853
message += ": ";
848854
message += stringOpt.getValue();

test/SILOptimizer/constant_evaluable_subset_test.swift

+32
Original file line numberDiff line numberDiff line change
@@ -925,3 +925,35 @@ func interpretBinaryIntegerDescription() -> String {
925925
str += testBinaryIntegerDescription(UInt(20))
926926
return str
927927
}
928+
929+
// CHECK-LABEL: @testPreconditionFailure
930+
// CHECK: error: not constant evaluable
931+
@_semantics("constant_evaluable")
932+
func testPreconditionFailure(_ x: Int) -> Int {
933+
precondition(x > 0, "argument must be positive")
934+
return x + 1
935+
// CHECK: note: operation traps
936+
// Note that the message displayed depends on the assert configuration,
937+
// therefore it is not checked here. For debug stdlib, the full message
938+
// must be displayed.
939+
}
940+
941+
@_semantics("test_driver")
942+
func interpretPreconditionFailure() -> Int {
943+
return testPreconditionFailure(-10)
944+
}
945+
946+
// CHECK-LABEL: @testFatalError
947+
// CHECK: error: not constant evaluable
948+
@_semantics("constant_evaluable")
949+
func testFatalError() -> Int {
950+
fatalError("invoked an uncallable function")
951+
return 0
952+
// CHECK: note: Fatal error: invoked an uncallable function
953+
// CHECK: note: operation traps
954+
}
955+
956+
@_semantics("test_driver")
957+
func interpretFatalError() -> Int {
958+
return testFatalError()
959+
}

0 commit comments

Comments
 (0)