Aprimoramentos de conformidade do C++, alterações de comportamento e correções de bugs no Visual Studio 2022

O Microsoft C/C++ no Visual Studio (MSVC) faz aprimoramentos de conformidade e correções de bugs em cada versão. Este artigo lista as melhorias significativas por versão principal e depois pela versão. Para ir diretamente para as alterações de uma versão específica, use os links Neste artigo .

Este documento lista as alterações no Visual Studio 2022.

Para obter alterações no Visual Studio 2019, consulte Aprimoramentos de conformidade com C++ no Visual Studio 2019.
Para conhecer as alterações no Visual Studio 2017, confira Aprimoramentos de conformidade do C++ no Visual Studio 2017.
Para obter alterações em versões mais antigas, consulte Visual C++ What's New 2003 até 2015.

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.9

Visual Studio 2022 versão 17.9 contém os seguintes aprimoramentos de conformidade, correções de bugs e alterações de comportamento no compilador Microsoft C/C++.

Para obter um resumo mais amplo das alterações feitas na Biblioteca de Modelos Padrão, consulte STL Changelog VS 2022 17.9.

Aplicação de em um tipo estruturado _Alignas em C

Em versões do Visual C++ antes do Visual Studio 2022 versão 17.9, quando _Alignas aparecia ao lado de um tipo de estrutura em uma declaração, ele não era aplicado corretamente de acordo com o padrão ISO-C. Por exemplo:

// compile with /std:c17
#include <stddef.h>
struct Outer
{
    _Alignas(32) struct Inner { int i; } member1;
    struct Inner member2;
};
static_assert(offsetof(struct Outer, member2)==4, "incorrect alignment");

De acordo com o padrão ISO-C, este código deve ser compilado sem a emissão de static_assert um diagnóstico. A _Alignas directiva aplica-se apenas à variável member1membro . Não deve alterar o alinhamento do struct Inner. No entanto, antes da versão 17.9.1 do Visual Studio, o diagnóstico "alinhamento incorreto" foi emitido. O compilador alinhado member2 a um deslocamento de 32 bytes dentro struct Outerdo .

Corrigir isso é uma alteração de quebra binária, portanto, quando essa mudança de comportamento é aplicada, um aviso é emitido. Para o código anterior, Aviso C5274, " não se aplica mais ao tipo 'Interno' (aplica-se apenas a objetos de dados declarados)"_Alignas agora é emitido no nível de aviso 1.

Em versões anteriores do Visual Studio, _Alignas foi ignorado quando apareceu ao lado de uma declaração de tipo anônimo. Por exemplo:

// compile with /std:c17
#include <stddef.h>
struct S {
    _Alignas(32) struct { int anon_member; };
    int k;
};
static_assert(offsetof(struct S, k)==4, "incorrect offsetof");
static_assert(sizeof(struct S)==32, "incorrect size");

Anteriormente, ambas as static_assert instruções falharam ao compilar esse código. O código agora é compilado, mas com os seguintes avisos de nível 1:

warning C5274: behavior change: _Alignas no longer applies to the type '<unnamed-tag>' (only applies to declared data objects)
warning C5273: behavior change: _Alignas on anonymous type no longer ignored (promoted members will align)

Se desejar o comportamento anterior, substitua _Alignas(N) por __declspec(align(N)). Ao contrário _Alignasdo , declspec(align) pode ser aplicado a um tipo.

__VA_OPT__ está habilitado como uma extensão em /Zc:preprocessor

__VA_OPT__ foi adicionado ao C++20 e C23. Antes de sua adição, não havia uma maneira padrão de elidir uma vírgula em uma macro variádica. Para fornecer melhor compatibilidade com versões anteriores, __VA_OPT__ é habilitado sob o pré-processador /Zc:preprocessor baseado em token em todas as versões de idioma.

Por exemplo, isso agora compila sem erro:

#define LOG_WRAPPER(message, ...) WRITE_LOG(__LINE__, message __VA_OPT__(, __VA_ARGS__))

// Failed to build under /std:c11, now succeeds.
LOG_WRAPPER("Log message");
LOG_WRAPPER("Log message with %s", "argument")

Língua C23

Para C23, os seguintes itens estão disponíveis ao usar a opção do /std:clatest compilador:

typeof
typeof_unqual

Os itens a seguir estão disponíveis para todas as versões do idioma C:

