我刚刚将我的编译器升级到了GCC 11.1.0,在尝试编译我的使用LLVM的程序时遇到了问题。
出现的错误如下:
In file included from /usr/include/llvm/IR/DebugInfo.h:19,
from /home/<redacted>/src/sword/format/llvm.hpp:12,
from /home/<redacted>/src/main.cpp:9:
/usr/include/llvm/ADT/STLExtras.h:1793:18: error: expected unqualified-id before ‘const’
1793 | result_pair<R>(const result_pair<R> &Other)
| ^~~~~
/usr/include/llvm/ADT/STLExtras.h:1793:18: error: expected ‘)’ before ‘const’
1793 | result_pair<R>(const result_pair<R> &Other)
| ~^~~~~
| )
/usr/include/llvm/ADT/STLExtras.h:1843:22: error: expected unqualified-id before ‘const’
1843 | enumerator_iter<R>(const enumerator_iter<R> &Other) : Result(Other.Result) {}
| ^~~~~
/usr/include/llvm/ADT/STLExtras.h:1843:22: error: expected ‘)’ before ‘const’
1843 | enumerator_iter<R>(const enumerator_iter<R> &Other) : Result(Other.Result) {}
| ~^~~~~
| )我已经看过源代码了,但不确定LLVM的代码是格式错误,还是有一个GCC的bug。
STLExtra.h中第1793行的错误与类的定义有关:
template <typename R> struct result_pair {
...
result_pair<R>(const result_pair<R> &Other)
: Index(Other.Index), Iter(Other.Iter) {}
...
};通常,当我使用模板参数定义一个类时,我不会将模板参数放在构造函数的声明中(即result_pair(...))。实际上,当我将构造函数从result_pair<R>(...)修改为result_pair(...) (对enumerator_iter也是如此)时,我的程序编译得很好。
那么,LLVM的代码是错的,而GCC是正确的吗?还是说这是一种GCC的回归?我对C++标准的了解太有限了,无法有效地在谷歌上检查这是否是一个已知的bug……任何帮助都是非常感谢的。
此外,我尝试使用clang-11编译我的程序,但它根本无法编译,因为C++20功能还不存在(具体地说,它在模板中的某个地方失败了)。所以,我不能这样缩小罪犯的范围。
附注:由于修改后编译得很好,我想我现在只需要修改头文件即可。
发布于 2021-05-26 12:34:30
你提到你正在使用C++20,这确实是一个错误:对于构造函数使用simple-template-ids被认为是容易出错和多余的,并被删除了。参见[diff.cpp17.class]/2。
正如您所提到的,您可以通过使用注入的类名来修复错误:
template <typename R>
struct result_pair {
// ...
result_pair(const result_pair &Other)
: Index(Other.Index), Iter(Other.Iter) {}
// ...
};特别是,这可以防止在构造函数声明中意外使用错误的模板参数,这显然是不应该编译的。
发布于 2021-10-21 14:50:09
根据N.Shead的回答,以下是一个补丁文件,可用于修复LLVM 12.0.1上的错误:
--- /usr/include/llvm/ADT/STLExtras.h.orig 2021-10-21 10:41:36.706064183 -0400
+++ /usr/include/llvm/ADT/STLExtras.h 2021-10-21 10:41:59.442775225 -0400
@@ -1820,9 +1820,9 @@
result_pair(std::size_t Index, IterOfRange<R> Iter)
: Index(Index), Iter(Iter) {}
- result_pair<R>(const result_pair<R> &Other)
+ result_pair(const result_pair &Other)
: Index(Other.Index), Iter(Other.Iter) {}
- result_pair<R> &operator=(const result_pair<R> &Other) {
+ result_pair &operator=(const result_pair &Other) {
Index = Other.Index;
Iter = Other.Iter;
return *this;
@@ -1856,22 +1856,22 @@
result_type &operator*() { return Result; }
const result_type &operator*() const { return Result; }
- enumerator_iter<R> &operator++() {
+ enumerator_iter &operator++() {
assert(Result.Index != std::numeric_limits<size_t>::max());
++Result.Iter;
++Result.Index;
return *this;
}
- bool operator==(const enumerator_iter<R> &RHS) const {
+ bool operator==(const enumerator_iter &RHS) const {
// Don't compare indices here, only iterators. It's possible for an end
// iterator to have different indices depending on whether it was created
// by calling std::end() versus incrementing a valid iterator.
return Result.Iter == RHS.Result.Iter;
}
- enumerator_iter<R>(const enumerator_iter<R> &Other) : Result(Other.Result) {}
- enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
+ enumerator_iter(const enumerator_iter &Other) : Result(Other.Result) {}
+ enumerator_iter &operator=(const enumerator_iter &Other) {
Result = Other.Result;
return *this;
}将上述内容保存到~/STLExtras.h.patch,然后通过以下方式应用补丁:
$ sudo patch --backup /usr/include/llvm/ADT/STLExtras.h ~/STLExtras.h.patch
patching file /usr/include/llvm/ADT/STLExtras.h原件将被保存到/usr/include/llvm/ADT/STLExtras.h.orig,您可以保留或删除它。
https://stackoverflow.com/questions/67698523
复制相似问题