Vscode-cpptools: `_MSVC_LANG` is (usually) incorrect and can't be overridden since 0.16.x

Created on 1 Apr 2018  Â·  13Comments  Â·  Source: microsoft/vscode-cpptools

Firstly, the value of the _MSVC_LANG macro (MSVC's stand-in for __cplusplus) is dictated by the /std compiler flag and controls (among other things) availability of various standard library features e.g. std::optional and std::variant. Using the msvc-x64 mode, this macro always evaluates to 201402, which results in the default intellisense engine breaking for any code using these stdlib features. In previous versions of the extension it was possible to set the correct value for _MSVC_LANG in c_cpp_properties.json, but in 0.16.1 this is no longer possible; I don't know whether this "regression" began with 0.16.0 or 0.16.1. Ideally the extension would set the correct value for this macro, but I understand the difficulties surrounding doing that reliably; in the meantime, it at least needs to be possible to set the value for this macro manually, as it was before.

Secondly, it's concerning that the value of _MSVC_LANG doesn't change for different values of the cppStandard setting. Presently the macro is always 201402 regardless, but if one manually edits msvc.64.intel.json to pass --ms_c++latest to the frontend driver it changes to 201403. This implies that if one changes the cppStandard setting to e.g. c++17 that the frontend must necessarily be passed --ms_c++17 and not just --c++17 – I'm not sure if this is already the case, since the same _MSVC_LANG is given by the frontend for both C++14 and C++17, but it surely needs to be. Either way we also need a cppStandard value to reflect /std:c++latest/-std=c++2a so that the frontend can be passed --ms_c++latest.

That said, even when passing --ms_c++17 or --ms_c++latest to the frontend, the value of _MSVC_LANG is _still_ wrong – for the former it is 201402 when it should be 201703, and for the latter it is 201403 when it should be 201704.

One closely related thing that probably doesn't warrant opening its own issue, but if it does, let me know..: The macros _MSVC_LANG and __cplusplus don't get their values from the list obtained by setting compilerPath. Having _MSVC_LANG wrong is bad enough, but when using Clang on Windows this means that _both_ macros are wrong... I understand that these macros are "special" and likely need special handling, but it would be nice to get the correct values when using compilerPath.

EDIT: FWIW, I'd like to add that this is a breaking issue for me, necessitating a downgrade to 0.15 until it's resolved.

Language Service bug

Most helpful comment

@dodheim 0.17.1 sets the correct _MSVC_LANG and EDG flags so the C++17 headers work now. We haven't implemented cl.exe querying or processing of /Zc:__cpluplus yet though.

All 13 comments

What compiler are you using? It sounds like your intelliSenseMode is msvc-64 and you're on Windows, which means you should be using cl.exe and not clang. We didn't implement cl.exe define querying yet. In general, defines are supposed to overwrite any defines set by the compiler querying, but there may be special cases where our parser will overwrite those internally.

You can downgrade using a vsix at https://github.com/Microsoft/vscode-cpptools/releases .

What compiler are you using? It sounds like your intelliSenseMode is msvc-64 and you're on Windows, which means you should be using cl.exe and not clang.

I am using both, which was working fine until 0.16. I have two configurations – both use msvc-x64 mode, but one is actually for MSVC and doesn't set compilerPath, and the other is for Clang and does. They need different defines, so prior to 0.16 I simply had multiple configurations with different include paths and defines and all worked well. For the purpose of the _primary_ issue, ignore clang as the issue affects both equally; i.e. 100% of the motivating problem here is MSVC-specific.

That said, for Clang, setting compilerPath to clang++ <args...> in msvc-x64 mode is working perfectly; the only problem is the values of __cplusplus and _MSVC_LANG, but as I said _MSVC_LANG is equally wrong for MSVC, and once "fixed" there Clang will likely be "fixed" as well.

The summary here is that for MSVC, _MSVC_LANG has the wrong value which makes it impossible to include C++17-specific stdlib headers without completely breaking (default) intellisense, even with c++17 cppStandard setting. Along the same line, a setting for c++latest/c++2a is needed, as similar issues will soon crop up for post-C++17 libraries. What further information is needed?

(EDIT: And to be clear, the actual request that I have is to be able to override the value of _MSVC_LANG in c_cpp_properties.json or from the compiler via compilerPath; I don't expect setting it to it's actual correct value to be realistic.)

You don't want to use msvc-x64 mode with clang -- it will parse the code as if the compiler is cl.exe instead of clang. We've discussed automatically changing the intelliSenseMode to reflect the compiler set to avoid the wrong value being used.

For cl.exe, we didn't intentionally change any of the defines set and it's expected to behave as it did in 0.15.0. I don't know how we regressed handling of _MSVC_LANG, but I'll investigate.

You don't want to use msvc-x64 mode with clang -- it will parse the code as if the compiler is cl.exe instead of clang.

On Windows, Clang itself parses the code as if it's cl.exe (whether you want it to or not, annoyingly), so that behavior is exactly what is warranted. (And in case you weren't aware, Clang relies on an MSVC installation for its stdlib, which is why this issue affects both.) I assure you, other than the value of these two macros, Clang in msvc-x64 mode is working exactly as well as MSVC itself is (and always has, aside from the need to define ~100 macros in c_cpp_properties.json, until now). :-]

