Issue
I just upgraded my compiler to GCC 11.1.0 and having trouble trying to compile my program that uses LLVM.
The error that occurs is the following:
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) {}
| ~^~~~~
| )
I've looked at the source code but wasn't sure whether LLVM's code is ill-formed, or it's a GCC bug.
The error at line 1793 in STLExtra.h is related to the definition of a class:
template <typename R> struct result_pair {
...
result_pair<R>(const result_pair<R> &Other)
: Index(Other.Index), Iter(Other.Iter) {}
...
};
Usually, when I define a class with template parameters, I don't put the template parameters in the declaration of the constructor (i.e. result_pair(...)
).
And indeed, my program compiled fine when I modified the constructors from result_pair<R>(...)
to result_pair(...)
(Did the same for enumerator_iter
).
So, is LLVM's code wrong and GCC is correct? Or is this a GCC regression? My knowledge of the C++ standard is too limited to effectively Google to check whether this is a known bug or not... Any help is greatly appreciated.
Also, I tried compiling my program using clang-11 but it fails to compile at all because the C++20 features are not there yet (specifically, it fails somewhere in with templates). So, I couldn't narrow down the culprit that way.
P.S. Since it compiles just fine with the modification, I guess I'll just leave the header modified for now.
Solution
You mention you're using C++20. This is indeed an error as of C++20: the use of simple-template-ids for constructors was deemed error-prone and redundant, and removed. See [diff.cpp17.class]/2.
As you mentioned, you can fix the error by using an injected class name instead:
template <typename R>
struct result_pair {
// ...
result_pair(const result_pair &Other)
: Index(Other.Index), Iter(Other.Iter) {}
// ...
};
In particular, this prevents accidentally using the wrong template parameters in the constructor declaration, which obviously should not compile.
Answered By - N. Shead