https://gcc.gnu.org/g:7be54613e8a1b1080f0480cf061baa73317a26d3

commit r15-7200-g7be54613e8a1b1080f0480cf061baa73317a26d3
Author: Gaius Mulley <gaiusm...@gmail.com>
Date:   Sat Jan 25 00:05:48 2025 +0000

    PR modula2/118589 Opaque type fields are visible outside implementation 
module
    
    This patch fixes a bug shown when a variable declared as an opaque type is
    dereferenced outside the declaration module.  The fix also improves error
    recovery.  In the error cases it ensures that an error symbol is created
    and the appropriate virtual token is assigned.  Finally there is a new
    testsuite directory gm2.dg which contains tests to check against expected
    error messages.
    
    gcc/m2/ChangeLog:
    
            PR modula2/118589
            * gm2-compiler/M2MetaError.mod (symDesc): Add opaque type
            description.
            * gm2-compiler/M2Quads.mod (BuildDesignatorPointerError): New
            procedure.
            (BuildDesignatorPointer): Reimplement.
            * gm2-compiler/P3Build.bnf (SubDesignator): Tidy up error message.
            Use MetaErrorT2 rather than WriteForma1 and use the token pos from
            the quad stack.
    
    gcc/testsuite/ChangeLog:
    
            PR modula2/118589
            * lib/gm2-dg.exp (gm2.exp): load_lib.
            * gm2.dg/pim/fail/badopaque.mod: New test.
            * gm2.dg/pim/fail/badopaque2.mod: New test.
            * gm2.dg/pim/fail/dg-pim-fail.exp: New test.
            * gm2.dg/pim/fail/opaquedefs.def: New test.
            * gm2.dg/pim/fail/opaquedefs.mod: New test.
    
    Signed-off-by: Gaius Mulley <gaiusm...@gmail.com>

Diff:
---
 gcc/m2/gm2-compiler/M2MetaError.mod           |  7 ++-
 gcc/m2/gm2-compiler/M2Quads.mod               | 90 ++++++++++++++++++---------
 gcc/m2/gm2-compiler/P3Build.bnf               |  7 +--
 gcc/testsuite/gm2.dg/pim/fail/badopaque.mod   | 15 +++++
 gcc/testsuite/gm2.dg/pim/fail/badopaque2.mod  | 17 +++++
 gcc/testsuite/gm2.dg/pim/fail/dg-pim-fail.exp | 34 ++++++++++
 gcc/testsuite/gm2.dg/pim/fail/opaquedefs.def  |  7 +++
 gcc/testsuite/gm2.dg/pim/fail/opaquedefs.mod  | 13 ++++
 gcc/testsuite/lib/gm2-dg.exp                  |  2 +
 9 files changed, 157 insertions(+), 35 deletions(-)

diff --git a/gcc/m2/gm2-compiler/M2MetaError.mod 
b/gcc/m2/gm2-compiler/M2MetaError.mod
index 11874861e66d..22bc77f6ad00 100644
--- a/gcc/m2/gm2-compiler/M2MetaError.mod
+++ b/gcc/m2/gm2-compiler/M2MetaError.mod
@@ -1611,7 +1611,12 @@ BEGIN
       END
    ELSIF IsType(sym)
    THEN
-      RETURN InitString('type')
+      IF IsHiddenType (sym)
+      THEN
+         RETURN InitString('opaque type')
+      ELSE
+         RETURN InitString('type')
+      END
    ELSIF IsRecord(sym)
    THEN
       RETURN InitString('record')
diff --git a/gcc/m2/gm2-compiler/M2Quads.mod b/gcc/m2/gm2-compiler/M2Quads.mod
index fd3482b1f2d2..785a6e9885a8 100644
--- a/gcc/m2/gm2-compiler/M2Quads.mod
+++ b/gcc/m2/gm2-compiler/M2Quads.mod
@@ -63,6 +63,7 @@ FROM SymbolTable IMPORT ModeOfAddr, GetMode, PutMode, 
GetSymName, IsUnknown,
                         GetScope, GetCurrentScope,
                         GetSubrange, SkipTypeAndSubrange,
                         GetModule, GetMainModule,
