Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Saturday, October 18, 2025

Using clang-cl in Visual Studio

clang-cl

 clang-cl is the command line tool in Visual Studio capable of invoking the clang compiler with the arguments of msvc. In Visual Studio projects one can just flip the toolset and the clang compiler will be chosen. clang has the following positive aspects:

  • better C++ conformance. Examples are that msvc is leniant towards missing 'typename' for dependent types and 'template' for nesting templates; clang picks them up. There are other issues.
  • offers some code improvements like correct member order in constructors and virtuals which override base class
  • detects some performance improvements like advising to use shared_ptr by reference in loops
  • more precise compilation warnings and errors

It has also some drawbacks: 

  • some noisy warnings 
  • does not understand all msvc code. For example the msvc's #import extension is not understood

 Despite using msvc's code analysis the clang compiler was still able to pick up other issues. Some clang warnings are far fetched and one can choose to disable them. This is especially needed for external libraries which one cannot easily patch. To disable warnings one can use the following:

#ifdef __clang__
#pragma clang diagnostic ignored "-Wimplicit-exception-spec-mismatch"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic ignored "-W#pragma-messages"
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
#pragma clang diagnostic ignored "-Wunused-local-typedef"
#endif

 The first one for example is necessary to suppress warnings in MFC. 'delete' should be specified with 'noexcept' but the MFC delete lacks this.


Sunday, July 27, 2025

Watch out for an old VC++ runtime

 VC_redist.x64.exe

 For C/ C++ applications the VC++ runtime needs to be installed on the computer. The other day we experienced crashes when a component developed with a late version of VS2022 was crashing on a fresh installation of Windows 11. It turned out that this Windows 11 still uses an old version of the VC++ runtime which could crash the application (most notably in grabbing a std::mutex lock). After updating the PC with a recent version of 'VC_redist.x64.exe' the problem was solved.

 

Sunday, June 29, 2025

Watch out for atan change in Visual Studio 2022 17.14.6

atan

 Recently we updated Visual Studio 2022 17.14.6 and the regression test reported errors. It turned out that atan implementation was changed resulting a different value for debug vs release builts with CPU's having AVX2. One can recreate this with the following values:

    const double ax          = 38.176459921094995;
    const double ay          = 15.964755390006060;
    const double dblRotation =  atan(ay/ax);

 We had to relax the equality checks; even for deterministic calculations.


Tuesday, August 9, 2022

Watch out for MSVC's std::map's move constructor

move constructor

 The other day I found out that MSVC's std::map move constructor doesn't have noexcept:

map(map&& _Right) : _Mybase(_STD move(_Right)) {}

This means that it can throw when moved and it's not eligible for move_if_noexcept which is used in vector reallocation's. I filed a report but it got rejected. Take care when you want map's to be moveable (which can be a factor compared to copying all nodes).

Thursday, April 21, 2022

Careful with mixing types in loop variables

Loop

 The other day I stumbled upon code which accidentally used a double as end condition:

#include <cstdint>
#include <cstdlib>

constexpr double g_dW = 10;

int main()
{
int res = 0;

for (int n = 0; n < g_dW; ++n)
{
res += std::rand(); // use rand just to have a valid loop
}

return res;
}

One would think that the optimizer Visual Studio 2019 16.13 is smart enough to use integer comparison but this is not the case. VS2019 issues a relative expensive integer to double conversion and comparison:

   
    for (int n = 0; n < g_dW; ++n)
00007FF7C9A01011  movsd       xmm6,mmword ptr [__real@4024000000000000 (07FF7C9A02240h)]  
00007FF7C9A01019  mov         edi,ebx  
00007FF7C9A0101B  nop         dword ptr [rax+rax]  
    {
        res += std::rand();
00007FF7C9A01020  call        qword ptr [__imp_rand (07FF7C9A02188h)]  
00007FF7C9A01026  inc         edi  
00007FF7C9A01028  add         ebx,eax  
00007FF7C9A0102A  movd        xmm0,edi  
00007FF7C9A0102E  cvtdq2pd    xmm0,xmm0  
00007FF7C9A01032  comisd      xmm6,xmm0  
00007FF7C9A01036  ja          main+20h (07FF7C9A01020h)  
    }
    
    return res;
 

The solution is simple to use an integer as block condition:

 constexpr int g_dW = 10;

Therefore watch out that VS2019 does not optimize things automatically.

 

Friday, August 6, 2021

Explicit member function template specialisation on Visual Studio 2019

Template member function templates

  Classes can have member function templates. These member templates can be explicit specialized. For example:

struct Foo
{
   template <typename T>
   void f()
   {
   }
};

template <>
inline void Foo::f<int>()
{
   // full specialization
}
It seems that Visual Studio 2019 allows for an illegal syntax with the full specialization declaration in the class itself:
struct Foo
{
   template <typename T>
   void f();
   
   // illegal?
   template <>
   void Foo::f<int>();
};

template <>
void Foo::f<int>()
{
}
Also the inline specifier isn't necessary then in Visual Studio without running into errors with duplicate symbols.

Links

Sunday, January 3, 2021

Visual Studio std::pow implementations

pow

After an upgrade of Visual Studio 2017 to 2019 it was noticed that regression tests were failing with the new version. There were multiple causes; one of them was that (yet again) the implementation of std::pow had changed.

 The Visual Studio 2017 implementation uses a different code path for the common power 2 (square) case: it issues a simple multiplication. The implementation is something like this:


_Check_return_ inline double pow(_In_ double _Xx, _In_ int _Yx) noexcept
       {
       if (_Yx == 2)
              return (_Xx * _Xx);

       return (_CSTD pow(_Xx, static_cast<double>(_Yx)));
       }

 The Visual Studio 2019 implementation isn't available in source code form but the exceptional code path for calculating the square seems not present anymore. This gives (small) differences with some numbers, e.g. the square of '0.10000000055703842' gives a different result.

Alternative

Luckily boost offers an alternative for calculating squared and other integer powers known at compile time in its math library:


#include <boost/math/special_functions/pow.hpp>

constexpr double d = 0.10000000055703842;

const double d2 = boost::math::pow<2>(d);

 Using this function should give stable result for the coming upgrades of Visual Studio. It has also the extra benefit of better performance. Results of a test case with running many power calculations:

Function Time (s)
boost::math::pow<2> 0.241
std::pow 9.395

  Note that instead of using a power function direct multiplication is ofc also possible. Often though these power functions are fed with another calculated value which otherwise has to be duplicated or write down explicitly:


const double d = std::sqrt(boost::math::pow<2>(pt.x - x) + boost::math::pow<2>(pt.y - y));

 Boost's math::pow has the extra benefit of doing the least amount of multiplications in case the power is larger than 3.

Using clang-cl in Visual Studio

clang-cl   clang-cl is the command line tool in Visual Studio capable of invoking the clang compiler with the arguments of msvc. In Visual ...