没有 return 语句的 Obj-C 方法如果包含 @try @catch 块则编译
Obj-C method without return statement compiles if it includes a @try @catch block
问题:如何让 Xcode 报告失踪的 return?
下面是一个新的 Xcode 11 测试应用程序。我添加了带有空@try/@catch 块和no return 值 的shouldReturnAnObject
方法。此编译和分析没有警告或错误。
#import "AppDelegate.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
- (nonnull id)shouldReturnAnObject {
@try {
} @catch (NSException *exception) {
} @finally {
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
id obj = [self shouldReturnAnObject];
NSLog(@"obj: %@", obj);
}
@end
如果我从中删除@try 块,它将无法编译并出现错误:Control reaches end of non-void function
。对于没有 return return.
的任何方法,这是我期望的行为
版本:Xcode11.5,macOS 10.15.5。没有更改构建设置。
添加 -Wall
不会改变行为。
我理解 Cocoa 最佳做法是仅将异常用作异常。真正的应用程序很少使用异常,只是为了防止真正的异常行为。我提供了一个简单的测试应用程序来关注这个问题。
我相信这种行为在 Xcode/Clang 中已经存在很长时间了。如果行为是故意的,有人可以解释为什么存在这种行为吗?whi
相关信息:我还构建了快速测试应用程序:
- C++ (Clang++):编译失败并出现错误
-Wreturn-type
- Java () :编译失败
error: missing return statement
- Objective-C++(使用.mm文件):无警告,无错误,编译成功
对我来说,这绝对是一个编译器错误。 (您可以在 https://bugs.llvm.org/ 提交错误)证据如下。
我尝试了以下方法,但问题仍然存在:
@try {} @catch (NSException *e) {}
没有 @finally
@try {} @finally {}
没有 @catch
+
而不是 -
- 地址清理器
- 未定义的行为消毒程序
-Weverything
尽管编译器拒绝生成警告,但您可以使用 LLDB 看到它生成了一个实际上完全空的方法体(启用了优化):
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
* frame #0: 0x0000000100000eb4 asdf`-[MyObj shouldReturnAnObject](self=0x0000000103108440, _cmd="shouldReturnAnObject") at main.m:23:1 [opt]
frame #1: 0x0000000100000eee asdf`main(argc=<unavailable>, argv=<unavailable>) at main.m:31:79 [opt]
frame #2: 0x00007fff684f6cc9 libdyld.dylib`start + 1
frame #3: 0x00007fff684f6cc9 libdyld.dylib`start + 1
(lldb) disassemble
asdf`-[MyObj shouldReturnAnObject]:
0x100000eb0 <+0>: pushq %rbp
0x100000eb1 <+1>: movq %rsp, %rbp
-> 0x100000eb4 <+4>: popq %rbp
0x100000eb5 <+5>: retq
0x100000eb6 <+6>: nopw %cs:(%rax,%rax)
https://godbolt.org/z/ZkF48u 显示相同,尽管程序无法 link 因为那里没有可用的 Obj-C 运行时。你可以尝试不同的编译器版本——事实上,这个问题似乎至少从 Clang 3.0.0 开始就存在了。
最后,对于某些 luck/care,您可以观察到缺少 return 值会导致未定义的行为。在这里,代替缺失的 return 值,程序只是抓取栈上已经存在的任何内容,例如字符串:
后续注意事项:
在 clang 中找到案例的功劳归功于@jtbandes。
看起来这个案例还没有实现。
https://github.com/llvm/llvm-project/blob/master/clang/lib/Analysis/CFG.cpp#L3666
他还追踪到了 11 年前最初的“FIXME”提交。
https://twitter.com/jtbandes/status/1279870326784929792
我已将 ~radar~ 反馈助手错误提交给 Apple:FB7851551
我没有 llvm 贡献者帐户,而且由于垃圾邮件,他们不接受新成员,所以不能在那里提交错误。如果别人愿意,那就太棒了。如果他们确实给我一个帐户,我也会在那里跟进错误报告。
至此,我认为案子已经结案了。也许运气好的话,它可以在今年秋天成为 SDK 的最终版本。谢谢大家帮我找到这个。
这是一个错误。在 https://llvm.org/PR46693
上有一个 LLVM 错误
问题:如何让 Xcode 报告失踪的 return?
下面是一个新的 Xcode 11 测试应用程序。我添加了带有空@try/@catch 块和no return 值 的shouldReturnAnObject
方法。此编译和分析没有警告或错误。
#import "AppDelegate.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
- (nonnull id)shouldReturnAnObject {
@try {
} @catch (NSException *exception) {
} @finally {
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
id obj = [self shouldReturnAnObject];
NSLog(@"obj: %@", obj);
}
@end
如果我从中删除@try 块,它将无法编译并出现错误:Control reaches end of non-void function
。对于没有 return return.
版本:Xcode11.5,macOS 10.15.5。没有更改构建设置。
添加 -Wall
不会改变行为。
我理解 Cocoa 最佳做法是仅将异常用作异常。真正的应用程序很少使用异常,只是为了防止真正的异常行为。我提供了一个简单的测试应用程序来关注这个问题。
我相信这种行为在 Xcode/Clang 中已经存在很长时间了。如果行为是故意的,有人可以解释为什么存在这种行为吗?whi
相关信息:我还构建了快速测试应用程序:
- C++ (Clang++):编译失败并出现错误
-Wreturn-type
- Java () :编译失败
error: missing return statement
- Objective-C++(使用.mm文件):无警告,无错误,编译成功
对我来说,这绝对是一个编译器错误。 (您可以在 https://bugs.llvm.org/ 提交错误)证据如下。
我尝试了以下方法,但问题仍然存在:
@try {} @catch (NSException *e) {}
没有@finally
@try {} @finally {}
没有@catch
+
而不是-
- 地址清理器
- 未定义的行为消毒程序
-Weverything
尽管编译器拒绝生成警告,但您可以使用 LLDB 看到它生成了一个实际上完全空的方法体(启用了优化):
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
* frame #0: 0x0000000100000eb4 asdf`-[MyObj shouldReturnAnObject](self=0x0000000103108440, _cmd="shouldReturnAnObject") at main.m:23:1 [opt]
frame #1: 0x0000000100000eee asdf`main(argc=<unavailable>, argv=<unavailable>) at main.m:31:79 [opt]
frame #2: 0x00007fff684f6cc9 libdyld.dylib`start + 1
frame #3: 0x00007fff684f6cc9 libdyld.dylib`start + 1
(lldb) disassemble
asdf`-[MyObj shouldReturnAnObject]:
0x100000eb0 <+0>: pushq %rbp
0x100000eb1 <+1>: movq %rsp, %rbp
-> 0x100000eb4 <+4>: popq %rbp
0x100000eb5 <+5>: retq
0x100000eb6 <+6>: nopw %cs:(%rax,%rax)
https://godbolt.org/z/ZkF48u 显示相同,尽管程序无法 link 因为那里没有可用的 Obj-C 运行时。你可以尝试不同的编译器版本——事实上,这个问题似乎至少从 Clang 3.0.0 开始就存在了。
最后,对于某些 luck/care,您可以观察到缺少 return 值会导致未定义的行为。在这里,代替缺失的 return 值,程序只是抓取栈上已经存在的任何内容,例如字符串:
后续注意事项:
在 clang 中找到案例的功劳归功于@jtbandes。 看起来这个案例还没有实现。 https://github.com/llvm/llvm-project/blob/master/clang/lib/Analysis/CFG.cpp#L3666
他还追踪到了 11 年前最初的“FIXME”提交。 https://twitter.com/jtbandes/status/1279870326784929792
我已将 ~radar~ 反馈助手错误提交给 Apple:FB7851551
我没有 llvm 贡献者帐户,而且由于垃圾邮件,他们不接受新成员,所以不能在那里提交错误。如果别人愿意,那就太棒了。如果他们确实给我一个帐户,我也会在那里跟进错误报告。
至此,我认为案子已经结案了。也许运气好的话,它可以在今年秋天成为 SDK 的最终版本。谢谢大家帮我找到这个。
这是一个错误。在 https://llvm.org/PR46693
上有一个 LLVM 错误