public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* ODR violation in ranges
@ 2020-03-11 10:08 Nathan Sidwell
  2020-03-11 10:26 ` Jonathan Wakely
  0 siblings, 1 reply; 8+ messages in thread
From: Nathan Sidwell @ 2020-03-11 10:08 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: GCC Patches

Jonathan,
the ranges header contains code like:
     inline constexpr __adaptor::_RangeAdaptorClosure all
       = [] <viewable_range _Range> (_Range&& __r)
       {
  if constexpr (view<decay_t<_Range>>)
    return std::forward<_Range>(__r);
  else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
    return ref_view{std::forward<_Range>(__r)};
  else
    return subrange{std::forward<_Range>(__r)};
       };

(line 1236)

When you strip away all the templateyness, you have:


inline constexpr auto all = [] () {};


That's an ODR violation -- the initializers in different TUs are not the 
same!

As you can guess, I can't turn this into a header unit (well, I can, but 
merging duplicates complains at you)

nathan
-- 
Nathan Sidwell

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 10:08 ODR violation in ranges Nathan Sidwell
@ 2020-03-11 10:26 ` Jonathan Wakely
  2020-03-11 10:56   ` Tam S. B.
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Wakely @ 2020-03-11 10:26 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: GCC Patches, libstdc++, ppalka

On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
>Jonathan,
>the ranges header contains code like:
>    inline constexpr __adaptor::_RangeAdaptorClosure all
>      = [] <viewable_range _Range> (_Range&& __r)
>      {
> if constexpr (view<decay_t<_Range>>)
>   return std::forward<_Range>(__r);
> else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
>   return ref_view{std::forward<_Range>(__r)};
> else
>   return subrange{std::forward<_Range>(__r)};
>      };
>
>(line 1236)
>
>When you strip away all the templateyness, you have:
>
>
>inline constexpr auto all = [] () {};
>
>
>That's an ODR violation -- the initializers in different TUs are not 
>the same!
>
>As you can guess, I can't turn this into a header unit (well, I can, 
>but merging duplicates complains at you)

CC libstdc++@ and Patrick.

I did wonder if using lambdas for those global variables would be OK.

I think we'll need a new class template for each view adaptor, rather
than using the _RangeAdaptorClosure to hold a closure.

Patrick, can you look into that please?


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 10:26 ` Jonathan Wakely
@ 2020-03-11 10:56   ` Tam S. B.
  2020-03-11 12:47     ` Jonathan Wakely
                       ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Tam S. B. @ 2020-03-11 10:56 UTC (permalink / raw)
  To: Jonathan Wakely via Libstdc++, Nathan Sidwell; +Cc: GCC Patches

IIUC using lambda in inline variable initializer is not ODR violation. This is covered in CWG 2300 ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300 ).

________________________________________
From: Libstdc++ <libstdc++-bounces@gcc.gnu.org> on behalf of Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org>
Sent: Wednesday, March 11, 2020 10:26
To: Nathan Sidwell
Cc: libstdc++@gcc.gnu.org; GCC Patches
Subject: Re: ODR violation in ranges

On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
>Jonathan,
>the ranges header contains code like:
>    inline constexpr __adaptor::_RangeAdaptorClosure all
>      = [] <viewable_range _Range> (_Range&& __r)
>      {
> if constexpr (view<decay_t<_Range>>)
>   return std::forward<_Range>(__r);
> else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
>   return ref_view{std::forward<_Range>(__r)};
> else
>   return subrange{std::forward<_Range>(__r)};
>      };
>
>(line 1236)
>
>When you strip away all the templateyness, you have:
>
>
>inline constexpr auto all = [] () {};
>
>
>That's an ODR violation -- the initializers in different TUs are not
>the same!
>
>As you can guess, I can't turn this into a header unit (well, I can,
>but merging duplicates complains at you)

CC libstdc++@ and Patrick.

I did wonder if using lambdas for those global variables would be OK.

I think we'll need a new class template for each view adaptor, rather
than using the _RangeAdaptorClosure to hold a closure.

Patrick, can you look into that please?


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 10:56   ` Tam S. B.
@ 2020-03-11 12:47     ` Jonathan Wakely
  2020-03-11 13:21     ` Patrick Palka
  2020-03-11 15:05     ` Nathan Sidwell
  2 siblings, 0 replies; 8+ messages in thread
From: Jonathan Wakely @ 2020-03-11 12:47 UTC (permalink / raw)
  To: Tam S. B.; +Cc: Jonathan Wakely via Libstdc++, Nathan Sidwell, GCC Patches