As a strongly-related aside, in case you weren't aware, Clang on Windows does not support GCC (MinGW)/libstdc++ (as it does on *nix). It relies exclusively on MSVC's stdlib (and linker by default), and forcefully emulates MSVC's parsing quirks. Because of this, clang-x64 mode on Windows doesn't work with Clang (only with GCC; go figure), and msvc-x64 _must_ be used if one wants to get as close to Clang's behavior as possible. (Like I said, it involved the definition of _many_ macros, but this is more-or-less an ergonomic issue since it _could_ be made to work.)

So, ideally, clang-x64 would work with Clang on Windows, but in the meantime this macro is all that's stopping Clang with msvc-x64 from working.

Hopefully this clears things up. :-]

Also, the _proper_ way to emulate Clang on Windows is to pass --clang --ms_compatibility --ms_extensions to the frontend driver; without the last two it operates as Clang does on Linux. (N.b. this works for EDG-proper, but it doesn't seem to work in the extension; I'm not sure why.)

That said, the last one is optional (for Clang it's called -f[no-]ms-extensions) so _ideally_ it would be configurable to reflect actual build settings, just as _ideally_ --[no_]ms_permissive would be configurable to reflect actual /permissive[-] settings... But, I realize that isn't realistic.

Apologies for spamming the issue, I just wanted to point out that your intellisense FE _does actually_ support the proper configurations for Clang on Windows, but presently only the proper arguments for Clang on *nix are passed to it by the extension. But, because of the way Clang itself works on Windows, the msvc-x64 mode works as a fine substitute, excepting the motivating macro values.

I'm able to set _MSVC_LANG in the defines. Are you modifying any of the .json files to pass different args to EDG? Can you give an example of code that is giving incorrect error squiggles? std::optional is working for me (using 15.7 Preview, 14.14.26329 headers). After we enable the compilerPath to work with cl.exe it might fix some of these issues by setting the defines correctly.

Well, your question was very percipient... Before submitting this issue I spent at least an hour bisecting out any changes I made to make sure they weren't the cause, but I incorrectly assumed that the -D_MSC_VER= and -D_MSC_FULL_VER= flags to the frontend must be in sync with the --microsoft_version and --microsoft_build_number flags; I wanted to update the macros and as it turns out, only the first two are "necessary" and the last two are actively counterproductive – setting --microsoft_version to anything higher than 1900 induces the behavior I described. So in the end my primary issue was indeed caused by changes I made to the frontend flags – many apologies for the noise...

In an attempt to salvage this issue, I'll summarize the actual outstanding problems:

  • The cppStandard setting does not correctly set the value of _MSVC_LANG according to the selected version; as far as MSVC is concerned, this means the cppStandard setting has no effect
  • The cppStandard setting is missing an option correlating to /std:c++latest/-std=c++2a
  • It should be possible to override the value of the __cplusplus macro somehow – this is both to handle MSVC's new /Zc:__cplusplus flag, and to address the only present deficiency in correctly emulating Clang on Windows without altering msvc.*.json

Thanks again for your time, Sean.

Ah, yeah, -- we have a TODO to query cl.exe for the correct _MSVC_LANG and the small amount of other defines to use based on the compilerPath (and args, such as /Zc:__cplusplus). Maybe for May. We'll also investigate adding support for a c++latest/c++20. Not many cl.exe users have complained about compilerPath/cppStandard not working with it so getting WSL/Cygwin to work have been higher priority for April's release.

@dodheim 0.17.1 sets the correct _MSVC_LANG and EDG flags so the C++17 headers work now. We haven't implemented cl.exe querying or processing of /Zc:__cpluplus yet though.

This seems to have come up again... _MSVC_LANG should be 201703L for C++17, but it is 201704L, which causes C++20 features to show up in intellisense (see yvals_core.h:230 - #if _STL_LANG > 201703L).

@parkovski This is a known issue, semi-tracked by https://github.com/microsoft/vscode-cpptools/issues/3448 . We are incorrectly forcing the C++17 version to C++latest, causing some C++20 behavior.

It looks like this issue was reopened to track something also tracked by #3448 . Since #3448 has been addressed, I assume this has been addressed as well. Closing.

Was this page helpful?
0 / 5 - 0 ratings