sammccall added inline comments.
================ Comment at: clang-tools-extra/clangd/AST.cpp:832 continue; + // Check that this expands all the way until the last parameter. + auto ParamEnd = It + Parameters.size() - 1; ---------------- upsj wrote: > sammccall wrote: > > The essence of this test seems to be "if we can't rule it out by counting > > parameters, it must be right" which... doesn't seem very robust? Am I > > missing something? > > > > AIUI the idea here is that > > A) `foo(pack...)` is "expanded all the way" into consecutive arguments > > B) `foo(pack)...` is not considered forwarding for our purposes > > C) we want to treat `foo(bar(pack)...)` specially if `bar` is "just a cast" > > like move or forward > > > > The difference between cases A and B aren't about counting arguments > > though, they're about what operations occur intercede between `pack` and > > the `...` operator. (i.e. `foo((&pack)...)` is fine for the same reason > > `forward` is. > > > > This seems like something best handled by: > > - finding the `PackExpansionExpr` controlling `pack` in the > > non-instantiated template AST > > - walking down to try to find `pack` > > - continue as we walk through e.g. parens or std::forward > > - bail out if we walk through something unknown (e.g. another function > > call) > > > > Does this seem sensible/feasible? > > (Walking up from `pack` is nicer but the AST doesn't support walking up > > well...) > This goes a bit more generally into the question how to approach parameter > packs across clangd. For inlay hints and hover, we are already looking at > instantiated templates (is that true in all cases? Haven't dug in yet), so > implementing forwarding there was straightforward. For signature help and > code completion, we'd probably need to go via the uninstantiated template > (and probably lose a bit of type information on the way, e.g. reference vs. > value, l-value vs. r-value). If we wanted a generic way to deal with > forwarding, the instantiation pattern would be my first choice, but I didn't > have the time to go down this rabbit hole yet. > Unless there is a nice way to map between template and instantiation AST, I > don't think combining them is feasible. > > On the heuristic itself: Is there a way in C++ to "partially" unpack a > parameter pack without this showing up in the AST? I am not aware of any, > which is why the test "do the first and last parameters appear in a matching > range of the arguments" seems sufficient and necessary in all but > single-entry parameter packs. > Unless there is a nice way to map between template and instantiation AST, I > don't think combining them is feasible. Fair enough, I don't see one. > On the heuristic itself: Is there a way in C++ to "partially" unpack a > parameter pack without this showing up in the AST? Not AFAIK, the is either expanded at "this level" yielding sibling args, or at "a higher level" yielding a single arg. So maybe the "first & last" test is actually robust, but it would need some justification in comments. There's an exception I think, if the pack size is one it falls over: ``` bar(int bar0); bar(int bar0, int bar1); bar(int bar0i, int bar1, int bar2); template <class...Args> void foo(Args...args) { bar(args...); // should yield labels when expanded bar(args)...; // should not yield labels when expanded } // but when there's one arg (foo<int>) the two have the same AST ``` I think it's OK to just get this one wrong Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D130260/new/ https://reviews.llvm.org/D130260 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits