Re: [C++ Patch] Remove is_auto_or_concept, etc

2017-05-16 Thread Adam Butcher
Sorry for not getting back to your original post Paolo.  I haven't been 
picking up mails for a while.


On 2017-05-01 16:56, Jason Merrill wrote:
On Thu, Apr 27, 2017 at 2:02 PM, Paolo Carlini 
 wrote:

On 26/04/2017 12:32, Paolo Carlini wrote:


in 2013 (2013-09-16) Adam added two slightly obscure functions and I 
can't

find much around in terms of rationale, etc:

is_auto_or_concept (const_tree type)

type_uses_auto_or_concept (tree type)



I don't think they were there in the original 2009 version on the old 
lambdas branch -- but it stagnated somewhat and when I remade it against 
mainline (4.something) it was around the time that concepts were showing 
similar semantics (in terms of implicit/abbrievated templates).  I made 
a cardinal sin and introduced an overly-generic function name expecting 
that a future concepts implementation would need to trigger at the same 
point of the parse too.  I.e. if a concept name or 'auto' is seen we 
inject an implicit template parameter (or make the "plain" function into 
a template at that point).


That intent was not well documented or published (other than in the API 
name) and, since -fconcepts is now working without any calls to this 
function, it's clearly not been necessary or has been more naturally 
done in a different way.



The latter seems completely unused (it's meant for debugging 
purposes?);




Quite possibly for debugging though maybe some refactoring got rid of 
the need for it and neglected to bin it.




the former evidently simply forwards to is_auto, and we end up in the
front-end with uses of both, which in fact are equivalent, which 
seems
weird: IMHO, if they are actually equivalent in our implementation we 
should

clearly explain that in the comment and have only one. Or what?



... replying to myself, in practice we could do the below, which 
certainly
passes testing, and in fact now seems to me even more obvious than I 
thought

a couple of days ago...



Definitely OK to bin.  No point in having dead or confusing code; it's 
complicated enough as it is.  :)




Re: [lambda] Segmentation fault in simple lambda program

2009-07-29 Thread Adam Butcher
Hi

Esben Mose Hansen writes:
> this program SEGFAULTs
>
> #include 
>
> int main() {
>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>   int sum = 0;
>   int f = 5;
>   std::for_each(&numbers[0], &numbers[nn],  [&]  (int n)  {
> sum += n * f;
>   });
>
> }
> ...
> I am completely new to gcc hacking, just
> dying to get lambda into gcc 4.5 :)
>
Me to on both counts!  So much so that I've got a working copy of the latest 
lambda branch, svnmerged the latest 4.5.0
trunk into it, fixed a few build issues and started poking around.  I have 
never ventured into gcc internals before so
its all a bit alien at the mo.

> On Thursday 30 April 2009 19:19:31 Ian wrote:
> > When I try to specify the capture it works ((&sum, &f) works too but f is
> > const):
> >
> > #include 
> >
> > int
> > main(void)
> > {
> >   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
> >   const std::size_t nn = sizeof(numbers)/sizeof(int);
> >   int sum = 0;
> >   int f = 5;
> >
> >   //std::for_each(&numbers[0], &numbers[nn], [&](int n) { sum += n * f; });
> >
> >   std::for_each(&numbers[0], &numbers[nn], [&sum, f](int n) { sum += n * f;
> > });
> >
> >   return 0;
> > }
>
>  Yup. In fact, almost any other capture block than the [&] works :) I will try
>  to look at those tree options when I get sober again.
>
It is crashing when invoking a copied 'implicit capture' lambda.  The same 
occurs with:

  int main()
  {
 char i,j,k;
 auto const& f = [&] { i = 1; j = 2; k = 3; };
 auto g = f;
 g();
 return i+j+k;
  }

With explicit captures (i.e. specifying [&i,&j,&k] instead of [&] above) it 
works fine.  Also using f() (in place of
g()) is fine so the code in the lambda and the call to it must be okay.  So I 
started looking into the instance data.

The resulting lambda class in the above program is generated by the compiler to 
look something like the following in
name and structure:

   struct __lambda0
   {
  char &i,&j,&k;
  void operator() () const
  {
 i = 1; j = 2; k = 3;
  }
   };

