shithub: rgbds

Download patch

ref: 49aac2961d01a395d60b6eeeb7467021b43498f6
parent: 3741bd46171a143c5549422e8f55a2933b59eb97
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Wed Mar 31 06:00:21 EDT 2021

Warn about backwards FOR loops with -Wbackwards-for (-Wall)

Fixes #816

--- a/include/asm/warning.h
+++ b/include/asm/warning.h
@@ -15,6 +15,7 @@
 
 enum WarningID {
 	WARNING_ASSERT,		      /* Assertions */
+	WARNING_BACKWARDS_FOR,	      /* `for` loop with backwards range */
 	WARNING_BUILTIN_ARG,	      /* Invalid args to builtins */
 	WARNING_CHARMAP_REDEF,        /* Charmap entry re-definition */
 	WARNING_DIV,		      /* Division undefined behavior */
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -487,6 +487,10 @@
 	else if (step == 0)
 		error("FOR cannot have a step value of 0\n");
 
+	if ((step > 0 && start > stop) || (step < 0 && start < stop))
+		warning(WARNING_BACKWARDS_FOR, "FOR goes backwards from %d to %d by %d\n",
+			start, stop, step);
+
 	if (count == 0)
 		return;
 	if (!newReptContext(reptLineNo, body, size))
--- a/src/asm/rgbasm.1
+++ b/src/asm/rgbasm.1
@@ -189,7 +189,7 @@
 prefix, entries are listed alphabetically.
 .Bl -tag -width Ds
 .It Fl Wno-assert
-Warns when
+Warn when
 .Ic WARN Ns No -type
 assertions fail. (See
 .Dq Aborting the assembly process
@@ -197,6 +197,12 @@
 .Xr rgbasm 5
 for
 .Ic ASSERT ) .
+.It Fl Wbackwards-for
+Warn when
+.Ic FOR
+loops have their start and stop values switched according to the step value.
+This warning is enabled by
+.Fl Wall .
 .It Fl Wbuiltin-args
 Warn about incorrect arguments to built-in functions, such as
 .Fn STRSUB
@@ -239,7 +245,7 @@
 directive are encountered.
 .It Fl Wshift
 Warn when shifting right a negative value.
-Use a division by 2^N instead.
+Use a division by 2**N instead.
 .It Fl Wshift-amount
 Warn when a shift's operand is negative or greater than 32.
 .It Fl Wno-truncation
--- a/src/asm/warning.c
+++ b/src/asm/warning.c
@@ -30,6 +30,7 @@
 
 static enum WarningState const defaultWarnings[NB_WARNINGS] = {
 	[WARNING_ASSERT]		= WARNING_ENABLED,
+	[WARNING_BACKWARDS_FOR]		= WARNING_DISABLED,
 	[WARNING_BUILTIN_ARG]		= WARNING_DISABLED,
 	[WARNING_CHARMAP_REDEF]		= WARNING_DISABLED,
 	[WARNING_DIV]			= WARNING_DISABLED,
@@ -72,6 +73,7 @@
 
 static char const *warningFlags[NB_WARNINGS_ALL] = {
 	"assert",
+	"backwards-for",
 	"builtin-args",
 	"charmap-redef",
 	"div",
@@ -100,6 +102,7 @@
 
 /* Warnings that probably indicate an error */
 static uint8_t const _wallCommands[] = {
+	WARNING_BACKWARDS_FOR,
 	WARNING_BUILTIN_ARG,
 	WARNING_CHARMAP_REDEF,
 	WARNING_EMPTY_DATA_DIRECTIVE,
@@ -119,6 +122,7 @@
 
 /* Literally everything. Notably useful for testing */
 static uint8_t const _weverythingCommands[] = {
+	WARNING_BACKWARDS_FOR,
 	WARNING_BUILTIN_ARG,
 	WARNING_DIV,
 	WARNING_EMPTY_DATA_DIRECTIVE,
--- a/test/asm/for.asm
+++ b/test/asm/for.asm
@@ -8,11 +8,15 @@
 endr
 
 for v, 2, 1
-	print "unreached"
+	print "backwards"
 endr
 
 for v, 1, 2, 0
 	print "unreached"
+endr
+
+for v, 1, 2, -1
+	print "backwards"
 endr
 
 for x, 1, 5+1
--- a/test/asm/for.err
+++ b/test/asm/for.err
@@ -1,6 +1,10 @@
+warning: for.asm(12): [-Wbackwards-for]
+    FOR goes backwards from 2 to 1 by 1
 ERROR: for.asm(16):
     FOR cannot have a step value of 0
-ERROR: for.asm(41) -> for.asm::REPT~4(47):
-    'v' already defined as constant at for.asm(41) -> for.asm::REPT~4(45)
-FATAL: for.asm(41) -> for.asm::REPT~4(47):
+warning: for.asm(20): [-Wbackwards-for]
+    FOR goes backwards from 1 to 2 by -1
+ERROR: for.asm(45) -> for.asm::REPT~4(51):
+    'v' already defined as constant at for.asm(45) -> for.asm::REPT~4(49)
+FATAL: for.asm(45) -> for.asm::REPT~4(51):
     Failed to update FOR symbol value