3

I was trying Coverity out on some code base and I got a warning on a code akin to

struct Foo
{
    std::string name;
};

Foo getFoo();
//...
const auto& name = getFoo().name;
useName(name);

Is this code valid?

I had the intuition that it's indeed invalid. But then, when searching for proofs, I've come across [class.temporary]/6.4, which seems to say that it's actually well-formed. Yet, Coverity issues a warning, and Coverity is surely written by some smart folks that can interpret the standard better than me.

The specific Coverity warning that's issued is

Dereferencing the returned or out-of-scope stack pointer will access an invalid location on the stack after its scope or after the function returns.

In whateverSurroundingFunction(): Pointer to a local stack variable returned or used outside scope (CWE-562)

on the subsequent usage of name. The preceding warning is that

out_of_scope: Temporary variable of type Foo goes out of scope

And a sort of MRE is this (kudos to @user4581301 in the comments).


SO has a bunch of questions about temporary bound references, but those that I've seen each has a slightly different context, hence here comes yet another question on them.

Community
  • 1
  • 1
0xd34df00d
  • 1,496
  • 1
  • 8
  • 17
  • Yes, a reference will extend the lifetime of a temporary. But this does not apply here, because you're not creating a reference to a temporary value. It really isn't. It's a reference to a member of a class that's the temporary object is an instance of. Big difference. – Sam Varshavchik May 12 '20 at 04:06
  • But, again, isn't it covered by the paragraph that I linked (/6.4)? If not, how should I read it — that is, what does /6.4 cover? – 0xd34df00d May 12 '20 at 04:08
  • 1
    I recommend strengthening your question with a legit MCVE, something like https://godbolt.org/z/S9NXsT . I want to see how this one pans out once the language lawyers are through. – user4581301 May 12 '20 at 04:21
  • @user4581301 your example is close enough (I think), I'll link it in the question body if you don't mind. – 0xd34df00d May 12 '20 at 04:22
  • 1
    does Coverity give a warning for the godbolt example? – M.M May 12 '20 at 04:34

1 Answers1

7

This code is well-formed. As the linked standard says, the lifetime of the temporary returned by getFoo() will be extended to the lifetime of the reference variable name.

(emphasis mine)

Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference

The reference is bound to the subobject name of the temporary Foo directly, then the lifetime gets extended. Other ways, e.g. binding the reference via the member function returning reference to data member won't work.

struct Foo
{
    std::string name;
    std::string& get_name() { return name; }
};

Foo getFoo();

then

const auto& name = getFoo().get_name();
std::cout << name << std::endl; // UB; name is dangled

LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405