Looking at the implementation in gcc/cp/{class.c,parser.c,semantics.c} it seems 
that, in implicit capture mode,
references to enclosing scope identifiers are retrospectively added to the 
lambda class on first use in the lambda
body.  This made me worry about the class structure changing as you progress 
through the parse of the lambda body. 
I.e. at the start of the body nothing is captured -- since nothing is 
referenced.  As you meet enclosing scope
references, each is added as a capture member to the lambda class.  Is this 
okay or has something already decided on
the size and structure of the class?  I figured (almost certainly naively and 
incorrectly) that it ought to be similar
to the difference between:

   struct X
   {
  int i;
  void init_i() { i = 1; }
   };

and

   struct X
   {
  void init_i() { i = 1; }
  int i;
   };

I changed the program above to check the sizes of the generated lambda class 
and it is indeed as expected (three
pointers). So the class has the correct size -- why does it not copy?  Surely a 
bitwise copy in this case is
sufficient and that ought to be auto-generated.  -- Except we're in compiler 
land here -- are we supposed to do the
auto-generating?  To test the theory I added

 memcpy(&g,&f,sizeof g);

after the assignment (auto g = f) to force the instance data to be copied from 
f to g.  It worked!  So why is the
compiler not generating suitable code for the lambda class copy -- the size is 
right, but no copy of instance data is
made -- maybe its already decided that the size is zero (as it was before the 
lambda body) and generated 'do-nothing'
copy constructors?

I had a poke around in gcc/cp/{class.c,parser.c,semantics.c} and believe I have 
worked around the issue -- the proper
solution I don't think is as straight-forward (or maybe its more 
straight-forward for a gcc guru?).

Note that the following diff hunk is after an svnmerge of trunk commits into my 
wc of the lambda branch so offsets
will likely be wrong.  I would give a full diff but my wc is in rather a messy 
state at the mo.  I have no idea
whether there are any nasty side effects to doing this but it seems to do the 
copy correctly afterwards.  I have not
looked into it much further at the mo.  Thought I'd just post my findings.

### snip ##
--- gcc/cp/parser.c (revision 150148)
+++ gcc/cp/parser.c (working copy)
@@ -6936,6 +6991,24 @@

 cp_parser_lambda_body (parser, lambda_expr);

+/* relayout again -- to allow for implicit
+ * parameters to have been added to the capture if it was a
+ * 'default capture' -- note that this would not be necessary if
+ * the stack-pointer variant was implemented -- since the layout
+ * would be known.
+ * Relayingout here might have nasty effect if one were to query
+ * sizeof *this from within the body -- would that ev

Re: [lambda] Segmentation fault in simple lambda program

2009-08-04 Thread Adam Butcher
Jason Merrill wrote:
> On 08/03/2009 09:36 PM, Adam Butcher wrote:
>> Thanks.  I haven't any copyright assignments on file -- this is my first 
>> dabbling with gcc and I've been doing it
>> mostly to experiment with C++ lambda support and non-standard extensions 
>> such as polymorphic lambda support.
>
> OK.  We'll need an assignment in order to incorporate your changes into
> GCC.  If you want to assign all present and future changes to the
> compiler, you could use the form
>
OK I've kicked that off.

>> I've been working in my own repository which I rebased earlier today from 
>> trunk (r150148).  I've attached the
>> rebase including the fix for generating correct copying of lambda classes 
>> (re-laying out after parsing body).

> Hmm, having the new changes folded into the old changes is kind of
> inconvenient, but I suppose I can deal.  It's moot anyway until your
> assignment is on file.
>
Yes sorry about that.  I appreciate the issue.  I had taken a branch of trunk 
and applied the lambda changes to it to
keep only lambda changes on my working branch (allowing simpler future 
rebaseing).  There were a number of things I
had to change to to get the lambda changes a) building and b) working with test 
programs.  Unfortunately I did all
this in one commit.  Not very helpful.  I will mail you my 'fixes' diff against 
the latest lambda branch head
independent of the rebase noise if you want.

> Incidentally, comments like
>
> /*
>   *
>   *
>   */
>
> aren't customary in GCC sources; that's just something John did that
> we'll need to clean up before the code goes into the trunk.  There are
> other formatting irregularities, some of which I've corrected.
>
Ah I see.  I was following the principle of following the nearest style!  I 
have reworked my changes in this style.

>> Experimenting with a working version and seeing it's issues will be useful 
>> to me.  To others to maybe.  With
>> concepts
>> gone from C++0x and being reworked for C++15(?) maybe support for 
>> polymorphic lambdas could be reintroduced? --
>> though
>> I'm sure its much too late for that and that its likely been around the buoy 
>> many times.  From what I have read I
>> got
>> the idea that the Callable concept was the primary reason for polymorphic 
>> lambdas not being accepted.
>
> I don't know what the reasoning was there, but people have been somewhat
> conservative about what usages of lambdas are allowed for fear of
> unforseen implementation issues.  Certainly having a working
> implementation would go a lot toward convincing people to allow it, even
> if it doesn't make it into C++0x.
>
Hopefully.  From my point of view the class generated by a lambda expression 
should be equivalent to something you
could write yourself -- aside from the single stack-pointer reference 
optimization which only a compiler could achieve
-- the class has a name, albeit invisible to the user (except in 
errors/warnings), and instances of should be useable
just as if there were user-defined functors.  I'm sure there are things I've 
overlooked but hopefully this
proof-of-concept will help to allay people's fears.

>> Implied template typename arguments via auto are not currently supported.  
>> The syntax parses but I haven't yet
>> synthesized the template arguments and therefore not replaced the auto's 
>> with them so it doesn't compile.
>
> Since templates work so differently from normal functions, I'm a little
> uncomfortable with the idea of templates that don't involve any template
> syntax, just the use of auto in the parameter list.  But I'm open to
> giving it a try, at least in the lambda context.  Maybe outside of
> lambda it could be used with a small template introducer...
>
I did think about auto as a shortcut for template typename outside of lambdas 
but I figured that was pushing it a bit
too far.  It wouldn't be obvious that a function declared in that way was 
actually a function template.  The benefit
of using it in lambdas is that the call operator is never 'seen', so whether 
its a template or not shouldn't affect
the caller providing the input arguments are compatible.

>> I'd welcome feedback on the syntax and semantics and of course any 
>> fundamental things I've missed by coming up with
>> such a syntax!
>>
>>  From a grammar point of view I've just expanded 
>> lambda-parameter-declaration to start with:
>>lambda-template-param-decl [opt]
>> where lambda-template-param-decl is:
>><  template-parameter-list>
>
> Makes sense.  I suppose

Re: [lambda] Segmentation fault in simple lambda program

2009-08-04 Thread Adam Butcher
Hi Jason,

Pending response from assign at gnu dot org, I've attached diffs made against 
your latest lambda head.  They are
cleaned up a little to from the previous diffs against trunk.  First is the 
re-layout fix, second is experimental
polymorphic lambda support.

Cheers,
Adam


0001-Re-laid-out-lambda-class-after-parsing-body.patch
Description: Binary data


0002-First-pass-polymorphic-lambda-support.patch
Description: Binary data


Re: [lambda] Segmentation fault in simple lambda program

2009-08-06 Thread Adam Butcher
Adam Butcher wrote:
>John Freeman wrote:
>>
>> I just inspected my code again.  The call to layout_class_type at the
>> beginning of finish_lambda_function_body at semantics.c:5241 was
>> intended to recalculate offsets to members in the case of default captures.
>>
>> Here is the complete order of the pertinent function calls (file
>> location has nothing to do with call order; I supply them to help the
>> reader to follow):
>>
>> finish_struct @ parser.c:6985
>>
>> cp_parser_lambda_body @ parser.c:6992
>> --> finish_lambda_function_body @ parser.c:7380
>> > layout_class_type @ semantics.c:5241
>>
>> finish_struct_1 @  I don't see this added yet.  I've checked out
>> revision 150396.
>>
>I think Jason's waiting for the formality of copyright assignment to be 
>finalized.   I attached my patches against the
>latest lambda branch head in the following mail if you want to try them out:
>  http://gcc.gnu.org/ml/gcc/2009-08/msg00058.html
>
I see you've committed the fix.  Great.  Much better to do the relayout in 
semantics.c where the previous layout stuff
was than in the parser.  I take you're point on it potentially being overkill 
but at least it means that user programs
that copy can work.

