Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang vs gcc: variadic lambda captures

I am trying to capture a variadic lambda argument inside a inner lambda and use it there. As an example, consider this code:

int main () {
    auto first = [&] (auto&&... one) {
        auto second = [&] (auto&&... two) {
            return ((one * two) + ...);
        };
        return second(one...);
    };
    return first(5);
}

This works with gcc9 but fails with clang8 (https://godbolt.org/z/i2K9cK).

A way to make the code compile is to explicitly capture [&one...], but i was wondering whether this is a bug in clang.

Also interesting: Changing the return statement to something where one is directly expanded (before combining with two), this compiles again: return (((one * ...) * two) + ...);

I have found this related post, but the bug declared there seems to be fixed in clang8.

like image 706
nnolte Avatar asked May 29 '19 08:05

nnolte


People also ask

What is the difference between GCC and Clang?

GCC usually produces faster code if you target x86/x86-64. For ARM the situation is ambiguous, often Clang optimizes better. Also, AFAIK Clang does not support optimization for code size.

Who has the better error diagnostics GCC or Clang?

GCC and Clang have always been trying to prove who has the better error diagnostics. Clang first dissed GCC in their “Expressive Diagnostics”article. GCC improved their diagnostics and released their comeback article, titled “Clang Diagnostics Comparison”.

Which is better clang or MSVC?

Clang clearly won here, with MSVC in second. GCC didn't recognize the second error, and the "expected ';' before 'return'" errors from MSVC and GCC are like saying that to climb a tree, I must put the tree below me. It is technicallytrue, but it is stupid.

What is the difference between GCC and LLVM?

Of course there are differences, for example LLVM enables auto-vectorizer at -O2 while GCC only enables it by default at -O3, however How come Clang in the last two years have caught up with GCC in version numbers?


1 Answers

This is a bug in Clang. It has been reported. Per comment:

Fixed in r362358.

(Side note: Clang seems to have difficulty with pack-expansions in captures in general. Let's roll out our own version of the closure type generated for the generic lambda first:

struct __closure_first {
    template <typename... Args>
    auto operator()(Args&&... one) const
    {
        auto second = [&] (auto&&... two) {
            return ((one * two) + ...);
        };
        return second(one...);
    }
};

Clearly, this is not a real closure type, and non-closure local classes cannot have member function templates. Putting this in the global scope, GCC still works and Clang still fails.)

like image 159
L. F. Avatar answered Sep 20 '22 14:09

L. F.