__typeof__
__typeof_unqual__

Biblioteca Padrão C++

Recursos do C++23

  • formattable, range_format, format_kinde set_debug_format() como parte de P2286R8 Intervalos de formatação
  • <mdspan> por P0009R18 e alterações de redação subsequentes que foram aplicadas ao padrão C++23.
  • format() ponteiros por P2510R3.

Melhorias de conformidade no Visual Studio 2022 versão 17.8

O Visual Studio 2022 versão 17.8 contém as seguintes melhorias de conformidade, correções de bug e alterações de comportamento no compilador do Microsoft C/C++.

/FU emite um erro

O compilador C costumava aceitar a opção /FU, embora não tenha suporte para compilação gerenciada há algum tempo. Agora, ele emite um erro. Os projetos que passam essa opção precisam restringi-la somente a projetos C++/CLI.

Biblioteca Padrão C++

Os módulos nomeados C++23 std e std.compat agora estão disponíveis ao compilar com /std:c++20.

Para obter um resumo mais amplo das alterações feitas na Biblioteca Padrão C++, confira STL Changelog VS 2022 17.8.

Melhorias de conformidade no Visual Studio 2022 versão 17.7

O Visual Studio 2022 versão 17.7 contém os seguintes aprimoramentos de conformidade realçados, correções de bug e alterações de comportamento no compilador do Microsoft C/C++.

Adicionado /std:clatest ao compilador C

Essa opção se comporta como a alternância /std:c++latest do compilador C++. A alternância habilita todos os recursos do compilador e da biblioteca padrão atualmente implementados propostos para o próximo rascunho do padrão C, assim como alguns recursos experimentais e em andamento.

Biblioteca Padrão C++

Agora há suporte para a biblioteca <print>. Confira Saída formatada P2093R14.

views::cartesian_product implementado.

Para obter um resumo mais amplo das alterações feitas na Biblioteca de Modelos Padrão, confira STL Changelog VS 2022 17.7.

Conformidade using

Anteriormente, a diretiva using poderia fazer com que os nomes de namespaces usados permanecessem visíveis quando não deveriam. Isso pode fazer com que a pesquisa de nome não qualificada localize um nome em um namespace mesmo quando não houver nenhuma diretiva using ativa.

Aqui estão alguns exemplos do comportamento novo e antigo.
Referências nos seguintes comentários para "(1)" significam a chamada para f<K>(t) no namespace A:

namespace A
{ 
    template<typename K, typename T> 
    auto f2(T t)
    { 
        return f<K>(t); // (1) Unqualified lookup should not find anything
    } 
} 

namespace B
{ 
    template<typename K, typename T> 
    auto f(T t) noexcept
    { // Previous behavior: This function was erroneously found during unqualified lookup at (1)
        return A::f2<K>(t); 
    } 
} 

namespace C
{ 
    template<typename T> 
    struct S {}; 

    template<typename, typename U> 
    U&& f(U&&) noexcept; // New behavior: ADL at (1) correctly finds this function 
} 

namespace D
{ 
    using namespace B; 

    void h()
    { 
        D::f<void>(C::S<int>()); 
    } 
} 

O mesmo problema subjacente pode fazer com que o código compilado anteriormente seja rejeitado:

#include <memory>
namespace Addin {}
namespace Gui
{
    using namespace Addin;
}

namespace Addin
{
    using namespace std;
}

// This previously compiled, but now emits error C2065 for undeclared name 'allocator'.
// This should be declared as 'std::allocator<T*>' because the using directive nominating
// 'std' is not active at this point.
template <class T, class U = allocator<T*>>
class resource_list
{
};

namespace Gui
{
    typedef resource_list<int> intlist;
}

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.6

O Visual Studio 2022 versão 17.6 apresenta os aprimoramentos de conformidade, correções de bug e alterações de comportamento a seguir no compilador do Microsoft C/C++.

Atribuições volatile compostas não foram mais preteridas

C++20 preterido aplicando determinados operadores a tipos qualificados com volatile. Por exemplo, quando o seguinte código é compilado com cl /std:c++20 /Wall test.cpp:

void f(volatile int& expr)
{
   ++expr;
}

O compilador produz test.cpp(3): warning C5214: applying '++' to an operand with a volatile qualified type is deprecated in C++20.

No C++20, os operadores de atribuição composta (operadores do formulário @=) foram preteridos. No C++23, os operadores compostos excluídos no C++20 não são mais preteridos. Por exemplo, no C++23, o código a seguir não produz um aviso, enquanto no C++20:

void f(volatile int& e1, int e2)
{
   e1 += e2;
}

Para obter mais informações sobre essa alteração, confira CWG:2654

Reescrever a igualdade em expressões consiste menos em uma alteração interruptiva (P2468R2)

No C++20, P2468R2 alterou o compilador para aceitar código como:

struct S
{
    bool operator==(const S&);
    bool operator!=(const S&);
};
bool b = S{} != S{};

O compilador aceita esse código, o que significa que o compilador é mais estrito com código como:

struct S
{
  operator bool() const;
  bool operator==(const S&);
};

bool b = S{} == S{};

A versão 17.5 do compilador aceita este programa. A versão 17.6 do compilador o rejeita. Para corrigi-lo, adicione const a operator== para remover a ambiguidade. Ou adicione um correspondente operator!= à definição, conforme mostrado no exemplo a seguir:

struct S
{
  operator bool() const;
  bool operator==(const S&);
  bool operator!=(const S&);
};

bool b = S{} == S{};

As versões 17.5 e 17.6 do compilador do Microsoft C/C++ aceitam o programa anterior e chamadas S::operator== em ambas as versões.

O modelo de programação geral descrito em P2468R2 é que, se há um correspondente operator!= para um tipo, ele normalmente suprime o comportamento de reescrita. Adicionar um correspondente operator!= é a correção sugerida para o código que foi compilado anteriormente no C++17. Para saber mais, confira Modelo de programação.

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.4

O Visual Studio 2022 versão 17.4 apresenta as melhorias de conformidade, correções de bug e alterações de comportamento a seguir no compilador do Microsoft C/C++.

Tipos subjacentes de enum sem escopo sem tipo fixo

Em versões do Visual Studio antes do Visual Studio 2022 versão 17.4, o compilador C++ não determinava corretamente o tipo subjacente de uma enumeração sem escopo sem tipo base fixo. No /Zc:enumTypes, agora implementamos corretamente o comportamento padrão.

O C++ Standard requer que o tipo subjacente de um enum seja grande o suficiente para manter todos os enumeradores nesse enum. Enumeradores suficientemente grandes podem definir o tipo subjacente do enum como unsigned int, long long ou unsigned long long. Anteriormente, esses tipos enum sempre tinham um tipo subjacente de int no compilador da Microsoft, independentemente dos valores do enumerador.

Quando habilitada, a opção /Zc:enumTypes é uma possível alteração de falha de origem e binária. Ela está desativada por padrão e não está habilitada por /permissive- porque a correção pode afetar a compatibilidade binária. Alguns tipos de enumeração mudam de tamanho quando a correção de conformidade está habilitada. Determinados cabeçalhos do SDK do Windows incluem essas definições de enumeração.

Exemplo

enum Unsigned
{
    A = 0xFFFFFFFF // Value 'A' does not fit in 'int'.
};

// Previously, failed this static_assert. Now passes with /Zc:enumTypes.
static_assert(std::is_same_v<std::underlying_type_t<Unsigned>, unsigned int>);

template <typename T>
void f(T x)
{
}

int main()
{
    // Previously called f<int>, now calls f<unsigned int>.
    f(+A);
}

// Previously this enum would have an underlying type of `int`, but Standard C++ requires this to have
// a 64-bit underlying type. Using /Zc:enumTypes changes the size of this enum from 4 to 8, which could
// impact binary compatibility with code compiled with an earlier compiler version or without the switch.
enum Changed
{
    X = -1,
    Y = 0xFFFFFFFF
};

Tipos de enumeradores dentro de uma definição enum sem tipo subjacente fixo

Nas versões do Visual Studio antes do Visual Studio 2022 versão 17.4, o compilador C++ não modelava corretamente os tipos de enumeradores. Ele poderia assumir um tipo incorreto em enumerações sem um tipo subjacente fixo antes da chave de fechamento da enumeração. No /Zc:enumTypes, o compilador agora implementa corretamente o comportamento padrão.