I guess this thread is done with now that the fix has been committed.  I should 
start another to discuss polymorphic
lambda experimentation and implicit template parameters.  BTW I have got the 
latter working now -- to a certain (read
limited and buggy) extent.

The 'implicit template parameter via auto' addition is literally a quick hack 
for me to investigate what functionally
needs to occur to achieve it -- the implementation is not pleasant by any means 
as yet.

I've attached my two diffs made against the latest lambda head.  First is 
explicit polymorphic lambda support via the
additional template parameter syntax, second is the very hacky 
'for-discovery-purposes-only' prototype for typename
inference.  The examples below demonstrate the supported syntaxes.

  1.  []  (T const& t, U u) { return t + u; }
  2.  [] (auto const& t, auto u) { return t + u; }
  3.  []  (T const& t, auto u) { return t + u; }

Currently for auto typename inference, cv-qualifiers (and other bits like 
attributes) are lost but I'll come to that
when I rewrite it all in light of what I have found out.  Just thought I'd 
share this functional-approximation to a
solution.  As a result of the aforementioned bug, although 1. and 3. produce 
effectively the same code, 2. ends up
being equivalent to:

  []  (__AutoT1& t, __AutoT2 u) { 
return t + u; }

rather than the expected:

  []  (__AutoT1 const& t, __AutoT2 u) 
{ return t + u; }

There's a number of things I'm not sure about regarding location of the 
implementation (parser.c, semantics.c, decl.c
etc).

One thing I'm worried about is that I'm using make_tree_vec() with a length one 
greater than that of the previous
vector in order to grow the template parameter list whilst parsing function 
arguments.  This seems inefficient and
ugly.  Not least as there seems to be no way to ditch the old tree-vec.  I can 
ggc_free it but that won't do any
housekeeping of the tree counts and sizes.  It looks like tree-vecs are only 
supposed to be alloc'd into the pool
(zone?) and never removed.  In this case, incrementally adding additional 
parameters, you get allocs like:

  [--tree-vec-1--]
  [--tree-vec-1--] [-+-tree-vec-2-+-]
  [--tree-vec-1--] [-+-tree-vec-2-+-] [-++-tree-vec-3-++-]

And all you want is the last one.  I appreciate that its probably done this way 
to avoiding full fragmentation
management but I'd expect this sort of thing may happen often (or maybe it 
shouldn't!).  Off the top of my head, one
solution would be to add tree_vec_resize() which would realloc the memory and 
update the counts/sizes iff the tree-vec
were the last in the list.  The fallback behaviour if it weren't the last would 
be to do the previous manual
make_tree_vec() behaviour.  Something like:

   [--tv1--]

tv1 = tree_vec_resize (tv1, TREE_VEC_LENGTH (tv1) + 1);

   [-+-tv1-+-]

tv1 = tree_vec_resize (tv1, TREE_VEC_LENGTH (tv1) + 1);

   [-++-tv1-++-]

tv2 = make_tree_vec (n)

   [-++-tv1-++-] [--tv2--]

tv1 = tree_vec_resize (tv1, TREE_VEC_LENGTH (tv1) + 1);

   [-++-tv1-++-] [--tv2--] [-+++-tv1-+++-]
   ^   ^
   | no longer |
   | referenced|

This seems to work optimally in the case of incremental addition to the last 
tree-vec -- you are left with the minimum
tree-vecs necessary to avoid full fragmentation handling, and it degrades to 
supports the effect of the manual method
of calling make_tree_vec (old_size + n).

Maybe a doubling size on realloc and starting at, say, 4 elements could make 
realloc'ing more efficient -- 

[lambda] Latest experimental polymorphic lambda patches

2009-08-10 Thread Adam Butcher
Attached are my latest experimental polymorphic lambda patches against the 
latest lambda branch.  Template parameters
implied by auto in the lambda's call parameter list no longer lose qualifiers.  
The following examples produce
equivalent functions:

   1.   [] (auto x, auto& y, auto const& z) { return x + y + z; }
   2.   []  (X x, Y& y, Z const& z) { 
return x + y + z; }
   3.   []  (auto x, Y& y, auto const& z) { return x + y + z; }

Note that using an explicit template parameter is only really useful if you 
wish to either a) ensure consistency among
a number of call parameters, b) use a non-type template parameter or c) specify 
a call parameter type constraint (or
other complex parameter type).

