Uma declaração usando “auto” corresponde a uma declaração externa que usa um especificador de tipo concreto?

Considere o seguinte programa:

extern int x; auto x = 42; int main() { } 

Clang 3.5 aceita ( demonstração ao vivo ), GCC 4.9 e VS2013 não ( demonstração ao vivo para o primeiro ). Quem está certo e onde está o comportamento correto especificado no Padrão C ++?

Há surpreendentemente pouco no padrão sobre isso. Sobre tudo que ouvimos sobre redeclaração é:

[C++11: 3.1/1]: Uma declaração (Cláusula 7) pode introduzir um ou mais nomes em uma unidade de tradução ou redeclarar nomes introduzidos por declarações anteriores. [..]

e a única parte relevante da semântica do auto :

[C++11: 7.1.6.4/3]: Caso contrário, o tipo da variável é deduzido do seu inicializador. [..]

(lembrando-nos que o tipo de x é int ).

Sabemos que uma variável deve receber o mesmo tipo em todas as declarações:

[C++11: 3.5/10]: Após todos os ajustes de tipos (durante os quais typedefs (7.1.3) são substituídos por suas definições), os tipos especificados por todas as declarações referentes a uma dada variável ou function devem ser idênticos , exceto que as declarações de um object de matriz podem especificar tipos de matriz que diferem pela presença ou ausência de um limite de matriz principal (8.3.4). Uma violação desta regra no tipo de identidade não requer um diagnóstico.

e o “afinal de contas de ajustes de tipos” deveria cuidar de qualquer pergunta relativo à participação de auto em tudo isto; minha interpretação, então, é que isso é inerentemente uma redeclaração (e definição) válida do x no escopo global com o tipo int , e que o Clang está correto . Mesmo se propusermos que o auto não conta como “ajuste do tipo”, uma vez que nenhum diagnóstico é necessário, na pior das hipóteses todas as implementações listadas são compatíveis à sua maneira.

Eu acredito que o GCC e o Visual Studio estão tomando o seguinte como inspiração:

[C++11: 7.1.6.4/5]: Um programa que usa auto em um contexto não explicitamente permitido nesta seção é mal formado.

… Mas acho que isso é míope. Parece improvável que a linguagem padrão tenha a intenção de proibir as regras usuais de redeclaração, apenas porque elas não são repetidas ou explicitamente referenciadas no 7.1.6.4 .

C ++ 14 acrescenta redação relacionada a declarações de funções com tipos deduzidos:

[C++14: 7.1.6.4/13]: Declarações ou especializações de uma function ou modelo de function com um tipo de retorno declarado que usa um tipo de espaço reservado também devem usar esse espaço reservado, não um tipo deduzido. [..]

Por simetria, pode-se sugerir que, no seu caso int , pretende-se que o GCC e o VS estejam corretos ao rejeitar o programa. No entanto, essa é uma característica diferente (uma vez que a dedução não pode ser aplicada a meras declarações) e, portanto, um cenário diferente.

De qualquer maneira, a redação padrão melhorada ajudaria aqui. Eu considero um defeito editorial [razoavelmente menor].