Skip to content

Commit dff7024

Browse files
Colin RobertsonGitHubber17
authored andcommitted
Add experimental module, newLambdaProcessor, preprocessor (#2267)
* First pass at experimental switches * Add experimental compiler options * Fix link issues * Remove lambda processor * Add description to new articles.
1 parent 10e14d3 commit dff7024

10 files changed

+326
-9
lines changed

docs/build/reference/compiler-options-listed-alphabetically.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ The following is a comprehensive alphabetical list of compiler options. For a ca
2929
|[/EP](ep-preprocess-to-stdout-without-hash-line-directives.md)|Copies preprocessor output to standard output.|
3030
|[/errorReport](errorreport-report-internal-compiler-errors.md)|Allows you to provide internal compiler error (ICE) information directly to the Microsoft C++ team.|
3131
|[/execution-charset](execution-charset-set-execution-character-set.md)|Set execution character set.|
32+
|[/experimental:module](experimental-module.md)|Enables experimental module support.|
33+
|[/experimental:preprocessor](experimental-preprocessor.md)|Enables experimental conforming preprocessor support.|
3234
|[/F](f-set-stack-size.md)|Sets stack size.|
3335
|[/favor](favor-optimize-for-architecture-specifics.md)|Produces code that is optimized for a specific x64 architecture or for the specifics of micro-architectures in both the AMD64 and Extended Memory 64 Technology (EM64T) architectures.|
3436
|[/FA](fa-fa-listing-file.md)|Creates a listing file.|

docs/build/reference/compiler-options-listed-by-category.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,15 @@ This article contains a categorical list of compiler options. For an alphabetica
188188
|[/permissive-](permissive-standards-conformance.md)|Set standard-conformance mode.|
189189
|[/std](std-specify-language-standard-version.md)|C++ standard version compatibility selector.|
190190

191+
## Experimental options
192+
193+
Experimental options may only be supported by certain versions of the compiler, and may behave differently in different compiler versions. Often the best, or only, documentation for experimental options is in the [Microsoft C++ Team Blog](https://devblogs.microsoft.com/cppblog/).
194+
195+
|Option|Purpose|
196+
|------------|-------------|
197+
|[/experimental:module](experimental-module.md)|Enables experimental module support.|
198+
|[/experimental:preprocessor](experimental-preprocessor.md)|Enables experimental conforming preprocessor support.|
199+
191200
## Deprecated and removed compiler options
192201

193202
|Option|Purpose|
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: "/experimental:module (Enable module support)"
3+
description: "Use the /experimental:module compiler option to enable experimental compiler support for modules."
4+
ms.date: "09/03/2019"
5+
f1_keywords: ["module", "/experimental:module"]
6+
helpviewer_keywords: ["module", "/experimental:module", "Enable module support"]
7+
---
8+
# /experimental:module (Enable module support)
9+
10+
Enables experimental compiler support for modules, as specified by the draft C++20 standard.
11+
12+
## Syntax
13+
14+
> **/experimental:module**[**-**]
15+
16+
## Remarks
17+
18+
You can enable experimental modules support by use of the **/experimental:module** compiler option along with the [/std:c++latest](std-specify-language-standard-version.md) option. You can use **/experimental:module-** to disable module support explicitly.
19+
20+
This option is available starting in Visual Studio 2015 Update 1. As of Visual Studio 2019 version 16.2, Draft C++20 Standard modules are not fully implemented in the Microsoft C++ compiler. You can use the modules feature to create single-partition modules and to import the Standard Library modules provided by Microsoft. A module and the code that consumes it must be compiled with the same compiler options.
21+
22+
For more information on modules and how to use and create them, see [Overview of modules in C++](../../cpp/modules-cpp.md).
23+
24+
Here's an example of the compiler command-line options used to create an export module from source file *ModuleName.ixx*:
25+
26+
```cmd
27+
cl /EHsc /MD /experimental:module /module:export /module:name ModuleName /module:wrapper C:\Output\path\ModuleName.h /module:output C:\Output\path\ModuleName.ifc -c ModuleName.ixx
28+
```
29+
30+
### To set this compiler option in the Visual Studio development environment
31+
32+
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).
33+
34+
1. Set the **Configuration** drop-down to **All Configurations**.
35+
36+
1. Select the **Configuration Properties** > **C/C++** > **Language** property page.
37+
38+
1. Modify the **Enable C++ Modules (experimental)** property, and then choose **OK**.
39+
40+
## See also
41+
42+
[/Zc (Conformance)](zc-conformance.md)
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
---
2+
title: "/experimental:preprocessor (Enable preprocessor conformance mode)"
3+
description: "Use the /experimental:preprocessor compiler option to enable experimental compiler support for a standard conforming preprocessor."
4+
ms.date: "09/03/2019"
5+
f1_keywords: ["preprocessor", "/experimental:preprocessor"]
6+
helpviewer_keywords: ["preprocessor conformance", "/experimental:preprocessor", "Enable preprocessor conformance mode"]
7+
---
8+
# /experimental:preprocessor (Enable preprocessor conformance mode)
9+
10+
This option enables an experimental, token-based preprocessor that conforms to C++11 standards, including C99 preprocessor features.
11+
12+
## Syntax
13+
14+
> **/experimental:preprocessor**[**-**]
15+
16+
## Remarks
17+
18+
Use the **/experimental:preprocessor** compiler option to enable the experimental conforming preprocessor. You can use **/experimental:preprocessor-** option to explicitly specify the traditional preprocessor.
19+
20+
The **/experimental:preprocessor** option is available starting in Visual Studio 2017 version 15.8.
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:
23+
24+
```cpp
25+
#if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL
26+
// Logic using the traditional preprocessor
27+
#else
28+
// 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+
#define DEBUG_INFO(val) L"debug prefix:" L#val
58+
// ^
59+
// this prefix
60+
61+
const wchar_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+
#define DEBUG_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+
#define STRING(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+
#define STRING1(str) L""#str
82+
83+
// Add the prefix after #str is stringized with additional macro expansion
84+
#define WIDE(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+
#define STRING3(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+
void func(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.
153+
#define TWO_STRINGS( first, ... ) #first, #__VA_ARGS__
154+
#define A( ... ) TWO_STRINGS(__VA_ARGS__)
155+
156+
const char* c[2] = { A(1, 2) };
157+
// Conformant preprocessor results:
158+
// const char c[2] = { "1", "2" };
159+
// 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:
168+
169+
```cpp
170+
#define CAT(a,b) a ## b
171+
#define ECHO(...) __VA_ARGS__
172+
173+
// IMPL1 and IMPL2 are implementation details
174+
#define IMPL1(prefix,value) do_thing_one( prefix, value)
175+
#define IMPL2(prefix,value) do_thing_two( prefix, value)
176+
// 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:
200+
201+
`ECHO(("Hello", "World"))` -> `("Hello", "World")`
202+
203+
`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+
#define CAT(a,b) a##b
211+
#define ECHO(...) __VA_ARGS__
212+
213+
// IMPL1 and IMPL2 are macros implementation details
214+
#define IMPL1(prefix,value) do_thing_one( prefix, value)
215+
#define IMPL2(prefix,value) do_thing_two( prefix, value)
216+
217+
#define CALL(macroName, args) macroName args
218+
#define DO_THING_FIXED(a,b) CALL( CAT(IMPL, a), ECHO(( "Hello",b)))
219+
220+
DO_THING_FIXED(1, "World");
221+
// macro expanded to:
222+
// do_thing_one( "Hello", "World");
223+
```
224+
225+
### Conformance mode conformance
226+
227+
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+
### To set this compiler option in the Visual Studio development environment
236+
237+
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).
238+
239+
1. Select the **Configuration Properties** > **C/C++** > **Command Line** property page.
240+
241+
1. Modify the **Additional Options** property to include **/experimental:preprocessor** and then choose **OK**.
242+
243+
## See also
244+
245+
[/Zc (Conformance)](zc-conformance.md)