O C++ Standard especifica que, dentro de uma definição de enumeração sem tipo subjacente fixo, os inicializadores determinam os tipos de enumeradores. Ou, para os enumeradores sem inicializador, pelo tipo do enumerador anterior (contabilizando o estouro). Anteriormente, esses enumeradores sempre recebiam o tipo deduzido da enumeração, com um espaço reservado para o tipo subjacente (normalmente int).

Quando habilitada, a opção /Zc:enumTypes é uma possível alteração de falha de origem e binária. Ela está desativada por padrão e não está habilitada por /permissive- porque a correção pode afetar a compatibilidade binária. Alguns tipos de enumeração mudam de tamanho quando a correção de conformidade está habilitada. Determinados cabeçalhos do SDK do Windows incluem essas definições de enumeração.

Exemplo

enum Enum {
    A = 'A',
    B = sizeof(A)
};

static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes

Neste exemplo, o enumerador A deve ter tipo char antes da chave de fechamento da enumeração, portanto B , deve ser inicializado usando sizeof(char). Antes da correção /Zc:enumTypes, A tinha um tipo de enumeração Enum com um tipo subjacente deduzido int e B era inicializado usando sizeof(Enum) ou 4.

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.3

O Visual Studio 2022 versão 17.3 apresenta as melhorias de conformidade, correções de bug e alterações de comportamento a seguir no compilador do Microsoft C/C++.

C: Verificação de compatibilidade aprimorada do modificador entre ponteiros

O compilador C não comparou corretamente os modificadores entre ponteiros, especialmente void*. Esse defeito pode resultar em um diagnóstico inadequado de incompatibilidade entre const int** e void* e compatibilidade entre int* volatile* e void*.

Exemplo

void fn(void* pv) { (pv); }

int main()
{
    int t = 42;
    int* pt = &t;
    int* volatile * i = &pt;
    fn(i);    // Now raises C4090
    const int** j = &pt;
    fn(j);    // No longer raises C4090
}

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.2

O Visual Studio 2022 versão 17.2 apresenta as melhorias de conformidade, correções de bug e alterações de comportamento a seguir no compilador do Microsoft C/C++.

Avisos de caracteres bidirecionais não finalizados

O Visual Studio 2022 versão 17.2 adiciona o aviso de nível 3 C5255 para caracteres bidirecionais Unicode não finalizados em comentários e cadeias de caracteres. O aviso aborda uma preocupação de segurança descrita em Trojan Source: Invisible Vulnerabilities por Nicholas Boucher e Ross Anderson. Para obter mais informações sobre caracteres bidirecionais Unicode, confira Unicode® Standard Annex #9: UNICODE BIDIRECTIONAL ALGORITHM.

O aviso C5255 apenas aborda arquivos que, após a conversão, contêm caracteres bidirecionais Unicode. Esse aviso se aplica aos arquivos UTF-8, UTF-16 e UTF-32, portanto, a codificação de origem adequada deve ser fornecida. Essa alteração é uma alteração interruptiva do código.

Exemplo (antes/depois)

Nas versões do Visual Studio antes do Visual Studio 2022 versão 17.2, um caractere bidirecional não finalizado não produzia um aviso. O Visual Studio 2022 versão 17.2 produz o aviso C5255:

// bidi.cpp
int main() {
    const char *access_level = "user";
    // The following source line contains bidirectional Unicode characters equivalent to:
    //    if ( strcmp(access_level, "user\u202e \u2066// Check if admin \u2069 \u2066") ) {
    // In most editors, it's rendered as:
    //    if ( strcmp(access_level, "user") ) { // Check if admin
    if ( strcmp(access_level, "user‮ ⁦// Check if admin ⁩ ⁦") ) {
        printf("You are an admin.\n");
    }
    return 0;
}

/* build output
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+202e'
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+2066'
*/

from_chars()Desempate de float

O Visual Studio 2022 versão 17.2 corrige um bug nas regras de desempate <charconv>from_chars()float que produziram resultados incorretos. Esse bug afetava cadeias de caracteres decimais que estavam no ponto médio exato de valores consecutivos float, dentro de um intervalo estreito. (Os menores e maiores valores afetados foram 32768.009765625 e 131071.98828125, respectivamente.) A regra de desempate queria arredondar para "par", e "par" passou a ser "para baixo", mas a implementação arredondava incorretamente "para cima" (double não foi afetada). Para obter mais informações e detalhes de implementação, consulte microsoft/STL#2366.