I have flattened the latest auto-template-inference changes with the previous 
one to remove complexity due to
re-arrangement.  In particular it no longer abuses decl.c -- those changes have 
currently moved into parser.c but it
is pretty clear that they have more in common with pt.c owing to a need to pull 
in some local static functions from
that file.  I intend to split or move parts (or most) into pt.c on my next 
attempt (if I get time to make one!)

There are currently many issues:
  - efficiency of template parameter list growing.
  - implicit return type deduction doesn't work from
inside a template context if the lambda's return
expression involves a dependent type.  Specifying
decltype explicitly in these contexts is a
workaround.
  - dependent inferred return type needs to be
deferred and decayed.  This may go some way (all
the way?) to solving the previous point.
  - location of implementation.
  - only a few use-cases have been considered.


Adam


Summary:

Subject: [PATCH] First pass polymorphic lambda support.

This commit adds experimental support for an optional template-parameter-list 
in angle-brackets at the start of a
lambda-parameter-declaration.
---
Subject: [PATCH] Restored decltype in lambda return type deduction for when 
expr is dependent.
---
Subject: [PATCH] Second version of typename inference from auto parameters in 
lambda call operator.

Still quite hacky -- though better than previous.  No longer loses
qualifiers on replaced auto parameters so is functionally closer to
what's really needed.

 - This is just a behavioural proof to find out how things work.
 - Need to shuffle some stuff into pt.c and do away with code dup.
 - Not sure how to free tree_vec's and tidy up the counts and sizes
   (looks like they're only intended to grow.)
 - Added `type_decays_to (non_reference (finish_decltype_type' as
   suggested by Jason.  Currently doesn't remove cv-quals from
   non-class types though.  Need to treat implicit return type
   differently for dependent types -- should defer and mark that it
   needs to be computed later.
---


0001-First-pass-polymorphic-lambda-support.patch
Description: Binary data


0002-Restored-decltype-in-lambda-return-type-deduction-fo.patch
Description: Binary data


0003-Second-version-of-typename-inference-from-auto-param.patch
Description: Binary data


Re: [lambda] Latest experimental polymorphic lambda patches

2009-08-11 Thread Adam Butcher
Thanks for the feedback.

Jason Merrill wrote:
>Adam Butcher wrote:
>> The following examples produce
>> equivalent functions:
>>
>>1.   [] (auto x, auto& y, auto const& z) { return x + y + z; }
>>2.   []  (X x, Y& y, Z const& z) { 
>> return x + y + z; }
>>3.   []  (auto x, Y& y, auto const& z) { return x + y + z; }
>
> IMO #3 should not be equivalent to the others; the auto template parms
> should come after Y.  And I believe that's currently the case with your
> patch.
>
Sorry, I wasn't clear.  I meant that they generate the same function from the 
user's point of view, not that their
internals are the same.  I didn't mean to suggest that the order of their 
template parameters would be the same.  It
was meant to demonstrate that using 'auto' and specifying an explicit unique 
typename are equivalent from a client
point-of-view.  You are correct that in #3's case the generated lambda is 
equivalent to:

   []  (__AutoT1 x, Y& y, 
__AutoT2 const& z) { return x + y + z; }

Which is, from the user's perspective, equivalent to the lambda functions 
defined by #1 and #2, just that the order of
the template arguments are different.

I accept that this does give a different function signature in terms of 
template parameter indexes.  I've assumed that
explicit specialization of the call operator is not useful and therefore the 
user would never see the final template
parameter list and would not need to understand its ordering.

> If you save up all the auto parms until the end and then assign indices
> and adjust the parm vector then, that will avoid reallocating the vector
> each time.
>
Yes that would be better.

> But don't worry about tidying tree_node_counts; it just tracks how many
> of a particular tree code we create, not how many we currently have.
> Normal GC throws away lots of stuff without adjusting the counts.
>
Ah okay.  Would it be worth enhancing the tree-vec interface to include block 
reallocation with size doubling and end
marking to allow for more efficient reallocation?  Such a structural change 
maybe hidden by the macro front-end.  I
wonder how many uses of make_tree_vec don't ggcfree their previous tree-vec 
when using it in a 'realloc' way.

A quick grep for 'make_tree_vec\>' in gcc reveals about 80 uses, many of which 
with an arithmetic expression as its
argument.  I wonder how many of these might benefit from such an allocation 
scheme and how many would be impaired by
it?

Maybe its an insignificant issue.

>> +  /* XXX: Maybe to loop rather than recurse here? */
>
> At -O2, the GCC optimizers should convert tail recursion into looping.
>
Great, no worries there then.

>> +  if (type_dependent_expression_p (expr))
>> +/* TODO: Should defer this until instantiation rather than using
>> + decltype.  */
>> +return_type = type_decays_to (non_reference (finish_decltype_type
>> +  (expr, /*id_expression_or_member_access_p=*/false)));
>
> Definitely need to defer it; type_decays_to and non_reference don't work
> on DECLTYPE_TYPE.
>
I thought as much -- I assume it's just trying to strip non-existent qualifiers 
from `decltype(expr)' which amounts to
a no-op.

Thanks again for the feedback.  I'll try to get deferred return type deduction 
working when I get some time.  Working
through that will probably end up sorting some of the issues with dependent 
return type deduction inside templates.

Cheers,
Adam




Re: Slightly offtpic: why svn stubbornly refuses to listen to ctrl-c?!?

2010-01-15 Thread Adam Butcher
On Fri, January 15, 2010 1:43 pm, Paolo Carlini wrote:
>
> I mean, why a well designed application should refuse to listen to
> ctrl-c when something goes wrong? Why every time for some reason it gets
> stuck, I have to kill it from another shell? That's definitely annoying.
>
If you're on a posix-compatible have you tried using SIGQUIT (CTRL-\ or CTRL-4) 
instead of SIGINT?

Adam




Re: Slightly offtpic: why svn stubbornly refuses to listen to ctrl-c?!?

2010-01-15 Thread Adam Butcher
On Fri, January 15, 2010 3:57 pm, Dave Korn wrote:
> Adam Butcher wrote:
>> On Fri, January 15, 2010 1:43 pm, Paolo Carlini wrote:
>>> I mean, why a well designed application should refuse to listen to ctrl-c
>>> when something goes wrong? Why every time for some reason it gets stuck,
>>> I have to kill it from another shell? That's definitely annoying.
>>>
>> If you're on a posix-compatible have you tried using SIGQUIT (CTRL-\ or
>> CTRL-4) instead of SIGINT?
>
>   Or kill -9 of course, but beware; Vincent LeFevre reported sandboxes
> corrupted beyond anything 'svn cleanup' could repair in one of the links I
> posted in another reply.
>
Sure, this is a last resort.  I only mentioned SIGQUIT because its
'typeable' so you wouldn't have the annoyance of going to a new shell
(or suspending svn), finding the pid and killing it (or use killall).
That's providing svn doesn't implement the same best-effort cancellation
checkpoints for SIGQUIT also of course.

