Collision of nested typenames in MSVC
<p>I have encountered a problem while was using variadic templates, but the problem is not related to variadic templates and can be reproduced without them.
The problem is related to same names of types in inherited and base classes.</p>

<p>I've simplified code to the following snippet:</p>

<pre><code>#include &lt;typeinfo&gt;
#include &lt;iostream&gt;

struct A
{
    int member;
};

struct B: public A
{
    typedef A NEXT;

    short member;
};

struct Foo: public B
{
    typedef B NEXT;

    void Check()
    { 
        std::cout &lt;&lt; typeid(NEXT::member).name() &lt;&lt; '\n';
        std::cout &lt;&lt; typeid(NEXT::NEXT::member).name() &lt;&lt; '\n';

        NEXT::NEXT::member = 1;
        NEXT::member = 2;

        std::cout &lt;&lt; NEXT::NEXT::member &lt;&lt; '\n';
        std::cout &lt;&lt; NEXT::member &lt;&lt; '\n';
    };
};

int main()
{
    Foo foo;
    foo.Check();
}
</code></pre>

<p>It compiles without warnings and works with GCC and clang, but it produces wrong output with MSVC (at least with Visual Studio 2015 Update 1).</p>

<p>It seems that some collision in names happens, and it treats <code>NEXT::NEXT::member</code> as <code>NEXT::member</code>, but in the same place, it lies to <code>typeid</code> (as well as to <code>std::is_same</code>).</p>

<p>When compiled with GCC or clang the output is:</p>

<pre><code>s                                                                                                                                                                                                                                                      
i                                                                                                                                                                                                                                                      
1                                                                                                                                                                                                                                                      
2 
</code></pre>

<p>But in case of MSVC, the output is:</p>

<pre><code>short
int
2
2
</code></pre>

<p>The following code compiles without warnings with GCC or clang, but as expected produces error with MSVC:</p>

<pre><code>struct A
{
    int member;
};

struct B: public A
{
    typedef A NEXT;

    short member;
};

struct Foo: public B
{
    typedef B NEXT;

    short&amp; GetB() { return NEXT::member; };
    int&amp; GetA()   { return NEXT::NEXT::member; };    
};
</code></pre>

<p>The MSVC error:</p>

<pre><code>source_file.cpp(18): error C2440: 'return': cannot convert from 'short' to 'int &amp;'
</code></pre>

<p>Is the code above valid? Is it a problem of MSVC or I'm utilizing UB somehow? </p>

<h1>Update</h1>

<p>The problem can not be reproduced in MSVC 2015 update 3.</p>