mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 00:36:34 +00:00
[clangd] Refactor forwarding call detection logic
Differential Revision: https://reviews.llvm.org/D130261
This commit is contained in:
parent
1515490c80
commit
b5871dfaf3
@ -791,51 +791,46 @@ private:
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
auto OptPackLocation = findPack(Args);
|
||||
if (OptPackLocation) {
|
||||
size_t PackLocation = OptPackLocation.value();
|
||||
ArrayRef<ParmVarDecl *> 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<ParmVarDecl *> 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<size_t> 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<ParmVarDecl>(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 @@ private:
|
||||
}
|
||||
}
|
||||
// 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 @@ private:
|
||||
return MatchingDecl;
|
||||
}
|
||||
|
||||
// Removes any implicit cast expressions around the given expression.
|
||||
static const Expr *unwrapImplicitCast(const Expr *E) {
|
||||
while (const auto *Cast = dyn_cast<ImplicitCastExpr>(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<CallExpr>(E)) {
|
||||
const auto Callee = Call->getBuiltinCallee();
|
||||
if (Callee == Builtin::BIforward) {
|
||||
return Call->getArg(0);
|
||||
return dyn_cast<DeclRefExpr>(
|
||||
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<DeclRefExpr>(E);
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user