Cheers,
Adam




[Patch] [C++0x] Support decltype as base-specifier (Bug 42603)

2011-01-20 Thread Adam Butcher
Hi there,

Attached is a tentative patch to support using decltype as a
base-type-specifier (Re:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42603).

It should handle also the case where decltype is used as the start of a
nested-name-specifier when this is supported in the future.

Any feedback welcome -- I have done only basic testing -- it appears to
work okay for what I want (so far at least).

Regards,
Adam

PS. I already have sorted copyright assignment a while ago so you can go
ahead and apply this at your convenience if it is any good (subject to
review of course).


0001-C-0x-Support-decltype-as-base-specifier.patch
Description: Binary data


Re: [Patch] [C++0x] Support decltype as base-specifier (Bug 42603)

2011-01-20 Thread Adam Butcher
On Thu, January 20, 2011 4:43 pm, Jonathan Wakely wrote:
> On 20 January 2011 14:26, Adam Butcher wrote:
> > Hi there,
> >
> > Attached is a tentative patch ...
> > [snip]
>
> thanks for working on this.  Patches should be sent to the gcc-patches
> list for review, you could then add the URL of the archived email to
> the bugzilla report.
>
Thanks Jonathan, Paolo had already mailed me off list about this.  I
have posted the original mail and a further patch to handle decltype in
nested-name-specifiers to gcc-patches.

I will update the related bugzilla issues 42603 and 6709 also.

