[cfe-dev] Using Libtooling to find for loop break statements

Phil King via cfe-dev cfe-dev at lists.llvm.org
Thu Aug 13 01:24:01 PDT 2020


Thanks, I’ll have a look at that. I was trying to use the marchers and hadn’t thought of other approaches!

Sent from my iPhone

> On 12 Aug 2020, at 20:36, David Rector <davrecthreads at gmail.com> wrote:
> 
> 
> 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/20200813/c1d66bb4/attachment-0001.html>


More information about the cfe-dev mailing list