If the return block is unreachable, clang removes it in
CodeGenFunction::FinishFunction(). This removal can leave dangling
references to values defined in the return block if the return block has
successors, which it /would/ if UBSan's return value check is emitted.
In this case, as the UBSan check wouldn't be reachable, it's better to
simply not emit it.
rdar://
59196131
if (!CurCodeDecl)
return;
+ // If the return block isn't reachable, neither is this check, so don't emit
+ // it.
+ if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty())
+ return;
+
ReturnsNonNullAttr *RetNNAttr = nullptr;
if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute))
RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>();
--- /dev/null
+// RUN: %clang_cc1 -fsanitize=nullability-return -emit-llvm %s -o - -triple x86_64-apple-macosx10.10.0 -Wno-objc-root-class | FileCheck %s
+
+// CHECK-LABEL: define internal i8* @"\01-[I init]"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+#pragma clang assume_nonnull begin
+@interface I
+- (instancetype)init __attribute__((unavailable));
+@end
+@implementation I
+- (instancetype)init __attribute__((unavailable)) { __builtin_unreachable(); }
+@end
+#pragma clang assume_nonnull end