Declaração de mudanças de método que significam de símbolo

Para o seguinte código:

struct foo {}; struct A { typedef foo foo_type; void foo(); }; 

O GCC apresenta um erro no compilador:

 test.cpp:7:14: error: declaration of 'void A::foo()' [-fpermissive] void foo(); ^ test.cpp:1:8: error: changes meaning of 'foo' from 'struct foo' [-fpermissive] struct foo {}; ^ 

Mas clang aceita sem erros de compilador. Quem está certo?

Note que se o typedef for removido ou alterado para typedef ::foo foo_type , tanto o gcc como o clang aceitam o código.

O gcc está correto, mas o clang não é necessário para fornecer um diagnóstico (3.3.7):

Um nome N usado em uma class S deve se referir à mesma declaração em seu contexto e quando reavaliado no escopo completo de S. Nenhum diagnóstico é necessário para uma violação desta regra.

Isso é por causa de como o escopo de class funciona. O foo do void foo(); é visível em todo o escopo da class A , portanto, a declaração de void foo(); altera o significado de foo no typedef de referir-se a struct foo para o nome da function foo .