]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR modula2/122499: misspelt procedure in import list causes clutter
authorGaius Mulley <gaiusmod2@gmail.com>
Sun, 2 Nov 2025 21:44:03 +0000 (21:44 +0000)
committerGaius Mulley <gaiusmod2@gmail.com>
Sun, 2 Nov 2025 21:44:03 +0000 (21:44 +0000)
A misspelt ident in an import list causes a sequence of clutted errors.
This bug fix filters unknowns built during import lists.  It also
checks for spelling mistakes against the modules exported identifiers.

gcc/m2/ChangeLog:

PR modula2/122499
* gm2-compiler/M2StackSpell.mod (PushName): Add comment.
(GetSpellHint): Rewrite.
(GetExportedSpellHint): New procedure function.
(GetScopeSpellHint): New procedure function.
* gm2-compiler/P1Build.bnf (IdentScope): Rewrite.
(PossiblyExportIdent): Ditto.
* gm2-compiler/P1SymBuild.mod (BuildImportInnerModule): Add
parameter to AddNameToImportList.
* gm2-compiler/SymbolTable.def (GetUnknownOnImport): New
procedure function.
(GetUnknownDeclScope): Ditto.
(AddNameToScope): Add tok parameter.
(AddNameToImportList): Ditto.
* gm2-compiler/SymbolTable.mod (SymUndefined): New field
declScope.
New field onImport.
(MakeObject): Add tok parameter.
(FillInUnknownFields): Initialize declScope.
Initialize onImport.
(GetUnknownOnImport): New procedure function.
(GetUnknownDeclScope): Ditto.
(AddNameToScope): Pass tok to MakeObject.
(AddNameToImportList): Add tok parameter.
Pass tok to MakeObject.
(GetDeclaredSym): Add parameters to FillInUnknownFields.
(RequestSym): Ditto.
(FetchUnknownFromModule): Ditto.
(FetchUnknownFromDefImp): Ditto.
(FetchUnknownFrom): Ditto.

gcc/testsuite/ChangeLog:

PR modula2/122499
* gm2.dg/spell/iso/fail/badimport2.mod: New test.
* gm2.dg/spell/iso/fail/badimport3.mod: New test.
* gm2.dg/spell/iso/fail/badimport4.mod: New test.

Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>
gcc/m2/gm2-compiler/M2StackSpell.mod
gcc/m2/gm2-compiler/P1Build.bnf
gcc/m2/gm2-compiler/P1SymBuild.mod
gcc/m2/gm2-compiler/SymbolTable.def
gcc/m2/gm2-compiler/SymbolTable.mod
gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod [new file with mode: 0644]
gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod [new file with mode: 0644]
gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod [new file with mode: 0644]

index ac58c1c98d09aae65f31fc69161ba8468732206d..06ce923c55fd817bd01a44cf8ce276d8dbff819b 100644 (file)
@@ -23,8 +23,10 @@ IMPLEMENTATION MODULE M2StackSpell ;
 
 FROM SymbolTable IMPORT NulSym, IsModule, IsDefImp, IsRecord,
                         IsEnumeration, IsProcedure, GetNth,
-                        GetSymName, GetSym, GetLocalSym,
-                        UnknownReported,
+                        GetSymName, GetSym, GetLocalSym, GetScope,
+                        UnknownReported, IsUnknown,
+                        GetUnknownOnImport, GetUnknownDeclScope,
+                        ForeachExportedDo,
                         ForeachProcedureDo, ForeachLocalSymDo,
                         ForeachFieldEnumerationDo ;
 
@@ -179,8 +181,9 @@ VAR
    PushCount    : CARDINAL ;
    PushCandidate: Candidates ;
 
+
 (*
-   PushName -
+   PushName - push a name to the candidate vec.
 *)
 
 PROCEDURE PushName (sym: CARDINAL) ;
@@ -279,7 +282,7 @@ BEGIN
       cand := m2spellcheck.InitCandidates () ;
       IF PushCandidates (cand, sym) > 1
       THEN
-         content := m2spellcheck.FindClosestCharStar (cand, string (misspelt)) ;
+         content := m2spellcheck.FindClosestCharStar (cand, string (misspelt))
       ELSE
          content := NIL
       END ;
@@ -310,6 +313,52 @@ END AddPunctuation ;
 *)
 
 PROCEDURE GetSpellHint (unknown: CARDINAL) : String ;