Essa alteração afeta o comportamento do runtime no intervalo de casos especificado:

Exemplo

// from_chars_float.cpp
#include <cassert>
#include <charconv>
#include <cstdio>
#include <string_view>
#include <system_error>
using namespace std;
int main() {
    const double dbl  = 32768.009765625;
    const auto sv     = "32768.009765625"sv;
    float flt         = 0.0f;
    const auto result = from_chars(sv.data(), sv.data() + sv.size(), flt);
    assert(result.ec == errc{});
    printf("from_chars() returned: %.1000g\n", flt);
    printf("This rounded %s.\n", flt < dbl ? "DOWN" : "UP");
}

Em versões anteriores ao Visual Studio 2022 versão 17.2:

C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.01171875
This rounded UP.

No Visual Studio 2022 versão 17.2 e posteriores:

C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.0078125
This rounded DOWN.

/Zc:__STDC__ disponibiliza __STDC__ para C

O padrão do C requer que uma implementação do C em conformidade defina __STDC__ como 1. Devido ao comportamento do UCRT, que não expõe as funções POSIX quando __STDC__ é 1, não é possível definir essa macro para o C por padrão sem introduzir alterações interruptivas nas versões estáveis da linguagem. O Visual Studio 2022 versão 17.2 e posteriores adiciona uma opção de conformidade /Zc:__STDC__ que define essa macro. Não há uma versão negativa da opção. Atualmente, planejamos usar essa opção por padrão para versões futuras do C.

Essa alteração é uma alteração interruptiva do código. Ela se aplica quando o modo C11 ou C17 está habilitado, /std:c11 ou /std:c17, junto com /Zc:__STDC__.

Exemplo

// test__STDC__.c
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
#if __STDC__
    int f = _open("file.txt", _O_RDONLY);
    _close(f);
#else
    int f = open("file.txt", O_RDONLY);
    close(f);
#endif
}

/* Command line behavior

C:\Temp>cl /EHsc /W4 /Zc:__STDC__ test__STDC__.c && test__STDC__

*/

Aviso para chaves ausentes

O aviso C5246 relata chaves ausentes durante a inicialização agregada de um subobjeto. Antes do Visual Studio 2022 versão 17.2, o aviso não lidava com o caso de um struct ou union anônimo.

Essa alteração é uma alteração interruptiva do código. Ela se aplica quando o aviso C5246, desativado por padrão, é habilitado.

Exemplo

No Visual Studio 2022 versão 17.2 e posteriores, esse código agora causa um erro:

struct S {
   union {
      float f[4];
      double d[2];
   };
};

void f()
{
   S s = { 1.0f, 2.0f, 3.14f, 4.0f };
}

/* Command line behavior
cl /Wall /c t.cpp

t.cpp(10): warning C5246: 'anonymous struct or union': the initialization of a subobject should be wrapped in braces
*/

Para resolver esse problema, adicione chaves ao inicializador:

void f()
{
   S s = { { 1.0f, 2.0f, 3.14f, 4.0f } };
}

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.1

O Visual Studio 2022 versão 17.1 apresenta as melhorias de conformidade, correções de bug e alterações de comportamento a seguir no compilador do Microsoft C/C++.

Detectar padrão de captura mal formada em expressões lambda não locais

O Padrão do C++ só permite que uma expressão lambda no escopo de bloco tenha um padrão de captura. No Visual Studio 2022 versão 17.1 e posteriores, o compilador detecta quando um padrão de captura não é permitido em uma expressão lambda não local. Ele emite um novo aviso de nível 4, C5253.

Essa alteração é uma alteração interruptiva do código. Ela se aplica a qualquer modo que use o novo processador lambda: /Zc:lambda, /std:c++20 ou /std:c++latest.

Exemplo

No Visual Studio 2022 versão 17.1, esse código agora emite um erro:

#pragma warning(error:5253)

auto incr = [=](int value) { return value + 1; };

// capture_default.cpp(3,14): error C5253: a nonlocal lambda cannot have a capture default
// auto incr = [=](int value) { return value + 1; };
//              ^

Para corrigir esse problema, remova o padrão de captura:

#pragma warning(error:5253)

auto incr = [](int value) { return value + 1; };

O C4028 agora é C4133 para operações de função a ponteiro

