[clang] Remove warnings from -Wchar-subscripts for known positive constants (PR #69061)

via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 2 12:46:00 PDT 2023


https://github.com/wheatman updated https://github.com/llvm/llvm-project/pull/69061

>From b46d376e803bae29231e313a623f508e22e6c9d6 Mon Sep 17 00:00:00 2001
From: Brian Wheatman <bwheatman at gmail.com>
Date: Sat, 14 Oct 2023 12:02:19 -0400
Subject: [PATCH] Remove warnings from -Wchar-subscripts for known positive
 constants

---
 clang/docs/ReleaseNotes.rst              |   2 +
 clang/lib/Sema/SemaExpr.cpp              |  11 ++-
 clang/test/Sema/warn-char-subscripts.c   |  25 ++++++
 clang/test/Sema/warn-char-subscripts.cpp | 103 +++++++++++++++++++++++
 4 files changed, 138 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Sema/warn-char-subscripts.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index be7c8bf247f7af5..4e3d7108f0408cc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -393,6 +393,8 @@ Bug Fixes in This Version
   operator in C. No longer issuing a confusing diagnostic along the lines of
   "incompatible operand types ('foo' and 'foo')" with extensions such as matrix
   types. Fixes (`#69008 <https://github.com/llvm/llvm-project/issues/69008>`_)
+- Clang's ``-Wchar-subscripts`` no longer warns on chars whose values are known non-negative constants.
+  Fixes (`#18763 <https://github.com/llvm/llvm-project/issues/18763>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index aa30a3a03887558..5c84c8ff146a3f6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6018,9 +6018,14 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
                      << IndexExpr->getSourceRange());
 
   if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
-       IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
-         && !IndexExpr->isTypeDependent())
-    Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange();
+       IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) &&
+      !IndexExpr->isTypeDependent()) {
+    std::optional<llvm::APSInt> IntegerContantExpr =
+        IndexExpr->getIntegerConstantExpr(getASTContext());
+    if (!IntegerContantExpr.has_value() ||
+        IntegerContantExpr.value().isNegative())
+      Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange();
+  }
 
   // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
   // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
diff --git a/clang/test/Sema/warn-char-subscripts.c b/clang/test/Sema/warn-char-subscripts.c
index 2e72d90fa612aed..0a012f68feae07f 100644
--- a/clang/test/Sema/warn-char-subscripts.c
+++ b/clang/test/Sema/warn-char-subscripts.c
@@ -62,3 +62,28 @@ void t10(void) {
   UnsignedCharTy subscript = 0;
   int val = array[subscript]; // no warning for unsigned char
 }
+
+void t11(void) {
+  int array[256] = { 0 };
+  int val = array['a']; // no warning for char with known positive value
+}
+
+void t12(void) {
+  int array[256] = { 0 };
+  char b = 'a';
+  int val = array[b]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t13(void) {
+  int array[256] = { 0 };
+  const char b = 'a';
+  int val = array[b]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t14(void) {
+  int array[256] = { 0 }; // expected-note {{array 'array' declared here}}
+  const char b = -1;
+  // expected-warning at +2 {{array subscript is of type 'char'}}
+  // expected-warning at +1 {{array index -1 is before the beginning of the array}}
+  int val = array[b];
+}
diff --git a/clang/test/Sema/warn-char-subscripts.cpp b/clang/test/Sema/warn-char-subscripts.cpp
new file mode 100644
index 000000000000000..929fb372c5173fd
--- /dev/null
+++ b/clang/test/Sema/warn-char-subscripts.cpp
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -Wchar-subscripts -fsyntax-only -verify %s
+
+void t1(void) {
+  int array[1] = { 0 };
+  char subscript = 0;
+  int val = array[subscript]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t2(void) {
+  int array[1] = { 0 };
+  char subscript = 0;
+  int val = subscript[array]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t3(void) {
+  int *array = 0;
+  char subscript = 0;
+  int val = array[subscript]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t4(void) {
+  int *array = 0;
+  char subscript = 0;
+  int val = subscript[array]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+char returnsChar(void);
+void t5(void) {
+  int *array = 0;
+  int val = array[returnsChar()]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t6(void) {
+  int array[1] = { 0 };
+  signed char subscript = 0;
+  int val = array[subscript]; // no warning for explicit signed char
+}
+
+void t7(void) {
+  int array[1] = { 0 };
+  unsigned char subscript = 0;
+  int val = array[subscript]; // no warning for unsigned char
+}
+
+typedef char CharTy;
+void t8(void) {
+  int array[1] = { 0 };
+  CharTy subscript = 0;
+  int val = array[subscript]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+typedef signed char SignedCharTy;
+void t9(void) {
+  int array[1] = { 0 };
+  SignedCharTy subscript = 0;
+  int val = array[subscript]; // no warning for explicit signed char
+}
+
+typedef unsigned char UnsignedCharTy;
+void t10(void) {
+  int array[1] = { 0 };
+  UnsignedCharTy subscript = 0;
+  int val = array[subscript]; // no warning for unsigned char
+}
+
+void t11(void) {
+  int array[256] = { 0 };
+  int val = array['a']; // no warning for char with known positive value
+}
+
+void t12(void) {
+  int array[256] = { 0 };
+  char b = 'a';
+  int val = array[b]; // expected-warning{{array subscript is of type 'char'}}
+}
+
+void t13(void) {
+  int array[256] = { 0 };
+  const char b = 'a';
+  int val = array[b]; // no warning for char with known positive value
+}
+
+void t14(void) {
+  int array[256] = { 0 };
+  constexpr char b = 'a';
+  int val = array[b]; // no warning for char with known positive value
+}
+
+void t15(void) {
+  int array[256] = { 0 }; // expected-note {{array 'array' declared here}}
+  const char b = -1;
+  // expected-warning at +2 {{array subscript is of type 'char'}}
+  // expected-warning at +1 {{array index -1 is before the beginning of the array}}
+  int val = array[b];
+}
+
+void t16(void) {
+  int array[256] = { 0 }; // expected-note {{array 'array' declared here}}
+  constexpr char b = -1;
+  // expected-warning at +2 {{array subscript is of type 'char'}}
+  // expected-warning at +1 {{array index -1 is before the beginning of the array}}
+  int val = array[b];
+}



More information about the cfe-commits mailing list