diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 53adf230beae0a..44c6f49f55c20b 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -791,51 +791,46 @@ class ForwardingCallVisitor })) { return; } - auto OptPackLocation = findPack(Args); - if (OptPackLocation) { - size_t PackLocation = OptPackLocation.value(); - ArrayRef MatchingParams = - Callee->parameters().slice(PackLocation, Parameters.size()); - // Check whether the function has a parameter pack as the last template - // parameter - if (const auto *TTPT = getFunctionPackType(Callee)) { - // In this case: Separate the parameters into head, pack and tail - auto IsExpandedPack = [&](const ParmVarDecl *P) { - return getUnderylingPackType(P) == TTPT; - }; - ForwardingInfo FI; - FI.Head = MatchingParams.take_until(IsExpandedPack); - FI.Pack = MatchingParams.drop_front(FI.Head.size()) - .take_while(IsExpandedPack); - FI.Tail = MatchingParams.drop_front(FI.Head.size() + FI.Pack.size()); - FI.PackTarget = Callee; - Info = FI; - return; - } - // Default case: assume all parameters were fully resolved + auto PackLocation = findPack(Args); + if (!PackLocation) + return; + ArrayRef MatchingParams = + Callee->parameters().slice(*PackLocation, Parameters.size()); + // Check whether the function has a parameter pack as the last template + // parameter + if (const auto *TTPT = getFunctionPackType(Callee)) { + // In this case: Separate the parameters into head, pack and tail + auto IsExpandedPack = [&](const ParmVarDecl *P) { + return getUnderylingPackType(P) == TTPT; + }; ForwardingInfo FI; - FI.Head = MatchingParams; + FI.Head = MatchingParams.take_until(IsExpandedPack); + FI.Pack = + MatchingParams.drop_front(FI.Head.size()).take_while(IsExpandedPack); + FI.Tail = MatchingParams.drop_front(FI.Head.size() + FI.Pack.size()); + FI.PackTarget = Callee; Info = FI; + return; } + // Default case: assume all parameters were fully resolved + ForwardingInfo FI; + FI.Head = MatchingParams; + Info = FI; } // Returns the beginning of the expanded pack represented by Parameters // in the given arguments, if it is there. llvm::Optional findPack(typename CallExpr::arg_range Args) { // find the argument directly referring to the first parameter - auto FirstMatch = std::find_if(Args.begin(), Args.end(), [&](Expr *Arg) { - const auto *RefArg = unwrapArgument(Arg); - if (RefArg) { - if (Parameters.front() == dyn_cast(RefArg->getDecl())) { - return true; - } + for (auto It = Args.begin(); It != Args.end(); ++It) { + const Expr *Arg = *It; + if (const auto *RefArg = unwrapForward(Arg)) { + if (Parameters.front() != RefArg->getDecl()) + continue; + return std::distance(Args.begin(), It); } - return false; - }); - if (FirstMatch == Args.end()) { - return llvm::None; } - return std::distance(Args.begin(), FirstMatch); + return llvm::None; } static FunctionDecl *getCalleeDeclOrUniqueOverload(CallExpr *E) { @@ -847,7 +842,7 @@ class ForwardingCallVisitor } } // Ignore the callee if the number of arguments is wrong (deal with va_args) - if (Callee->getNumParams() == E->getNumArgs()) + if (Callee && Callee->getNumParams() == E->getNumArgs()) return Callee; return nullptr; } @@ -873,31 +868,17 @@ class ForwardingCallVisitor return MatchingDecl; } - // Removes any implicit cast expressions around the given expression. - static const Expr *unwrapImplicitCast(const Expr *E) { - while (const auto *Cast = dyn_cast(E)) { - E = Cast->getSubExpr(); - } - return E; - } - - // Maps std::forward(E) to E, nullptr otherwise - static const Expr *unwrapForward(const Expr *E) { + // Tries to get to the underlying argument by unwrapping implicit nodes and + // std::forward. + static const DeclRefExpr *unwrapForward(const Expr *E) { + E = E->IgnoreImplicitAsWritten(); if (const auto *Call = dyn_cast(E)) { const auto Callee = Call->getBuiltinCallee(); if (Callee == Builtin::BIforward) { - return Call->getArg(0); + return dyn_cast( + Call->getArg(0)->IgnoreImplicitAsWritten()); } } - return E; - } - - // Maps std::forward(DeclRefExpr) to DeclRefExpr, removing any intermediate - // implicit casts, nullptr otherwise - static const DeclRefExpr *unwrapArgument(const Expr *E) { - E = unwrapImplicitCast(E); - E = unwrapForward(E); - E = unwrapImplicitCast(E); return dyn_cast(E); } };