https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/206040
>From 0cc4d9314bdb518dd8b2ae972c208723a6bb1780 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Fri, 26 Jun 2026 13:48:47 +0200 Subject: [PATCH] [Clang] Do not allowed narrowing in pack indexing expression. We were reusing CCEKind::Array which turned out to be incorrect. Note that some diagnostics are emmitted multiple times as we do not have a clean way to detect the error in all cases. Fixes #205650 --- clang/docs/ReleaseNotes.rst | 1 + .../clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/include/clang/Sema/Sema.h | 1 + clang/lib/Sema/SemaTemplateVariadic.cpp | 10 ++--- clang/lib/Sema/SemaType.cpp | 15 +++---- clang/test/SemaCXX/cxx2c-pack-indexing.cpp | 42 +++++++++++++++---- 6 files changed, 50 insertions(+), 23 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a2eef75e2a719..6708015952034 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -805,6 +805,7 @@ Bug Fixes to C++ Support - Fix a problem where a substitution failure when evaluating a type requirement could directly make the program ill-formed. - Fix a problem where pack index expressions where incorrectly being regarded as equivalent. +- Correctly diagnose narrowing in pack index expressions. (#GH205650) - Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable when used inside decltype in the return type. (#GH180460) - Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ac82ba0d6773d..c958ddfa37ae9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -142,11 +142,11 @@ def err_typecheck_converted_constant_expression_indirect : Error< def err_expr_not_cce : Error< "%select{case value|enumerator value|non-type template argument|non-type parameter of template template parameter|" "array size|explicit specifier argument|noexcept specifier argument|" - "call to 'size()'|call to 'data()'}0 is not a constant expression">; + "call to 'size()'|call to 'data()'|pack index}0 is not a constant expression">; def ext_cce_narrowing : ExtWarn< "%select{case value|enumerator value|non-type template argument|non-type parameter of template template parameter|" "array size|explicit specifier argument|noexcept specifier argument|" - "call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from " + "call to 'size()'|call to 'data()'||pack index}0 %select{cannot be narrowed from " "type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure; def err_ice_not_integral : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2cf16fac83282..2d606b1551ceb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -848,6 +848,7 @@ enum class CCEKind { ///< message. StaticAssertMessageData, ///< Call to data() in a static assert ///< message. + PackIndex ///< Index of a pack indexing expression or specifier. }; /// Enums for the diagnostics of target, target_version and target_clones. diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 5b1aad3fa8470..fd1e506aaa895 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1355,20 +1355,20 @@ ExprResult Sema::BuildPackIndexingExpr(Expr *PackExpression, ArrayRef<Expr *> ExpandedExprs, bool FullySubstituted) { - std::optional<int64_t> Index; + std::optional<uint64_t> Index; if (!IndexExpr->isInstantiationDependent()) { llvm::APSInt Value(Context.getIntWidth(Context.getSizeType())); ExprResult Res = CheckConvertedConstantExpression( - IndexExpr, Context.getSizeType(), Value, CCEKind::ArrayBound); - if (!Res.isUsable()) + IndexExpr, Context.getSizeType(), Value, CCEKind::PackIndex); + if (!Res.isUsable() || !Value.isRepresentableByInt64()) return ExprError(); - Index = Value.getExtValue(); + Index = Value.getZExtValue(); IndexExpr = Res.get(); } if (Index && FullySubstituted) { - if (*Index < 0 || *Index >= int64_t(ExpandedExprs.size())) { + if (*Index < 0 || *Index >= ExpandedExprs.size()) { Diag(PackExpression->getBeginLoc(), diag::err_pack_index_out_of_bound) << *Index << PackExpression << ExpandedExprs.size(); return ExprError(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 7d9fff1051068..fb40ffde00f3d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -10117,16 +10117,17 @@ QualType Sema::BuildPackIndexingType(QualType Pattern, Expr *IndexExpr, ArrayRef<QualType> Expansions) { UnsignedOrNone Index = std::nullopt; - if (FullySubstituted && !IndexExpr->isValueDependent() && - !IndexExpr->isTypeDependent()) { - llvm::APSInt Value(Context.getIntWidth(Context.getSizeType())); + if (!IndexExpr->isInstantiationDependent()) { + llvm::APSInt Value; ExprResult Res = CheckConvertedConstantExpression( - IndexExpr, Context.getSizeType(), Value, CCEKind::ArrayBound); - if (!Res.isUsable()) + IndexExpr, Context.getSizeType(), Value, CCEKind::PackIndex); + + if (!Res.isUsable() || !Value.isRepresentableByInt64()) return QualType(); + IndexExpr = Res.get(); - int64_t V = Value.getExtValue(); - if (FullySubstituted && (V < 0 || V >= int64_t(Expansions.size()))) { + uint64_t V = Value.getZExtValue(); + if (FullySubstituted && (V < 0 || V >= Expansions.size())) { Diag(IndexExpr->getBeginLoc(), diag::err_pack_index_out_of_bound) << V << Pattern << Expansions.size(); return QualType(); diff --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp index 86d17be4f72b7..0892394955a60 100644 --- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp +++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++2c -verify %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify %s struct NotAPack; template <typename T, auto V, template<typename> typename Tp> @@ -46,12 +46,14 @@ void test() { params<1>(0); // expected-note{{here}} \ // expected-error@#error-param-size {{invalid index 1 for pack 'p' of size 1}} params<-1>(0); // expected-note{{here}} \ - // expected-error@#error-param-size {{invalid index -1 for pack 'p' of size 1}} + // expected-error@#error-param-size {{evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} test_types<-1>(); //expected-note {{in instantiation}} \ - // expected-error@#error-type-size {{invalid index -1 for pack 'T' of size 0}} - test_types<-1, int>(); //expected-note {{in instantiation}} \ - // expected-error@#error-type-size {{invalid index -1 for pack 'T' of size 1}} + // expected-error@#error-type-size {{evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} + + test_types<-1, int>(); // expected-note {{in instantiation}} \ + // expected-error@#error-type-size {{evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} + test_types<0>(); //expected-note {{in instantiation}} \ // expected-error@#error-type-size {{invalid index 0 for pack 'T' of size 0}} test_types<1, int>(); //expected-note {{in instantiation}} \ @@ -59,7 +61,7 @@ void test() { } void invalid_indexes(auto... p) { - p...[non_constant_index()]; // expected-error {{array size is not a constant expression}}\ + p...[non_constant_index()]; // expected-error {{pack index is not a constant expression}}\ // expected-note {{cannot be used in a constant expression}} const char* no_index = ""; @@ -68,9 +70,10 @@ void invalid_indexes(auto... p) { void invalid_index_types() { []<typename... T> { - T...[non_constant_index()] a; // expected-error {{array size is not a constant expression}}\ - // expected-note {{cannot be used in a constant expression}} - }(); //expected-note {{in instantiation}} + T...[non_constant_index()] a; // expected-error {{pack index is not a constant expression}}\ + // expected-note {{cannot be used in a constant expression}} \ + // expected-error {{use of undeclared identifier 'a'}} + }(); } } @@ -354,3 +357,24 @@ namespace PackIndexExprEquivalency1 { requires (Us...[0] != 0) void f() {} } // namespace PackIndexExprEquivalency1 + + +namespace GH205650 { +template <typename...T> +void foo(auto...x){ + (void)x...[(__int128)18446744073709551615U+1]; + // expected-warning@-1 3{{implicit conversion from '__int128' to '__size_t'}} + // expected-error@-2 2{{evaluates to 18446744073709551616, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} + + (void)x...[4294967296]; + //expected-error@-1 {{invalid index 4294967296 for pack 'x' of size 1}} + + using T1 = T...[(__int128)18446744073709551615U+1]; + // expected-warning@-1 3{{implicit conversion from '__int128' to '__size_t'}} + // expected-error@-2 2{{evaluates to 18446744073709551616, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} +} +int test(){ + (void)foo<int>(0); // expected-note {{in instantiation of function template specialization 'GH205650::foo<int, int>' requested here}} + +} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