+                        GetModuleScope, GetCurrentModuleScope,
                         GetCurrentModule, GetFileModule, GetLocalSym,
                         GetStringLength, GetString,
                         GetArraySubscript, GetDimension,
@@ -115,7 +116,7 @@ FROM SymbolTable IMPORT ModeOfAddr, GetMode, PutMode, 
GetSymName, IsUnknown,
                         PutDeclared,
                         MakeComponentRecord, MakeComponentRef,
                         IsSubscript, IsComponent, IsConstStringKnown,
-                        IsTemporary,
+                        IsTemporary, IsHiddenType,
                         IsAModula2Type,
                         PutLeftValueFrontBackType,
                         PushSize, PushValue, PopValue,
@@ -11427,6 +11428,24 @@ BEGIN
 END BuildDesignatorError ;
 
 
+(*
+   BuildDesignatorPointerError - removes the designator from the stack and 
replaces
+                                 it with an error symbol.
+*)
+
+PROCEDURE BuildDesignatorPointerError (type, rw: CARDINAL; tokpos: CARDINAL;
+                                       message: ARRAY OF CHAR) ;
+VAR
+   error: CARDINAL ;
+BEGIN
+   error := MakeError (tokpos, MakeKey (message)) ;
+   IF GetSType (type) # NulSym
+   THEN
+      type := GetSType (type)
+   END ;
+   PushTFrwtok (error, type, rw, tokpos)
+END BuildDesignatorPointerError ;
+
 
 (*
    BuildDesignatorArray - Builds the array referencing.
@@ -11819,13 +11838,13 @@ END DebugLocation ;
 PROCEDURE BuildDesignatorPointer (ptrtok: CARDINAL) ;
 VAR
    combinedtok,
-   exprtok    : CARDINAL ;
+   destok    : CARDINAL ;
    rw,
    Sym1, Type1,
    Sym2, Type2: CARDINAL ;
 BEGIN
-   PopTFrwtok (Sym1, Type1, rw, exprtok) ;
-   DebugLocation (exprtok, "expression") ;
+   PopTFrwtok (Sym1, Type1, rw, destok) ;
+   DebugLocation (destok, "des ptr expression") ;
 
    Type1 := SkipType (Type1) ;
    IF Type1 = NulSym
@@ -11834,33 +11853,44 @@ BEGIN
    ELSIF IsUnknown (Sym1)
    THEN
       MetaError1 ('{%1EMad} is undefined and therefore {%1ad}^ cannot be 
resolved', Sym1)
-   ELSIF IsPointer (Type1)
-   THEN
-      Type2 := GetSType (Type1) ;
-      Sym2 := MakeTemporary (ptrtok, LeftValue) ;
-      (*
-         Ok must reference by address
-         - but we contain the type of the referenced entity
-      *)
-      MarkAsRead (rw) ;
-      PutVarPointerCheck (Sym1, TRUE) ;
-      CheckPointerThroughNil (ptrtok, Sym1) ;
-      IF GetMode (Sym1) = LeftValue
-      THEN
-         rw := NulSym ;
-         PutLeftValueFrontBackType (Sym2, Type2, Type1) ;
-         GenQuadO (ptrtok, IndrXOp, Sym2, Type1, Sym1, FALSE)    (* Sym2 := 
*Sym1 *)
-      ELSE
-         PutLeftValueFrontBackType (Sym2, Type2, NulSym) ;
-         GenQuadO (ptrtok, BecomesOp, Sym2, NulSym, Sym1, FALSE) (* Sym2 :=  
Sym1 *)
-      END ;
-      PutVarPointerCheck (Sym2, TRUE) ;       (* we should check this for *)
-                                     (* Sym2 later on (pointer via NIL)   *)
-      combinedtok := MakeVirtualTok (exprtok, exprtok, ptrtok) ;
-      PushTFrwtok (Sym2, Type2, rw, combinedtok) ;
-      DebugLocation (combinedtok, "pointer expression")
    ELSE
-      MetaError2 ('{%1ad} is not a pointer type but a {%2d}', Sym1, Type1)
+      combinedtok := MakeVirtual2Tok (destok, ptrtok) ;
+      IF IsPointer (Type1)
+      THEN
+         Type2 := GetSType (Type1) ;
+         Sym2 := MakeTemporary (ptrtok, LeftValue) ;
+         (*
+          Ok must reference by address
+          - but we contain the type of the referenced entity
+         *)
+         MarkAsRead (rw) ;
+         PutVarPointerCheck (Sym1, TRUE) ;
+         CheckPointerThroughNil (ptrtok, Sym1) ;
+         IF GetMode (Sym1) = LeftValue
+         THEN
+            rw := NulSym ;
+            PutLeftValueFrontBackType (Sym2, Type2, Type1) ;
+            GenQuadO (ptrtok, IndrXOp, Sym2, Type1, Sym1, FALSE)    (* Sym2 := 
*Sym1.  *)
+         ELSE
+            PutLeftValueFrontBackType (Sym2, Type2, NulSym) ;
+            GenQuadO (ptrtok, BecomesOp, Sym2, NulSym, Sym1, FALSE) (* Sym2 := 
 Sym1.  *)
+         END ;
+         (* We should check this for Sym2 later on (pointer via NIL).   *)
+         PutVarPointerCheck (Sym2, TRUE) ;
+         PushTFrwtok (Sym2, Type2, rw, combinedtok) ;
+         DebugLocation (combinedtok, "pointer expression")
+      ELSIF IsHiddenType (Type1) AND (GetModuleScope (Type1) # 
GetCurrentModuleScope ())
+      THEN
+         MetaErrorT1 (ptrtok,
+                      '{%1Ead} is declared with an opaque type from a 
different module and cannot be dereferenced',
+                      Sym1) ;
+         MarkAsRead (rw) ;
+         BuildDesignatorPointerError (Type1, rw, combinedtok, 'bad opaque 
pointer dereference')
+      ELSE
+         MetaError2 ('{%1Ead} is not a pointer type but a {%2d}', Sym1, Type1) 
;
+         MarkAsRead (rw) ;
+         BuildDesignatorPointerError (Type1, rw, combinedtok, 'bad pointer 
dereference')
+      END
    END
 END BuildDesignatorPointer ;
 
diff --git a/gcc/m2/gm2-compiler/P3Build.bnf b/gcc/m2/gm2-compiler/P3Build.bnf
index b68f3e1192c6..d181f2381dfb 100644
--- a/gcc/m2/gm2-compiler/P3Build.bnf
+++ b/gcc/m2/gm2-compiler/P3Build.bnf
@@ -54,7 +54,7 @@ FROM DynamicStrings IMPORT String, InitString, KillString, 
Mark, ConCat, ConCatC
 FROM M2Printf IMPORT printf0, printf1 ;
 FROM M2Debug IMPORT Assert ;
 FROM P2SymBuild IMPORT BuildString, BuildNumber ;
-FROM M2MetaError IMPORT MetaErrorT0 ;
+FROM M2MetaError IMPORT MetaErrorT0, MetaErrorT2 ;
 FROM M2CaseList IMPORT ElseCase ;
 
 FROM M2Reserved IMPORT tokToTok, toktype,
@@ -1085,15 +1085,14 @@ SubDesignator := "."                                    
                   % VAR
                                                                                
 n1 := GetSymName(Sym) ;
                                                                                
 IF IsModuleKnown(GetSymName(Sym))
                                                                                
 THEN
-                                                                               
    WriteFormat2('%a looks like a module which has not been globally imported 
(eg. suggest that you IMPORT %a ;)',
+                                                                               
    WriteFormat2('%a looks like a module which has not been globally imported 
(eg. suggest that you IMPORT %a)',
                                                                                
    n1, n1)
                                                                                
 ELSE
                                                                                
    WriteFormat1('%a is not a record variable', n1)
                                                                                
 END
                                                                              
ELSIF NOT IsRecord(Type)
                                                                              
THEN
-                                                                               
 n1 := GetSymName(Type) ;
-                                                                               
 WriteFormat1('%a is not a record type', n1)
+                                                                               
 MetaErrorT2 (tok, "the type of {%1ad} is not a record (but {%2ad}) and 
therefore it has no field", Sym, Type) ;
                                                                              
END ;
                                                                              
StartScope(Type) %
                  Ident
diff --git a/gcc/testsuite/gm2.dg/pim/fail/badopaque.mod 
b/gcc/testsuite/gm2.dg/pim/fail/badopaque.mod
new file mode 100644
index 000000000000..1d67bf9e6817
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/pim/fail/badopaque.mod
@@ -0,0 +1,15 @@
+
+(* { dg-do compile } *)
+(* { dg-options "-g" } *)
+
+MODULE badopaque ;  
+
+FROM opaquedefs IMPORT OpaqueA ;
+
+VAR
+   a: OpaqueA ;
+   c: CARDINAL ;
+BEGIN
+   c := 123 ;
+   a^ := c     (* { dg-error "with an opaque type" }  *)
+END badopaque.
diff --git a/gcc/testsuite/gm2.dg/pim/fail/badopaque2.mod 
b/gcc/testsuite/gm2.dg/pim/fail/badopaque2.mod
new file mode 100644
index 000000000000..80f9324d2404
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/pim/fail/badopaque2.mod
@@ -0,0 +1,17 @@
+
+(* { dg-do compile } *)
+(* { dg-options "-g" } *)
+
+MODULE badopaque2 ;  
+
+FROM opaquedefs IMPORT OpaqueB ;
+
+VAR
+   b: OpaqueB ;
+   c: CARDINAL ;
+BEGIN
+   c := 123 ;
+   b^.width := c  (* { dg-bogus "unnamed" } *)
+   (* { dg-error "cannot be dereferenced" "b^.width" { target *-*-* } 14 } *)  
 
+   (* { dg-error "has no field" "no field" { target *-*-* } 14 } *)   
+END badopaque2.
diff --git a/gcc/testsuite/gm2.dg/pim/fail/dg-pim-fail.exp 
b/gcc/testsuite/gm2.dg/pim/fail/dg-pim-fail.exp
new file mode 100644
index 000000000000..09ea4f755102
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/pim/fail/dg-pim-fail.exp
@@ -0,0 +1,34 @@
+# Copyright (C) 2025 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/>.
+
+# Compile tests, no torture testing.
+#
+# These tests raise errors in the front end; torture testing doesn't apply.
+
+# Load support procs.
+load_lib gm2-dg.exp
+
+gm2_init_pim4 $srcdir/$subdir
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.mod]] "" ""
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gm2.dg/pim/fail/opaquedefs.def 
b/gcc/testsuite/gm2.dg/pim/fail/opaquedefs.def
new file mode 100644
index 000000000000..3432a655be33
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/pim/fail/opaquedefs.def
@@ -0,0 +1,7 @@
+DEFINITION MODULE opaquedefs ;  
+
+TYPE
+   OpaqueA ;
+   OpaqueB ;   
+
+END opaquedefs.
diff --git a/gcc/testsuite/gm2.dg/pim/fail/opaquedefs.mod 
b/gcc/testsuite/gm2.dg/pim/fail/opaquedefs.mod
new file mode 100644
index 000000000000..7c253292a2d2
--- /dev/null
+++ b/gcc/testsuite/gm2.dg/pim/fail/opaquedefs.mod
@@ -0,0 +1,13 @@
+(* { dg-do compile } *)
+(* { dg-options "-g -c" } *)
+
+IMPLEMENTATION MODULE opaquedefs ;
+
+TYPE
+   OpaqueA = POINTER TO CARDINAL ;
+   OpaqueB = POINTER TO RECORD
+                           width : CARDINAL ;
+                           height: CARDINAL ;
+                        END ;
+
+END opaquedefs.
diff --git a/gcc/testsuite/lib/gm2-dg.exp b/gcc/testsuite/lib/gm2-dg.exp
index 62081f863252..eaed554014f8 100644
--- a/gcc/testsuite/lib/gm2-dg.exp
+++ b/gcc/testsuite/lib/gm2-dg.exp
@@ -15,6 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 load_lib gcc-dg.exp
+load_lib gm2.exp
 
 # Define gm2 callbacks for dg.exp.
 
@@ -75,3 +76,4 @@ proc gm2-dg-runtest { testcases flags default-extra-flags } {
        }
     }
 }
+

Reply via email to