AST matcher: ForEach FunctionDecl -> ParmVarDecl

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

AST matcher: ForEach FunctionDecl -> ParmVarDecl

Richard Smith via cfe-dev
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

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AST matcher: ForEach FunctionDecl -> ParmVarDecl

Richard Smith via cfe-dev
On 30/12/2018 14:00, FarSight Studios via cfe-dev wrote:
> I am trying to match call expressions where the caller arguments are the
> parameters of another, outer function.

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.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AST matcher: ForEach FunctionDecl -> ParmVarDecl

Richard Smith via cfe-dev
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.

On Sun, Dec 30, 2018 at 4:41 PM Stephen Kelly via cfe-dev <[hidden email]> wrote:
On 30/12/2018 14:00, FarSight Studios via cfe-dev wrote:
> I am trying to match call expressions where the caller arguments are the
> parameters of another, outer function.

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.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


--
-------------------------------------
FarSight Studios
http://design.shadas.net

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev