How can the operator()
of a lambda be declared as noreturn
?
Ideone accepts the following code:
#include <cstdlib>
int main() {
[]() [[noreturn]] { std::exit(1); }();
return 0;
}
Clang 3.5 rejects it with:
error: 'noreturn' attribute cannot be applied to types
You can try it in godbolt: http://goo.gl/vsuCsF
Which one is right?
Update: the relevant standard sections appear to be 5.1.2.5, 7.6.3, 7.6.4 but after reading does it still isn't 100% clear to me (i) what is the right behavior, (ii) how to mark the operator() of a lambda as noreturn
.
I concede that this wording, as is, doesn't prohibit the attribute from appearing elsewhere, but in concert with seeing no evidence anywhere in the standard for it, I don't think this is intended to work with lambda declarations.
Therefore, Clang would be correct.
It may or may not be telling that there was a patch proposal to Clang to allow GCC-style
noreturn
attributes on lambdas, but not the standard form.Unfortunately, this feature is not included in GCC's list of extensions, so I can't really see exactly what's going on here.
Clang is correct. An attribute can appertain to a function being declared, or to its type; the two are different.
[[noreturn]]
must appertain to the function itself. The difference can be seen inIndeed if you compile this in g++ it tells you that
Note that it doesn't emit a warning that
g()
actually does return.Since an "attribute-specifier-seq in the lambda-declarator appertains to the type of the corresponding function call operator or operator template" (§5.1.2 [expr.prim.lambda]/p5) rather than to that operator/operator template itself, you can't use
[[noreturn]]
there. More generally, the language provides no way for you to apply an attribute to theoperator ()
of a lambda itself.So a lambda delcarator has the following grammar the draft C++ standard section
5.1.2
Lambda expressions:and the noreturn attribute is indeed a valid attribute-specifier-seq so from a grammar perspective I don't see a restriction from section
7.6.3
Noreturn attribute it says (emphasis mine going forward):which does not seem to forbid your use but it does suggest that it is not allowed. If we look at section
7.6.4
Carries dependency attribute it says:the fact that it explicitly includes the lamda case strongly indicates that section
7.6.3
is meant to exclude lambdas and thereforeclang
would be correct. As a side note Visual Studio also rejects this code.