[clang] 8f68022 - [clang][analyzer] Fix crash in loop unrolling (#82089)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 14 01:16:44 PDT 2024
Author: huang-me
Date: 2024-03-14T09:16:40+01:00
New Revision: 8f68022f8e6e54d1aeae4ed301f5a015963089b7
URL: https://github.com/llvm/llvm-project/commit/8f68022f8e6e54d1aeae4ed301f5a015963089b7
DIFF: https://github.com/llvm/llvm-project/commit/8f68022f8e6e54d1aeae4ed301f5a015963089b7.diff
LOG: [clang][analyzer] Fix crash in loop unrolling (#82089)
StaticAnalyzer didn't check if the variable is declared in
`CompoundStmt` under `SwitchStmt`, which make static analyzer reach root
without finding the declaration.
Fixes #68819
---------
Co-authored-by: Balazs Benics <benicsbalazs at gmail.com>
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
clang/test/Analysis/loop-unrolling.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index abeb5a8b77bf1f..71c1edc8f67b17 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -492,6 +492,10 @@ libclang
Static Analyzer
---------------
+- Fixed crashing on loops if the loop variable was declared in switch blocks
+ but not under any case blocks if ``unroll-loops=true`` analyzer config is
+ set. (#GH68819)
+
New features
^^^^^^^^^^^^
diff --git a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
index a80352816be613..7042f1aeb803fc 100644
--- a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
+++ b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
@@ -190,6 +190,17 @@ static bool isCapturedByReference(ExplodedNode *N, const DeclRefExpr *DR) {
return FD->getType()->isReferenceType();
}
+static bool isFoundInStmt(const Stmt *S, const VarDecl *VD) {
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+ for (const Decl *D : DS->decls()) {
+ // Once we reach the declaration of the VD we can return.
+ if (D->getCanonicalDecl() == VD)
+ return true;
+ }
+ }
+ return false;
+}
+
// A loop counter is considered escaped if:
// case 1: It is a global variable.
// case 2: It is a reference parameter or a reference capture.
@@ -219,13 +230,19 @@ static bool isPossiblyEscaped(ExplodedNode *N, const DeclRefExpr *DR) {
continue;
}
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
- for (const Decl *D : DS->decls()) {
- // Once we reach the declaration of the VD we can return.
- if (D->getCanonicalDecl() == VD)
- return false;
+ if (isFoundInStmt(S, VD)) {
+ return false;
+ }
+
+ if (const auto *SS = dyn_cast<SwitchStmt>(S)) {
+ if (const auto *CST = dyn_cast<CompoundStmt>(SS->getBody())) {
+ for (const Stmt *CB : CST->body()) {
+ if (isFoundInStmt(CB, VD))
+ return false;
+ }
}
}
+
// Check the usage of the pass-by-ref function calls and adress-of operator
// on VD and reference initialized by VD.
ASTContext &ASTCtx =
diff --git a/clang/test/Analysis/loop-unrolling.cpp b/clang/test/Analysis/loop-unrolling.cpp
index fc1fb06cdc014e..66a828abfb5133 100644
--- a/clang/test/Analysis/loop-unrolling.cpp
+++ b/clang/test/Analysis/loop-unrolling.cpp
@@ -547,3 +547,15 @@ void capture_implicitly_by_ref_as_loop_counter() {
}
};
}
+
+
+void test_escaping_on_var_before_switch_case_no_crash(int c) {
+ // https://github.com/llvm/llvm-project/issues/68819
+ switch (c) {
+ int i; // no-crash: The declaration of `i` is found here.
+ case 0: {
+ for (i = 0; i < 16; i++) {}
+ break;
+ }
+ }
+}
More information about the cfe-commits
mailing list