The new matcher allows users to provide a matcher for both the argument of a CallExpr/CxxConstructExpr a well as the ParmVarDecl of the argument.
Details
Diff Detail
Event Timeline
include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
2825–2851 | I don't think the handling of BoundNodesTreeBuilder is correct (writing tests to catch that will be a nice exercise ;) The trick is that the resulting BoundNodesTreeBuilder must contain the full results of all matches. If you look at the other forEach matchers, you can see a pattern: If you don't pass the builder in that is initialized with the current result, any subexpressions that uses equalsBoundNode will be incorrect. Please add tests that test equalsBoundNode behavior in all cases, especially if you have multiple ones where everything matches, but then the equalsBoundNode fails. |
I think I'm not yet fully clean on the semantics of matching bound nodes. Do we want to allow that also between the argument matcher and the param matcher by copying the matches between the two matchers or do we only support matches to bound nodes that are already matched before forEachArgumetWithParam is invoked?
I'm also not quite sure how write these tests. Looking at some of the other forEach matchers (SwitchCase, ContructorInitializer) I don't see examples I could pattern mine after.
I updated the change to copy the Builder.
The tests to look at are the equalsBoundNode matchers (because it mainly makes a difference there). Especially take a look at FiltersMatchedCombinations.
The question is what we want to happen for things like:
void g(int x, int y);
void f() { int a; int b; int c; g(a, 0); g(a, b); b(0, b); } functionDecl( forEachDescendant(varDecl().bind("v")), forEachDescendant(callExpr(forEachArgumentWithParam(declRefExpr(to(decl(equalsBoundNode("v")))), parmVarDecl()))))
The trick is that we currently want all combinations to match (and no match with 'c' bound to 'v').
Does that make sense?
Add the new matcher to ASTMatchers/Dynamic/Registry.cpp to make it accessible to clang-query.
include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
2837 | use isa<> instead of dyn_cast<> if you don't care about the pointer itself. Also, you could fold that check into the matcher itself using expr(anyOf(cxxConstructExpr(...), callExpr(...))) |
Thanks. I've added that test case and am counting 4 matches, two where 'a' is used as argument and two for 'b'.
Let me know if that is sufficient whether you can think of more test cases.
Thanks for the example. I created a test case based on it. Let me know if any other cases are still missing.
include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
2837 | Thanks, done! |
I had to update the semantics of forEachArgumentWithParam further to correctly handle CXXOperatorCallExpr (a sub-class of CallExpr) for member operator calls. In this case the first 0-th argument is actually the implicit object argument and the corresponding matcher should not be applied against parameter 0 which belongs to argument 0.
To handle this I'm incrementing the argument index by one in this case.
Updated patch with this.
Sorry, the above comment was confusing (a lot of off-by one errors). Corrected version:
I had to update the semantics of forEachArgumentWithParam further to correctly handle CXXOperatorCallExpr (a sub-class of CallExpr) for member operator calls. In this case the 0-th argument is actually the implicit object argument and Argument matcher should not be applied it. Instead argument 1 and parameter 0 should be paired.
To handle this I'm incrementing the argument index by one in this case.
include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
2835 | Changing to unsigned due to -Wsign-compare trigger. |
Changing to unsigned due to -Wsign-compare trigger.