diff options
author | Gaius Mulley <gaiusmod2@gmail.com> | 2023-07-03 11:18:20 +0100 |
---|---|---|
committer | Gaius Mulley <gaiusmod2@gmail.com> | 2023-07-03 11:18:20 +0100 |
commit | b0762d4c7e7894845e70e839c8513ae4c9e9d42e (patch) | |
tree | bdff23cd62678c7079701d171819ac5507c0cf33 /gcc/doc | |
parent | 49485639c25c77b116d35c2f9c3dbfb8bf4cf814 (diff) | |
download | gcc-b0762d4c7e7894845e70e839c8513ae4c9e9d42e.zip gcc-b0762d4c7e7894845e70e839c8513ae4c9e9d42e.tar.gz gcc-b0762d4c7e7894845e70e839c8513ae4c9e9d42e.tar.bz2 |
PR modula2/110125 variables reported as uninitialized when set inside WITH
The modula-2 static analysis incorrectly identifies variables as
uninitialized if they are initialized within a WITH statement. This bug
fix re-implements the variable static analysis and will detect simple
pointer record fields being accessed before being initialized.
The static analysis is limited to the first basic block in a procedure.
It does not check variant records, arrays or sets. A new option
-Wuninit-variable-checking will turn on the new semantic checking
(-Wall also enables the new checking).
gcc/ChangeLog:
PR modula2/110125
* doc/gm2.texi (Semantic checking): Include examples using
-Wuninit-variable-checking.
gcc/m2/ChangeLog:
PR modula2/110125
* Make-lang.in (GM2-COMP-BOOT-DEFS): Add M2SymInit.def.
(GM2-COMP-BOOT-MODS): Add M2SymInit.mod.
* gm2-compiler/M2BasicBlock.mod: Formatting changes.
* gm2-compiler/M2Code.mod: Remove import of VariableAnalysis from
M2Quads. Import VariableAnalysis from M2SymInit.mod.
* gm2-compiler/M2GCCDeclare.mod (PrintVerboseFromList):
Add debugging print for a component.
(TypeConstFullyDeclared): Call RememberType for every type.
* gm2-compiler/M2GenGCC.mod (CodeReturnValue): Add parameter to
GetQuadOtok.
(CodeBecomes): Add parameter to GetQuadOtok.
(CodeXIndr): Add parameter to GetQuadOtok.
* gm2-compiler/M2Optimize.mod (ReduceBranch): Reformat and
preserve operand token positions when reducing the branch
quadruples.
(ReduceGoto): Reformat.
(FoldMultipleGoto): Reformat.
(KnownReachable): Reformat.
* gm2-compiler/M2Options.def (UninitVariableChecking): New
variable declared and exported.
(SetUninitVariableChecking): New procedure.
* gm2-compiler/M2Options.mod (SetWall): Set
UninitVariableChecking.
(SetUninitVariableChecking): New procedure.
* gm2-compiler/M2Quads.def (PutQuadOtok): Exported and declared.
(VariableAnalysis): Removed.
* gm2-compiler/M2Quads.mod (PutQuadOtok): New procedure.
(doVal): Reformatted.
(MarkAsWrite): Reformatted.
(MarkArrayAsWritten): Reformatted.
(doIndrX): Use PutQuadOtok.
(MakeRightValue): Use GenQuadOtok.
(MakeLeftValue): Use GenQuadOtok.
(CheckReadBeforeInitialized): Remove.
(IsNeverAltered): Reformat.
(DebugLocation): New procedure.
(BuildDesignatorPointer): Use GenQuadO to preserve operand token
position.
(BuildRelOp): Use GenQuadOtok ditto.
* gm2-compiler/SymbolTable.def (VarCheckReadInit): New procedure.
(VarInitState): New procedure.
(PutVarInitialized): New procedure.
(PutVarFieldInitialized): New procedure function.
(GetVarFieldInitialized): New procedure function.
(PrintInitialized): New procedure.
* gm2-compiler/SymbolTable.mod (VarCheckReadInit): New procedure.
(VarInitState): New procedure.
(PutVarInitialized): New procedure.
(PutVarFieldInitialized): New procedure function.
(GetVarFieldInitialized): New procedure function.
(PrintInitialized): New procedure.
(LRInitDesc): New type.
(SymVar): InitState new field.
(MakeVar): Initialize InitState.
* gm2-gcc/m2options.h (M2Options_SetUninitVariableChecking):
New function declaration.
* gm2-lang.cc (gm2_langhook_handle_option): Detect
OPT_Wuninit_variable_checking and call SetUninitVariableChecking.
* lang.opt: Add Wuninit-variable-checking.
* gm2-compiler/M2SymInit.def: New file.
* gm2-compiler/M2SymInit.mod: New file.
gcc/testsuite/ChangeLog:
PR modula2/110125
* gm2/switches/uninit-variable-checking/fail/testinit.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testlarge.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testlarge2.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testrecinit.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testrecinit2.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testrecinit5.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testsmallrec.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testsmallrec2.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testsmallvec.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testvarinit.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testwithnoptr.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testwithptr.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testwithptr2.mod: New test.
* gm2/switches/uninit-variable-checking/fail/testwithptr3.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testrecinit3.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testrecinit5.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testsmallrec.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testsmallrec2.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testvarinit.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testwithptr.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testwithptr2.mod: New test.
* gm2/switches/uninit-variable-checking/pass/testwithptr3.mod: New test.
Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>
Diffstat (limited to 'gcc/doc')
-rw-r--r-- | gcc/doc/gm2.texi | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/gcc/doc/gm2.texi b/gcc/doc/gm2.texi index 3e531a8..ae87434 100644 --- a/gcc/doc/gm2.texi +++ b/gcc/doc/gm2.texi @@ -659,6 +659,11 @@ zero. @item -fwholevalue generate code to detect whole number overflow and underflow. +@item -Wuninit-variable-checking +issue a warning if a variable is used before it is initialized. +The checking only occurs in the first basic block in each procedure. +It does not check parameters, array types or set types. + @c the following warning options are complete but need to be @c regression tested against all other front ends @c to ensure the options do not conflict. @@ -1452,6 +1457,127 @@ with @samp{-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 @samp{-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. + +The following example detects whether a sub component within a record +is uninitialized. + +@example +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. +@end example + +@example +$ 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. *) + | ~^~~ +@end example + +The following example detects if an individual field is uninitialized. + +@example +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. +@end example + +The following example detects a record is uninitialized via a +pointer variable in a @samp{WITH} block. + +@example +$ 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 + | ~^~ +@end example + +@example +MODULE testwithptr ; + +FROM SYSTEM IMPORT ADR ; + +TYPE + PtrToVec = POINTER TO Vec ; + Vec = RECORD + x, y: CARDINAL ; + END ; + +PROCEDURE test ; +VAR + p: PtrToVec ; + v: Vec ; +BEGIN + p := ADR (v) ; + WITH p^ DO + x := 1 ; + x := 2 (* Deliberate typo, user meant y. *) + END ; + IF p^.y = 2 + THEN + END +END test ; + +BEGIN + test +END testwithptr. +@end example + +@example +gm2 -c -Wuninit-variable-checking testwithptr.mod +testwithptr.mod:26:9: warning: In procedure ‘test’: attempting to +access expression before it has been initialized + 26 | IF p^.y = 2 + | ~~^~ +@end example + @node Extensions, Type compatibility, Semantic checking, Using @section GNU Modula-2 language extensions |