[cxx-abi-dev] need mangling for string literals and lifetime-extended temporaries used in static constexpr member initializers and for string literals in constexpr functions

Gabriel Dos Reis gdr at integrable-solutions.net
Fri May 24 09:21:36 UTC 2013


On Fri, May 24, 2013 at 3:10 AM, John McCall <rjmccall at apple.com> wrote:
> On May 23, 2013, at 11:29 PM, Richard Smith <richardsmith at google.com> wrote:
>
> On Thu, May 23, 2013 at 10:41 PM, John McCall <rjmccall at apple.com> wrote:
>>
>> On May 23, 2013, at 10:23 PM, Richard Smith <richardsmith at google.com>
>> wrote:
>> > So... this problem was not really new in C++11. In C++98 it can be
>> > witnessed for an inline function such as:
>> >
>> > inline const char *get() {
>> >   static const char *str = "foo";
>> >   return str;
>> > }
>>
>> How is this different from the following?
>>
>>   inline const char *get_nostatic() { return "foo"; }
>>
>> or
>>
>>   inline const char *get_separate() {
>>     const char *temp = "foo";
>>     static const char *str = tmp;
>>     return str;
>>   }
>>
>> Please find or add something in the standard which will allow us to
>> not export a symbol for every string literal(*) that happens to be used
>> in a function with weak linkage.
>
>
> Finding failed. In addition to the implications of the ODR, we have this:
>
> [dcl.fct.spec]p4: "A string literal in the body of an extern inline function
> is the same object in different translation units."
>
>
> This is a really terrible language requirement.  Does anyone actually do
> what's necessary for this?

It has been in C++ for over 2 decades, if I remember correctly.

Here is a testcase -- which is handled properly by G++.
There are 4 translation units involved.

1.  a.h contains only

inline const char*
get_sptr() {
   static const char* s = "foo";
   return s;
}

2. a1.C includes a.h and defines f1:
#include "a.h"

const char* f1() {
   return get_sptr();
}


3. a2.C includes a.h and defines f2:
#include "a.h"

const char* f2() {
   return get_sptr();
}


4. b.C includes <assert.h> but not a.h, calls f1, f2 in main() with an
assertion:
#include <assert.h>

const char* f1();
const char* f2();

int main() {
   assert(f1() == f2());
}


Now, compile the translation units obtained form a1.C, a2.C, and b.C
separately, and link them.  The assertion should pass.  G++ on x86
and x86_64 handles that properly.


> I really can't imagine actually implementing it;
> it would be a *ton* of new extern symbols.

Only if the string literals escape their enclosing functions.

-- Gaby


More information about the cxx-abi-dev mailing list