Skip to content

C, C11 and later: padding not set to “zero bits” in compound literal #58945

Open
@pascal-cuoq

Description

@pascal-cuoq

Consider the C program:

#include <stdint.h>
#include <string.h>
#include <stdio.h>

struct record {
  uint64_t id;
  uint32_t gold_coins;
};

__attribute__((noinline))
void sink(void*p) {
    static const struct record ref = {1};
    if (memcmp(&ref, p, sizeof ref))
      printf("different\n");
    else
      printf("identical\n");
}

int main(void) {
    struct record a = {1};
    sink(&a);

    void *p = &(struct record){1};
    sink(p);
}

The program above compiled with Clang 15.0.0 using clang -std=c17 -O2 prints:

identical
different

Compiler Explorer link

The “different” output shows that the padding of the compound literal was not set to 0. Here's the relevant snippet of the generated assembly:

        movq    $1, (%rsp)
        movl    $0, 8(%rsp)
        movq    %rsp, %rdi
        callq   sink

This might indicate a bug in Clang, depending on how one interprets the words “the remainder of the aggregate” in C17 6.7.9:21:

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

If “the remainder of the aggregate” is taken to include padding, then the padding should be zeroed in the compound literal in my example according to C17 6.7.9:10, which applies in this case per the phrase “the same as objects that have static storage duration” in 6.7.9:21.

If “the remainder of the aggregate” is taken not to include padding, then Clang needlessly generates and copies zero bits in the case of the automatic variable a. From the assembly output:

.L__const.main.a:
        .quad   1                               # 0x1
        .long   0                               # 0x0
        .zero   4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions