[clang] 9b132a2 - [Clang] Do not allowed narrowing in pack indexing expression. (#206040)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 29 08:54:48 PDT 2026
Author: Corentin Jabot
Date: 2026-06-29T15:54:42Z
New Revision: 9b132a2ff80dac4bc8e78b242bebb97551c292c7
URL: https://github.com/llvm/llvm-project/commit/9b132a2ff80dac4bc8e78b242bebb97551c292c7
DIFF: https://github.com/llvm/llvm-project/commit/9b132a2ff80dac4bc8e78b242bebb97551c292c7.diff
LOG: [Clang] Do not allowed narrowing in pack indexing expression. (#206040)
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
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaTemplateVariadic.cpp
clang/lib/Sema/SemaType.cpp
clang/test/SemaCXX/cxx2c-pack-indexing.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 76e2170a7352a..a4ffb3ff74e45 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -806,6 +806,7 @@ Bug Fixes to C++ Support
could directly make the program ill-formed.
- Typo correction now corrects the name qualifier for invalid template names.
- 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..896334648d341 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -139,14 +139,15 @@ def err_typecheck_converted_constant_expression_disallowed : Error<
def err_typecheck_converted_constant_expression_indirect : Error<
"conversion from %0 to %1 in converted constant expression would "
"bind reference to a temporary">;
-def err_expr_not_cce : Error<
+
+def select_cce_kind : TextSubstitution<
"%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">;
+def err_expr_not_cce : Error<
+ "%sub{select_cce_kind}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 "
+ "%sub{select_cce_kind}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 at -1 3{{implicit conversion from '__int128' to '__size_t'}}
+ // expected-error at -2 2{{evaluates to 18446744073709551616, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}}
+
+ (void)x...[4294967296];
+ //expected-error at -1 {{invalid index 4294967296 for pack 'x' of size 1}}
+
+ using T1 = T...[(__int128)18446744073709551615U+1];
+ // expected-warning at -1 3{{implicit conversion from '__int128' to '__size_t'}}
+ // expected-error at -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}}
+
+}
+}
More information about the cfe-commits
mailing list