[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