Menu

#3822 Function pointer declaration following a block erases variable declaration within

closed-fixed
None
Front-end
5
2025-02-01
2025-01-21
No

Some strange error. I can't even describe this error.

The error occurs because of the void(*fun)(void);line.

D:\Infocom\Developming\DWINosvetitel\firmware_DWINoswetitel\bug8>sdcc -v 
SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/sm83/tlcs90/ez80_z80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8 TD- 4.5.0 #15237 (MINGW64)
published under GNU General Public License (GPL)

D:\Infocom\Developming\DWINosvetitel\firmware_DWINoswetitel\bug8>sdcc -mmcs51 --opt-code-size --fverbose-asm -c -o main.rel main.c 
main.c:6: error 20: Undefined identifier '_f'
main.c:6: warning 127: non-pointer type cast to generic pointer
from type 'int fixed'
  to type 'const-char generic* fixed'
2 Attachments

Discussion

  • Benedikt Freisen

    • summary: Strange error --> Function pointer declaration following a block erases variable declaration within
     
  • Benedikt Freisen

    I have no idea, either, but the example can be simplified a bit:

    void main(void) {
    
        if (1) {
            char c;
            c;
        }
    
        void(*fun)(void);
        fun;
    }
    

    The c in line 5 is then ostensibly an undefined identifier.

     
    • Janko Stamenović

      On this version:

      SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/sm83/tlcs90/ez80_z80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8 TD- 4.5.0 #15224 (MINGW64)
      published under GNU General Public License (GPL)
      

      that example with if doesn't fail, but:

      void main(void) {
          for (;;) {
              char c;
              c;
          }
          void(*fun)(void);
          fun;
      }
      

      fails:

      a.c:4: error 20: Undefined identifier 'c'
      a.c:7: warning 85: in function main unreferenced local variable : 'c'
      

      Dumping AST I can only conclude that what's dumped as AST is already "wrong", and the error matches that (there's a.c:4: UNDEFINED SYMBOL (L3:0 B4 c=0000000e124109b0 @ 0000000e12413e10) type (int fixed)

       
      • Benedikt Freisen

        Alright. Maybe your first observation already helps us narrow it down, because I have actually been testing with the next branch with the newly implemented if-declaration support for which I reused quite a bit of code from loop counter declaration within for loop headers. The for loop above does not have any declaration, but the code that handles scoping is still there.

        EDIT: I.e. we don't know where the original bug comes from, but we do know that [r15233] transplanted it from for to if.

         

        Related

        Commit: [r15233]


        Last edit: Benedikt Freisen 2025-01-21
        • Benedikt Freisen

          The bug could be caused by this part at the end of the function_declarator : declarator2 '(' parameter_type_list ')' production rule:

          // if this was a pointer (to a function)
          if (!IS_FUNC($1->type))
              cleanUpLevel(SymbolTab, NestLevel + LEVEL_UNIT);
          

          This looks very suspicious and could be loosely related to the issue described in this post in [bugs:#3289].
          The line with the cleanUpLevel call looks like it blindly cleans up part of the symbol table based on the nest level alone. (It should rather only clean up the symbols created for function parameters.)

           
          👍
          1

          Related

          Bugs: #3289


          Last edit: Benedikt Freisen 2025-01-22
          • Benedikt Freisen

            Without that line, this works fine:

            void main(void) {
                for (;;) {
                    char c;
                    c;
                }
                void (*fun)(int i);
                fun;
                int i;
                i;
            }
            

            The mechanism to clean up symbols appears to be already there in the lines directly above the special case with cleanUpLevel for function pointers:

            /* nest level was incremented to take care of the parms  */
            leaveBlockScope (currBlockno);
            NestLevel -= LEVEL_UNIT;
            currBlockno = STACK_POP(blockNum);
            seqPointNo++; /* not a true sequence point, but helps resolve scope */
            

            So maybe the special case is just leftover code from six or seven years ago. @epetrich, do you have an opinion on this?

            EDIT: All existing regression tests still pass.

             
            👍
            1

            Last edit: Benedikt Freisen 2025-01-25
  • Benedikt Freisen

    But weirdly enough, this apparently works:

    typedef void (*my_fp_type)(void);
    
    void main(void) {
    
        if (1) {
            char c;
            c;
        }
    
        my_fp_type fun;
        fun;
    }
    
     
  • Benedikt Freisen

    Fixed in [r15257].
    I left the offending lines in there as a comment block, because I am not entirely sure why they were still in there and whether they still served a purpose.

     

    Related

    Commit: [r15257]

  • Benedikt Freisen

    • status: open --> closed-fixed
    • assigned_to: Benedikt Freisen
     

Log in to post a comment.

MongoDB Logo MongoDB