+BEGIN
+   IF IsUnknown (unknown) AND
+      GetUnknownOnImport (unknown) AND
+      (GetUnknownDeclScope (unknown) # GetScope (unknown))
+   THEN
+      (* It was created during an import statement.  *)
+      RETURN GetExportedSpellHint (unknown, GetUnknownDeclScope (unknown))
+   END ;
+   RETURN GetScopeSpellHint (unknown)
+END GetSpellHint ;
+
+
+(*
+   GetExportedSpellHint - return a string describing a spelling hint
+                          using the module exported identifiers.
+*)
+
+PROCEDURE GetExportedSpellHint (unknown, module: CARDINAL) : String ;
+VAR
+   content : ConstCharStar ;
+   misspell,
+   HintStr : String ;
+BEGIN
+   misspell := InitStringCharStar (KeyToCharStar (GetSymName (unknown))) ;
+   HintStr := NIL ;
+   PushCount := 0 ;
+   PushCandidate := m2spellcheck.InitCandidates () ;
+   ForeachExportedDo (module, PushName) ;
+   ForeachLocalSymDo (module, PushName) ;
+   IF PushCount > 0
+   THEN
+      content := m2spellcheck.FindClosestCharStar (PushCandidate,
+                                                   string (misspell)) ;
+      HintStr := BuildHintStr (HintStr, content)
+   END ;
+   m2spellcheck.KillCandidates (PushCandidate) ;
+   RETURN AddPunctuation (HintStr, '?')
+END GetExportedSpellHint ;
+
+
+(*
+   GetScopeSpellHint - return a string describing a spelling hint
+                       using the visible scopes.
+*)
+
+PROCEDURE GetScopeSpellHint (unknown: CARDINAL) : String ;
 VAR
    i, n     : CARDINAL ;
    sym      : CARDINAL ;
@@ -331,7 +380,7 @@ BEGIN
       INC (i)
    END ;
    RETURN AddPunctuation (HintStr, '?')
-END GetSpellHint ;
+END GetScopeSpellHint ;
 
 
 (*
index 4cbdf1725ea7873da91569e4e948042636a2b502..d56a2862f88d581a481ea687dc06e301ba009464 100644 (file)
@@ -358,9 +358,12 @@ END Ident ;
 *)
 
 PROCEDURE IdentScope (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
+VAR
+   tokpos: CARDINAL ;
 BEGIN
-   Ident(stopset0, stopset1, stopset2) ;
-   AddNameToScope(LastIdent)
+   tokpos := GetTokenNo () ;
+   Ident (stopset0, stopset1, stopset2) ;
+   AddNameToScope (tokpos, LastIdent)
 END IdentScope ;
 
 
@@ -374,14 +377,14 @@ PROCEDURE PossiblyExportIdent (stopset0: SetOfStop0; stopset1: SetOfStop1; stops
 VAR
    nothing: CARDINAL ;
 BEGIN
-   AddNameToScope(makekey(currentstring)) ;
-   PushTFtok(makekey(currentstring), identtok, GetTokenNo()) ;
+   AddNameToScope (GetTokenNo (), makekey (currentstring)) ;
+   PushTFtok (makekey (currentstring), identtok, GetTokenNo ()) ;
    CheckExplicitExported ;
-   IF NOT IsAutoPushOn()
+   IF NOT IsAutoPushOn ()
    THEN
-      PopT(nothing)
+      PopT (nothing)
    END ;
-   Expect(identtok, stopset0, stopset1, stopset2)
+   Expect (identtok, stopset0, stopset1, stopset2)
 END PossiblyExportIdent ;
 
 
index d6c0f2fcdcf54c9e3f6afac846e2999aa388dfed..33d12bdeabbf6769f73e0ed3bc277df831baf2e7 100644 (file)
@@ -39,6 +39,7 @@ FROM M2Reserved IMPORT ImportTok, ExportTok, QualifiedTok, UnQualifiedTok,
 
 FROM FifoQueue IMPORT PutEnumerationIntoFifoQueue ;
 FROM P0SymBuild IMPORT EnterBlock, LeaveBlock ;
+FROM libc IMPORT printf ;
 
 FROM SymbolTable IMPORT NulSym,
                         ModeOfAddr,
@@ -472,9 +473,6 @@ BEGIN
                              OperandT(n+1)) ;
       i := 1 ;
       WHILE i<=n DO
-(*
-         WriteString('Importing ') ; WriteKey(Operand(j)) ; WriteString(' from ') ; WriteKey(GetSymName(ModSym)) ; WriteLn ;
-*)
          Sym := GetExported (OperandTok (n+1-i),
                              ModSym, OperandT (n+1-i)) ;
          PutImported (Sym) ;
@@ -619,7 +617,7 @@ BEGIN
       (* Ident List contains list of objects *)
       i := 1 ;
       WHILE i<=n DO
-         AddNameToImportList (OperandT (i)) ;
+         AddNameToImportList (OperandTok (i), OperandT (i)) ;
          INC (i)
       END
    ELSE
index 09a5590013f2e3240494dbd4fdefd3770fe5946b..2a2f201306706b4e2e686e96f864cdb9a5a1687c 100644 (file)
@@ -2135,6 +2135,20 @@ PROCEDURE CheckForUnknownInModule (tokno: CARDINAL) ;
 PROCEDURE UnknownReported (sym: CARDINAL) ;
 
 
+(*
+   GetUnknownOnImport - returns the onimport field of unknown sym.
+*)
+
+PROCEDURE GetUnknownOnImport (sym: CARDINAL) : BOOLEAN ;
+
+
+(*
+   GetUnknownDeclScope - returns the decl scope of unknown sym.
+*)
+
+PROCEDURE GetUnknownDeclScope (sym: CARDINAL) : CARDINAL ;
+
+
 (*
    IsReallyPointer - returns TRUE is sym is a pointer, address or a
                      type declared as a pointer or address.
@@ -2613,7 +2627,7 @@ PROCEDURE ResolveConstructorTypes ;
                     current scope.
 *)
 
-PROCEDURE AddNameToScope (n: Name) ;
+PROCEDURE AddNameToScope (tok: CARDINAL; n: Name) ;
 
 
 (*
@@ -2621,7 +2635,7 @@ PROCEDURE AddNameToScope (n: Name) ;
                          module.
 *)
 
-PROCEDURE AddNameToImportList (n: Name) ;
+PROCEDURE AddNameToImportList (tok: CARDINAL; n: Name) ;
 
 
 (*
index 023bd49105418f4439b3784f976430b91c510422..25170fb46a433eb9d564f0bba766c38e1651ca62 100644 (file)
@@ -230,6 +230,10 @@ TYPE
    SymUndefined = RECORD
                      name      : Name ;       (* Index into name array, name *)
                                               (* of record.                  *)
+                     declScope : CARDINAL ;   (* Scope where unknown is      *)
+                                              (* created.                    *)
+                     onImport  : BOOLEAN ;    (* Was it created during an    *)
+                                              (* import?                     *)
                      oafamily  : CARDINAL ;   (* The oafamily for this sym   *)
                      errorScope: ErrorScope ; (* Title scope used if an      *)
                                               (* error is emitted.           *)
@@ -1591,7 +1595,7 @@ END IsError ;
    MakeObject - creates an object node.
 *)
 
-PROCEDURE MakeObject (name: Name) : CARDINAL ;
+PROCEDURE MakeObject (tok: CARDINAL; name: Name) : CARDINAL ;
 VAR
    pSym: PtrToSymbol ;
    Sym : CARDINAL ;
@@ -1601,8 +1605,8 @@ BEGIN
    WITH pSym^ DO
       SymbolType := ObjectSym ;
       Object.name := name ;
-      InitWhereDeclared(Object.At) ;
-      InitWhereFirstUsed(Object.At)
+      InitWhereDeclaredTok (tok, Object.At) ;
+      InitWhereFirstUsedTok (tok, Object.At)
    END ;
    RETURN( Sym )
 END MakeObject ;
@@ -8647,7 +8651,7 @@ BEGIN
       THEN
          (* Make unknown *)
          NewSym (Sym) ;
-         FillInUnknownFields (tok, Sym, SymName) ;
+         FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ;
          (* Add to unknown tree *)
          AddSymToUnknownTree (ScopePtr, SymName, Sym)
          (*
@@ -8684,7 +8688,7 @@ BEGIN
       THEN
          (* Make unknown.  *)
          NewSym (Sym) ;
-         FillInUnknownFields (tok, Sym, SymName) ;
+         FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ;
          (* Add to unknown tree *)
          AddSymToUnknownTree (ScopePtr, SymName, Sym)
          (*
@@ -9252,7 +9256,7 @@ BEGIN
                        IF Sym=NulSym
                        THEN
                           NewSym (Sym) ;
-                          FillInUnknownFields (tok, Sym, SymName) ;
+                          FillInUnknownFields (tok, Sym, SymName, ModSym, TRUE) ;
                           PutSymKey (Unresolved, SymName, Sym)
                        END
                     END
@@ -9283,7 +9287,7 @@ BEGIN
                        IF Sym=NulSym
                        THEN
                           NewSym(Sym) ;
-                          FillInUnknownFields (tok, Sym, SymName) ;
+                          FillInUnknownFields (tok, Sym, SymName, ModSym, TRUE) ;
                           PutSymKey (Unresolved, SymName, Sym)
                        END
                     END
@@ -9310,7 +9314,7 @@ BEGIN
                        IF Sym=NulSym
                        THEN
                           NewSym(Sym) ;
-                          FillInUnknownFields (tok, Sym, SymName) ;
+                          FillInUnknownFields (tok, Sym, SymName, scope, TRUE) ;
                           PutSymKey(Unresolved, SymName, Sym)
                        END
                     END |
@@ -9319,7 +9323,7 @@ BEGIN
                        IF Sym=NulSym
                        THEN
                           NewSym(Sym) ;
-                          FillInUnknownFields (tok, Sym, SymName) ;
+                          FillInUnknownFields (tok, Sym, SymName, scope, TRUE) ;
                           PutSymKey(Unresolved, SymName, Sym)
                        END
                     END |
@@ -9328,7 +9332,7 @@ BEGIN
                           IF Sym=NulSym
                           THEN
                              NewSym(Sym) ;
-                             FillInUnknownFields (tok, Sym, SymName) ;
+                             FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ;
                              PutSymKey(Unresolved, SymName, Sym)
                           END
                        END
@@ -9599,7 +9603,8 @@ BEGIN
                     CheckForUnknowns (tokno, name, ExportUnQualifiedTree,
                                       'EXPORT UNQUALIFIED') ;
                     CheckForSymbols (ExportRequest,
-                                     'requested by another modules import (symbols have not been exported by the appropriate definition module)') ;
+                                     'requested by another module import' +
+                                     ' and the symbol has not been exported by the appropriate definition module') ;
                     CheckForUnknowns (tokno, name, Unresolved, 'unresolved') ;
                     CheckForUnknowns (tokno, name, LocalSymbols, 'locally used')
                  END |
@@ -9752,12 +9757,12 @@ PROCEDURE CheckForSymbols (Tree: SymbolTree; a: ARRAY OF CHAR) ;
 VAR
    s: String ;
 BEGIN
-   IF NOT IsEmptyTree(Tree)
+   IF DoesTreeContainAny (Tree, IsUnreportedUnknown)
    THEN
       s := InitString ("the symbols are unknown at the end of module {%1Ea} when ") ;
       s := ConCat (s, Mark(InitString(a))) ;
       MetaErrorString1 (s, MainModule) ;
-      ForeachNodeDo(Tree, SymbolError)
+      ForeachNodeDo (Tree, SymbolError)
    END
 END CheckForSymbols ;
 
@@ -11708,10 +11713,11 @@ END IsProcedureAnyNoReturn ;
 
 
 (*
-   FillInUnknownFields -
+   FillInUnknownFields - fills in all fields for the undefined sym.
 *)
 
-PROCEDURE FillInUnknownFields (tok: CARDINAL; sym: CARDINAL; SymName: Name) ;
+PROCEDURE FillInUnknownFields (tok: CARDINAL; sym: CARDINAL; SymName: Name;
+                               descscope: CARDINAL; onimport: BOOLEAN) ;
 VAR
    pSym: PtrToSymbol ;
 BEGIN
@@ -11722,12 +11728,42 @@ BEGIN
          name     := SymName ;
          oafamily := NulSym ;
          errorScope := GetCurrentErrorScope () ;
+         declScope := descscope ;
+         onImport := onimport ;
          InitWhereFirstUsedTok (tok, At)
       END
    END
 END FillInUnknownFields ;
 
 
+(*
+   GetUnknownOnImport - returns the onimport field of unknown sym.
+*)
+
+PROCEDURE GetUnknownOnImport (sym: CARDINAL) : BOOLEAN ;
+VAR
+   pSym: PtrToSymbol ;
+BEGIN
+   Assert (IsUnknown (sym)) ;
+   pSym := GetPsym (sym) ;
+   RETURN pSym^.Undefined.onImport
+END GetUnknownOnImport ;
+
+
+(*
+   GetUnknownDeclScope - returns the decl scope of unknown sym.
+*)
+
+PROCEDURE GetUnknownDeclScope (sym: CARDINAL) : CARDINAL ;
+VAR
+   pSym: PtrToSymbol ;
+BEGIN
+   Assert (IsUnknown (sym)) ;
+   pSym := GetPsym (sym) ;
+   RETURN pSym^.Undefined.declScope
+END GetUnknownDeclScope ;
+
+
 (*
    FillInPointerFields - given a new symbol, sym, make it a pointer symbol
                          and initialize its fields.
@@ -12985,7 +13021,7 @@ END AddNameTo ;
                     current scope.
 *)
 
-PROCEDURE AddNameToScope (n: Name) ;
+PROCEDURE AddNameToScope (tok: CARDINAL; n: Name) ;
 VAR
    pSym : PtrToSymbol ;
    scope: CARDINAL ;
@@ -12995,9 +13031,9 @@ BEGIN
    WITH pSym^ DO
       CASE SymbolType OF
 
-      ProcedureSym:  AddNameTo(Procedure.NamedObjects, MakeObject(n)) |
-      ModuleSym   :  AddNameTo(Module.NamedObjects, MakeObject(n)) |
-      DefImpSym   :  AddNameTo(DefImp.NamedObjects, MakeObject(n))
+      ProcedureSym:  AddNameTo(Procedure.NamedObjects, MakeObject (tok, n)) |
+      ModuleSym   :  AddNameTo(Module.NamedObjects, MakeObject (tok, n)) |
+      DefImpSym   :  AddNameTo(DefImp.NamedObjects, MakeObject (tok, n))
 
       ELSE
          InternalError ('expecting - DefImp')
@@ -13011,7 +13047,7 @@ END AddNameToScope ;
                          module.
 *)
 
-PROCEDURE AddNameToImportList (n: Name) ;
+PROCEDURE AddNameToImportList (tok: CARDINAL; n: Name) ;
 VAR
    pSym : PtrToSymbol ;
    scope: CARDINAL ;
@@ -13021,8 +13057,8 @@ BEGIN
    WITH pSym^ DO
       CASE SymbolType OF
 
-      ModuleSym:  AddNameTo(Module.NamedImports, MakeObject(n)) |
-      DefImpSym:  AddNameTo(DefImp.NamedImports, MakeObject(n))
+      ModuleSym:  AddNameTo (Module.NamedImports, MakeObject (tok, n)) |
+      DefImpSym:  AddNameTo (DefImp.NamedImports, MakeObject (tok, n))
 
       ELSE
          InternalError ('expecting - DefImp or Module symbol')
diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod
new file mode 100644 (file)
index 0000000..63fd338
--- /dev/null
@@ -0,0 +1,12 @@
+
+(* { dg-do compile } *)
+(* { dg-options "-g -c" } *)
+
+MODULE badimport2 ;
+
+FROM StrIO IMPORT Writestring ;
+ (* { dg-error "error: In program module 'badimport2': unknown symbol 'Writestring', did you mean WriteString?" "Writestring" { target *-*-* } 7 } *)
+
+BEGIN
+
+END badimport2.
diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod
new file mode 100644 (file)
index 0000000..ab82cd5
--- /dev/null
@@ -0,0 +1,17 @@
+
+(* { dg-do compile } *)
+(* { dg-options "-g -c" } *)
+
+MODULE badimport3 ;
+
+CONST
+   Foo = 42 ;
+
+MODULE inner ;
+IMPORT foo ;
+ (* { dg-error "error: In inner module 'inner': unknown symbol 'foo', did you mean Foo?" "foo" { target *-*-* } 11 } *)
+END inner ;
+
+
+BEGIN
+END badimport3.
diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod
new file mode 100644 (file)
index 0000000..1b310d7
--- /dev/null
@@ -0,0 +1,17 @@
+
+(* { dg-do compile } *)
+(* { dg-options "-g -c" } *)
+
+MODULE badimport4 ;
+
+CONST
+   Foo = 42 ;
+
+MODULE inner ;
+IMPORT foo ;
+ (* { dg-error "error: In inner module 'inner': unknown symbol 'foo', did you mean Foo?" "foo" { target *-*-* } 11 } *)
+END inner ;
+
+
+BEGIN
+END badimport4.