Visual C++ 2008 compiler bugs

Back to Blog

Here are some of the bugs I have found in the Visual C++ 2008 compiler.

Default parameter from template parameter

This code should print 1 2 3 4, but instead prints 1 1 1 1.

#include <iostream>

template <int N>
void f(int x = N);

template <int N>
void f(int x)
{
    std::cout << x << std::endl;
}

int main()
{
    f<1>();
    f<2>();
    f<3>();
    f<4>();

    return 0;
}

Incomplete inner classes bug

Because templates are involved, no code for A::f is instantiated until it is referred to. Therefore, it should be legal to use B:s constructors in f although the definition of B is yet to follow.

template <typename Type>
class C
{
public:
    class A;
    class B;
};

template <typename Type>
class C<Type>::A
{
public:
    B f() const
    {
        return B();
    }
};

template <typename Type>
class C<Type>::B
{
};

int main()
{
    C<int> c;

    return 0;
}

Incorrect enumerator scoping

This bug is only present when language extensions are enabled. Because the base class of B (A\<N\>) is dependent on a template parameter, it’s contents should not be visible to B‘s definition. However, now the compiler thinks that the N in typedef A\<N\> Base; refers to the N in the base class (which is private), rather than the template parameter N.

template <int N>
class A
{
private:
    enum
    {
        N = 1
    };
};

template <int N>
class B
    : public A<N>
{
public:
    typedef A<N> Base;
};

int main()
{
    B<1> a;
    return 0;
}

Incorrect warning with base classes

Here the compiler warns that the two instances of the CommonBase class template are of the same type while they are not: one is CommonBase\<Tuple\<N, Real\> \> and the other one is CommonBase\<Vector\<N, Real\> \>. However, the compiler does the right thing despite this warning. It is the warning message that is in error. Btw, do not try to use this technique to implement vectors since multiple inheritance takes additional memory.

template <typename Type>
class CommonBase
{
};

template <int N, typename Real, typename Derived>
class TupleBase
    : CommonBase<Derived>
{
};

template <int N, typename Real>
class Tuple
    : public TupleBase<N, Real, Tuple<N, Real> >
{
};

template <int N, typename Real, typename Derived>
class VectorBase
    : public Tuple<N, Real>
    , CommonBase<Derived>
{
};

template <int N, typename Real>
class Vector
    : public VectorBase<N, Real, Vector<N, Real> >
{
};

int main()
{
    return 0;
}

Internal compiler error

It took me hours to reduce to this small snippet from an actual program.

#include <string>
#include <set>

class C
{
public:
    C(long a)
        : a_(a)
    {
    }

    ~C()
    {
        if (_InterlockedDecrement(&a_) == 0)
        {
        }
    }

    long a_;
};

template <typename Real>
void f(const Real& a, const Real& b = 0);

template <typename Real>
void f(const Real& a, const Real& b)
{
    C c(b);
}

void h2()
{
    f((double)0);
    "" + std::string() +  "" + std::string();
}

void g(void(*)())
{
}

void h()
{
    h2();
    g(h);
}

int main()
{
    return 0;
}

Static const member variable

This bug is only present when language extensions are enabled. The response from Microsoft was a bit disappointing - it is by design.

test.h

#ifndef TEST_H
#define TEST_H

class Test
{
public:
    static const int V = 2;
};

#endif

test.cpp

#include "test.h"

const int Test::V;

main.cpp:

#include "test.h"

int main()
{
    return 0;
}

Template deduction

template <int N>
class Vector
{
};

template <int M, int N>
class Matrix
{
};

template <int M, int N>
Vector<N> operator*(const Vector<M>& other,
                    const Matrix<M + 1, N>& that)
{
    return Vector<N>();
}

int main()
{
    Vector<3> a;
    Matrix<4, 4> m;

    a * m;

    return 0;
}

Using declaration

class Base
{
public:
    enum {VALUE = 2};
};

class Derived
    : public Base
{
public:
    // If you comment this, this will compile.
    using Base::VALUE;
};

template <int N>
class Something {};

template <typename T>
Something<T::VALUE> f(T& that)
{
    return Something<T::VALUE>();
}

int main()
{
    Derived derived;
    f(derived);
    return 0;
}

Using destructor

It is not essential for the Base be a dependent type. However, this represents the normal use-case better.

class C
{
};

class A
{
public:
    typedef C B;
};

template <typename Base>
class Derived
    : public Base
{
public:
    using typename Base::B;

    Derived()
    {
        b->~B();
    }

private:
    B* b;
};

int main()
{
    Derived<A> d;

    return 0;
}

Using namespace

Here the compiler complains that the uint in the class A declaration ambiguates with the uint declaration in namespace N. However, the using namespace N; is yet to follow when the class A is declared.

typedef unsigned int uint; 

template <typename Type> 
class A 
{ 
public: 
    uint a_; 
}; 

namespace N 
{ 

    typedef unsigned int uint; 

} 

using namespace N; 

A<int> a;

int main()
{
    return 0;
}