Skip to content

Commit

Permalink
Tailored error reporting when dynamic casts have nonsensical type args
Browse files Browse the repository at this point in the history
This inserts a suitably named function into the stack trace whenever
a dynamic cast failure involves a NULL source or target type.
Very often, crash logs include backtraces with function names but
no log output; with this change, such a backtrace might look like
the following -- note `TARGET_TYPE_NULL` in the function name
here to mark the missing type information:

```
 frame #0: __pthread_kill + 8
 frame swiftlang#1: pthread_kill + 288
 frame swiftlang#2: abort + 128
 frame swiftlang#3: swift::fatalErrorv()
 frame swiftlang#4: swift::fatalError()
 frame swiftlang#5: swift_dynamicCastFailure_TARGET_TYPE_NULL()
 frame swiftlang#6: swift::swift_dynamicCastFailure()
 frame swiftlang#7: ::swift_dynamicCast()
```

Resolves rdar://130630157
  • Loading branch information
tbkka committed Jul 10, 2024
1 parent 588a7db commit fac8c97
Showing 1 changed file with 42 additions and 3 deletions.
45 changes: 42 additions & 3 deletions stdlib/public/runtime/Casting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,48 @@ swift::swift_dynamicCastFailure(const void *sourceType, const char *sourceName,
message ? message : "");
}

SWIFT_NORETURN void swift::swift_dynamicCastFailure(const Metadata *sourceType,
const Metadata *targetType,
const char *message) {
SWIFT_NORETURN SWIFT_NOINLINE void
swift_dynamicCastFailure_SOURCE_AND_TARGET_TYPE_NULL(const char *message) {
swift::fatalError(0, "Unconditional cast failed. "
"Both source and target types were NULL. "
"%s\n",
message ? message : "");
}

SWIFT_NORETURN SWIFT_NOINLINE void
swift_dynamicCastFailure_SOURCE_TYPE_NULL(const Metadata *targetType, const char *message) {
std::string targetName = nameForMetadata(targetType);
swift::fatalError(0, "Unconditional cast failed. "
"Source type was NULL, target was '%s' (%p). "
"%s\n",
targetName.c_str(), targetType,
message ? message : "");
}

SWIFT_NORETURN SWIFT_NOINLINE void
swift_dynamicCastFailure_TARGET_TYPE_NULL(const Metadata *sourceType, const char *message) {
std::string sourceName = nameForMetadata(sourceType);
swift::fatalError(0, "Unconditional cast failed. "
"Source type was '%s' (%p), target type was NULL. "
"%s\n",
sourceName.c_str(), sourceType,
message ? message : "");
}

SWIFT_NORETURN SWIFT_NOINLINE void
swift::swift_dynamicCastFailure(const Metadata *sourceType,
const Metadata *targetType,
const char *message) {
if (sourceType == nullptr) {
if (targetType == nullptr) {
swift_dynamicCastFailure_SOURCE_AND_TARGET_TYPE_NULL(message);
} else {
swift_dynamicCastFailure_SOURCE_TYPE_NULL(targetType, message);
}
} else if (targetType == nullptr) {
swift_dynamicCastFailure_TARGET_TYPE_NULL(sourceType, message);
}

std::string sourceName = nameForMetadata(sourceType);
std::string targetName = nameForMetadata(targetType);

Expand Down

0 comments on commit fac8c97

Please sign in to comment.