void foobar(int); int main() { foobar(1 + 2); ^ }
Currently the CalleeArgInfo will be "Passed by reference", which should
be "Passed by value".
Differential D142014
[clangd] fix wrong CalleeArgInfo in the hover v1nh1shungry on Jan 18 2023, 6:28 AM. Authored by Tokens
Details void foobar(int); int main() { foobar(1 + 2); ^ } Currently the CalleeArgInfo will be "Passed by reference", which should
Diff Detail
Event TimelineComment Actions Thanks for the patch! I had a look at the code history, and it looks like the original reason for not using the param decl's type to determine the passing mode was (based on this comment) to handle cases like this correctly: struct C { C(int&); }; void foo(const C&); int main() { int y; foo(y); // want PassMode::Ref } However, your patch keeps this case working by keeping the check for a CXXConstructExpr and using the constructor's parameter decl instead (and this scenario has test coverage in the test Hover.CallPassType), so this seems fine to me, and indeed a nice simplification. That said, I will cc @adamcz and @kadircet (as author and reviewer of the original patch) to see if they have any concerns about this refactoring breaking any other cases.
Comment Actions Thanks for the review! @tom-anders
Comment Actions I just came up with a case where the original implementation and this patch behave differently. void foobar(const float &); int main() { foobar(0); ^ } Used to Passed by value, now it is Passed by const reference. I think the former one is apparently better. This case can be fixed by getting the PassType.PassBy = HoverInfo::PassType::Value; back to the ImplicitCastExpr case, but hmm...It does make me hesitate to insist on the current code change. Maybe we should switch to @kadircet's idea if I understand him correctly. WDYT, @nridge, @tom-anders and @adamcz? But the isLiteral() and ImplicitCastExpr cases in the original implementation bring enough mystery and risks to me. For me this is a hard decision.
Comment Actions Why is "passed by value" better? My mental model here is that the value does not get copied; for a built-in type that may not be much of a distinction, but if you imagine generalizing to a class type constructed using a user-defined literal, it could be a noncopyable (and in C++17, even non-moveable) type that can't be passed around by value. Comment Actions Ah, I think you're right. I was confused. This case seems good to me. I guess I was thinking about void foobar(const float &); int main() { int a; foobar(a); ^ } Used to be Passed by value, now it is Passed by const reference. I think it's kind of confusing because the local variable a isn't actually referenced, right?
Comment Actions Thanks for the review! @kadircet Would you mind having a look at if there're any concerns about the current code change, @nridge, @tom-anders, and @adamcz? Thanks a lot! |
nit: name the parameter ParmType, so it's clear whose type it's expecting