You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This option enables an experimental, token-based preprocessor that conforms to C++11 standards, including C99 preprocessor features.
10
+
This option enables an experimental, token-based preprocessor that more closely conforms to C++11 standards, including C99 preprocessor features. For more information, see [MSVC experimental preprocessor overview](../../preprocessor/preprocessor-experimental-overview.md).
11
11
12
12
## Syntax
13
13
@@ -19,219 +19,6 @@ Use the **/experimental:preprocessor** compiler option to enable the experimenta
19
19
20
20
The **/experimental:preprocessor** option is available starting in Visual Studio 2017 version 15.8.
21
21
22
-
You can detect which preprocessor is in use at compile time. Check the value of the predefined macro [\_MSVC\_TRADITIONAL](../../preprocessor/predefined-macros.md) to tell if the traditional preprocessor is in use. This macro is set unconditionally by versions of the compiler that support it, independent of which preprocessor is invoked. Its value is 1 for the traditional preprocessor. It's 0 for the conformant experimental preprocessor:
// Logic using cross-platform compatible preprocessor
29
-
#endif
30
-
```
31
-
32
-
### Behavior changes in the experimental preprocessor
33
-
34
-
Here are some of the more common breaking changes found when preprocessor conformance mode is enabled:
35
-
36
-
#### Macro comments
37
-
38
-
The traditional preprocessor uses character buffers instead of preprocessor tokens. That allows some unusual behavior, such as this preprocessor comment trick, which doesn't work under the conforming preprocessor:
39
-
40
-
```cpp
41
-
#if DISAPPEAR
42
-
#define DISAPPEARING_TYPE /##/
43
-
#else
44
-
#define DISAPPEARING_TYPE int
45
-
#endif
46
-
47
-
// myVal disappears when DISAPPEARING_TYPE is turned into a comment
48
-
// To make standards compliant, wrap the following line with the appropriate #if/#endif
49
-
DISAPPEARING_TYPE myVal;
50
-
```
51
-
52
-
#### String prefixes (L#val)
53
-
54
-
The traditional preprocessor incorrectly combines a string prefix to the result of the [stringizing operator (#)](../../preprocessor/stringizing-operator-hash.md):
55
-
56
-
```cpp
57
-
#defineDEBUG_INFO(val) L"debug prefix:" L#val
58
-
// ^
59
-
// this prefix
60
-
61
-
constwchar_t *info = DEBUG_INFO(hello world);
62
-
```
63
-
64
-
The `L` prefix is unnecessary here, because the adjacent string literals get combined after macro expansion anyway. The backward compatible fix is to change the definition to:
65
-
66
-
```cpp
67
-
#defineDEBUG_INFO(val) L"debug prefix:" #val
68
-
// ^
69
-
// no prefix
70
-
```
71
-
72
-
This issue is also found in convenience macros that 'stringize' the argument to a wide string literal:
73
-
74
-
```cpp
75
-
// The traditional preprocessor creates a single wide string literal token
76
-
#defineSTRING(str) L#str
77
-
78
-
// Potential fixes:
79
-
// Use string concatenation of L"" and #str to add prefix
80
-
// This works because adjacent string literals are combined after macro expansion
81
-
#defineSTRING1(str) L""#str
82
-
83
-
// Add the prefix after #str is stringized with additional macro expansion
84
-
#defineWIDE(str) L##str
85
-
#define STRING2(str) WIDE(#str)
86
-
87
-
// Use concatenation operator ## to combine the tokens.
88
-
// The order of operations for ## and # is unspecified, although all compilers
89
-
// checked perform the # operator before ## in this case.
90
-
#defineSTRING3(str) L## #str
91
-
```
92
-
93
-
#### Warning on invalid ##
94
-
95
-
When the [token-pasting operator (##)](../../preprocessor/token-pasting-operator-hash-hash.md) doesn't result in a single, valid preprocessing token, the behavior is undefined. The traditional preprocessor silently fails to combine the tokens. The new preprocessor matches the behavior of most other compilers and emits a diagnostic.
96
-
97
-
```cpp
98
-
// The ## is unnecessary and doesn't result in a single preprocessing token.
99
-
#define ADD_STD(x) std::##x
100
-
101
-
// Declare a std::string
102
-
ADD_STD(string) s;
103
-
```
104
-
105
-
#### Comma elision in variadic macros
106
-
107
-
Consider the following example:
108
-
109
-
```cpp
110
-
voidfunc(int, int = 2, int = 3);
111
-
// This macro replacement list has a comma followed by __VA_ARGS__
112
-
#define FUNC(a, ...) func(a, __VA_ARGS__)
113
-
int main()
114
-
{
115
-
// The following macro is replaced with:
116
-
// func(10,20,30)
117
-
FUNC(10, 20, 30);
118
-
119
-
// A conforming preprocessor replaces the following macro with:
120
-
// func(1, );
121
-
// which results in a syntax error.
122
-
FUNC(1, );
123
-
}
124
-
```
125
-
126
-
All major compilers have a preprocessor extension that helps address this issue. The traditional MSVC preprocessor always removes commas before empty `__VA_ARGS__` replacements. The updated preprocessor more closely follows 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 `##` operator:
127
-
128
-
```cpp
129
-
#define FUNC2(a, ...) func(a , ## __VA_ARGS__)
130
-
int main()
131
-
{
132
-
// The variadic argument is missing in the macro being evoked
133
-
// The comma is removed and replaced with:
134
-
// func(1)
135
-
FUNC2(1);
136
-
137
-
// The variadic argument is empty, but not missing. (Notice the
138
-
// comma in the argument list.) The comma isn't removed
139
-
// when the macro is replaced:
140
-
// func(1, )
141
-
FUNC2(1, );
142
-
}
143
-
```
144
-
145
-
In the upcoming C++2a standard, this issue has been addressed by adding `__VA_OPT__`, which isn't implemented yet.
146
-
147
-
#### Macro arguments are 'unpacked'
148
-
149
-
In the traditional preprocessor, if a macro forwards one of its arguments to another dependent macro, then the argument doesn't get "unpacked" when it's substituted. Usually this optimization goes unnoticed, but it can lead to unusual behavior:
150
-
151
-
```cpp
152
-
// Create a string out of the first argument, and the rest of the arguments.
// Traditional preprocessor results, all arguments are in the first string:
160
-
// const char c[2] = { "1, 2", };
161
-
```
162
-
163
-
When expanding `A()`, the traditional preprocessor forwards all of the arguments packaged in `__VA_ARGS__` to the first argument of `TWO_STRINGS`. The variadic argument of `TWO_STRINGS` is empty, which causes the result of `#first` to be `"1, 2"` rather than just `"1"`. You may be wondering what happened to the result of `#__VA_ARGS__` in the traditional preprocessor expansion. if the variadic parameter is empty, it should result in an empty string literal "". Because of a separate issue, the empty string literal token wasn't generated.
164
-
165
-
#### Rescanning replacement list for macros
166
-
167
-
After a macro is replaced, the resulting tokens are rescanned for additional macro identifiers to replace. The rescan algorithm used by the traditional preprocessor isn't conformant, as shown in this example based on actual code:
// MACRO chooses the expansion behavior based on the value passed to macro_switch
177
-
#define DO_THING(macro_switch, b) CAT(IMPL, macro_switch) ECHO(( "Hello", b))
178
-
179
-
DO_THING(1, "World");
180
-
// Traditional preprocessor:
181
-
// do_thing_one( "Hello", "World");
182
-
// Conformant preprocessor:
183
-
// IMPL1 ( "Hello","World");
184
-
```
185
-
186
-
To see what is going on in this example, we break down the expansion starting with `DO_THING`:
187
-
188
-
`DO_THING(1, "World")` ->
189
-
`CAT(IMPL, 1) ECHO(("Hello", "World"))`
190
-
191
-
Second, CAT is expanded:
192
-
193
-
`CAT(IMPL, 1)` -> `IMPL ## 1` -> `IMPL1`
194
-
195
-
Which puts the tokens into this state:
196
-
197
-
`IMPL1 ECHO(("Hello", "World"))`
198
-
199
-
The preprocessor finds the function-like macro identifier `IMPL1`, but it's not followed by a "(", so it's not considered a function-like macro invocation. It moves on to the following tokens and finds the function-like macro `ECHO` invoked:
`IMPL1` is never considered again for expansion, so the full result of the expansions is:
204
-
205
-
`IMPL1("Hello", "World");`
206
-
207
-
The macro can be modified to behave the same way under both the experimental preprocessor and the traditional preprocessor. The solution is to add another layer of indirection:
208
-
209
-
```cpp
210
-
#defineCAT(a,b) a##b
211
-
#define ECHO(...) __VA_ARGS__
212
-
213
-
// IMPL1 and IMPL2 are macros implementation details
The experimental preprocessor isn't complete yet, and some preprocessor directive logic still falls back to the traditional behavior. Here is a partial list of incomplete features:
228
-
229
-
- Support for `_Pragma`
230
-
- C++20 features
231
-
- Additional diagnostic improvements
232
-
- Switches to control the output under /E and /P
233
-
- Boost blocking bug: Logical operators in preprocessor constant expressions aren't fully implemented in the new preprocessor. On some `#if` directives, the new preprocessor can fall back to the traditional preprocessor. The effect is only noticeable when macros that are incompatible with the traditional preprocessor get expanded, which can happen when building Boost preprocessor slots.
234
-
235
22
### To set this compiler option in the Visual Studio development environment
236
23
237
24
1. Open the project's **Property Pages** dialog box. For details, see [Set C++ compiler and build properties in Visual Studio](../working-with-project-properties.md).
Copy file name to clipboardExpand all lines: docs/overview/visual-cpp-language-conformance.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
title: "Microsoft C++ language conformance table"
3
-
ms.date: "08/12/2019"
3
+
ms.date: "10/31/2019"
4
4
ms.technology: "cpp-language"
5
5
ms.assetid: 475da6e9-0d78-4b4e-bd23-f41c406c4efe
6
6
author: "corob-msft"
@@ -340,7 +340,7 @@ The compiler option [/Zc:noexceptTypes](../build/reference/zc-noexcepttypes.md)
340
340
341
341
<aname="note_B"></a>__B__ Supported in [/permissive-](../build/reference/permissive-standards-conformance.md) mode in Visual Studio 2017 version 15.7. see [Two-phase name lookup support comes to MSVC](https://blogs.msdn.microsoft.com/vcblog/2017/09/11/two-phase-name-lookup-support-comes-to-msvc/) for more information.
342
342
343
-
<aname="note_C"></a>__C__ The compiler’s support for C99 Preprocessor rules is incomplete in Visual Studio 2017. Variadic macros are supported, but there are many bugs in the preprocessor’s behavior. We are overhauling the preprocessor, and will experimentally ship those changes under the [/permissive-](../build/reference/permissive-standards-conformance.md)mode soon.
343
+
<aname="note_C"></a>__C__ The compiler’s support for C99 Preprocessor rules is incomplete in Visual Studio 2017. We are overhauling the preprocessor, and began shipping those changes in Visual Studio 2017 version 15.8 with the [/experimental:preprocessor](../build/reference/experimental-preprocessor.md)compiler switch.
344
344
345
345
<aname="note_D"></a>__D__ Supported under [/std:c++14](../build/reference/std-specify-language-standard-version.md) with a suppressible warning, [C4984](../error-messages/compiler-warnings/compiler-warning-c4984.md).
Copy file name to clipboardExpand all lines: docs/overview/what-s-new-for-visual-cpp-in-visual-studio.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -251,6 +251,10 @@ The compiler supports about 75% of the features that are new in C++17, including
251
251
252
252
The MSVC compiler toolset in Visual Studio version 15.7 now conforms with the C++ Standard. For more information, see [Announcing: MSVC Conforms to the C++ Standard](https://devblogs.microsoft.com/cppblog/announcing-msvc-conforms-to-the-c-standard/) and [Microsoft C++ Language Conformance](../visual-cpp-language-conformance.md).
253
253
254
+
##### Visual Studio 2017 version 15.8
255
+
256
+
The [/experimental:preprocessor](../build/reference/experimental-preprocessor.md) compiler switch enables the new experimental MSVC preprocessor that will eventually be conformant with all applicable C and C++ standards. For more information, see [MSVC experimental preprocessor overview](../preprocessor/preprocessor-experimental-overview.md).
257
+
254
258
### New compiler options
255
259
256
260
-[/permissive-](../build/reference/permissive-standards-conformance.md): Enable all strict standards conformance compiler options and disable most Microsoft-specific compiler extensions (but not `__declspec(dllimport)`, for example). This option is on by default in Visual Studio 2017 version 15.5. The **/permissive-** conformance mode includes support for two-phase name lookup. For more information, see [C++ Conformance Improvements in Visual Studio](cpp-conformance-improvements.md).
The *C/C++ preprocessor reference* explains the preprocessor as it is implemented in Microsoft C/C++. The preprocessor performs preliminary operations on C and C++ files before they are passed to the compiler. You can use the preprocessor to conditionally compile code, insert files, specify compile-time error messages, and apply machine-specific rules to sections of code.
10
10
11
+
In Visual Studio 2019 the [/experimental:preprocessor](../build/reference/experimental-preprocessor.md) compiler option enables a new implementation of the preprocessor. The new implementation is still in progress, and is therefore considered experimental. It is intended to eventually be conformant with C99, C11, and C++20. For more information, see [MSVC experimental preprocessor overview](preprocessor-experimental-overview.md).
12
+
11
13
## In this section
12
14
15
+
[Preprocessor](preprocessor.md)\
16
+
Provides an overview of the traditional and new experimental preprocessors.
0 commit comments