aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaius Mulley <gaiusmod2@gmail.com>2024-07-23 15:54:16 +0100
committerGaius Mulley <gaiusmod2@gmail.com>2024-07-23 15:54:16 +0100
commit7f8064ff0e2ac90c5bb6c30cc61acc5a28ebbe4c (patch)
tree6d9caf1a7bb5f61b74a1bed221835fe3abc03f76
parent826134760c49518d97769c8bb7ecbc264b78cac9 (diff)
downloadgcc-7f8064ff0e2ac90c5bb6c30cc61acc5a28ebbe4c.zip
gcc-7f8064ff0e2ac90c5bb6c30cc61acc5a28ebbe4c.tar.gz
gcc-7f8064ff0e2ac90c5bb6c30cc61acc5a28ebbe4c.tar.bz2
PR modula2/116048 ICE when encountering wrong kind of qualident
Following on from PR-115957 further ICEs can be generated by using the wrong kind of qualident symbol. For example using a variable instead of a type or using a type instead of a const. This fix tracks the expected qualident kind state when parsing const, type and variable declarations. If the error is unrecoverable then a detailed message explaining the context of the qualident (and why the seen qualident is wrong) is generated. gcc/m2/ChangeLog: PR modula2/116048 * Make-lang.in (GM2-COMP-BOOT-DEFS): Add M2StateCheck.def. (GM2-COMP-BOOT-MODS): Add M2StateCheck.mod. (GM2-COMP-DEFS): Add M2StateCheck.def. (GM2-COMP-MODS): Add M2StateCheck.mod. * gm2-compiler/M2Quads.mod (StartBuildWith): Generate unrecoverable error is the qualident type is NulSym. Replace MetaError1 with MetaErrorT1 and position the error to the qualident. * gm2-compiler/P3Build.bnf (M2StateCheck): Import procedures. (seenError): New variable. (WasNoError): Remove variable. (BlockState): New variable. (ErrorString): Rewrite using seenError. (CompilationUnit): Ditto. (QualidentCheck): New rule. (ConstantDeclaration): Bookend with InclConst and ExclConst. (Constructor): Add InclConstructor, ExclConstructor and call CheckQualident. (ConstActualParameters): Call PushState, PopState, InclConstFunc and CheckQualident. (TypeDeclaration): Bookend with InclType and ExclType. (SimpleType): Call QualidentCheck. (CaseTag): Ditto. (OptReturnType): Ditto. (VariableDeclaration): Bookend with InclVar and ExclVar. (Designator): Call QualidentCheck. (Formal;Type): Ditto. * gm2-compiler/PCBuild.bnf (M2StateCheck): Import procedures. (ConstantDeclaration): Rewrite using InclConst and ExclConst. (Constructor): Bookend with InclConstructor and ExclConstructor. Call CheckQualident. (ConstructorOrConstActualParameters): Rewrite and cal l CheckQualident. (ConstActualParameters): Bookend with PushState PopState. Call InclConstFunc and CheckQualident. * gm2-gcc/init.cc (_M2_M2StateCheck_init): New declaration. (_M2_P3Build_init): New declaration. (init_PerCompilationInit): Call _M2_M2StateCheck_init and _M2_P3Build_init. * gm2-compiler/M2StateCheck.def: New file. * gm2-compiler/M2StateCheck.mod: New file. gcc/testsuite/ChangeLog: PR modula2/116048 * gm2/errors/fail/errors-fail.exp: Remove -Wstudents and add -Wuninit-variable-checking=all. Replace gm2_init_pim with gm2_init_iso. * gm2/errors/fail/testfio.mod: Modify test code to provoke an error in the first basic block. * gm2/errors/fail/testparam.mod: Ditto. * gm2/errors/fail/array1.mod: Ditto. * gm2/errors/fail/badtype.mod: New test. * gm2/errors/fail/badvar.mod: New test. Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>
-rw-r--r--gcc/m2/Make-lang.in4
-rw-r--r--gcc/m2/gm2-compiler/M2Quads.mod45
-rw-r--r--gcc/m2/gm2-compiler/M2StateCheck.def154
-rw-r--r--gcc/m2/gm2-compiler/M2StateCheck.mod344
-rw-r--r--gcc/m2/gm2-compiler/P3Build.bnf65
-rw-r--r--gcc/m2/gm2-compiler/PCBuild.bnf45
-rw-r--r--gcc/m2/gm2-gcc/init.cc4
-rw-r--r--gcc/testsuite/gm2/errors/fail/array1.mod5
-rw-r--r--gcc/testsuite/gm2/errors/fail/badtype.mod10
-rw-r--r--gcc/testsuite/gm2/errors/fail/badvar.mod10
-rw-r--r--gcc/testsuite/gm2/errors/fail/errors-fail.exp2
-rw-r--r--gcc/testsuite/gm2/errors/fail/testfio.mod8
-rw-r--r--gcc/testsuite/gm2/errors/fail/testparam.mod5
13 files changed, 645 insertions, 56 deletions
diff --git a/gcc/m2/Make-lang.in b/gcc/m2/Make-lang.in
index daa7ef6..2bd60ca 100644
--- a/gcc/m2/Make-lang.in
+++ b/gcc/m2/Make-lang.in
@@ -808,6 +808,7 @@ GM2-COMP-BOOT-DEFS = \
M2Size.def \
M2StackAddress.def \
M2StackWord.def \
+ M2StateCheck.def \
M2Students.def \
M2Swig.def \
M2SymInit.def \
@@ -882,6 +883,7 @@ GM2-COMP-BOOT-MODS = \
M2Size.mod \
M2StackAddress.mod \
M2StackWord.mod \
+ M2StateCheck.mod \
M2Students.mod \
M2Swig.mod \
M2SymInit.mod \
@@ -1090,6 +1092,7 @@ GM2-COMP-DEFS = \
M2Size.def \
M2StackAddress.def \
M2StackWord.def \
+ M2StateCheck.def \
M2Students.def \
M2Swig.def \
M2SymInit.def \
@@ -1161,6 +1164,7 @@ GM2-COMP-MODS = \
M2Size.mod \
M2StackAddress.mod \
M2StackWord.mod \
+ M2StateCheck.mod \
M2Students.mod \
M2Swig.mod \
M2SymInit.mod \
diff --git a/gcc/m2/gm2-compiler/M2Quads.mod b/gcc/m2/gm2-compiler/M2Quads.mod
index 6476806..6230bf7 100644
--- a/gcc/m2/gm2-compiler/M2Quads.mod
+++ b/gcc/m2/gm2-compiler/M2Quads.mod
@@ -12068,31 +12068,34 @@ BEGIN
PopTFtok (Sym, Type, tok) ;
DebugLocation (tok, "expression") ;
Type := SkipType (Type) ;
-
- Ref := MakeTemporary (tok, LeftValue) ;
- PutVar (Ref, Type) ;
- IF GetMode (Sym) = LeftValue
+ IF Type = NulSym
THEN
- (* Copy LeftValue. *)
- GenQuadO (tok, BecomesOp, Ref, NulSym, Sym, TRUE)
+ MetaErrorT1 (tok,
+ '{%1Aa} {%1d} has a no type, the {%kWITH} statement requires a variable or parameter of a {%kRECORD} type',
+ Sym)
ELSE
- (* Calculate the address of Sym. *)
- GenQuadO (tok, AddrOp, Ref, NulSym, Sym, TRUE)
- END ;
+ Ref := MakeTemporary (tok, LeftValue) ;
+ PutVar (Ref, Type) ;
+ IF GetMode (Sym) = LeftValue
+ THEN
+ (* Copy LeftValue. *)
+ GenQuadO (tok, BecomesOp, Ref, NulSym, Sym, TRUE)
+ ELSE
+ (* Calculate the address of Sym. *)
+ GenQuadO (tok, AddrOp, Ref, NulSym, Sym, TRUE)
+ END ;
- PushWith (Sym, Type, Ref, tok) ;
- DebugLocation (tok, "with ref") ;
- IF Type = NulSym
- THEN
- MetaError1 ('{%1Ea} {%1d} has a no type, the {%kWITH} statement requires a variable or parameter of a {%kRECORD} type',
- Sym)
- ELSIF NOT IsRecord(Type)
- THEN
- MetaError1 ('the {%kWITH} statement requires that {%1Ea} {%1d} be of a {%kRECORD} {%1tsa:type rather than {%1tsa}}',
- Sym)
+ PushWith (Sym, Type, Ref, tok) ;
+ DebugLocation (tok, "with ref") ;
+ IF NOT IsRecord(Type)
+ THEN
+ MetaErrorT1 (tok,
+ 'the {%kWITH} statement requires that {%1Ea} {%1d} be of a {%kRECORD} {%1tsa:type rather than {%1tsa}}',
+ Sym)
+ END ;
+ StartScope (Type)
END ;
- StartScope (Type)
- ; DisplayStack ;
+ DisplayStack ;
END StartBuildWith ;
diff --git a/gcc/m2/gm2-compiler/M2StateCheck.def b/gcc/m2/gm2-compiler/M2StateCheck.def
new file mode 100644
index 0000000..ca597c2
--- /dev/null
+++ b/gcc/m2/gm2-compiler/M2StateCheck.def
@@ -0,0 +1,154 @@
+(* M2StateCheck.def provide state check tracking for declarations.
+
+Copyright (C) 2024 Free Software Foundation, Inc.
+Contributed by Gaius Mulley <gaiusmod2@gmail.com>.
+
+This file is part of GNU Modula-2.
+
+GNU Modula-2 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, or (at your option)
+any later version.
+
+GNU Modula-2 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 GNU Modula-2; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. *)
+
+DEFINITION MODULE M2StateCheck ;
+
+(* This module provides state tracking for VAR, TYPE and CONST
+ declarations. It should be used by any pass creating
+ symbols in these blocks and it will detect a constant
+ being created from a variable, type from a variable,
+ variable from a constant (instead of type) etc. *)
+
+TYPE
+ StateCheck ;
+
+
+(*
+ InitState - returns a new initialized StateCheck.
+*)
+
+PROCEDURE InitState () : StateCheck ;
+
+
+(*
+ KillState - destructor for StateCheck.
+*)
+
+PROCEDURE KillState (VAR s: StateCheck) ;
+
+
+(*
+ PushState - duplicates the StateCheck s and chains the new copy to s.
+ Return the copy.
+*)
+
+PROCEDURE PushState (VAR s: StateCheck) ;
+
+
+(*
+ PopState - pops the current state.
+*)
+
+PROCEDURE PopState (VAR s: StateCheck) ;
+
+
+(*
+ InclVar - s := s + {var}.
+*)
+
+PROCEDURE InclVar (s: StateCheck) ;
+
+
+(*
+ InclConst - s := s + {const}.
+*)
+
+PROCEDURE InclConst (s: StateCheck) ;
+
+
+(*
+ InclType - s := s + {type}.
+*)
+
+PROCEDURE InclType (s: StateCheck) ;
+
+
+(*
+ InclConstFunc - s := s + {constfunc}.
+*)
+
+PROCEDURE InclConstFunc (s: StateCheck) ;
+
+
+(*
+ InclVarParam - s := s + {varparam}.
+*)
+
+PROCEDURE InclVarParam (s: StateCheck) ;
+
+
+(*
+ InclConstructor - s := s + {constructor}.
+*)
+
+PROCEDURE InclConstructor (s: StateCheck) ;
+
+
+(*
+ ExclVar - s := s + {var}.
+*)
+
+PROCEDURE ExclVar (s: StateCheck) ;
+
+
+(*
+ ExclConst - s := s + {const}.
+*)
+
+PROCEDURE ExclConst (s: StateCheck) ;
+
+
+(*
+ ExclType - s := s + {type}.
+*)
+
+PROCEDURE ExclType (s: StateCheck) ;
+
+
+(*
+ ExclConstFunc - s := s + {constfunc}.
+*)
+
+PROCEDURE ExclConstFunc (s: StateCheck) ;
+
+
+(*
+ ExclVarParam - s := s + {varparam}.
+*)
+
+PROCEDURE ExclVarParam (s: StateCheck) ;
+
+
+(*
+ ExclConstructor - s := s - {varparam}.
+*)
+
+PROCEDURE ExclConstructor (s: StateCheck) ;
+
+
+(*
+ CheckQualident - checks to see that qualident sym is allowed in the state s.
+*)
+
+PROCEDURE CheckQualident (tok: CARDINAL; s: StateCheck; sym: CARDINAL) ;
+
+
+END M2StateCheck.
diff --git a/gcc/m2/gm2-compiler/M2StateCheck.mod b/gcc/m2/gm2-compiler/M2StateCheck.mod
new file mode 100644
index 0000000..e53cb17
--- /dev/null
+++ b/gcc/m2/gm2-compiler/M2StateCheck.mod
@@ -0,0 +1,344 @@
+(* M2StateCheck.mod provide state check tracking for declarations.
+
+Copyright (C) 2024 Free Software Foundation, Inc.
+Contributed by Gaius Mulley <gaiusmod2@gmail.com>.
+
+This file is part of GNU Modula-2.
+
+GNU Modula-2 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, or (at your option)
+any later version.
+
+GNU Modula-2 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 GNU Modula-2; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. *)
+
+IMPLEMENTATION MODULE M2StateCheck ;
+
+FROM Storage IMPORT ALLOCATE ;
+FROM M2MetaError IMPORT MetaErrorStringT1 ;
+FROM DynamicStrings IMPORT String, InitString, ConCat, Mark ;
+FROM SymbolTable IMPORT NulSym, IsType, IsVar, IsConst ;
+
+
+TYPE
+ StateCheck = POINTER TO RECORD
+ state: StateSet ;
+ stack,
+ next : StateCheck ;
+ END ;
+
+ State = (const, var, type, constfunc, varparam, constructor) ;
+
+ StateSet = SET OF State ;
+
+VAR
+ FreeList: StateCheck ;
+
+
+(*
+ InitState - returns a new initialized StateCheck.
+*)
+
+PROCEDURE InitState () : StateCheck ;
+VAR
+ s: StateCheck ;
+BEGIN
+ s := New () ;
+ WITH s^ DO
+ state := StateSet {} ;
+ stack := NIL ;
+ next := NIL
+ END ;
+ RETURN s
+END InitState ;
+
+
+(*
+ New - returns an uninitialized StateCheck.
+*)
+
+PROCEDURE New () : StateCheck ;
+VAR
+ s: StateCheck ;
+BEGIN
+ IF FreeList = NIL
+ THEN
+ NEW (s)
+ ELSE
+ s := FreeList ;
+ FreeList := FreeList^.next
+ END ;
+ RETURN s
+END New ;
+
+
+(*
+ PushState - duplicates the StateCheck s and chains the new copy to s.
+ Return the copy.
+*)
+
+PROCEDURE PushState (VAR s: StateCheck) ;
+VAR
+ copy: StateCheck ;
+BEGIN
+ copy := InitState () ;
+ copy^.state := s^.state ;
+ copy^.stack := s ;
+ s := copy
+END PushState ;
+
+
+(*
+ KillState - destructor for StateCheck.
+*)
+
+PROCEDURE KillState (VAR s: StateCheck) ;
+VAR
+ t: StateCheck ;
+BEGIN
+ WHILE s^.stack # NIL DO
+ t := s^.stack ;
+ s^.stack := t^.stack ;
+ Dispose (t)
+ END ;
+ Dispose (s)
+END KillState ;
+
+
+(*
+ Dispose - place s onto the FreeList and set s to NIL.
+*)
+
+PROCEDURE Dispose (VAR s: StateCheck) ;
+BEGIN
+ s^.next := FreeList ;
+ FreeList := s
+END Dispose ;
+
+
+(*
+ InclVar - s := s + {var}.
+*)
+
+PROCEDURE InclVar (s: StateCheck) ;
+BEGIN
+ INCL (s^.state, var)
+END InclVar ;
+
+
+(*
+ InclConst - s := s + {const}.
+*)
+
+PROCEDURE InclConst (s: StateCheck) ;
+BEGIN
+ INCL (s^.state, const)
+END InclConst ;
+
+
+(*
+ InclType - s := s + {type}.
+*)
+
+PROCEDURE InclType (s: StateCheck) ;
+BEGIN
+ INCL (s^.state, type)
+END InclType ;
+
+
+(*
+ InclConstFunc - s := s + {constfunc}.
+*)
+
+PROCEDURE InclConstFunc (s: StateCheck) ;
+BEGIN
+ INCL (s^.state, constfunc)
+END InclConstFunc ;
+
+
+(*
+ InclVarParam - s := s + {varparam}.
+*)
+
+PROCEDURE InclVarParam (s: StateCheck) ;
+BEGIN
+ INCL (s^.state, varparam)
+END InclVarParam ;
+
+
+(*
+ InclConstructor - s := s + {constructor}.
+*)
+
+PROCEDURE InclConstructor (s: StateCheck) ;
+BEGIN
+ INCL (s^.state, constructor)
+END InclConstructor ;
+
+
+(*
+ ExclVar - s := s - {var}.
+*)
+
+PROCEDURE ExclVar (s: StateCheck) ;
+BEGIN
+ EXCL (s^.state, var)
+END ExclVar ;
+
+
+(*
+ ExclConst - s := s - {const}.
+*)
+
+PROCEDURE ExclConst (s: StateCheck) ;
+BEGIN
+ EXCL (s^.state, const)
+END ExclConst ;
+
+
+(*
+ ExclType - s := s - {type}.
+*)
+
+PROCEDURE ExclType (s: StateCheck) ;
+BEGIN
+ EXCL (s^.state, type)
+END ExclType ;
+
+
+(*
+ ExclConstFunc - s := s - {constfunc}.
+*)
+
+PROCEDURE ExclConstFunc (s: StateCheck) ;
+BEGIN
+ EXCL (s^.state, constfunc)
+END ExclConstFunc ;
+
+
+(*
+ ExclVarParam - s := s - {varparam}.
+*)
+
+PROCEDURE ExclVarParam (s: StateCheck) ;
+BEGIN
+ EXCL (s^.state, varparam)
+END ExclVarParam ;
+
+
+(*
+ ExclConstructor - s := s - {varparam}.
+*)
+
+PROCEDURE ExclConstructor (s: StateCheck) ;
+BEGIN
+ EXCL (s^.state, constructor)
+END ExclConstructor ;
+
+
+(*
+ PopState - pops the current state.
+*)
+
+PROCEDURE PopState (VAR s: StateCheck) ;
+VAR
+ t: StateCheck ;
+BEGIN
+ t := s ;
+ s := s^.stack ;
+ t^.stack := NIL ;
+ Dispose (t)
+END PopState ;
+
+
+(*
+ CheckQualident - checks to see that qualident sym is allowed in the state s.
+*)
+
+PROCEDURE CheckQualident (tok: CARDINAL; s: StateCheck; sym: CARDINAL) ;
+BEGIN
+ IF sym = NulSym
+ THEN
+ (* Ignore. *)
+ ELSIF IsType (sym)
+ THEN
+ IF (constfunc IN s^.state) OR (constructor IN s^.state)
+ THEN
+ (* Ok. *)
+ ELSIF const IN s^.state
+ THEN
+ GenerateError (tok, s, sym)
+ END
+ ELSIF IsConst (sym)
+ THEN
+ IF (constfunc IN s^.state) OR (constructor IN s^.state)
+ THEN
+ (* Ok. *)
+ ELSIF (var IN s^.state) OR (type IN s^.state)
+ THEN
+ GenerateError (tok, s, sym)
+ END
+ ELSIF IsVar (sym)
+ THEN
+ IF constfunc IN s^.state
+ THEN
+ (* Ok. *)
+ ELSIF (const IN s^.state) OR (type IN s^.state) OR (var IN s^.state)
+ THEN
+ GenerateError (tok, s, sym)
+ END
+ END
+END CheckQualident ;
+
+
+(*
+ GenerateError - generates an unrecoverable error string based on the state and sym.
+*)
+
+PROCEDURE GenerateError (tok: CARDINAL; s: StateCheck; sym: CARDINAL) ;
+VAR
+ str: String ;
+BEGIN
+ str := InitString ('not expecting a {%1Ad} {%1a: }in a ') ;
+ IF const IN s^.state
+ THEN
+ str := ConCat (str, Mark (InitString ('{%kCONST} block')))
+ ELSIF type IN s^.state
+ THEN
+ str := ConCat (str, Mark (InitString ('{%kTYPE} block')))
+ ELSIF var IN s^.state
+ THEN
+ str := ConCat (str, Mark (InitString ('{%kVAR} block')))
+ END ;
+ IF constfunc IN s^.state
+ THEN
+ str := ConCat (str, Mark (InitString (' and within a constant procedure function actual parameter')))
+ END ;
+ IF constructor IN s^.state
+ THEN
+ str := ConCat (str, Mark (InitString (' and within a constructor')))
+ END ;
+ MetaErrorStringT1 (tok, str, sym)
+END GenerateError ;
+
+
+(*
+ init - initialize the global variables in the module.
+*)
+
+PROCEDURE init ;
+BEGIN
+ FreeList := NIL
+END init ;
+
+
+BEGIN
+ init
+END M2StateCheck.
diff --git a/gcc/m2/gm2-compiler/P3Build.bnf b/gcc/m2/gm2-compiler/P3Build.bnf
index 0cec329..f48b508 100644
--- a/gcc/m2/gm2-compiler/P3Build.bnf
+++ b/gcc/m2/gm2-compiler/P3Build.bnf
@@ -132,6 +132,7 @@ FROM M2Quads IMPORT PushT, PopT, PushTF, PopTF, PopNothing, Annotate,
PushInConstExpression, PopInConstExpression,
PushInConstParameters, PopInConstParameters, IsInConstParameters,
BuildDefaultFieldAlignment, BuildPragmaField,
+ OperandT, OperandTok,
IsAutoPushOn, PushAutoOff, PushAutoOn, PopAuto ;
FROM P3SymBuild IMPORT P3StartBuildProgModule,
@@ -177,6 +178,14 @@ FROM M2Batch IMPORT IsModuleKnown ;
FROM M2CaseList IMPORT BeginCaseList, EndCaseList ;
+FROM M2StateCheck IMPORT StateCheck,
+ InitState, PushState, PopState,
+ InclConst, ExclConst,
+ InclType, ExclType,
+ InclVar, ExclVar,
+ InclConstructor, ExclConstructor,
+ InclConstFunc, CheckQualident ;
+
IMPORT M2Error ;
CONST
@@ -184,19 +193,20 @@ CONST
DebugAsm = FALSE ;
VAR
- WasNoError: BOOLEAN ;
+ seenError : BOOLEAN ;
+ BlockState: StateCheck ;
PROCEDURE ErrorString (s: String) ;
BEGIN
- ErrorStringAt(s, GetTokenNo ()) ;
- WasNoError := FALSE
+ ErrorStringAt (s, GetTokenNo ()) ;
+ seenError := TRUE
END ErrorString ;
PROCEDURE ErrorArray (a: ARRAY OF CHAR) ;
BEGIN
- ErrorString(InitString(a))
+ ErrorString (InitString (a))
END ErrorArray ;
@@ -391,9 +401,9 @@ END Expect ;
PROCEDURE CompilationUnit () : BOOLEAN ;
BEGIN
- WasNoError := TRUE ;
+ seenError := FALSE ;
FileUnit(SetOfStop0{eoftok}, SetOfStop1{}, SetOfStop2{}) ;
- RETURN( WasNoError )
+ RETURN NOT seenError
END CompilationUnit ;
@@ -457,6 +467,8 @@ BEGIN
END Real ;
% module P3Build end
+BEGIN
+ BlockState := InitState ()
END P3Build.
% rules
error 'ErrorArray' 'ErrorString'
@@ -662,12 +674,25 @@ Qualident := % VAR
{ "." Ident } % END %
=:
+
+QualidentCheck := % PushAutoOn %
+ Qualident
+ % PopAuto %
+ % CheckQualident (OperandTok (1), BlockState, OperandT (1)) %
+ % IF NOT IsAutoPushOn ()
+ THEN
+ PopNothing
+ END %
+ =:
+
ConstantDeclaration := % VAR tokno: CARDINAL ; %
+ % InclConst (BlockState) %
% PushAutoOn %
( Ident "=" % tokno := GetTokenNo () -1 %
% BuildConst %
ConstExpression ) % BuildAssignConstant (tokno) %
% PopAuto %
+ % ExclConst (BlockState) %
=:
ConstExpression := % VAR tokpos: CARDINAL ; %
@@ -764,10 +789,14 @@ ArraySetRecordValue := ComponentValue % Bui
Constructor := % VAR tokpos: CARDINAL ; %
% DisplayStack %
+ % InclConstructor (BlockState) %
+ % CheckQualident (OperandTok (1), BlockState, OperandT (1)) %
'{' % tokpos := GetTokenNo () -1 %
% BuildConstructorStart (tokpos) %
[ ArraySetRecordValue ] % BuildConstructorEnd (tokpos, GetTokenNo()) %
- '}' =:
+ '}'
+ % ExclConstructor (BlockState) %
+ =:
ConstSetOrQualidentOrFunction := % VAR tokpos: CARDINAL ; %
% tokpos := GetTokenNo () %
@@ -779,8 +808,12 @@ ConstSetOrQualidentOrFunction := % VAR
Constructor
) =:
-ConstActualParameters := % PushInConstParameters %
+ConstActualParameters := % PushState (BlockState) %
+ % InclConstFunc (BlockState) %
+ % CheckQualident (OperandTok (1), BlockState, OperandT (1)) %
+ % PushInConstParameters %
ActualParameters % PopInConstParameters %
+ % PopState (BlockState) %
=:
ConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "(" % PushAutoOn %
@@ -802,7 +835,9 @@ ByteAlignment := % VAR
Alignment := [ ByteAlignment ] =:
-TypeDeclaration := Ident "=" Type Alignment
+TypeDeclaration := % InclType (BlockState) %
+ Ident "=" Type Alignment
+ % ExclType (BlockState) %
=:
Type :=
@@ -814,7 +849,7 @@ Type :=
| ProcedureType ) % PopAuto %
=:
-SimpleType := Qualident [ SubrangeType ] | Enumeration | SubrangeType =:
+SimpleType := QualidentCheck [ SubrangeType ] | Enumeration | SubrangeType =:
Enumeration := "("
( IdentList
@@ -900,7 +935,7 @@ FieldList := IdentList ":"
TagIdent := [ Ident ] =:
-CaseTag := TagIdent [":" Qualident ] =:
+CaseTag := TagIdent [":" QualidentCheck ] =:
Varient := [ % BeginVarientList %
VarientCaseLabelList ":" FieldListSequence % EndVarientList %
@@ -980,7 +1015,7 @@ FormalTypeList := "(" ( ")" FormalReturn |
FormalReturn := [ ":" OptReturnType ] =:
-OptReturnType := "[" Qualident "]" | Qualident =:
+OptReturnType := "[" QualidentCheck "]" | QualidentCheck =:
ProcedureParameters := ProcedureParameter
{ "," ProcedureParameter } =:
@@ -1027,10 +1062,12 @@ VarIdentList := VarIdent % VAR
=:
VariableDeclaration := VarIdentList ":"
+ % InclVar (BlockState) %
Type Alignment
+ % ExclVar (BlockState) %
=:
-Designator := Qualident % CheckWithReference %
+Designator := QualidentCheck % CheckWithReference %
{ SubDesignator } =:
SubDesignator := "." % VAR Sym, Type, tok,
@@ -1419,7 +1456,7 @@ OptArg := "[" Ident ":" FormalType [ "=" ConstExpression % Bui
DefOptArg := "[" Ident ":" FormalType "=" ConstExpression % BuildOptArgInitializer %
"]" =:
-FormalType := { "ARRAY" "OF" } Qualident =:
+FormalType := { "ARRAY" "OF" } QualidentCheck =:
ModuleDeclaration := % VAR modulet: CARDINAL ; %
% modulet := GetTokenNo () %
diff --git a/gcc/m2/gm2-compiler/PCBuild.bnf b/gcc/m2/gm2-compiler/PCBuild.bnf
index 0e45b2e..6e263b0 100644
--- a/gcc/m2/gm2-compiler/PCBuild.bnf
+++ b/gcc/m2/gm2-compiler/PCBuild.bnf
@@ -61,7 +61,8 @@ FROM M2Reserved IMPORT tokToTok, toktype,
OrTok, TimesTok, DivTok, DivideTok, ModTok, RemTok,
AndTok, AmbersandTok, PeriodPeriodTok, ByTok ;
-FROM M2Quads IMPORT Top, PushT, PopT, PushTF, PopTF, PopNothing, OperandT, PushTFA,
+FROM M2Quads IMPORT Top, PushT, PopT, PushTF, PopTF, PopNothing, OperandT, OperandTok,
+ PushTFA,
PushTFn, PopTFn, PushTFtok, PopTtok, PopTFtok, PushTtok, PushTFntok,
PushT, PushTF, IsAutoPushOn, PushAutoOff, PushAutoOn, PopAuto,
BuildTypeForConstructor, BuildConstructor, BuildConstructorEnd,
@@ -120,6 +121,11 @@ FROM SymbolTable IMPORT MakeGnuAsm, PutGnuAsmVolatile, PutGnuAsm, PutGnuAsmInput
FROM M2Batch IMPORT IsModuleKnown ;
+FROM M2StateCheck IMPORT StateCheck,
+ InitState, PushState, PopState, InclConst, ExclConst,
+ InclConstructor, ExclConstructor,
+ InclConstFunc, CheckQualident ;
+
IMPORT M2Error ;
@@ -128,9 +134,8 @@ CONST
Pass1 = FALSE ;
VAR
- InConstParameter,
- InConstBlock,
- seenError : BOOLEAN ;
+ BlockState: StateCheck ;
+ seenError : BOOLEAN ;
PROCEDURE ErrorString (s: String) ;
@@ -407,8 +412,7 @@ END Real ;
% module PCBuild end
BEGIN
- InConstParameter := FALSE ;
- InConstBlock := FALSE
+ BlockState := InitState ()
END PCBuild.
% rules
error 'ErrorArray' 'ErrorString'
@@ -597,7 +601,7 @@ Qualident := % VAR
=:
ConstantDeclaration := % VAR top: CARDINAL ; %
- % InConstBlock := TRUE %
+ % InclConst (BlockState) %
% top := Top() %
% PushAutoOn %
( Ident "=" % StartDesConst %
@@ -607,7 +611,7 @@ ConstantDeclaration := % VAR
% EndDesConst %
% PopAuto %
% Assert(top=Top()) %
- % InConstBlock := FALSE %
+ % ExclConst (BlockState) %
=:
ConstExpression := % VAR top: CARDINAL ; %
@@ -697,11 +701,14 @@ ComponentValue := ComponentElement [ 'BY' ConstExpression ] =:
ArraySetRecordValue := ComponentValue { ',' % NextConstructorField %
ComponentValue } =:
-Constructor := '{' % PushConstructorCastType %
+Constructor := '{' % InclConstructor (BlockState) %
+ % CheckQualident (OperandTok (1), BlockState, OperandT (1)) %
+ % PushConstructorCastType %
% PushInConstructor %
% BuildConstructor (GetTokenNo ()-1) %
[ ArraySetRecordValue ] % PopConstructor %
'}' % PopInConstructor %
+ % ExclConstructor (BlockState) %
=:
ConstructorOrConstActualParameters := Constructor | ConstActualParameters % PushConstFunctionType %
@@ -714,23 +721,21 @@ ConstSetOrQualidentOrFunction := % Pus
% VAR tokpos: CARDINAL ; %
% tokpos := GetTokenNo () %
(
- PushQualident % IF (NOT InConstParameter) AND InConstBlock
- THEN
- CheckNotVar (tokpos)
- END %
- ( ConstructorOrConstActualParameters | % PushConstType %
+ PushQualident
+ ( ConstructorOrConstActualParameters | % CheckQualident (OperandTok (1), BlockState, OperandT (1)) %
+ % PushConstType %
% PopNothing %
)
| % BuildTypeForConstructor (tokpos) %
Constructor ) % PopAuto %
=:
-ConstActualParameters := % VAR oldConstParameter: BOOLEAN ; %
- % oldConstParameter := InConstParameter %
- % InConstParameter := TRUE %
+ConstActualParameters := % PushState (BlockState) %
+ % InclConstFunc (BlockState) %
+ % CheckQualident (OperandTok (1), BlockState, OperandT (1)) %
% PushT(0) %
"(" [ ConstExpList ] ")"
- % InConstParameter := oldConstParameter %
+ % PopState (BlockState) %
=:
ConstExpList := % VAR n: CARDINAL ; %
@@ -1023,9 +1028,9 @@ ConstructorOrSimpleDes := Constructor | % Pop
SimpleDes [ ActualParameters ]
=:
-SetOrDesignatorOrFunction := % PushAutoOff %
- % VAR tokpos: CARDINAL ; %
+SetOrDesignatorOrFunction := % VAR tokpos: CARDINAL ; %
% tokpos := GetTokenNo () %
+ % PushAutoOff %
(
PushQualident
( ConstructorOrSimpleDes | % PopNothing %
diff --git a/gcc/m2/gm2-gcc/init.cc b/gcc/m2/gm2-gcc/init.cc
index 17ca918..de9fb99 100644
--- a/gcc/m2/gm2-gcc/init.cc
+++ b/gcc/m2/gm2-gcc/init.cc
@@ -105,6 +105,8 @@ 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 _M2_M2StateCheck_init (int argc, char *argv[], char *envp[]);
+EXTERN void _M2_P3Build_init (int argc, char *argv[], char *envp[]);
EXTERN void exit (int);
EXTERN void M2Comp_compile (const char *filename);
EXTERN void RTExceptions_DefaultErrorCatch (void);
@@ -200,5 +202,7 @@ init_PerCompilationInit (const char *filename)
_M2_M2SymInit_init (0, NULL, NULL);
_M2_M2Check_init (0, NULL, NULL);
_M2_M2LangDump_init (0, NULL, NULL);
+ _M2_M2StateCheck_init (0, NULL, NULL);
+ _M2_P3Build_init (0, NULL, NULL);
M2Comp_compile (filename);
}
diff --git a/gcc/testsuite/gm2/errors/fail/array1.mod b/gcc/testsuite/gm2/errors/fail/array1.mod
index 274011b..221b32e 100644
--- a/gcc/testsuite/gm2/errors/fail/array1.mod
+++ b/gcc/testsuite/gm2/errors/fail/array1.mod
@@ -17,9 +17,14 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *)
MODULE array1 ;
+PROCEDURE init ;
VAR
a: ARRAY [FALSE..TRUE] OF CARDINAL ;
i, j: CARDINAL ;
BEGIN
a[i=j] := j
+END init ;
+
+BEGIN
+ init
END array1.
diff --git a/gcc/testsuite/gm2/errors/fail/badtype.mod b/gcc/testsuite/gm2/errors/fail/badtype.mod
new file mode 100644
index 0000000..32ac3a6
--- /dev/null
+++ b/gcc/testsuite/gm2/errors/fail/badtype.mod
@@ -0,0 +1,10 @@
+MODULE badtype ;
+
+PROCEDURE bar (VAR a: CARDINAL) ;
+TYPE
+ Foo = a ;
+BEGIN
+END bar ;
+
+BEGIN
+END badtype.
diff --git a/gcc/testsuite/gm2/errors/fail/badvar.mod b/gcc/testsuite/gm2/errors/fail/badvar.mod
new file mode 100644
index 0000000..2d67cb6
--- /dev/null
+++ b/gcc/testsuite/gm2/errors/fail/badvar.mod
@@ -0,0 +1,10 @@
+MODULE badvar ;
+
+PROCEDURE bar (VAR a: CARDINAL) ;
+VAR
+ Foo: a ;
+BEGIN
+END bar ;
+
+BEGIN
+END badvar.
diff --git a/gcc/testsuite/gm2/errors/fail/errors-fail.exp b/gcc/testsuite/gm2/errors/fail/errors-fail.exp
index 8af0e72..a8fbd2c 100644
--- a/gcc/testsuite/gm2/errors/fail/errors-fail.exp
+++ b/gcc/testsuite/gm2/errors/fail/errors-fail.exp
@@ -25,7 +25,7 @@ if $tracelevel then {
# load support procs
load_lib gm2-torture.exp
-gm2_init_pim "${srcdir}/gm2/errors/fail" -Wpedantic -Wstudents -Wunused-variable
+gm2_init_iso "${srcdir}/gm2/errors/fail" -Wpedantic -Wunused-variable -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.
diff --git a/gcc/testsuite/gm2/errors/fail/testfio.mod b/gcc/testsuite/gm2/errors/fail/testfio.mod
index fabf93e..f11e09e 100644
--- a/gcc/testsuite/gm2/errors/fail/testfio.mod
+++ b/gcc/testsuite/gm2/errors/fail/testfio.mod
@@ -22,12 +22,16 @@ FROM StdIO IMPORT Write ;
FROM StrIO IMPORT WriteString, WriteLn ;
FROM FIO IMPORT Exists, OpenToRead, Close, File, IsNoError, EOF, ReadChar ;
+PROCEDURE init ;
VAR
i: INTEGER ;
f: File ;
c: CARDINAL ;
a: ARRAY [0..20] OF CHAR ;
BEGIN
+ IF f = 0
+ THEN
+ END ;
WriteString('testfio starting') ; WriteLn ;
c := 1 ;
WHILE GetArg(a, c) DO
@@ -45,4 +49,8 @@ BEGIN
END ;
INC(c)
END
+END init ;
+
+BEGIN
+ init
END testfio.
diff --git a/gcc/testsuite/gm2/errors/fail/testparam.mod b/gcc/testsuite/gm2/errors/fail/testparam.mod
index 238334f..142a251 100644
--- a/gcc/testsuite/gm2/errors/fail/testparam.mod
+++ b/gcc/testsuite/gm2/errors/fail/testparam.mod
@@ -19,10 +19,15 @@ MODULE testparam ;
FROM FIO IMPORT IsNoError, Close, EOF ;
+PROCEDURE init ;
VAR
i: INTEGER ;
BEGIN
IF EOF(i)
THEN
END
+END init ;
+
+BEGIN
+ init
END testparam.