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 <[email protected]>
---
 gcc/m2/gm2-compiler/M2StackSpell.mod          | 59 ++++++++++++--
 gcc/m2/gm2-compiler/P1Build.bnf               | 17 ++--
 gcc/m2/gm2-compiler/P1SymBuild.mod            |  6 +-
 gcc/m2/gm2-compiler/SymbolTable.def           | 18 ++++-
 gcc/m2/gm2-compiler/SymbolTable.mod           | 80 ++++++++++++++-----
 .../gm2.dg/spell/iso/fail/badimport2.mod      | 12 +++
 .../gm2.dg/spell/iso/fail/badimport3.mod      | 17 ++++
 .../gm2.dg/spell/iso/fail/badimport4.mod      | 17 ++++
 8 files changed, 186 insertions(+), 40 deletions(-)
 create mode 100644 gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod
 create mode 100644 gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod
 create mode 100644 gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod

diff --git a/gcc/m2/gm2-compiler/M2StackSpell.mod 
b/gcc/m2/gm2-compiler/M2StackSpell.mod
index ac58c1c98d0..06ce923c55f 100644
--- a/gcc/m2/gm2-compiler/M2StackSpell.mod
+++ b/gcc/m2/gm2-compiler/M2StackSpell.mod
@@ -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 ;
 
 
 (*
diff --git a/gcc/m2/gm2-compiler/P1Build.bnf b/gcc/m2/gm2-compiler/P1Build.bnf
index 4cbdf1725ea..d56a2862f88 100644
--- a/gcc/m2/gm2-compiler/P1Build.bnf
+++ b/gcc/m2/gm2-compiler/P1Build.bnf
@@ -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 ;
 
 
diff --git a/gcc/m2/gm2-compiler/P1SymBuild.mod 
b/gcc/m2/gm2-compiler/P1SymBuild.mod
index d6c0f2fcdcf..33d12bdeabb 100644
--- a/gcc/m2/gm2-compiler/P1SymBuild.mod
+++ b/gcc/m2/gm2-compiler/P1SymBuild.mod
@@ -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
diff --git a/gcc/m2/gm2-compiler/SymbolTable.def 
b/gcc/m2/gm2-compiler/SymbolTable.def
index 09a5590013f..2a2f2013067 100644
--- a/gcc/m2/gm2-compiler/SymbolTable.def
+++ b/gcc/m2/gm2-compiler/SymbolTable.def
@@ -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) ;
 
 
 (*
diff --git a/gcc/m2/gm2-compiler/SymbolTable.mod 
b/gcc/m2/gm2-compiler/SymbolTable.mod
index 023bd491054..25170fb46a4 100644
--- a/gcc/m2/gm2-compiler/SymbolTable.mod
+++ b/gcc/m2/gm2-compiler/SymbolTable.mod
@@ -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
index 00000000000..63fd33841d2
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod
@@ -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
index 00000000000..ab82cd5e8ee
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod
@@ -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
index 00000000000..1b310d79c71
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod
@@ -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.
-- 
2.39.5

Reply via email to