sbenza added inline comments.

================
Comment at: clang-tidy/misc/AssignOperatorCheck.cpp:63
@@ +62,3 @@
+
+  Finder->addMatcher(returnStmt(IsBadReturnStatement, 
hasAncestor(IsGoodAssign))
+                         .bind("returnStmt"),
----------------
baloghadamsoftware wrote:
> sbenza wrote:
> > baloghadamsoftware wrote:
> > > sbenza wrote:
> > > > baloghadamsoftware wrote:
> > > > > sbenza wrote:
> > > > > > I dislike these uses of hasAnscestor. They are kind of slow.
> > > > > > But more importantly, they break with nested functions/types.
> > > > > > This particular example is not checking that the return statement 
> > > > > > is from the assignment operator, only that it is within it. For 
> > > > > > example, it would match a lambda.
> > > > > > I think this would trip the check:
> > > > > > 
> > > > > >     F& operator=(const F& o) {
> > > > > >       std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v 
> > > > > > > 0; });
> > > > > >       return *this;
> > > > > >     }
> > > > > I can change it to hasDescendant if it is faster, but it does not 
> > > > > solve the lambda problem. No solution for that comes to my mind with 
> > > > > the existing matchers. Maybe a new matcher hasDescendantStatement 
> > > > > could help which only traverses statements down the AST. Is this the 
> > > > > right way to go?
> > > > hasDescendant has the same problem has hasAnscestor.
> > > > I think the best is to write a matcher like:
> > > > 
> > > >     AST_MATCHER_P(ReturnStmt, forFunction, 
> > > > internal::Matcher<FunctionDecl>, InnerMatcher) {
> > > >       ...
> > > >     }
> > > > 
> > > > In there we can find the right FunctionDecl that encloses the return 
> > > > statement and apply the matcher.
> > > > This matcher seems like a good candidate to add to ASTMatchers.h
> > > Maybe I am wrong, but your proposal also seems a bottom-up matcher which 
> > > is slow. That is the reason I proposed a top-down matcher, e.g. 
> > > hasDescendantStatement or something like this which is top-down and only 
> > > traverses statements so it does not search in a lambda which is a 
> > > declaration.
> > hasAnscestor is slow because it is way too general. There are tons of 
> > virtual function calls, cache lookups, memory allocations, etc. And the 
> > search will not stop until it find a match or runs out of anscestors. This 
> > means it will go all the way to the translationUnitDecl before it figures 
> > out that there are no matches.
> > Every parent will be run through the matcher.
> > 
> > What I propose is a simple matcher that:
> >  1. Finds the enclosing FunctionDecl for a statement.
> >  2. Runs the matcher on it, if there is an enclosing function.
> > 
> > (1) can be done without any virtual function call and with no/minimal 
> > memory allocations.
> > (2) will be done only once on the found node.
> > 
> I did something like your proposal and it is working, but before uploading a 
> patch I have a question. There are some nodes, even statement having multiple 
> parents, probably due to template instantiations. Is it enough if we chose 
> the first parent here (thus going up only to the template itself) or should 
> we do a depth-first (better to say height-search here, since we are not 
> searching downwards in a tree but upwards in a DAG) search here and go up to 
> every parent? hasAncestor uses breadth-first search which is out of the 
> question here.
Yes, with templates you can have multiple parents.
I think you can use any of the parents, but it would be unspecified which 
FunctionDecl you get.
Maybe step (1) can return a list of FunctionDecls instead.
In this particular case you might need the particular template instantiation 
because the return type might be a dependent type.


http://reviews.llvm.org/D18265



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to