Cheers
Adam




Re: [lambda] Latest experimental polymorphic lambda patches

2013-04-27 Thread Adam Butcher

Hi Jason,

On 23.04.2013 14:42, Jason Merrill wrote:

On 22.04.2013 17:42, Jason Merrill wrote:
> On 08/10/2009 08:33 PM, Adam Butcher wrote:
> > Attached are my latest experimental polymorphic lambda patches
> > against the latest lambda branch.
>
> Polymorphic lambdas were voted in for C++14 at the meeting this 
past

> week; are you interested in resuming this work?
>

Yes very interested.  I have been meaning to get around to remaking
the patch against 4.8 (and previously 4.7) for ages now.  Though
getting the time to do so has been, and will likely continue to be, a
problem what with work, fatherhood and other commitments.

Since the gcc/cp code base is significantly different now from the old
lambda branch where the changes were originally made in 2009, my
intent was to remake the changes from scratch implementing the
entirety of N3559 (now N3649) and, at least, the explicit template
parameter specifier syntax from N3560 (though I'm very interested
getting the single expression body syntax working also).

I have no problem with someone else getting on with this as I can't
guarantee consistent availability for it but I will try to get some
time to at least look at my previous aborted efforts to get the
changes applied to the more recent mainlines (I have some git repos
around here and at work with some incomplete changes).  I will see how
far I got with these and maybe post a few patches.  It is highly
likely though that these were just abortive attempts to merge the
previous stuff or incomplete restarts.


> The proposal will be at
>
>  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html
>
It's now been posted at http://isocpp.org/files/papers/N3649.html



Cheers,
Adam




Re: [lambda] First stage remake of old lambda patches

2013-06-12 Thread Adam Butcher
Hi Jason,

I did find some code in the end but it wasn't much use due to the
changes in gcc/cp since the old lambda branch from which the original
patch was based.

I've since been finding 10 minutes here and there to have a hack about
and have finally got the first stage of generic lambda support
functional against GCC's trunk.

It currently only supports the explicit template-style syntax of the
second (non approved) paper (and my original patch) but I believe this
is good place to start even if it is considered a GNU extension for
now.  I will try to reapply the 'auto' syntax patch at some point but
that is syntactic rather than a behavioral.

I want to fix up the stateless lambda ptr-to-fn conversion-op stuff
next which, I think, is currently the biggest wheel off mechanically.

I've no idea how well this will deal with parameter packs or more
exotic use cases than the simple test program below but I'd welcome
any feedback at this stage.

I do feel like I've gone backward with this but I think it's worth
getting the mechanical side working right with the latest GCC before
integrating the 'auto' parameter patch.

Cheers,
Adam

## begin test program ##

// to check generated asm
//
volatile int E = 1;
volatile int F = 2;
volatile int G = 3;
volatile int H = 4;

// instantiation generates a -Wwrite-strings warning showing the type
// bindings for T and U (currently not displayed in generic lambda
// diagnostics) as part of the synthesized constructor.
//
template 
struct diagnostic { char* x = ""; };

int main()
{
  int i = 1;

  // e: monomorphic stateless lambda
  // f: monomorphic closure
  // g: polymorphic stateless lambda
  // (Note: explicit return type specified to avoid current
  //conversion-op bug)
  // h: polymorphic closure
  //
  auto e = []  (char a, char b) { return E + a + b; };
  auto f = [i] (char a, char b) { return F + i + a + b; };
  auto g = []   (T a, U b) -> double { 
diagnostic(); return G + a + b; };
  auto h = [i]  (T a, U b) { diagnostic(); return 
H + i + a + b; };

  // SEGV currently: conversion-op not implemented correctly yet:
  //   int (*p) (char, float) = g;
  //   int (*q) (int, double) = g;
  
  return g (1.0, 2) + h (2.f, '\003');
}

## end test program ##




[PATCH] Remake initial changes from old lambda branch to support explicit lambda template support and fixup against mainline gcc/cp changes.

2013-06-12 Thread Adam Butcher
This only supports the explicit template parameter syntax and does not
correctly support conversion to static ptr-to-function for generic
stateless lambdas.
---
 gcc/cp/mangle.c|  2 ++
 gcc/cp/parser.c| 43 +--
 gcc/cp/semantics.c | 24 
 3 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 8da62b5..4d4c0fd 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1438,6 +1438,8 @@ write_closure_type_name (const tree type)
   MANGLE_TRACE_TREE ("closure-type-name", type);
 
   write_string ("Ul");
