重置C/C++预处理器#line物理文件/line

mrphzbgm  于 2023-10-16  发布在  C/C++
关注(0)|答案(6)|浏览(135)

我有一个代码生成器,它将接受一些用户编写的代码,并将其嵌入到一个更大的生成文件中。我希望底层编译器在用户代码中存在缺陷时提供良好的诊断,但我也不希望生成代码中的缺陷在不应该的情况下被错误地归因于源代码。
我打算在每个用户编写的代码块的开头发出#line lineNum "sourceFile"指令。然而,我找不到任何关于#line指令的文档,其中提到了一种技术,即在我离开用户提供的代码后,将__LINE____FILE__“重置”回生成文件中的实际行。理想的解决方案类似于C#预处理器的#line default指令。
我只需要记录我写了多少行,然后自己手动重置吗?或者有没有更好的方法,可以将某种重置指令或sentinel值传递给#line,以删除与用户代码的关联?
看起来这可能是posed before,尽管没有确切的答案。为了区分这一点,我还要问一下,C++11是否改变了缺乏答案的情况。

jjjwad0x

jjjwad0x1#

我以前使用过的一种技术是,当代码生成器想要重置行指令时,它会在一行中输出一个#,然后使用一个简单的awk脚本对文件进行后处理,并将其更改为正确的行指令:

#!/bin/awk -f
/^#$/ { printf "#line %d \"%s\"\n", NR+1, FILENAME; next; }
{ print; }
kyks70gy

kyks70gy2#

是的,您需要跟踪输出的行数,并且需要知道要输出到的文件的名称。请记住,您指定的行号是下一行的行号。因此,如果到目前为止已经写了12行,则需要输出#line 14 "filename",因为#line指令将在第13行执行,因此下一行是第14行。
CC++中的#line预处理器指令之间没有区别。

vxbzzdmp

vxbzzdmp3#

假设代码生成器的输入“user.code”包含以下内容:

int foo () {
   return error1 ();
}

int bar () {
   return error2 ();
}

假设你想增加它,所以它看起来基本上是这样的:

int foo () {
   return error1 ();
}

int generated_foo () {
   return generated_error1 ();
}

int bar () {
   return error2 ();
}

int generated_bar () {
   return generated_error2 ();
}

但你不想那样。您希望向生成的代码添加#line指令,以便编译器消息指示错误/警告是来自用户代码还是自动生成的代码。#line指令指示下一行代码的源代码(而不是包含#line指令的行)。

#line 1 "user.code"
int foo () {
   return error1 ();
}

#line 7 "generated_code.cpp"  // NOTE: This is line #6 of generated_code.cpp
int generated_foo () {
   return generated_error1 ();
}

#line 5 "user.code"
int bar () {
   return error2 ();
}

#line 17 "generated_code.cpp" // NOTE: This is line #16 of generated_code.cpp
int generated_bar () {
   return generated_error2 ();
}
ufj5ltwl

ufj5ltwl4#

从C++20开始,source_location提供了一个接口来获取与__LINE____FILE__相同的信息(甚至更多)。
它被标记为constexpr,因此应该可以完全替换预处理器代码,并允许您在适当的时候修改信息。

bvk5enib

bvk5enib5#

@Novelocrat,
我以前问过这个问题here,没有可靠的答案,但我发现,如果在自动生成的代码中插入指向用户代码的行指令,那么这会使自动生成的代码难以重新定位。您必须将自动生成的代码和用户代码保存在编译器可以找到它们以报告错误的位置。我认为最好在生成的代码中简单地插入用户代码的文件名和行号。在好的文本编辑器中,通过将光标放在文件名上来跳转到文件中的一行是一件很简单的事情。
例如:在Vim中,将光标放在file-name上并按g-f会将你带到文件,而:42会将你带到出现错误的第42行。
只是把这一点贴在这里,这样其他人提出同样的问题也可以考虑这个替代方案。

2skhul33

2skhul336#

你试过__LINE____FILE__给你的给予吗?我相信它们是从你的#line指令中提取的(如果不是,那还有什么意义呢?).
(使用gcc-4.7.2和clang-3.1进行的快速测试证实了我的预感)。

相关问题