Antes do Visual Studio 2022 versão 17.1, o compilador relatava uma mensagem de erro incorreta em determinadas comparações de ponteiro para função no código do C. A mensagem incorreta era relatada quando você comparava dois ponteiros de função que tinham as mesmas contagens de argumentos, mas tipos incompatíveis. Agora, emitimos um aviso diferente que informa da incompatibilidade do ponteiro para a função em vez da incompatibilidade do parâmetro da função.

Essa alteração é uma alteração interruptiva do código. Aplica-se quando o código é compilado como C.

Exemplo

int f1(int); 
int f2(char*); 
int main(void) 
{ 
    return (f1 == f2); 
}
// Old warning:
// C4028: formal parameter 1 different from declaration
// New warning:
// C4113: 'int (__cdecl *)(char *)' differs in parameter lists from 'int (__cdecl *)(int)'

Erro em um static_assert não dependente

No Visual Studio 2022 versão 17.1 e posterior, se a expressão associada a um static_assert não for uma expressão dependente, o compilador avaliará a expressão quando ela for analisada. Se a expressão for avaliada como false, o compilador emitirá um erro. Anteriormente, se a static_assert estivesse dentro do corpo de um modelo de função (ou dentro do corpo de uma função membro de um modelo de classe), o compilador não executaria essa análise.

Essa alteração é uma alteração interruptiva do código. Ela se aplica a qualquer modo que implique /permissive- ou /Zc:static_assert. Essa alteração no comportamento pode ser desabilitada usando a opção do compilador /Zc:static_assert-.

Exemplo

No Visual Studio 2022 versão 17.1 e posteriores, esse código agora causa um erro:

template<typename T>
void f()
{
   static_assert(false, "BOOM!");
}

Para corrigir esse problema, torne a expressão dependente. Por exemplo:

template<typename>
constexpr bool dependent_false = false;

template<typename T>
void f()
{
   static_assert(dependent_false<T>, "BOOM!");
}

Com essa alteração, o compilador só emitirá um erro se o modelo de função f for instanciado.

Aprimoramentos de conformidade no Visual Studio 2022 versão 17.0

O Visual Studio 2022 versão 17.0 apresenta as melhorias de conformidade, correções de bug e alterações de comportamento a seguir no compilador do Microsoft C/C++.

Aviso na largura do campo de bits para o tipo enumeração

Quando você declara uma instância de um tipo de enumeração como um campo de bits, a largura do campo de bits deve acomodar todos os valores possíveis da enumeração. Caso contrário, o compilador emitirá uma mensagem de diagnóstico. Considere este exemplo: Considere:

enum class E : unsigned { Zero, One, Two };

struct S {
  E e : 1;
};

Um programador pode esperar que o membro da classe S::e possa conter qualquer um dos valores explicitamente nomeados enum. Dado o número de elementos de enumeração, isso não é possível. O campo de bits não pode cobrir o intervalo de valores fornecidos explicitamente de E (conceitualmente, o domínio de E). Para resolver a questão de que a largura do campo de bits não é grande o suficiente para o domínio da enumeração, um novo aviso (desativado por padrão) foi adicionado ao MSVC:

t.cpp(4,5): warning C5249: 'S::e' of type 'E' has named enumerators with values that cannot be represented in the given bit field width of '1'.
  E e : 1;
    ^
t.cpp(1,38): note: see enumerator 'E::Two' with value '2'
enum class E : unsigned { Zero, One, Two };
                                     ^

Esse comportamento do compilador é uma alteração interruptiva de código e binário que afeta os modos /std e /permissive.

Erro na comparação ordenada de ponteiro em relação a nullptr ou 0

O Padrão do C++ inadvertidamente permitia uma comparação de ponteiro ordenada em relação a nullptr ou 0. Por exemplo:

bool f(int *p)
{
   return p >= 0;
}

O trabalho N3478 do WG21 removeu essa omissão. Essa alteração é implementada no MSVC. Quando o exemplo é compilado usando /permissive- (e /diagnostics:caret), ele emite o seguinte erro:

t.cpp(3,14): error C7664: '>=': ordered comparison of pointer and integer zero ('int *' and 'int')
    return p >= 0;
             ^

Esse comportamento do compilador é uma alteração de falha de código e binária que afeta o código compilado usando /permissive- em todos os modos /std.

Confira também

Conformidade com a linguagem do Microsoft C/C++