aboutsummaryrefslogtreecommitdiff
path: root/gcc/doc
diff options
context:
space:
mode:
authorGaius Mulley <gaiusmod2@gmail.com>2023-07-03 11:18:20 +0100
committerGaius Mulley <gaiusmod2@gmail.com>2023-07-03 11:18:20 +0100
commitb0762d4c7e7894845e70e839c8513ae4c9e9d42e (patch)
treebdff23cd62678c7079701d171819ac5507c0cf33 /gcc/doc
parent49485639c25c77b116d35c2f9c3dbfb8bf4cf814 (diff)
downloadgcc-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.texi126
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