AST matcher: ForEach FunctionDecl -> ParmVarDecl

Dear all,

Is there any AST matcher that can produce an iteration operation like: FOR-EACH parameter of function?
I am trying to match call expressions where the caller arguments are the parameters of another, outer function.
For this solution I am using equalsBoundNode() as a narrowing matcher.

My problem is that I am unable to find a way to match all the function parameters. The matcher only matches the first parameter.

Here is the full matcher:

auto calleeArgVarDecl = declRefExpr(to(varDecl().bind(“callerArg”)))

auto innerCallExpr = callExpr(
forEachArgumentWithParam(
anyOf(
unaryOperator(hasDescendant(calleeArgVarDecl)),
calleeArgVarDecl
),
parmVarDecl().bind(“calleeParam”)
),
callee(functionDecl().bind(“calleeFunc”)), unless(isExpansionInSystemHeader())).bind(“callExpr”)

auto fullMatcher = functionDecl(
forEachDescendant(innerCallExpr),
hasAnyParameter(
parmVarDecl(equalsBoundNode(“callerArg”)).bind(“outerFuncParam”)
)
).bind(“outerFunc”)

I tryed to use the folowing matchers but none of them solved my problem:
hasAnyParameter(…) - It only binds the first parameter that is matched.
hasParameter(n,…) - I can use this one only if the function has a known number of parameters. This solution is not so good because the number of parameters is unknown.
forEachArgumentWithParam - only works for caller expressions, and I am matching parameters of a functionDecl.

Any help would be greatly appreciated

You need to write your own matcher.

These untested/uncompiled snippets should get you started:

bool callArgsAreFuncParams(CallExpr const& C, FunctionDecl const& F)
{
     // TODO: Handle variadic args

     // TODO: Handle default arguments in call

     if (C.argumentCount() != F.parameterCount())
         return false;

     for (auto i = 0; i < C.argumentCount(); ++i)
     {
         if (C.getArg(i).getDecl() != F.getParameter(i))
             return false;
     }
     return true;
}

AST_MATCHER(CallExpr, forwardsAllParameters) {
   const auto &Parents = Finder->getASTContext().getParents(Node, true);

   llvm::SmallVector<ast_type_traits::DynTypedNode, 8> Stack(Parents.begin(),
                                                             Parents.end());
   while(!Stack.empty()) {
     const auto &CurNode = Stack.back();
     Stack.pop_back();
     if(const auto *FuncDeclNode = CurNode.get<FunctionDecl>()) {
       if (callArgsAreFuncParams(Node, *FuncDeclNode))
         return true;
     } else if(const auto *LambdaExprNode = CurNode.get<LambdaExpr>()) {
       if (callArgsAreFuncParams(Node, *LambdaExprNode->getCallOperator()))
         return true;
     } else {
       for (const auto &Parent :
            Finder->getASTContext().getParents(CurNode, true))
         Stack.push_back(Parent);
     }
   }
   return false;
}

auto fullMatcher = callExpr(
     forwardsAllParameters(),
     forFunction(functionDecl().bind("outerFunction"))
     ).bind("innerCall")

It would also be possible to design the matcher such that it is used like this:

  forwardsAllParametersFrom(functionDecl().bind("outerFunction"))

That's left as an exercise for the reader.

Thanks,

Stephen.

Hi,
I am really sorry I did not gave a proper explanation of what I am trying to do.

I want to match the call expressions where at least SOME of its arguments are the parameters or SOME of the parameters of the outer function.
Not all arguments have to be the parameters of the outer function.
I don’t really need to forward all parameters to arguments.

The combination of the built-in matches that I used, only matched the first parameter because I was unable to do some sort of loop there.
As a result, only first parameter of the outer function is matched, others are were not matched.

Is there an option to make an iteration over all outer function parameters and still use the equalsBoundNode(“callerArg”) narrowing matcher?
Or the only option is to try implementing a custom matcher?

Thank you so much for your help.