[PATCH] Step 1: Simple Generic lambda (no captures or return type deduction)
Faisal Vali
faisalv at gmail.com
Tue Jun 11 22:05:04 PDT 2013
Hello,
Attached is a patch that implements a very simple form of generic lambdas
that allows 'auto' and variadic 'auto' as parameters in lambdas. This
allows the
following code to compile:
auto Fact = [](auto Self, unsigned n) -> unsigned {
return !n ? 1 : Self(Self, n - 1) * n;
};
auto six = Fact(Fact, 3);
What is not included: (and what I plan to incrementally add once this patch
has been approved, in order of appearance):
- return type deduction
- capturing variables in generic lambdas
- supporting nested capturing generic lambdas
- conversion to function pointer
- full variadic capturing support
- ensuring all visitors/readers are generic lambda aware.
In this rendition of the patch, i have some comments prefaced with FVQUESTION?
I intend to remove these comments prior to commit once someone has
answered them.
As an example, does anyone know the answer to this question which
occurs within Sema::InstantiateFunctionDefintion
(SemaTemplateInstantiateDecl.cpp):
// FVQUESTION? When a generic lamdba call operator is being instantiated, if
// for some reason instantiation fails, the SemaDiagnosticEmitter ends up
// emitting the entire instantiation stack, and since local pending
// instantiations are called recursively, misleading information gets
// dumped for e.g:
// int main() {
// {
// auto L = [](auto a) -> int { return a + 3; };
// L(3); <-- 1
// }
// {
// auto L = [](auto a) -> int { return a + 5; };
// L(4); <-- 2
// struct M { } m;
// L(m); <-- 3
// }
// }
//
// When the call @ 3 is being isntantiated, and fails because m
// has no addition operator defined, clang prints the following
// error:
// <file>:48:43: error: invalid operands to binary expression
// ('M' and 'int')
// auto L = [](auto a) -> int { return a + 5; };
// ~ ^ ~
// <file>:51:6: note: in instantiation of function template
// specialization 'main()::<anonymous class>::operator()<M>' requested here
// L(m);
// ^
// <file>:49:6: note: in instantiation of function template
// specialization 'main()::<anonymous class>::operator()<int>' requested here
// L(4);
// ^
// <file>:44:6: note: in instantiation of function template
// specialization 'main()::<anonymous class>::operator()<int>' requested here
// L(3);
// I am not sure i understand why we need to recursively instantiate these
// templates. This may have to do with preserving the local instantiation
// scope for those templates nested within others.
// What follows is a naive attempt to fix this:
// - the fix assumes that all instantiations that are "nested" within this
// one, will be added to the pending-isntantiations queue during
// transformation of the body of this template function.
// - so if the number of pending local instantiations or pending
// instantiations increases after having transformed the body of a
// generic lambda call operator, only then recursively instantiate
// pending instantiations.
//
// I will be the first to admit that this fix has a bad smell to it - but
// I need help ascertaining its origin.
// Any thoughts on how to better address it? or whether we should ignore
// this issue entirely for now?
Look forward to your review and feedback.
thanks!
Faisal Vali
-------------- next part --------------
A non-text attachment was scrubbed...
Name: simple-generic-lambda-1.patch
Type: application/octet-stream
Size: 60973 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130612/e3ae97d8/attachment.obj>
More information about the cfe-commits
mailing list