+  if (TREE_CODE (fn) == TEMPLATE_DECL) // XXX: should we bother mangling 
generic lambdas?
+fn = DECL_TEMPLATE_RESULT (fn);
   write_method_parms (parms, /*method_p=*/1, fn);
   write_char ('E');
   write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 319da21..407dca3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8668,6 +8668,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree 
lambda_expr)
 /* Parse the (optional) middle of a lambda expression.
 
lambda-declarator:
+ < template-parameter-list [opt] >
  ( parameter-declaration-clause [opt] )
attribute-specifier [opt]
mutable [opt]
@@ -8687,10 +8688,26 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
   tree param_list = void_list_node;
   tree attributes = NULL_TREE;
   tree exception_spec = NULL_TREE;
+  tree template_param_list = NULL_TREE;
   tree t;
 
-  /* The lambda-declarator is optional, but must begin with an opening
- parenthesis if present.  */
+  /* The template-parameter-list is optional, but must begin with
+ an opening angle if present.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+{
+  cp_lexer_consume_token (parser->lexer);
+
+  template_param_list = cp_parser_template_parameter_list (parser);
+
+  cp_parser_skip_to_end_of_template_parameter_list (parser);
+
+  /* We just processed one more parameter list.  */
+  ++parser->num_template_parameter_lists;
+}
+
+  /* The parameter-declaration-clause is optional (unless
+ template-parameter-list was given), but must begin with an
+ opening parenthesis if present.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
 {
   cp_lexer_consume_token (parser->lexer);
@@ -8736,6 +8753,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree 
lambda_expr)
 
   leave_scope ();
 }
+  else if (template_param_list != NULL_TREE) // generate diagnostic
+cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
   /* Create the function call operator.
 
@@ -8779,6 +8798,23 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree 
lambda_expr)
DECL_ARTIFICIAL (fco) = 1;
/* Give the object parameter a different name.  */
DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure");
+   if (template_param_list != NULL_TREE)
+ {
+   tree saved_current_function_decl = current_function_decl;
+
+   /* Clear current function decl to allow check_member_template
+  to pass.  Currently it rejects templates inside functions.
+  Couldn't figure out a clean way to test for lambda inside
+  check_member_template.  */
+   current_function_decl = NULL_TREE;
+   fco = finish_member_template_decl (fco);
+   current_function_decl = saved_current_function_decl;
+
+   --parser->num_template_parameter_lists;
+
+   finish_template_decl (template_param_list);
+
+ }
   }
 
 finish_member_declaration (fco);
@@ -8822,6 +8858,9 @@ cp_parser_lambda_body (cp_parser* parser, tree 
lambda_expr)
 tree compound_stmt;
 tree cap;
 
+if (TREE_CODE (fco) == TEMPLATE_DECL)
+  fco = DECL_TEMPLATE_RESULT (fco);
+
 /* Let the front end know that we are going to be defining this
function.  */
 start_preparsed_function (fco,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b5c3b0a..db5ba7b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9135,7 +9135,7 @@ lambda_function (tree lambda)
  /*protect=*/0, /*want_type=*/false,
  tf_warning_or_error);
   if (lambda)
-lambda = BASELINK_FUNCTIONS (lambda);
+lambda = OVL_CURRENT (BASELINK_FUNCTIONS (lambda));
   return lambda;
 }
 
@@ -9381,6 +9381,8 @@ build_capture_proxy (tree member)
 
   closure = DECL_CONTEXT (member);
   fn = lambda_function (closure);
+  if (TREE_CODE (fn) == TEMPLATE_DECL)
+fn = DECL_TEMPLATE_RESULT (fn);
   lam = CLASSTYPE_LAMBDA_EXPR (closure);
 
   /* The proxy variable forwards to the capture field.  */
@@ -9795,7 +9797,8 @@ maybe_add_lambda_conv_op (tree type)
   if (processing_template_decl)
 return;
 
-  if (DECL_INITIAL (callop) == NULL_TREE)
+  if (TREE_CODE (callop) != TEMPLATE