diff --git a/include/asm/warning.h b/include/asm/warning.h index 18a57962..98d273d4 100644 --- a/include/asm/warning.h +++ b/include/asm/warning.h @@ -23,6 +23,7 @@ enum WarningID { WARNING_EMPTY_STRRPL, /* Empty second argument in `STRRPL` */ WARNING_LARGE_CONSTANT, /* Constants too large */ WARNING_LONG_STR, /* String too long for internal buffers */ + WARNING_MACRO_SHIFT, /* Shift past available arguments in macro */ WARNING_NESTED_COMMENT, /* Comment-start delimiter in a block comment */ WARNING_OBSOLETE, /* Obsolete things */ WARNING_SHIFT, /* Shifting undefined behavior */ diff --git a/src/asm/macro.c b/src/asm/macro.c index b6220490..f47d55d8 100644 --- a/src/asm/macro.c +++ b/src/asm/macro.c @@ -168,12 +168,17 @@ void macro_ShiftCurrentArgs(int32_t count) { if (!macroArgs) { error("Cannot shift macro arguments outside of a macro\n"); - } else if (macroArgs->shift < macroArgs->nbArgs) { + } else if (count > 0 && (count > macroArgs->nbArgs + || macroArgs->shift > macroArgs->nbArgs - count)) { + warning(WARNING_MACRO_SHIFT, + "Cannot shift macro arguments past their end\n"); + macroArgs->shift = macroArgs->nbArgs; + } else if (count < 0 && macroArgs->shift < -count) { + warning(WARNING_MACRO_SHIFT, + "Cannot shift macro arguments past their beginning\n"); + macroArgs->shift = 0; + } else { macroArgs->shift += count; - if (macroArgs->shift > macroArgs->nbArgs) - macroArgs->shift = macroArgs->nbArgs; - else if (macroArgs->shift < 0) - macroArgs->shift = 0; } } diff --git a/src/asm/rgbasm.1 b/src/asm/rgbasm.1 index f34fe685..ca173c2a 100644 --- a/src/asm/rgbasm.1 +++ b/src/asm/rgbasm.1 @@ -229,6 +229,10 @@ This warning is enabled by Warn when a string too long to fit in internal buffers is encountered. This warning is enabled by .Fl Wall . +.It Fl Wmacro-shift +Warn when shifting macro arguments past their limits. +This warning is enabled by +.Fl Wextra . .It Fl Wno-obsolete Warn when obsolete constructs such as the .Ic _PI diff --git a/src/asm/warning.c b/src/asm/warning.c index 69b973b0..c7ceda5b 100644 --- a/src/asm/warning.c +++ b/src/asm/warning.c @@ -38,6 +38,7 @@ static enum WarningState const defaultWarnings[NB_WARNINGS] = { [WARNING_EMPTY_STRRPL] = WARNING_DISABLED, [WARNING_LARGE_CONSTANT] = WARNING_DISABLED, [WARNING_LONG_STR] = WARNING_DISABLED, + [WARNING_MACRO_SHIFT] = WARNING_DISABLED, [WARNING_NESTED_COMMENT] = WARNING_ENABLED, [WARNING_OBSOLETE] = WARNING_ENABLED, [WARNING_SHIFT] = WARNING_DISABLED, @@ -79,6 +80,7 @@ static char const *warningFlags[NB_WARNINGS_ALL] = { "empty-strrpl", "large-constant", "long-string", + "macro-shift", "nested-comment", "obsolete", "shift", @@ -110,6 +112,7 @@ static uint8_t const _wallCommands[] = { /* Warnings that are less likely to indicate an error */ static uint8_t const _wextraCommands[] = { WARNING_EMPTY_ENTRY, + WARNING_MACRO_SHIFT, WARNING_NESTED_COMMENT, META_WARNING_DONE }; @@ -123,6 +126,7 @@ static uint8_t const _weverythingCommands[] = { WARNING_EMPTY_STRRPL, WARNING_LARGE_CONSTANT, WARNING_LONG_STR, + WARNING_MACRO_SHIFT, WARNING_NESTED_COMMENT, WARNING_OBSOLETE, WARNING_SHIFT, diff --git a/test/asm/narg-decreases-after-shift.err b/test/asm/narg-decreases-after-shift.err index e69de29b..a6eb6fd5 100644 --- a/test/asm/narg-decreases-after-shift.err +++ b/test/asm/narg-decreases-after-shift.err @@ -0,0 +1,2 @@ +warning: narg-decreases-after-shift.asm(14) -> narg-decreases-after-shift.asm::testing(9): [-Wmacro-shift] + Cannot shift macro arguments past their end diff --git a/test/asm/rept-shift.asm b/test/asm/rept-shift.asm index 3f48cd71..4b74b6f1 100644 --- a/test/asm/rept-shift.asm +++ b/test/asm/rept-shift.asm @@ -8,9 +8,7 @@ m: macro ; Shifting a little more to check that over-shifting doesn't crash SHIFT SHIFT - REPT 256 - SHIFT - ENDR + SHIFT 256 PRINTLN "\1" endm diff --git a/test/asm/rept-shift.err b/test/asm/rept-shift.err index 30fd3490..be4a73d9 100644 --- a/test/asm/rept-shift.err +++ b/test/asm/rept-shift.err @@ -1,2 +1,6 @@ -FATAL: rept-shift.asm(17) -> rept-shift.asm::m(14): +warning: rept-shift.asm(15) -> rept-shift.asm::m(10): [-Wmacro-shift] + Cannot shift macro arguments past their end +warning: rept-shift.asm(15) -> rept-shift.asm::m(11): [-Wmacro-shift] + Cannot shift macro arguments past their end +FATAL: rept-shift.asm(15) -> rept-shift.asm::m(12): Macro argument '\1' not defined diff --git a/test/asm/shift-negative.asm b/test/asm/shift-negative.asm index d99d5eef..87617fd3 100644 --- a/test/asm/shift-negative.asm +++ b/test/asm/shift-negative.asm @@ -12,5 +12,9 @@ ENDM m: MACRO shift 2 shift -3 + shift 1 + shift 1 + shift -1 + shift -1 ENDM - m + m one diff --git a/test/asm/shift-negative.err b/test/asm/shift-negative.err index e69de29b..654d585e 100644 --- a/test/asm/shift-negative.err +++ b/test/asm/shift-negative.err @@ -0,0 +1,8 @@ +warning: shift-negative.asm(20) -> shift-negative.asm::m(13): [-Wmacro-shift] + Cannot shift macro arguments past their end +warning: shift-negative.asm(20) -> shift-negative.asm::m(14): [-Wmacro-shift] + Cannot shift macro arguments past their beginning +warning: shift-negative.asm(20) -> shift-negative.asm::m(16): [-Wmacro-shift] + Cannot shift macro arguments past their end +warning: shift-negative.asm(20) -> shift-negative.asm::m(18): [-Wmacro-shift] + Cannot shift macro arguments past their beginning