On 11/03/20 10:56 +0000, Tam S. B. via Libstdc++ wrote:
>IIUC using lambda in inline variable initializer is not ODR violation. This is covered in CWG 2300 ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300 ).

Ah yes, I think somebody (probably Patrick) has pointed out that
wording before, and I'd forgotten about it.

So that would make it an unsupported G++ feature then?


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 10:56   ` Tam S. B.
  2020-03-11 12:47     ` Jonathan Wakely
@ 2020-03-11 13:21     ` Patrick Palka
  2020-03-11 15:05     ` Nathan Sidwell
  2 siblings, 0 replies; 8+ messages in thread
From: Patrick Palka @ 2020-03-11 13:21 UTC (permalink / raw)
  To: Tam S. B.; +Cc: Jonathan Wakely via Libstdc++, Nathan Sidwell, GCC Patches

On Wed, 11 Mar 2020, Tam S. B. via Gcc-patches wrote:

> IIUC using lambda in inline variable initializer is not ODR violation. This is covered in CWG 2300 ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300 ).
> 
> ________________________________________
> From: Libstdc++ <libstdc++-bounces@gcc.gnu.org> on behalf of Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org>
> Sent: Wednesday, March 11, 2020 10:26
> To: Nathan Sidwell
> Cc: libstdc++@gcc.gnu.org; GCC Patches
> Subject: Re: ODR violation in ranges
> 
> On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
> >Jonathan,
> >the ranges header contains code like:
> >    inline constexpr __adaptor::_RangeAdaptorClosure all
> >      = [] <viewable_range _Range> (_Range&& __r)
> >      {
> > if constexpr (view<decay_t<_Range>>)
> >   return std::forward<_Range>(__r);
> > else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
> >   return ref_view{std::forward<_Range>(__r)};
> > else
> >   return subrange{std::forward<_Range>(__r)};
> >      };
> >
> >(line 1236)
> >
> >When you strip away all the templateyness, you have:
> >
> >
> >inline constexpr auto all = [] () {};
> >
> >
> >That's an ODR violation -- the initializers in different TUs are not
> >the same!
> >
> >As you can guess, I can't turn this into a header unit (well, I can,
> >but merging duplicates complains at you)
> 
> CC libstdc++@ and Patrick.
> 
> I did wonder if using lambdas for those global variables would be OK.
> 
> I think we'll need a new class template for each view adaptor, rather
> than using the _RangeAdaptorClosure to hold a closure.
> 
> Patrick, can you look into that please?

IIUC, it should suffice to replace the lambda in the initializer with a
function object, maybe something like:

  struct _All
  {
    constexpr auto
    operator()(...)
    {
    };
  };

  inline constexpr __adaptor::_RangeAdaptorClosure<_All> all;

Do the lambdas in the bodies of _RangeAdaptor::operator() and
_RangeAdaptorClosure::operator|() pose a problem too?


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 10:56   ` Tam S. B.
  2020-03-11 12:47     ` Jonathan Wakely
  2020-03-11 13:21     ` Patrick Palka
@ 2020-03-11 15:05     ` Nathan Sidwell
  2020-03-11 15:23       ` Jason Merrill
  2 siblings, 1 reply; 8+ messages in thread
From: Nathan Sidwell @ 2020-03-11 15:05 UTC (permalink / raw)
  To: Tam S. B., Jonathan Wakely via Libstdc++; +Cc: GCC Patches

On 3/11/20 6:56 AM, Tam S. B. wrote:
> IIUC using lambda in inline variable initializer is not ODR violation. This is covered in CWG 2300 ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300 ).

ah, thanks for the pointer.  For lambdas in function scope we do achieve 
this (the mangling of the lambda uses the function as scope and a 
function-specific index).

We do not do so for lambdas in the initializer of namespace-scope inline 
variables, which is I think the missing bit.  That's an ABI thing, I'll 
ask over there.

The ranges header we'll die horribly if we ever emit non-inline code to 
evaluate the lambda at runtime.  We'll give it a name that depends on 
the order of (namespace-scope?) lambdas. :(

inline constexpr auto foo = [] (int i) {return i * 2;};
int bob (int i)
{ return foo (i); }

compile with -fno-inline and observe '_ZNKUliE_clEi'

sigh,

nathan
> 
> ________________________________________
> From: Libstdc++ <libstdc++-bounces@gcc.gnu.org> on behalf of Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org>
> Sent: Wednesday, March 11, 2020 10:26
> To: Nathan Sidwell
> Cc: libstdc++@gcc.gnu.org; GCC Patches
> Subject: Re: ODR violation in ranges
> 
> On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
>> Jonathan,
>> the ranges header contains code like:
>>     inline constexpr __adaptor::_RangeAdaptorClosure all
>>       = [] <viewable_range _Range> (_Range&& __r)
>>       {
>> if constexpr (view<decay_t<_Range>>)
>>    return std::forward<_Range>(__r);
>> else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
>>    return ref_view{std::forward<_Range>(__r)};
>> else
>>    return subrange{std::forward<_Range>(__r)};
>>       };
>>
>> (line 1236)
>>
>> When you strip away all the templateyness, you have:
>>
>>
>> inline constexpr auto all = [] () {};
>>
>>
>> That's an ODR violation -- the initializers in different TUs are not
>> the same!
>>
>> As you can guess, I can't turn this into a header unit (well, I can,
>> but merging duplicates complains at you)
> 
> CC libstdc++@ and Patrick.
> 
> I did wonder if using lambdas for those global variables would be OK.
> 
> I think we'll need a new class template for each view adaptor, rather
> than using the _RangeAdaptorClosure to hold a closure.
> 
> Patrick, can you look into that please?
> 


-- 
Nathan Sidwell

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 15:05     ` Nathan Sidwell
@ 2020-03-11 15:23       ` Jason Merrill
  2020-03-11 15:39         ` Nathan Sidwell
  0 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2020-03-11 15:23 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: Tam S. B., Jonathan Wakely via Libstdc++, GCC Patches

