-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove warnings from -Wchar-subscripts for known positive constants #69061
Conversation
@llvm/pr-subscribers-clang Author: None (wheatman) ChangesThis is to address #18763 it removes warnings from using a signed char as an array bound if the char is a known positives constant. This goes one step farther than gcc does. For example given the following code 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'.
This pull request in incomplete in that this is my first change submitted and I don't know how to add tests, any guidance on what sort of tests to add, and where to find documentation on the testing infrastructure Full diff: https://github.com/llvm/llvm-project/pull/69061.diff 1 Files Affected:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index aa30a3a03887558..dd9ba5cecaf2404 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6018,9 +6018,15 @@ 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().isNonNegative())) {
+ 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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to make sure you tests have newlines at the end
void t6(void) { | ||
int array[1] = { 0 }; | ||
signed char subscript = 0; | ||
int val = array[subscript]; // no warning for explicit signed char |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we exclude the signed char
case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is an interesting questions, the behavior for that was not changed.
The current behavior for explicitly signed or unsigned chars is to have no warning, only unspecified chars have warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We rule out explicitly signed or explicitly unsigned char
type because of int8_t
and uint8_t
because those are pretty reasonable to use as array indexes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this! The changes should come with a release note in clang/docs/ReleaseNotes.rst
so users know about the change in behavior.
clang/lib/Sema/SemaExpr.cpp
Outdated
std::optional<llvm::APSInt> IntegerContantExpr = | ||
IndexExpr->getIntegerConstantExpr(getASTContext()); | ||
if (!(IntegerContantExpr.has_value() && | ||
IntegerContantExpr.value().isNonNegative())) { | ||
Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::optional<llvm::APSInt> IntegerContantExpr = | |
IndexExpr->getIntegerConstantExpr(getASTContext()); | |
if (!(IntegerContantExpr.has_value() && | |
IntegerContantExpr.value().isNonNegative())) { | |
Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange(); | |
} | |
std::optional<llvm::APSInt> IntegerContantExpr = | |
IndexExpr->getIntegerConstantExpr(getASTContext()); | |
if (!IntegerContantExpr.has_value() || | |
IntegerContantExpr.value().isNegative()) | |
Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange(); |
This performs extra work for each array subscript in the TU, but because it's limited to only array subscripts with a character type, I don't think the compile-time performance hit should be too bad, so this seems reasonable to me.
void t6(void) { | ||
int array[1] = { 0 }; | ||
signed char subscript = 0; | ||
int val = array[subscript]; // no warning for explicit signed char |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We rule out explicitly signed or explicitly unsigned char
type because of int8_t
and uint8_t
because those are pretty reasonable to use as array indexes.
Thanks you for the comments. I made the updates and added the note in |
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you for the fix!
Thank you for the review. |
@AaronBallman if there are no more comments, could you please merge it in |
@wheatman can you rebase again? I want to make sure CI passes before merging (and the bots were broken earlier today). Thanks. |
@cor3ntin done, thanks for taking a look |
Thanks for your first contribution. Maybe the first of many :D |
This is to address #18763
it removes warnings from using a signed char as an array bound if the char is a known positives constant.
This goes one step farther than gcc does.
For example given the following code
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'.
This pull request is my first change and I would appreciate any comments or suggestions.