Informando clang que assembly embutido lê uma região específica da memória

O GCC (todas as versões que posso testar convenientemente) pode ser informado de que uma instrução de montagem em linha lê uma região específica da memória (expressa como um ponteirop e um tamanhon) com esse construto reconhecidamente estranho:

asm ("..." : : "m" (*(struct { char x[n]; } *)p));

No entanto, isso não funciona no clang (3. [45]), você recebe um erro grave:

 error: fields must have a constant size: 'variable
      length array in structure' extension will never be supported
 asm ("..." : : "m" (*(struct {char x[n];} *)p));
                                    ^

Existe (idealmente) uma construção diferente que produzirá o mesmo efeito nos dois compiladores, ou (na sua falta) uma construção diferente que produzirá o mesmo efeito apenas no clang?

Observe que, no caso em que me preocupo, não insiro instruções reais de montagem; o objetivo da construção é direcionar o compilador para não excluir um aparentemente mortomemset. Assim, a "construção diferente" poderia perfeitamente não envolver montagem em linha. No entanto, sugira construções que lêemarbitrário memória ou gerar código adicional, apenas se não houver alternativa. Além disso, NÃO sugiramemset_s, explicit_bzero, ou similar; esta é uma tentativa deimplemento um fallback para essas funções sem precisar hackear o compilador.

O programa de demonstração em grande escala segue -

#include <string.h>

extern void foo(const char *a, const char *b, const char *c, char *d);

void bar(const char *x, char *y, size_t n)
{
  char w[16];
  char v[n];
  memset(w, 0x11, n);
  memset(v, 0x22, n);

  foo(w, v, x, y);

  memset(w, 0, 16);
  memset(v, 0, n);
  asm ("" : : "m" (*(struct {char _[n];} *)v));
}

- conforme compilado pelo gcc 5.0 em-O2 -S, x86-64, CFI goo elided -

bar:
        pushq   %rbp
        leaq    15(%rdx), %rax
        movq    %rsp, %rbp
        pushq   %r14
        andq    $-16, %rax
        movq    %rsi, %r14
        pushq   %r13
        movl    $17, %esi
        movq    %rdi, %r13
        pushq   %r12
        leaq    -48(%rbp), %rdi
        pushq   %rbx
        movq    %rdx, %rbx
        subq    $16, %rsp
        subq    %rax, %rsp
        call    memset
        movq    %rbx, %rdx
        movq    %rsp, %rdi
        movl    $34, %esi
        call    memset
        movq    %r14, %rcx
        movq    %r13, %rdx
        movq    %rsp, %rsi
        leaq    -48(%rbp), %rdi
        call    foo
        movq    %rbx, %rdx
        xorl    %esi, %esi
        movq    %rsp, %rdi
        call    memset
        leaq    -32(%rbp), %rsp
        popq    %rbx
        popq    %r12
        popq    %r13
        popq    %r14
        popq    %rbp
        ret

- o objetivo é obter omesmo número de memória de bloco preenche o clang. Dois estão errados, mas quatro também estão errados.

questionAnswers(0)

yourAnswerToTheQuestion