[PATCH] D130260: [clangd] Make forwarding parameter detection logic resilient
Kadir Cetinkaya via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 21 05:49:39 PDT 2022
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: All.
kadircet requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang-tools-extra.
This could crash when our heuristic picks the wrong function. Make sure
there is enough parameters in the candidate to prevent those crashes.
Also special case copy/move constructors to make the heuristic work in
presence of those.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D130260
Files:
clang-tools-extra/clangd/AST.cpp
clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Index: clang-tools-extra/clangd/unittests/InlayHintTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -1432,26 +1432,30 @@
TEST(ParameterHints, ArgPacksAndConstructors) {
assertParameterHints(
R"cpp(
- struct Foo{ Foo(int x); };
+ struct Foo{ Foo(); Foo(int x); };
void foo(Foo a, int b);
-
template <typename... Args>
- void bar(Args... args) { foo(args...); }
-
+ void bar(Args... args) {
+ foo(args...);
+ }
template <typename... Args>
- void baz(Args... args) { foo(Foo(args...), args...); }
+ void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
template <typename... Args>
- void bax(Args... args) { foo({args...}, args...); }
+ void bax(Args... args) { foo($param3[[{args...}]], args...); }
void foo() {
- bar($param1[[Foo{2}]], $param2[[42]]);
- baz($param3[[42]]);
- bax($param4[[42]]);
+ bar($param4[[Foo{}]], $param5[[42]]);
+ bar($param6[[42]], $param7[[42]]);
+ baz($param8[[42]]);
+ bax($param9[[42]]);
}
)cpp",
ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
- ExpectedHint{"x: ", "param3"}, ExpectedHint{"x: ", "param4"});
+ ExpectedHint{"a: ", "param3"}, ExpectedHint{"a: ", "param4"},
+ ExpectedHint{"b: ", "param5"}, ExpectedHint{"a: ", "param6"},
+ ExpectedHint{"b: ", "param7"}, ExpectedHint{"x: ", "param8"},
+ ExpectedHint{"b: ", "param9"});
}
// FIXME: Low-hanging fruit where we could omit a type hint:
Index: clang-tools-extra/clangd/AST.cpp
===================================================================
--- clang-tools-extra/clangd/AST.cpp
+++ clang-tools-extra/clangd/AST.cpp
@@ -786,6 +786,9 @@
// inspects the given callee with the given args to check whether it
// contains Parameters, and sets Info accordingly.
void handleCall(FunctionDecl *Callee, typename CallExpr::arg_range Args) {
+ // Skip functions with less parameters, they can't be the target.
+ if (Callee->parameters().size() < Parameters.size())
+ return;
if (std::any_of(Args.begin(), Args.end(), [](const Expr *E) {
return dyn_cast<PackExpansionExpr>(E) != nullptr;
})) {
@@ -823,8 +826,7 @@
llvm::Optional<size_t> findPack(typename CallExpr::arg_range Args) {
// find the argument directly referring to the first parameter
for (auto It = Args.begin(); It != Args.end(); ++It) {
- const Expr *Arg = *It;
- if (const auto *RefArg = unwrapForward(Arg)) {
+ if (const auto *RefArg = unwrapForward(*It)) {
if (Parameters.front() != dyn_cast<ParmVarDecl>(RefArg->getDecl()))
continue;
return std::distance(Args.begin(), It);
@@ -871,6 +873,13 @@
// Maps std::forward(E) to E, identity otherwise.
static const DeclRefExpr *unwrapForward(const Expr *E) {
E = E->IgnoreImplicitAsWritten();
+ // There might be an implicit copy/move constructor call on top of the
+ // forwarded arg.
+ // FIXME: Maybe mark that in the AST as so, this might skip explicit calls
+ // too.
+ if (const auto *Const = dyn_cast<CXXConstructExpr>(E))
+ if (Const->getConstructor()->isCopyOrMoveConstructor())
+ E = Const->getArg(0)->IgnoreImplicitAsWritten();
if (const auto *Call = dyn_cast<CallExpr>(E)) {
const auto Callee = Call->getBuiltinCallee();
if (Callee == Builtin::BIforward) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D130260.446456.patch
Type: text/x-patch
Size: 3550 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220721/690b8ea3/attachment-0001.bin>
More information about the cfe-commits
mailing list