[cxx-abi-dev] lambda ABI inline function ODR compatibility issue

Richard Smith richardsmith at google.com
Fri Jan 18 02:38:03 UTC 2013


On Thu, Jan 17, 2013 at 6:01 PM, John McCall <rjmccall at apple.com> wrote:

> On Jan 17, 2013, at 4:12 PM, Richard Smith <richardsmith at google.com>
> wrote:
>
> On Thu, Jan 17, 2013 at 2:35 PM, Michael Wong <michaelw at ca.ibm.com> wrote:
>
>> Lawrence Crowl <crowl at googlers.com> wrote on 01/17/2013 04:50:52 PM:
>>
>> > From:
>> >
>> > Lawrence Crowl <crowl at googlers.com>
>> >
>> > To:
>> >
>> > Michael Wong/Toronto/IBM at IBMCA
>> >
>> > Cc:
>> >
>> > cxx-abi-dev at codesourcery.com
>> >
>> > Date:
>> >
>> > 01/17/2013 04:50 PM
>> >
>> > Subject:
>> >
>> > Re: [cxx-abi-dev] lambda ABI inline function ODR compatibility issue
>> >
>> > On 1/16/13, Michael Wong <michaelw at ca.ibm.com> wrote:
>> > > Does the C++ Standard committee intend for the ODR to imply that
>> lambdas
>> > > need to have an ABI specified layout in order to deal with inline
>> > > functions.
>> >
>> > I believe that we thought it was not an issue.
>>
>> >
>> > >
>> > > Consider the following with one object compiled with -DMAIN and
>> another
>> > > without:
>> > > - in one case the layout needs to be compatible between different
>> > > implementations since the static local is shared between translation
>> units
>> > >
>> > > /data/a.o: In function `main':
>> > > a.cpp:(.text+0x18): undefined reference to `bar()'
>> > > collect2: error: ld returned 1 exit status
>> > >
>> > > - in the other case, the layout needs to be compatible between
>> different
>> > > implementations in order to satisfy the ODR requirement that the
>> program
>> > > behave as if there was only one definition of the inline function
>> > >
>> > > extern "C" int printf(const char *, ...);
>> > > extern long gz;
>> > >
>> > > inline void foo() {
>> > >    long x = 0, q = 0, &z = gz;
>> > >    static auto f = [=, &z]() mutable { q += ++x; gz = q + x; };
>> > >
>> > >    long a, b;
>> > >    auto ff = [=]{ sizeof(a /*not an odr-use*/), printf("%u\n", &b <
>> &a); };
>> > >    f();
>> > >    ff();
>> > > }
>> > >
>> > > void bar();
>> > >
>> > > #if ! MAIN
>> > > void bar() { foo(); }
>> > > #else
>> > > long gz;
>> > > int main() {
>> > >    foo();
>> > >    bar();
>> > >    foo();
>> > >    return gz;
>> > > }
>> > > #endif
>> >
>> > And this code demonstrates that it is an issue.
>> Agreed.
>>
>> >
>> > Do you have a proposal?
>>
>> Probably 2 thoughts:
>> 1. Make a static in an inline a violation of the ODR rule in the C++ Std
>> (add in suitable wording covering all uses with external linkage)or
>> 2. create an ABI binding in the C++ ABI such that all vendors follow the
>> same behavior in this case
>>
>> I think I am OK with either solution.
>> There may be other solutions I have not entertained yet ...
>
>
> For option 1, we would only need to disallow static local variables from
> having types involving local lambdas with captures, right? All the other
> problems I can think of would be handled by putting the lambda's symbols in
> a COMDAT with the containing function.
>
>
> We could also have problems with template specializations involving the
> lambda type, no?
>
> template <class T> InstanceCount {
>   static int count;
> };
> template <class T> int InstanceCount<T>::count = 0;
>
> inline void foo(int x) {
>   auto lambda = [=] { return x; };
>   InstanceCount<decltype(lambda)>::count++; // is this count consistent
> across translation units?
> }
>

That's OK; it just needs the mangling of the lambda's type.

This case seems more problematic:

void *p;
inline void f(int a, int b) {
  auto lambda = [=] { return a + b; };
  if (p)
    (*reinterpret_cast<decltype(lambda)*>(p))();
  else
    p = new auto(lambda);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20130117/813568dd/attachment.html>


More information about the cxx-abi-dev mailing list