Interacción entre decltype y el nombre de miembro de clase sombreando un nombre externo

Este código

int clash; struct Foo { decltype(clash) clash; }; 

comstack silenciosamente en clang, pero no comstack en gcc dando los errores

error: statement de ‘int Foo :: clash’ [-fpermissive]

error: cambia el significado de ‘clash’ de ‘int clash’ [-fpermissive]

Parece que se requieren 2 ingredientes para que surja el error:

  1. El sombreado debe hacerlo un miembro de la clase (no hay problema si se trata del scope local de una función).

  2. decltype ([shadowed name]) se debe usar en el ámbito sombreado antes de la statement de [shadowing name].

Mi pregunta es doble:

  1. ¿Está justificado gcc al rechazar este código?
  2. ¿Dónde dice eso en el estándar?

gcc es correcto, el progtwig está mal formado, aunque esta violación en particular no requiere un diagnóstico, por lo que no es necesario que proporcione uno.

Si miramos el estándar C ++ 11 ( el borrador más cercano sería N3337 ) sección 3.3.7 Alcance de clase dice:

Un nombre N usado en una clase S se referirá a la misma statement en su contexto y cuando se vuelva a evaluar en el scope completo de S. No se requiere diagnóstico para una violación de esta regla.

y la siguiente regla dice:

Si reordenar las declaraciones de miembros en una clase produce un progtwig válido alternativo bajo (1) y (2), el progtwig está mal formado, no se requiere diagnóstico.

Tiene sentido que deseemos evitar situaciones en las que reordenar las declaraciones en una clase proporcione un progtwig diferente. Es curioso si estas dos reglas son redundantes o no .

La sección también proporciona el siguiente ejemplo:

 enum { i = 1 }; class X { char v[i]; // error: i refers to ::i // but when reevaluated is X::i int f() { return sizeof(c); } // OK: X::c char c; enum { i = 2 }; }; 

y si probamos este ejemplo con gcc ( verlo en vivo ), obtenemos un error casi idéntico al que produce su código:

  error: declaration of 'i' [-fpermissive] enum { i = 2 }; ^ error: changes meaning of 'i' from ' i' [-fpermissive] enum { i = 1 };