diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp @@ -61,6 +61,12 @@ const auto *Matched = Result.Nodes.getNodeAs("expr"); const auto *IndexExpr = Result.Nodes.getNodeAs("index"); + // This expression can only appear inside ArrayInitLoopExpr, which + // is always implicitly generated. ArrayInitIndexExpr is not a + // constant, but we shouldn't report a warning for it. + if (isa(IndexExpr)) + return; + if (IndexExpr->isValueDependent()) return; // We check in the specialization. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index.cpp @@ -75,13 +75,34 @@ s[i] = 3; // OK, custom operator } +namespace ArrayInitIndexExpr { struct A { // The compiler-generated copy constructor uses an ArraySubscriptExpr. Don't warn. int x[3]; }; -void use_A() { +void implicitCopyMoveCtor() { // Force the compiler to generate a copy constructor. A a; A a2(a); + + // Force the compiler to generate a move constructor. + A a3 = (A&&) a; +} + +void lambdaCapture() { + int arr[3]; + + // Capturing an array by value uses an ArraySubscriptExpr. Don't warn. + [arr](){}; +} + +#if __cplusplus >= 201703L +void structuredBindings() { + int arr[3]; + + // Creating structured bindings by value uses an ArraySubscriptExpr. Don't warn. + auto [a,b,c] = arr; } +#endif +} // namespace ArrayInitIndexExpr