llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Corentin Jabot (cor3ntin)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/206040.diff


6 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+1) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-2) 
- (modified) clang/include/clang/Sema/Sema.h (+1) 
- (modified) clang/lib/Sema/SemaTemplateVariadic.cpp (+5-5) 
- (modified) clang/lib/Sema/SemaType.cpp (+8-7) 
- (modified) clang/test/SemaCXX/cxx2c-pack-indexing.cpp (+32-8) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d1303d4c98507..e6d3446e4a96b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -788,6 +788,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 7e20630708312..38e06aeded082 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 b8d760e7e0975..d13733cd22435 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..c01e5091d63e0 100644
--- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
+++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
@@ -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}}
+
+}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/206040
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to