Cha*_*dia 9 c++ compiler-construction grammar compilation
今天我正在与我的编译器发生另一项国内事务时,这个问题突然出现在我的脑海中.尽管我的粉红色(由于我在工作时所做的所有分号按压),我在一个if声明之前设法错过了一个.显然,这导致编译错误:
错误C2143:语法错误:缺少';' 在"如果"之前
所以我在想"好哎呀,你为什么不能告诉我缺少分号,而不是行的行之后的问题." 然后我开始尝试其他类似的语法错误:
错误C2065:'myUndeclared':未声明的标识符
错误C2143:语法错误:在'if'之前缺少')'
等等...
现在,所有这些错误同样会带我走到问题之后,并在if声明之前抱怨某事.
考虑以下:
SomeFunction(x) //Notice, there is no ';' here
if(bSomeCondition)
{
...
}
Run Code Online (Sandbox Code Playgroud)
我收到两个编译错误:
(第265行)错误C2065:'x':未声明的标识符
(第266行)错误C2143:语法错误:缺少';' 在"如果"之前
但是,第一个错误正确告诉我行号,尽管丢失了分号.这告诉我编译器在解析时不会被绊倒,并且能够使它超过分号问题.那么,为什么编译器坚持以这种方式报告语法错误呢?在找到它们的行上报告其他错误(非语法).这是否与编译器进行多次传递有关?基本上,我希望具有C++编译器工作知识的人可以具体解释编译器正在做什么,这需要以"之前"的方式报告错误.
Ada*_*ght 22
对"为什么C/C++错误消息很糟糕"这个更普遍的问题的简短回答是"有时候C++很难解析"(它实际上没有上下文无关语法).但是,这并不是一个真正有效的原因 - 人们仍然可以制作比大多数C++编译器记录更好的诊断信息的工具.
更实际的答案是"编译器作者继承了遗留代码库,这些代码库没有重视错误消息",加上温和的"编译器作者懒惰",以及"诊断报告不是一个激动人心的问题".大多数编译器编写者会添加新的语言功能或3%的codegen性能改进,而不是在代码库上进行重大的重构以允许正确的错误报告.关于"为什么错误没有正确地定位到'导致'他们"的行的具体问题就是这样的一个例子.实际上没有技术上的原因,编译器通常无法确定;缺少a,然后告诉你最后一个;缺失语句的源跨度- 即使存在C++的一般空白不变性.只是存储这些信息(很大程度上)在历史上被忽略了.
也就是说,没有受到数十年旧代码阻碍的新编译器做得更好.看看Clang编译器,它以合理的错误消息为荣.在上诊断页显示了他们是如何比GCC更好的.这种情况的一个例子是:
$ gcc-4.2 t.c
t.c: In function 'foo':
t.c:5: error: expected ';' before '}' token
$ clang t.c
t.c:4:8: error: expected ';' after expression
bar()
^
;
Run Code Online (Sandbox Code Playgroud)
或者,更令人印象深刻:
$ cat t.cc
template<class T>
class a {}
class temp {};
a<temp> b;
struct b {
}
$ gcc-4.2 t.cc
t.cc:3: error: multiple types in one declaration
t.cc:4: error: non-template type 'a' used as a template
t.cc:4: error: invalid type in declaration before ';' token
t.cc:6: error: expected unqualified-id at end of input
$ clang t.cc
t.cc:2:11: error: expected ';' after class
class a {}
^
;
t.cc:6:2: error: expected ';' after struct
}
^
;
Run Code Online (Sandbox Code Playgroud)
看,它甚至告诉我们输入什么来解决问题!</ clang_salespitch>
Oli*_*rth 12
因为在C++中,白色空间总体上并不重要.所以这是有效的代码:
SomeFunction(x)
;if(bSomeCondition)
{
...
}
Run Code Online (Sandbox Code Playgroud)
所以编译器消息只是报告在结束之前没有出现过分号if.
在这段代码中:
SomeFunction(x)
if (y) {
}
Run Code Online (Sandbox Code Playgroud)
如你所说,错误将在第2行报告为missing ';' before 'if'.
第1行没有错.没有分号就完全有效,除了一个分号(例如点,数学运算符,赋值或指针等)之外,还可以使用几个表达式.
因此,报告上一行的错误可能并不总是有意义,请举例:
SomeFunction(x)
+= 10
- 5
// blank line
// blank line
if (y) {
}
Run Code Online (Sandbox Code Playgroud)
哪条线有错误?这条线与- 5?还是其中一条评论专栏?对于编译器,错误实际上是'if',因为它是第一个可以检测到错误的地方.要报告不同的线路,编译器会已经报到的最后一个正确解析令牌错误,而不是第一位置处检测到的错误.这听起来有些倒退,并且说//blank line1缺少分号更令人困惑,因为改变它//blank line;当然不会改变或修复错误.
顺便说一句,这不是C或C++独有的.这是在大多数解析器中报告错误的常用方法.
| 归档时间: |
|
| 查看次数: |
3837 次 |
| 最近记录: |