sinelaw
sinelaw

Reputation: 16553

GCC, empty structs, and -Wunused-result

The following program causes gcc to emit -Wunused-result:

struct Empty { };

__attribute__((warn_unused_result))
static struct Empty func(void) {
  return (struct Empty){};
}

int main(void) {
  struct Empty res = func();
  (void)res;
  return 0;
}

Compiler output:

gcc -Wall -Wextra /tmp/test.c -c -o /tmp/test
/tmp/test.c: In function ‘main’:
/tmp/test.c:12:22: warning: ignoring return value of ‘func’, declared with attribute warn_unused_result [-Wunused-result]
   struct Empty res = func();
                      ^~~~~~

clang doesn't emit a warning.

Is this a bug or a feature?

(Empty struct as return value is useful in some code generation scenarios where a return value is always expected, but that is beside the question)

Upvotes: 0

Views: 311

Answers (1)

zwol
zwol

Reputation: 140485

This does indeed appear to be a bug in GCC. I filed a bug report with them.

A workaround is to include a nameless bitfield in the "empty" structure:

struct Empty {char:1;};

extern void use_empty(struct Empty);

__attribute__((warn_unused_result))
extern struct Empty make_empty(void);

void should_warn(void)
{
    make_empty();
}

void shouldnt_warn_1(void)
{
    use_empty(make_empty());
}

void shouldnt_warn_2(void)
{
    struct Empty e = make_empty();
    use_empty(e);
}

warns only for 'should_warn'. This does mean that sizeof(struct Empty) is 1 rather than 0, and GCC generates an additional move instruction in both shouldnt_warn_1 and shouldnt_warn_2, but those are probably acceptable side-effects.

(Note that both a struct with no fields at all, and a struct with no named fields, are GNU extensions — in ISO C you must include at least one named field in every struct. Nameless bitfields, however, are standard, just obscure.)

Upvotes: 1

Related Questions