docs/build/reference/permissive-standards-conformance.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,5 +452,5 @@ In versions before Visual Studio 2017 version 15.5, use this procedure:
452452
453453
## See also
454454
455-
- [MSVC Compiler Options](compiler-options.md)
456-
- [MSVC Compiler Command-Line Syntax](compiler-command-line-syntax.md)
455+
[MSVC Compiler Options](compiler-options.md)\
456+
[MSVC Compiler Command-Line Syntax](compiler-command-line-syntax.md)

docs/cpp/import-export-module.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ description: Use the import statement to access types and functions defined in t
88

99
# module, import, export
1010

11-
The **module**, **import**, and **export** keywords are available in C++20 and require the `/experimental:modules` compiler switch along with `/std:c++latest`. For more information, see [Overview of modules in C++](modules-cpp.md).
11+
The **module**, **import**, and **export** keywords are available in C++20 and require the [/experimental:module](../build/reference/experimental-module.md) compiler switch along with [/std:c++latest](../build/reference/std-specify-language-standard-version.md). For more information, see [Overview of modules in C++](modules-cpp.md).
1212

1313
## module
1414

@@ -76,4 +76,5 @@ class Baz
7676
```
7777
7878
## See Also
79+
7980
[Overview of modules in C++](modules-cpp.md)

docs/cpp/modules-cpp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Modules can be used side by side with header files. A C++ source file can import
1313

1414
## Enable modules in the Microsoft C++ compiler
1515

16-
As of Visual Studio 2019 version 16.2, modules are not fully implemented in the Microsoft C++ compiler. You can use the modules feature to create single-partition modules and to import the Standard Library modules provided by Microsoft. To enable support for modules, compile with `/experimental:modules` and `/std:c++latest`. In a Visual Studio project, right-click the project node in **Solution Explorer** and choose **Properties**. Set the **Configuration** drop-down to **All Configurations**, then choose **Configuration Properties** > **C/C++** > **Language** > **Enable C++ Modules (experimental)**.
16+
As of Visual Studio 2019 version 16.2, modules are not fully implemented in the Microsoft C++ compiler. You can use the modules feature to create single-partition modules and to import the Standard Library modules provided by Microsoft. To enable support for modules, compile with [/experimental:module](../build/reference/experimental-module.md) and [/std:c++latest](../build/reference/std-specify-language-standard-version.md). In a Visual Studio project, right-click the project node in **Solution Explorer** and choose **Properties**. Set the **Configuration** drop-down to **All Configurations**, then choose **Configuration Properties** > **C/C++** > **Language** > **Enable C++ Modules (experimental)**.
1717

1818
A module and the code that consumes it must be compiled with the same compiler options.
1919

docs/error-messages/compiler-errors-2/compiler-error-c2760.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ ms.assetid: 585757fd-d519-43f3-94e5-50316ac8b90b
77
---
88
# Compiler Error C2760
99

10-
syntax error : expected 'name1' not 'name2'
10+
> syntax error : expected '*name1*' not '*name2*'
1111
12-
A casting operator is used with an invalid operator.
12+
## Remarks
1313

14-
The following sample generates C2760:
14+
There are several ways to cause this error. Usually, it's caused by a token sequence that the compiler can't make sense of.
1515

16-
```
16+
## Example
17+
18+
In this sample, a casting operator is used with an invalid operator.
19+
20+
```cpp
1721
// C2760.cpp
1822
class B {};
1923
class D : public B {};
@@ -23,4 +27,4 @@ void f(B* pb) {
2327
D* pd2 = static_cast<D*>=(pb); // C2760
2428
D* pd3 = static_cast<D*=(pb); // C2760
2529
}
26-
```
30+
```

docs/preprocessor/predefined-macros.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ MSVC supports these additional predefined macros.
259259

260260
- **&#95;&#95;MSVC&#95;RUNTIME&#95;CHECKS** Defined as 1 when one of the [/RTC](../build/reference/rtc-run-time-error-checks.md) compiler options is set. Otherwise, undefined.
261261

262+
- **&#95;MSVC&#95;TRADITIONAL** Defined as 0 when the preprocessor conformance mode [/experimental:preprocessor](../build/reference/rtc-run-time-error-checks.md) compiler option is set. Defined as 1 by default, or when the [/experimental:preprocessor-](../build/reference/rtc-run-time-error-checks.md) compiler option is set, to indicate the traditional preprocessor is in use. The **&#95;MSVC&#95;TRADITIONAL** macro and [/experimental:preprocessor (Enable preprocessor conformance mode)](../build/reference/experimental-preprocessor.md) compiler option is available beginning in Visual Studio 2017 version 15.8.
263+
264+
```cpp
265+
#if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL
266+
// Logic using the traditional preprocessor
267+
#else
268+
// Logic using cross-platform compatible preprocessor
269+
#endif
270+
```
271+
262272
- **&#95;MT** Defined as 1 when [/MD or /MDd](../build/reference/md-mt-ld-use-run-time-library.md) (Multithreaded DLL) or [/MT or /MTd](../build/reference/md-mt-ld-use-run-time-library.md) (Multithreaded) is specified. Otherwise, undefined.
263273

264274
- **&#95;NATIVE&#95;WCHAR&#95;T&#95;DEFINED** Defined as 1 when the [/Zc:wchar_t](../build/reference/zc-wchar-t-wchar-t-is-native-type.md) compiler option is set. Otherwise, undefined.

0 commit comments

Comments
 (0)