Menu

#645 Access to global duplicated symbol is captured by local symbol

closed
nobody
compiler
2021-09-26
2013-01-05
No

From a scope block, the syntax for accessing a duplicated symbol defined in a namespace/UDT is captured by the local symbol, making impossible the desired access.


Simple example with a procedure inside a namespace:

Namespace NS
  Dim x As Integer = 3
  Sub S ()
    Dim x As Integer = 4
    Print "From Sub() in Namespace 'NS', access to 'NS.x' is captured by local 'x'"
    Print "x="; x, "NS.x="; NS.x
  End Sub
End Namespace

NS.S()
Sleep

Output:

From Sub() in Namespace 'NS', access to 'NS.x' is captured by local 'x'
x= 4          NS.x= 4

More complex example with 3 different failing cases:

  • procedure inside a namespace
  • procedure inside global namescape
  • member procedure inside UDT

    Dim Shared x As Integer = 1

    Type UDT
    Dim As Integer dummy
    Static As Integer x
    Declare Static Sub S ()
    End Type
    Dim As Integer UDT.x = 2

    Namespace NS
    Dim x As Integer = 3
    Sub S ()
    Dim x As Integer = 4
    Print "From Sub() in Namespace 'NS', access to 'NS.x' is captured by local 'x'"
    Print "x="; x, "NS.x="; NS.x, "UDT.x="; UDT.x, ".x="; .x
    End Sub
    End Namespace

    Sub S ()
    Dim x As Integer = 4
    Print "From Sub() in Global Namespace '.', access to '.x' is captured by local 'x'"
    Print "x="; x, "NS.x="; NS.x, "UDT.x="; UDT.x, ".x="; .x
    End Sub

    Static Sub UDT.S ()
    Dim x As Integer = 4
    Print "From Sub() in Type 'UDT', access to 'UDT.x' is captured by local 'x'"
    Print "x="; x, "NS.x="; NS.x, "UDT.x="; UDT.x, ".x="; .x
    End Sub

    NS.S()
    Print
    S()
    Print
    UDT.S()
    sleep

Output:

From Sub() in Namespace 'NS', access to 'NS.x' is captured by local 'x'
x= 4          NS.x= 4       UDT.x= 2      .x= 1

From Sub() in Global Namespace '.', access to '.x' is captured by local 'x'
x= 4          NS.x= 3       UDT.x= 2      .x= 4

From Sub() in Type 'UDT', access to 'UDT.x' is captured by local 'x'
x= 4          NS.x= 3       UDT.x= 4      .x= 1

Related

Bugs: #581
Bugs: #871
Bugs: #945

Discussion

  • fxm (freebasic.net)

    Check if there is not a link with #581 Locals break/override THIS access to inherited members

     
  • dkl

    dkl - 2014-05-08

    Indeed, I think [#581] is caused by this.

    Perhaps this could be fixed by making each scope have its own namespace - but that's a massive change to fbc's symbol tables, that will surely have a negative impact on scope creation & symbol lookup performance, or will even require lots of the code to be rewritten.

     

    Related

    Bugs: #581

    • Jeff Marshall

      Jeff Marshall - 2021-09-26

      Indeed, first glance there is a temptation to rewrite the symbol database, but that would probably take months. Digging deep in to the compiler internals, I have come up with 2 underlying causes which could be improved incrementally:

      • the global namespace and current namespace are both internally represented by a 'NULL' FBSYMBOL depending on where you look.
      • local symbols added to a namespace should not be allowed to be accessed by explicit use of that namespace

      I'm working on a pull request to address these 2 issues for shared variables (and arrays) that starts the effort to do 2 things:

      • internally use explicit namespace resolution, including the global namespace resolution operator '.' and '..' prefix rather than rely on a default of 'NULL'
      • when symbols are referenced by explicit namespace skip over any local symbols in the FBSYMCHAIN
       
  • fxm (freebasic.net)

    The linked #581 "Locals break/override THIS access to inherited members" is less troublesome because exists a simple workaround that is to access with BASE.[BASE.]...

    At opposite, faced with this bug above, there is only one possibility of workaround to access the real value of "UDT.x". This is: "Cast(UDT Ptr, 0)->x".
    No workaround for others (except differentiate the symbol names!).

     

    Last edit: fxm (freebasic.net) 2014-11-11
  • fxm (freebasic.net)

    Another variant:

    In the following example, not only does the local array 'd ()' hide the global variable 'd', but also captures the data-type of the global variable for its own data-type if it is not specified in 'redim ...':

    dim as integer d
    
    scope
      redim d(10)   '' should induce a compiler error message
      'd = 1        '' error 72: Array access, index expected
      print d(10)
    end scope
    
     
  • fxm (freebasic.net)

    Similar behavior:

    Type UDT
      Dim As Integer I
      Declare Sub test ()
      Declare Static Sub test (Byref u As UDT)
    End Type
    
    Print @UDT.test  '' error 209: Illegal non-static member access, UDT.TEST in 'Print @UDT.test'
    

    [edit]
    Behavior normal with overload procedures, because by default, the first is choosen.
    Can be solved with:
    Print ProcPtr(UDT.test, Sub(Byref As UDT))

     

    Last edit: fxm (freebasic.net) 2021-09-27
  • Jeff Marshall

    Jeff Marshall - 2021-09-26
    • labels: --> scope, namespace
    • status: open --> closed
     

Log in to post a comment.

MongoDB Logo MongoDB