aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp54
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;