On Wed, Mar 11, 2020 at 11:05 AM Nathan Sidwell <nathan@acm.org> wrote:

> On 3/11/20 6:56 AM, Tam S. B. wrote:
> > IIUC using lambda in inline variable initializer is not ODR violation.
> This is covered in CWG 2300 (
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300
> ).
>
> ah, thanks for the pointer.  For lambdas in function scope we do achieve
> this (the mangling of the lambda uses the function as scope and a
> function-specific index).
>
> We do not do so for lambdas in the initializer of namespace-scope inline
> variables, which is I think the missing bit.  That's an ABI thing, I'll
> ask over there.
>

Looks like the condition on the call to start_lambda_scope in
cp_parser_init_declarator just needs to be adjusted to handle non-template
inline variables.


> The ranges header we'll die horribly if we ever emit non-inline code to
> evaluate the lambda at runtime.  We'll give it a name that depends on
> the order of (namespace-scope?) lambdas. :(
>
> inline constexpr auto foo = [] (int i) {return i * 2;};
> int bob (int i)
> { return foo (i); }
>
> compile with -fno-inline and observe '_ZNKUliE_clEi'
>
> sigh,
>
> nathan
> >
> > ________________________________________
> > From: Libstdc++ <libstdc++-bounces@gcc.gnu.org> on behalf of Jonathan
> Wakely via Libstdc++ <libstdc++@gcc.gnu.org>
> > Sent: Wednesday, March 11, 2020 10:26
> > To: Nathan Sidwell
> > Cc: libstdc++@gcc.gnu.org; GCC Patches
> > Subject: Re: ODR violation in ranges
> >
> > On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
> >> Jonathan,
> >> the ranges header contains code like:
> >>     inline constexpr __adaptor::_RangeAdaptorClosure all
> >>       = [] <viewable_range _Range> (_Range&& __r)
> >>       {
> >> if constexpr (view<decay_t<_Range>>)
> >>    return std::forward<_Range>(__r);
> >> else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
> >>    return ref_view{std::forward<_Range>(__r)};
> >> else
> >>    return subrange{std::forward<_Range>(__r)};
> >>       };
> >>
> >> (line 1236)
> >>
> >> When you strip away all the templateyness, you have:
> >>
> >>
> >> inline constexpr auto all = [] () {};
> >>
> >>
> >> That's an ODR violation -- the initializers in different TUs are not
> >> the same!
> >>
> >> As you can guess, I can't turn this into a header unit (well, I can,
> >> but merging duplicates complains at you)
> >
> > CC libstdc++@ and Patrick.
> >
> > I did wonder if using lambdas for those global variables would be OK.
> >
> > I think we'll need a new class template for each view adaptor, rather
> > than using the _RangeAdaptorClosure to hold a closure.
> >
> > Patrick, can you look into that please?
> >
>
>
> --
> Nathan Sidwell
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ODR violation in ranges
  2020-03-11 15:23       ` Jason Merrill
@ 2020-03-11 15:39         ` Nathan Sidwell
  0 siblings, 0 replies; 8+ messages in thread
