[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
John McCall
rjmccall at apple.com
Fri May 24 19:53:38 UTC 2013
On May 24, 2013, at 2:21 AM, Gabriel Dos Reis <gdr at integrable-solutions.net> wrote:
> 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.
Three, sir.
> 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.
See, this is tricky. Does it handle it properly, or does it happen to work
because the linker combines strings within a linkage unit?
>> 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.
In practice, almost every string literal escapes its enclosing function.
printf("foo\n"); // <-- unless the compiler hard-codes printf, this is an escape
John.
More information about the cxx-abi-dev
mailing list