提问人:Bass 提问时间:10/27/2023 更新时间:10/27/2023 访问量:62
预处理前后 C 或 C++ 代码中行号:列号之间的映射
Mapping between line:column numbers in C or C++ code before and after preprocessing
问:
当 C 或 C++ 源文件中出现语法错误时,GCC 和 Clang 都会报告错误所在位置的确切行和列。例如,如果我们尝试编译以下代码片段:
#include <stdio.h>
static void f(char *arg, int ignored) {
printf("%s\n", arg);
}
#define FUNCTION(x) f(x)
#define ARG "test"
int main() {
FUNCTION(ARG);
return 0;
}
— 然后 GCC 将在(宏正文)处报告错误:7:21
a.c: In function ‘main’:
a.c:7:21: error: too few arguments to function ‘f’
7 | #define FUNCTION(x) f(x)
| ^
a.c:12:9: note: in expansion of macro ‘FUNCTION’
12 | FUNCTION(ARG);
| ^~~~~~~~
a.c:3:13: note: declared here
3 | static void f(char *arg, int ignored) {
|
而 Clang 将指向宏调用站点 ():12:2
a.c:12:2: error: too few arguments to function call, expected 2, have 1
FUNCTION(ARG);
^~~~~~~~~~~~~
a.c:7:24: note: expanded from macro 'FUNCTION'
#define FUNCTION(x) f(x)
~ ^
a.c:3:13: note: 'f' declared here
static void f(char *arg, int ignored) {
不同编译器风格和版本的输出可能略有不同,但 GCC 和 Clang 或多或少是一致的。
现在,据我了解,每当调用编译器驱动程序(如 or)时,都会首先运行预处理器 (, or , or ),并且特定于语言的编译器前端处理已经预处理的代码。gcc
clang++
gcc -E
clang -E
cpp
然而,如果我们看一下预处理的代码,它确实会有大量的注释,但原始文件中只有行号,完全缺少列号信息。例:
# 885 "/usr/include/stdio.h" 3 4
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 909 "/usr/include/stdio.h" 3 4
# 2 "a.c" 2
# 3 "a.c"
static void f(char *arg, int ignored) {
printf("%s\n", arg);
}
因此,从上面的内容来看,我们可以推断出实际上声明为 at(这是真的),并且 starts at 的定义(这也是真的)。您还可以看到代码已重新格式化(缩进级别已更改)。此处更详细地介绍了预处理器输出的格式。__uflow(...)
/usr/include/stdio.h:885
f(...)
a.c:3
现在的问题是:在向用户报告反馈时,编译器前端究竟如何在预处理代码和原始代码之间执行位置转换,因为预处理器输出显然包含的信息不足?
如果第三方工具(例如:静态分析器)只能访问原始代码和预处理代码(或者预处理代码的 AST),它如何执行相同的操作?
是否可以使用 Liblang 的 API?
答: 暂无答案
评论