From: Nathan Sidwell @ 2020-03-11 15:39 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Tam S. B., Jonathan Wakely via Libstdc++, GCC Patches

On 3/11/20 11:23 AM, Jason Merrill wrote:
> On Wed, Mar 11, 2020 at 11:05 AM Nathan Sidwell <nathan@acm.org 
> <mailto:nathan@acm.org>> wrote:
> 
>     On 3/11/20 6:56 AM, Tam S. B. wrote:
>      > IIUC using lambda in inline variable initializer is not ODR
>     violation. This is covered in CWG 2300 (
>     http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300
>     ).
> 
>     ah, thanks for the pointer.  For lambdas in function scope we do
>     achieve
>     this (the mangling of the lambda uses the function as scope and a
>     function-specific index).
> 
>     We do not do so for lambdas in the initializer of namespace-scope
>     inline
>     variables, which is I think the missing bit.  That's an ABI thing, I'll
>     ask over there.
> 
> 
> Looks like the condition on the call to start_lambda_scope in 
> cp_parser_init_declarator just needs to be adjusted to handle 
> non-template inline variables.

thanks!

The ABI does describe how to mangle these (it focusses on data-members, 
but AFAICT works for namespace-scope vars too).  We don't do any of that 
though :(

> 
>     The ranges header we'll die horribly if we ever emit non-inline code to
>     evaluate the lambda at runtime.  We'll give it a name that depends on
>     the order of (namespace-scope?) lambdas. :(
> 
>     inline constexpr auto foo = [] (int i) {return i * 2;};
>     int bob (int i)
>     { return foo (i); }
> 
>     compile with -fno-inline and observe '_ZNKUliE_clEi'
> 
>     sigh,
> 
>     nathan
>      >
>      > ________________________________________
>      > From: Libstdc++ <libstdc++-bounces@gcc.gnu.org
>     <mailto:libstdc%2B%2B-bounces@gcc.gnu.org>> on behalf of Jonathan
>     Wakely via Libstdc++ <libstdc++@gcc.gnu.org
>     <mailto:libstdc%2B%2B@gcc.gnu.org>>
>      > Sent: Wednesday, March 11, 2020 10:26
>      > To: Nathan Sidwell
>      > Cc: libstdc++@gcc.gnu.org <mailto:libstdc%2B%2B@gcc.gnu.org>; GCC
>     Patches
>      > Subject: Re: ODR violation in ranges
>      >
>      > On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
>      >> Jonathan,
>      >> the ranges header contains code like:
>      >>     inline constexpr __adaptor::_RangeAdaptorClosure all
>      >>       = [] <viewable_range _Range> (_Range&& __r)
>      >>       {
>      >> if constexpr (view<decay_t<_Range>>)
>      >>    return std::forward<_Range>(__r);
>      >> else if constexpr (requires {
>     ref_view{std::forward<_Range>(__r)}; })
>      >>    return ref_view{std::forward<_Range>(__r)};
>      >> else
>      >>    return subrange{std::forward<_Range>(__r)};
>      >>       };
>      >>
>      >> (line 1236)
>      >>
>      >> When you strip away all the templateyness, you have:
>      >>
>      >>
>      >> inline constexpr auto all = [] () {};
>      >>
>      >>
>      >> That's an ODR violation -- the initializers in different TUs are not
>      >> the same!
>      >>
>      >> As you can guess, I can't turn this into a header unit (well, I can,
>      >> but merging duplicates complains at you)
>      >
>      > CC libstdc++@ and Patrick.
>      >
>      > I did wonder if using lambdas for those global variables would be OK.
>      >
>      > I think we'll need a new class template for each view adaptor, rather
>      > than using the _RangeAdaptorClosure to hold a closure.
>      >
>      > Patrick, can you look into that please?
>      >
> 
> 
>     -- 
>     Nathan Sidwell
> 


-- 
Nathan Sidwell

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-03-11 15:39 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-11 10:08 ODR violation in ranges Nathan Sidwell
2020-03-11 10:26 ` Jonathan Wakely
2020-03-11 10:56   ` Tam S. B.
2020-03-11 12:47     ` Jonathan Wakely
2020-03-11 13:21     ` Patrick Palka
2020-03-11 15:05     ` Nathan Sidwell
2020-03-11 15:23       ` Jason Merrill
2020-03-11 15:39         ` Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).