gpt4 book ai didi

objective-c - llvm 从在不同范围 : is that llvm's bug? 中定义的两个中选择第一个(错误的)本地结构定义

转载 作者:行者123 更新时间:2023-12-04 05:31:01 26 4
gpt4 key购买 nike

我有以下示例代码:

@interface S1 : NSObject
{
void(*fn_)();
}
@end
@implementation S1
- (void) set:(BOOL)f
{
if (f)
{
struct A { static void f() { std::cout << "1" << std::endl; } };
fn_ = A::f;
}
else
{
struct A { static void f() { std::cout << "2" << std::endl; } };
fn_ = A::f;
}
}
- (void) test { fn_(); }
@end

struct S2
{
void set(BOOL f)
{
if (f)
{
struct A { static void f() { std::cout << "1" << std::endl; } };
fn_ = A::f;
}
else
{
struct A { static void f() { std::cout << "2" << std::endl; } };
fn_ = A::f;
}
}
void test() { fn_(); }
void(*fn_)();
};

int main(int argc, const char * argv[])
{
auto s1 = [[S1 alloc] init];
[s1 set:TRUE];
[s1 test];
[s1 set:FALSE];
[s1 test];

S2 s2;
s2.set(TRUE);
s2.test();
s2.set(FALSE);
s2.test();

return 0;
}

它打印
1
1
1
2

但我期待
1
2
1
2

如果我将第二个结构的名称更改为不同的(例如“B”),则始终按预期工作。

不会出现任何警告,因此很难找出您的程序无法正常运行的原因。

这是我的无知还是 llvm 的错误?

最佳答案

它确实似乎是一个 clang 错误。 (需要注意的是,没有指定 Objective-C++ 语言的标准,所以什么是“正确的”有点悬而未决)

如果不是编译为可执行代码,而是使用这样的命令生成 LLVM IR

clang -g -std=c++11  -Wall -Wextra localstruct.mm  -emit-llvm -S
-set:方法编译成这样,突出显示了两个函数指针赋值行:
define internal void @"\01-[S1 set:]"(%0* %self, i8* %_cmd, i8 signext %f) uwtable ssp {
%1 = alloca %0*, align 8
%2 = alloca i8*, align 8
%3 = alloca i8, align 1
store %0* %self, %0** %1, align 8
call void @llvm.dbg.declare(metadata !{%0** %1}, metadata !1490), !dbg !1491
store i8* %_cmd, i8** %2, align 8
call void @llvm.dbg.declare(metadata !{i8** %2}, metadata !1492), !dbg !1491
store i8 %f, i8* %3, align 1
call void @llvm.dbg.declare(metadata !{i8* %3}, metadata !1493), !dbg !1494
%4 = load i8* %3, align 1, !dbg !1495
%5 = icmp ne i8 %4, 0, !dbg !1495
br i1 %5, label %6, label %12, !dbg !1495

; <label>:6 ; preds = %0
%7 = load %0** %1, align 8, !dbg !1497
%8 = load i64* @"OBJC_IVAR_$_S1.fn_", !dbg !1497, !invariant.load !1499
%9 = bitcast %0* %7 to i8*, !dbg !1497
%10 = getelementptr inbounds i8* %9, i64 %8, !dbg !1497
%11 = bitcast i8* %10 to void ()**, !dbg !1497

store void ()* @"_ZN10-[S1 set:]1A1fEv", void ()** %11, align 8, !dbg !1497
  br label %18, !dbg !1500

; <label>:12 ; preds = %0
%13 = load %0** %1, align 8, !dbg !1501
%14 = load i64* @"OBJC_IVAR_$_S1.fn_", !dbg !1501, !invariant.load !1499
%15 = bitcast %0* %13 to i8*, !dbg !1501
%16 = getelementptr inbounds i8* %15, i64 %14, !dbg !1501
%17 = bitcast i8* %16 to void ()**, !dbg !1501

store void ()* @"_ZN10-[S1 set:]1A1fEv", void ()** %17, align 8, !dbg !1501
  br label %18

; <label>:18 ; preds = %12, %6
ret void, !dbg !1503
}

两种情况似乎都引用了相同的功能符号 _ZN10-[S1 set:]1A1fEv .如果查看struct中方法的对应代码,它引用了两个: _ZZN2S23setEaEN1A1fEv_ZZN2S23setEaEN1A1fE_0v .

FWIW,GCC 的 Objective-C++ 编译器产生了想要的结果。请务必将错误报告给 clang 项目,不要只是解决代码中的问题。

关于objective-c - llvm 从在不同范围 : is that llvm's bug? 中定义的两个中选择第一个(错误的)本地结构定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12628892/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com