Clang用var args [duplicate]编译调用void函数

问题描述 投票:0回答:2

这个问题在这里已有答案:

我正在尝试模拟一个项目,以便我可以测试遍历CG的选择传递,但是我被主要由于clang的奇怪编译选择而被阻止,而llvm-link进一步加剧了这种选择。我会给你一些代码:

main.c中:

#include "xos/xos.h"

int main() {

  playXOs();

  return 0;
}

xos.h:

#ifndef SLICEREXAMPLEPROJECT_XOS_H
#define SLICEREXAMPLEPROJECT_XOS_H

void playXOs();

#endif // SLICEREXAMPLEPROJECT_XOS_H

我单独编译:

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  call void(...) @playXOs()
  ret i32 0
}

declare dso_local void @playXOs(...) #1

然后链接其他文件:

define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  call void (...) bitcast (void ()* @playXOs to void (...)*)()
  ret i32 0
}

在初始编译中,如果我理解正确,认为playXOs是一个var arg函数?如果我手动编辑main.ll来更改调用站点并将前向声明更改为playXOs(...),那么链接文件中没有奇怪的bitcast。有没有人有办法解决吗?

llvm信息:

clang version 8.0.0 ([email protected]:llvm-mirror/clang.git 8ca7a0dcb7e9a0cd7bf71ff4b70e12462c16f205) ([email protected]:llvm-mirror/llvm.git e9eedd7fa6f4f861afbc7a2862f3f5504e6d340f)
Target: x86_64-unknown-linux-gnu
Thread model: posix

编辑:我忘了提到,这对我来说是一个问题,因为虽然我得到的CG包含playXOs的调用站点,但CallGraphNode有一个null函数。

c llvm llvm-clang llvm-ir
2个回答
2
投票

像“int f()”这样的声明意味着f是一个具有固定数量参数的函数,但是我们不知道有多少个参数。它不是具有可变数量参数的函数。它可能是一个带有0,1,2,3 ......参数的函数,我们只是不知道哪一个。

还要求所有参数的类型(我们不知道)是“常规促销”的结果。所以真正的函数不能是“int f(float x)”,因为调用f(3.0f)会将3.0f提升为double,然后调用就会出错。

当你实际调用say f(3.0f,(char)1)时,编译器会将3.0f提升为double,将(char)1提升为int,并且如果实际函数是“int f(double,则生成正确的代码) x,int y)“。如果猜测错误,您的应用程序可能会崩溃。

当然如果实际函数是“int f(void)”并且你调用f(),一切都很好。但你可以调用f(1),这将是未定义的行为。


0
投票

按照惯例,你花了一两个小时的感觉完全难倒,放弃并发布SO,几秒钟后找到答案。

我将标头声明更改为void playXOs(void)以明确标记为没有任何参数,并且它编译时没有任何转换或VA猜测。

有人能指出我在c规范,它说编译器不能假设f()f(void)而不是f(...)?将接受作为答案。

© www.soinside.com 2019 - 2024. All rights reserved.