Quuxplusone added inline comments.
================ Comment at: clang/lib/Sema/SemaCoroutine.cpp:896 + if (S.CanPerformCopyInitialization(Entity, &AsRvalue)) + return true; + } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) { ---------------- aaronpuchert wrote: > Overlad resolution can actually still fail if there is a viable candidate, > namely when there are multiple candidates and none is better than all others. > It's a bit weird though to fall back to lvalue parameter then as if nothing > happened. That is an interesting point! I had not considered it during [P1155](https://wg21.link/p1155r2). I imagine that it might make implementation of [P1155](https://wg21.link/p1155r2)'s new logic more difficult. GCC 8 (but not trunk) implements the behavior I would expect to see for derived-to-base conversions: https://godbolt.org/z/fj_lNw C++ always treats "an embarrassment of riches" equivalently to a "famine"; overload resolution //can// fail due to ambiguity just as easily as it can fail due to no candidates at all. I agree it's "a bit weird," but it would be vastly weirder if C++ did anything //different// from its usual behavior in this case. I'm still amenable to the idea that `co_return` should simply not do the copy-elision or implicit-move optimizations at all. I wish I knew some use-cases for `co_return`, so that we could see if the optimization is useful to anyone. ================ Comment at: clang/test/SemaCXX/coroutine-rvo.cpp:65 + NoCopyNoMove value; + co_return value; +} ---------------- @aaronpuchert wrote: > Given the complexities of this implementation, I'm beginning to doubt whether > implicit moves make sense for `co_return` at all. Since there can never be > any kind of RVO, why not always require an explicit `std::move`? Implicit > moves on return were introduced because an explicit move would inhibit NRVO, > and without move there wouldn't be a graceful fallback for implementations > that don't have NRVO. I still think that it makes sense to do implicit-move on //any// control-flow construct that "exits" the current function. Right now that's `return` and `throw`, and they both do implicit-move (albeit inconsistently with plenty of implementation divergence documented in [P1155](http://wg21.link/p1155r2)). C++2a adds `co_return` as another way to "exit." I think it would be un-graceful and inconsistent to permit `return p` but require `co_return std::move(p)`. Now, I do think that C++2a Coroutines are needlessly complicated, which makes the implementation needlessly complicated. You've noticed that to codegen `t.return_value(x)` requires not just overload resolution, but actually figuring out whether `task::return_value` is a function at all — it might be a static data member of function-pointer type, or something [even wilder](https://quuxplusone.github.io/blog/2019/09/18/cppcon-whiteboard-puzzle/). But eliminating implicit-move won't make that complexity go away, will it? Doing implicit-move just means doing the required overload resolution twice instead of once. That //should// be easy, compared to the rest of the mess. That said, I would be happy to start a thread among you, me, David Stone, and the EWG mailing list to consider removing the words "or `co_return`" from [class.copy.elision/3](http://eel.is/c++draft/class.copy.elision#3.1). Say the word. [EDIT: aw shoot, I never submitted this comment last time] Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D68845/new/ https://reviews.llvm.org/D68845 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits