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 <benicsbal...@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; + } + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits