Consider the following program:
MODULE assignvalue ; (*!m2iso+gm2*) PROCEDURE bad () : INTEGER ; VAR i: INTEGER ; BEGIN i := -1 ; RETURN i END bad ; VAR foo: CARDINAL ; BEGIN (* The m2rte plugin will detect this as an error, post optimization. *) foo := bad () END assignvalue.
here we see that the programmer has overlooked that the return value from ‘bad’ will cause an overflow to ‘foo’. If we compile the code with the following options:
$ gm2 -g -fsoft-check-all -O2 -c assignvalue.mod assignvalue.mod:16:0:inevitable that this error will occur at run time, assignment will result in an overflow
The gm2 semantic plugin is automatically run and will generate a warning message for every exception call which is known as reachable. It is highly advised to run the optimizer (‘-O2’ or ‘-O3’) with ‘-fsoft-check-all’ so that the compiler is able to run the optimizer and perform variable and flow analysis before the semantic plugin is invoked.
The ‘-Wuninit-variable-checking’ can be used to identify uninitialized variables within the first basic block in a procedure. The checking is limited to variables so long as they are not an array or set or a variant record or var parameter.
The following example detects whether a sub component within a record is uninitialized.
MODULE testlarge2 ; TYPE color = RECORD r, g, b: CARDINAL ; END ; pixel = RECORD fg, bg: color ; END ; PROCEDURE test ; VAR p: pixel ; BEGIN p.fg.r := 1 ; p.fg.g := 2 ; p.fg.g := 3 ; (* Deliberate typo should be p.fg.b. *) p.bg := p.fg ; (* Accessing an uninitialized field. *) END test ; BEGIN test END testlarge2.
$ gm2 -c -Wuninit-variable-checking testlarge2.mod testlarge2.mod:19:13: warning: In procedure ‘test’: attempting to access expression before it has been initialized 19 | p.bg := p.fg ; (* Accessing an uninitialized field. *) | ~^~~
The following example detects if an individual field is uninitialized.
MODULE testwithnoptr ; TYPE Vec = RECORD x, y: CARDINAL ; END ; PROCEDURE test ; VAR p: Vec ; BEGIN WITH p DO x := 1 ; x := 2 (* Deliberate typo, user meant y. *) END ; IF p.y = 2 THEN END END test ; BEGIN test END testwithnoptr.
The following example detects a record is uninitialized via a pointer variable in a ‘WITH’ block.
$ gm2 -g -c -Wuninit-variable-checking testwithnoptr.mod testwithnoptr.mod:21:8: warning: In procedure ‘test’: attempting to access expression before it has been initialized 21 | IF p.y = 2 | ~^~
MODULE testnew6 ; FROM Storage IMPORT ALLOCATE ; TYPE PtrToVec = POINTER TO RECORD x, y: INTEGER ; END ; PROCEDURE test ; VAR p: PtrToVec ; BEGIN NEW (p) ; WITH p^ DO x := 1 ; x := 2 (* Deliberate typo, user meant y. *) END ; IF p^.y = 2 THEN END END test ; BEGIN test END testnew6.
$ gm2 -g -c -Wuninit-variable-checking testnew6.mod testnew6.mod:19:9: warning: In procedure ‘test’: attempting to access expression before it has been initialized 19 | IF p^.y = 2 | ~~^~