<div dir="auto"><br></div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, May 24, 2021 at 3:21 PM Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="ltr"><div dir="ltr">On Mon, 24 May 2021 at 12:25, Vitali Lovich via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="ltr">I was trying to incorporate the lifetime bound in an OSS project (<a href="https://github.com/capnproto/capnproto/pull/1246" target="_blank">https://github.com/capnproto/capnproto/pull/1246</a>) and it surfaced a potential limitation of the annotation (or perhaps I'm just not utilizing its full power yet).<div><br></div><div>Is there a way to use the lifetime annotation to have the compiler track the lifetime through copies? For example, if <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">std::string</font>'s conversion operator to <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">std::string_view</font> is annotated, will copying/moving/assigning the returned std::string_view (e.g. when building up a <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">vector</font> of <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">string_view</font> in a loop but accidentally having that <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">string_view</font> point to a <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">string</font> local to the loop) cause the compiler to still see the copies as having their lifetimes tied to the original std::string? One would think that defaulted copies/moves/assignments would automatically preserve the lifetime & there would need to be some kind of additional annotation for the more complex use-cases, but from my testing this is perhaps not yet implemented?.</div></div></blockquote><div><br></div><div>Yes, this should work as you describe, but that is not implemented yet.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="ltr"><div>Relatedly, it seems even as something as simple as below didn't trigger the warning so I'm wondering if I'm misusing it or if the lifetime tracking is just very limited in the cases it can find.</div><div><br></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">struct Foo {</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">  std::string buf;</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">  operator std::string_view() const [[clang::lifetimebound]] {</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">    return buf;</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">  }</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">};</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)"><br></font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">int main() {</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">  for (int i = 0; i < 5; i++) {</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">    std::string_view x;</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">    {</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">      Foo str = { .buf = std::to_string(i) };</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">      x = str;</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">    }</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">    std::cerr << x << "\n";</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">  }</font></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">}</font></div><div><br></div><div><font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">clang++ -std=c++20 -Wall</font> doesn't seem to generate a warning (v13 from revision 0e92cbd6a652c). Adding <font face="monospace" style="font-family:monospace;color:rgb(0,0,0)">-fsanitize=address</font> does cause the program to crash when run.</div></div></blockquote><div><br></div><div>At the moment, the lifetimebound warning only considers initializations, not assignments. We could in principle warn that `x = str;` assigns a value with shorter lifetime to a variable with longer lifetime, though that would have false positives on cases like:</div><div><br></div><div>string_view x;</div><div>{</div><div>  Foo str = ...</div><div>  x = str;</div><div>  ...</div><div>  x = "something else";</div><div>}</div><div><br></div><div>... or if x is not used after the lifetime of str ends. Correctly handling those cases would require a more sophisticated kind of analysis than the syntactic check we currently perform. (Though perhaps the simplistic analysis that warns directly on the `x = str;` assignment without considering the context would be useful enough in practice, despite the potential for false positives?)</div></div></div></blockquote><div dir="auto">ah ok. That explains it. The specific case I was hoping would be caught was initializing a vector of string views and accidentally using a reference to a string that didn’t outlive the loop itself. I was doing something like v[i] = std::to_string(…). I suspect the false positive would be fine for my specific project (although I’d need to double-check with a version of clang that could do that) but I can’t make the call for all users of clang/this annotation. I found it interesting that libc++ has not itself adopted this annotation and I suspect I may be one of very few people who’s not a clang maintaner/developer to have noticed the existence of the annotation in the first place and tried to use it :).</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="ltr"><div class="gmail_quote"><div dir="auto"></div></div></div>
</blockquote></div></div>