-
-
Notifications
You must be signed in to change notification settings - Fork 442
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
Partial code improvements with respect to Clang 19 warnings #1516
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,16 +49,19 @@ static inline void Meter_displayBuffer(const Meter* this, RichString* out) { | |
/* ---------- TextMeterMode ---------- */ | ||
|
||
static void TextMeterMode_draw(Meter* this, int x, int y, int w) { | ||
if (w <= 0) | ||
return; | ||
|
||
const char* caption = Meter_getCaption(this); | ||
attrset(CRT_colors[METER_TEXT]); | ||
mvaddnstr(y, x, caption, w); | ||
attrset(CRT_colors[RESET_COLOR]); | ||
|
||
int captionLen = strlen(caption); | ||
x += captionLen; | ||
w -= captionLen; | ||
if (w <= 0) | ||
size_t captionLen = strlen(caption); | ||
if ((size_t)w <= captionLen) | ||
return; | ||
x += (int)captionLen; | ||
w -= (int)captionLen; | ||
|
||
RichString_begin(out); | ||
Meter_displayBuffer(this, &out); | ||
|
@@ -301,6 +304,10 @@ static void LEDMeterMode_drawDigit(int x, int y, int n) { | |
} | ||
|
||
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) { | ||
assert(x >= 0); | ||
if (w <= 0) | ||
return; | ||
|
||
#ifdef HAVE_LIBNCURSESW | ||
if (CRT_utf8) | ||
LEDMeterMode_digits = LEDMeterMode_digitsUtf8; | ||
|
@@ -318,25 +325,25 @@ static void LEDMeterMode_draw(Meter* this, int x, int y, int w) { | |
y + 2; | ||
attrset(CRT_colors[LED_COLOR]); | ||
const char* caption = Meter_getCaption(this); | ||
mvaddstr(yText, x, caption); | ||
int xx = x + strlen(caption); | ||
mvaddnstr(yText, x, caption, w); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is a little beyond my knowledge. According to man pages, the Perhaps a good way is to test how this function call would output, would it be " /* "1234 fullwidth" */
addnstr("\uFF11\uFF12\uFF13\uFF14 fullwidth", 2); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I wish is a function that does an inverse of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately that is easier said than actual done, but based on the fact that NB: There's actually an issue that might benefit from this functionality in #462 IIRC. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
size_t xx = (size_t)x + strlen(caption); | ||
int len = RichString_sizeVal(out); | ||
for (int i = 0; i < len; i++) { | ||
for (size_t i = 0; i < (size_t)len; i++) { | ||
int c = RichString_getCharVal(out, i); | ||
if (c >= '0' && c <= '9') { | ||
if (xx - x + 4 > w) | ||
if (xx + 4 > (unsigned int)x + (unsigned int)w) | ||
break; | ||
|
||
LEDMeterMode_drawDigit(xx, y, c - '0'); | ||
LEDMeterMode_drawDigit((int)xx, y, c - '0'); | ||
xx += 4; | ||
} else { | ||
if (xx - x + 1 > w) | ||
if (xx + 1 > (unsigned int)x + (unsigned int)w) | ||
break; | ||
#ifdef HAVE_LIBNCURSESW | ||
const cchar_t wc = { .chars = { c, '\0' }, .attr = 0 }; /* use LED_COLOR from attrset() */ | ||
mvadd_wch(yText, xx, &wc); | ||
mvadd_wch(yText, (int)xx, &wc); | ||
#else | ||
mvaddch(yText, xx, c); | ||
mvaddch(yText, (int)xx, c); | ||
#endif | ||
xx += 1; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -428,23 +428,23 @@ void Row_printNanoseconds(RichString* str, unsigned long long totalNanoseconds, | |
} | ||
|
||
unsigned long long totalSeconds = totalMicroseconds / 1000000; | ||
unsigned long microseconds = totalMicroseconds % 1000000; | ||
uint32_t microseconds = totalMicroseconds % 1000000; | ||
if (totalSeconds < 60) { | ||
int width = 5; | ||
unsigned long fraction = microseconds / 10; | ||
uint32_t fraction = microseconds / 10; | ||
if (totalSeconds >= 10) { | ||
width--; | ||
fraction /= 10; | ||
} | ||
len = xSnprintf(buffer, sizeof(buffer), "%u.%0*lus ", (unsigned int)totalSeconds, width, fraction); | ||
len = xSnprintf(buffer, sizeof(buffer), "%u.%0*lus ", (unsigned int)totalSeconds, width, (unsigned long)fraction); | ||
RichString_appendnAscii(str, baseColor, buffer, len); | ||
return; | ||
} | ||
|
||
if (totalSeconds < 600) { | ||
unsigned int minutes = totalSeconds / 60; | ||
unsigned int seconds = totalSeconds % 60; | ||
unsigned int milliseconds = microseconds / 1000; | ||
unsigned int minutes = (unsigned int)totalSeconds / 60; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the cast here happen after the division? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not necessary because of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not necessarily, as Won't happen in this case based on the previous check, but the correctness should take priority here. |
||
unsigned int seconds = (unsigned int)totalSeconds % 60; | ||
unsigned int milliseconds = (unsigned int)(microseconds / 1000); | ||
len = xSnprintf(buffer, sizeof(buffer), "%u:%02u.%03u ", minutes, seconds, milliseconds); | ||
RichString_appendnAscii(str, baseColor, buffer, len); | ||
return; | ||
|
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.
I think this one is a step backwards. Stick with
size_t
.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.
Can't understand what you mean. What's the reason of keeping the
size_t
?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.
Two-fold:
unsigned int
looks kinda unwieldy IMHO.%zu
is much more portable thanuint32_t
which would require you to use%"PRIu32"
instead of just%u
.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.
@BenBE Well, I have a different view on this:
int
type would not needsize_t
(that is,unsigned long
) for storing.int
types are slightly cheaper than comparinglong
orsize_t
(in terms of code size). Whenint
types can suffice, usinglong
would make the code one-byte-per-operation larger.COLS
), and the latter is bound tosigned int
type already.PRIu32
here. It'sunsigned int
, notuint32_t
.This case is slightly different from string lengths. My view is string lengths in
size_t
can serve as a defence in depth, where the user is possible to feed a 4 GiB large string in a config file. But if the object size would be bound by any other factor, thensize_t
might be a waste.(By the way, I did read this article from EWONTFIX when I write my changes.)
I hope htop developers can reconsider.
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.
Personal opinion following:
Nonetheless
size_t
is less about the number of entities itself, but that you are counting entities.Otherwise you could argue that "this hashtable implementation only needs
short
for its size, because I never store more than 65535 elements in it".I know, that example is hyperbole, but follows that same logic. When I ask for
size_t
it's really little about "how many", but the "what" (AKA semantics).That might be true for x86_64, but that's not the only platform we need to support. There's at least ARM, ARM64, MIPS, and probably several others, where htop is runing. Unless performance really IS a bottleneck for these functions (AFAICS it's not), priority should be on correctness, not code size or performance.
See arguments from the article you linked.
That limit is implied by the current interface from ncurses, but a future version could just switch to size_t for its column and row counts (potentially breaking BC at that point); there are good reasons like huge screens where terminals COULD have that many columns/rows.
k, ACK on that. But that's only a minor note regarding the chosen type signature.
Allocations are typically backed by 4 KiB pages at minimum, with the usual memory manager implementation pre-allocating some memory to handle sudden spikes. Thus unless the savings are major or we have massive amounts of objects (where storing UTF-8 instead of UTF-16 saves several hundreds of megabytes (like with some browsers) there's usually little need to save every last byte. Furthermore, by storing smaller data types you sometimes may make the alignment of the data worse, thus actually reducing performance.
From my experience I can tell, that I've seen real-life cases of where
uint16_t
vs.uint32_t
was actually harmful due to alignment and memory access patterns. For 32 bit values on a 64 bit architecture, similar considerations apply.FWIW, I personally side with the author.
@cgzones @fasterit @ginggs @natoscott : Your opinion on this matter of
size_t
vsunsigned int
?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.
I'm happy to stick with size_t here.
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.
Seconded
/DLange
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.
@BenBE @natoscott @fasterit
This commit was to fix the implicit downcast warnings from
HeaderLayout_getColumns()
by Clang 19 (the messages was: "implicit conversion loses integer precision: 'size_t' (aka 'unsigned long') to 'unsigned int' [-Wshorten-64-to-32]
").HeaderLayout_getColumns()
was an inline function that returns asize_t
that, in certain caller codes, has to downcast toint
because terminal column variables are inint
type to followcurses
API.With this background, I would like some clarifications on which decision to make:
(A) Keep
HeaderLayout_getColumns()
return value insize_t
. Usesize_t
for local variables that hold the return values ofHeaderLayout_getColumns()
, and add explicit downcasts when needed (e.g. when used in the context of terminal column widths).(B) Let
HeaderLayout_getColumns()
return anunsigned int
. Keep usingint
type for places like terminal columns. But when using in array iterators (like in this example code you guys are commented on), upcast tosize_t
.(C) Let
HeaderLayout_getColumns()
return anunsigned int
. Also useunsigned int
for array iterators that would never cross the bound ofHeaderLayout_getColumns()
. This is my original proposal.EDIT: Just a reminder that the (A) option is the least preferred to me as the downcasts can hide potential errors when the original "getColumns" values are out of bounds. Although assertions may be added to ensure the numbers are in bound, they still look like an overkill solution to me (making the problem more complicated than necessary).
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.
A.