diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp')
-rw-r--r-- | clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index 3c3024d..4b495e3 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -49,7 +49,7 @@ static Matcher<Stmt> loopEndingStmt(Matcher<Stmt> Internal) { } /// Return whether `Var` was changed in `LoopStmt`. -static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var, +static bool isChanged(const Stmt *LoopStmt, const ValueDecl *Var, ASTContext *Context) { if (const auto *ForLoop = dyn_cast<ForStmt>(LoopStmt)) return (ForLoop->getInc() && @@ -64,24 +64,35 @@ static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var, return ExprMutationAnalyzer(*LoopStmt, *Context).isMutated(Var); } +static bool isVarPossiblyChanged(const Decl *Func, const Stmt *LoopStmt, + const ValueDecl *VD, ASTContext *Context) { + const VarDecl *Var = nullptr; + if (const auto *VarD = dyn_cast<VarDecl>(VD)) { + Var = VarD; + } else if (const auto *BD = dyn_cast<BindingDecl>(VD)) { + if (const auto *DD = dyn_cast<DecompositionDecl>(BD->getDecomposedDecl())) + Var = DD; + } + + if (!Var) + return false; + + if (!Var->isLocalVarDeclOrParm() || Var->getType().isVolatileQualified()) + return true; + + if (!VD->getType().getTypePtr()->isIntegerType()) + return true; + + return hasPtrOrReferenceInFunc(Func, VD) || isChanged(LoopStmt, VD, Context); + // FIXME: Track references. +} + /// Return whether `Cond` is a variable that is possibly changed in `LoopStmt`. static bool isVarThatIsPossiblyChanged(const Decl *Func, const Stmt *LoopStmt, const Stmt *Cond, ASTContext *Context) { if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) { - if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!Var->isLocalVarDeclOrParm()) - return true; - - if (Var->getType().isVolatileQualified()) - return true; - - if (!Var->getType().getTypePtr()->isIntegerType()) - return true; - - return hasPtrOrReferenceInFunc(Func, Var) || - isChanged(LoopStmt, Var, Context); - // FIXME: Track references. - } + if (const auto *VD = dyn_cast<ValueDecl>(DRE->getDecl())) + return isVarPossiblyChanged(Func, LoopStmt, VD, Context); } else if (isa<MemberExpr, CallExpr, ObjCIvarRefExpr, ObjCPropertyRefExpr, ObjCMessageExpr>(Cond)) { // FIXME: Handle MemberExpr. @@ -123,6 +134,10 @@ static std::string getCondVarNames(const Stmt *Cond) { if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) { if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) return std::string(Var->getName()); + + if (const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) { + return std::string(BD->getName()); + } } std::string Result; @@ -214,10 +229,17 @@ static bool overlap(ArrayRef<CallGraphNode *> SCC, /// returns true iff `Cond` involves at least one static local variable. static bool hasStaticLocalVariable(const Stmt *Cond) { - if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) + if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) { if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) if (VD->isStaticLocal()) return true; + + if (const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) + if (const auto *DD = dyn_cast<DecompositionDecl>(BD->getDecomposedDecl())) + if (DD->isStaticLocal()) + return true; + } + for (const Stmt *Child : Cond->children()) if (Child && hasStaticLocalVariable(Child)) return true; |