https://gcc.gnu.org/g:fba2f08152375e2c1c167ec921a0197e4c07efc6
commit r16-1546-gfba2f08152375e2c1c167ec921a0197e4c07efc6 Author: Gaius Mulley <gaiusm...@gmail.com> Date: Tue Jun 17 17:41:21 2025 +0100 PR modula2/120673: Mutually dependent types crash the compiler This patch fixes an ICE which will occur if cyclic dependent types are used when declaring a variable. This patch detects the cyclic dependency and issues an error message for each outstanding component. gcc/m2/ChangeLog: PR modula2/120673 * gm2-compiler/M2GCCDeclare.mod (ErrorDepList): New global variable set containing every errant dependency symbol. (mystop): Remove. (EmitCircularDependancyError): Replace with ... (EmitCircularDependencyError): ... this. (AssertAllTypesDeclared): Rewrite. (DoVariableDeclaration): Ditto. (TypeDependentsDeclared): New procedure function. (PrepareGCCVarDeclaration): Ditto. (DeclareVariable): Remove assert. (DeclareLocalVariable): Ditto. (Constructor): Initialize ErrorDepList. * gm2-compiler/M2MetaError.mod (doErrorScopeProc): Rewrite and ensure that a symbol with a module scope does not lookup from a definition module. * gm2-compiler/P2SymBuild.mod (BuildType): Rewrite so that a synonym type is created using the token refering to the name on the lhs. gcc/testsuite/ChangeLog: PR modula2/120673 * gm2/pim/fail/badmodvar.mod: New test. * gm2/pim/fail/cyclictypes.mod: New test. * gm2/pim/fail/cyclictypes2.mod: New test. * gm2/pim/fail/cyclictypes4.mod: New test. Signed-off-by: Gaius Mulley <gaiusm...@gmail.com> Diff: --- gcc/m2/gm2-compiler/M2GCCDeclare.mod | 94 +++++++++++++++++++++-------- gcc/m2/gm2-compiler/M2MetaError.mod | 37 ++++-------- gcc/m2/gm2-compiler/P2SymBuild.mod | 31 ++++++---- gcc/testsuite/gm2/pim/fail/badmodvar.mod | 7 +++ gcc/testsuite/gm2/pim/fail/cyclictypes.mod | 13 ++++ gcc/testsuite/gm2/pim/fail/cyclictypes2.mod | 9 +++ gcc/testsuite/gm2/pim/fail/cyclictypes4.mod | 13 ++++ 7 files changed, 140 insertions(+), 64 deletions(-) diff --git a/gcc/m2/gm2-compiler/M2GCCDeclare.mod b/gcc/m2/gm2-compiler/M2GCCDeclare.mod index b12add6b26e8..be80695d3e8a 100644 --- a/gcc/m2/gm2-compiler/M2GCCDeclare.mod +++ b/gcc/m2/gm2-compiler/M2GCCDeclare.mod @@ -251,6 +251,7 @@ TYPE VAR FreeGroup, GlobalGroup : Group ; (* The global group of all sets. *) + ErrorDepList, (* The set of symbols with dependency errors. *) VisitedList, ChainedList : Set ; HaveInitDefaultTypes: BOOLEAN ; (* Have we initialized them yet? *) @@ -261,9 +262,6 @@ VAR enumDeps : BOOLEAN ; -PROCEDURE mystop ; BEGIN END mystop ; - - (* *************************************************** *) (* PrintNum - @@ -1315,14 +1313,26 @@ END CanBeDeclaredPartiallyViaPartialDependants ; (* - EmitCircularDependancyError - issue a dependancy error. + EmitCircularDependencyError - issue a dependency error. *) -PROCEDURE EmitCircularDependancyError (sym: CARDINAL) ; +PROCEDURE EmitCircularDependencyError (sym: CARDINAL) ; BEGIN - MetaError1('circular dependancy error found when trying to resolve {%1Uad}', - sym) -END EmitCircularDependancyError ; + (* Ensure we only issue one dependency message per symbol for this + error classification. *) + IF NOT IsElementInSet (ErrorDepList, sym) + THEN + IncludeElementIntoSet (ErrorDepList, sym) ; + IF IsVar (sym) OR IsParameter (sym) + THEN + MetaError1 ('circular dependency error found when trying to resolve {%1Had}', + sym) + ELSE + MetaError1 ('circular dependency error found when trying to resolve {%1Dad}', + sym) + END + END +END EmitCircularDependencyError ; TYPE @@ -1529,17 +1539,17 @@ BEGIN IF ForeachTryDeclare (todolist, circulartodo, NotAllDependantsFullyDeclared, - EmitCircularDependancyError) + EmitCircularDependencyError) THEN ELSIF ForeachTryDeclare (partiallydeclared, circularpartial, NotAllDependantsPartiallyDeclared, - EmitCircularDependancyError) + EmitCircularDependencyError) THEN ELSIF ForeachTryDeclare (niltypedarrays, circularniltyped, NotAllDependantsPartiallyDeclared, - EmitCircularDependancyError) + EmitCircularDependencyError) THEN END END ; @@ -2855,13 +2865,8 @@ BEGIN n := 1 ; Var := GetNth(scope, n) ; WHILE Var#NulSym DO - IF NOT AllDependantsFullyDeclared(GetSType(Var)) - THEN - mystop - END ; - IF NOT AllDependantsFullyDeclared(GetSType(Var)) + IF NOT TypeDependentsDeclared (Var, TRUE) THEN - EmitCircularDependancyError(GetSType(Var)) ; failed := TRUE END ; INC(n) ; @@ -3411,15 +3416,55 @@ PROCEDURE DoVariableDeclaration (var: CARDINAL; name: ADDRESS; isImported, isExported, isTemporary, isGlobal: BOOLEAN; scope: tree) ; +BEGIN + IF NOT (IsComponent (var) OR IsVarHeap (var)) + THEN + IF TypeDependentsDeclared (var, TRUE) + THEN + PrepareGCCVarDeclaration (var, name, isImported, isExported, + isTemporary, isGlobal, scope) + END + END +END DoVariableDeclaration ; + + +(* + TypeDependentsDeclared - return TRUE if all type dependents of variable + have been declared. +*) + +PROCEDURE TypeDependentsDeclared (variable: CARDINAL; errorMessage: BOOLEAN) : BOOLEAN ; +VAR + type: CARDINAL ; +BEGIN + type := GetSType (variable) ; + IF AllDependantsFullyDeclared (type) + THEN + RETURN TRUE + ELSE + IF errorMessage + THEN + EmitCircularDependencyError (variable) ; + ForeachElementInSetDo (GlobalGroup^.ToDoList, EmitCircularDependencyError) + END + END ; + RETURN FALSE +END TypeDependentsDeclared ; + + +(* + PrepareGCCVarDeclaration - +*) + +PROCEDURE PrepareGCCVarDeclaration (var: CARDINAL; name: ADDRESS; + isImported, isExported, + isTemporary, isGlobal: BOOLEAN; + scope: tree) ; VAR type : tree ; varType : CARDINAL ; location: location_t ; BEGIN - IF IsComponent (var) OR IsVarHeap (var) - THEN - RETURN - END ; IF GetMode (var) = LeftValue THEN (* @@ -3457,7 +3502,7 @@ BEGIN isGlobal, scope, NIL)) ; WatchRemoveList (var, todolist) ; WatchIncludeList (var, fullydeclared) -END DoVariableDeclaration ; +END PrepareGCCVarDeclaration ; (* @@ -3493,7 +3538,6 @@ BEGIN THEN scope := FindContext (ModSym) ; decl := FindOuterModule (variable) ; - Assert (AllDependantsFullyDeclared (GetSType (variable))) ; PushBinding (ModSym) ; DoVariableDeclaration (variable, KeyToCharStar (GetFullSymName (variable)), @@ -3521,7 +3565,6 @@ BEGIN THEN scope := FindContext (mainModule) ; decl := FindOuterModule (variable) ; - Assert (AllDependantsFullyDeclared (GetSType (variable))) ; PushBinding (mainModule) ; DoVariableDeclaration (variable, KeyToCharStar (GetFullSymName (variable)), @@ -3618,7 +3661,6 @@ END DeclareImportedVariablesWholeProgram ; PROCEDURE DeclareLocalVariable (var: CARDINAL) ; BEGIN - Assert (AllDependantsFullyDeclared (var)) ; DoVariableDeclaration (var, KeyToCharStar (GetFullSymName (var)), FALSE, (* local variables cannot be imported *) @@ -3662,7 +3704,6 @@ BEGIN scope := Mod2Gcc (GetProcedureScope (sym)) ; Var := GetNth (sym, i) ; WHILE Var # NulSym DO - Assert (AllDependantsFullyDeclared (GetSType (Var))) ; DoVariableDeclaration (Var, KeyToCharStar (GetFullSymName (Var)), FALSE, (* inner module variables cannot be imported *) @@ -6658,6 +6699,7 @@ END InitDeclarations ; BEGIN FreeGroup := NIL ; GlobalGroup := InitGroup () ; + ErrorDepList := InitSet (1) ; ChainedList := InitSet(1) ; WatchList := InitSet(1) ; VisitedList := NIL ; diff --git a/gcc/m2/gm2-compiler/M2MetaError.mod b/gcc/m2/gm2-compiler/M2MetaError.mod index 22bc77f6ad00..3aa7543231d7 100644 --- a/gcc/m2/gm2-compiler/M2MetaError.mod +++ b/gcc/m2/gm2-compiler/M2MetaError.mod @@ -1437,35 +1437,22 @@ BEGIN doError (eb, GetDeclaredDef (sym)) ELSE M2Error.EnterErrorScope (GetErrorScope (scope)) ; - IF IsProcedure (scope) + IF IsVar (sym) OR IsParameter (sym) THEN - IF IsVar (sym) OR IsParameter (sym) - THEN - doError (eb, GetVarParamTok (sym)) - ELSE - doError (eb, GetDeclaredDef (sym)) - END + doError (eb, GetVarParamTok (sym)) + ELSIF IsProcedure (scope) + THEN + doError (eb, GetDeclaredDef (sym)) + ELSIF IsModule (scope) + THEN + doError (eb, GetDeclaredMod (sym)) ELSE - IF IsModule (scope) + Assert (IsDefImp (scope)) ; + IF GetDeclaredDefinition (sym) = UnknownTokenNo THEN - IF IsInnerModule (scope) - THEN - doError (eb, GetDeclaredDef (sym)) - ELSE - doError (eb, GetDeclaredDef (sym)) - END + doError (eb, GetDeclaredMod (sym)) ELSE - Assert (IsDefImp (scope)) ; - (* if this fails then we need to skip to the outer scope. - REPEAT - OuterModule := GetScope(OuterModule) - UNTIL GetScope(OuterModule)=NulSym ; *) - IF GetDeclaredDefinition (sym) = UnknownTokenNo - THEN - doError (eb, GetDeclaredMod (sym)) - ELSE - doError (eb, GetDeclaredDef (sym)) - END + doError (eb, GetDeclaredDef (sym)) END END END ; diff --git a/gcc/m2/gm2-compiler/P2SymBuild.mod b/gcc/m2/gm2-compiler/P2SymBuild.mod index 8f3b4995ac88..5c82ec8ede05 100644 --- a/gcc/m2/gm2-compiler/P2SymBuild.mod +++ b/gcc/m2/gm2-compiler/P2SymBuild.mod @@ -1225,7 +1225,8 @@ VAR Sym, Type : CARDINAL ; name : Name ; - tokno : CARDINAL ; + nametokno, + typetokno: CARDINAL ; BEGIN (* Two cases @@ -1234,8 +1235,8 @@ BEGIN - when type with a name that is different to Name. In which case we create a new type. *) - PopTtok(Type, tokno) ; - PopT(name) ; + PopTtok (Type, typetokno) ; + PopTtok (name, nametokno) ; IF Debugging THEN n1 := GetSymName(GetCurrentModule()) ; @@ -1264,11 +1265,11 @@ BEGIN *) (* WriteString('Blank name type') ; WriteLn ; *) - PushTFtok(Type, name, tokno) ; + PushTFtok(Type, name, typetokno) ; Annotate("%1s(%1d)|%2n|%3d||type|type name|token no") ELSIF IsError(Type) THEN - PushTFtok(Type, name, tokno) ; + PushTFtok(Type, name, typetokno) ; Annotate("%1s(%1d)|%2n|%3d||error type|error type name|token no") ELSIF GetSymName(Type)=name THEN @@ -1276,7 +1277,7 @@ BEGIN IF isunknown OR (NOT IsDeclaredIn(GetCurrentScope(), Type)) THEN - Sym := MakeType(tokno, name) ; + Sym := MakeType (typetokno, name) ; IF NOT IsError(Sym) THEN IF Sym=Type @@ -1295,19 +1296,23 @@ BEGIN CheckForEnumerationInCurrentModule(Type) END END ; - PushTFtok(Sym, name, tokno) ; + PushTFtok(Sym, name, typetokno) ; Annotate("%1s(%1d)|%2n|%3d||type|type name|token no") ELSE - PushTFtok(Type, name, tokno) ; + PushTFtok(Type, name, typetokno) ; Annotate("%1s(%1d)|%2n|%3d||type|type name|token no") END ELSE (* example TYPE a = CARDINAL *) - Sym := MakeType(tokno, name) ; - PutType(Sym, Type) ; - CheckForExportedImplementation(Sym) ; (* May be an exported hidden type *) - PushTFtok(Sym, name, tokno) ; - Annotate("%1s(%1d)|%2n|%3d||type|type name|token no") + Sym := MakeType (nametokno, name) ; + PutType (Sym, Type) ; + CheckForExportedImplementation (Sym) ; (* May be an exported hidden type *) + PushTFtok (Sym, name, nametokno) ; + Annotate ("%1s(%1d)|%2n|%3d||type|type name|token no") ; + IF Debugging + THEN + MetaErrorT1 (nametokno, 'type pos {%1Wa}', Sym) + END END END BuildType ; diff --git a/gcc/testsuite/gm2/pim/fail/badmodvar.mod b/gcc/testsuite/gm2/pim/fail/badmodvar.mod new file mode 100644 index 000000000000..dd90920af71f --- /dev/null +++ b/gcc/testsuite/gm2/pim/fail/badmodvar.mod @@ -0,0 +1,7 @@ +MODULE badmodvar ; + +VAR + x: y ; +BEGIN + +END badmodvar. diff --git a/gcc/testsuite/gm2/pim/fail/cyclictypes.mod b/gcc/testsuite/gm2/pim/fail/cyclictypes.mod new file mode 100644 index 000000000000..f2adb49c9082 --- /dev/null +++ b/gcc/testsuite/gm2/pim/fail/cyclictypes.mod @@ -0,0 +1,13 @@ +MODULE cyclictypes ; + +TYPE + A = B; + B = A; + +PROCEDURE foo ; +VAR + bar: A ; +END foo ; + + +END cyclictypes. diff --git a/gcc/testsuite/gm2/pim/fail/cyclictypes2.mod b/gcc/testsuite/gm2/pim/fail/cyclictypes2.mod new file mode 100644 index 000000000000..a5630c86ff6a --- /dev/null +++ b/gcc/testsuite/gm2/pim/fail/cyclictypes2.mod @@ -0,0 +1,9 @@ +MODULE cyclictypes2 ; + +TYPE + A = B; + B = A; + +VAR + bar: A ; +END cyclictypes2. diff --git a/gcc/testsuite/gm2/pim/fail/cyclictypes4.mod b/gcc/testsuite/gm2/pim/fail/cyclictypes4.mod new file mode 100644 index 000000000000..69f061b6ebb1 --- /dev/null +++ b/gcc/testsuite/gm2/pim/fail/cyclictypes4.mod @@ -0,0 +1,13 @@ +MODULE cyclictypes4 ; + +TYPE + A = B ; + B = C ; + C = D ; + D = A ; + +VAR + v: A ; +BEGIN + +END cyclictypes4.