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

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

我有一个代码生成器,它将获取一些用户编写的代码并将其块嵌入到更大的生成文件中。我希望底层编译器在用户代码中存在缺陷时提供良好的诊断,但我也不希望生成的代码中的缺陷在不应该的情况下被错误地归因于源代码。

我打算在每个用户编写的代码块的开头发出

#line lineNum "sourceFile"
指令。但是,我找不到
#line
指令的任何文档,其中提到了一旦我离开用户提供的代码,“重置”
__LINE__
__FILE__
回到生成文件中的实际行的技术。理想的解决方案类似于 C# 预处理器的
#line default
指令。

我是否只需要跟踪我写了多少行并自己手动重置?或者是否有更好的方法,某种重置指令或哨兵值,我可以传递给

#line
来删除与用户代码的关联?

看起来这可能已经被提出过,尽管那里没有可靠的答案。为了区分这一点,我会另外询问 C++11 中缺乏答案的情况是否有所改变。

c++ c c-preprocessor
6个回答
7
投票

我之前使用过的一种技术是让我的代码生成器在想要重置行指令时在一行上单独输出一个

#
,然后使用一个简单的 awk 脚本来后处理文件并将其更改为正确的行指令:

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

2
投票

是的,您需要跟踪已输出的行数,并且需要知道要输出到的文件的名称。请记住,您指定的行号是下一行的行号。因此,如果到目前为止您已经编写了 12 行,则需要输出

#line 14 "filename"
,因为 #line 指令将出现在第 13 行,因此下一行是 14。

#line
C
中的
C++
预处理器指令没有区别。


1
投票

假设代码生成器的输入“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 ();
}

0
投票

@Novelocrat,

我之前在这里问过这个问题,并且没有发布可靠的答案,但我发现如果在指向用户代码的自动生成的代码中插入行指令,那么这就会生成自动生成的代码很难搬迁。您必须将自动生成的代码和用户代码保存在编译器可以找到它们以报告错误的位置。我认为最好在生成的代码中简单地插入用户代码的文件名和行号。在优秀的文本编辑器中,只需按几次键即可通过将光标放在文件名上来跳转到文件中的一行。

例如:在 vim 中,将光标放在文件名上,然后按

g-f

 将您带到该文件,而 
:42
 将您带到有错误的第 42 行(比如说)。

只是在这里发布这一点,以便其他提出相同问题的人也可以考虑这种替代方案。


0
投票
自 C++20 起,有

source_location 提供了一个接口来获取与 __LINE__

__FILE__
(以及更多)相同的信息。

它被标记为

constexpr

,因此应该可以用它完全替换预处理器代码,并允许您在适当的时候修改信息。


-3
投票
您尝试过

__LINE__

__FILE__
给您带来的好处吗?我相信它们取自您的 
#line
 指令(如果不是的话还有什么意义?)。

(使用 gcc-4.7.2 和 clang-3.1 进行快速测试证实了我的预感)。

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