设置“Fastest -O”优化时,编译失败并显示有效代码

Posted

技术标签:

【中文标题】设置“Fastest -O”优化时,编译失败并显示有效代码【英文标题】:Compilation fails with valid code when "Fastest -O" optimizations are set 【发布时间】:2015-06-30 00:44:16 【问题描述】:

以下代码是有效的 Swift 代码,并且在禁用优化时可以正确编译。

protocol Foo 
    var bar: String  get set 


class BaseFoo: Foo 
    var bar: String = "hello"


class ChildFoo: BaseFoo 
    private var _bar: String = "world"

    override var bar: String 
        get 
            return _bar
        
        set 
            _bar = newValue
        
    

启用 Swift 优化(Fastest -O)后,我只会从 xcode 收到一条非常模糊的错误消息:

命令 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc 失败,退出代码为 1

所以我尝试运行 Xcode 说失败的命令,我能够找到更有趣的错误:

PHINode 应该为其父基本块的每个前任都有一个条目! %11 = phi i64 [ %43, %33 ], [ 0, %29 ], !dbg !747 LLVM 错误:发现损坏的函数,编译中止!

【问题讨论】:

【参考方案1】:

答案是编译器存在错误。不知何故,它在覆盖协议中定义的读写属性方面存在问题。我找不到解决方案,只有以下解决方法:

    如果在协议中将该属性设为只读(通过将 get set 更改为 get ),错误将消失。不幸的是,如果您无权访问实现类型,您将无法重写变量(而且您不应该这样做,否则您将失去协议带来的好处)

    不要覆盖子类中的属性(在我们的例子中为ChildFoo)。如果您不覆盖它,您将不会遇到此错误。另一方面,如果您不需要这样做,您可能不会覆盖它,所以这对您没有多大帮助。

    最后但并非最不重要的解决方法是为您提供覆盖支持和读写访问(嗯,有点)。将协议更改为没有变量,但有 getter 和 setter 方法。这样您就可以从外部设置值,也可以覆盖 get 或 set 的行为。

我最终使用了第三种解决方法,因为我需要读写和覆盖支持。所以最后我的代码看起来像这样:

protocol Foo 
    func getBar() -> String

    func setBar(bar: String)


class BaseFoo: Foo 
    private var bar: String = "hello"

    func getBar() -> String 
        return bar
    

    func setBar(bar: String) 
        self.bar = bar
    


class ChildFoo: BaseFoo 
    private var _bar: String = "world"

    override func getBar() -> String 
        return _bar
    

    override func setBar(bar: String) 
        _bar = bar
    

我填写了一份雷达报告 http://www.openradar.appspot.com/21603216,希望 Apple 能够修复它。我在 Swift 2.0 的新 Xcode nor没有尝试过这个。

希望这对遇到同样问题的人有所帮助。

【讨论】:

以上是关于设置“Fastest -O”优化时,编译失败并显示有效代码的主要内容,如果未能解决你的问题,请参考以下文章

当文件存在并与 onedrive 同步时,_open 失败并显示 O_TRUNC

iOS逆向之OC反汇编(上)

当 Row 接受可变参数时,为啥 Scala 编译器会失败并显示“此处不允许 ': _*' 注释”?

错误,使用 ng-cli 运行 ng serve 时编译失败

编译 GooglsMaps.Framework 时 Apple Mach O Link Key 失败

我可以让 SQL*Plus 在函数编译失败时退出并出现错误吗?