[cfe-dev] Using Libtooling to find for loop break statements
David Rector via cfe-dev
cfe-dev at lists.llvm.org
Wed Aug 12 12:36:53 PDT 2020
Here is how a RecursiveASTVisitor could do it (not tested):
```
#include "clang/AST/RecursiveASTVisitor.h"
/// Usage:
/// std::map<ForStmt *, std::vector<BreakStmt *>> for2breaks;
/// ForBreakMapper(for2breaks).TraverseDecl(
/// /*Context.getTranslationUnitDecl(), some function decl, etc…);
///
class ForBreakMapper : public RecursiveASTVisitor<ForBreakMapper> {
using BaseType = RecursiveASTVisitor<ForBreakMapper>;
ForStmt *ActiveFor = nullptr;
std::map<ForStmt *, std::vector<BreakStmt *>> &forbreaks_mapref;
public:
ForBreakMapper(decltype(for2breaks_mapref) forbreaks_mapref)
: for2breaks_mapref(for2breaks_mapref) {}
// Need this override to disable "data recursion" and thus
// guarantee VisitBreakStmt happens within its parent's
// Traverse*Stmt call:
bool TraverseStmt(Stmt *S) { return BaseType::TraverseStmt(S); }
bool TraverseForStmt(ForStmt *S) {
SaveAndRestore<ForStmt *> RAII(ActiveFor, S);
return BaseType::TraverseForStmt(S);
}
// Nullify ActiveFor for SwitchStmts (any others?)
bool TraverseSwitchStmt(SwitchStmt *S) {
SaveAndRestore<ForStmt *> RAII(ActiveFor, nullptr);
return BaseType::TraverseSwitchStmt(S);
}
bool VisitBreakStmt(BreakStmt *S) {
if (ActiveFor && S)
forbreaks_mapref[ActiveFor].push_back(S);
return true;
}
};
```
I’m a big fan of this general technique, i.e. using llvm::SaveAndRestore in Traverse* overrides to keep track of traversal state data, which you then use in your Visit* overrides.
You do need that seemingly-trivial TraverseStmt override whenever you do this sort of thing with Stmts though, otherwise the Visit* statements will not be called within the ancestor’s Traverse* statements (due to the "data recursion" queueing performed by default in the base RecursiveASTVisitor.)
Good luck,
- Dave
> On Aug 12, 2020, at 11:16 AM, Phil King via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>
> Hi,
>
> I am trying to find all of the break statements that can cause termination of for loops. The following gives me all the break statements under a “for” node, but I cannot see how to filter out those that cannot terminate the current loop (e.g., they may terminate a case statement, be enclosed within a nested loop, etc.):
>
> forStmt( forEachDescentant( breakStmt().bind( “myBreaks” ) ) ).bind( “myFors” )
>
> How should I go about filtering out the unwanted breaks?
>
> Sent from my iPhone
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200812/eff6ac20/attachment.html>
More information about the cfe-dev
mailing list