Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an attribute to tell the compiler to ignore a missing return statement?

Tags:

I don't believe this is a duplicate because the function does return in the happy path. Using the attribute no-return allows the compiler to optimise on the assumption that the function never returns, which is not the case here.

I have come C code that either returns a pointer or calls another function to exit out of the program. This is in an if statement, so either it returns the result or exits. As the function returns a void *, the compiler warns that it's possible the function won't return a value (which is of course true):

error: control reaches end of non-void function [-Werror=return-type]

I can get around this by just adding return *temp; to the end of the function but I'd like to be clear in my intent by having something like the unused variable attribute:

__attribute__((__unused__))

That way I can leave -Wall on and not have to add unnecessary or possibly confusing code.

I'd also be up for rewriting the code if there's a better way to express this intent.

The code looks something like:

void *get_memory() {
    void *temp = malloc(100);
    if (temp) {
        // do some setup work
        return temp;
    } else {
        exit_program_with_epic_fail();
    }
    // Compiler warns if the following line isn't present
    return temp;
}
like image 914
PeterM Avatar asked Jun 26 '19 08:06

PeterM


2 Answers

There are 2 ways to get rid of the warning:

  • tag the exit_program_with_epic_fail() function with the appropriate attribute, _Noreturn in C11, but there is no portable way to do this to pre-C11 compilers. Many compilers support __attribute__((noreturn)), notably gcc, clang and tinycc, but it is an compiler specific extension.
  • reorganise the code to let the compiler see the function always return.

Here is a modified version:

void *get_memory(void) {
    void *temp = malloc(100);
    if (!temp) {
        exit_program_with_epic_fail();
    }
    // do some setup work
    return temp;
}
like image 108
chqrlie Avatar answered Nov 03 '22 00:11

chqrlie


This seems to be a pure design problem.

The warning/error "control reaches end of non-void function" isn't the problem, it is rather just an indicator telling you where the actual problem is.

You could/should simply rewrite the function as

void *get_memory (void) 
{
  void *temp = malloc(100);
  if(temp != NULL)
  {
    // do stuff
  }

  return temp;
}

And leave error handling to the caller. Because it is not an allocation function's job to terminate the application - that's bad design.

Alternative version with detailed error handling:

typedef enum
{
  OK,
  ERR_OUTOFMEMORY,
  ...
} err_t;

err_t get_memory (void** mem) 
{
  *mem = malloc(100);
  if(*mem == NULL)
  {
    return ERR_OUTOFMEMORY;
  }

  // do stuff

  return OK;
}
like image 23
Lundin Avatar answered Nov 03 '22 00:11

Lundin