[cxx-abi-dev] lambda ABI inline function ODR compatibility issue
John McCall
rjmccall at apple.com
Fri Jan 18 02:01:24 UTC 2013
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?
}
John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20130117/95302ba9/attachment-0001.html>
More information about the cxx-abi-dev
mailing list