This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/MSP-CGT: BUG: Arithmetic on pointer to void produces incorrect code in comparisons (and optimisations)

Part Number: MSP-CGT

Tool/software: TI C/C++ Compiler

If I have the following code

extern unsigned char __heap[512];

#define mid     ((void *)__heap + 256)
#define end     ((void *)__heap + 512)

void func(void)
{
    void *ptr = end;
    do {
        *(unsigned char *)ptr = 1;
        ptr -= 32;
    } while (ptr > mid);
}

I get suppressible warnings about void pointer arithmetic but the produced code is incorrect under all optimisation levels.

Under opt_level=0 I get the following:

;** 9   -----------------------    ptr = &__heap+512;
    .dwpsn  file "ptrloop.c",line 9,column 15,is_stmt,isa 0
        MOV.W     #__heap+512,r15       ; [] |9| 
;* --------------------------------------------------------------------------*
;*   BEGIN LOOP $C$L1
;*
;*   Loop source line                : 10
;*   Loop closing brace source line  : 13
;*   Known Minimum Trip Count        : 1
;*   Known Maximum Trip Count        : 4294967295
;*   Known Max Trip Count Factor     : 1
;* --------------------------------------------------------------------------*
$C$L1:    
;** -----------------------g2:
;** 11  -----------------------    *(unsigned char *)ptr = 1u;
    .dwpsn  file "ptrloop.c",line 11,column 9,is_stmt,isa 0
        MOV.B     #1,0(r15)             ; [] |11| 
;** 13  -----------------------    if ( (ptr -= 32) > &__heap ) goto g2;
    .dwpsn  file "ptrloop.c",line 13,column 14,is_stmt,isa 0
        SUB.W     #32,r15               ; [] |13| 
        CMP.W     #__heap+1,r15         ; [] |13| 
        JHS       $C$L1                 ; [] |13| 
                                          ; [] |13| 
;**     -----------------------    return;

where you can see that the comparison is against `__heap+1` rather than `__heap+257`.

Under opt_level=4 I get the following:

        MOV.W     #__heap+512,r15       ; [] |9| 
;**     -----------------------    #pragma MUST_ITERATE(16, 16, 16)
;**     -----------------------    #pragma LOOP_FLAGS(0u)
;**     -----------------------    L$1 = 16;
        MOV.W     #16,r14               ; [] 
;* --------------------------------------------------------------------------*
;*   BEGIN LOOP $C$L1
;*
;*   Loop source line                : 10
;*   Loop closing brace source line  : 13
;*   Known Minimum Trip Count        : 16
;*   Known Maximum Trip Count        : 16
;*   Known Max Trip Count Factor     : 16
;* --------------------------------------------------------------------------*
$C$L1:    
;** -----------------------g2:
;** 11  -----------------------    *(unsigned char *)ptr = 1u;
    .dwpsn  file "ptrloop.c",line 11,column 9,is_stmt,isa 0
        MOV.B     #1,0(r15)             ; [] |11| 
;** 13  -----------------------    ptr -= 32;
    .dwpsn  file "ptrloop.c",line 13,column 14,is_stmt,isa 0
        SUB.W     #32,r15               ; [] |13| 
;** 13  -----------------------    if ( L$1 = L$1-1 ) goto g2;
        SUB.W     #1,r14                ; [] |13| 
        JNE       $C$L1                 ; [] |13| 
                                          ; [] |13| 
;**     -----------------------    return;

Where you can see that the loop runs 16 times where it should only run 8.

From what I can tell I don't have a problem if the result of void pointer arithmetic is stored, only in comparisons.  This should be fixed, or else the void pointer arithmetic warning should be changed to an error.

  • According to Harbison and Steele in the section on additive operators (7.6.2) : "It is invalid for p [a pointer] to be a function pointer or to have type void *".

  • Thank you for notifying us of this problem and for providing a concise test case.  I can reproduce the same result.  I filed the entry EXT_EP-9941 to have this investigated.  You are welcome to follow it with the link below in my signature.

    Keith Barkley is correct to note that math or comparison operations for a pointer to void is not defined.  That said, many compilers, including the TI MSP430 compiler, handle it by pretending it points to char instead of void.

    Parakleta said:
    or else the void pointer arithmetic warning should be changed to an error.

    Many warning diagnostics, including this one, can be changed to an error on the compiler command line.  Add the compiler option --display_error_number, and the compiler shows the diagnostic number in the message.

    % cl430 --opt_level=4 -s -vmspx --display_error_number file.c
    "file.c", line 8: warning #1219-D: arithmetic on pointer to void or function type
    "file.c", line 11: warning #1219-D: arithmetic on pointer to void or function type
    "file.c", line 12: warning #1219-D: arithmetic on pointer to void or function type

    Use the option --diag_error=number to have a diagnostic with that number be handled as an error.

    % cl430 --opt_level=4 -s -vmspx --display_error_number --diag_error=1219 file.c
    "file.c", line 8: error #1219-D: arithmetic on pointer to void or function type
    "file.c", line 11: error #1219-D: arithmetic on pointer to void or function type
    "file.c", line 12: error #1219-D: arithmetic on pointer to void or function type
    3 errors detected in the compilation of "file.c".
    
    >> Compilation failure

    Thanks and regards,

    -George

  • Keith is correct that the C standard does not allow pointer arithmetic on pointers to void.

    George is correct that the TI compilers nonetheless support this GCC-like extension in relaxed mode.

    This test case demonstrates a bug, which will be fixed eventually.

    In the meantime, the workaround is to change all of the "void*" pointers to "unsigned char *" pointers, which will have the added benefit of being allowed in strict ANSI mode.