[PATCH] Step 1: Simple Generic lambda (no captures or return type deduction)

Eli Friedman eli.friedman at gmail.com
Thu Jun 13 10:58:23 PDT 2013


On Tue, Jun 11, 2013 at 10:05 PM, Faisal Vali <faisalv at gmail.com> wrote:

> 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);
>

Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp (revision 183717)
+++ lib/Serialization/ASTReader.cpp (working copy)
@@ -4704,7 +4704,10 @@
     QualType Deduced = readType(*Loc.F, Record, Idx);
     bool IsDecltypeAuto = Record[Idx++];
     bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
-    return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
+    //FIXME: How do we figure out if this needs to be a parameter pack?

By making the corresponding change to ASTWriter.cpp.

@@ -547,6 +550,18 @@

     /// \brief The type of the call method.
     TypeSourceInfo *MethodTyInfo;
+
+    /// \brief The Lambda call method
+    CXXMethodDecl *CallOperator;
+
+    /// \brief The Lambda conversion operator, for non-capturing lambdas
+    CXXConversionDecl *ConversionOperator;
+
+    /// \brief The Lambda static method invoker, for non-capturing lambdas
+    CXXMethodDecl *StaticInvoker;
+
+    LambdaExpr *ParentLambdaExpr;

It's not obvious why you're making this change... we try to keep the AST as
small as possible.


+      ParmVarDecl *PVD = cast<ParmVarDecl>(Param);
+      // Handle 'auto' within a generic lambda.
+      // FVQUESTION: Should I use getOriginalType here - how do i
+      // know when to use which?
+      QualType ParamType = PVD->getType();

If you're unsure, getType() is probably the right choice... I don't think
it matters here, though.

+      if (getLangOpts().CPlusPlus1y && ParamType->getContainedAutoType())
{
+        TemplateTypeParmDecl *TemplateParam =
+            Actions.ActOnLambdaAutoParameter(getCurScope(), PVD,
+                          CurTemplateDepth, CurAutoParameterIndex);
+        TemplateParams.push_back(TemplateParam);
+      }

We generally prefer to avoid having code in Parser/ inspect AST types.  Can
you move building the TemplateParameterList into
ActOnStartOfLambdaDefinition?

+// The name of the static invoker function that will forward
+// to the corresponding lambda call operator.
+static inline const char* getSecretLambdaStaticInvokerStringID() {
+  return "__invoker";
+}

I'm not sure how this abstraction is actually helpful, given the function
only has one use.

+  // 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,

We should not be instantiating the lambda in your example more than once at
the same time.  If we are, it's probably a bug.


-Eli
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130613/7b763424/attachment.html>


More information about the cfe-commits mailing list