{"id":20045,"date":"2018-07-06T14:30:26","date_gmt":"2018-07-06T21:30:26","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/?p=20045"},"modified":"2019-04-18T09:31:03","modified_gmt":"2019-04-18T09:31:03","slug":"msvc-preprocessor-progress-towards-conformance","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/msvc-preprocessor-progress-towards-conformance\/","title":{"rendered":"MSVC Preprocessor Progress towards Conformance"},"content":{"rendered":"<p><span style=\"color: #2e75b5;font-size: 14pt\"><strong>Why re-write the preprocessor?<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 27pt\">Recently, we published a blog post on <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2018\/05\/07\/announcing-msvc-conforms-to-the-c-standard\/\">C++ conformance completion.<\/a> As mentioned in the blog post, the preprocessor in MSVC is currently getting an overhaul. We are doing this to improve its language conformance, address some of the longstanding bugs that were difficult to fix due to its design and improve its usability and diagnostics. In addition to that, there are places in the standard where the preprocessor behavior is undefined or unspecified and our traditional behavior diverged from other major compilers. In some of those cases, we want to move closer to the ecosystem to make it easier for cross platform libraries to come to MSVC.<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 27pt\">If there is an old library you use or maintain that depends on the non-conformant traditional behavior of the MSVC preprocessor, you don&#8217;t need to worry about these breaking changes as we will still support this behavior. The updated preprocessor is currently under the switch \/experimental:preprocessor until it is fully implemented and production-ready, at which point it will be moved to a \/Zc: switch which is enabled by default under \/permissive- mode.<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p><span style=\"color: #2e75b5;font-size: 14pt\"><strong>How do I use it?<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 27pt\">The behavior of the traditional preprocessor is maintained and continues to be the default behavior of the compiler. The conformant preprocessor can be enabled by using the \/experimental:preprocessor switch on the command line starting with the <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/2018\/06\/26\/visual-studio-2017-version-15-8-preview-3\">Visual Studio 2017 15.8 Preview 3 release<\/a>.<\/p>\n<p style=\"margin-left: 27pt\">We have introduced a new predefined macro in the compiler called &#8220;_<em>MSVC_TRADITIONAL<\/em>&#8221; to indicate the traditional preprocessor is being used. This macro is set unconditionally, independent of which preprocessor is invoked. Its value is &#8220;1&#8221; for the traditional preprocessor, and &#8220;0&#8221; for the conformant experimental preprocessor.<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#if<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #7f7f7f\">defined<span style=\"color: black\">(_MSVC_TRADITIONAL) &amp;&amp; _MSVC_TRADITIONAL\n<\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Logic using the traditional preprocessor<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#else<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Logic using cross-platform compatible preprocessor<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#endif<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" alt=\"\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/070618_2031_MSVCPreproc1.png\" \/><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p><span style=\"color: #2e75b5;font-size: 14pt\"><strong>What are the behavior changes?<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 27pt\">This first experimental release is focused on getting conformant macro expansions done to maximize adoption of new libraries by the MSVC compiler. Below is a list of some of the more common breaking changes that were run into when testing the updated preprocessor with real world projects.<\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #377bac;font-size: 12pt\"><strong>Behavior 1 [macro comments]<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 54pt\">The traditional preprocessor is based on character buffers rather than preprocessor tokens. This allows unusual behavior such as this preprocessor comment trick which will not work under the conforming preprocessor:<\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#if<span style=\"color: black\"> DISAPPEAR\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: black\"> DISAPPEARING_TYPE \/##\/\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#else<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">DISAPPEARING_TYPE<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: blue\">int<span style=\"color: black\">\n<\/span><\/span><\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#endif<span style=\"color: black\">\n<\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ myVal disappears when DISAPPEARING_TYPE is turned into a comment<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ To make standard compliant wrap the following line with the appropriate \/\/ \/\/ #if\/#endif<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">DISAPPEARING_TYPE<span style=\"color: black\"> myVal;\n<\/span><\/span><\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #377bac;font-size: 12pt\"><strong>Behavior 2 [L#val]<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 54pt\">The traditional preprocessor incorrectly combines a string prefix to the result of the # operator:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"font-family: Times New Roman\">\u00a0<\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">DEBUG_INFO<span style=\"color: black\">(val) <span style=\"color: #a31515\">L&#8221;debug prefix:&#8221;<span style=\"color: black\"> L#val\n<\/span><\/span><\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ^<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 this prefix<span style=\"color: black\">\n<\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: blue;font-family: Consolas;font-size: 9pt\">const<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: blue\">wchar_t<span style=\"color: black\"> *info = <span style=\"color: #6f008a\">DEBUG_INFO<span style=\"color: black\">(hello world);\n<\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\">In this case the <span style=\"font-family: Consolas\">L<\/span> prefix is unnecessary because the adjacent string literals get combined after macro expansion anyway. The backward compatible fix is to change the definition to:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define <span style=\"color: black\"><span style=\"color: #6f008a\">DEBUG_INFO<span style=\"color: black\">(val) <span style=\"color: #a31515\">L&#8221;debug prefix:&#8221;<span style=\"color: black\"> #val\n<\/span><\/span><\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ^<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 no prefix<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 36pt\">This issue is also found in convenience macros that &#8216;stringize&#8217; the argument to a wide string literal:<\/p>\n<p style=\"margin-left: 54pt\"><span style=\"font-family: Times New Roman\">\u00a0<\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ The traditional preprocessor creates a single wide string literal token\n<\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #001000;font-family: Georgia,'Times New Roman','Bitstream Charter',Times,serif;font-size: medium\"> <\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\"><span style=\"color: black\"><span style=\"color: #6f008a\">STRING<span style=\"color: black\">(str) L#str<\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Potential fixes:<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Use string concatenation of L&#8221;&#8221; and #str to add prefix<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ This works because adjacent string literals are combined after macro expansion<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">STRING1<span style=\"color: black\">(str) <span style=\"color: #a31515\">L&#8221;&#8221;<span style=\"color: black\">#str<\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Add the prefix after #str is stringized with additional macro expansion<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">WIDE<span style=\"color: black\">(str) L##str\n<\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">STRING2<span style=\"color: black\">(str) <span style=\"color: #6f008a\">WIDE<span style=\"color: black\">(#str)<\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Use concatenation operator ## to combine the tokens.<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ The order of operations for ## and # is unspecified, although all compilers<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ I checked perform the # operator before ## in this case.<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f\"><span style=\"font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">STRING3<span style=\"color: black\">(str) L## #str<\/span><\/span><\/span><\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/span><\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #4472c4;font-size: 12pt\"><strong>Behavior 3 [warning on invalid ##]<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 54pt\">When the <span style=\"color: black;font-family: Consolas;font-size: 9pt\">##<\/span> operator does not result in a single valid preprocessing token, the behavior is undefined. The traditional preprocessor will silently fail to combine the tokens. The new preprocessor will match the behavior of most other compilers and emit a diagnostic.<\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ The ## is unnecessary and does not result in a single preprocessing token.<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">ADD_STD<span style=\"color: black\">(x) std::##x<\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Declare a std::string<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #6f008a\"><span style=\"font-family: Consolas;font-size: 9pt\">ADD_STD<span style=\"color: black\">(string) s;<\/span><\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/span><\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #4472c4;font-size: 12pt\"><strong>Behavior 4 [comma elision in variadic macros]<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 54pt\">Consider the following example:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: blue;font-family: Consolas;font-size: 9pt\">void<span style=\"color: black\"> func(<span style=\"color: blue\">int<span style=\"color: black\">, <span style=\"color: blue\">int<span style=\"color: black\"> = 2, <span style=\"color: blue\">int<span style=\"color: black\"> = 3);\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ This macro replacement list has a comma followed by __VA_ARGS__<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">FUNC<span style=\"color: black\">(a, &#8230;) func(a, __VA_ARGS__)\n<\/span><\/span><\/span><\/span><span style=\"color: blue;font-family: Consolas;font-size: 9pt\">int<span style=\"color: black\"> main()\n<\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">{\n<\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\">\/\/ The following macro is replaced with:<span style=\"color: black\">\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\">\/\/ func(10,20,30)<span style=\"color: black\">\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: #6f008a\">FUNC<span style=\"color: black\">(10, 20, 30);<\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\">\/\/ A conforming preprocessor will<span style=\"color: black\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\"> replace the following macro with: <span style=\"color: black\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\">func(1, );<span style=\"color: black\">\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\">\/\/ Which will result in a syntax error. <span style=\"color: black\">\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: #6f008a\">FUNC<span style=\"color: black\">(1, );\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">}<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\">All major compilers have a preprocessor extension that helps address this issue. The traditional MSVC preprocessor always removes commas before empty <span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">__VA_ARGS__<\/span> replacements. In the updated preprocessor we have decided to more closely follow the behavior of other popular cross platform compilers. For the comma to be removed, the variadic argument must be missing (not just empty) and it must be marked with a <span style=\"color: black\"><span style=\"font-family: Consolas;font-size: 9pt\">##<span style=\"color: #6f008a\">\n<\/span><\/span>operator.<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">FUNC2<span style=\"color: black\">(a, &#8230;) func(a , ## __VA_ARGS__)\n<\/span><\/span><\/span><\/span><span style=\"color: blue;font-family: Consolas;font-size: 9pt\">int<span style=\"color: black\"> main()\n<\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">{\n<\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">\u00a0\u00a0\u00a0\u00a0<span style=\"color: green\">\/\/ The variadic argument is missing in the macro being evoked\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Comma will be removed and replaced with:\n<\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: green\">\/\/ func(1)\n<\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: #6f008a\">FUNC2<span style=\"color: black\">(1);<\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: green\">\u00a0 \u00a0 \/\/ The variadic argument is empty, but not missing (notice the<span style=\"color: black\">\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: green\">\/\/ comma in the argument list). The comma will not be removed\n<\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: green\">\/\/ when the macro is replaced.<span style=\"color: black\">\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: green\">\/\/ func(1, )<span style=\"color: black\">\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\"><span style=\"color: #6f008a\">FUNC2<span style=\"color: black\">(1, );\n<\/span><\/span><\/span><span style=\"color: black;font-family: Consolas;font-size: 9pt\">}<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\">In the upcoming C++2a standard this issue has been addressed by adding<span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\"> __VA_OPT__<\/span>, which is not yet implemented.<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #4472c4;font-size: 12pt\"><strong>Behavior 5 [macro arguments are &#8216;unpacked&#8217;]<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 54pt\">In the traditional preprocessor, if a macro forwards one of its arguments to another dependent macro then the argument does not get &#8220;unpacked&#8221; when it is substituted. Usually this optimization goes unnoticed, but it can lead to unusual behavior:<\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Create a string out of the first argument, and the rest of the arguments.<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">TWO_STRINGS<span style=\"color: black\">( first, &#8230; ) #first, #__VA_ARGS__\n<\/span><\/span><\/span><\/span><span style=\"color: gray;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">A<span style=\"color: black\">( &#8230; ) <span style=\"color: #6f008a\">TWO_STRINGS<span style=\"color: black\">(__VA_ARGS__)<\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: blue;font-family: Consolas;font-size: 9pt\">const<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: blue\">char<span style=\"color: black\">* c[2] = { <span style=\"color: #6f008a\">A<span style=\"color: black\">(1, 2) };\n<\/span><\/span><\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Conformant preprocessor results:<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ const char c[2] = { &#8220;1&#8221;, &#8220;2&#8221; };<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Traditional preprocessor results, all arguments are in the first string:<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ const char c[2] = { &#8220;1, 2&#8221;, };<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\">When expanding A(), the traditional preprocessor forwards all of the arguments packaged in <span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">__VA_ARGS__<\/span> to the first argument of <span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">TWO_STRINGS<\/span>, which leaves the variadic argument of <span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">TWO_STRINGS<\/span> empty. This causes the result of #first to be &#8220;1, 2&#8221; rather than just &#8220;1&#8221;. If you are following along closely, then you may be wondering what happened to the result of #<span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">__VA_ARGS__<\/span> in the traditional preprocessor expansion: if the variadic parameter is empty it should result in an empty string literal &#8220;&#8221;. Due to a separate issue, the empty string literal token was not generated.<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 27pt\"><span style=\"color: #4472c4;font-size: 12pt\"><strong>Behavior 6 [rescanning replacement list for macros]<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 54pt\">After a macro is replaced, the resulting tokens are rescanned for additional macro identifiers that need to be replaced. The algorithm used by the traditional preprocessor for doing the rescan is not conformant as shown in this example based on actual code:<\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define <span style=\"color: black\"><span style=\"color: #6f008a\">CAT<span style=\"color: black\">(a,b) a ## b\n<\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">ECHO<span style=\"color: black\">(&#8230;) __VA_ARGS__<\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ IMPL1 and IMPL2 are implementation details<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">IMPL1<span style=\"color: black\">(prefix,value) do_thing_one( prefix, value)\n<\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define <span style=\"color: black\"><span style=\"color: #6f008a\">IMPL2<span style=\"color: black\">(prefix,value) do_thing_two( prefix, value)\n<\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ MACRO chooses the expansion behavior based on the value passed to macro_switch<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">DO_THING<span style=\"color: black\">(macro_switch, b) <span style=\"color: #6f008a\">CAT<span style=\"color: black\">(IMPL, macro_switch) <span style=\"color: #6f008a\">ECHO<span style=\"color: black\">(( <span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">, b))<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">DO_THING<span style=\"color: black\">(1, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">);\n<\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Traditional preprocessor:<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ do_thing_one( &#8220;Hello&#8221;, &#8220;World&#8221;);<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ Conformant preprocessor:<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ IMPL1 ( &#8220;Hello&#8221;,&#8221;World&#8221;);<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\">Although this example is a bit contrived, we have run into this issue few times when testing the preprocessor changes against real world code. To see what is going on we can break down the expansion starting with <span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">DO_THING<\/span>:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #6f008a\"><span style=\"font-family: Consolas;font-size: 9pt\">DO_THING<span style=\"color: black\">(1, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">)<\/span><\/span><\/span><\/span>&#8212; &gt;<span style=\"color: black;font-family: Consolas;font-size: 9pt\">\n<span style=\"color: #6f008a\">CAT<span style=\"color: black\">(IMPL, 1) <span style=\"color: #6f008a\">ECHO<span style=\"color: black\">((<span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">))\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\">Second, CAT is expanded:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">CAT<span style=\"color: black\">(IMPL, 1)&#8211; &gt; IMPL <span style=\"color: #7f7f7f\">#<span style=\"color: black\"># 1 &#8212; &gt; IMPL1\n<\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\">Which puts the tokens into this state:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: black;font-family: Consolas;font-size: 9pt\">IMPL1 <span style=\"color: #6f008a\">ECHO<span style=\"color: black\">((<span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">))\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\">The preprocessor finds the function-like macro identifier IMPL1, but it is not followed by a &#8220;(&#8220;, so it is not considered a function-like macro invocation. It moves on to the following tokens and finds the function-like macro ECHO being invoked:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">ECHO<span style=\"color: black\">((<span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">))&#8211; &gt; (<span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">)\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\">IMPL1 is never considered again for expansion, so the full result of the expansions is:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">IMPL1<span style=\"color: black\">(<span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">);\n<\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\">The macro can be modified to behave the same under the experimental preprocessor and the traditional preprocessor by adding in another layer of indirection:<span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">CAT<span style=\"color: black\">(a,b) a##b\n<\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">ECHO<span style=\"color: black\">(&#8230;) __VA_ARGS__<\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ IMPL1 and IMPL2 are macros implementation details<span style=\"color: black\">\n<\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">IMPL1<span style=\"color: black\">(prefix,value) do_thing_one( prefix, value)\n<\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">IMPL2<span style=\"color: black\">(prefix,value) do_thing_two( prefix, value)<\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define<span style=\"color: #b00000\"> <\/span><span style=\"color: black\"><span style=\"color: #6f008a\">CALL<span style=\"color: black\">(macroName, args) macroName args\n<\/span><\/span><\/span><\/span><span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#define <span style=\"color: black\"><span style=\"color: #6f008a\">DO_THING_FIXED<span style=\"color: black\">(a,b) <span style=\"color: #6f008a\">CALL<span style=\"color: black\">( <span style=\"color: #6f008a\">CAT<span style=\"color: black\">(IMPL, a), <span style=\"color: #6f008a\">ECHO<span style=\"color: black\">(( <span style=\"color: #a31515\">&#8220;Hello&#8221;<span style=\"color: black\">,b)))<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p style=\"margin-left: 54pt\"><span style=\"color: #6f008a;font-family: Consolas;font-size: 9pt\">DO_THING_FIXED<span style=\"color: black\">(1, <span style=\"color: #a31515\">&#8220;World&#8221;<span style=\"color: black\">);\n<\/span><\/span><\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ macro expanded to:<span style=\"color: black\">\n<\/span><\/span><span style=\"color: green;font-family: Consolas;font-size: 9pt\">\/\/ do_thing_one( &#8220;Hello&#8221;, &#8220;World&#8221;);<\/span><span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<p><span style=\"color: #2e75b5;font-size: 14pt\"><strong>What&#8217;s next\u2026<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 27pt\">The preprocessor overhaul is not yet complete; we will continue to make changes under the experimental mode and fix bugs from early adopters. <span style=\"font-family: Times New Roman\">\n<\/span><\/p>\n<ul style=\"margin-left: 54pt\">\n<li>Some preprocessor directive logic needs completion rather than falling back to the traditional behavior<span style=\"font-family: Times New Roman\">\n<\/span><\/li>\n<li>Support for _Pragma<span style=\"font-family: Times New Roman\">\n<\/span><\/li>\n<li>C++20 features<span style=\"font-family: Times New Roman\">\n<\/span><\/li>\n<li>Additional diagnostic improvements<span style=\"font-family: Times New Roman\">\n<\/span><\/li>\n<li>New switches to control the output under \/E and \/P<span style=\"font-family: Times New Roman\">\n<\/span><\/li>\n<li>\n<div>Boost blocking bug<span style=\"font-family: Times New Roman\">\n<\/span><\/div>\n<ul>\n<li>Logical operators in preprocessor constant expressions are not fully implemented in the new preprocessor so on <span style=\"color: #7f7f7f;font-family: Consolas;font-size: 9pt\">#if <\/span>directives the new preprocessor can fall back to the traditional preprocessor. This is only noticeable when macros not compatible with the traditional preprocessor are expanded, which can be the case when building boost preprocessor slots.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"color: #2e75b5;font-size: 14pt\"><strong>In closing<span style=\"font-family: Times New Roman\">\n<\/span><\/strong><\/span><\/p>\n<p style=\"margin-left: 27pt\">We&#8217;d love for you to download <a href=\"https:\/\/visualstudio.microsoft.com\/vs\/\"><span style=\"color: blue;text-decoration: underline\">Visual Studio 2017 version 15.8 preview<\/span><\/a> and try out all the new experimental features.<span style=\"font-family: Times New Roman\">\n<\/span>As always, we welcome your feedback. We can be reached via the comments below or via email (<a href=\"mailto:visualcpp@microsoft.com\"><span style=\"color: blue;text-decoration: underline\">visualcpp@microsoft.com<\/span><\/a>). If you encounter other problems with MSVC in Visual Studio 2017 please let us know through <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/ide\/how-to-report-a-problem-with-visual-studio-2017\"><span style=\"color: blue;text-decoration: underline\">Help &gt; Report A Problem in the product<\/span><\/a>, or via <a href=\"https:\/\/developercommunity.visualstudio.com\/topics\/C%2B%2B.html\"><span style=\"color: blue;text-decoration: underline\">Developer Community<\/span><\/a>. Let us know your suggestions through <a href=\"https:\/\/visualstudio.uservoice.com\/forums\/121579-visual-studio-2015\/category\/30937-languages-c\"><span style=\"color: blue;text-decoration: underline\">UserVoice<\/span><\/a>. You can also find us on Twitter (<a href=\"https:\/\/twitter.com\/visualc\"><span style=\"color: blue;text-decoration: underline\">@VisualC<\/span><\/a>) and Facebook (<a href=\"https:\/\/www.facebook.com\/msftvisualcpp\"><span style=\"color: blue;text-decoration: underline\">msftvisualcpp<\/span><\/a><span style=\"font-family: Times New Roman\">).<\/span><\/p>\n<p>Thank you,<\/p>\n<p>Phil Christensen, Ulzii Luvsanbat<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Why re-write the preprocessor? Recently, we published a blog post on C++ conformance completion. As mentioned in the blog post, the preprocessor in MSVC is currently getting an overhaul. We are doing this to improve its language conformance, address some of the longstanding bugs that were difficult to fix due to its design and improve [&hellip;]<\/p>\n","protected":false},"author":1062,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[270,256,230],"tags":[281,289,290],"class_list":["post-20045","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-announcement","category-experimental","category-new-feature","tag-conformance","tag-preprocessor","tag-visual-c"],"acf":[],"blog_post_summary":"<p>Why re-write the preprocessor? Recently, we published a blog post on C++ conformance completion. As mentioned in the blog post, the preprocessor in MSVC is currently getting an overhaul. We are doing this to improve its language conformance, address some of the longstanding bugs that were difficult to fix due to its design and improve [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/20045","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/1062"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=20045"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/20045\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=20045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=20045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=20045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}