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

Eli Friedman eli.friedman at gmail.com
Fri Jun 14 10:26:45 PDT 2013


On Fri, Jun 14, 2013 at 10:01 AM, Faisal Vali <faisalv at gmail.com> wrote:

> On Thu, Jun 13, 2013 at 12:58 PM, Eli Friedman <eli.friedman at gmail.com>
> wrote:
> > On Tue, Jun 11, 2013 at 10:05 PM, Faisal Vali <faisalv at gmail.com> wrote:
> > @@ -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.
> >
>
> I see, but how do you suggest I access this data when I need it?
>

If you really do need it all, it's okay, I guess... it was just a bit
surprising at first glance.  Taking another look, it doesn't look like
you're actually using getLambdaConversionOperator() (and in clang's
implementation, lambdas can have multiple conversion operators).


>
> >
> > +      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.
> >
>
> Thanks!  What is the difference between the two?
>

getOriginalType() returns the undecayed type; getType() returns the
semantic type of the declaration.


>
> > +      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?
> >
>
>
> In my initial implementation of generic lambdas, I had encased this
> transformation
> entirely within ActOnStartOfLambdaDefinition (which is called once the
> parameter
> declaration clause has been constructed).   In that version, I
> reconstructed
> the typesourceinfo and function type of the call operator after it was
> initially
> parsed and semanalyzed, by replacing each auto with a template type
> paramater,
> creating the template prameter list, and using a visitor to fix all
> subsequent references (ugh!)
>
> Based on sage advice from Doug, I moved the transformation upstream
> and the code changes
> have proved to be much leaner.
>

Okay.

In regards to avoiding having the Parser inspect AST types What I
> could do is nest
> ActOnAutoParameter within ActOnParamDeclarator.  Is it ok that I pass
> in a vector
> of TemplateTypeParamDecl* as an out parameter to
> ParseParameterDeclarationClause
> which I will then need to pass in to ActOnParamDeclarator? Or is it
> important that I find a way to do it without passing that vector around?
>

That should be fine.


> > +// 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.
> >
>
> I figured it might be less brittle if more uses cropped up in the future.
>  But
> I can just insert the name: "__invoker" in the one place i need it, and
> drop
> this function?
>

I think so.  We can always change it when we add more uses.


> > +  // 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.
> >
>
>
> Does my workaround seem reasonable?
>
>
Sorry, I'm not really an expert on template instantiation.  Hopefully Doug
will chime in.

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


More information about the cfe-commits mailing list