[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