[cfe-dev] Class Template Argument Deduction failure
Nicolas Lesser via cfe-dev
cfe-dev at lists.llvm.org
Mon Apr 29 07:13:14 PDT 2019
Lorenzo Cavallini via cfe-dev wrote:
> Hello everyone,
> I'm writing to report what I think is an issue related to Class Template
> Argument Deduction (CTAD for short). Compiling this short snippet:
>
> #include <cstdio>
> #include <vector>
>
> template<typename T>
> void printV(const std::vector<T>& v)
> {
> if (v.size() == 1) {
> printf("%d ", v[0]);
> return;
> }
> int middle = v.size()/2;
> printV(std::vector{v.begin(), v.end()+middle});
> }
>
> int main()
> {
> std::vector<int> v = {10,1};
> printV(v);
> return 0;
> }
>
> will result in clang generating an infinite error report (at least, I left
> it running for several hours, then I stopped the process...), due to (I
> guess) wrongly deducted template arguments. If the "printf" line is
> removed, no error is generated but clang will compile for what it looks
> like forever (the process is constantly at 100% and does not stop after
> several hours).
> This has been tested also with the following versions of clang: "Apple LLVM
> version 10.0.0 (clang-1000.10.44.4)", "clang version 7.0.1 (Fedora
> 7.0.1-6.fc29)". I also tested clang 8.0 and clang-HEAD on wandbox.org ,
> with the same results (on wandbox.org the process gets killed after a
> while).
> Obviously this only happens when compiling with "--std=c++17" or
> "--std=c++2a".
> Strangely enough, I got more or less the same results with gcc (7, 8.3 and
> HEAD), so my guess is that this might be related to some ambiguity either
> on the standard or in its interpretation. Given that as far as I know,
> clang and gcc are using two completely unrelated parsers and frontends.
>
> Using () instead of {} will properly give a syntax error. So my guess is
> that this is related to both CTAD and uniform initialization because of
> std::vector having an std::initializer_list constructor. At least form what
> I could understand from the huge error output, it looks like the compiler
> is recursively instantiating std::vector<T> with T =
> std::initializer_list<some iterator type>, but this may be wrong.
>
> If required I can provide part of the huge error output, but it can be
> generated by compiling the provided snippet on wandbox.
>
> Thanks to anyone who can sort this out!
>
> Best regards,
>
> Lorenzo
Very interesting find! You are correct that this happens due to infinite template recursion, not due to a bug in the standard. Consider:
template <typename> struct tag {};
template <typename T> void f(T a) { f(tag<T>{}); }
int main() { f(1); }
This also has infinite template recursion, but in that case, gcc and clang stop after a specified -ftemplate-depth. Seems like in your specific example this limit is somehow bypassed.
--
- Nicolas
More information about the cfe-dev
mailing list