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

Reply via email to