Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to suppress "warning: control reaches end of non-void function"

I have some PowerPC assembly code translated with a gcc cross compiler with this function:

uint32_t fill_cache(void)
{
    __asm__ ("addi 3, 0, 0\n");  /* R3 = 0 */
    /* More asm here modifying R3 and filling the cache lines. */
}

which, under the PowerPC EABI, returns the value computed in R3. When compiling I get

foo.c:105: warning: control reaches end of non-void function

Is there a way to teach gcc that a value is actually returned? Or is there a way to suppress the warning (without removing -Wall or adding -Wno-*)? I would like to very selectively suppress this warning for only this function in order to leave the general warning level as high as possible.

It is not an option to make this function return void since the value computed is required by the caller.

like image 625
Jens Avatar asked Apr 10 '13 13:04

Jens


2 Answers

Solution 1: with diagnostic pragmas you can locally suppress certain diagnostic checks. The specific option (which also is implied by -Wall) that complains for no return in a non-void function is -Wreturn-type. So the specific code to suppress the warning is:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
/* Your code here */
#pragma GCC diagnostic pop

You can find out which option is causing the warning by compiling with -fdiagnostics-show-option. It will simply append the option to the warning message.

Solution 2: define a register variable and put it in the desired register. Refer to the variable in an inline assembler template, with the resulting code:

uint32_t fill_cache(void)
{
  register uint32_t cacheVal __asm__ ("r3");

  __asm__ __volatile__ ("addi %0, 0, 0" : "=r" (cacheVal));
  /* More code here */

  return cacheVal;
}

The volatile modifier is to ensure that the instruction is not removed or in some other way affected undesirably by the optimization strategy.

Solution 2 is preferred for at least two reasons:

  1. The value of a no returning non-void function is undefined as far as the standard is concerned.
  2. There's no risk of suppressing (new) diagnostic warnings there was no intention to suppress in the first place.
like image 148
Robert Johansson Avatar answered Sep 28 '22 04:09

Robert Johansson


Function could be declared as naked, in this case compiler would not generate prolog & epilog and would assume that programmer preserves all necessary registers and puts output value into correct register(s) before return.

uint32_t fill_cache(void) __attribute__((naked)); // Declaration
// attribute should be specified in declaration not in implementation

uint32_t fill_cache(void) 
{
    __asm__ ("addi 3, 0, 0\n");  /* R3 = 0 */
    /* More asm here modifying R3 and filling the cache lines. */
}

A bit late but maybe someone will step in this as well :)

PS: For my best knowledge __asm__ as well as __volatile__ are std=c89 syntax. Practically there is not difference between __asm__ & asm in GNU GCC. But the modern approach is underscoreless style: asm volatile.

asm_language

like image 33
user3124812 Avatar answered Sep 28 '22 05:09

user3124812