https://github.com/zeyi2 created https://github.com/llvm/llvm-project/pull/203865
None >From 6921b5d464bbbbc0ae9950746076bcb2f35eee93 Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Mon, 15 Jun 2026 17:50:58 +0800 Subject: [PATCH] [clang-tidy] Fix altera-unroll-loops crash on multi-decl for init --- .../clang-tidy/altera/UnrollLoopsCheck.cpp | 6 ++- clang-tools-extra/docs/ReleaseNotes.rst | 5 ++ .../checkers/altera/unroll-loops.cpp | 53 +++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp b/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp index 15fa75f19ef28..eb41acaf4650a 100644 --- a/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp +++ b/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp @@ -124,7 +124,8 @@ bool UnrollLoopsCheck::hasKnownBounds(const Stmt *Statement, if (!Initializer || !Conditional || !Increment) return false; // If the loop variable value isn't known, loop bounds are unknown. - if (const auto *InitDeclStatement = dyn_cast<DeclStmt>(Initializer)) { + if (const auto *InitDeclStatement = dyn_cast<DeclStmt>(Initializer); + InitDeclStatement && InitDeclStatement->isSingleDecl()) { if (const auto *VariableDecl = dyn_cast<VarDecl>(InitDeclStatement->getSingleDecl())) { const APValue *Evaluation = VariableDecl->evaluateValue(); @@ -173,7 +174,8 @@ bool UnrollLoopsCheck::hasLargeNumIterations(const Stmt *Statement, const Expr *Increment = ForLoop->getInc(); int InitValue = 0; // If the loop variable value isn't known, we can't know the loop bounds. - if (const auto *InitDeclStatement = dyn_cast<DeclStmt>(Initializer)) { + if (const auto *InitDeclStatement = dyn_cast<DeclStmt>(Initializer); + InitDeclStatement && InitDeclStatement->isSingleDecl()) { if (const auto *VariableDecl = dyn_cast<VarDecl>(InitDeclStatement->getSingleDecl())) { APValue *Evaluation = VariableDecl->evaluateValue(); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 9703bb8f17208..5b1c3fb169fa6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -343,6 +343,11 @@ Changes in existing checks positives when ordinary variable or field assignments are used in loop conditions and note locations for inferred ID-dependent fields. +- Improved :doc:`altera-unroll-loops + <clang-tidy/checks/altera/unroll-loops>` check by fixing a crash when + analyzing a ``for`` loop whose initialization statement declares multiple + variables. + - Improved :doc:`bugprone-argument-comment <clang-tidy/checks/bugprone/argument-comment>`: diff --git a/clang-tools-extra/test/clang-tidy/checkers/altera/unroll-loops.cpp b/clang-tools-extra/test/clang-tidy/checkers/altera/unroll-loops.cpp index c06cec794e8eb..05a9e1b21c011 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/altera/unroll-loops.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/altera/unroll-loops.cpp @@ -125,6 +125,30 @@ void for_loops(int *A, int size) { A[i]++; } +#pragma unroll + for (int i = 0, j = 0; i < 50; ++i) { + A[i] += j; + } + +#pragma unroll + for (int i = 0, j = 0; i < 50; ++i, ++j) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive + // FIXME: This is a false positive. + A[i] += j; + } + +#pragma unroll + for (int j = size, i = 0; i < 50; ++i) { + A[i] += j; + } + +#pragma unroll + for (int j = 0, i = 100; i < 150; ++i) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive + // FIXME: This is a false positive. + A[i] += j; + } + // Loop with unknown size should be partially unrolled. #pragma unroll for (int i = 0; i < size; ++i) { @@ -132,6 +156,18 @@ void for_loops(int *A, int size) { A[i]++; } +#pragma unroll + for (int i = 0, j = 0; i < size; ++i) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive + A[i] += j; + } + +#pragma unroll + for (int j = 0, i = size; i < 50; ++i) { + // FIXME: This is a false negative. + A[i] += j; + } + #pragma unroll for (;;) { // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops] @@ -181,6 +217,11 @@ void for_loops(int *A, int size) { A[i]++; } +#pragma unroll 5 + for (int i = 0, j = 0; i < size; ++i) { + A[i] += j; + } + // Loop with large size should be partially unrolled. #pragma unroll for (int i = 0; i < 51; ++i) { @@ -188,6 +229,18 @@ void for_loops(int *A, int size) { A[i]++; } +#pragma unroll + for (int i = 0, j = 0; i < 51; ++i) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive + A[i] += j; + } + +#pragma unroll + for (int j = 100, i = 0; i < 51; ++i) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive + A[i] += j; + } + // Loop with large size correctly unrolled. #pragma unroll 5 for (int i = 0; i < 51; ++i) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
