[clang] 0031efe - Remove warnings from -Wchar-subscripts for known positive constants (#69061)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 3 21:49:41 PST 2023
Author: wheatman
Date: 2023-12-04T06:49:37+01:00
New Revision: 0031efe6be19735402656a76b64a173d17f1f935
URL: https://github.com/llvm/llvm-project/commit/0031efe6be19735402656a76b64a173d17f1f935
DIFF: https://github.com/llvm/llvm-project/commit/0031efe6be19735402656a76b64a173d17f1f935.diff
LOG: Remove warnings from -Wchar-subscripts for known positive constants (#69061)
Fixes #18763
Remove warnings when using a signed char as an array bound if the char is a known positive constant.
This goes one step farther than gcc does.
For example given the following code
```c++
char upper[300];
int main() {
upper['a'] = 'A';
char b = 'a';
upper[b] = 'A';
const char c = 'a';
upper[c] = 'A';
constexpr char d = 'a';
upper[d] = 'A';
char e = -1;
upper[e] = 'A';
const char f = -1;
upper[f] = 'A';
constexpr char g = -1;
upper[g] = 'A';
return 1;
}
```
clang currently gives warnings for all cases, while gcc gives warnings
for all cases except for 'a' (https://godbolt.org/z/5ahjETTv3)
With the change there is no longer any warning for 'a', 'c', or 'd'.
Added:
clang/test/Sema/warn-char-subscripts.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaExpr.cpp
clang/test/Sema/warn-char-subscripts.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c7a948fd3fae5..683d0026bb345 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -651,6 +651,8 @@ Bug Fixes in This Version
- Fixed false positive error emitted by clang when performing qualified name
lookup and the current class instantiation has dependent bases.
Fixes (`#13826 <https://github.com/llvm/llvm-project/issues/13826>`_)
+- 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 d1b2b8084b8ff..d629be083d8c3 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6053,9 +6053,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 2e72d90fa612a..0a012f68feae0 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 0000000000000..929fb372c5173
--- /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