rsmith added inline comments.

================
Comment at: clang/lib/Sema/SemaStmt.cpp:3150-3153
+  // If we got a non-deduced auto ReturnType, we are in a dependent context and
+  // there is no point in allowing copy elision since we won't have it deduced
+  // by the point the VardDecl is instantiated, which is the last chance we 
have
+  // of deciding if the candidate is really copy elisible.
----------------
mizvekov wrote:
> mizvekov wrote:
> > rsmith wrote:
> > > How does this happen? Are there any cases where we could do NRVO or 
> > > should do an implicit move that are blocked by this?
> > > 
> > > It seems to me that we should (nearly always) be able to work out whether 
> > > copy elision is possible here without knowing the deduced type:
> > > -- if the return type is //cv// `auto` then it will always be deduced to 
> > > the type of the returned variable, so we can always perform copy elision
> > > -- if the return type is `decltype(auto)`, then we can perform copy 
> > > elision if the expression is unparenthesized and otherwise cannot; we 
> > > could perhaps track whether the expression was parenthesized in 
> > > `NRVOResult`, and can conservatively disallow copy elision if we don't 
> > > know (eg, from template instantiation, where we're only looking at the 
> > > variable and not the return statements)
> > > -- if the return type is anything else involving `auto`, it can't 
> > > possibly instantiate to a class type, so we'll never perform copy elision
> > Yeah, what you suggested is what I tried on a previous patch in this DR, 
> > but then studying the NRVO tracker carefully I thought about this counter 
> > example:
> > ```
> > template<bool B> static auto bar() {
> >   {                                 
> >     Foo foo;                        
> >     if constexpr(B)                 
> >       return foo;                  
> >   }                                 
> >   {                                 
> >     Bar bar;                        
> >     if constexpr(!B)                
> >       return bar;                   
> >   }                                 
> > }                                   
> > ````
> > 
> > Since we run the tracker before instantiation, we would see both return 
> > statements and mark both foo and bar as NRVO variables.
> > Ofcourse in the B = false case, we would end up constructing a Foo in a Bar 
> > return slot....
> > 
> > As a side note, It is actually funny that we currently perform this 
> > optimization (most likely accidentally):
> > ```
> > template<bool B> static Foo bar() {
> >   {                                 
> >     Foo foo1;                        
> >     if constexpr(B)                 
> >       return foo1;                  
> >   }                                 
> >   {
> >     Foo foo2;
> >     return foo2                                 
> >   }                                 
> > }
> > ```
> > In the B = false case, we end up constructing foo1 in the return slot even 
> > though we actually never return it.
> Compiler explorer link for the accidental optimization I am talking about: 
> https://godbolt.org/z/czdWodW87
That's amazing, and makes total sense. Yeah, `if constexpr` pretty thoroughly 
destroys the assumptions we make in the `Scope`-based NRVO computation about 
what a templated function will look like after instantiation.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D99696/new/

https://reviews.llvm.org/D99696

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to