#2068 SDCC allows address-of register variable

Maarten Brock
Brian Ruthven

K&R C (section 4.7) states that passing the address of a "register" variable is not allowed. Thus the following program should fail but doesn't:

======== begin ========
extern int foo(int *);

int mumble(int val)
register int r = val;

return (foo(&r));
======== end ========

gcc and Sun's Studio 12 flag the address-of-register error:

$ /opt/SUNWspro/bin/cc -c test.c
"test.c", line 8: cannot take address of register: r
cc: acomp failed for test.c
$ gcc -c test.c
test.c: In function ‘foo’:
test.c:8:2: error: address of register variable ‘r’ requested
$ /build/sdcc/sdcc-20120817-8070/bin/sdcc -c test.c
$ echo $?

I realise that the "register" storage class is a hint, and the compiler is entitled to elect not to keep it in a register, but the K&R book says:
"And it is not possible to take the address of a register variable (a topic covered in Chapter 5), regardless of
whether the variable is actually placed in a register."

Thus the C front end should reject the above test program.


  • Sergey

    It strongly depends from target platform.
    For example, register set of MSC-51 physically is simply "first page" of IRAM.
    Thus, in that case, "memory address" is legally applicable to register variable.

  • sdcc does not strongly try to obey the register keyword, and uses it more as a hint in register allocation. AFAIK, as soon as the address is taken, the variable is not placed in a register. Is being able to take the address of register variables useful to any users? If not we should emit an error for it; if it is useful to some we should emit a warning.


  • Maarten Brock
    Maarten Brock

    According to the C standard the register keyword is just a hint to access the data as fast as possible. But it does prohibit taking the address of the variable. So even though it is possible to take the address of a register on an mcs51 I still think we should create an error.

    On the other hand if the variable comes without register keyword but SDCC placed it in a register anyway, SDCC is allowed to take the address of this register. But I doubt this will ever happen.

    I think the backend implementations can all choose what to do with 'register' variables. For example, place them in DATA, ZERO PAGE or real registers.

  • Brian Ruthven
    Brian Ruthven

    Agreed. The back end can place the variable where it likes (and this could be registers for all variables), but the front end should reject the explicit register hint followed by address-of.

    The mcs51 case fits the first part of that - i.e. the back end elects to place all variables in registers and can pass "address-of" those registers, but it should never be asked to provide address-of in the case where the C variable was declared with the register keyword.

    IMO this should be fixed at the front end to provide parity across all back end ports.

    • Category: --> Front-end
    • Group: --> fixed
  • Maarten Brock
    Maarten Brock

    • status: open --> closed-rejected
    • assigned_to: Maarten Brock
  • Maarten Brock
    Maarten Brock

    I cannot reproduce this problem. The current SDCC generates error 35 on this code. And the failing test was already present in revision 3!

    I guess Philipps 'fixed' was once again an artifact of setting the Category.

  • I jst checked: For me, the example code from the bug reports compiles without error in some ports, while it gives an error 35 in other ports. Shouldn't this be handled in the front-end?


  • Brian Ruthven
    Brian Ruthven

    If there is no "register" keyword, then the front-end and/or back-end are free to place the storage where it likes (register or otherwise).

    However, if the "register" keyword is present, the back-end is still free to place it where it likes (using "register" as a hint and ignoring it if desired), but the front-end should reject using the address-of facility with a variable declared as a register. The back-end implementation has no bearing on this - the K&R C spec is clear on this, is it not?

    I've not checked later C specs on this, but there should be some level of consistency on this between the different ports (I didn't realise they were inconsistent when I raised the bug). As it appears to be covered by the C spec, IMO the front end is the place to deal with this consistently.

    • status: closed-rejected --> open
  • Maarten Brock
    Maarten Brock

    But it IS checked in the front-end in SDCCast.c line 3355. I admit I only checked mcs51, but Brian didn't use a different target either in the first post. And the rest in here seemed a theoretical discussion to me.

    A retry for Z80 shows that the storage class is S_AUTO instead of S_REGISTER.

  • Maarten Brock
    Maarten Brock

    The problem was in SDCCsymt.c where mergeSpec and checkSClass overwrite the S_REGISTER storage class. There may be more places still. Now fixed in SDCC 3.3.2 #8931.

    What's also weird is that you can't do
    char __xdata * register p;
    But must write
    register char __xdata * p;
    And in this case p does not get storage class S_REGISTER.

  • Maarten Brock
    Maarten Brock

    • status: open --> closed-fixed