aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/doc/gm2.texi11
-rw-r--r--gcc/m2/gm2-compiler/M2BasicBlock.def3
-rw-r--r--gcc/m2/gm2-compiler/M2BasicBlock.mod22
-rw-r--r--gcc/m2/gm2-compiler/M2Code.mod45
-rw-r--r--gcc/m2/gm2-compiler/M2GCCDeclare.mod36
-rw-r--r--gcc/m2/gm2-compiler/M2GenGCC.def2
-rw-r--r--gcc/m2/gm2-compiler/M2GenGCC.mod4
-rw-r--r--gcc/m2/gm2-compiler/M2Optimize.mod3
-rw-r--r--gcc/m2/gm2-compiler/M2Options.def12
-rw-r--r--gcc/m2/gm2-compiler/M2Options.mod182
-rw-r--r--gcc/m2/gm2-compiler/M2Quads.def12
-rw-r--r--gcc/m2/gm2-compiler/M2Quads.mod68
-rw-r--r--gcc/m2/gm2-compiler/M2Scope.def2
-rw-r--r--gcc/m2/gm2-compiler/M2Scope.mod4
-rw-r--r--gcc/m2/gm2-compiler/M2SymInit.def7
-rw-r--r--gcc/m2/gm2-compiler/M2SymInit.mod671
-rw-r--r--gcc/m2/gm2-compiler/SymbolTable.def15
-rw-r--r--gcc/m2/gm2-compiler/SymbolTable.mod45
-rw-r--r--gcc/m2/gm2-gcc/init.cc2
-rw-r--r--gcc/m2/gm2-gcc/m2options.h2
-rw-r--r--gcc/m2/gm2-lang.cc5
-rw-r--r--gcc/m2/lang.opt4
-rw-r--r--gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/cascadedif.mod25
-rw-r--r--gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/switches-uninit-variable-checking-cascade-fail.exp37
24 files changed, 979 insertions, 240 deletions
diff --git a/gcc/doc/gm2.texi b/gcc/doc/gm2.texi
index ae87434..8d5d95f 100644
--- a/gcc/doc/gm2.texi
+++ b/gcc/doc/gm2.texi
@@ -664,6 +664,17 @@ 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.
+@item -Wuninit-variable-checking=all,known,cond
+issue a warning if a variable is used before it is initialized.
+The checking will only occur in the first basic block in each
+procedure if @samp{known} is specified. If @samp{cond} or @samp{all}
+is specified then checking continues into conditional branches of the
+flow graph. All checking will stop when a procedure call is invoked
+or the top of a loop is encountered.
+The option @samp{-Wall} will turn on this flag with
+@samp{-Wuninit-variable-checking=known}.
+The @samp{-Wuninit-variable-checking=all} will increase compile time.
+
@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.
diff --git a/gcc/m2/gm2-compiler/M2BasicBlock.def b/gcc/m2/gm2-compiler/M2BasicBlock.def
index 44606dd..3a67ea6 100644
--- a/gcc/m2/gm2-compiler/M2BasicBlock.def
+++ b/gcc/m2/gm2-compiler/M2BasicBlock.def
@@ -60,7 +60,8 @@ PROCEDURE InitBasicBlocks (sb: ScopeBlock) : BasicBlock ;
reachable are removed.
*)
-PROCEDURE InitBasicBlocksFromRange (start, end: CARDINAL) : BasicBlock ;
+PROCEDURE InitBasicBlocksFromRange (ScopeSym: CARDINAL;
+ start, end: CARDINAL) : BasicBlock ;
(*
diff --git a/gcc/m2/gm2-compiler/M2BasicBlock.mod b/gcc/m2/gm2-compiler/M2BasicBlock.mod
index 1d005f6..d3eb135 100644
--- a/gcc/m2/gm2-compiler/M2BasicBlock.mod
+++ b/gcc/m2/gm2-compiler/M2BasicBlock.mod
@@ -35,12 +35,15 @@ FROM M2Quads IMPORT IsReferenced, IsConditional, IsUnConditional, IsCall,
IsInitialisingConst,
IsPseudoQuad, IsDefOrModFile,
GetNextQuad, GetQuad, QuadOperator,
- SubQuad ;
+ SubQuad, DisplayQuadRange ;
FROM M2Scope IMPORT ScopeBlock, ForeachScopeBlockDo ;
FROM M2GenGCC IMPORT ConvertQuadsToTree ;
+CONST
+ Debugging = FALSE ;
+
TYPE
BasicBlock = POINTER TO RECORD
StartQuad : CARDINAL ; (* First Quad in Basic Block *)
@@ -77,10 +80,15 @@ END InitBasicBlocks ;
reachable are removed.
*)
-PROCEDURE InitBasicBlocksFromRange (start, end: CARDINAL) : BasicBlock ;
+PROCEDURE InitBasicBlocksFromRange (ScopeSym: CARDINAL;
+ start, end: CARDINAL) : BasicBlock ;
BEGIN
HeadOfBasicBlock := NIL ;
- ConvertQuads2BasicBlock(start, end) ;
+ ConvertQuads2BasicBlock (ScopeSym, start, end) ;
+ IF Debugging
+ THEN
+ DisplayBasicBlocks (HeadOfBasicBlock)
+ END ;
RETURN( HeadOfBasicBlock )
END InitBasicBlocksFromRange ;
@@ -144,7 +152,7 @@ END New ;
which has only has one entry and exit point.
*)
-PROCEDURE ConvertQuads2BasicBlock (Start, End: CARDINAL) ;
+PROCEDURE ConvertQuads2BasicBlock (ScopeSym: CARDINAL; Start, End: CARDINAL) ;
VAR
LastQuadDefMod,
LastQuadConditional,
@@ -154,6 +162,10 @@ VAR
CurrentBB : BasicBlock ;
LastBB : BasicBlock ;
BEGIN
+ IF Debugging
+ THEN
+ DisplayQuadRange (ScopeSym, Start, End)
+ END ;
(*
Algorithm to perform Basic Block:
@@ -323,7 +335,6 @@ END Sub ;
DisplayBasicBlocks - displays the basic block data structure.
*)
-(*
PROCEDURE DisplayBasicBlocks (bb: BasicBlock) ;
VAR
b: BasicBlock ;
@@ -347,7 +358,6 @@ BEGIN
WriteString(' end ') ; WriteCard(EndQuad, 6) ;
END
END DisplayBlock ;
-*)
BEGIN
diff --git a/gcc/m2/gm2-compiler/M2Code.mod b/gcc/m2/gm2-compiler/M2Code.mod
index c4069e9..d2ace72 100644
--- a/gcc/m2/gm2-compiler/M2Code.mod
+++ b/gcc/m2/gm2-compiler/M2Code.mod
@@ -45,7 +45,7 @@ FROM M2Quads IMPORT CountQuads, GetFirstQuad, DisplayQuadList, DisplayQuadRange,
BackPatchSubrangesAndOptParam,
LoopAnalysis, ForLoopAnalysis, GetQuad, QuadOperator ;
-FROM M2SymInit IMPORT VariableAnalysis ;
+FROM M2SymInit IMPORT ScopeBlockVariableAnalysis ;
FROM M2Pass IMPORT SetPassToNoPass, SetPassToCodeGeneration ;
@@ -293,16 +293,16 @@ END Code ;
InitialDeclareAndCodeBlock - declares all objects within scope,
*)
-PROCEDURE InitialDeclareAndOptimize (start, end: CARDINAL) ;
+PROCEDURE InitialDeclareAndOptimize (scope: CARDINAL; start, end: CARDINAL) ;
BEGIN
- Count := CountQuads() ;
- FreeBasicBlocks(InitBasicBlocksFromRange(start, end)) ;
- BasicB := Count - CountQuads() ;
- Count := CountQuads() ;
-
- FoldBranches(start, end) ;
- Jump := Count - CountQuads() ;
- Count := CountQuads()
+ Count := CountQuads () ;
+ FreeBasicBlocks (InitBasicBlocksFromRange (scope, start, end)) ;
+ BasicB := Count - CountQuads () ;
+ Count := CountQuads () ;
+
+ FoldBranches (start, end) ;
+ Jump := Count - CountQuads () ;
+ Count := CountQuads ()
END InitialDeclareAndOptimize ;
@@ -310,24 +310,25 @@ END InitialDeclareAndOptimize ;
DeclareAndCodeBlock - declares all objects within scope,
*)
-PROCEDURE SecondDeclareAndOptimize (start, end: CARDINAL) ;
+PROCEDURE SecondDeclareAndOptimize (scope: CARDINAL;
+ start, end: CARDINAL) ;
BEGIN
REPEAT
FoldConstants(start, end) ;
DeltaConst := Count - CountQuads () ;
Count := CountQuads () ;
- FreeBasicBlocks(InitBasicBlocksFromRange (start, end)) ;
+ FreeBasicBlocks(InitBasicBlocksFromRange (scope, start, end)) ;
DeltaBasicB := Count - CountQuads () ;
Count := CountQuads () ;
- FreeBasicBlocks (InitBasicBlocksFromRange (start, end)) ;
+ FreeBasicBlocks (InitBasicBlocksFromRange (scope, start, end)) ;
FoldBranches(start, end) ;
DeltaJump := Count - CountQuads () ;
Count := CountQuads () ;
- FreeBasicBlocks(InitBasicBlocksFromRange (start, end)) ;
+ FreeBasicBlocks(InitBasicBlocksFromRange (scope, start, end)) ;
INC (DeltaBasicB, Count - CountQuads ()) ;
Count := CountQuads () ;
@@ -375,20 +376,6 @@ END Init ;
(*
- BasicBlockVariableAnalysis -
-*)
-
-PROCEDURE BasicBlockVariableAnalysis (start, end: CARDINAL) ;
-VAR
- bb: BasicBlock ;
-BEGIN
- bb := InitBasicBlocksFromRange(start, end) ;
- ForeachBasicBlockDo (bb, VariableAnalysis) ;
- KillBasicBlocks (bb)
-END BasicBlockVariableAnalysis ;
-
-
-(*
DisplayQuadsInScope -
*)
@@ -416,7 +403,7 @@ BEGIN
OptimTimes := 1 ;
Current := CountQuads () ;
ForeachScopeBlockDo (sb, InitialDeclareAndOptimize) ;
- ForeachScopeBlockDo (sb, BasicBlockVariableAnalysis) ;
+ ForeachScopeBlockDo (sb, ScopeBlockVariableAnalysis) ;
REPEAT
ForeachScopeBlockDo (sb, SecondDeclareAndOptimize) ;
Previous := Current ;
diff --git a/gcc/m2/gm2-compiler/M2GCCDeclare.mod b/gcc/m2/gm2-compiler/M2GCCDeclare.mod
index c502726..eaa3255 100644
--- a/gcc/m2/gm2-compiler/M2GCCDeclare.mod
+++ b/gcc/m2/gm2-compiler/M2GCCDeclare.mod
@@ -1610,13 +1610,13 @@ BEGIN
THEN
InternalError ('trying to declare the NulSym')
END ;
- IF IsConstructor(sym) AND (NOT GccKnowsAbout(sym))
+ IF IsConstructor (sym) AND (NOT GccKnowsAbout (sym))
THEN
- WalkConstructor(sym, TraverseDependants) ;
- DeclareTypesConstantsProceduresInRange(quad, quad) ;
- Assert(IsConstructorDependants(sym, IsFullyDeclared)) ;
- PushValue(sym) ;
- DeclareConstantFromTree(sym, PopConstructorTree(tokenno))
+ WalkConstructor (sym, TraverseDependants) ;
+ DeclareTypesConstantsProceduresInRange (GetScope (sym), quad, quad) ;
+ Assert (IsConstructorDependants (sym, IsFullyDeclared)) ;
+ PushValue (sym) ;
+ DeclareConstantFromTree (sym, PopConstructorTree (tokenno))
END
END DeclareConstructor ;
@@ -2539,24 +2539,24 @@ END FoldConstants ;
DeclareTypesConstantsProceduresInRange -
*)
-PROCEDURE DeclareTypesConstantsProceduresInRange (start, end: CARDINAL) ;
+PROCEDURE DeclareTypesConstantsProceduresInRange (scope, start, end: CARDINAL) ;
VAR
n, m: CARDINAL ;
BEGIN
IF DisplayQuadruples
THEN
- DisplayQuadRange(start, end)
+ DisplayQuadRange (scope, start, end)
END ;
REPEAT
n := NoOfElementsInSet(ToDoList) ;
- WHILE ResolveConstantExpressions(DeclareConstFully, start, end) DO
+ WHILE ResolveConstantExpressions (DeclareConstFully, start, end) DO
END ;
(* we need to evaluate some constant expressions to resolve these types *)
IF DeclaredOutstandingTypes (FALSE)
THEN
END ;
m := NoOfElementsInSet(ToDoList)
- UNTIL (NOT ResolveConstantExpressions(DeclareConstFully, start, end)) AND
+ UNTIL (NOT ResolveConstantExpressions (DeclareConstFully, start, end)) AND
(n=m)
END DeclareTypesConstantsProceduresInRange ;
@@ -2620,16 +2620,16 @@ VAR
s, t: CARDINAL ;
sb : ScopeBlock ;
BEGIN
- sb := InitScopeBlock(scope) ;
- PushBinding(scope) ;
+ sb := InitScopeBlock (scope) ;
+ PushBinding (scope) ;
REPEAT
- s := NoOfElementsInSet(ToDoList) ;
+ s := NoOfElementsInSet (ToDoList) ;
(* ForeachLocalSymDo(scope, DeclareTypeInfo) ; *)
- ForeachScopeBlockDo(sb, DeclareTypesConstantsProceduresInRange) ;
- t := NoOfElementsInSet(ToDoList) ;
+ ForeachScopeBlockDo (sb, DeclareTypesConstantsProceduresInRange) ;
+ t := NoOfElementsInSet (ToDoList) ;
UNTIL s=t ;
- PopBinding(scope) ;
- KillScopeBlock(sb)
+ PopBinding (scope) ;
+ KillScopeBlock (sb)
END DeclareTypesConstantsProcedures ;
@@ -2691,7 +2691,7 @@ BEGIN
WalkTypesInProcedure(scope) ;
DeclareProcedure(scope) ;
ForeachInnerModuleDo(scope, WalkTypesInModule) ;
- DeclareTypesConstantsProcedures(scope) ;
+ DeclareTypesConstantsProcedures (scope) ;
ForeachInnerModuleDo(scope, DeclareTypesConstantsProcedures) ;
DeclareLocalVariables(scope) ;
ForeachInnerModuleDo(scope, DeclareModuleVariables) ;
diff --git a/gcc/m2/gm2-compiler/M2GenGCC.def b/gcc/m2/gm2-compiler/M2GenGCC.def
index 646e09e..b132bf0 100644
--- a/gcc/m2/gm2-compiler/M2GenGCC.def
+++ b/gcc/m2/gm2-compiler/M2GenGCC.def
@@ -45,7 +45,7 @@ EXPORT QUALIFIED ConvertQuadsToTree, ResolveConstantExpressions,
the GCC tree structure.
*)
-PROCEDURE ConvertQuadsToTree (Start, End: CARDINAL) ;
+PROCEDURE ConvertQuadsToTree (Scope: CARDINAL; Start, End: CARDINAL) ;
(*
diff --git a/gcc/m2/gm2-compiler/M2GenGCC.mod b/gcc/m2/gm2-compiler/M2GenGCC.mod
index 8b877e2..0955106 100644
--- a/gcc/m2/gm2-compiler/M2GenGCC.mod
+++ b/gcc/m2/gm2-compiler/M2GenGCC.mod
@@ -395,7 +395,7 @@ BEGIN
THEN
RETURN FALSE
END ;
- scope := GetScope(scope)
+ scope := GetScope (scope)
END ;
InternalError ('expecting scope to eventually reach a module or defimp symbol')
ELSE
@@ -410,7 +410,7 @@ END IsExportedGcc ;
the GCC tree structure.
*)
-PROCEDURE ConvertQuadsToTree (Start, End: CARDINAL) ;
+PROCEDURE ConvertQuadsToTree (Scope: CARDINAL; Start, End: CARDINAL) ;
BEGIN
REPEAT
CodeStatement (Start) ;
diff --git a/gcc/m2/gm2-compiler/M2Optimize.mod b/gcc/m2/gm2-compiler/M2Optimize.mod
index 416eb42..408e958 100644
--- a/gcc/m2/gm2-compiler/M2Optimize.mod
+++ b/gcc/m2/gm2-compiler/M2Optimize.mod
@@ -351,7 +351,8 @@ BEGIN
END RemoveProcedures ;
-PROCEDURE KnownReachable (Start, End: CARDINAL) ;
+PROCEDURE KnownReachable (Scope: CARDINAL;
+ Start, End: CARDINAL) ;
VAR
Op : QuadOperator ;
Op1, Op2, Op3: CARDINAL ;
diff --git a/gcc/m2/gm2-compiler/M2Options.def b/gcc/m2/gm2-compiler/M2Options.def
index 722e56c..d8d3845 100644
--- a/gcc/m2/gm2-compiler/M2Options.def
+++ b/gcc/m2/gm2-compiler/M2Options.def
@@ -73,6 +73,7 @@ EXPORT QUALIFIED SetReturnCheck, SetNilCheck, SetCaseCheck,
VariantValueChecking,
UnusedVariableChecking, UnusedParameterChecking,
UninitVariableChecking, SetUninitVariableChecking,
+ UninitVariableConditionalChecking,
SetUnusedVariableChecking, SetUnusedParameterChecking,
Quiet, LineDirectives, StrictTypeChecking,
CPreProcessor, Xcode, ExtendedOpaque,
@@ -162,6 +163,10 @@ VAR
UnusedParameterChecking, (* Should we warn about unused parameters? *)
UninitVariableChecking, (* Should we warn about accessing *)
(* uninitialized variables in the first bb? *)
+ UninitVariableConditionalChecking,
+ (* Should we warn about accessing *)
+ (* uninitialized variables in subsequent *)
+ (* basic blocks? *)
LowerCaseKeywords, (* Should keywords in errors be in lower? *)
DebugBuiltins, (* Should we always call a real function? *)
AutoInit, (* -fauto-init assigns pointers to NIL. *)
@@ -922,10 +927,13 @@ PROCEDURE SetShared (value: BOOLEAN) ;
(*
- SetUninitVariableChecking - sets the UninitVariableChecking flag to value.
+ SetUninitVariableChecking - sets the UninitVariableChecking flag to value
+ or UninitVariableConditionalChecking to value.
+ Arg can be "known", "known,cond", "cond,known"
+ or "all".
*)
-PROCEDURE SetUninitVariableChecking (value: BOOLEAN) ;
+PROCEDURE SetUninitVariableChecking (value: BOOLEAN; arg: ADDRESS) : INTEGER ;
(*
diff --git a/gcc/m2/gm2-compiler/M2Options.mod b/gcc/m2/gm2-compiler/M2Options.mod
index 84fcb57..1174a0d 100644
--- a/gcc/m2/gm2-compiler/M2Options.mod
+++ b/gcc/m2/gm2-compiler/M2Options.mod
@@ -28,7 +28,7 @@ FROM M2Search IMPORT SetDefExtension, SetModExtension ;
FROM PathName IMPORT DumpPathName, AddInclude ;
FROM M2Printf IMPORT printf0, printf1, fprintf1 ;
FROM FIO IMPORT StdErr ;
-FROM libc IMPORT exit ;
+FROM libc IMPORT exit, printf ;
FROM Debug IMPORT Halt ;
FROM m2linemap IMPORT location_t ;
FROM m2configure IMPORT FullPathCPP ;
@@ -1369,84 +1369,114 @@ END SetShared ;
SetUninitVariableChecking - sets the UninitVariableChecking flag to value.
*)
-PROCEDURE SetUninitVariableChecking (value: BOOLEAN) ;
+PROCEDURE SetUninitVariableChecking (value: BOOLEAN; arg: ADDRESS) : INTEGER ;
+VAR
+ s: String ;
BEGIN
- UninitVariableChecking := value
+ IF Debugging
+ THEN
+ IF value
+ THEN
+ printf ("SetUninitVariableChecking (TRUE, %s)\n", arg)
+ ELSE
+ printf ("SetUninitVariableChecking (FALSE, %s)\n", arg)
+ END
+ END ;
+ s := InitStringCharStar (arg) ;
+ IF EqualArray (s, "all") OR
+ EqualArray (s, "known,cond") OR
+ EqualArray (s, "cond,known") OR
+ EqualArray (s, "cond")
+ THEN
+ UninitVariableChecking := value ;
+ UninitVariableConditionalChecking := value ;
+ s := KillString (s) ;
+ RETURN 1
+ ELSIF EqualArray (s, "known")
+ THEN
+ UninitVariableChecking := value ;
+ UninitVariableConditionalChecking := NOT value ;
+ s := KillString (s) ;
+ RETURN 1
+ ELSE
+ s := KillString (s) ;
+ RETURN 0
+ END
END SetUninitVariableChecking ;
-
BEGIN
- cflag := FALSE ; (* -c. *)
- RuntimeModuleOverride := InitString (DefaultRuntimeModuleOverride) ;
- CppArgs := InitString ('') ;
- Pim := TRUE ;
- Pim2 := FALSE ;
- Pim3 := FALSE ;
- Pim4 := TRUE ;
- PositiveModFloorDiv := FALSE ;
- Iso := FALSE ;
- SeenSources := FALSE ;
- Statistics := FALSE ;
- StyleChecking := FALSE ;
- CompilerDebugging := FALSE ;
- GenerateDebugging := FALSE ;
- Optimizing := FALSE ;
- Pedantic := FALSE ;
- Verbose := FALSE ;
- Quiet := TRUE ;
- CC1Quiet := TRUE ;
- Profiling := FALSE ;
- DisplayQuadruples := FALSE ;
- OptimizeBasicBlock := FALSE ;
- OptimizeUncalledProcedures := FALSE ;
- OptimizeCommonSubExpressions := FALSE ;
- NilChecking := FALSE ;
- WholeDivChecking := FALSE ;
- WholeValueChecking := FALSE ;
- FloatValueChecking := FALSE ;
- IndexChecking := FALSE ;
- RangeChecking := FALSE ;
- ReturnChecking := FALSE ;
- CaseElseChecking := FALSE ;
- CPreProcessor := FALSE ;
- LineDirectives := FALSE ;
- ExtendedOpaque := FALSE ;
- UnboundedByReference := FALSE ;
- VerboseUnbounded := FALSE ;
- PedanticParamNames := FALSE ;
- PedanticCast := FALSE ;
- Xcode := FALSE ;
- DumpSystemExports := FALSE ;
- GenerateSwig := FALSE ;
- Exceptions := TRUE ;
- DebugBuiltins := FALSE ;
- ForcedLocation := FALSE ;
- WholeProgram := FALSE ;
- DebugTraceQuad := FALSE ;
- DebugTraceAPI := FALSE ;
- DebugFunctionLineNumbers := FALSE ;
- GenerateStatementNote := FALSE ;
- LowerCaseKeywords := FALSE ;
- UnusedVariableChecking := FALSE ;
- UnusedParameterChecking := FALSE ;
- StrictTypeChecking := TRUE ;
- AutoInit := FALSE ;
- SaveTemps := FALSE ;
- ScaffoldDynamic := TRUE ;
- ScaffoldStatic := FALSE ;
- ScaffoldMain := FALSE ;
- UselistFilename := NIL ;
- GenModuleList := FALSE ;
- GenModuleListFilename := NIL ;
- SharedFlag := FALSE ;
- Barg := NIL ;
- MDarg := NIL ;
- MMDarg := NIL ;
- MQarg := NIL ;
- SaveTempsDir := NIL ;
- DumpDir := NIL ;
- UninitVariableChecking := FALSE ;
- M2Prefix := InitString ('') ;
- M2PathName := InitString ('')
+ cflag := FALSE ; (* -c. *)
+ RuntimeModuleOverride := InitString (DefaultRuntimeModuleOverride) ;
+ CppArgs := InitString ('') ;
+ Pim := TRUE ;
+ Pim2 := FALSE ;
+ Pim3 := FALSE ;
+ Pim4 := TRUE ;
+ PositiveModFloorDiv := FALSE ;
+ Iso := FALSE ;
+ SeenSources := FALSE ;
+ Statistics := FALSE ;
+ StyleChecking := FALSE ;
+ CompilerDebugging := FALSE ;
+ GenerateDebugging := FALSE ;
+ Optimizing := FALSE ;
+ Pedantic := FALSE ;
+ Verbose := FALSE ;
+ Quiet := TRUE ;
+ CC1Quiet := TRUE ;
+ Profiling := FALSE ;
+ DisplayQuadruples := FALSE ;
+ OptimizeBasicBlock := FALSE ;
+ OptimizeUncalledProcedures := FALSE ;
+ OptimizeCommonSubExpressions := FALSE ;
+ NilChecking := FALSE ;
+ WholeDivChecking := FALSE ;
+ WholeValueChecking := FALSE ;
+ FloatValueChecking := FALSE ;
+ IndexChecking := FALSE ;
+ RangeChecking := FALSE ;
+ ReturnChecking := FALSE ;
+ CaseElseChecking := FALSE ;
+ CPreProcessor := FALSE ;
+ LineDirectives := FALSE ;
+ ExtendedOpaque := FALSE ;
+ UnboundedByReference := FALSE ;
+ VerboseUnbounded := FALSE ;
+ PedanticParamNames := FALSE ;
+ PedanticCast := FALSE ;
+ Xcode := FALSE ;
+ DumpSystemExports := FALSE ;
+ GenerateSwig := FALSE ;
+ Exceptions := TRUE ;
+ DebugBuiltins := FALSE ;
+ ForcedLocation := FALSE ;
+ WholeProgram := FALSE ;
+ DebugTraceQuad := FALSE ;
+ DebugTraceAPI := FALSE ;
+ DebugFunctionLineNumbers := FALSE ;
+ GenerateStatementNote := FALSE ;
+ LowerCaseKeywords := FALSE ;
+ UnusedVariableChecking := FALSE ;
+ UnusedParameterChecking := FALSE ;
+ StrictTypeChecking := TRUE ;
+ AutoInit := FALSE ;
+ SaveTemps := FALSE ;
+ ScaffoldDynamic := TRUE ;
+ ScaffoldStatic := FALSE ;
+ ScaffoldMain := FALSE ;
+ UselistFilename := NIL ;
+ GenModuleList := FALSE ;
+ GenModuleListFilename := NIL ;
+ SharedFlag := FALSE ;
+ Barg := NIL ;
+ MDarg := NIL ;
+ MMDarg := NIL ;
+ MQarg := NIL ;
+ SaveTempsDir := NIL ;
+ DumpDir := NIL ;
+ UninitVariableChecking := FALSE ;
+ UninitVariableConditionalChecking := FALSE ;
+ M2Prefix := InitString ('') ;
+ M2PathName := InitString ('')
END M2Options.
diff --git a/gcc/m2/gm2-compiler/M2Quads.def b/gcc/m2/gm2-compiler/M2Quads.def
index ef6c06c..cd011ba 100644
--- a/gcc/m2/gm2-compiler/M2Quads.def
+++ b/gcc/m2/gm2-compiler/M2Quads.def
@@ -106,6 +106,7 @@ EXPORT QUALIFIED StartBuildDefFile, StartBuildModFile, EndBuildFile,
IsBackReference,
IsUnConditional,
IsConditional, IsBackReferenceConditional,
+ IsGoto,
IsCall,
IsReturn,
IsProcedureScope,
@@ -250,6 +251,13 @@ PROCEDURE IsBackReferenceConditional (q: CARDINAL) : BOOLEAN ;
(*
+ IsGoto - returns true if QuadNo is a goto operation.
+*)
+
+PROCEDURE IsGoto (QuadNo: CARDINAL) : BOOLEAN ;
+
+
+(*
IsCall - returns true if QuadNo is a call operation.
*)
@@ -382,7 +390,7 @@ PROCEDURE DisplayQuadList ;
DisplayQuadRange - displays all quads in list range, start..end.
*)
-PROCEDURE DisplayQuadRange (start, end: CARDINAL) ;
+PROCEDURE DisplayQuadRange (scope: CARDINAL; start, end: CARDINAL) ;
(*
@@ -2591,7 +2599,7 @@ PROCEDURE BuildStmtNote (offset: INTEGER) ;
LoopAnalysis - checks whether an infinite loop exists.
*)
-PROCEDURE LoopAnalysis (Current, End: CARDINAL) ;
+PROCEDURE LoopAnalysis (Scope: CARDINAL; Current, End: CARDINAL) ;
(*
diff --git a/gcc/m2/gm2-compiler/M2Quads.mod b/gcc/m2/gm2-compiler/M2Quads.mod
index dc73265..5ed2252 100644
--- a/gcc/m2/gm2-compiler/M2Quads.mod
+++ b/gcc/m2/gm2-compiler/M2Quads.mod
@@ -126,6 +126,7 @@ FROM SymbolTable IMPORT ModeOfAddr, GetMode, PutMode, GetSymName, IsUnknown,
GetUnboundedRecordType,
GetUnboundedAddressOffset,
GetUnboundedHighOffset,
+ PutVarArrayRef,
ForeachFieldEnumerationDo, ForeachLocalSymDo,
GetExported, PutImported, GetSym, GetLibName,
@@ -588,6 +589,7 @@ BEGIN
RETURN( TRUE )
END
+ ELSE
END ;
i := GetNextQuad (i)
END ;
@@ -712,6 +714,16 @@ END IsQuadA ;
(*
+ IsGoto - returns true if QuadNo is a goto operation.
+*)
+
+PROCEDURE IsGoto (QuadNo: CARDINAL) : BOOLEAN ;
+BEGIN
+ RETURN( IsQuadA (QuadNo, GotoOp) )
+END IsGoto ;
+
+
+(*
IsCall - returns true if QuadNo is a call operation.
*)
@@ -10667,7 +10679,7 @@ END IsInfiniteLoop ;
LoopAnalysis - checks whether an infinite loop exists.
*)
-PROCEDURE LoopAnalysis (Current, End: CARDINAL) ;
+PROCEDURE LoopAnalysis (Scope: CARDINAL; Current, End: CARDINAL) ;
VAR
op : QuadOperator ;
op1, op2, op3: CARDINAL ;
@@ -10683,10 +10695,18 @@ BEGIN
(* found a loop - ie a branch which goes back in quadruple numbers *)
IF IsInfiniteLoop(Current)
THEN
+ MetaErrorT1 (QuadToTokenNo(op3),
+ 'it is very likely (although not absolutely certain) that the top of an infinite loop exists here in {%1Wad}',
+ Scope) ;
+ MetaErrorT1 (QuadToTokenNo(Current),
+ 'and the bottom of the infinite loop is ends here in {%1Wad} or alternatively a component of this loop is never executed',
+ Scope) ;
+(*
WarnStringAt(InitString('it is very likely (although not absolutely certain) that the top of an infinite loop is here'),
QuadToTokenNo(op3)) ;
WarnStringAt(InitString('and the bottom of the infinite loop is ends here or alternatively a component of this loop is never executed'),
QuadToTokenNo(Current))
+*)
END
END
END ;
@@ -11216,6 +11236,7 @@ BEGIN
(* BuildDesignatorArray may have detected des is a constant. *)
PutVarConst (Adr, IsVarConst (Array))
END ;
+ PutVarArrayRef (Adr, TRUE) ;
(*
From now on it must reference the array element by its lvalue
- so we create the type of the referenced entity
@@ -11246,15 +11267,15 @@ BEGIN
THEN
(* ti has no type since constant *)
ti := MakeTemporary (tok, ImmediateValue) ;
- PutVar(ti, Cardinal) ;
+ PutVar (ti, Cardinal) ;
GenQuadO (tok, ElementSizeOp, ti, arrayType, 1, TRUE)
ELSE
INC(dim) ;
tk := MakeTemporary (tok, RightValue) ;
- PutVar(tk, Cardinal) ;
+ PutVar (tk, Cardinal) ;
GenHigh (tok, tk, dim, arraySym) ;
tl := MakeTemporary (tok, RightValue) ;
- PutVar(tl, Cardinal) ;
+ PutVar (tl, Cardinal) ;
GenQuadO (tok, AddOp, tl, tk, MakeConstLit (tok, MakeKey ('1'), Cardinal), TRUE) ;
tj := calculateMultipicand (tok, arraySym, arrayType, dim) ;
ti := MakeTemporary (tok, RightValue) ;
@@ -11385,6 +11406,7 @@ BEGIN
GenQuad (MultOp, tk, ti, tj) ;
Adr := MakeTemporary (combinedTok, LeftValue) ;
+ PutVarArrayRef (Adr, TRUE) ;
(*
Ok must reference by address
- but we contain the type of the referenced entity
@@ -13168,14 +13190,14 @@ END DisplayQuadList ;
DisplayQuadRange - displays all quads in list range, start..end.
*)
-PROCEDURE DisplayQuadRange (start, end: CARDINAL) ;
+PROCEDURE DisplayQuadRange (scope: CARDINAL; start, end: CARDINAL) ;
VAR
f: QuadFrame ;
BEGIN
- printf0('Quadruples:\n') ;
- WHILE (start<=end) AND (start#0) DO
- DisplayQuad(start) ;
- f := GetQF(start) ;
+ printf0 ('Quadruples for scope: ') ; WriteOperand (scope) ; printf0 ('\n') ;
+ WHILE (start <= end) AND (start # 0) DO
+ DisplayQuad (start) ;
+ f := GetQF (start) ;
start := f^.Next
END
END DisplayQuadRange ;
@@ -13194,10 +13216,10 @@ BEGIN
IF QuadrupleGeneration
THEN
WHILE QuadNo#0 DO
- f := GetQF(QuadNo) ;
+ f := GetQF (QuadNo) ;
WITH f^ DO
i := Operand3 ; (* Next Link along the BackPatch *)
- ManipulateReference(QuadNo, Value) (* Filling in the BackPatch. *)
+ ManipulateReference (QuadNo, Value) (* Filling in the BackPatch. *)
END ;
QuadNo := i
END
@@ -13596,17 +13618,17 @@ PROCEDURE WriteOperand (Sym: CARDINAL) ;
VAR
n: Name ;
BEGIN
- IF Sym=NulSym
+ IF Sym = NulSym
THEN
- printf0('<nulsym>')
+ printf0 ('<nulsym>')
ELSE
- n := GetSymName(Sym) ;
- printf1('%a', n) ;
- IF IsVar(Sym) OR IsConst(Sym)
+ n := GetSymName (Sym) ;
+ printf1 ('%a', n) ;
+ IF IsVar (Sym) OR IsConst (Sym)
THEN
- printf0('[') ; WriteMode(GetMode(Sym)) ; printf0(']')
+ printf0 ('[') ; WriteMode (GetMode (Sym)) ; printf0(']')
END ;
- printf1('(%d)', Sym)
+ printf1 ('(%d)', Sym)
END
END WriteOperand ;
@@ -13666,7 +13688,15 @@ BEGIN
LogicalOrOp : RETURN InitString ('{%kOR}') |
LogicalAndOp: RETURN InitString ('{%kAND}') |
InclOp : RETURN InitString ('{%kINCL}') |
- ExclOp : RETURN InitString ('{%kEXCL}')
+ ExclOp : RETURN InitString ('{%kEXCL}') |
+ IfEquOp : RETURN InitString ('=') |
+ IfLessEquOp : RETURN InitString ('<=') |
+ IfGreEquOp : RETURN InitString ('>=') |
+ IfGreOp : RETURN InitString ('>') |
+ IfLessOp : RETURN InitString ('<') |
+ IfNotEquOp : RETURN InitString ('#') |
+ IfInOp : RETURN InitString ('IN') |
+ IfNotInOp : RETURN InitString ('NOT IN')
ELSE
RETURN NIL
diff --git a/gcc/m2/gm2-compiler/M2Scope.def b/gcc/m2/gm2-compiler/M2Scope.def
index 9aed024..c1b684e 100644
--- a/gcc/m2/gm2-compiler/M2Scope.def
+++ b/gcc/m2/gm2-compiler/M2Scope.def
@@ -37,7 +37,7 @@ EXPORT QUALIFIED ScopeBlock, ScopeProcedure,
TYPE
ScopeBlock ;
- ScopeProcedure = PROCEDURE (CARDINAL, CARDINAL) ;
+ ScopeProcedure = PROCEDURE (CARDINAL, CARDINAL, CARDINAL) ;
(*
diff --git a/gcc/m2/gm2-compiler/M2Scope.mod b/gcc/m2/gm2-compiler/M2Scope.mod
index d840bf5..106c2a8 100644
--- a/gcc/m2/gm2-compiler/M2Scope.mod
+++ b/gcc/m2/gm2-compiler/M2Scope.mod
@@ -349,7 +349,7 @@ BEGIN
END ;
printf0 ("\n") ;
- DisplayQuadRange (low, high) ;
+ DisplayQuadRange (scopeSym, low, high) ;
IF next#NIL
THEN
DisplayScope (next)
@@ -428,7 +428,7 @@ BEGIN
enter (sb) ;
IF (low # 0) AND (high # 0)
THEN
- p (low, high)
+ p (scopeSym, low, high)
END ;
leave (sb)
END ;
diff --git a/gcc/m2/gm2-compiler/M2SymInit.def b/gcc/m2/gm2-compiler/M2SymInit.def
index 2ea6bfc..d0e39fb 100644
--- a/gcc/m2/gm2-compiler/M2SymInit.def
+++ b/gcc/m2/gm2-compiler/M2SymInit.def
@@ -45,12 +45,11 @@ PROCEDURE GetFieldInitialized (desc: InitDesc; fieldlist: List) : BOOLEAN ;
(*
- VariableAnalysis - checks to see whether a variable is:
-
- read before it has been initialized
+ ScopeBlockVariableAnalysis - checks to see whether a variable is
+ read before it has been initialized.
*)
-PROCEDURE VariableAnalysis (Start, End: CARDINAL) ;
+PROCEDURE ScopeBlockVariableAnalysis (Scope: CARDINAL; Start, End: CARDINAL) ;
PROCEDURE PrintSymInit (desc: InitDesc) ;
diff --git a/gcc/m2/gm2-compiler/M2SymInit.mod b/gcc/m2/gm2-compiler/M2SymInit.mod
index 18200af..a5457ec 100644
--- a/gcc/m2/gm2-compiler/M2SymInit.mod
+++ b/gcc/m2/gm2-compiler/M2SymInit.mod
@@ -23,17 +23,28 @@ IMPLEMENTATION MODULE M2SymInit ;
FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
FROM M2Debug IMPORT Assert ;
+FROM M2Printf IMPORT printf0, printf1, printf2, printf3, printf4 ;
FROM libc IMPORT printf ;
FROM NameKey IMPORT Name, NulName, KeyToCharStar ;
-FROM M2Options IMPORT UninitVariableChecking ;
-FROM M2MetaError IMPORT MetaErrorT1 ;
+
+FROM M2Options IMPORT UninitVariableChecking, UninitVariableConditionalChecking,
+ CompilerDebugging ;
+
+FROM M2MetaError IMPORT MetaErrorT1, MetaErrorStringT1, MetaErrorStringT2 ;
FROM M2LexBuf IMPORT UnknownTokenNo ;
+FROM DynamicStrings IMPORT String, InitString, Mark, ConCat, InitString ;
+FROM M2Error IMPORT InternalError ;
+
+FROM M2BasicBlock IMPORT BasicBlock,
+ InitBasicBlocks, InitBasicBlocksFromRange,
+ KillBasicBlocks, FreeBasicBlocks,
+ ForeachBasicBlockDo ;
IMPORT Indexing ;
FROM Lists IMPORT List, InitList, GetItemFromList, PutItemIntoList,
IsItemInList, IncludeItemIntoList, NoOfItemsInList,
- RemoveItemFromList, ForeachItemInListDo, KillList ;
+ RemoveItemFromList, ForeachItemInListDo, KillList, DuplicateList ;
FROM SymbolTable IMPORT NulSym, ModeOfAddr, IsVar, IsRecord, GetSType,
GetNth, IsRecordField, IsSet, IsArray, IsProcedure,
@@ -43,10 +54,14 @@ FROM SymbolTable IMPORT NulSym, ModeOfAddr, IsVar, IsRecord, GetSType,
IsConst, IsConstString, NoOfParam, IsVarParam,
ForeachLocalSymDo, IsTemporary, ModeOfAddr,
IsReallyPointer, IsUnbounded,
- IsVarient, IsFieldVarient, GetVarient ;
+ IsVarient, IsFieldVarient, GetVarient,
+ IsVarArrayRef ;
+
+FROM M2Quads IMPORT QuadOperator, GetQuadOtok, GetQuad, GetNextQuad,
+ IsNewLocalVar, IsReturn, IsKillLocalVar, IsConditional,
+ IsUnConditional, IsBackReference, IsCall, IsGoto,
+ GetM2OperatorDesc, Opposite, DisplayQuadRange ;
-FROM M2Quads IMPORT QuadOperator, GetQuadOtok, GetQuad, GetNextQuad ;
-FROM M2Options IMPORT CompilerDebugging ;
FROM M2Printf IMPORT printf0, printf1, printf2 ;
FROM M2GCCDeclare IMPORT PrintSym ;
@@ -78,9 +93,32 @@ TYPE
next : symAlias ;
END ;
+ bbEntry = POINTER TO RECORD
+ start, end: CARDINAL ;
+ (* Is this the first bb? *)
+ first,
+ (* Does it end with a call? *)
+ endCall,
+ (* Does it end with a goto? *)
+ endGoto,
+ (* Does it end with a conditional? *)
+ endCond,
+ (* Does it form part of a loop? *)
+ topOfLoop: BOOLEAN ;
+ indexBB,
+ nextQuad,
+ condQuad,
+ nextBB,
+ condBB : CARDINAL ;
+ next : bbEntry ;
+ END ;
+
VAR
aliasArray: Indexing.Index ;
freeList : symAlias ;
+ bbArray : Indexing.Index ;
+ bbFreeList: bbEntry ;
+ errorList : List ; (* Ensure that we only generate one set of warnings per token. *)
(*
@@ -427,11 +465,115 @@ END ContainsVariant ;
(*
+ IssueConditional -
+*)
+
+PROCEDURE IssueConditional (quad: CARDINAL; conditional: BOOLEAN) ;
+VAR
+ op : QuadOperator ;
+ op1, op2, op3 : CARDINAL ;
+ op1tok, op2tok, op3tok, qtok: CARDINAL ;
+ overflowChecking : BOOLEAN ;
+ s : String ;
+BEGIN
+ GetQuadOtok (quad, qtok, op, op1, op2, op3, overflowChecking,
+ op1tok, op2tok, op3tok) ;
+ IF IsUniqueWarning (qtok)
+ THEN
+ op1tok := DefaultTokPos (op1tok, qtok) ;
+ op2tok := DefaultTokPos (op2tok, qtok) ;
+ op3tok := DefaultTokPos (op3tok, qtok) ;
+ IF NOT conditional
+ THEN
+ op := Opposite (op)
+ END ;
+ s := InitString ('depending upon the result of {%1Oad} ') ;
+ s := ConCat (s, Mark (GetM2OperatorDesc (op))) ;
+ s := ConCat (s, InitString (' {%2ad}')) ;
+ MetaErrorStringT2 (qtok, s, op1, op2)
+ END
+END IssueConditional ;
+
+
+(*
+ GenerateNoteFlow -
+*)
+
+PROCEDURE GenerateNoteFlow (lst: List; n: CARDINAL; warning: BOOLEAN) ;
+VAR
+ i : CARDINAL ;
+ ip1Ptr,
+ iPtr : bbEntry ;
+BEGIN
+ IF NOT warning
+ THEN
+ (* Only issue flow messages for non warnings. *)
+ i := 1 ;
+ WHILE i <= n DO
+ iPtr := Indexing.GetIndice (bbArray, i) ;
+ IF iPtr^.endCond
+ THEN
+ IF i < n
+ THEN
+ ip1Ptr := Indexing.GetIndice (bbArray, i+1) ;
+ IssueConditional (iPtr^.end, iPtr^.condBB = ip1Ptr^.indexBB)
+ END
+ END ;
+ INC (i)
+ END
+ END
+END GenerateNoteFlow ;
+
+
+(*
+ IssueWarning - issue a warning or note at tok location.
+*)
+
+PROCEDURE IssueWarning (tok: CARDINAL;
+ before, after: ARRAY OF CHAR;
+ sym: CARDINAL; warning: BOOLEAN) ;
+VAR
+ s: String ;
+BEGIN
+ s := InitString (before) ;
+ IF warning
+ THEN
+ s := ConCat (s, Mark (InitString ('{%1Wad}')))
+ ELSE
+ s := ConCat (s, Mark (InitString ('{%1Oad}')))
+ END ;
+ s := ConCat (s, Mark (InitString (after))) ;
+ MetaErrorStringT1 (tok, s, sym)
+END IssueWarning ;
+
+
+(*
+ IsUniqueWarning - return TRUE if a warning has not been issued at tok.
+ It remembers tok and subsequent calls will always return FALSE.
+*)
+
+PROCEDURE IsUniqueWarning (tok: CARDINAL) : BOOLEAN ;
+BEGIN
+ IF NOT IsItemInList (errorList, tok)
+ THEN
+ IncludeItemIntoList (errorList, tok) ;
+ RETURN TRUE
+ ELSE
+ RETURN FALSE
+ END
+END IsUniqueWarning ;
+
+
+(*
CheckDeferredRecordAccess -
*)
PROCEDURE CheckDeferredRecordAccess (procsym: CARDINAL; tok: CARDINAL;
- sym: CARDINAL; canDereference: BOOLEAN) ;
+ sym: CARDINAL;
+ canDereference, warning: BOOLEAN;
+ lst: List; i: CARDINAL) ;
+VAR
+ unique: BOOLEAN ;
BEGIN
IF IsVar (sym)
THEN
@@ -459,32 +601,49 @@ BEGIN
ELSIF IsComponent (sym)
THEN
Trace ("checkReadInit IsComponent (%d) is true)", sym) ;
- IF NOT GetVarComponentInitialized (sym)
+ IF (NOT GetVarComponentInitialized (sym)) AND IsUniqueWarning (tok)
THEN
- MetaErrorT1 (tok,
- 'attempting to access {%1Wad} before it has been initialized',
- sym)
+ GenerateNoteFlow (lst, i, warning) ;
+ IssueWarning (tok,
+ 'attempting to access ',
+ ' before it has been initialized',
+ sym, warning)
END
ELSIF (GetMode (sym) = LeftValue) AND canDereference
THEN
Trace ("checkReadInit GetMode (%d) = LeftValue and canDereference (LeftValue and RightValue VarCheckReadInit)", sym) ;
+ unique := TRUE ;
IF NOT VarCheckReadInit (sym, LeftValue)
THEN
- MetaErrorT1 (tok,
- 'attempting to access the address of {%1Wad} before it has been initialized',
- sym)
+ unique := IsUniqueWarning (tok) ;
+ IF unique
+ THEN
+ GenerateNoteFlow (lst, i, warning) ;
+ IssueWarning (tok,
+ 'attempting to access the address of ',
+ ' before it has been initialized',
+ sym, warning)
+ END
END ;
IF NOT VarCheckReadInit (sym, RightValue)
THEN
- MetaErrorT1 (tok,
- 'attempting to access {%1Wad} before it has been initialized', sym)
+ IF unique
+ THEN
+ GenerateNoteFlow (lst, i, warning) ;
+ IssueWarning (tok,
+ 'attempting to access ', ' before it has been initialized',
+ sym, warning)
+ END
END
ELSE
Trace ("checkReadInit call VarCheckReadInit using GetMode (%d)", sym) ;
- IF NOT VarCheckReadInit (sym, GetMode (sym))
+ IF (NOT VarCheckReadInit (sym, GetMode (sym))) AND IsUniqueWarning (tok)
THEN
- MetaErrorT1 (tok,
- 'attempting to access {%1Wad} before it has been initialized', sym)
+ GenerateNoteFlow (lst, i, warning) ;
+ IssueWarning (tok,
+ 'attempting to access ',
+ ' before it has been initialized',
+ sym, warning)
END
END
END
@@ -757,7 +916,7 @@ BEGIN
(IsGlobalVar (sym) OR IsVarAParam (sym) OR
ContainsVariant (GetSType (sym)) OR
IsArray (GetSType (sym)) OR IsSet (GetSType (sym)) OR
- IsUnbounded (GetSType (sym)))
+ IsUnbounded (GetSType (sym)) OR IsVarArrayRef (sym))
END IsExempt ;
@@ -768,10 +927,11 @@ END IsExempt ;
PROCEDURE CheckBinary (procSym,
op1tok, op1,
op2tok, op2,
- op3tok, op3: CARDINAL) ;
+ op3tok, op3: CARDINAL; warning: BOOLEAN;
+ lst: List; i: CARDINAL) ;
BEGIN
- CheckDeferredRecordAccess (procSym, op2tok, op2, FALSE) ;
- CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE) ;
+ CheckDeferredRecordAccess (procSym, op2tok, op2, FALSE, warning, lst, i) ;
+ CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE, warning, lst, i) ;
SetVarInitialized (op1, FALSE)
END CheckBinary ;
@@ -782,9 +942,10 @@ END CheckBinary ;
PROCEDURE CheckUnary (procSym,
lhstok, lhs,
- rhstok, rhs: CARDINAL) ;
+ rhstok, rhs: CARDINAL; warning: BOOLEAN;
+ lst: List; i: CARDINAL) ;
BEGIN
- CheckDeferredRecordAccess (procSym, rhstok, rhs, FALSE) ;
+ CheckDeferredRecordAccess (procSym, rhstok, rhs, FALSE, warning, lst, i) ;
SetVarInitialized (lhs, FALSE)
END CheckUnary ;
@@ -793,13 +954,15 @@ END CheckUnary ;
CheckXIndr -
*)
-PROCEDURE CheckXIndr (procSym, lhstok, lhs, type, rhstok, rhs: CARDINAL) ;
+PROCEDURE CheckXIndr (procSym, lhstok, lhs, type,
+ rhstok, rhs: CARDINAL; warning: BOOLEAN;
+ bblst: List; i: CARDINAL) ;
VAR
lst : List ;
vsym: CARDINAL ;
BEGIN
- CheckDeferredRecordAccess (procSym, rhstok, rhs, FALSE) ;
- CheckDeferredRecordAccess (procSym, lhstok, lhs, FALSE) ;
+ CheckDeferredRecordAccess (procSym, rhstok, rhs, FALSE, warning, bblst, i) ;
+ CheckDeferredRecordAccess (procSym, lhstok, lhs, FALSE, warning, bblst, i) ;
(* Now see if we know what lhs is pointing to and set fields if necessary. *)
vsym := getAlias (lhs) ;
IF (vsym # lhs) AND (GetSType (vsym) = type)
@@ -824,11 +987,13 @@ END CheckXIndr ;
CheckIndrX -
*)
-PROCEDURE CheckIndrX (procSym, lhstok, lhs, type, rhstok, rhs: CARDINAL) ;
+PROCEDURE CheckIndrX (procSym, lhstok, lhs, type, rhstok, rhs: CARDINAL;
+ warning: BOOLEAN;
+ lst: List; i: CARDINAL) ;
BEGIN
- CheckDeferredRecordAccess (procSym, rhstok, rhs, FALSE) ;
- CheckDeferredRecordAccess (procSym, rhstok, rhs, TRUE) ;
- SetVarInitialized (lhs, FALSE)
+ CheckDeferredRecordAccess (procSym, rhstok, rhs, FALSE, warning, lst, i) ;
+ CheckDeferredRecordAccess (procSym, rhstok, rhs, TRUE, warning, lst, i) ;
+ SetVarInitialized (lhs, IsVarAParam (rhs))
END CheckIndrX ;
@@ -846,12 +1011,13 @@ END CheckRecordField ;
CheckBecomes -
*)
-PROCEDURE CheckBecomes (procSym, destok, des, exprtok, expr: CARDINAL) ;
+PROCEDURE CheckBecomes (procSym, destok, des, exprtok, expr: CARDINAL;
+ warning: BOOLEAN; bblst: List; i: CARDINAL) ;
VAR
lst : List ;
vsym: CARDINAL ;
BEGIN
- CheckDeferredRecordAccess (procSym, exprtok, expr, FALSE) ;
+ CheckDeferredRecordAccess (procSym, exprtok, expr, FALSE, warning, bblst, i) ;
SetupAlias (des, expr) ;
SetVarInitialized (des, FALSE) ;
(* Now see if we know what lhs is pointing to and set fields if necessary. *)
@@ -872,10 +1038,11 @@ END CheckBecomes ;
CheckComparison -
*)
-PROCEDURE CheckComparison (procSym, op1tok, op1, op2tok, op2: CARDINAL) ;
+PROCEDURE CheckComparison (procSym, op1tok, op1, op2tok, op2: CARDINAL;
+ warning: BOOLEAN; lst: List; i: CARDINAL) ;
BEGIN
- CheckDeferredRecordAccess (procSym, op1tok, op1, FALSE) ;
- CheckDeferredRecordAccess (procSym, op2tok, op2, FALSE)
+ CheckDeferredRecordAccess (procSym, op1tok, op1, FALSE, warning, lst, i) ;
+ CheckDeferredRecordAccess (procSym, op2tok, op2, FALSE, warning, lst, i)
END CheckComparison ;
@@ -916,7 +1083,8 @@ END stop ;
CheckReadBeforeInitQuad -
*)
-PROCEDURE CheckReadBeforeInitQuad (procSym: CARDINAL; quad: CARDINAL) : BOOLEAN ;
+PROCEDURE CheckReadBeforeInitQuad (procSym: CARDINAL; quad: CARDINAL;
+ warning: BOOLEAN; lst: List; i: CARDINAL) : BOOLEAN ;
VAR
op : QuadOperator ;
op1, op2, op3 : CARDINAL ;
@@ -949,7 +1117,7 @@ BEGIN
IfLessOp,
IfLessEquOp,
IfGreOp,
- IfGreEquOp : CheckComparison (procSym, op1tok, op1, op2tok, op2) |
+ IfGreEquOp : CheckComparison (procSym, op1tok, op1, op2tok, op2, warning, lst, i) |
TryOp,
ReturnOp,
CallOp,
@@ -960,26 +1128,27 @@ BEGIN
(* Variable references. *)
InclOp,
- ExclOp : CheckDeferredRecordAccess (procSym, op1tok, op1, FALSE) ;
- CheckDeferredRecordAccess (procSym, op1tok, op1, TRUE) ;
- CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE) |
- NegateOp : CheckUnary (procSym, op1tok, op1, op3tok, op3) |
- BecomesOp : CheckBecomes (procSym, op1tok, op1, op3tok, op3) |
+ ExclOp : CheckDeferredRecordAccess (procSym, op1tok, op1, FALSE, warning, lst, i) ;
+ CheckDeferredRecordAccess (procSym, op1tok, op1, TRUE, warning, lst, i) ;
+ CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE, warning, lst, i) |
+ NegateOp : CheckUnary (procSym, op1tok, op1, op3tok, op3, warning, lst, i) |
+ BecomesOp : CheckBecomes (procSym, op1tok, op1, op3tok, op3, warning, lst, i) |
UnboundedOp,
FunctValueOp,
+ StandardFunctionOp,
HighOp,
SizeOp : SetVarInitialized (op1, FALSE) |
AddrOp : CheckAddr (procSym, op1tok, op1, op3tok, op3) |
ReturnValueOp : SetVarInitialized (op1, FALSE) |
NewLocalVarOp : |
- ParamOp : CheckDeferredRecordAccess (procSym, op2tok, op2, FALSE) ;
- CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE) ;
+ ParamOp : CheckDeferredRecordAccess (procSym, op2tok, op2, FALSE, warning, lst, i) ;
+ CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE, warning, lst, i) ;
IF (op1 > 0) AND (op1 <= NoOfParam (op2)) AND
IsVarParam (op2, op1)
THEN
SetVarInitialized (op3, TRUE)
END |
- ArrayOp : CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE) ;
+ ArrayOp : CheckDeferredRecordAccess (procSym, op3tok, op3, FALSE, warning, lst, i) ;
SetVarInitialized (op1, TRUE) |
RecordFieldOp : CheckRecordField (procSym, op1tok, op1, op2tok, op2) |
LogicalShiftOp,
@@ -1002,14 +1171,43 @@ BEGIN
DivFloorOp,
ModTruncOp,
DivTruncOp : CheckBinary (procSym,
- op1tok, op1, op2tok, op2, op3tok, op3) |
- XIndrOp : CheckXIndr (procSym, op1tok, op1, op2, op3tok, op3) |
- IndrXOp : CheckIndrX (procSym, op1tok, op1, op2, op3tok, op3) |
- RangeCheckOp : |
+ op1tok, op1, op2tok, op2, op3tok, op3, warning, lst, i) |
+ XIndrOp : CheckXIndr (procSym, op1tok, op1, op2, op3tok, op3, warning, lst, i) |
+ IndrXOp : CheckIndrX (procSym, op1tok, op1, op2, op3tok, op3, warning, lst, i) |
SaveExceptionOp : SetVarInitialized (op1, FALSE) |
- RestoreExceptionOp: CheckDeferredRecordAccess (procSym, op1tok, op1, FALSE)
+ RestoreExceptionOp: CheckDeferredRecordAccess (procSym, op1tok, op1, FALSE, warning, lst, i) |
+
+ SubrangeLowOp,
+ SubrangeHighOp : InternalError ('quadruples should have been resolved') |
+ ElementSizeOp,
+ BuiltinConstOp, (* Nothing to do, it is assigning a constant to op1 (also a const). *)
+ BuiltinTypeInfoOp, (* Likewise assigning op1 (const) with a type. *)
+ ProcedureScopeOp,
+ InitEndOp,
+ InitStartOp,
+ FinallyStartOp,
+ FinallyEndOp,
+ CatchBeginOp,
+ CatchEndOp,
+ ThrowOp,
+ StartDefFileOp,
+ StartModFileOp,
+ EndFileOp,
+ CodeOnOp,
+ CodeOffOp,
+ ProfileOnOp,
+ ProfileOffOp,
+ OptimizeOnOp,
+ OptimizeOffOp,
+ InlineOp,
+ LineNumberOp,
+ StatementNoteOp,
+ SavePriorityOp,
+ RestorePriorityOp,
+ RangeCheckOp,
+ ModuleScopeOp,
+ ErrorOp : |
- ELSE
END ;
RETURN FALSE
END CheckReadBeforeInitQuad ;
@@ -1019,7 +1217,9 @@ END CheckReadBeforeInitQuad ;
FilterCheckReadBeforeInitQuad -
*)
-PROCEDURE FilterCheckReadBeforeInitQuad (procSym: CARDINAL; start: CARDINAL) : BOOLEAN ;
+PROCEDURE FilterCheckReadBeforeInitQuad (procSym: CARDINAL; start: CARDINAL;
+ warning: BOOLEAN;
+ lst: List; i: CARDINAL) : BOOLEAN ;
VAR
Op : QuadOperator ;
Op1, Op2, Op3: CARDINAL ;
@@ -1027,7 +1227,7 @@ BEGIN
GetQuad (start, Op, Op1, Op2, Op3) ;
IF (Op # RangeCheckOp) AND (Op # StatementNoteOp)
THEN
- RETURN CheckReadBeforeInitQuad (procSym, start)
+ RETURN CheckReadBeforeInitQuad (procSym, start, warning, lst, i)
END ;
RETURN FALSE
END FilterCheckReadBeforeInitQuad ;
@@ -1038,43 +1238,366 @@ END FilterCheckReadBeforeInitQuad ;
*)
PROCEDURE CheckReadBeforeInitFirstBasicBlock (procSym: CARDINAL;
- start, end: CARDINAL) ;
+ start, end: CARDINAL;
+ warning: BOOLEAN;
+ lst: List; i: CARDINAL) ;
BEGIN
- ForeachLocalSymDo (procSym, SetVarUninitialized) ;
LOOP
- IF FilterCheckReadBeforeInitQuad (procSym, start) OR (start = end)
+ IF FilterCheckReadBeforeInitQuad (procSym, start, warning, lst, i)
THEN
- RETURN
END ;
- start := GetNextQuad (start)
+ IF start = end
+ THEN
+ RETURN
+ ELSE
+ start := GetNextQuad (start)
+ END
END
END CheckReadBeforeInitFirstBasicBlock ;
(*
- VariableAnalysis - checks to see whether a variable is:
+ bbArrayKill -
+*)
+
+PROCEDURE bbArrayKill ;
+VAR
+ i, h : CARDINAL ;
+ bbPtr: bbEntry ;
+BEGIN
+ h := Indexing.HighIndice (bbArray) ;
+ i := 1 ;
+ WHILE i <= h DO
+ bbPtr := Indexing.GetIndice (bbArray, i) ;
+ bbPtr^.next := bbFreeList ;
+ bbFreeList := bbPtr ;
+ INC (i)
+ END ;
+ bbArray := Indexing.KillIndex (bbArray)
+END bbArrayKill ;
- read before it has been initialized
+
+(*
+ DumpBBEntry -
*)
-PROCEDURE VariableAnalysis (Start, End: CARDINAL) ;
+PROCEDURE DumpBBEntry (bbPtr: bbEntry; procSym: CARDINAL) ;
+BEGIN
+ printf4 ("bb %d: scope %d: quads: %d .. %d",
+ bbPtr^.indexBB, procSym, bbPtr^.start, bbPtr^.end) ;
+ IF bbPtr^.first
+ THEN
+ printf0 (" first")
+ END ;
+ IF bbPtr^.endCall
+ THEN
+ printf0 (" endcall")
+ END ;
+ IF bbPtr^.endGoto
+ THEN
+ printf0 (" endgoto")
+ END ;
+ IF bbPtr^.endCond
+ THEN
+ printf0 (" endcond")
+ END ;
+ IF bbPtr^.topOfLoop
+ THEN
+ printf0 (" topofloop")
+ END ;
+ IF bbPtr^.condBB # 0
+ THEN
+ printf1 (" cond %d", bbPtr^.condBB)
+ END ;
+ IF bbPtr^.nextBB # 0
+ THEN
+ printf1 (" next %d", bbPtr^.nextBB)
+ END ;
+ printf0 ("\n")
+END DumpBBEntry ;
+
+
+(*
+ DumpBBArray -
+*)
+
+PROCEDURE DumpBBArray (procSym: CARDINAL) ;
VAR
- Op : QuadOperator ;
- Op1, Op2, Op3: CARDINAL ;
+ bbPtr: bbEntry ;
+ i, n : CARDINAL ;
BEGIN
- IF UninitVariableChecking
+ i := 1 ;
+ n := Indexing.HighIndice (bbArray) ;
+ WHILE i <= n DO
+ bbPtr := Indexing.GetIndice (bbArray, i) ;
+ DumpBBEntry (bbPtr, procSym) ;
+ INC (i)
+ END ;
+ i := 1 ;
+ WHILE i <= n DO
+ bbPtr := Indexing.GetIndice (bbArray, i) ;
+ printf4 ("bb %d: scope %d: quads: %d .. %d\n",
+ bbPtr^.indexBB, procSym, bbPtr^.start, bbPtr^.end) ;
+ DisplayQuadRange (procSym, bbPtr^.start, bbPtr^.end) ;
+ INC (i)
+ END
+END DumpBBArray ;
+
+
+(*
+ DumpBBSequence -
+*)
+
+PROCEDURE DumpBBSequence (procSym: CARDINAL; lst: List) ;
+VAR
+ arrayindex,
+ listindex, n: CARDINAL ;
+BEGIN
+ n := NoOfItemsInList (lst) ;
+ listindex := 1 ;
+ printf0 ("=============\n");
+ printf0 (" checking sequence:");
+ WHILE listindex <= n DO
+ arrayindex := GetItemFromList (lst, listindex) ;
+ printf1 (" [%d]", listindex) ;
+ INC (listindex)
+ END ;
+ printf0 ("\n")
+END DumpBBSequence ;
+
+
+(*
+ TestBBSequence -
+*)
+
+PROCEDURE TestBBSequence (procSym: CARDINAL; lst: List) ;
+VAR
+ bbPtr : bbEntry ;
+ bbi,
+ i, n : CARDINAL ;
+ warning: BOOLEAN ; (* Should we issue a warning rather than a note? *)
+BEGIN
+ IF Debugging
THEN
- GetQuad (Start, Op, Op1, Op2, Op3) ;
- CASE Op OF
+ DumpBBSequence (procSym, lst)
+ END ;
+ ForeachLocalSymDo (procSym, SetVarUninitialized) ;
+ initBlock ;
+ n := NoOfItemsInList (lst) ;
+ i := 1 ;
+ warning := TRUE ;
+ WHILE i <= n DO
+ bbi := GetItemFromList (lst, i) ;
+ bbPtr := Indexing.GetIndice (bbArray, bbi) ;
+ CheckReadBeforeInitFirstBasicBlock (procSym, bbPtr^.start, bbPtr^.end, warning, lst, i) ;
+ IF bbPtr^.endCond
+ THEN
+ (* Check to see if we are moving into an conditional block in which case
+ we will issue a note. *)
+ warning := FALSE
+ END ;
+ INC (i)
+ END ;
+ killBlock
+END TestBBSequence ;
- NewLocalVarOp: initBlock ;
- CheckReadBeforeInitFirstBasicBlock (Op3, Start, End) ;
- killBlock
+(*
+ CreateBBPermultations -
+*)
+
+PROCEDURE CreateBBPermultations (procSym: CARDINAL; i: CARDINAL; lst: List) ;
+VAR
+ duplst: List ;
+ iPtr : bbEntry ;
+BEGIN
+ IF i = 0
+ THEN
+ TestBBSequence (procSym, lst)
+ ELSE
+ iPtr := Indexing.GetIndice (bbArray, i) ;
+ IF iPtr^.topOfLoop
+ THEN
+ TestBBSequence (procSym, lst)
ELSE
+ duplst := DuplicateList (lst) ;
+ IncludeItemIntoList (duplst, i) ;
+ IF iPtr^.endCall
+ THEN
+ TestBBSequence (procSym, duplst)
+ ELSIF iPtr^.endGoto
+ THEN
+ CreateBBPermultations (procSym, iPtr^.nextBB, duplst)
+ ELSIF UninitVariableConditionalChecking AND iPtr^.endCond
+ THEN
+ CreateBBPermultations (procSym, iPtr^.nextBB, duplst) ;
+ CreateBBPermultations (procSym, iPtr^.condBB, duplst)
+ ELSIF iPtr^.endCond
+ THEN
+ TestBBSequence (procSym, duplst)
+ ELSE
+ (* Fall through. *)
+ CreateBBPermultations (procSym, iPtr^.nextBB, duplst)
+ END ;
+ KillList (duplst)
END
END
-END VariableAnalysis ;
+END CreateBBPermultations ;
+
+
+(*
+ ScopeBlockVariableAnalysis - checks to see whether a variable is
+ read before it has been initialized.
+*)
+
+PROCEDURE ScopeBlockVariableAnalysis (Scope: CARDINAL;
+ Start, End: CARDINAL) ;
+VAR
+ bb : BasicBlock ;
+ lst: List ;
+BEGIN
+ IF UninitVariableChecking
+ THEN
+ bbArray := Indexing.InitIndex (1) ;
+ bb := InitBasicBlocksFromRange (Scope, Start, End) ;
+ ForeachBasicBlockDo (bb, AppendEntry) ;
+ KillBasicBlocks (bb) ;
+ GenerateCFG ;
+ IF Scope # NulSym
+ THEN
+ InitList (lst) ;
+ IF Debugging
+ THEN
+ DumpBBArray (Scope) ;
+ IF UninitVariableConditionalChecking
+ THEN
+ printf0 ("UninitVariableConditionalChecking is TRUE\n")
+ END
+ END ;
+ CreateBBPermultations (Scope, 1, lst) ;
+ KillList (lst)
+ END ;
+ bbArrayKill
+ END
+END ScopeBlockVariableAnalysis ;
+
+
+(*
+ GetOp3 -
+*)
+
+PROCEDURE GetOp3 (quad: CARDINAL) : CARDINAL ;
+VAR
+ op: QuadOperator ;
+ op1, op2, op3: CARDINAL ;
+BEGIN
+ GetQuad (quad, op, op1, op2, op3) ;
+ RETURN op3
+END GetOp3 ;
+
+
+(*
+ getBBindex - return the basic block index which starts with quad.
+*)
+
+PROCEDURE getBBindex (quad: CARDINAL) : CARDINAL ;
+VAR
+ iPtr : bbEntry ;
+ i, high: CARDINAL ;
+BEGIN
+ i := 1 ;
+ high := Indexing.HighIndice (bbArray) ;
+ WHILE i <= high DO
+ iPtr := Indexing.GetIndice (bbArray, i) ;
+ IF iPtr^.start = quad
+ THEN
+ RETURN iPtr^.indexBB
+ END ;
+ INC (i)
+ END ;
+ RETURN 0
+END getBBindex ;
+
+
+(*
+ GenerateCFG -
+*)
+
+PROCEDURE GenerateCFG ;
+VAR
+ iPtr : bbEntry ;
+ next,
+ i, high: CARDINAL ;
+BEGIN
+ i := 1 ;
+ high := Indexing.HighIndice (bbArray) ;
+ WHILE i <= high DO
+ iPtr := Indexing.GetIndice (bbArray, i) ;
+ IF IsKillLocalVar (iPtr^.end) OR IsReturn (iPtr^.end)
+ THEN
+ (* Nothing to do as we have reached the end of this scope. *)
+ ELSE
+ next := GetNextQuad (iPtr^.end) ;
+ iPtr^.nextQuad := next ;
+ iPtr^.nextBB := getBBindex (next) ;
+ IF iPtr^.endCond
+ THEN
+ iPtr^.condQuad := GetOp3 (iPtr^.end) ;
+ iPtr^.condBB := getBBindex (iPtr^.condQuad)
+ END
+ END ;
+ INC (i)
+ END
+END GenerateCFG ;
+
+
+(*
+ NewEntry -
+*)
+
+PROCEDURE NewEntry () : bbEntry ;
+VAR
+ bbPtr: bbEntry ;
+BEGIN
+ IF bbFreeList = NIL
+ THEN
+ NEW (bbPtr)
+ ELSE
+ bbPtr := bbFreeList ;
+ bbFreeList := bbFreeList^.next
+ END ;
+ RETURN bbPtr
+END NewEntry ;
+
+
+(*
+ AppendEntry -
+*)
+
+PROCEDURE AppendEntry (Start, End: CARDINAL) ;
+VAR
+ bbPtr: bbEntry ;
+ high : CARDINAL ;
+BEGIN
+ high := Indexing.HighIndice (bbArray) ;
+ bbPtr := NewEntry () ;
+ WITH bbPtr^ DO
+ start := Start ;
+ end := End ;
+ first := high = 0 ;
+ endCall := IsCall (End) ;
+ endGoto := IsGoto (End) ;
+ endCond := IsConditional (End) ;
+ topOfLoop := IsBackReference (Start) ;
+ indexBB := high + 1 ;
+ nextQuad := 0 ;
+ condQuad := 0 ;
+ nextBB := 0 ;
+ condBB := 0 ;
+ next := NIL
+ END ;
+ Indexing.PutIndice (bbArray, high + 1, bbPtr)
+END AppendEntry ;
(*
@@ -1298,7 +1821,9 @@ END SetupAlias ;
PROCEDURE init ;
BEGIN
- freeList := NIL
+ freeList := NIL ;
+ bbFreeList := NIL ;
+ InitList (errorList)
END init ;
diff --git a/gcc/m2/gm2-compiler/SymbolTable.def b/gcc/m2/gm2-compiler/SymbolTable.def
index c861cff..8c4feed 100644
--- a/gcc/m2/gm2-compiler/SymbolTable.def
+++ b/gcc/m2/gm2-compiler/SymbolTable.def
@@ -158,6 +158,7 @@ EXPORT QUALIFIED NulSym,
PutDefLink,
PutModLink,
PutModuleBuiltin,
+ PutVarArrayRef, IsVarArrayRef,
PutConstSet,
PutConstructor,
@@ -3562,6 +3563,20 @@ PROCEDURE PutModuleBuiltin (sym: CARDINAL; value: BOOLEAN) ;
(*
+ PutVarArrayRef - assigns ArrayRef field with value.
+*)
+
+PROCEDURE PutVarArrayRef (sym: CARDINAL; value: BOOLEAN) ;
+
+
+(*
+ IsVarArrayRef - returns ArrayRef field value.
+*)
+
+PROCEDURE IsVarArrayRef (sym: CARDINAL) : BOOLEAN ;
+
+
+(*
VarCheckReadInit - returns TRUE if sym has been initialized.
*)
diff --git a/gcc/m2/gm2-compiler/SymbolTable.mod b/gcc/m2/gm2-compiler/SymbolTable.mod
index c10e20c..73528b5 100644
--- a/gcc/m2/gm2-compiler/SymbolTable.mod
+++ b/gcc/m2/gm2-compiler/SymbolTable.mod
@@ -525,6 +525,8 @@ TYPE
IsWritten : BOOLEAN ; (* Is variable written to? *)
IsSSA : BOOLEAN ; (* Is variable a SSA? *)
IsConst : BOOLEAN ; (* Is variable read/only? *)
+ ArrayRef : BOOLEAN ; (* Is variable used to point *)
+ (* to an array? *)
InitState : LRInitDesc ; (* Initialization state. *)
At : Where ; (* Where was sym declared/used *)
ReadUsageList, (* list of var read quads *)
@@ -4260,6 +4262,7 @@ BEGIN
IsWritten := FALSE ;
IsSSA := FALSE ;
IsConst := FALSE ;
+ ArrayRef := FALSE ;
InitWhereDeclaredTok(tok, At) ;
InitWhereFirstUsedTok(tok, At) ; (* Where symbol first used. *)
InitList(ReadUsageList[RightValue]) ;
@@ -6905,6 +6908,48 @@ END PutConst ;
(*
+ PutVarArrayRef - assigns ArrayRef field with value.
+*)
+
+PROCEDURE PutVarArrayRef (sym: CARDINAL; value: BOOLEAN) ;
+VAR
+ pSym: PtrToSymbol ;
+BEGIN
+ pSym := GetPsym(sym) ;
+ WITH pSym^ DO
+ CASE SymbolType OF
+
+ VarSym: Var.ArrayRef := value
+
+ ELSE
+ InternalError ('expecting VarSym')
+ END
+ END
+END PutVarArrayRef ;
+
+
+(*
+ IsVarArrayRef - returns ArrayRef field value.
+*)
+
+PROCEDURE IsVarArrayRef (sym: CARDINAL) : BOOLEAN ;
+VAR
+ pSym: PtrToSymbol ;
+BEGIN
+ pSym := GetPsym(sym) ;
+ WITH pSym^ DO
+ CASE SymbolType OF
+
+ VarSym: RETURN (Var.ArrayRef)
+
+ ELSE
+ InternalError ('expecting VarSym')
+ END
+ END
+END IsVarArrayRef ;
+
+
+(*
PutFieldRecord - places a field, FieldName and FieldType into a record, Sym.
VarSym is a optional varient symbol which can be returned
by a call to GetVarient(fieldsymbol). The created field
diff --git a/gcc/m2/gm2-gcc/init.cc b/gcc/m2/gm2-gcc/init.cc
index 834a84e..7bf79cc 100644
--- a/gcc/m2/gm2-gcc/init.cc
+++ b/gcc/m2/gm2-gcc/init.cc
@@ -103,6 +103,7 @@ EXTERN void _M2_dtoa_init (int argc, char *argv[], char *envp[]);
EXTERN void _M2_ldtoa_init (int argc, char *argv[], char *envp[]);
EXTERN void _M2_M2Check_init (int argc, char *argv[], char *envp[]);
EXTERN void _M2_M2SSA_init (int argc, char *argv[], char *envp[]);
+EXTERN void _M2_M2SymInit_init (int argc, char *argv[], char *envp[]);
EXTERN void exit (int);
EXTERN void M2Comp_compile (const char *filename);
EXTERN void RTExceptions_DefaultErrorCatch (void);
@@ -195,6 +196,7 @@ init_PerCompilationInit (const char *filename)
_M2_PCBuild_init (0, NULL, NULL);
_M2_Sets_init (0, NULL, NULL);
_M2_M2SSA_init (0, NULL, NULL);
+ _M2_M2SymInit_init (0, NULL, NULL);
_M2_M2Check_init (0, NULL, NULL);
M2Comp_compile (filename);
}
diff --git a/gcc/m2/gm2-gcc/m2options.h b/gcc/m2/gm2-gcc/m2options.h
index e203fce4..dd79509 100644
--- a/gcc/m2/gm2-gcc/m2options.h
+++ b/gcc/m2/gm2-gcc/m2options.h
@@ -136,7 +136,7 @@ EXTERN void M2Options_SetM2Prefix (const char *arg);
EXTERN char *M2Options_GetM2Prefix (void);
EXTERN void M2Options_SetM2PathName (const char *arg);
EXTERN char *M2Options_GetM2PathName (void);
-EXTERN void M2Options_SetUninitVariableChecking (bool value);
+EXTERN int M2Options_SetUninitVariableChecking (bool value, const char *arg);
#undef EXTERN
diff --git a/gcc/m2/gm2-lang.cc b/gcc/m2/gm2-lang.cc
index ae999a3..c21d29b 100644
--- a/gcc/m2/gm2-lang.cc
+++ b/gcc/m2/gm2-lang.cc
@@ -470,8 +470,9 @@ gm2_langhook_handle_option (
M2Options_SetUnusedParameterChecking (value);
return 1;
case OPT_Wuninit_variable_checking:
- M2Options_SetUninitVariableChecking (value);
- return 1;
+ return M2Options_SetUninitVariableChecking (value, "known");
+ case OPT_Wuninit_variable_checking_:
+ return M2Options_SetUninitVariableChecking (value, arg);
case OPT_fm2_strict_type:
M2Options_SetStrictTypeChecking (value);
return 1;
diff --git a/gcc/m2/lang.opt b/gcc/m2/lang.opt
index 6dbdf9d..730a1a2 100644
--- a/gcc/m2/lang.opt
+++ b/gcc/m2/lang.opt
@@ -297,6 +297,10 @@ Wuninit-variable-checking
Modula-2
turns on compile time analysis in the first basic block of a procedure detecting access to uninitialized data.
+Wuninit-variable-checking=
+Modula-2 Joined
+turns on compile time analysis to detect access to uninitialized variables, the checking can be specified by: known,cond,all.
+
B
Modula-2
; Documented in c.opt
diff --git a/gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/cascadedif.mod b/gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/cascadedif.mod
new file mode 100644
index 0000000..4468ce0
--- /dev/null
+++ b/gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/cascadedif.mod
@@ -0,0 +1,25 @@
+MODULE cascadedif ;
+
+
+PROCEDURE test ;
+VAR
+ i: CARDINAL ;
+ p: CARDINAL ;
+BEGIN
+ i := 1 ;
+ IF i = 1
+ THEN
+ IF p = 1
+ THEN
+ END
+ ELSE
+ IF p = 2
+ THEN
+ END
+ END
+END test ;
+
+
+BEGIN
+ test
+END cascadedif.
diff --git a/gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/switches-uninit-variable-checking-cascade-fail.exp b/gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/switches-uninit-variable-checking-cascade-fail.exp
new file mode 100644
index 0000000..f5e0c07
--- /dev/null
+++ b/gcc/testsuite/gm2/switches/uninit-variable-checking/cascade/fail/switches-uninit-variable-checking-cascade-fail.exp
@@ -0,0 +1,37 @@
+# Expect driver script for GCC Regression Tests
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file was written by Gaius Mulley (gaius.mulley@southwales.ac.uk)
+# for GNU Modula-2.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# load support procs
+load_lib gm2-torture.exp
+
+gm2_init_pim "${srcdir}/gm2/switches/uninit-variable-checking/cascade/fail" -Wuninit-variable-checking=all
+
+foreach testcase [lsort [glob -nocomplain $srcdir/$subdir/*.mod]] {
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $testcase] then {
+ continue
+ }
+
+ gm2-torture-fail $testcase
+}