mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Fix -W parameter parsing
This commit is contained in:
@@ -28,7 +28,7 @@ struct WarningState {
|
|||||||
void update(WarningState other);
|
void update(WarningState other);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::pair<WarningState, std::optional<uint8_t>> getInitialWarningState(std::string &flag);
|
std::pair<WarningState, std::optional<uint32_t>> getInitialWarningState(std::string &flag);
|
||||||
|
|
||||||
template<typename L>
|
template<typename L>
|
||||||
struct WarningFlag {
|
struct WarningFlag {
|
||||||
@@ -150,20 +150,17 @@ std::string Diagnostics<L, W>::processWarningFlag(char const *flag) {
|
|||||||
if (!param.has_value() || *param == 0) {
|
if (!param.has_value() || *param == 0) {
|
||||||
param = paramWarning.defaultLevel;
|
param = paramWarning.defaultLevel;
|
||||||
} else if (*param > maxParam) {
|
} else if (*param > maxParam) {
|
||||||
if (*param != 255) { // Don't warn if already capped
|
warnx(
|
||||||
warnx(
|
"Invalid warning flag parameter \"%s=%" PRIu32 "\"; capping at maximum %" PRIu8,
|
||||||
"Invalid parameter %" PRIu8
|
rootFlag.c_str(),
|
||||||
" for warning flag \"%s\"; capping at maximum %" PRIu8,
|
*param,
|
||||||
*param,
|
maxParam
|
||||||
rootFlag.c_str(),
|
);
|
||||||
maxParam
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*param = maxParam;
|
*param = maxParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the first <param> to enabled/error, and disable the rest
|
// Set the first <param> to enabled/error, and disable the rest
|
||||||
for (uint8_t ofs = 0; ofs < maxParam; ofs++) {
|
for (uint32_t ofs = 0; ofs < maxParam; ofs++) {
|
||||||
if (WarningState &warning = state.flagStates[baseID + ofs]; ofs < *param) {
|
if (WarningState &warning = state.flagStates[baseID + ofs]; ofs < *param) {
|
||||||
warning.update(flagState);
|
warning.update(flagState);
|
||||||
} else {
|
} else {
|
||||||
@@ -174,7 +171,7 @@ std::string Diagnostics<L, W>::processWarningFlag(char const *flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (param.has_value()) {
|
if (param.has_value()) {
|
||||||
warnx("Unknown warning flag parameter \"%s\"", rootFlag.c_str());
|
warnx("Unknown warning flag parameter \"%s=%" PRIu32 "\"", rootFlag.c_str(), *param);
|
||||||
return rootFlag;
|
return rootFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ void WarningState::update(WarningState other) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<WarningState, std::optional<uint8_t>> getInitialWarningState(std::string &flag) {
|
std::pair<WarningState, std::optional<uint32_t>> getInitialWarningState(std::string &flag) {
|
||||||
// Check for prefixes that affect what the flag does
|
// Check for prefixes that affect what the flag does
|
||||||
WarningState state;
|
WarningState state;
|
||||||
if (flag.starts_with("error=")) {
|
if (flag.starts_with("error=")) {
|
||||||
@@ -51,28 +51,22 @@ std::pair<WarningState, std::optional<uint8_t>> getInitialWarningState(std::stri
|
|||||||
// Is the rest of the string a decimal number?
|
// Is the rest of the string a decimal number?
|
||||||
// We want to avoid `strtoul`'s whitespace and sign, so we parse manually
|
// We want to avoid `strtoul`'s whitespace and sign, so we parse manually
|
||||||
char const *ptr = flag.c_str() + equals + 1;
|
char const *ptr = flag.c_str() + equals + 1;
|
||||||
uint8_t param = 0;
|
uint32_t param = 0;
|
||||||
bool warned = false;
|
bool overflowed = false;
|
||||||
|
|
||||||
// The `if`'s condition above ensures that this will run at least once
|
for (; *ptr >= '0' && *ptr <= '9'; ++ptr) {
|
||||||
do {
|
if (overflowed) {
|
||||||
// If we don't have a digit, bail
|
|
||||||
if (*ptr < '0' || *ptr > '9') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Avoid overflowing!
|
|
||||||
if (param > UINT8_MAX - (*ptr - '0')) {
|
|
||||||
if (!warned) {
|
|
||||||
warnx("Invalid warning flag \"%s\": capping parameter at 255", flag.c_str());
|
|
||||||
}
|
|
||||||
warned = true; // Only warn once, cap always
|
|
||||||
param = 255;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
param = param * 10 + (*ptr - '0');
|
|
||||||
|
|
||||||
++ptr;
|
uint32_t c = *ptr - '0';
|
||||||
} while (*ptr);
|
if (param > (UINT32_MAX - c) / 10) {
|
||||||
|
overflowed = true;
|
||||||
|
param = UINT32_MAX;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
param = param * 10 + c;
|
||||||
|
}
|
||||||
|
|
||||||
// If we reached the end of the string, truncate it at the '='
|
// If we reached the end of the string, truncate it at the '='
|
||||||
if (*ptr == '\0') {
|
if (*ptr == '\0') {
|
||||||
|
|||||||
4
test/asm/diagnostic-parameter-cap.asm
Normal file
4
test/asm/diagnostic-parameter-cap.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
opt Wtruncation=256
|
||||||
|
section "test", rom0
|
||||||
|
db 999
|
||||||
|
db -254
|
||||||
5
test/asm/diagnostic-parameter-cap.err
Normal file
5
test/asm/diagnostic-parameter-cap.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
warning: Invalid warning flag parameter "truncation=256"; capping at maximum 2
|
||||||
|
warning: diagnostic-parameter-cap.asm(3): [-Wtruncation]
|
||||||
|
Expression must be 8-bit; use LOW() to force 8-bit
|
||||||
|
warning: diagnostic-parameter-cap.asm(4): [-Wtruncation]
|
||||||
|
Expression must be 8-bit; use LOW() to force 8-bit
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
warning: Invalid parameter 99 for warning flag "truncation"; capping at maximum 2
|
warning: Invalid warning flag parameter "truncation=99"; capping at maximum 2
|
||||||
warning: invalid-param.asm(2): [-Wtruncation]
|
warning: invalid-param.asm(2): [-Wtruncation]
|
||||||
Expression must be 8-bit; use LOW() to force 8-bit
|
Expression must be 8-bit; use LOW() to force 8-bit
|
||||||
warning: invalid-param.asm(3): [-Wtruncation]
|
warning: invalid-param.asm(3): [-Wtruncation]
|
||||||
|
|||||||
Reference in New Issue
Block a user