diff --git a/.acrolinx-config.edn b/.acrolinx-config.edn deleted file mode 100644 index 78cdd0e4df0..00000000000 --- a/.acrolinx-config.edn +++ /dev/null @@ -1,27 +0,0 @@ -{:allowed-branchname-matches ["main" "release-.*"] - :allowed-filename-matches ["docs" "styleguide"] - - :template-header - " -## Acrolinx Scorecards - - Click the scorecard links for each article to review the Acrolinx feedback on grammar, spelling, punctuation, writing style, and terminology: - -| Article | Score | Issues | Scorecard | -| ------- | ----- | ------ | --------- | -" - - ;; do not remove the spaces at the end of lines! That is markdown for - ;; linebreak - :template-change - "| **${github/filename}** | ${acrolinx/qualityscore} | ${acrolinx/flags/issues} | [link](${acrolinx/scorecard}) | -" - - :template-footer -" -**More info about Acrolinx** - -- [Install Acrolinx locally for VS Code](https://review.docs.microsoft.com/en-us/help/contribute/contribute-acrolinx-vscode) -- [Report false positives or issues](https://aka.ms/acrolinxbug) - -"} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 75e32e18c89..6498b2c6631 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -15,6 +15,9 @@ This document uses the following markers to indicate instruction priority: ## General Guidelines +### Using MCP tools +If the user intent relates to Azure Devops, make sure to prioritize the Azure DevOps MCP server tools. + ### 1. Issue Handling When creating a PR for an issue: - [ ] Read the full issue and all linked references diff --git a/.github/workflows/generate-preview-links.yml b/.github/workflows/generate-preview-links.yml new file mode 100644 index 00000000000..784d2be5b6e --- /dev/null +++ b/.github/workflows/generate-preview-links.yml @@ -0,0 +1,25 @@ +name: 'Preview link generator' + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: + contents: read + +jobs: + preview_link_generator_job: + name: Generate preview link table + runs-on: ubuntu-latest + permissions: + statuses: read + pull-requests: write + steps: + - name: Harden Runner + uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1 + with: + egress-policy: audit + + - uses: dotnet/docs-tools/actions/preview-link-generator@main + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 717a62c31c1..e437970bff5 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1,5 +1,10 @@ { "redirections": [ + { + "source_path": "docs/porting/copilot-app-modernization-cpp.md", + "redirect_url": "/cpp/porting/github-copilot-modernization-cpp/overview", + "redirect_document_id": true + }, { "source_path": "docs/parallel/amp/cpp-amp-cpp-accelerated-massive-parallelism.md", "redirect_url": "/previous-versions/cpp/parallel/amp/cpp-amp-cpp-accelerated-massive-parallelism", diff --git a/docs/assembler/masm/at-unwindversion.md b/docs/assembler/masm/at-unwindversion.md new file mode 100644 index 00000000000..388cfd802e7 --- /dev/null +++ b/docs/assembler/masm/at-unwindversion.md @@ -0,0 +1,60 @@ +--- +description: "Learn more about: @UnwindVersion" +title: "@UnwindVersion" +ms.date: 05/07/2026 +f1_keywords: ["@UnwindVersion"] +helpviewer_keywords: ["@UnwindVersion symbol"] +ai-usage: ai-assisted +--- +# \@UnwindVersion + +A predefined macro that returns the unwind version the `.asm` file is being assembled with. + +## Syntax + +> **\@UnwindVersion** + +## Remarks + +> [!IMPORTANT] +> This symbol is experimental and is subject to change. Enable Unwind Version 3 with `ml64.exe /unwindv3`. + +**\@UnwindVersion** is set to the unwind version used by the assembler. When `/unwindv3` is passed to `ml64.exe`, **\@UnwindVersion** is set to `3`; otherwise it's set to `1`. + +Use this macro with conditional assembly directives such as `IF` to assemble different code paths depending on the unwind version. + +This example is intended to be assembled only as it doesn't define an application entry point: + +## Example for unwindv3 + +```asm +; ml64 /c /unwindv3 ex1.asm +.code + +IF @UnwindVersion EQ 3 + +foo PROC FRAME + .pushreg r12 + push r12 + + .endprolog + + mov rax, 0 + + .beginepilog + .popreg r12 + pop r12 + .endepilog + ret +foo ENDP +ELSE + .ERR <@UnwindVersion should be 3> +ENDIF + +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/directives-reference.md b/docs/assembler/masm/directives-reference.md index c9f7208c7d7..97de3fcad7a 100644 --- a/docs/assembler/masm/directives-reference.md +++ b/docs/assembler/masm/directives-reference.md @@ -4,7 +4,7 @@ title: "Directives Reference" ms.date: 07/15/2020 f1_keywords: ["Directives Reference"] helpviewer_keywords: ["MASM (Microsoft Macro Assembler), directives reference"] -ms.assetid: da6efcd1-18f7-41de-81cd-a002a02f9a22 +ai-usage: ai-assisted --- # Directives Reference @@ -27,6 +27,49 @@ ms.assetid: da6efcd1-18f7-41de-81cd-a002a02f9a22 :::column-end::: :::row-end::: +## x64 Unwind Version 3 (experimental) + +The following directives are used with `ml64.exe` when the `/unwindv3` option is enabled. Unwind Version 3 is experimental and is subject to change. + +**Prologue directives** + +:::row::: + :::column span=""::: + [`.ALLOCSTACK`](dot-allocstack.md)\ + [`.ENDPROLOG`](dot-endprolog.md)\ + [`.PUSH2REG`](dot-push2reg.md) + :::column-end::: + :::column span=""::: + [`.PUSHFRAME`](dot-pushframe.md)\ + [`.PUSHREG`](dot-pushreg.md)\ + [`.SAVEREG`](dot-savereg.md) + :::column-end::: + :::column span=""::: + [`.SAVEXMM128`](dot-savexmm128.md)\ + [`.SETFRAME`](dot-setframe.md) + :::column-end::: +:::row-end::: + +**Epilogue directives** + +:::row::: + :::column span=""::: + [`.BEGINEPILOG`](dot-beginepilog.md)\ + [`.ENDEPILOG`](dot-endepilog.md)\ + [`.FREESTACK`](dot-freestack.md) + :::column-end::: + :::column span=""::: + [`.POP2REG`](dot-pop2reg.md)\ + [`.POPFRAME`](dot-popframe.md)\ + [`.POPREG`](dot-popreg.md)\ + [`.RESTOREREG`](dot-restorereg.md) + :::column-end::: + :::column span=""::: + [`.RESTOREXMM128`](dot-restorexmm128.md)\ + [`.UNSETFRAME`](dot-unsetframe.md) + :::column-end::: +:::row-end::: + ## Code Labels :::row::: diff --git a/docs/assembler/masm/dot-allocstack.md b/docs/assembler/masm/dot-allocstack.md index 13c5e6e1146..6d0881627bd 100644 --- a/docs/assembler/masm/dot-allocstack.md +++ b/docs/assembler/masm/dot-allocstack.md @@ -1,39 +1,41 @@ --- description: "Learn more about: .ALLOCSTACK" title: ".ALLOCSTACK" -ms.date: "12/17/2019" +ms.date: 05/11/2026 f1_keywords: [".ALLOCSTACK"] helpviewer_keywords: [".ALLOCSTACK directive"] -ms.assetid: 9801594b-7ac2-4df2-a49d-07d9dd9af99e +ai-usage: ai-assisted --- # .ALLOCSTACK -Generates a **UWOP_ALLOC_SMALL** or a **UWOP_ALLOC_LARGE** with the specified size for the current offset in the prologue. +`.ALLOCSTACK` generates a **UWOP_ALLOC_SMALL** or a **UWOP_ALLOC_LARGE** with the specified size for the current offset in the prologue. ## Syntax -> **.ALLOCSTACK** *size* +> `.ALLOCSTACK` *size* ## Remarks -MASM will choose the most efficient encoding for a given size. +Microsoft Assembler (MASM) chooses the most efficient encoding for a given size. -**.ALLOCSTACK** allows ml64.exe users to specify how a frame function unwinds and is only allowed within the prologue, which extends from the [PROC](proc.md) FRAME declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives do not generate code; they only generate `.xdata` and `.pdata`. **.ALLOCSTACK** should be preceded by instructions that actually implement the actions to be unwound. It is a good practice to wrap both the unwind directives and the code they are meant to unwind in a macro to ensure agreement. +`.ALLOCSTACK` allows `ml64.exe` users to specify how a frame function unwinds and is only allowed within the prologue, which extends from the [PROC](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- Precede `.ALLOCSTACK` with the instructions that actually implement the actions to be unwound. Wrap both the unwind directives and the code they're meant to unwind in a macro to ensure agreement. The *size* operand must be a multiple of 8. -For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +The epilogue counterpart is [.FREESTACK](dot-freestack.md). -## Sample +## Example: specify an unwind version 3 unwind/exception handler The following sample shows how to specify an unwind/exception handler: ```asm -; ml64 ex3.asm /link /entry:Example1 /SUBSYSTEM:Console +; ml64 ex3.asm /link /entry:Example3 /SUBSYSTEM:Console text SEGMENT PUBLIC Example3 PUBLIC Example3_UW -Example3_UW PROC NEAR +Example3_UW PROC ; exception/unwind handler body ret 0 @@ -56,7 +58,61 @@ text ENDS END ``` +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. Enable it by using `ml64.exe /unwindv3`. + +`.ALLOCSTACK` generates a `WOD_ALLOC_SMALL`, `WOD_ALLOC_LARGE`, or `WOD_ALLOC_HUGE` Unwind Version 3 unwind code entry with the specified size for the current offset in the prolog. + +`.ALLOCSTACK` must appear **before** the `sub rsp, N` instruction it describes. This requirement is the opposite of Version 1, where the directive follows the instruction. + +MASM emits one of three unwind codes depending on the allocation size: + +| Unwind code | Condition | +|---|---| +| `WOD_ALLOC_SMALL` | *size* ≤ 128 bytes | +| `WOD_ALLOC_LARGE` | *size* ≤ 32 KB | +| `WOD_ALLOC_HUGE` | *size* > 32 KB | + +Version 1 generates only `UWOP_ALLOC_SMALL` or `UWOP_ALLOC_LARGE`. Version 3 adds a third variant, `WOD_ALLOC_HUGE`, for allocations larger than 32 KB. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +### Example for unwindv3 + +```asm +; ml64 ex3.asm /unwindv3 /link /entry:Example3 /SUBSYSTEM:Console +text SEGMENT +PUBLIC Example3 +PUBLIC Example3_UW +Example3_UW PROC + ; exception/unwind handler body + + ret 0 + +Example3_UW ENDP + +Example3 PROC FRAME : Example3_UW + +.allocstack 16 + sub rsp, 16 + +.endprolog + + ; function body + add rsp, 16 + ret 0 + +Example3 ENDP +text ENDS +END +``` + ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ [Directives Reference](directives-reference.md)\ -[MASM BNF Grammar](masm-bnf-grammar.md) +[MASM BNF Grammar](masm-bnf-grammar.md)\ +[MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md) \ No newline at end of file diff --git a/docs/assembler/masm/dot-beginepilog.md b/docs/assembler/masm/dot-beginepilog.md new file mode 100644 index 00000000000..9f05bcdaf1d --- /dev/null +++ b/docs/assembler/masm/dot-beginepilog.md @@ -0,0 +1,59 @@ +--- +description: "Learn more about: .BEGINEPILOG" +title: ".BEGINEPILOG" +ms.date: 05/04/2026 +ai-usage: ai-assisted +f1_keywords: [".BEGINEPILOG"] +helpviewer_keywords: [".BEGINEPILOG directive"] +--- +# .BEGINEPILOG + +Marks the start of an epilogue unwind region. This directive doesn't emit an Unwind Operation Descriptors (WOD) code. + +## Syntax + +> `.BEGINEPILOG` + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. +> Enable Unwind Version 3 by using `ml64.exe /unwindv3`. + +`.BEGINEPILOG` is only valid in Unwind Version 3. + +- It marks the start of an epilogue region where epilogue unwind operations are recorded. Pair `.BEGINEPILOG` with a closing [.ENDEPILOG](dot-endepilog.md) or no epilog unwind codes are emitted. +- In Unwind Version 3, epilog directives are mandatory for epilog unwind code generation. +- Epilogues must contain at least one directive. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 16 + sub rsp, 16 +.endprolog + ; function body + .beginepilog + .freestack 16 + add rsp, 16 + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.ENDEPILOG](dot-endepilog.md)\ +[.ENDPROLOG](dot-endprolog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-endepilog.md b/docs/assembler/masm/dot-endepilog.md new file mode 100644 index 00000000000..af9383ae19e --- /dev/null +++ b/docs/assembler/masm/dot-endepilog.md @@ -0,0 +1,60 @@ +--- +description: "Learn more about: .ENDEPILOG" +title: ".ENDEPILOG" +ms.date: "04/29/2026" +ai-usage: ai-assisted +f1_keywords: [".ENDEPILOG"] +helpviewer_keywords: [".ENDEPILOG directive"] +--- +# .ENDEPILOG + +Marks the end of an epilogue unwind region. This directive doesn't emit a Windows unwind data (WOD) unwind code. + +## Syntax + +> **.ENDEPILOG** + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. +> Enable Unwind Version 3 by using `ml64.exe /unwindv3`. + +**.ENDEPILOG** is only valid in Unwind Version 3. + +- It marks the end of an epilogue region started by [.BEGINEPILOG](dot-beginepilog.md). +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- Epilogues must contain at least one directive. +- Epilogue directives are mandatory for epilogue unwind code generation. No epilogue unwind codes are emitted without a `.BEGINEPILOG`/`.ENDEPILOG` pair. +- It's an error to use epilogue directives outside of the region between [.BEGINEPILOG](dot-beginepilog.md) and **.ENDEPILOG**. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 16 + sub rsp, 16 +.endprolog + ; function body + .beginepilog + .freestack 16 + add rsp, 16 + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[.ENDPROLOG](dot-endprolog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-endprolog.md b/docs/assembler/masm/dot-endprolog.md index c864e0c8494..bc366ab72e5 100644 --- a/docs/assembler/masm/dot-endprolog.md +++ b/docs/assembler/masm/dot-endprolog.md @@ -1,14 +1,14 @@ --- description: "Learn more about: .ENDPROLOG" title: ".ENDPROLOG" -ms.date: "12/17/2019" +ms.date: 05/06/2026 f1_keywords: [".ENDPROLOG"] helpviewer_keywords: [".ENDPROLOG directive"] -ms.assetid: 61a2474c-9527-46e6-9f9d-bc4b42c10f35 +ai-usage: ai-assisted --- # .ENDPROLOG -Signals the end of the prologue declarations. +Marks the end of the prologue declarations. ## Syntax @@ -16,11 +16,22 @@ Signals the end of the prologue declarations. ## Remarks -It is an error to use any of the prologue declarations outside of the region between [PROC](proc.md) **FRAME** and **.ENDPROLOG**. +It's an error to use any of the prologue declarations outside of the region between [PROC](proc.md) `FRAME` and **.ENDPROLOG**. For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. +> Enable it with `ml64.exe /unwindv3`. + +`.ENDPROLOG` is also used in Unwind Version 3 and continues to mark the end of the function prologue. It doesn't generate a Windows unwind data (WOD) unwind code entry. + +It's an error to use any prologue directive outside the region between `PROC FRAME` and `.ENDPROLOG`. + ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ [Directives Reference](directives-reference.md)\ [MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-freestack.md b/docs/assembler/masm/dot-freestack.md new file mode 100644 index 00000000000..bf80a2be682 --- /dev/null +++ b/docs/assembler/masm/dot-freestack.md @@ -0,0 +1,74 @@ +--- +description: "Learn more about: .FREESTACK" +title: ".FREESTACK" +ms.date: 05/06/2026 +f1_keywords: [".FREESTACK"] +helpviewer_keywords: [".FREESTACK directive"] +ai-usage: ai-assisted +--- +# .FREESTACK + +Generates a **WOD_ALLOC_SMALL**, **WOD_ALLOC_LARGE**, or **WOD_ALLOC_HUGE** unwind code entry with the specified size for the current offset in the epilogue. + +## Syntax + +> **.FREESTACK** *size* + +## Parameters + +*size*\ +The number of bytes to deallocate from the stack. Must be a multiple of 8. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. +> Enable Unwind Version 3 by using `ml64.exe /unwindv3`. + +- You can use **.FREESTACK** only in Unwind Version 3. It's the epilogue counterpart to [.ALLOCSTACK](dot-allocstack.md). +- You can use **.FREESTACK** only within an epilogue region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). +- In Unwind Version 3, **.FREESTACK** must appear **before** the `add rsp, N` instruction that implements the stack deallocation. +- To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- Microsoft Assembler (MASM) chooses the most efficient encoding for a given size. + +MASM emits one of three unwind codes depending on the size: + +| Unwind code | Condition | +|---|---| +| `WOD_ALLOC_SMALL` | *size* ≤ 128 bytes | +| `WOD_ALLOC_LARGE` | *size* ≤ 32 KB | +| `WOD_ALLOC_HUGE` | *size* > 32 KB | + +In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. The assembler doesn't emit epilogue unwind codes without a `.BEGINEPILOG`/`.ENDEPILOG` pair. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 16 + sub rsp, 16 +.endprolog + ; function body + .beginepilog + .freestack 16 + add rsp, 16 + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.ALLOCSTACK](dot-allocstack.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-pop2reg.md b/docs/assembler/masm/dot-pop2reg.md new file mode 100644 index 00000000000..56dbdff4b52 --- /dev/null +++ b/docs/assembler/masm/dot-pop2reg.md @@ -0,0 +1,76 @@ +--- +description: "Learn more about: .POP2REG" +title: ".POP2REG" +ms.date: 05/04/2026 +f1_keywords: [".POP2REG"] +helpviewer_keywords: [".POP2REG directive"] +ai-usage: ai-assisted +--- +# .POP2REG + +Generates a two-register pop unwind code entry for the specified register pair using the current offset in the epilogue. + +## Syntax + +> **.POP2REG** *register1*, *register2* + +## Parameters + +*register1*\ +The first register to pop. Must be a general-purpose 64-bit register. + +*register2*\ +The second register to pop. Must be a general-purpose 64-bit register. + +*register1* and *register2* may each be one of:\ +`RAX, RCX, RDX, RBX, RDI, RSI, RBP, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31`. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 with `ml64.exe /unwindv3`. + +- **.POP2REG** is only valid in Unwind Version 3. It's the epilogue counterpart to [.PUSH2REG](dot-push2reg.md). +- **.POP2REG** is only allowed within an epilogue region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- In Unwind Version 3, **.POP2REG** must appear **before** the instruction that actually implements the action to be unwound. +- In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. No epilogue unwind codes are emitted without a `.BEGINEPILOG`/`.ENDEPILOG` pair. +- To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. + +If *register1* and *register2* are consecutive and in increasing order, MASM emits a `WOD_PUSH_CONSECUTIVE_2` unwind code. Otherwise, MASM emits a `WOD_PUSH2` unwind code. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .push2reg rbx, rsi + push2 rbx, rsi + .push2reg r10, r11 + push2 r10, r11 +.endprolog + ; rest of function ... + .beginepilog + .pop2reg r10, r11 + pop2 r10, r11 + .pop2reg rbx, rsi + pop2 rbx, rsi + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.PUSH2REG](dot-push2reg.md)\ +[.POPREG](dot-popreg.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-popframe.md b/docs/assembler/masm/dot-popframe.md new file mode 100644 index 00000000000..6f0d869f13d --- /dev/null +++ b/docs/assembler/masm/dot-popframe.md @@ -0,0 +1,74 @@ +--- +description: "Learn more about: .POPFRAME" +title: ".POPFRAME" +ms.date: 05/01/2026 +f1_keywords: [".POPFRAME"] +helpviewer_keywords: [".POPFRAME directive"] +ai-usage: ai-assisted +--- +# .POPFRAME + +Generates a `WOD_PUSH_CANONICAL_FRAME` Windows unwind data (WOD) unwind code entry in the epilogue. + +## Syntax + +> **.POPFRAME** ⟦**CODE** | *value*⟧ + +## Parameters + +*value*\ +An optional numeric modifier in the range 0–255.\ +Mutually exclusive with **CODE**. If you specify the optional **CODE** keyword, the unwind code entry receives a modifier of 1.\ +If you specify an optional numeric *value* instead, it receives the specified value.\ +If you don't pass an argument, the value is 0. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 with `ml64.exe /unwindv3`. + +The **.POPFRAME** directive lets `ml64.exe` users specify how a frame function unwinds in an epilog. You can only use it within an epilog region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). + +- **.POPFRAME** is only valid in Unwind Version 3. It's the epilog counterpart of [.PUSHFRAME](dot-pushframe.md). The operand value should match the corresponding **.PUSHFRAME** in the prologue. +- In Unwind Version 3, **.POPFRAME** must appear **before** the instruction that implements the action to be unwound. To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. +- In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. No epilogue unwind codes are emitted without a `.BEGINEPILOG`/`.ENDEPILOG` pair. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. + +> [!NOTE] +> In Unwind Version 1, directives appear after the corresponding instruction. In Unwind Version 3, directives appear **before** the instruction. + +## Example for unwindv3 + +The following example shows how to use **.POPFRAME** in an epilogue to indicate an interrupt handler that pushes and pops a canonical machine frame. + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .pushframe + .pushreg rbx + push rbx + .allocstack 32 + sub rsp, 32 +.endprolog + ; interrupt handler body ... + .beginepilog + .freestack 32 + add rsp, 32 + .popreg rbx + pop rbx + .popframe + .endepilog + iretq +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[.PUSHFRAME](dot-pushframe.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[.ENDEPILOG](dot-endepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-popreg.md b/docs/assembler/masm/dot-popreg.md new file mode 100644 index 00000000000..963e7de0f48 --- /dev/null +++ b/docs/assembler/masm/dot-popreg.md @@ -0,0 +1,70 @@ +--- +description: "Learn more about: .POPREG" +title: ".POPREG" +ms.date: 05/04/2026 +f1_keywords: [".POPREG"] +helpviewer_keywords: [".POPREG directive"] +ai-usage: ai-assisted +--- +# .POPREG + +Generates a `WOD_PUSH` unwind code entry for the specified register using the current offset in the epilogue. + +## Syntax + +> .POPREG *register* + +## Parameters + +*register*\ +The register to pop. Must be a general-purpose 64-bit register. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 by using the `/unwindv3` option in ml64.exe. + +`.POPREG` is only valid in Unwind Version 3. It's the epilogue counterpart to [.PUSHREG](dot-pushreg.md). + +`.POPREG` is only allowed within an epilogue region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. In Unwind Version 3, `.POPREG` must appear **before** the `pop` instruction that implements the register restore. To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. + +*register* may be one of:\ +`RAX, RCX, RDX, RBX, RDI, RSI, RBP, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31` + +In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. The assembler doesn't emit epilogue unwind codes without a `.BEGINEPILOG`/`.ENDEPILOG` pair. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .pushreg rbx + push rbx + .pushreg rsi + push rsi +.endprolog + ; rest of function ... + .beginepilog + .popreg rsi + pop rsi + .popreg rbx + pop rbx + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.PUSHREG](dot-pushreg.md)\ +[.POP2REG](dot-pop2reg.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-push2reg.md b/docs/assembler/masm/dot-push2reg.md new file mode 100644 index 00000000000..d43e1113271 --- /dev/null +++ b/docs/assembler/masm/dot-push2reg.md @@ -0,0 +1,65 @@ +--- +description: "Learn more about: .PUSH2REG" +title: ".PUSH2REG" +ms.date: 05/04/2026 +f1_keywords: [".PUSH2REG"] +helpviewer_keywords: [".PUSH2REG directive"] +ai-usage: ai-assisted +--- +# .PUSH2REG + +Generates a two-register push unwind code entry for the specified register pair using the current offset in the prologue. + +## Syntax + +> `.PUSH2REG` *register1*, *register2* + +## Parameters + +*register1*\ +The first register to push. Must be a general-purpose 64-bit register. + +*register2*\ +The second register to push. Must be a general-purpose 64-bit register. + +*register1* and *register2* may each be one of:\ +`RAX, RCX, RDX, RBX, RDI, RSI, RBP, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31.` + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 by using `ml64.exe /unwindv3`. + +- Use `.PUSH2REG` to specify how a frame function unwinds. You can only use this directive within the prologue, which extends from the [PROC](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. In Unwind Version 3, `.PUSH2REG` must appear **before** the instruction that actually implements the action to be unwound. To ensure agreement, it's a good practice to wrap both the unwind directives and the code they're meant to unwind in a macro. +- If *register1* and *register2* are consecutive and in increasing order, MASM emits a `WOD_PUSH_CONSECUTIVE_2` unwind code. Otherwise, MASM emits a `WOD_PUSH2` unwind code. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .push2reg r10, r11 + push2 r10, r11 + .push2reg rbx, rsi + push2 rbx, rsi +.endprolog + ; rest of function ... + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.POP2REG](dot-pop2reg.md)\ +[.PUSHREG](dot-pushreg.md)\ +[.ENDPROLOG](dot-endprolog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-pushframe.md b/docs/assembler/masm/dot-pushframe.md index 07dc3972dfc..da3d77c596f 100644 --- a/docs/assembler/masm/dot-pushframe.md +++ b/docs/assembler/masm/dot-pushframe.md @@ -4,23 +4,58 @@ description: "Describes the .PUSHFRAME MASM directive, used to specify how to un ms.date: "12/06/2019" f1_keywords: [".PUSHFRAME"] helpviewer_keywords: [".PUSHFRAME directive"] -ms.assetid: 17b123d0-4c6d-4fd2-85eb-798e8ad0a73c +ai-usage: ai-assisted --- # .PUSHFRAME -Generates a `UWOP_PUSH_MACHFRAME` unwind code entry. If the optional **CODE** keyword is specified, the unwind code entry is given a modifier of 1. Otherwise the modifier is 0. +Generates a `UWOP_PUSH_MACHFRAME` unwind code entry. If you specify the optional **CODE** keyword, the unwind code entry gets a modifier of 1. Otherwise, the modifier is 0. ## Syntax -> **.PUSHFRAME** ⟦**CODE**⟧;; +> `.PUSHFRAME` ⟦**CODE**⟧ ;Prior to Unwind Version 3 +> `.PUSHFRAME` ⟦**CODE**⟧ | [0-255] ;Unwind Version 3 specific ## Remarks -.PUSHFRAME allows ml64.exe users to specify how a frame function unwinds. It's only allowed within the prologue, which extends from the [PROC](proc.md) FRAME declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives don't generate code; they only generate `.xdata` and `.pdata`. **.PUSHFRAME** should be preceded by instructions that actually implement the actions to be unwound. It's a good practice to wrap both the unwind directives and the code they're meant to unwind in a macro to ensure agreement. +Use `.PUSHFRAME` with `ml64.exe` to specify how a frame function unwinds. You can only use it within the prologue, which extends from the [PROC](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- Precede `.PUSHFRAME` with the instructions that implement the actions to be unwound. +- To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. -For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. Enable it by using `ml64.exe /unwindv3`. + +In Unwind Version 3, `.PUSHFRAME` emits a `WOD_PUSH_CANONICAL_FRAME` unwind code entry.\ +When you specify the optional **CODE** keyword, the unwind code entry modifier value is 1.\ +If you specify an optional *value*, the directive uses it directly.\ +If you don't pass an argument, the value is 0. The *value* must be in the range 0–255. + +> **Note:** In Unwind Version 1 the directives come after the instruction. In Unwind Version 3, the directives come before the instruction. +> `.PUSHFRAME` must appear **before** the instruction it describes. This behavior is the opposite of Version 1, where the directive follows the instruction. + +### Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .pushframe CODE +.endprolog + ; interrupt handler body ... + iretq +Example1 ENDP +_text ENDS +END +``` + +The epilogue counterpart is [.POPFRAME](dot-popframe.md). ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ [Directives reference](directives-reference.md)\ -[MASM BNF Grammar](masm-bnf-grammar.md) +[.POPFRAME](dot-popframe.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md)\ +[MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md) diff --git a/docs/assembler/masm/dot-pushreg.md b/docs/assembler/masm/dot-pushreg.md index a433f688d6e..d6a48cb5227 100644 --- a/docs/assembler/masm/dot-pushreg.md +++ b/docs/assembler/masm/dot-pushreg.md @@ -1,10 +1,10 @@ --- description: "Learn more about: .PUSHREG" title: ".PUSHREG" -ms.date: "12/16/2019" +ms.date: 05/04/2026 f1_keywords: [".PUSHREG"] helpviewer_keywords: [".PUSHREG directive"] -ms.assetid: e0c83758-dfed-40ea-afe6-cb833c8d2d30 +ai-usage: ai-assisted --- # .PUSHREG @@ -14,23 +14,20 @@ Generates a `UWOP_PUSH_NONVOL` unwind code entry for the specified register numb > .PUSHREG *register* -## Remarks - -**.PUSHREG** allows ml64.exe users to specify how a frame function unwinds, and is only allowed within the prologue, which extends from the [PROC](proc.md) **FRAME** declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives do not generate code; they only generate `.xdata` and `.pdata`. **.PUSHREG** should be preceded by instructions that actually implement the actions to be unwound. It is a good practice to wrap both the unwind directives and the code they are meant to unwind in a macro to ensure agreement. - *register* may be one of:\ -RAX | RCX | RDX | RBX | RDI | RSI | RBP | R8 | R9 | R10 | R11 | R12 | R13 | R14 | R15. - -For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +`RAX, RCX, RDX, RBX, RDI, RSI, RBP, R8, R9, R10, R11, R12, R13, R14, R15` -## Sample +Unwind Version 3 extends register support to include R16–R31. *register* may be one of:\ +`RAX, RCX, RDX, RBX, RDI, RSI, RBP, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31` -### Description +## Remarks -The following sample shows how to push non-volatile registers. +Use `.PUSHREG` with `ml64.exe` to specify how a frame function unwinds. You can only use `.PUSHREG` within the prologue, which extends from the [PROC](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. Precede `.PUSHREG` with the instructions that actually implement the actions to be unwound. To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. ### Code +The following sample shows how to push nonvolatile registers. + ```asm ; ml64 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE _text SEGMENT @@ -51,7 +48,42 @@ _text ENDS END ``` +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. Enable it by using `ml64.exe /unwindv3`. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. +> In Unwind Version 3, `.PUSHREG` generates a `WOD_PUSH` unwind code entry and must appear **before** the `push reg` instruction it describes. This requirement is the opposite of Version 1, where the directive follows the instruction. + +### Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .pushreg r10 + push r10 + .pushreg r15 + push r15 + .pushreg rbx + push rbx + .pushreg rsi + push rsi +.endprolog + ; rest of function ... + ret +Example1 ENDP +_text ENDS +END +``` + +The epilogue counterpart is [.POPREG](dot-popreg.md). + ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ [Directives reference](directives-reference.md)\ -[MASM BNF Grammar](masm-bnf-grammar.md) +[MASM BNF Grammar](masm-bnf-grammar.md)\ +[MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md) \ No newline at end of file diff --git a/docs/assembler/masm/dot-restorereg.md b/docs/assembler/masm/dot-restorereg.md new file mode 100644 index 00000000000..94836c8da74 --- /dev/null +++ b/docs/assembler/masm/dot-restorereg.md @@ -0,0 +1,77 @@ +--- +description: "Learn more about: .RESTOREREG" +title: ".RESTOREREG" +ms.date: 05/04/2026 +f1_keywords: [".RESTOREREG"] +helpviewer_keywords: [".RESTOREREG directive"] +ai-usage: ai-assisted +--- +# .RESTOREREG + +Generates either a `WOD_SAVE_NONVOL` or a `WOD_SAVE_NONVOL_FAR` unwind code entry for the specified register and offset, using the current epilogue offset. + +## Syntax + +> `.RESTOREREG` *reg*, *offset* + +## Parameters + +*reg*\ +The nonvolatile register to restore. + +*offset*\ +The stack offset from which the register is restored. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 by using `ml64.exe /unwindv3`. + +`.RESTOREREG` is only valid in Unwind Version 3. It's the epilogue counterpart to [.SAVEREG](dot-savereg.md). + +Microsoft Assembler (MASM) chooses the most efficient encoding for a given offset. + +- `.RESTOREREG` is only allowed within an epilogue region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- In Unwind Version 3, `.RESTOREREG` must appear **before** the instruction that loads the register from the stack. +- To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. +- In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. No epilogue unwind codes are emitted without a `.BEGINEPILOG`/`.ENDEPILOG` pair. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 020h + sub rsp, 020h + .savereg rbx, 0 + mov [rsp], rbx + .savereg rsi, 8 + mov [rsp+8], rsi +.endprolog + ; rest of function ... + .beginepilog + .restorereg rsi, 8 + mov rsi, [rsp+8] + .restorereg rbx, 0 + mov rbx, [rsp] + .freestack 020h + add rsp, 020h + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.SAVEREG](dot-savereg.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-restorexmm128.md b/docs/assembler/masm/dot-restorexmm128.md new file mode 100644 index 00000000000..03d1bc27750 --- /dev/null +++ b/docs/assembler/masm/dot-restorexmm128.md @@ -0,0 +1,77 @@ +--- +description: "Learn more about: .RESTOREXMM128" +title: ".RESTOREXMM128" +ms.date: 05/06/2026 +f1_keywords: [".RESTOREXMM128"] +helpviewer_keywords: [".RESTOREXMM128 directive"] +ai-usage: ai-assisted +--- +# .RESTOREXMM128 + +Generates either a `WOD_SAVE_XMM128` or a `WOD_SAVE_XMM128_FAR` Unwind Version 3 unwind code entry for the specified XMM register and offset using the current epilogue offset. + +## Syntax + +> `.RESTOREXMM128` *xmmreg*, *offset* + +## Parameters + +*xmmreg*\ +The XMM register to restore. + +*offset*\ +The stack offset from which the register is restored. Must be a multiple of 16. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 with `ml64.exe /unwindv3`. + +`.RESTOREXMM128` is only valid in Unwind Version 3. It's the epilogue counterpart to [.SAVEXMM128](dot-savexmm128.md). + +Microsoft Assembler (MASM) chooses the most efficient encoding for a given offset. + +- `.RESTOREXMM128` is only allowed within an epilogue region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- In Unwind Version 3, `.RESTOREXMM128` must appear **before** the instruction that loads the XMM register from the stack. +- To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. +- In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. No epilogue unwind codes are emitted without a `.BEGINEPILOG`/`.ENDEPILOG` pair. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 030h + sub rsp, 030h + .savexmm128 xmm6, 0 + movdqa [rsp], xmm6 + .savexmm128 xmm7, 010h + movdqa [rsp+010h], xmm7 +.endprolog + ; rest of function ... + .beginepilog + .restorexmm128 xmm7, 010h + movdqa xmm7, [rsp+010h] + .restorexmm128 xmm6, 0 + movdqa xmm6, [rsp] + .freestack 030h + add rsp, 030h + .endepilog + ret +Example1 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.SAVEXMM128](dot-savexmm128.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-savereg.md b/docs/assembler/masm/dot-savereg.md index a786f88777f..654d19cfe57 100644 --- a/docs/assembler/masm/dot-savereg.md +++ b/docs/assembler/masm/dot-savereg.md @@ -1,26 +1,70 @@ --- description: "Learn more about: .SAVEREG" title: ".SAVEREG" -ms.date: "12/16/2019" +ms.date: 05/06/2026 f1_keywords: [".SAVEREG"] helpviewer_keywords: [".SAVEREG directive"] -ms.assetid: 1dbc2ef6-a197-40e7-9e55-fddcae8cef29 +ai-usage: ai-assisted --- # .SAVEREG -Generates either a `UWOP_SAVE_NONVOL` or a `UWOP_SAVE_NONVOL_FAR` unwind code entry for the specified register (*reg*) and offset (*offset*) using the current prologue offset. MASM will choose the most efficient encoding. +Generates either a `UWOP_SAVE_NONVOL` or a `UWOP_SAVE_NONVOL_FAR` unwind code entry for the specified register (*reg*) and offset (*offset*) using the current prologue offset. Microsoft Assembler (MASM) chooses the most efficient encoding. ## Syntax -> **.SAVEREG** *reg*__,__ *offset* +> `.SAVEREG` *reg*__,__ *offset* ## Remarks -**.SAVEREG** allows ml64.exe users to specify how a frame function unwinds and is only allowed within the prologue, which extends from the [PROC](proc.md) FRAME declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives do not generate code; they only generate `.xdata` and `.pdata`. **.SAVEREG** should be preceded by instructions that actually implement the actions to be unwound. It is a good practice to wrap both the unwind directives and the code they are meant to unwind in a macro to ensure agreement. +Use `.SAVEREG` with `ml64.exe` to specify how a frame function unwinds. You can only use it within the prologue, which extends from the [`PROC`](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. +- These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. +- Precede `.SAVEREG` with instructions that actually implement the actions to be unwound. +- To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. -For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. Enable it by using `ml64.exe /unwindv3`. + +In Unwind Version 3, `.SAVEREG` emits either a `WOD_SAVE_NONVOL` or a `WOD_SAVE_NONVOL_FAR` unwind code entry. MASM selects the most efficient encoding based on the size of *offset*: + +| Unwind code | Condition | +|---|---| +| `WOD_SAVE_NONVOL` | *offset* can be encoded as a scaled 16-bit value | +| `WOD_SAVE_NONVOL_FAR` | *offset* requires a full 32-bit value | + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. +> `.SAVEREG` must appear **before** the instruction it describes. This requirement is the opposite of Version 1, where the directive follows the instruction. + +### Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 020h + sub rsp, 020h + .savereg rbx, 0 + mov [rsp], rbx + .savereg rsi, 8 + mov [rsp+8], rsi +.endprolog + ; rest of function ... + mov rsi, [rsp+8] + mov rbx, [rsp] + add rsp, 020h + ret +Example1 ENDP +_text ENDS +END +``` + +The epilogue counterpart is [.RESTOREREG](dot-restorereg.md). ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ [Directives reference](directives-reference.md)\ +[MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md)\ [MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-savexmm128.md b/docs/assembler/masm/dot-savexmm128.md index 6a914c5547f..ed2fae15341 100644 --- a/docs/assembler/masm/dot-savexmm128.md +++ b/docs/assembler/masm/dot-savexmm128.md @@ -1,28 +1,69 @@ --- description: "Learn more about: .SAVEXMM128" title: ".SAVEXMM128" -ms.date: "12/17/2019" +ms.date: 05/04/2026 f1_keywords: [".SAVEXMM128"] helpviewer_keywords: [".SAVEXMM128 directive"] -ms.assetid: 551eb472-b8d0-47b1-8d82-995d1f485723 +ai-usage: ai-assisted --- # .SAVEXMM128 -Generates either a `UWOP_SAVE_XMM128` or a `UWOP_SAVE_XMM128_FAR` unwind code entry for the specified XMM register and offset using the current prologue offset. MASM will choose the most efficient encoding. +Generates either a `UWOP_SAVE_XMM128` or a `UWOP_SAVE_XMM128_FAR` unwind code entry for the specified XMM register and offset using the current prologue offset. Microsoft Assembler (MASM) chooses the most efficient encoding. ## Syntax -> **.SAVEXMM128** *xmmreg* , *offset* +> `.SAVEXMM128` *xmmreg* , *offset* ## Remarks -**.SAVEXMM128** allows ml64.exe users to specify how a frame function unwinds, and is only allowed within the prologue, which extends from the [PROC](proc.md) FRAME declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives do not generate code; they only generate `.xdata` and `.pdata`. .SAVEXMM128 should be preceded by instructions that actually implement the actions to be unwound. It is a good practice to wrap both the unwind directives and the code they are meant to unwind in a macro to ensure agreement. +Use `.SAVEXMM128` with `ml64.exe` to specify how a frame function unwinds. You can only use it within the prologue, which extends from the [`PROC`](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. Precede `.SAVEXMM128` by the instructions that actually implement the actions to be unwound. To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. *offset* must be a multiple of 16. -For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. Enable it by using `ml64.exe /unwindv3`. + +In Unwind Version 3, `.SAVEXMM128` emits either a `WOD_SAVE_XMM128` or a `WOD_SAVE_XMM128_FAR` unwind code entry. Microsoft Assembler (MASM) selects the most efficient encoding based on the size of *offset*: + +| Unwind code | Condition | +|---|---| +| `WOD_SAVE_XMM128` | *offset* can be encoded as a scaled 16-bit value | +| `WOD_SAVE_XMM128_FAR` | *offset* requires a full 32-bit value | + +> [!NOTE] +> In Unwind Version 1 the directives come after the instruction. In Unwind Version 3, the directives come before the instruction. +> `.SAVEXMM128` must appear **before** the instruction it describes. This requirement is the opposite of Version 1, where the directive follows the instruction. + +### Example for unwindv3 + +```asm +; ml64 /unwindv3 ex1.asm /link /entry:Example1 /SUBSYSTEM:CONSOLE +_text SEGMENT +Example1 PROC FRAME + .allocstack 030h + sub rsp, 030h + .savexmm128 xmm6, 0 + movdqa [rsp], xmm6 + .savexmm128 xmm7, 010h + movdqa [rsp+010h], xmm7 +.endprolog + ; rest of function ... + movdqa xmm7, [rsp+010h] + movdqa xmm6, [rsp] + add rsp, 030h + ret +Example1 ENDP +_text ENDS +END +``` + +The epilogue counterpart is [.RESTOREXMM128](dot-restorexmm128.md). ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ [Directives reference](directives-reference.md)\ -[MASM BNF Grammar](masm-bnf-grammar.md) +[MASM BNF Grammar](masm-bnf-grammar.md)\ +[MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md) diff --git a/docs/assembler/masm/dot-setframe.md b/docs/assembler/masm/dot-setframe.md index d33281ed97a..7eeec50f330 100644 --- a/docs/assembler/masm/dot-setframe.md +++ b/docs/assembler/masm/dot-setframe.md @@ -1,10 +1,10 @@ --- description: "Learn more about: .SETFRAME" title: ".SETFRAME" -ms.date: "12/17/2019" +ms.date: 05/04/2026 f1_keywords: [".SETFRAME"] helpviewer_keywords: [".SETFRAME directive"] -ms.assetid: eaa9b5ed-4daa-4f1e-bdb6-100758007ab3 +ai-usage: ai-assisted --- # .SETFRAME @@ -12,13 +12,11 @@ Fills in the frame register field and offset in the unwind information using the ## Syntax -> **.SETFRAME** *reg*, *offset* +> `.SETFRAME` *reg*, *offset* ## Remarks -**.SETFRAME** allows ml64.exe users to specify how a frame function unwinds, and is only allowed within the prologue, which extends from the [PROC](proc.md) FRAME declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives do not generate code; they only generate `.xdata` and `.pdata`. **.SETFRAME** should be preceded by instructions that actually implement the actions to be unwound. It is a good practice to wrap both the unwind directives and the code they are meant to unwind in a macro to ensure agreement. - -For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md). +Use `.SETFRAME` to specify how a frame function unwinds. You can only use it within the prologue, which extends from the [`PROC`](proc.md) `FRAME` declaration to the [.ENDPROLOG](dot-endprolog.md) directive. These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code. Precede `.SETFRAME` with instructions that implement the actions to be unwound. To ensure agreement, wrap both the unwind directives and the code they're meant to unwind in a macro. ## Sample @@ -55,7 +53,51 @@ _text ENDS END ``` +## Unwind Version 3 behavior + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. Enable it by using `ml64.exe /unwindv3`. + +In Unwind Version 3, `.SETFRAME` emits a `WOD_SET_FPREG` unwind code entry for the specified register using the current prologue offset. It also fills in the frame register field and offset in the unwind information. The *offset* must be a multiple of 16 and less than or equal to 240. + +> [!NOTE] +> In Unwind Version 1 the directives come after the instruction. In Unwind Version 3, the directives come before the instruction. +> `.SETFRAME` must appear **before** the instruction it describes. This requirement is the opposite of Version 1, where the directive follows the instruction. + +### Example for unwindv3 + +```asm +; ml64 /unwindv3 frmex2.asm /link /entry:frmex2 /SUBSYSTEM:CONSOLE +_text SEGMENT +frmex2 PROC FRAME + .pushreg rbp + push rbp + .allocstack 010h + sub rsp, 010h + .setframe rbp, 0 + mov rbp, rsp +.endprolog + ; modify the stack pointer outside of the prologue (similar to alloca) + sub rsp, 060h + + ; we can unwind from the following AV because of the frame pointer + mov rax, 0 + mov rax, [rax] ; AV! + + add rsp, 060h + add rsp, 010h + pop rbp + ret +frmex2 ENDP +_text ENDS +END +``` + +The epilogue counterpart is [.UNSETFRAME](dot-unsetframe.md). + ## See also +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md)\ [Directives reference](directives-reference.md)\ [MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/dot-unsetframe.md b/docs/assembler/masm/dot-unsetframe.md new file mode 100644 index 00000000000..10b55371053 --- /dev/null +++ b/docs/assembler/masm/dot-unsetframe.md @@ -0,0 +1,82 @@ +--- +description: "Learn more about: .UNSETFRAME" +title: ".UNSETFRAME" +ms.date: 05/04/2026 +f1_keywords: [".UNSETFRAME"] +helpviewer_keywords: [".UNSETFRAME directive"] +ai-usage: ai-assisted +--- +# .UNSETFRAME + +Generates a `WOD_SET_FPREG` unwind code entry for the specified register and offset using the current offset in the epilogue. + +## Syntax + +> `.UNSETFRAME` *reg*, *offset* + +## Parameters + +*reg*\ +The frame pointer register to unset. + +*offset*\ +The offset into the stack frame where the frame pointer was established. + +## Remarks + +> [!IMPORTANT] +> This directive is experimental and is subject to change. Enable Unwind Version 3 with `ml64.exe /unwindv3`. + +`.UNSETFRAME` is only valid in Unwind Version 3. It's the epilogue counterpart to [.SETFRAME](dot-setframe.md). + +`.UNSETFRAME` is only allowed within an epilogue region, between [.BEGINEPILOG](dot-beginepilog.md) and [.ENDEPILOG](dot-endepilog.md). These directives generate unwind metadata (`.xdata` and `.pdata` sections) but don't produce executable code.\ +In Unwind Version 3, `.UNSETFRAME` must appear **before** the instruction that restores the stack pointer from the frame pointer register.\ +It's a good practice to wrap both the unwind directives and the code they're meant to unwind in a macro to ensure agreement. + +In Unwind Version 3, epilogue directives are mandatory for epilogue unwind code generation. No epilogue unwind codes are emitted without a `.BEGINEPILOG`/`.ENDEPILOG` pair. + +> [!NOTE] +> In Unwind Version 1, the directive appears after the corresponding instruction. In Unwind Version 3, the directive appears **before** the instruction. + +## Example for unwindv3 + +```asm +; ml64 /unwindv3 frmex2.asm /link /entry:frmex2 /SUBSYSTEM:CONSOLE +_text SEGMENT +frmex2 PROC FRAME + .pushreg rbp + push rbp + .allocstack 010h + sub rsp, 010h + .setframe rbp, 0 + mov rbp, rsp +.endprolog + ; modify the stack pointer outside of the prologue (similar to alloca) + sub rsp, 060h + + ; we can unwind from the following AV because of the frame pointer + mov rax, 0 + mov rax, [rax] ; AV! + + add rsp, 060h + .beginepilog + .unsetframe rbp, 0 + mov rsp, rbp + .freestack 010h + add rsp, 010h + .popreg rbp + pop rbp + .endepilog + ret +frmex2 ENDP +_text ENDS +END +``` + +## See also + +[x64 Unwind Version 3 (experimental)](directives-reference.md#x64-unwind-version-3-experimental)\ +[Directives Reference](directives-reference.md)\ +[.SETFRAME](dot-setframe.md)\ +[.BEGINEPILOG](dot-beginepilog.md)\ +[MASM BNF Grammar](masm-bnf-grammar.md) diff --git a/docs/assembler/masm/masm-for-x64-ml64-exe.md b/docs/assembler/masm/masm-for-x64-ml64-exe.md index 840b0020837..6abb9b44993 100644 --- a/docs/assembler/masm/masm-for-x64-ml64-exe.md +++ b/docs/assembler/masm/masm-for-x64-ml64-exe.md @@ -1,8 +1,9 @@ --- description: "Learn more about: Microsoft Macro Assembler (MASM) for x64 (ml64.exe)" title: "MASM for x64 (ml64.exe)" -ms.date: 09/21/2021 +ms.date: 05/07/2026 helpviewer_keywords: ["ml64", "ml64.exe", "masm for x64"] +ai-usage: ai-assisted --- # MASM for x64 (ml64.exe) @@ -21,34 +22,54 @@ The Visual Studio project system supports assembler-language files built by usin ### To add an assembler-language file to an existing Visual Studio C++ project 1. Select the project in **Solution Explorer**. On the menu bar, choose **Project**, **Build Customizations**. - 1. In the **Visual C++ Build Customization Files** dialog box, check the checkbox next to **masm(.targets,.props)**. Choose **OK** to save your selection and close the dialog box. - 1. On the menu bar, choose **Project**, **Add New Item**. - 1. In the **Add New Item** dialog box, select **C++ file (.cpp)** in the center pane. In the **Name** edit control, enter a new file name that has a *`.asm`* extension instead of *`.cpp`*. Choose **Add** to add the file to your project and close the dialog box. Create your assembler-language code in the *`.asm`* file you added. When you build your solution, the MASM assembler is invoked to assemble the *`.asm`* file into an object file that is then linked into your project. To make symbol access easier, declare your assembler functions as `extern "C"` in your C++ source code, rather than using the C++ name decoration conventions in your assembler-language source files. -## ml64-Specific Directives +## ml64-specific directives You can use the following ml64-specific directives in your assembler-language source code that targets x64: - [`.ALLOCSTACK`](dot-allocstack.md) - - [`.ENDPROLOG`](dot-endprolog.md) - - [`.PUSHFRAME`](dot-pushframe.md) - - [`.PUSHREG`](dot-pushreg.md) - - [`.SAVEREG`](dot-savereg.md) - - [`.SAVEXMM128`](dot-savexmm128.md) - - [`.SETFRAME`](dot-setframe.md) -The [`PROC`](proc.md) directive has also been updated for use with ml64.exe. +The [`PROC`](proc.md) directive is also updated for use with ml64.exe. + +## Unwind Version 3 directives (experimental) + +> [!IMPORTANT] +> Unwind Version 3 support is experimental and is subject to change. + +Unwind Version 3 is an updated unwind code scheme for x64 that generates richer stack unwind metadata. It introduces new epilogue directives, extends register support, and changes the directive ordering model. + +### Enable Unwind Version 3 + +Assemble with the `/unwindv3` option: `ml64 /unwindv3 filename.asm /link /entry:FunctionName` + +### Key differences from Version 1 + +| Feature | Version 1 | Version 3 | +|---|---|---| +| Directive ordering | Directive follows instruction | Directive precedes instruction | +| Unwind codes | `UWOP_*` | `WOD_*` | +| `.ALLOCSTACK` size variants | 2 (`UWOP_ALLOC_SMALL`, `UWOP_ALLOC_LARGE`) | 3 (adds `WOD_ALLOC_HUGE` for > 32 KB) | +| `.PUSHREG` register range | R0–R15 | R0–R31 | +| Epilogue recording | Optional | Mandatory (`.BEGINEPILOG`/`.ENDEPILOG` required) | +| Register-pair push/pop | Not supported | `.PUSH2REG`/`.POP2REG` directives | + +Epilogue recording is mandatory in Version 3: `.BEGINEPILOG` and `.ENDEPILOG` must surround the epilogue instructions. Without them, no epilogue unwind codes are emitted. + +> [!NOTE] +> In Unwind Version 1 the directives come after the instruction. In Unwind Version 3, the directives come before the instruction. + +For a complete list of Version 3 directives, see [x64 Unwind Version 3 directives](directives-reference.md) and [@UnwindVersion](at-unwindversion.md). ## 32-Bit Address Mode (Address Size Override) diff --git a/docs/assembler/masm/ml-and-ml64-command-line-reference.md b/docs/assembler/masm/ml-and-ml64-command-line-reference.md index e4ea469e36f..ab91d77ce37 100644 --- a/docs/assembler/masm/ml-and-ml64-command-line-reference.md +++ b/docs/assembler/masm/ml-and-ml64-command-line-reference.md @@ -1,9 +1,10 @@ --- title: "ML and ML64 command-line reference" description: "Reference guide to the Microsoft MASM ML and ML64 assembler command-line options." -ms.date: 7/3/2023 -f1_keywords: ["ML"] -helpviewer_keywords: ["/W* MASM compiler option", "/c MASM compiler option", "/EP MASM compiler option", "/Fe MASM compiler option", "/Zp MASM compiler option", "/AT MASM compiler option", "/Zm MASM compiler option", "/Sf MASM compiler option", "/Sp MASM compiler option", "/w MASM compiler option", "/Fl MASM compiler option", "/coff MASM compiler option", "/St MASM compiler option", "/Cx MASM compiler option", "/Sl MASM compiler option", "/Cu MASM compiler option", "MASM (Microsoft Macro Assembler), ML command-line reference", "/FPi MASM compiler option", "/Zf MASM compiler option", "ML environment variable", "/Fr MASM compiler option", "/help MASM compiler option", "/Sa MASM compiler option", "/Zd MASM compiler option", "/I MASM compiler option", "/? MASM compiler option", "/Bl MASM compiler option", "/Fm MASM compiler option", "/Fo MASM compiler option", "command-line reference [ML]", "/Sn MASM compiler option", "/Gd MASM compiler option", "/D* MASM compiler option", "environment variables, ML", "/Gc MASM compiler option", "/F* MASM compiler option", "/Sc MASM compiler option", "/H MASM compiler option", "/Zs MASM compiler option", "/omf MASM compiler option", "/quiet MASM compiler option", "/Sg MASM compiler option", "/Cp MASM compiler option", "/Zi MASM compiler option", "/nologo MASM compiler option", "/Sx MASM compiler option", "/WX MASM compiler option", "/Ss MASM compiler option", "command line, reference [ML]", "/Ta MASM compiler option"] +ms.date: 05/25/2026 +ai-usage: ai-assisted +f1_keywords: ["ML", "/unwindv3"] +helpviewer_keywords: ["/W* MASM compiler option", "/c MASM compiler option", "/EP MASM compiler option", "/Fe MASM compiler option", "/Zp MASM compiler option", "/AT MASM compiler option", "/Zm MASM compiler option", "/Sf MASM compiler option", "/Sp MASM compiler option", "/w MASM compiler option", "/Fl MASM compiler option", "/coff MASM compiler option", "/St MASM compiler option", "/Cx MASM compiler option", "/Sl MASM compiler option", "/Cu MASM compiler option", "MASM (Microsoft Macro Assembler), ML command-line reference", "/FPi MASM compiler option", "/Zf MASM compiler option", "ML environment variable", "/Fr MASM compiler option", "/help MASM compiler option", "/Sa MASM compiler option", "/Zd MASM compiler option", "/I MASM compiler option", "/? MASM compiler option", "/Bl MASM compiler option", "/Fm MASM compiler option", "/Fo MASM compiler option", "command-line reference [ML]", "/Sn MASM compiler option", "/Gd MASM compiler option", "/D* MASM compiler option", "environment variables, ML", "/Gc MASM compiler option", "/F* MASM compiler option", "/Sc MASM compiler option", "/H MASM compiler option", "/Zs MASM compiler option", "/omf MASM compiler option", "/quiet MASM compiler option", "/Sg MASM compiler option", "/Cp MASM compiler option", "/Zi MASM compiler option", "/nologo MASM compiler option", "/Sx MASM compiler option", "/WX MASM compiler option", "/Ss MASM compiler option", "command line, reference [ML]", "/Ta MASM compiler option", "/unwindv3 MASM compiler option"] --- # ML and ML64 command-line reference @@ -61,6 +62,7 @@ The options listed in the following table: | **`/St`** *`text`* | Specifies title for source listing. Same as [`TITLE`](title.md) text. | | **`/Sx`** | Turns on false conditionals in listing. | | **`/Ta`** *`filename`* | Assembles source file whose name doesn't end with the *`.asm`* extension. | +| **`/unwindv3`** | Enables experimental Unwind Version 3 unwind directive support. When specified, V3 unwind directives must appear *before* their associated instruction (the reverse of V1 behavior), epilogue recording via [`.BEGINEPILOG`](dot-beginepilog.md)/[`.ENDEPILOG`](dot-endepilog.md) is required, and the predefined macro [`@UnwindVersion`](at-unwindversion.md) returns `3`. For more information, see [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md).
Only available in ml64.exe. | | **`/w`** | Same as **`/W0 /WX`**. | | **`/W`** *`level`* | Sets the warning level, where *`level`* = 0, 1, 2, or 3. | | **`/WX`** | If warnings are generated, returns an error code. | @@ -69,12 +71,16 @@ The options listed in the following table: | **`/Zf`** | Makes all symbols public. | | **`/ZH:MD5`** | Use MD5 for checksum in debug info. | | **`/ZH:SHA_256`** | Use SHA256 for checksum in debug info (default in Visual Studio 2022 version 17.0 and later). | +| **`/ZH:SHA384`** | Use SHA384 for checksum in debug info.18.6.0 | +| **`/ZH:SHA512`** | Use SHA512 for checksum in debug info.18.6.0 | | **`/Zi`** | Generates CodeView information in object file. | | **`/Zm`** | Enables **`M510`** option for maximum compatibility with MASM 5.1.
Not available in ml64.exe. | | **`/Zp`**⟦*`alignment`*⟧ | Packs structures on the specified byte boundary. The *`alignment`* can be 1, 2, 4, 8, or 16. | | **`/Zs`** | Performs a syntax check only. | | **`/?`** | Displays a summary of ML command-line syntax and options. | +18.6.0 This option is available starting in Visual Studio 2026 version 18.6.0 and MSVC version 14.51. + *`filename`*\ The name of the file. diff --git a/docs/assembler/masm/proc.md b/docs/assembler/masm/proc.md index 9eb65fc3770..222b437a4a9 100644 --- a/docs/assembler/masm/proc.md +++ b/docs/assembler/masm/proc.md @@ -12,8 +12,8 @@ Marks start and end of a procedure block called *label*. The statements in the b ## Syntax -> *label* **PROC** ⟦*distance*⟧ ⟦*language-type*⟧ ⟦ **PUBLIC** | **PRIVATE** | **EXPORT** ⟧ ⟦__\<__*prologuearg*__>__⟧ ⟦**USES** *reglist*⟧ ⟦__,__ *parameter* ⟦__:__*tag*⟧ ...⟧\ -> ⟦**FRAME** ⟦__:__*ehandler-address*⟧ ⟧\ +> *label* `PROC` ⟦*distance*⟧ ⟦*language-type*⟧ ⟦ `PUBLIC` | `PRIVATE` | `EXPORT` ⟧ ⟦__\<__*prologuearg*__>__⟧ ⟦`USES` *reglist*⟧ ⟦__,__ *parameter* ⟦__:__*tag*⟧ ...⟧\ +> ⟦`FRAME` ⟦__:__*ehandler-address*⟧ ⟧\ > *statements*\ > *label* **ENDP** @@ -21,9 +21,9 @@ Marks start and end of a procedure block called *label*. The statements in the b The ⟦*distance*⟧ and ⟦*language-type*⟧ arguments are valid only in 32-bit MASM. -⟦**FRAME** ⟦__:__*ehandler-address*⟧ ⟧ is only valid with ml64.exe, and causes MASM to generate a function table entry in .pdata and unwind information in .xdata for a function's structured exception handling unwind behavior. +⟦`FRAME` ⟦__:__*ehandler-address*⟧ ⟧ is only valid with ml64.exe, and causes MASM to generate a function table entry in .pdata and unwind information in .xdata for a function's structured exception handling unwind behavior. -When the **FRAME** attribute is used, it must be followed by an [.ENDPROLOG](dot-endprolog.md) directive. +When the `FRAME` attribute is used, it must be followed by an [.ENDPROLOG](dot-endprolog.md) directive. See [MASM for x64 (ml64.exe)](masm-for-x64-ml64-exe.md) for more information on using ml64.exe. @@ -49,7 +49,7 @@ _text ENDS END ``` -The above code will emit the following function table and unwind information: +The above code emits the following function table and unwind information: ```Output FileHeader->Machine 34404 diff --git a/docs/assembler/masm/symbols-reference.md b/docs/assembler/masm/symbols-reference.md index c7fd4af9f81..a6c296fc5c1 100644 --- a/docs/assembler/masm/symbols-reference.md +++ b/docs/assembler/masm/symbols-reference.md @@ -1,9 +1,9 @@ --- description: "Learn more about: Symbols reference" title: "Symbols reference" -ms.date: 07/15/2020 +ms.date: 05/04/2026 helpviewer_keywords: ["MASM (Microsoft Macro Assembler), symbols reference"] -ms.assetid: 96ed59cc-dafa-4299-bb2e-9c7c3f496491 +ai-usage: ai-assisted --- # Symbols reference @@ -30,6 +30,9 @@ ms.assetid: 96ed59cc-dafa-4299-bb2e-9c7c3f496491 :::column span=""::: [`@Interface`](at-interface.md) :::column-end::: + :::column span=""::: + [`@UnwindVersion`](at-unwindversion.md) + :::column-end::: :::column span=""::: [`@Version`](at-version.md) :::column-end::: diff --git a/docs/assembler/toc.yml b/docs/assembler/toc.yml index 8f8b923a9c3..1e90a1e19d3 100644 --- a/docs/assembler/toc.yml +++ b/docs/assembler/toc.yml @@ -117,6 +117,8 @@ items: href: ../assembler/masm/dot-alpha.md - name: ASSUME href: ../assembler/masm/assume.md + - name: .BEGINEPILOG + href: ../assembler/masm/dot-beginepilog.md - name: .BREAK href: ../assembler/masm/dot-break.md - name: BYTE @@ -171,6 +173,8 @@ items: href: ../assembler/masm/end-masm.md - name: .ENDIF href: ../assembler/masm/dot-endif.md + - name: .ENDEPILOG + href: ../assembler/masm/dot-endepilog.md - name: ENDM href: ../assembler/masm/endm.md - name: ENDP @@ -225,6 +229,8 @@ items: href: ../assembler/masm/forc.md - name: .FPO href: ../assembler/masm/dot-fpo.md + - name: .FREESTACK + href: ../assembler/masm/dot-freestack.md - name: FWORD href: ../assembler/masm/fword.md - name: GOTO @@ -315,8 +321,14 @@ items: href: ../assembler/masm/oword.md - name: PAGE href: ../assembler/masm/page.md + - name: .POP2REG + href: ../assembler/masm/dot-pop2reg.md - name: POPCONTEXT href: ../assembler/masm/popcontext.md + - name: .POPREG + href: ../assembler/masm/dot-popreg.md + - name: .POPFRAME + href: ../assembler/masm/dot-popframe.md - name: PROC href: ../assembler/masm/proc.md - name: PROTO @@ -325,6 +337,8 @@ items: href: ../assembler/masm/public-masm.md - name: PURGE href: ../assembler/masm/purge.md + - name: .PUSH2REG + href: ../assembler/masm/dot-push2reg.md - name: PUSHCONTEXT href: ../assembler/masm/pushcontext.md - name: .PUSHFRAME @@ -349,6 +363,10 @@ items: href: ../assembler/masm/repeat.md - name: REPT href: ../assembler/masm/rept.md + - name: .RESTOREREG + href: ../assembler/masm/dot-restorereg.md + - name: .RESTOREXMM128 + href: ../assembler/masm/dot-restorexmm128.md - name: .SAFESEH href: ../assembler/masm/dot-safeseh.md - name: .SALL @@ -401,6 +419,8 @@ items: href: ../assembler/masm/typedef-masm.md - name: UNION href: ../assembler/masm/union.md + - name: .UNSETFRAME + href: ../assembler/masm/dot-unsetframe.md - name: .UNTIL href: ../assembler/masm/dot-until.md - name: .UNTILCXZ @@ -479,6 +499,8 @@ items: href: ../assembler/masm/at-substr.md - name: "@Time" href: ../assembler/masm/at-time.md + - name: "@UnwindVersion" + href: ../assembler/masm/at-unwindversion.md - name: "@Version" href: ../assembler/masm/at-version.md - name: "@WordSize" diff --git a/docs/build/building-on-the-command-line.md b/docs/build/building-on-the-command-line.md index 5f7a2fdff45..ba6f8012556 100644 --- a/docs/build/building-on-the-command-line.md +++ b/docs/build/building-on-the-command-line.md @@ -1,202 +1,213 @@ --- title: "Use the Microsoft C++ Build Tools from the command line" -description: "Use the Microsoft C++ (MSVC) Build Tools from the command line outside of the Visual Studio IDE." +description: "Learn how to install and use the Microsoft C++ (MSVC) Build Tools from the command line." ms.custom: "conceptual" -ms.date: 04/07/2022 +ms.date: 06/02/2026 ms.topic: how-to helpviewer_keywords: ["command-line builds [C++]", "compiling source code [C++], command line", "builds [C++], command-line", "command line [C++], building from", "command line [C++], compilers"] +#custom intent: As a C++ developer, I want to understand the options for using the command line to compile and build my software projects. --- # Use the Microsoft C++ Build Tools from the command line -You can build C and C++ applications on the command line by using tools that are included in Visual Studio. The Microsoft C++ (MSVC) Build Tools are also downloadable as a standalone package. You don't need to install the Visual Studio IDE if you don't plan to use it. +You can build C and C++ applications on the command line by using tools that are included in Visual Studio. You can also download the Microsoft C++ (MSVC) Build Tools as a standalone package. You don't need to install the Visual Studio IDE if you don't plan to use it. > [!NOTE] -> This article is about how to set up an environment to use the individual compilers, linkers, librarian, and other basic tools. The native project build system in Visual Studio, based on MSBuild, doesn't use the environment as described in this article. For more information on how to use MSBuild from the command line, see [MSBuild on the command line - C++](msbuild-visual-cpp.md). +> This article is about how to set up an environment to use the individual compilers, linkers, libraries, and other basic tools. The native project build system in Visual Studio, based on MSBuild, doesn't use the environment as described in this article. For more information on how to use MSBuild from the command line, see [MSBuild on the command line - C++](msbuild-visual-cpp.md). ## Download and install the tools ::: moniker range=">=msvc-160" -If you've installed Visual Studio and a C++ workload, you have all the command-line tools. For information on how to install C++ and Visual Studio, see [Install C++ support in Visual Studio](vscpp-step-0-installation.md). If you only want the command-line toolset, download the [Build Tools for Visual Studio](https://visualstudio.microsoft.com/downloads/). On the downloads page, expand the **Tools for Visual Studio** section to find the Build Tools download. When you run the downloaded executable, it updates and runs the Visual Studio Installer. To install only the tools you need for C++ development, select the **Desktop development with C++** workload. You can select optional libraries and toolsets to include under **Installation details**. To build code by using the Visual Studio 2015, 2017, or 2019 toolsets, select the optional MSVC v140, v141, or v142 build tools. When you're satisfied with your selections, choose **Install**. +If you installed Visual Studio and a C++ workload, you have all the command-line tools. For information on how to install C++ and Visual Studio, see [Install C++ support in Visual Studio](vscpp-step-0-installation.md). + +If you want only the command-line toolset, download the [Build Tools for Visual Studio](https://visualstudio.microsoft.com/downloads/). On the downloads page, expand **Tools for Visual Studio** to find the Build Tools download. When you run the downloaded executable, it updates and runs the Visual Studio Installer. + +To install only the tools you need for C++ development, select the **Desktop development with C++** workload. Under **Installation details**, you can select optional libraries and toolsets. To build code by using the Visual Studio 2015, Visual Studio 2017, or Visual Studio 2019 toolsets, select the optional MSVC v140, v141, or v142 build tools. When you're satisfied with your selections, choose **Install**. ::: moniker-end ::: moniker range="<=msvc-150" -If you've installed Visual Studio and a C++ workload, you have all the command-line tools. For information on how to install C++ and Visual Studio, see [Install C++ support in Visual Studio](vscpp-step-0-installation.md). If you only want the command-line toolset, download the [Build Tools for Visual Studio 2017](https://my.visualstudio.com/Downloads?q=2017). When you run the downloaded executable, it updates and runs the Visual Studio Installer. To install only the tools you need for C++ development, select the **Desktop development with C++** workload. You can select optional libraries and toolsets to include under **Installation details**. To build code by using the Visual Studio 2015 toolset, select the optional MSVC v140 build tools. When you're satisfied with your selections, choose **Install**. +If you installed Visual Studio and a C++ workload, you have all the command-line tools. For information on how to install C++ and Visual Studio, see [Install C++ support in Visual Studio](vscpp-step-0-installation.md). + +If you want only the command-line toolset, download the [Build Tools for Visual Studio 2017](https://my.visualstudio.com/Downloads?q=2017). When you run the downloaded executable, it updates and runs the Visual Studio Installer. + +To install only the tools you need for C++ development, select the **Desktop development with C++** workload. Under **Installation details**, you can select optional libraries and toolsets. To build code by using the Visual Studio 2015 toolset, select the optional MSVC v140 build tools. When you're satisfied with your selections, choose **Install**. ::: moniker-end ## How to use the command-line tools -When you choose one of the C++ workloads in the Visual Studio Installer, by default, it installs a particular version of the MSVC Build Tools package. For Visual Studio 2022 and earlier, this is organized by a *platform toolset* (v### version format) that has all the C and C++ tools for a specific version of Visual Studio. For Visual Studio 2026 and later, this consists of the MSVC version (v##.## version format), which has all the C and C++ tools for that particular MSVC package. The MSVC version is decoupled from the Visual Studio version. The tools include the C/C++ compilers, linkers, assemblers, and other build tools, and matching libraries and header files. You can use all of these tools at the command-line. They're also used internally by the Visual Studio IDE. There are separate x86-hosted and x64-hosted compilers and tools that build code for x86, x64, ARM, and ARM64 targets. Each set of tools for a particular host and target build architecture is stored in its own directory. +When you choose one of the C++ workloads in the Visual Studio Installer, it installs a specific version of the MSVC Build Tools package by default. For Visual Studio 2022 and earlier, the package is organized by a *platform toolset* (v### version format) that includes all the C and C++ tools for a specific version of Visual Studio. Starting with Visual Studio 2026, the MSVC version is decoupled from the Visual Studio version. In other words, from Visual Studio 2026 onwards the package corresponds to the MSVC toolset version (v##.## version format), which includes all the C and C++ tools for that particular MSVC Build Tools package. -To work correctly, the tools require several specific environment variables to be set. These variables are used to add the tools to the path, and to set the locations of include files, library files, and SDKs. To make it easy to set these environment variables, the installer creates customized *command files*, or batch files, during installation. You can run one of these command files to set a specific host and target build architecture, Windows SDK version, and platform toolset. For convenience, the installer also creates shortcuts in your Start menu. The shortcuts open developer command prompt windows by using these command files for specific combinations of host and target. These shortcuts ensure all the required environment variables are set and ready to use. +The tools include the C/C++ compilers, linkers, assemblers, and other build tools. It includes matching libraries and header files. You can use all of these tools at the command line. The Visual Studio IDE uses them internally. There are separate x86-hosted and x64-hosted compilers and tools that build code for x86, x64, ARM, and ARM64 targets. Each set of tools for a particular host and target build architecture is stored in its own directory. -The required environment variables are specific to your installation and to the build architecture you choose. They also might be changed by product updates or upgrades. This variability is one reason why we recommend you use an installed command prompt shortcut or command file, instead of setting the environment variables yourself. +The tools require several environment variables to be set. These variables add the tools to the path and set the locations of include files, library files, and SDKs. To make it easy to set these environment variables, the installer creates customized *command files*, or batch files, during installation. You can run one of these command files to set a specific host and target build architecture, Windows SDK version, and platform toolset. -The toolsets, command files, and shortcuts installed depend on your computer processor and the options you selected during installation. The x86-hosted tools and cross tools that build x86 and x64 code are always installed. If you have 64-bit Windows, the x64-hosted tools and cross tools that build x86 and x64 code are also installed. If you choose the optional C++ Universal Windows Platform tools, then the x86 and x64 tools that build ARM and ARM64 code also get installed. Other workloads may install these and other tools. +For convenience, the installer also creates shortcuts in your **Start** menu. The shortcuts open developer Command Prompt windows by using these command files for specific combinations of host and target architectures. These shortcuts ensure all the required environment variables are set and ready to use. -## Path and environment variables for command-line builds +The required environment variables are specific to your installation and to the build architecture you choose. Product updates or upgrades might change the variables. This variability is one reason why we recommend you use an installed command prompt shortcut or command file, instead of setting the environment variables yourself. -The MSVC command-line tools use the `PATH`, `TMP`, `INCLUDE`, `LIB`, and `LIBPATH` environment variables, and also use other environment variables specific to your installed tools, platforms, and SDKs. Even a simple Visual Studio installation may set twenty or more environment variables. This complexity is why we strongly recommend that you use a [developer command prompt shortcut](#developer_command_prompt_shortcuts) or one of the [customized command files](#developer_command_file_locations). We don't recommend you set these variables in the Windows environment yourself. +The toolsets, command files, and shortcuts that the installer adds depend on your computer processor and the options you select during installation. The x86-hosted tools and cross tools that build x86 and x64 code are always installed. If you have 64-bit Windows, the x64-hosted tools and cross tools that build x86 and x64 code are also installed. If you choose the optional C++ Universal Windows Platform tools, the x86 and x64 tools that build ARM and ARM64 code are also installed. Other workloads can install these tools. -To see which environment variables are set by a developer command prompt shortcut, you can use the `SET` command. Open a plain command prompt window and capture the output of the `SET` command for a baseline. Open a developer command prompt window and capture the output of the `SET` command for comparison. Use a diff tool such as the one built into Visual Studio to highlight the environment variables set by the developer command prompt. For more information about the compiler and linker environment variables, see [CL environment variables](reference/cl-environment-variables.md). +## Path and environment variables for command-line builds -## Developer command prompt shortcuts +The MSVC command-line tools use the `PATH`, `TMP`, `INCLUDE`, `LIB`, and `LIBPATH` environment variables. They also use other environment variables specific to your installed tools, platforms, and SDKs. Even a simple Visual Studio installation can set twenty or more environment variables. This complexity is why we strongly recommend that you use a [developer command prompt shortcut](#developer_command_prompt_shortcuts) or one of the [customized command files](#developer_command_file_locations). We don't recommend you set these variables in the Windows environment yourself. -The command prompt shortcuts are installed in a version-specific Visual Studio folder in your Windows Start menu. Here's a list of the base command prompt shortcuts and the build architectures they support: +To see which environment variables a developer command prompt shortcut sets, use the `SET` command. Open a plain Command Prompt window and capture the output of the `SET` command for a baseline. Open a developer Command Prompt window and capture the output of the `SET` command for comparison. Use a diff tool such as the one built into Visual Studio to highlight the environment variables set by the developer command prompt. For more information about the compiler and linker environment variables, see [CL environment variables](reference/cl-environment-variables.md). -- **Developer Command Prompt** - Sets the environment to use 32-bit, x86-native tools to build 32-bit, x86-native code. -- **x86 Native Tools Command Prompt** - Sets the environment to use 32-bit, x86-native tools to build 32-bit, x86-native code. -- **x64 Native Tools Command Prompt** - Sets the environment to use 64-bit, x64-native tools to build 64-bit, x64-native code. -- **x86_x64 Cross Tools Command Prompt** - Sets the environment to use 32-bit, x86-native tools to build 64-bit, x64-native code. -- **x64_x86 Cross Tools Command Prompt** - Sets the environment to use 64-bit, x64-native tools to build 32-bit, x86-native code. +## Developer command prompt shortcuts -::: moniker range=">= msvc-160" +The command prompt shortcuts are installed in a version-specific Visual Studio folder in your Windows **Start** menu. Here's a list of the base command prompt shortcuts and the build architectures they support: -The Start menu folder and shortcut names vary depending on the installed version of Visual Studio. If you set one, they also depend on the installation **Nickname**. For example, suppose you installed Visual Studio 2022, and you gave it a nickname of *Latest*. The developer command prompt shortcut is named **Developer Command Prompt for VS 2022 (Latest)**, in a folder named **Visual Studio 2022**. +- **Developer Command Prompt**. Sets the environment to use 32-bit x86 tools to build 32-bit x86 code. +- **x86 Native Tools Command Prompt**. Sets the environment to use 32-bit x86 tools to build 32-bit x86 code. +- **x64 Native Tools Command Prompt**. Sets the environment to use 64-bit x64 tools to build 64-bit x64 code. +- **x86_x64 Cross Tools Command Prompt**. Sets the environment to use 32-bit x86 tools to build 64-bit x64 code. +- **x64_x86 Cross Tools Command Prompt**. Sets the environment to use 64-bit x64 tools to build 32-bit x86 code. +::: moniker range=">=msvc-180" +The **Start** menu folder and shortcut names vary depending on the installed version of Visual Studio. For example, suppose you installed the Visual Studio 2026 Insiders version. The developer command prompt shortcut is named **Developer Command Prompt for VS Insiders** in **Start** > **Programs** > **Visual Studio** > **Visual Studio Tools**. +::: moniker-end +::: moniker range="msvc-170" +The **Start** menu folder and shortcut names vary depending on the installed version of Visual Studio. For example, the developer prompt shortcut for Visual Studio 2022 is named **Developer Command Prompt for VS 2022** in **Start** > **Programs** > **Visual Studio 2022** > **Visual Studio Tools**. +::: moniker-end +::: moniker range="msvc-160" +The **Start** menu folder and shortcut names vary depending on the installed version of Visual Studio. For example, the developer prompt shortcut for Visual Studio 2019 is named **Developer Command Prompt for VS 2019** in **Start** > **Programs** > **Visual Studio 2019** > **Visual Studio Tools**. ::: moniker-end ::: moniker range="msvc-150" - -The Start menu folder and shortcut names vary depending on the installed version of Visual Studio. If you set one, they also depend on the installation **Nickname**. For example, suppose you installed Visual Studio 2017, and you gave it a nickname of *Latest*. The developer command prompt shortcut is named **Developer Command Prompt for VS 2017 (Latest)**, in a folder named **Visual Studio 2017**. - +The **Start** menu folder and shortcut names vary depending on the installed version of Visual Studio. For example, the developer prompt shortcut for Visual Studio 2017 is named **Developer Command Prompt for VS 2017** in **Start** > **Programs** > **Visual Studio 2017** > **Visual Studio Tools**. ::: moniker-end ::: moniker range="< msvc-150" - -The Start menu folder and shortcut names vary depending on the installed version of Visual Studio. For example, suppose you installed Visual Studio 2015. The developer command prompt shortcut is named **Developer Command Prompt for VS 2015**. - +The **Start** menu folder and shortcut names vary depending on the installed version of Visual Studio. For example, the developer prompt shortcut for Visual Studio 2015 is named **Developer Command Prompt for VS 2015** in **Start** > **Programs** > **Visual Studio 2015** > **Visual Studio Tools**. ::: moniker-end > [!NOTE] -> Several command-line tools or tool options may require Administrator permission. If you have permission issues when you use them, we recommend that you open the developer command prompt window by using the **Run as Administrator** option. Right-click to open the shortcut menu for the command prompt window, then choose **More**, **Run as administrator**. +> Several command-line tools or tool options require Administrator privileges. If you have permission issues when you use them, we recommend that you open the developer Command Prompt window by using the **Run as Administrator** option. Right-click to open the shortcut menu for the Command Prompt window, then choose **More** > **Run as administrator**. -### To open a developer command prompt window +### To open a developer Command Prompt window -1. On the desktop, open the Windows **Start** menu. In Windows 11, choose the **All apps** button to open the list of installed apps. In Windows 10, the list is open to the left. Scroll down the list to find and open the folder (not the app) for your version of Visual Studio, for example, **Visual Studio 2022**. - -1. In the folder, choose the **Developer Command Prompt** for your version of Visual Studio. This shortcut starts a developer command prompt window that uses the default build architecture of 32-bit, x86-native tools to build 32-bit, x86-native code. If you prefer a non-default build architecture, choose one of the native or cross tools command prompts to specify the host and target architecture. +1. On the desktop, open the Windows **Start** menu. In Windows 11, choose **All apps** to open the list of installed apps. In Windows 10, the list is open to the left. Scroll down the list to find and open the folder (not the app) for your version of Visual Studio, such as **Visual Studio 2022** or **Visual Studio** for version 2026 and later. +1. In the folder, choose the **Developer Command Prompt** for your version of Visual Studio. This shortcut starts a developer Command Prompt window that sets the environment to use 32-bit x86 tools to build 32-bit x86 code. If you prefer a nondefault build architecture, choose one of the native or cross tools command prompts to specify the host and target architecture. For an even faster way to open a developer command prompt, enter *developer command prompt* in the desktop search box. Then choose the result you want. > [!NOTE] -> By default, the current working directory in a developer command prompt is the root of your Visual Studio installation in the Program Files directory. This isn't an appropriate location for your code and projects. Change the current working directory to another location before you create a project. The IDE creates projects in your user directory, typically in *`%USERPROFILE%\source\repos`*. +> By default, the current working directory in a developer command prompt is the root of your Visual Studio installation in the Program Files directory. This location isn't appropriate for your code and projects. Change the current working directory to another location before you create a project. The IDE creates projects in your user directory, typically in `%USERPROFILE%\source\repos`. ## Developer command file locations -If you prefer to set the build environment in an existing command prompt window, you can use one of the command files created by the installer. We recommend you set the environment in a new command prompt window. We don't recommend you later switch environments in the same command window. +If you prefer to set the build environment in an existing Command Prompt window, you can use one of the command files created by the installer. We recommend you set the environment in a new Command Prompt window. We don't recommend you later switch environments in the same command window. + +::: moniker range=">= msvc-180" -::: moniker range=">= msvc-170" +The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2026 and later, the typical installation location on a 64-bit system is `C:\Program Files\Microsoft Visual Studio\18\`. The `` can be `Insiders`, `Community`, `Professional`, `Enterprise`, `BuildTools`. -The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2022, the typical installation location on a 64-bit system is in *`\Program Files\Microsoft Visual Studio\2022\`*. The *``* may be Community, Professional, Enterprise, BuildTools, or another nickname you supplied. +::: moniker-end +::: moniker range="= msvc-170" + +The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2022, the typical installation location is `C:\Program Files\Microsoft Visual Studio\2022\`. The `` can be `Community`, `Professional`, `Enterprise`, `BuildTools`. ::: moniker-end ::: moniker range="= msvc-160" -The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2019, the typical installation location on a 64-bit system is in *`\Program Files (x86)\Microsoft Visual Studio\2019\`*. The *``* may be Community, Professional, Enterprise, BuildTools, or another nickname you supplied. +The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2019, the typical installation location on a 64-bit system is `C:\Program Files (x86)\Microsoft Visual Studio\2019\`. The `` can be `Community`, `Professional`, `Enterprise`, `BuildTools`. ::: moniker-end ::: moniker range="= msvc-150" -The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2017, the typical installation location on a 64-bit system is in *`\Program Files (x86)\Microsoft Visual Studio\2017\`*. The *``* may be Community, Professional, Enterprise, BuildTools, or another nickname you supplied. +The command file location depends on the version of Visual Studio you installed, and on choices you made during installation. For Visual Studio 2017, the typical installation location on a 64-bit system is `C:\Program Files (x86)\Microsoft Visual Studio\2017\`. The `` can be `Community`, `Professional`, `Enterprise`, `BuildTools`. ::: moniker-end ::: moniker range="< msvc-150" -The command file location depends on the Visual Studio version, and the installation directory. For Visual Studio 2015, the typical installation location on a 64-bit system is in *`\Program Files (x86)\Microsoft Visual Studio 14.0`*. +The command file location depends on the Visual Studio version, and the installation directory. For Visual Studio 2015, the typical installation location on a 64-bit system is `C:\Program Files (x86)\Microsoft Visual Studio 14.0`. ::: moniker-end -The primary developer command prompt command file, *`VsDevCmd.bat`*, is located in the *`Common7\Tools`* subdirectory. When no parameters are specified, it sets the environment to use the x86-native tools to build 32-bit x86 code. +The primary developer command prompt command file, `VsDevCmd.bat`, is located in the `Common7\Tools` directory. When you don't specify parameters, it sets the environment to use the x86-native tools to build 32-bit x86 code. ::: moniker range=">= msvc-150" -More command files are available to set up specific build architectures. The command files available depend on the Visual Studio workloads and options you've installed. In Visual Studio 2017 and Visual Studio 2019, you'll find them in the *`VC\Auxiliary\Build`* subdirectory. +More command files are available to set up specific build architectures. The command files available depend on the Visual Studio workloads and options you installed. In Visual Studio 2017 and Visual Studio 2019, you find them in the `VC\Auxiliary\Build` directory. ::: moniker-end ::: moniker range="< msvc-150" -More command files are available to set up specific build architectures. The command files available depend on the Visual Studio workloads and options you've installed. In Visual Studio 2015, they're located in the *`VC`*, *`VC\bin`*, or *`VC\bin\`* subdirectories, where *``* is one of the native or cross-compiler options. +More command files are available to set up specific build architectures. The command files available depend on the Visual Studio workloads and options you installed. In Visual Studio 2015, they're located in the `VC`, `VC\bin`, or `VC\bin\` directories, where `` is one of the native or cross-compiler options. ::: moniker-end -These command files set default parameters and call *`VsDevCmd.bat`* to set up the specified build architecture environment. A typical installation may include these command files: +These command files set default parameters and call `VsDevCmd.bat` to set up the specified build architecture environment. A typical installation might include these command files: | Command File | Host and Target architectures | |--|--| -| *`vcvars32.bat`* | Use the 32-bit x86-native tools to build 32-bit x86 code. | -| *`vcvars64.bat`* | Use the 64-bit x64-native tools to build 64-bit x64 code. | -| *`vcvarsx86_amd64.bat`* | Use the 32-bit x86-native cross tools to build 64-bit x64 code. | -| *`vcvarsamd64_x86.bat`* | Use the 64-bit x64-native cross tools to build 32-bit x86 code. | -| *`vcvarsx86_arm.bat`* | Use the 32-bit x86-native cross tools to build ARM code. | -| *`vcvarsamd64_arm.bat`* | Use the 64-bit x64-native cross tools to build ARM code. | -| *`vcvarsx86_arm64.bat`* | Use the 32-bit x86-native cross tools to build ARM64 code. | -| *`vcvarsamd64_arm64.bat`* | Use the 64-bit x64-native cross tools to build ARM64 code. | -| *`vcvarsall.bat`* | Use parameters to specify the host and target architectures, Windows SDK, and platform choices. For a list of supported options, call by using a `/help` parameter. | +| `vcvars32.bat` | Use the 32-bit x86-native tools to build 32-bit x86 code. | +| `vcvars64.bat` | Use the 64-bit x64-native tools to build 64-bit x64 code. | +| `vcvarsx86_amd64.bat` | Use the 32-bit x86-native cross tools to build 64-bit x64 code. | +| `vcvarsamd64_x86.bat` | Use the 64-bit x64-native cross tools to build 32-bit x86 code. | +| `vcvarsx86_arm.bat` | Use the 32-bit x86-native cross tools to build ARM code. | +| `vcvarsamd64_arm.bat` | Use the 64-bit x64-native cross tools to build ARM code. | +| `vcvarsx86_arm64.bat` | Use the 32-bit x86-native cross tools to build ARM64 code. | +| `vcvarsamd64_arm64.bat` | Use the 64-bit x64-native cross tools to build ARM64 code. | +| `vcvarsall.bat` | Use parameters to specify the host and target architectures, Windows SDK, and platform choices. For a list of supported options, call by using a `/help` parameter. | > [!CAUTION] -> The *`vcvarsall.bat`* file and other Visual Studio command files can vary from computer to computer. Do not replace a missing or damaged *`vcvarsall.bat`* file by using a file from another computer. Rerun the Visual Studio installer to replace the missing file. +> The `vcvarsall.bat` file and other Visual Studio command files can vary from computer to computer. Don't replace a missing or damaged `vcvarsall.bat` file by using a file from another computer. Rerun the Visual Studio installer to replace the missing file. > -> The *`vcvarsall.bat`* file also varies from version to version. If the current version of Visual Studio is installed on a computer that also has an earlier version of Visual Studio, do not run *`vcvarsall.bat`* or another Visual Studio command file from different versions in the same command prompt window. +> The `vcvarsall.bat` file also varies from version to version. If the current version of Visual Studio is installed on a computer that also has an earlier version of Visual Studio, don't run `vcvarsall.bat` or another Visual Studio command file from different versions in the same Command Prompt window. ## Use the developer tools in an existing command window -The simplest way to specify a particular build architecture in an existing command window is to use the *`vcvarsall.bat`* file. Use *`vcvarsall.bat`* to set environment variables to configure the command line for native 32-bit or 64-bit compilation. Arguments let you specify cross-compilation to x86, x64, ARM, or ARM64 processors. You can target Microsoft Store, Universal Windows Platform, or Windows Desktop platforms. You can even specify which Windows SDK to use, and select the platform toolset version. +The simplest way to specify a particular build architecture in an existing command window is to use the `vcvarsall.bat` file. Use `vcvarsall.bat` to set environment variables to configure the Command Prompt window for native 32-bit or 64-bit compilation. Arguments let you specify cross-compilation to x86, x64, ARM, or ARM64 processors. You can target Microsoft Store, Universal Windows Platform, or Windows Desktop platforms. You can even specify which Windows SDK to use, and select the platform toolset version. -When used with no arguments, *`vcvarsall.bat`* configures the environment variables to use the current x86-native compiler for 32-bit Windows Desktop targets. You can add arguments to configure the environment to use any of the native or cross compiler tools. *`vcvarsall.bat`* displays an error message if you specify a configuration that's not installed, or not available on your computer. +When you use `vcvarsall.bat` with no arguments, it configures the environment variables to use the current x86-native compiler for 32-bit Windows Desktop targets. Add arguments to configure the environment to use any of the native or cross compiler tools. `vcvarsall.bat` displays an error message if you specify a configuration that isn't installed, or isn't available on your computer. ### `vcvarsall` syntax -> **`vcvarsall.bat`** [*`architecture`*] [*`platform_type`*] [*`winsdk_version`*] [**`-vcvars_ver=`***`vcversion`*] [*`spectre_mode`*] - -*`architecture`*\ -This optional argument specifies the host and target architecture to use. If *`architecture`* isn't specified, the default build environment is used. These arguments are supported: - -| *`architecture`* | Compiler | Host computer architecture | Build output (target) architecture | -|--|--|--|--| -| `x86` | x86 32-bit native | x86, x64 | x86 | -| `x86_amd64` or `x86_x64` | x64 on x86 cross | x86, x64 | x64 | -| `x86_arm` | ARM on x86 cross | x86, x64 | ARM | -| `x86_arm64` | ARM64 on x86 cross | x86, x64 | ARM64 | -| `amd64` or `x64` | x64 64-bit native | x64 | x64 | -| `amd64_x86` or `x64_x86` | x86 on x64 cross | x64 | x86 | -| `amd64_arm` or `x64_arm` | ARM on x64 cross | x64 | ARM | -| `amd64_arm64` or `x64_arm64` | ARM64 on x64 cross | x64 | ARM64 | +`vcvarsall.bat` [`architecture`] [`platform_type`] [`winsdk_version`] [`-vcvars_ver=`*`vcversion`*] [`spectre_mode`] -*`platform_type`*\ -This optional argument allows you to specify **`store`** or **`uwp`** as the platform type. By default, the environment is set to build desktop or console apps. +- `architecture` -*`winsdk_version`*\ -Optionally specifies the version of the Windows SDK to use. By default, the latest installed Windows SDK is used. To specify the Windows SDK version, you can use a full Windows SDK number such as **`10.0.10240.0`**, or specify **`8.1`** to use the Windows 8.1 SDK. + This optional argument specifies the host and target architecture to use. If you don't specify `architecture`, the default build environment is used. The following arguments are supported: -*`vcversion`*\ -Optionally specifies the Visual Studio compiler toolset to use. By default, the environment is set to use the current Visual Studio compiler toolset. + | `architecture` | Compiler | Host computer architecture | Build output (target) architecture | + |--|--|--|--| + | `x86` | x86 32-bit native | x86, x64 | x86 | + | `x86_amd64` or `x86_x64` | x64 on x86 cross | x86, x64 | x64 | + | `x86_arm` | ARM on x86 cross | x86, x64 | ARM | + | `x86_arm64` | ARM64 on x86 cross | x86, x64 | ARM64 | + | `amd64` or `x64` | x64 64-bit native | x64 | x64 | + | `amd64_x86` or `x64_x86` | x86 on x64 cross | x64 | x86 | + | `amd64_arm` or `x64_arm` | ARM on x64 cross | x64 | ARM | + | `amd64_arm64` or `x64_arm64` | ARM64 on x64 cross | x64 | ARM64 | -::: moniker range=">= msvc-160" +- `platform_type` -Use **-vcvars_ver=14.2x.yyyyy** to specify a specific version of the Visual Studio 2019 compiler toolset. + This optional argument specifies `store` or `uwp` as the platform type. By default, the environment is set to build desktop or console apps. -Use **-vcvars_ver=14.29** to specify the latest version of the Visual Studio 2019 compiler toolset. +- `winsdk_version` -::: moniker-end -::: moniker range="= msvc-150" + Optionally specifies the version of the Windows SDK to use. By default, the latest installed Windows SDK is used. To specify the Windows SDK version, use a full Windows SDK number such as `10.0.10240.0`, or specify `8.1` to use the Windows 8.1 SDK. -Use **-vcvars_ver=14.16** to specify the latest version of the Visual Studio 2017 compiler toolset. +- `vcversion` -Use **-vcvars_ver=14.1x.yyyyy** to specify a specific version of the Visual Studio 2017 compiler toolset. - -::: moniker-end + Optionally specifies the Visual Studio compiler toolset to use. By default, the environment uses the latest installed Visual Studio compiler toolset. The following table shows example `vcvars_ver` values: -Use **-vcvars_ver=14.0** to specify the Visual Studio 2015 compiler toolset. + | `vcvars_ver={value}` | Result | VS 2026 example | VS 2022 example | VS 2019 example | VS 2017 example | + |--|--|--|--|--|--| + | `"Preview"` | Use the Visual Studio preview compiler toolset. | Supported | Not supported | Not supported | Not supported | + | `"14.0"` | Use the Visual Studio 2015 compiler toolset. | Supported | Supported | Supported | Supported | + | `"14.xx"` | Use the latest installed `14.xx.yyyyy` toolset. | `"14.51"` | `"14.44"` | `"14.29"` | `"14.16"` | + | `"14.xx.yyyyy"` | Use a specific full version number. | `"14.51.36231"` | `"14.44.35207"` | `"14.29.30133"` | `"14.16.27034"` | -*`spectre_mode`*\ -Leave this parameter out to use libraries without Spectre mitigations. Use the value **`spectre`** to use libraries with Spectre mitigations. +- `spectre_mode` -#### To set up the build environment in an existing command prompt window + Leave this parameter out to use libraries without Spectre mitigations. Specify `spectre` to use libraries with Spectre mitigations. -1. At the command prompt, use the `CD` command to change to the Visual Studio installation directory. Then, use `CD` again to change to the subdirectory that contains the configuration-specific command files. For Visual Studio 2019 and Visual Studio 2017, use the *`VC\Auxiliary\Build`* subdirectory. For Visual Studio 2015, use the *`VC`* subdirectory. +#### To set up the build environment in an existing Command Prompt window -1. Enter the command for your preferred developer environment. For example, to build ARM code for UWP on a 64-bit platform, using the latest Windows SDK and Visual Studio compiler toolset, use this command line: +1. At the command prompt, use the `CD` command to change to the Visual Studio installation directory. For example, `C:\Program Files\Microsoft Visual Studio\18\Professional` if you are using Visual studio 2026. Then, use `CD` again to change to the subdirectory that contains the configuration-specific command files. For Visual Studio 2017 and beyond, use the `VC\Auxiliary\Build` subdirectory. For Visual Studio 2015, use the `VC` subdirectory. +1. Enter the command for your preferred developer environment. For example, to build ARM code for UWP on a 64-bit platform, using the latest Windows SDK and Visual Studio compiler toolset, use this command: ```cmd vcvarsall.bat amd64_arm uwp @@ -204,37 +215,73 @@ Leave this parameter out to use libraries without Spectre mitigations. Use the v ## Create your own command prompt shortcut -::: moniker range=">= msvc-160" +::: moniker range=">=msvc-180" -Open the Properties dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **x64 Native Tools Command Prompt for VS 2019** shortcut is something similar to: +Open the **Properties** dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **x64 Native Tools Command Prompt for VS** shortcut is similar to: ```cmd -%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" +%comspec% /k "C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Auxiliary\Build\vcvars64.bat" +``` + +:::moniker-end +::: moniker range="=msvc-170" + +Open the **Properties** dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **Developer Command Prompt for VS 2022** shortcut is similar to: + +```cmd +%comspec% /k "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\Tools\VsDevCmd.bat" +``` + +:::moniker-end +::: moniker range="= msvc-160" + +Open the **Properties** dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **Developer Command Prompt for VS 2019** shortcut is similar to: + +```cmd +%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Tools\VsDevCmd.bat" ``` ::: moniker-end ::: moniker range="= msvc-150" -Open the Properties dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **x64 Native Tools Command Prompt for VS 2017** shortcut is something similar to: +Open the **Properties** dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **Developer Command Prompt for VS 2017** shortcut is similar to: ```cmd -%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" +%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Tools\VsDevCmd.bat" ``` ::: moniker-end ::: moniker range="< msvc-150" -Open the Properties dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **VS2015 x64 Native Tools Command Prompt** shortcut is something similar to: +Open the **Properties** dialog for a developer command prompt shortcut to see the command target used. For example, the target for the **Developer Command Prompt for VS2015** shortcut is similar to: + +```cmd +%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd.bat" +``` + +::: moniker-end + +The architecture-specific batch files set the `architecture` parameter and call `vcvarsall.bat`. You can pass the same options to these batch files as you pass to `vcvarsall.bat`, or you can just call `vcvarsall.bat` directly. To specify parameters for your own command shortcut, add them to the end of the command in double quotes. To use an earlier compiler toolset, specify the version number. + +You can only target ARM64 starting with Visual Studio 2026 because ARM32 targeting was removed then. + +Here's a shortcut to build ARM64 code for UWP on a 64-bit platform, using the latest Windows SDK. Targeting ARM64 is shown for Visual Studio 2026 and later. Targeting ARM32 is shown for earlier versions. + +::: moniker range=">= msvc-180" ```cmd -%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 +%comspec% /k "C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 uwp -vcvars_ver=14.50 ``` ::: moniker-end +::: moniker range="= msvc-170" -The architecture-specific batch files set the *`architecture`* parameter and call *`vcvarsall.bat`*. You can pass the same options to these batch files as you would pass to *`vcvarsall.bat`*, or you can just call *`vcvarsall.bat`* directly. To specify parameters for your own command shortcut, add them to the end of the command in double-quotes. For example, here's a shortcut to build ARM code for UWP on a 64-bit platform, using the latest Windows SDK. To use an earlier compiler toolset, specify the version number. Use something like this command target in your shortcut: +```cmd +%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm uwp -vcvars_ver=14.44 +``` -::: moniker range=">= msvc-160" +::: moniker-end +::: moniker range="= msvc-160" ```cmd %comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm uwp -vcvars_ver=14.29 @@ -256,17 +303,19 @@ The architecture-specific batch files set the *`architecture`* parameter and cal ::: moniker-end -Adjust the path to reflect your Visual Studio installation directory. The *`vcvarsall.bat`* file has additional information about specific version numbers. +Adjust the path to reflect your Visual Studio installation directory. The `vcvarsall.bat` file has more information about specific version numbers. ## Command-line tools To build a C/C++ project at a command prompt, Visual Studio provides these command-line tools: -[`CL`](reference/compiling-a-c-cpp-program.md)\ -Use the compiler (`cl.exe`) to compile and link source code files into apps, libraries, and DLLs. +- [CL](reference/compiling-a-c-cpp-program.md) -[`Link`](reference/linking.md)\ -Use the linker (`link.exe`) to link compiled object files and libraries into apps and DLLs. + Use the compiler (`cl.exe`) to compile and link source code files into apps, libraries, and DLLs. + +- [Link](reference/linking.md) + + Use the linker (`link.exe`) to link compiled object files and libraries into apps and DLLs. When you build on the command line, the F1 command isn't available for instant help. Instead, you can use a search engine to get information about warnings, errors, and messages. You can also download and use the offline help files. To use the search in Microsoft Learn, enter your query in the search box at the top of any article. @@ -274,57 +323,33 @@ When you build on the command line, the F1 command isn't available for instant h By default, the Visual Studio IDE uses native project build systems based on MSBuild. You can invoke MSBuild directly to build projects without using the IDE. You can also use the `devenv` command to use Visual Studio to build projects and solutions. Visual Studio also supports build systems based on CMake or NMake. -[`MSBuild`](msbuild-visual-cpp.md)\ -Use MSBuild (`msbuild.exe`) and a project file (`.vcxproj`) to configure a build and invoke the toolset without loading the Visual Studio IDE. It's equivalent to running the **Build** project or **Build Solution** command in the Visual Studio IDE. MSBuild has advantages over the IDE when you build at the command line. You don't have to install the full IDE on all your build servers and build pipelines. You avoid the extra overhead of the IDE. MSBuild runs in containerized build environments, and supports a [binary logger](https://msbuildlog.com/). - -[`DEVENV`](/visualstudio/ide/reference/devenv-command-line-switches)\ -Use DEVENV (`devenv.exe`) combined with a command-line switch such as **`/Build`** or **`/Clean`** to execute certain build commands without displaying the Visual Studio IDE. - -[`CMake`](../build/cmake-projects-in-visual-studio.md)\ -CMake (`cmake.exe`) is a cross-platform, open-source tool for defining build processes that run on multiple platforms. CMake can configure and control native build tools for its supported platforms, such as MSBuild and Make. For more information about CMake, see the [CMake documentation](https://cmake.org/cmake/help/latest/index.html#). - -[`NMAKE`](reference/nmake-reference.md)\ -Use NMAKE (`nmake.exe`) to build C++ projects by using a traditional makefile. - -> [!NOTE] -> Starting in Visual Studio 2019 version 16.5, MSBuild and DEVENV don't use the command-line environment to control the toolset and libraries used. +- [MSBuild](msbuild-visual-cpp.md) -## In this section + Use MSBuild (`msbuild.exe`) and a project file (`.vcxproj`) to configure a build and invoke the toolset without loading the Visual Studio IDE. It's equivalent to running the **Build** project or **Build Solution** command in the Visual Studio IDE. MSBuild has advantages over the IDE when you build at the command line. You don't have to install the full IDE on all your build servers and build pipelines. You avoid the extra overhead of the IDE. MSBuild runs in containerized build environments, and supports a [binary logger](https://msbuildlog.com/). -These articles show how to build apps on the command line, and describe how to customize the command-line build environment. Some show how to use 64-bit toolsets, and target x86, x64, ARM, and ARM64 platforms. They also describe use of the command-line build tools MSBuild and NMAKE. +- [DEVENV](/visualstudio/ide/reference/devenv-command-line-switches) -[Walkthrough: Compiling a native C++ program on the command line](walkthrough-compiling-a-native-cpp-program-on-the-command-line.md)\ -Gives an example that shows how to create and compile a C++ program on the command line. + Use DEVENV (`devenv.exe`) combined with a command-line switch such as `/Build` or `/Clean` to execute certain build commands without displaying the Visual Studio IDE. -[Walkthrough: Compile a C program on the command line](walkthrough-compile-a-c-program-on-the-command-line.md)\ -Describes how to compile a program written in the C programming language. +- [CMake](../build/cmake-projects-in-visual-studio.md) -[Walkthrough: Compiling a C++/CLI program on the command line](walkthrough-compiling-a-cpp-cli-program-on-the-command-line.md)\ -Describes how to create and compile a C++/CLI program that uses the .NET Framework. + CMake (`cmake.exe`) is a cross-platform open-source tool for defining build processes that run on multiple platforms. CMake can configure and control native build tools for its supported platforms, such as MSBuild and Make. For more information about CMake, see the [CMake documentation](https://cmake.org/cmake/help/latest/index.html#). -[Walkthrough: Compiling a C++/CX program on the command line](walkthrough-compiling-a-cpp-cx-program-on-the-command-line.md)\ -Describes how to create and compile a C++/CX program that uses the Windows Runtime. +- [NMAKE](reference/nmake-reference.md) -[NMAKE reference](reference/nmake-reference.md)\ -Provides links to articles that describe the Microsoft Program Maintenance Utility (`NMAKE.EXE`). + Use NMAKE (`nmake.exe`) to build C++ projects by using a traditional makefile. -[MSBuild on the command line - C++](msbuild-visual-cpp.md)\ -Provides links to articles that discuss how to use `msbuild.exe` from the command line. - -## Related sections - -[`/MD`, `/MT`, `/LD` (Use run-time library)](reference/md-mt-ld-use-run-time-library.md)\ -Describes how to use these compiler options to use a Debug or Release run-time library. - -[C/C++ compiler options](reference/compiler-options.md)\ -Provides links to articles that discuss the C and C++ compiler options and `CL.exe`. - -[MSVC linker options](reference/linker-options.md)\ -Provides links to articles that discuss the linker options and `LINK.exe`. - -[Additional MSVC build tools](reference/c-cpp-build-tools.md)\ -Provides links to the C/C++ build tools that are included in Visual Studio. +> [!NOTE] +> Starting in Visual Studio 2019 version 16.5, MSBuild and DEVENV don't use the command-line environment to control the toolset and libraries used. ## See also -[Projects and build systems](projects-and-build-systems-cpp.md) +- [Walkthrough: Compiling a native C++ program on the command line](walkthrough-compiling-a-native-cpp-program-on-the-command-line.md) +- [Walkthrough: Compile a C program on the command line](walkthrough-compile-a-c-program-on-the-command-line.md) +- [Walkthrough: Compiling a C++/CLI program on the command line](walkthrough-compiling-a-cpp-cli-program-on-the-command-line.md) +- [Walkthrough: Compiling a C++/CX program on the command line](walkthrough-compiling-a-cpp-cx-program-on-the-command-line.md) +- [Projects and build systems](projects-and-build-systems-cpp.md) +- [`/MD`, `/MT`, `/LD` (Use run-time library)](reference/md-mt-ld-use-run-time-library.md) +- [C/C++ compiler options](reference/compiler-options.md) +- [MSVC linker options](reference/linker-options.md) +- [Additional MSVC build tools](reference/c-cpp-build-tools.md) diff --git a/docs/build/cmake-presets-vs.md b/docs/build/cmake-presets-vs.md index 5282a491801..62d80010a54 100644 --- a/docs/build/cmake-presets-vs.md +++ b/docs/build/cmake-presets-vs.md @@ -4,6 +4,7 @@ description: "Reference for using CMake Presets to configure and build CMake pro ms.date: 06/09/2023 ms.topic: reference ms.custom: sfi-image-nochange +ai-usage: ai-assisted --- # Configure and build with CMake Presets in Visual Studio @@ -460,6 +461,38 @@ The `` part lists other compilation flags, like `"-fno-omit- Pass runtime flags to AddressSanitizer by using the `ASAN_OPTIONS` field in *`launch.vs.json`*. `ASAN_OPTIONS` defaults to `detect_leaks=0` when no other runtime options are specified because LeakSanitizer isn't supported in Visual Studio. +## Enable Segment Heap + +The Segment Heap is a Windows heap implementation that reduces memory usage and fragmentation. Visual Studio ships a CMake script that enables Segment Heap for your project by adding the required manifest settings. New C++ CMake projects enable Segment Heap by default. + +To enable Segment Heap, set `CMAKE_PROJECT_TOP_LEVEL_INCLUDES` in the `cacheVariables` map of your Configure Preset in *`CMakePresets.json`*. Optionally, set the `VS_SEGMENT_HEAP_ALLOWLIST` and `VS_SEGMENT_HEAP_EXCLUDE` environment variables to control which targets in the project use Segment Heap. Separate target names with semicolons: + + ```json +{ + "configurePresets": [ + { + // ... + "environment": { + "VS_SEGMENT_HEAP_ALLOWLIST": "target1;target2;", + "VS_SEGMENT_HEAP_EXCLUDE": "target3;" + }, + "cacheVariables": { + "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "$env{VSINSTALLDIR}Common7/IDE/CommonExtensions/Microsoft/CMake/cmake/Microsoft/SegmentHeap.cmake" + } + } + ] +} + +``` + +> [!NOTE] +> `CMAKE_PROJECT_TOP_LEVEL_INCLUDES` is available in CMake 3.24 or later. + +- `VS_SEGMENT_HEAP_ALLOWLIST` — Apply the Segment Heap manifest entry only to the listed targets. Exclude all other targets. +- `VS_SEGMENT_HEAP_EXCLUDE` — Exclude the listed targets from using the Segment Heap. + +In this example, `CMAKE_PROJECT_TOP_LEVEL_INCLUDES` points to the Visual Studio-provided `SegmentHeap.cmake` script. The optional `VS_SEGMENT_HEAP_ALLOWLIST` and `VS_SEGMENT_HEAP_EXCLUDE` variables show how to include or exclude specific targets. If neither variable is set, Visual Studio enables Segment Heap for all targets. If both variables are set, `VS_SEGMENT_HEAP_ALLOWLIST` takes precedence. + ## Run CMake from the command line or a CI pipeline You can use the same *`CMakePresets.json`* and *`CMakeUserPresets.json`* files to invoke CMake in Visual Studio and from the command line. The [CMake](https://cmake.org/cmake/help/latest/manual/cmake.1.html) and [CTest](https://cmake.org/cmake/help/latest/manual/ctest.1.html) documentation are the best resources for invoking CMake and CTest with `--preset`. CMake version 3.20 or later is required. diff --git a/docs/build/create-reusable-property-configurations.md b/docs/build/create-reusable-property-configurations.md index 52af28e0f40..33a1075ce57 100644 --- a/docs/build/create-reusable-property-configurations.md +++ b/docs/build/create-reusable-property-configurations.md @@ -1,28 +1,35 @@ --- -description: "Learn more about: Share or reuse Visual Studio project settings" -title: "Share or reuse Visual Studio project settings - C++" -ms.date: 02/07/2022 +title: Share or reuse Visual Studio project settings - C++ +description: Learn how to create Visual Studio property sheets to share and reuse C++ project settings across projects. Simplify configuration with Property Manager. +ms.date: 07/14/2026 helpviewer_keywords: ["project properties [C++], reusable"] ms.topic: how-to +#customer intent: As a C++ developer, I want to create a reusable property sheet using Property Manager so that I can share project settings across multiple projects. --- # Share or reuse Visual Studio project settings -To create a custom group of settings that you can share with others or reuse in multiple projects, use **Property Manager** to create a *property sheet* (a *`.props`* file) to store the settings for each kind of project that you want to be able to reuse or share with others. Using property sheets are far less error-prone than other ways of creating "global" settings. +To create a custom group of settings that you can share with others or reuse in multiple projects, use **Property Manager** to create a *property sheet* (a *`.props`* file) to store the settings for each kind of project that you want to be able to reuse or share with others. Using property sheets is far less error-prone than other ways of creating "global" settings. > [!IMPORTANT] > **The problem with *`*.user`* files** > -> Past versions of Visual Studio used global property sheets that had a *`.user`* file name extension and were located in the *`\\AppData\Local\Microsoft\MSBuild\v4.0\`* folder. We no longer recommend these files because they set properties for project configurations on a per-user, per-computer basis. Such "global" settings can interfere with builds, especially when you are targeting more than one platform on your build computer. For example, if you have both an MFC project and Windows Phone project, the *`.user`* properties would be invalid for one of them. Reusable property sheets are more flexible and more robust. +> Past versions of Visual Studio used global property sheets that had a *`.user`* file name extension and were located in the *`\\AppData\Local\Microsoft\MSBuild\v4.0\`* folder. > -> Although *`.user`* files are still installed by Visual Studio and participate in property inheritance, they're empty by default. The best practice is to delete any reference to them in **Property Manager** to ensure that your projects operate independently of any per-user, per-computer settings. This practice is important to ensure correct behavior in a SCC (source code control) environment. +> Microsoft no longer recommends using this approach. These files set properties for project configurations on a per-user, per-computer basis. Such *global* settings can interfere with builds, especially when you are targeting more than one platform on your build computer. For example, if you have both an MFC project and Windows Phone project, the *`.user`* properties are invalid for one of them. Reusable property sheets are more flexible and more robust. +> +> Although Visual Studio still installs *`.user`* files and they participate in property inheritance, they're empty by default. The best practice is to delete any reference to them in **Property Manager** to ensure that your projects operate independently of any per-user, per-computer settings. This practice is important to ensure correct behavior in a source code control environment. To display **Property Manager**, on the menu bar, choose **View** > **Property Manager** or **View** > **Other Windows** > **Property Manager**, depending on your settings. -If you want to apply a common, frequently used set of properties to multiple projects, you can use **Property Manager** to capture them in a reusable *property sheet* file, which by convention has a *`.props`* file name extension. You can apply the sheet (or sheets) to new projects so you don't have to set those properties from scratch. +If you want to apply a common, frequently used set of properties to multiple projects, use **Property Manager** to capture them in a reusable *property sheet* file, which by convention has a *`.props`* file name extension. You can apply the sheet (or sheets) to new projects so you don't have to set those properties from scratch. + +:::image type="content" source="media/add-new-project-property-sheet.png" alt-text="Screenshot of the Property Manager context menu."::: + +Under each configuration node, you see nodes for each property sheet that applies to that configuration. The system adds property sheets that set common values based on options you choose in the app wizard when you create the project. Right-click any node and choose **Properties** to see the properties that apply to that node. -![Screenshot of the Property Manager shortcut menu.](media/sharingnew.png "SharingNew") +All the property sheets are imported automatically into the project's primary property sheet (*`ms.cpp.props`*) and are evaluated in the order they appear in **Property Manager**. You can move them to change the evaluation order. Property sheets that are evaluated later override the values in previously evaluated sheets. -Under each configuration node, you see nodes for each property sheet that applies to that configuration. The system adds property sheets that set common values based on options you choose in the app wizard when you create the project. Right-click any node and choose Properties to see the properties that apply to that node. All the property sheets are imported automatically into the project's primary property sheet (*`ms.cpp.props`*) and are evaluated in the order they appear in Property Manager. You can move them to change the evaluation order. Property sheets that are evaluated later override the values in previously evaluated sheets. For more information about the order of evaluation in the *`.vcxproj`* file, the *`.props`* and *`.targets`* files, environment variables, and the command line, see [Project property inheritance](project-property-inheritance.md). +For more information about the order of evaluation in the *`.vcxproj`* file, the *`.props`* and *`.targets`* files, environment variables, and the command line, see [Project property inheritance](project-property-inheritance.md). If you choose **Add New Project Property Sheet** and then select, for example, the MyProps.props property sheet, a property page dialog box appears. Notice that it applies to the MyProps property sheet; any changes you make are written to the sheet, not to the project file (.vcxproj). @@ -30,17 +37,20 @@ Properties in a property sheet are overridden if the same property is set direct You can import a property sheet as often as required. Multiple projects in a solution can inherit settings from the same property sheet, and a project can have multiple sheets. A property sheet itself can inherit settings from another property sheet. -You can also create a common property sheet for multiple configurations. To create a property sheet for each configuration, open the shortcut menu for one of them, choose **Add Existing Property Sheet**, and then add the other sheets. However, if you use a common property sheet, properties you set for all configurations that the sheet applies to. The IDE doesn't show which projects or other property sheets inherit from a given property sheet. +You can also create a common property sheet for multiple configurations. To create a property sheet for each configuration, open the shortcut menu for one of them, choose **Add Existing Property Sheet**, and then add the other sheets. However, if you use a common property sheet, properties you set apply to all configurations that the sheet applies to. The IDE doesn't show which projects or other property sheets inherit from a given property sheet. In large solutions that have many projects, it can be useful to create a common property sheet for all the projects in the solution. Create the property sheet as usual. Use **Property Manager** to add that property sheet to each project in the solution. If necessary at the project level, you can add another property sheet to set project-specific values. > [!IMPORTANT] -> A *`.props`* file by default does not participate in source control because it isn't created as a project item. You can manually add the file as a solution item if you want to include it in source control. +> A *`.props`* file by default doesn't participate in source control because it isn't created as a project item. You can manually add the file as a solution item if you want to include it in source control. #### To create a property sheet 1. On the menu bar, choose **View** > **Property Manager** or **View** > **Other Windows** > **Property Manager**. The **Property Manager** opens. +1. Select the item to which to apply the property sheet. This item can be a particular configuration, or another property sheet. +1. Right-click the item and then choose **Add New Project Property Sheet**. +1. In the **Add New Item** dialog, specify a name and location for the property sheet. Visual Studio saves the *`.props`* file in the specified location. -2. To define the scope of the property sheet, select the item to which it applies. This item can be a particular configuration, or another property sheet. Open the shortcut menu for this item and then choose **Add New Project Property Sheet**. Specify a name and location. + Expand the items under the project to see your property sheet. -3. In **Property Manager**, open the new property sheet and then set the properties you want to include. +1. In **Property Manager**, open the new property sheet and then set the properties you want to include. diff --git a/docs/build/creating-and-managing-visual-cpp-projects.md b/docs/build/creating-and-managing-visual-cpp-projects.md index 2441a8b327e..f72cbf8f850 100644 --- a/docs/build/creating-and-managing-visual-cpp-projects.md +++ b/docs/build/creating-and-managing-visual-cpp-projects.md @@ -1,29 +1,59 @@ --- -title: "Create and Configure Visual Studio C++ Projects" -description: "Learn how to create a Visual Studio C++ project, and then add code and build your project." -ms.date: 03/24/2025 +title: Create and Configure Visual Studio C++ Projects +description: Get started with Visual Studio C++ projects. Learn to create a solution, then compile and run your code. +ms.date: 07/15/2026 ms.topic: concept-article helpviewer_keywords: ["Visual Studio C++ projects, creating", "projects [C++], creating", "Visual Studio C++ projects"] --- # Visual Studio C++ projects -A *Visual Studio project* is a collection of code files and assets such as icons, images, and so on, that are built together using the MSBuild system. MSBuild is the native build system for Visual Studio and is generally the best build system to use for Windows-specific programs. MSBuild is tightly integrated with Visual Studio, but you can also use it from the command line. +A *Visual Studio project* is a collection of code files and assets such as icons, images, and other resources that you build together by using the MSBuild system. MSBuild is the native build system for Visual Studio and is generally the best build system to use for Windows-specific programs. Visual Studio tightly integrates with MSBuild, but you can also use MSBuild from the command line. For information about upgrading MSBuild projects from older versions of Visual Studio, see the [Microsoft C++ porting and upgrading guide](../porting/visual-cpp-porting-and-upgrading-guide.md). -For cross-platform projects, or projects that use open-source libraries, we recommend using [CMake projects in Visual Studio](cmake-projects-in-visual-studio.md). +For cross-platform projects, or projects that use open-source libraries, use [CMake projects in Visual Studio](cmake-projects-in-visual-studio.md). ## Create a Visual Studio C++ project -::: moniker range=">=msvc-160" +When you open Visual Studio, you see options to open an existing project or create a new one. You can also open Visual Studio without code. -1. Create a C++ project by choosing **File** > **New** > **Project**. +::: moniker range=">=msvc-180" -1. In the **Create a new project** dialog, set the **Language** dropdown to **C++**. This filters the list of project templates to C++ projects. You can filter the templates by setting the **Platform**, **Project Type**, or by entering keywords in the search box. +1. Open Visual Studio and select **Create a new project**. If you already opened Visual Studio, create a C++ project by choosing **File** > **New** > **Project**. - :::image type="content" source="../build/media/vs2019-choose-console-app.png" alt-text="Screenshot of the Create a new project wizard. The Console App project template is selected."::: +1. In the **Create a new project** dialog, set the **Language** dropdown menu to **C++**. This option filters the list of project templates to C++ projects. You can filter the templates by setting the **Platform**, **Project Type**, or by entering keywords in the search box. -1. Select a project template, then choose **Next**. + :::image type="content" source="media/vs-2026/choose-console-app.png" alt-text="Screenshot of the Create a new project dialog with the Console App project template selected."::: + +1. Select a project template, and then choose **Next**. + +1. On the **Configure your new project page**, enter project-specific settings such as the project name or location and then choose **Create** to create your project. + +::: moniker-end + +::: moniker range="msvc-170" + +1. Open Visual Studio and select **Create a new project**. If you already opened Visual Studio, create a C++ project by choosing **File** > **New** > **Project**. + +1. In the **Create a new project** dialog, set the **Language** dropdown menu to **C++**. This option filters the list of project templates to C++ projects. You can filter the templates by setting the **Platform**, **Project Type**, or by entering keywords in the search box. + + :::image type="content" source="media/vs-2022/choose-console-app.png" alt-text="Screenshot of the Create a new project dialog with the Console App project template selected."::: + +1. Select a project template, and then choose **Next**. + +1. On the **Configure your new project page**, enter project-specific settings such as the project name or location and then choose **Create** to create your project. + +::: moniker-end + +::: moniker range="msvc-160" + +1. Open Visual Studio and select **Create a new project**. If you already opened Visual Studio, create a C++ project by choosing **File** > **New** > **Project**. + +1. In the **Create a new project** dialog, set the **Language** dropdown menu to **C++**. This option filters the list of project templates to C++ projects. You can filter the templates by setting the **Platform**, **Project Type**, or by entering keywords in the search box. + + :::image type="content" source="../build/media/vs2019-choose-console-app.png" alt-text="Screenshot of the Create a new project dialog with the Console App project template selected."::: + +1. Select a project template, and then choose **Next**. 1. On the **Configure your new project page**, enter project-specific settings such as the project name or location and then choose **Create** to create your project. @@ -31,7 +61,7 @@ For cross-platform projects, or projects that use open-source libraries, we reco ::: moniker range="msvc-150" -1. Create a C++ project by choosing **File** > **New** > **Project**. +1. Open Visual Studio and select **Create a new project**. If you already opened Visual Studio, create a C++ project by choosing **File** > **New** > **Project**. 1. Choose **Visual C++** in the left pane. In the center pane, a list of project templates appears: @@ -43,9 +73,11 @@ For more information about the default project templates included in Visual Stud You can create your own project templates. For more information, see [Create project templates](/visualstudio/ide/how-to-create-project-templates). -After you create a project, it appears in the [Solution Explorer](/visualstudio/ide/solutions-and-projects-in-visual-studio) window: +After you create a project, it appears in [Solution Explorer](/visualstudio/ide/solutions-and-projects-in-visual-studio): -:::image type="content" source="media/mathlibrary-solution-explorer-153.png" alt-text="Screenshot of the Solution Explorer window, showing source files, header files, and resource files."::: +:::image type="content" source="media/vs-2026/solution-explorer.png" alt-text="Screenshot of the Solution Explorer window, showing source files, header files, and resource files." lightbox="media/vs-2026/solution-explorer.png"::: + +If you don't see **Solution Explorer**, from the main menu, select **View** > **Solution Explorer**. When you create a new project, a solution file (*`.sln`*) is also created. A *Visual Studio solution* is a collection of one or more projects. You can add another project to the solution by right-clicking the solution name in **Solution Explorer** > **Add** > **New project**. @@ -57,29 +89,30 @@ Add source code files, icons, or any other items to your project by right-clicki ## Add third-party libraries to a project -Over 900 C++ open source libraries are available via the [vcpkg](/vcpkg/) package manager. Run the Visual Studio integration step to set up the paths to that library when you reference it from any Visual Studio project. +Over 900 C++ open source libraries are available through the [vcpkg](/vcpkg/) package manager. Run the Visual Studio integration step to set up the paths to those libraries when you reference them from any Visual Studio project. + +For more information about consuming a library that you download by using the **vcpkg** package manager, see: -For more information about consuming a library that you have downloaded by using the **vcpkg** package manager, see: - [vcpkg in CMake projects](/vcpkg/users/buildsystems/cmake-integration) - [Install and use packages with CMake in Visual Studio](/vcpkg/get_started/get-started-vs) - [vcpkg in MSBuild projects](/vcpkg/users/buildsystems/msbuild-integration) - [Tutorial: Install and use packages with MSBuild in Visual Studio](/vcpkg/get_started/get-started-msbuild) -There are also commercial third-party libraries that you can install. Follow their installation instructions. +You can also install commercial third-party libraries. Follow their installation instructions. ## Set compiler options and build properties -To configure build settings for a project, right-click on the project in **Solution Explorer** and choose **Properties**. For more information, see [Set compiler and build properties](working-with-project-properties.md). +To configure build settings for a project, in **Solution Explorer**, right-click the project and choose **Properties**. For more information, see [Set compiler and build properties](working-with-project-properties.md). ## Compile and run a project -To compile and run the new project, press **F5** or select the *debug dropdown* with the green arrow on the main toolbar. The *configuration dropdown* is where you choose whether to perform a *Debug* or *Release* build (or some other custom configuration). +To compile and run the new project, press **F5** or select the **debug dropdown list** with the green arrow on the main toolbar. Use the **configuration dropdown list** to choose whether to perform a **Debug** or **Release** build, or some custom configuration. -A new project compiles without errors. When adding your own code, you might occasionally introduce an error or trigger a warning. An error prevents the build from completing; a warning doesn't. All errors and warnings appear both in the Output Window and in the Error List when you build the project. +A new project compiles without errors. When you add your own code, you might occasionally introduce an error or trigger a warning. An error prevents the build from completing. A warning doesn't. All errors and warnings appear both in the **Output** window and in the **Error List**. -:::image type="content" source="../overview/media/vs2017-output-error-list.png" alt-text="Screenshot of the Output window and Error list, showing a syntax error for a misplaced colon."::: +:::image type="content" source="media/vs-2026/output-error-list.png" alt-text="Screenshot of the Output window and Error list, showing a syntax error for a typo in a variable name."::: -In the **Error List**, you can press **F1** on the highlighted error to go to its documentation topic. +In the **Error List**, press **F1** on the highlighted error to go to its documentation topic. ## Related content diff --git a/docs/build/exception-handling-x64.md b/docs/build/exception-handling-x64.md index 8e35eb70ffd..efb1eac2d73 100644 --- a/docs/build/exception-handling-x64.md +++ b/docs/build/exception-handling-x64.md @@ -9,27 +9,31 @@ ms.assetid: 41fecd2d-3717-4643-b21c-65dcd2f18c93 An overview of structured exception handling and C++ exception handling coding conventions and behavior on the x64. For general information on exception handling, see [Exception Handling in Microsoft C++](../cpp/exception-handling-in-visual-cpp.md). -## Unwind data for exception handling, debugger support +## Unwind data for exception handling and debugger support -Several data structures are required for exception handling and debugging support. +To recover nonvolatile registers when an exception is handled, nonleaf functions are annotated with static data. This data, commonly referred to as "Function Unwind Information", describes how to properly unwind the function at an arbitrary instruction. This data is stored as *pdata*, or procedure data, which in turn refers to *xdata*, the exception handling data. + +The Function Unwind Information is composed of several data structures, described next. + +For Unwind Information supporting the Intel APX (Advanced Performance Extensions), see the [Unwind V3 Preview Specification](../build/x64-unwind-information-v3.md). ### struct RUNTIME_FUNCTION Table-based exception handling requires a table entry for all functions that allocate stack space or call another function (for example, nonleaf functions). Function table entries have the format: -|Size|Value| +| Size | Value | |-|-| |ULONG|Function start address| |ULONG|Function end address| |ULONG|Unwind info address| -The RUNTIME_FUNCTION structure must be DWORD aligned in memory. All addresses are image relative, that is, they're 32-bit offsets from the starting address of the image that contains the function table entry. These entries are sorted, and put in the .pdata section of a PE32+ image. For dynamically generated functions [JIT compilers], the runtime to support these functions must either use RtlInstallFunctionTableCallback or RtlAddFunctionTable to provide this information to the operating system. Failure to do so will result in unreliable exception handling and debugging of processes. +The `RUNTIME_FUNCTION` structure must be `DWORD` aligned in memory. All addresses are image relative, that is, they're 32-bit offsets from the starting address of the image that contains the function table entry. These entries are sorted, and put in the `.pdata` section of a PE32+ image. For dynamically generated functions [JIT compilers], the runtime to support these functions must either use `RtlInstallFunctionTableCallback` or `RtlAddFunctionTable` to provide this information to the operating system. Failure to do so results in unreliable exception handling and debugging of processes. ### struct UNWIND_INFO -The unwind data info structure is used to record the effects a function has on the stack pointer, and where the nonvolatile registers are saved on the stack: +The unwind data info structure records the effects a function has on the stack pointer and where the nonvolatile registers are saved on the stack: -|Size|Value| +| Size | Value | |-|-| |UBYTE: 3|Version| |UBYTE: 5|Flags| @@ -42,20 +46,20 @@ The unwind data info structure is used to record the effects a function has on t (1) Exception Handler -|Size|Value| +| Size | Value | |-|-| |ULONG|Address of exception handler| |variable|Language-specific handler data (optional)| (2) Chained Unwind Info -|Size|Value| +| Size | Value | |-|-| |ULONG|Function start address| |ULONG|Function end address| |ULONG|Unwind info address| -The UNWIND_INFO structure must be DWORD aligned in memory. Here's what each field means: +The `UNWIND_INFO` structure must be `DWORD` aligned in memory. Here's what each field means: - **Version** @@ -67,9 +71,9 @@ The UNWIND_INFO structure must be DWORD aligned in memory. Here's what each fiel |Flag|Description| |-|-| - |`UNW_FLAG_EHANDLER`| The function has an exception handler that should be called when looking for functions that need to examine exceptions.| - |`UNW_FLAG_UHANDLER`| The function has a termination handler that should be called when unwinding an exception.| - |`UNW_FLAG_CHAININFO`| This unwind info structure is not the primary one for the procedure. Instead, the chained unwind info entry is the contents of a previous RUNTIME_FUNCTION entry. For information, see [Chained unwind info structures](#chained-unwind-info-structures). If this flag is set, then the UNW_FLAG_EHANDLER and UNW_FLAG_UHANDLER flags must be cleared. Also, the frame register and fixed-stack allocation fields must have the same values as in the primary unwind info.| + |`UNW_FLAG_EHANDLER`| The function has an exception handler that the operating system calls to examine the state of the exception and potentially handle it. Language features such as the C `__try` clause register such a handler.| + |`UNW_FLAG_UHANDLER`| The function has a termination handler that the operation system calls when unwinding the stack. This handler could release resources allocated by the function in exception safe code. Language features such as local C++ object destructors and C `__finally` clauses register such a termination handler. | + |`UNW_FLAG_CHAININFO`| This unwind info structure isn't the primary one for the procedure. Instead, the chained unwind info entry is the contents of a previous `RUNTIME_FUNCTION` entry. For information, see [Chained unwind info structures](#chained-unwind-info-structures). If this flag is set, then the `UNW_FLAG_EHANDLER` and `UNW_FLAG_UHANDLER` flags must be cleared. Also, the frame register and fixed-stack allocation fields must have the same values as in the primary unwind info.| - **Size of prolog** @@ -77,23 +81,23 @@ The UNWIND_INFO structure must be DWORD aligned in memory. Here's what each fiel - **Count of unwind codes** - The number of slots in the unwind codes array. Some unwind codes, for example, UWOP_SAVE_NONVOL, require more than one slot in the array. + The number of slots in the unwind codes array. Some unwind codes, such as `UWOP_SAVE_NONVOL`, require more than one slot in the array. - **Frame register** - If nonzero, then the function uses a frame pointer (FP), and this field is the number of the nonvolatile register used as the frame pointer, using the same encoding for the operation info field of UNWIND_CODE nodes. + If nonzero, the function uses a frame pointer (FP), and this field is the number of the nonvolatile register used as the frame pointer, using the same encoding for the operation info field of `UNWIND_CODE` nodes. - **Frame register offset (scaled)** - If the frame register field is nonzero, this field is the scaled offset from RSP that is applied to the FP register when it's established. The actual FP register is set to RSP + 16 \* this number, allowing offsets from 0 to 240. This offset permits pointing the FP register into the middle of the local stack allocation for dynamic stack frames, allowing better code density through shorter instructions. (That is, more instructions can use the 8-bit signed offset form.) + This field is a scaled offset between the `RSP` register value and the selected Frame Pointer (FP) register value. The selected FP register is set to `RSP` + 16 * this number, which means you can use offsets from 0 to 240. This offset points the FP register into the middle of the local stack allocation for dynamic stack frames, so you get better code density through shorter instructions. (That is, more instructions can use the 8-bit signed offset form.) - **Unwind codes array** - An array of items that explains the effect of the prolog on the nonvolatile registers and RSP. See the section on UNWIND_CODE for the meanings of individual items. For alignment purposes, this array always has an even number of entries, and the final entry is potentially unused. In that case, the array is one longer than indicated by the count of unwind codes field. + An array of items that explains the effect of the prolog on the nonvolatile registers and `RSP`. See the section on [Unwind operations code](#unwind-operation-code) for the meanings of individual items. To maintain proper data alignment, this array always contains an even number of entries, and the final entry may be unused. In that case, the array is one longer than indicated by the count of unwind codes field. - **Address of exception handler** - An image-relative pointer to either the function's language-specific exception or termination handler, if flag UNW_FLAG_CHAININFO is clear and one of the flags UNW_FLAG_EHANDLER or UNW_FLAG_UHANDLER is set. + An image-relative pointer to either the function's language-specific exception or termination handler, if flag `UNW_FLAG_CHAININFO` is clear and one of the flags `UNW_FLAG_EHANDLER` or `UNW_FLAG_UHANDLER` is set. - **Language-specific handler data** @@ -101,13 +105,13 @@ The UNWIND_INFO structure must be DWORD aligned in memory. Here's what each fiel - **Chained Unwind Info** - If flag UNW_FLAG_CHAININFO is set, then the UNWIND_INFO structure ends with three UWORDs. These UWORDs represent the RUNTIME_FUNCTION information for the function of the chained unwind. + If flag `UNW_FLAG_CHAININFO` is set, the `UNWIND_INFO` structure ends with three `UWORD`s. These `UWORD`s represent the `RUNTIME_FUNCTION` information for the function of the chained unwind. ### struct UNWIND_CODE -The unwind code array is used to record the sequence of operations in the prolog that affect the nonvolatile registers and RSP. Each code item has this format: +Use the unwind code array to record the sequence of operations in the prolog that affect the nonvolatile registers and `RSP`. Each code item has this format: -|Size|Value| +| Size | Value | |-|-| |UBYTE|Offset in prolog| |UBYTE: 4|Unwind operation code| @@ -121,17 +125,17 @@ Offset (from the beginning of the prolog) of the end of the instruction that per #### Unwind operation code -Note: Certain operation codes require an unsigned offset to a value in the local stack frame. This offset is from the start, that is, the lowest address of the fixed stack allocation. If the Frame Register field in the UNWIND_INFO is zero, this offset is from RSP. If the Frame Register field is nonzero, this offset is from where RSP was located when the FP register was established. It equals the FP register minus the FP register offset (16 \* the scaled frame register offset in the UNWIND_INFO). If an FP register is used, then any unwind code taking an offset must only be used after the FP register is established in the prolog. +Certain operation codes require an unsigned offset to a value in the local stack frame. This offset is from the start, that is, the lowest address of the fixed stack allocation. If the Frame Register field in the `UNWIND_INFO` is zero, this offset is from `RSP`. If the Frame Register field is nonzero, this offset is from where `RSP` was located when the FP register was established. It equals the FP register minus the FP register offset (16 \* the scaled frame register offset in the `UNWIND_INFO`). If an FP register is used, then any unwind code taking an offset must only be used after the FP register is established in the prolog. -For all opcodes except `UWOP_SAVE_XMM128` and `UWOP_SAVE_XMM128_FAR`, the offset is always a multiple of 8, because all stack values of interest are stored on 8-byte boundaries (the stack itself is always 16-byte aligned). For operation codes that take a short offset (less than 512K), the final USHORT in the nodes for this code holds the offset divided by 8. For operation codes that take a long offset (512K <= offset < 4GB), the final two USHORT nodes for this code hold the offset (in little-endian format). +For all opcodes except `UWOP_SAVE_XMM128` and `UWOP_SAVE_XMM128_FAR`, the offset is always a multiple of 8, because all stack values of interest are stored on 8-byte boundaries (the stack itself is always 16-byte aligned). For operation codes that take a short offset (less than 512K), the final `USHORT` in the nodes for this code holds the offset divided by 8. For operation codes that take a long offset (512K <= offset < 4GB), the final two `USHORT` nodes for this code hold the offset (in little-endian format). -For the opcodes `UWOP_SAVE_XMM128` and `UWOP_SAVE_XMM128_FAR`, the offset is always a multiple of 16, since all 128-bit XMM operations must occur on 16-byte aligned memory. Therefore, a scale factor of 16 is used for `UWOP_SAVE_XMM128`, permitting offsets of less than 1M. +For the opcodes `UWOP_SAVE_XMM128` and `UWOP_SAVE_XMM128_FAR`, the offset is always a multiple of 16, since all 128-bit `XMM` operations must occur on 16-byte aligned memory. Therefore, a scale factor of 16 is used for `UWOP_SAVE_XMM128`, permitting offsets of less than 1M. The unwind operation code is one of these values: - `UWOP_PUSH_NONVOL` (0) 1 node - Push a nonvolatile integer register, decrementing RSP by 8. The operation info is the number of the register. Because of the constraints on epilogs, `UWOP_PUSH_NONVOL` unwind codes must appear first in the prolog and correspondingly, last in the unwind code array. This relative ordering applies to all other unwind codes except `UWOP_PUSH_MACHFRAME`. + Push a nonvolatile integer register, decrementing `RSP` by 8. The operation info is the number of the register. Because of the constraints on epilogs, `UWOP_PUSH_NONVOL` unwind codes must appear first in the prolog and correspondingly, last in the unwind code array. This relative ordering applies to all other unwind codes except `UWOP_PUSH_MACHFRAME`. - `UWOP_ALLOC_LARGE` (1) 2 or 3 nodes @@ -151,7 +155,7 @@ The unwind operation code is one of these values: - `UWOP_SET_FPREG` (3) 1 node - Establish the frame pointer register by setting the register to some offset of the current RSP. The offset is equal to the Frame Register offset (scaled) field in the UNWIND_INFO \* 16, allowing offsets from 0 to 240. The use of an offset permits establishing a frame pointer that points to the middle of the fixed stack allocation, helping code density by allowing more accesses to use short instruction forms. The operation info field is reserved and shouldn't be used. + Establish the frame pointer register by setting the register to some offset of the current `RSP`. The offset is equal to the Frame Register offset (scaled) field in the `UNWIND_INFO` \* 16, allowing offsets from 0 to 240. The use of an offset permits establishing a frame pointer that points to the middle of the fixed stack allocation, helping code density by allowing more accesses to use short instruction forms. The operation info field is reserved and shouldn't be used. - `UWOP_SAVE_NONVOL` (4) 2 nodes @@ -163,52 +167,52 @@ The unwind operation code is one of these values: - `UWOP_SAVE_XMM128` (8) 2 nodes - Save all 128 bits of a nonvolatile XMM register on the stack. The operation info is the number of the register. The scaled-by-16 stack offset is recorded in the next slot. + Save all 128 bits of a nonvolatile `XMM` register on the stack. The operation info is the number of the register. The scaled-by-16 stack offset is recorded in the next slot. - `UWOP_SAVE_XMM128_FAR` (9) 3 nodes - Save all 128 bits of a nonvolatile XMM register on the stack with a long offset. The operation info is the number of the register. The unscaled stack offset is recorded in the next two slots. + Save all 128 bits of a nonvolatile `XMM` register on the stack with a long offset. The operation info is the number of the register. The unscaled stack offset is recorded in the next two slots. - `UWOP_PUSH_MACHFRAME` (10) 1 node - Push a machine frame. This unwind code is used to record the effect of a hardware interrupt or exception. There are two forms. If the operation info equals 0, one of these frames has been pushed on the stack: + Push a machine frame. This unwind code records the effect of a hardware interrupt or exception. It has two forms. A value of 0, indicates hardware has pushed a frame such as this on the stack: |Location|Value| |-|-| - |RSP+32|SS| - |RSP+24|Old RSP| - |RSP+16|EFLAGS| - |RSP+8|CS| - |RSP|RIP| + |`RSP`+32|`SS`| + |`RSP`+24|Old `RSP`| + |`RSP`+16|`EFLAGS`| + |`RSP`+8|`CS`| + |`RSP`|`RIP`| - If the operation info equals 1, then one of these frames has been pushed: + A value of 1, indicates hardware has pushed a frame such as this on the stack: |Location|Value| |-|-| - |RSP+40|SS| - |RSP+32|Old RSP| - |RSP+24|EFLAGS| - |RSP+16|CS| - |RSP+8|RIP| - |RSP|Error code| + |`RSP`+40|`SS`| + |`RSP`+32|Old `RSP`| + |`RSP`+24|`EFLAGS`| + |`RSP`+16|`CS`| + |`RSP`+8|`RIP`| + |`RSP`|Error code| This unwind code always appears in a dummy prolog, which is never actually executed, but instead appears before the real entry point of an interrupt routine, and exists only to provide a place to simulate the push of a machine frame. `UWOP_PUSH_MACHFRAME` records that simulation, which indicates the machine has conceptually done this operation: - 1. Pop RIP return address from top of stack into *Temp* + 1. Pop `RIP` return address from top of stack into *Temp* - 1. Push SS + 1. Push `SS` - 1. Push old RSP + 1. Push old `RSP` - 1. Push EFLAGS + 1. Push `EFLAGS` - 1. Push CS + 1. Push `CS` 1. Push *Temp* 1. Push Error Code (if op info equals 1) - The simulated `UWOP_PUSH_MACHFRAME` operation decrements RSP by 40 (op info equals 0) or 48 (op info equals 1). + The simulated `UWOP_PUSH_MACHFRAME` operation decrements `RSP` by 40 (if op info equals 0) or 48 (if op info equals 1). #### Operation info @@ -216,57 +220,57 @@ The meaning of the operation info bits depends upon the operation code. To encod |Bit|Register| |-|-| -|0|RAX| -|1|RCX| -|2|RDX| -|3|RBX| -|4|RSP| -|5|RBP| -|6|RSI| -|7|RDI| -|8 to 15|R8 to R15| +|0|`RAX`| +|1|`RCX`| +|2|`RDX`| +|3|`RBX`| +|4|`RSP`| +|5|`RBP`| +|6|`RSI`| +|7|`RDI`| +|8 to 15|`R8` to `R15`| ### Chained unwind info structures -If the UNW_FLAG_CHAININFO flag is set, then an unwind info structure is a secondary one, and the shared exception-handler/chained-info address field contains the primary unwind information. This sample code retrieves the primary unwind information, assuming that `unwindInfo` is the structure that has the UNW_FLAG_CHAININFO flag set. +If the `UNW_FLAG_CHAININFO` flag is set, then an unwind info structure is a secondary one, and the shared exception-handler/chained-info address field contains the primary unwind information. This sample code retrieves the primary unwind information, assuming that `unwindInfo` is the structure that has the `UNW_FLAG_CHAININFO` flag set. ```cpp PRUNTIME_FUNCTION primaryUwindInfo = (PRUNTIME_FUNCTION)&(unwindInfo->UnwindCode[( unwindInfo->CountOfCodes + 1 ) & ~1]); ``` -Chained info is useful in two situations. First, it can be used for noncontiguous code segments. By using chained info, you can reduce the size of the required unwind information, because you do not have to duplicate the unwind codes array from the primary unwind info. +Chained info is useful in two situations. First, it can be used for noncontiguous code segments. By using chained info, you can reduce the size of the required unwind information, because you don't have to duplicate the unwind codes array from the primary unwind info. -You can also use chained info to group volatile register saves. The compiler may delay saving some volatile registers until it is outside of the function entry prolog. You can record them by having primary unwind info for the portion of the function before the grouped code, and then setting up chained info with a non-zero size of prolog, where the unwind codes in the chained info reflect saves of the nonvolatile registers. In that case, the unwind codes are all instances of UWOP_SAVE_NONVOL. A grouping that saves nonvolatile registers by using a PUSH or modifies the RSP register by using an additional fixed stack allocation is not supported. +You can also use chained info to group volatile register saves. The compiler might delay saving some volatile registers until it is outside of the function entry prolog. You can record them by having primary unwind info for the portion of the function before the grouped code, and then setting up chained info with a nonzero size of prolog, where the unwind codes in the chained info reflect saves of the nonvolatile registers. In that case, the unwind codes are all instances of `UWOP_SAVE_NONVOL`. A grouping that saves nonvolatile registers by using a `PUSH` or modifies the `RSP` register by using an additional fixed stack allocation isn't supported. -An UNWIND_INFO item that has UNW_FLAG_CHAININFO set can contain a RUNTIME_FUNCTION entry whose UNWIND_INFO item also has UNW_FLAG_CHAININFO set, sometimes called *multiple shrink-wrapping*. Eventually, the chained unwind info pointers arrive at an UNWIND_INFO item that has UNW_FLAG_CHAININFO cleared. This item is the primary UNWIND_INFO item, which points to the actual procedure entry point. +An `UNWIND_INFO` item that has `UNW_FLAG_CHAININFO` set can contain a `RUNTIME_FUNCTION` entry whose `UNWIND_INFO` item also has `UNW_FLAG_CHAININFO` set, sometimes called *multiple shrink-wrapping*. Eventually, the chained unwind info pointers arrive at an `UNWIND_INFO` item that has `UNW_FLAG_CHAININFO` cleared. This item is the primary `UNWIND_INFO` item, which points to the actual procedure entry point. ## Unwind procedure -The unwind code array is sorted into descending order. When an exception occurs, the complete context is stored by the operating system in a context record. The exception dispatch logic is then invoked, which repeatedly executes these steps to find an exception handler: +The unwind code array is sorted into descending order. When an exception occurs, the operating system stores the complete context in a context record. The exception dispatch logic is then invoked, which repeatedly executes these steps to find an exception handler: -1. Use the current RIP stored in the context record to search for a RUNTIME_FUNCTION table entry that describes the current function (or function portion, for chained UNWIND_INFO entries). +1. Use the current `RIP` stored in the context record to search for a `RUNTIME_FUNCTION` table entry that describes the current function (or function portion, for chained `UNWIND_INFO` entries). -1. If no function table entry is found, then it's in a leaf function, and RSP directly addresses the return pointer. The return pointer at [RSP] is stored in the updated context, the simulated RSP is incremented by 8, and step 1 is repeated. +1. If the search doesn't find a function table entry, the code is assumed to be part of a leaf function, and `RSP` directly addresses the return pointer. The return pointer at [`RSP`] is stored in the updated context, the simulated `RSP` is incremented by 8, and step 1 is repeated. -1. If a function table entry is found, RIP can lie within three regions: a) in an epilog, b) in the prolog, or c) in code that may be covered by an exception handler. +1. If the search finds a function table entry, `RIP` can lie within three regions: a) in an epilog, b) in the prolog, or c) in code that might be covered by an exception handler. - - Case a) If the RIP is within an epilog, then control is leaving the function, there can be no exception handler associated with this exception for this function, and the effects of the epilog must be continued to compute the context of the caller function. To determine if the RIP is within an epilog, the code stream from RIP onward is examined. If that code stream can be matched to the trailing portion of a legitimate epilog, then it's in an epilog, and the remaining portion of the epilog is simulated, with the context record updated as each instruction is processed. After this processing, step 1 is repeated. + - Case a) If the `RIP` is within an epilog, control is leaving the function. There can be no exception handler associated with this exception for this function. The effects of the epilog must continue to compute the context of the caller function. To determine if the `RIP` is within an epilog, the code stream from `RIP` onward is examined. If that code stream matches the trailing portion of a legitimate epilog, it's in an epilog. The remaining portion of the epilog is simulated, with the context record updated as each instruction is processed. After this processing, step 1 is repeated. - - Case b) If the RIP lies within the prologue, then control hasn't entered the function, there can be no exception handler associated with this exception for this function, and the effects of the prolog must be undone to compute the context of the caller function. The RIP is within the prolog if the distance from the function start to the RIP is less than or equal to the prolog size encoded in the unwind info. The effects of the prolog are unwound by scanning forward through the unwind codes array for the first entry with an offset less than or equal to the offset of the RIP from the function start, then undoing the effect of all remaining items in the unwind code array. Step 1 is then repeated. + - Case b) If the `RIP` lies within the prolog, control hasn't entered the function. There can be no exception handler associated with this exception for this function. The effects of the prolog must be undone to compute the context of the caller function. The `RIP` is within the prolog if the distance from the function start to the `RIP` is less than or equal to the prolog size encoded in the unwind info. The unwinder scans forward through the unwind codes array for the first entry with an offset less than or equal to the offset of the `RIP` from the function start, then undoes the effect of all remaining items in the unwind code array. Step 1 is then repeated. - - Case c) If the RIP isn't within a prolog or epilog, and the function has an exception handler (UNW_FLAG_EHANDLER is set), then the language-specific handler is called. The handler scans its data and calls filter functions as appropriate. The language-specific handler can return that the exception was handled or that the search is to be continued. It can also initiate an unwind directly. + - Case c) If the `RIP` isn't within a prolog or epilog, and the function has an exception handler (`UNW_FLAG_EHANDLER` is set), the language-specific handler is called. The handler scans its data and calls filter functions as appropriate. The language-specific handler can return that the exception was handled or that the search is to be continued. It can also initiate an unwind directly. -1. If the language-specific handler returns a handled status, then execution is continued using the original context record. +1. If the language-specific handler returns a handled status, execution continues by using the original context record. -1. If there's no language-specific handler or the handler returns a "continue search" status, then the context record must be unwound to the state of the caller. It's done by processing all of the unwind code array elements, undoing the effect of each. Step 1 is then repeated. +1. If there's no language-specific handler or the handler returns a "continue search" status, the context record must be unwound to the state of the caller. The unwinder undoes the effect of each element in the unwind code array. Step 1 is then repeated. -When chained unwind info is involved, these basic steps are still followed. The only difference is that, while walking the unwind code array to unwind a prolog's effects, once the end of the array is reached, it's then linked to the parent unwind info and the entire unwind code array found there is walked. This linking continues until arriving at an unwind info without the UNW_CHAINED_INFO flag, and then it finishes walking its unwind code array. +When chained unwind info is involved, these basic steps are still followed. The only difference is that, while walking the unwind code array to unwind a prolog's effects, once the process reaches the end of the array, it links to the parent unwind info and walks the entire unwind code array found there. This linking continues until arriving at an unwind info without the `UNW_CHAINED_INFO` flag, and then it finishes walking its unwind code array. -The smallest set of unwind data is 8 bytes. This would represent a function that only allocated 128 bytes of stack or less, and possibly saved one nonvolatile register. It's also the size of a chained unwind info structure for a zero-length prolog with no unwind codes. +The smallest set of unwind data is 8 bytes. Such set represents a function that only allocated 128 bytes of stack or less, and possibly saved one nonvolatile register. It's also the size of a chained unwind info structure for a zero-length prolog with no unwind codes. ## Language-specific handler -The relative address of the language-specific handler is present in the UNWIND_INFO whenever flags UNW_FLAG_EHANDLER or UNW_FLAG_UHANDLER are set. As described in the previous section, the language-specific handler is called as part of the search for an exception handler or as part of an unwind. It has this prototype: +The `UNWIND_INFO` structure provides the relative address of the language-specific handler when either `UNW_FLAG_EHANDLER` or `UNW_FLAG_UHANDLER` flags are set. As described in the previous section, the search for an exception handler or the process of unwinding calls the language-specific handler. The handler uses this prototype: ```cpp typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) ( @@ -298,15 +302,15 @@ typedef struct _DISPATCHER_CONTEXT { } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; ``` -**ControlPc** is the value of RIP within this function. This value is either an exception address or the address at which control left the establishing function. The RIP is used to determine if control is within some guarded construct inside this function, for example, a **`__try`** block for **`__try`**/**`__except`** or **`__try`**/**`__finally`**. +**ControlPc** is the value of `RIP` within this function. This value is either an exception address or the address at which control left the establishing function. The `RIP` is used to determine if control is within some guarded construct inside this function, for example, a **`__try`** block for **`__try`**/**`__except`** or **`__try`**/**`__finally`**. -**ImageBase** is the image base (load address) of the module containing this function, to be added to the 32-bit offsets used in the function entry and unwind info to record relative addresses. +**ImageBase** is the image base (load address) of the module containing this function. The 32-bit offsets used in the function entry and unwind info should be added to the ImageBase obtain the final address. -**FunctionEntry** supplies a pointer to the RUNTIME_FUNCTION function entry holding the function and unwind info image-base relative addresses for this function. +**FunctionEntry** supplies a pointer to the `RUNTIME_FUNCTION` function entry holding the function and unwind info image-base relative addresses for this function. **EstablisherFrame** is the address of the base of the fixed stack allocation for this function. -**TargetIp** Supplies an optional instruction address that specifies the continuation address of the unwind. This address is ignored if **EstablisherFrame** isn't specified. +**TargetIp** supplies an optional instruction address that specifies the continuation address of the unwind. This address is ignored if **EstablisherFrame** isn't specified. **ContextRecord** points to the exception context, for use by the system exception dispatch/unwind code. @@ -316,19 +320,19 @@ typedef struct _DISPATCHER_CONTEXT { ## Unwind helpers for MASM -In order to write proper assembly routines, there's a set of pseudo-operations that can be used in parallel with the actual assembly instructions to create the appropriate .pdata and .xdata. And, there's a set of macros that provide simplified use of the pseudo-operations for their most common uses. +To write proper assembly routines, use a set of pseudo-operations alongside the actual assembly instructions. These pseudo-operations create the appropriate `.pdata` and `.xdata`. Also, use a set of macros that simplify the use of these pseudo-operations for their most common uses. ### Raw pseudo-operations |Pseudo operation|Description| |-|-| -|PROC FRAME \[:*ehandler*]|Causes MASM to generate a function table entry in .pdata and unwind information in .xdata for a function's structured exception handling unwind behavior. If *ehandler* is present, this proc is entered in the .xdata as the language-specific handler.

When the FRAME attribute is used, it must be followed by an .ENDPROLOG directive. If the function is a leaf function (as defined in [Function types](../build/stack-usage.md#function-types)) the FRAME attribute is unnecessary, as are the remainder of these pseudo-operations.| -|.PUSHREG *register*|Generates a UWOP_PUSH_NONVOL unwind code entry for the specified register number using the current offset in the prologue.

Only use it with nonvolatile integer registers. For pushes of volatile registers, use an .ALLOCSTACK 8, instead| -|.SETFRAME *register*, *offset*|Fills in the frame register field and offset in the unwind information using the specified register and offset. The offset must be a multiple of 16 and less than or equal to 240. This directive also generates a UWOP_SET_FPREG unwind code entry for the specified register using the current prologue offset.| -|.ALLOCSTACK *size*|Generates a UWOP_ALLOC_SMALL or a UWOP_ALLOC_LARGE with the specified size for the current offset in the prologue.

The *size* operand must be a multiple of 8.| -|.SAVEREG *register*, *offset*|Generates either a UWOP_SAVE_NONVOL or a UWOP_SAVE_NONVOL_FAR unwind code entry for the specified register and offset using the current prologue offset. MASM chooses the most efficient encoding.

*offset* must be positive, and a multiple of 8. *offset* is relative to the base of the procedure's frame, which is generally in RSP, or, if using a frame pointer, the unscaled frame pointer.| -|.SAVEXMM128 *register*, *offset*|Generates either a UWOP_SAVE_XMM128 or a UWOP_SAVE_XMM128_FAR unwind code entry for the specified XMM register and offset using the current prologue offset. MASM chooses the most efficient encoding.

*offset* must be positive, and a multiple of 16. *offset* is relative to the base of the procedure's frame, which is generally in RSP, or, if using a frame pointer, the unscaled frame pointer.| -|.PUSHFRAME \[*code*]|Generates a UWOP_PUSH_MACHFRAME unwind code entry. If the optional *code* is specified, the unwind code entry is given a modifier of 1. Otherwise the modifier is 0.| +|PROC FRAME \[:*ehandler*]|Causes MASM to generate a function table entry in `.pdata` and unwind information in `.xdata` for a function's structured exception handling unwind behavior. If *ehandler* is present, this proc is entered in the .xdata as the language-specific handler.

When you use the FRAME attribute, follow it with an .ENDPROLOG directive. If the function is a leaf function (as defined in [Function types](../build/stack-usage.md#function-types)), the FRAME attribute is unnecessary, as are the remainder of these pseudo-operations.| +|.PUSHREG *register*|Generates a `UWOP_PUSH_NONVOL` unwind code entry for the specified register number using the current offset in the prologue.

Only use it with nonvolatile integer registers. For pushes of volatile registers, use an .ALLOCSTACK 8, instead.| +|.SETFRAME *register*, *offset*|Fills in the frame register field and offset in the unwind information using the specified register and offset. The offset must be a multiple of 16 and less than or equal to 240. This directive also generates a `UWOP_SET_FPREG` unwind code entry for the specified register using the current prologue offset.| +|.ALLOCSTACK *size*|Generates a `UWOP_ALLOC_SMALL` or a `UWOP_ALLOC_LARGE` with the specified size for the current offset in the prologue.

The *size* operand must be a multiple of 8.| +|.SAVEREG *register*, *offset*|Generates either a `UWOP_SAVE_NONVOL` or a `UWOP_SAVE_NONVOL_FAR` unwind code entry for the specified register and offset using the current prologue offset. MASM chooses the most efficient encoding.

*offset* must be positive, and a multiple of 8. *offset* is relative to the base of the procedure's frame, which is generally in `RSP`, or, if using a frame pointer, the unscaled frame pointer.| +|.SAVEXMM128 *register*, *offset*|Generates either a `UWOP_SAVE_XMM128` or a `UWOP_SAVE_XMM128_FAR` unwind code entry for the specified `XMM` register and offset using the current prologue offset. MASM chooses the most efficient encoding.

*offset* must be positive, and a multiple of 16. *offset* is relative to the base of the procedure's frame, which is generally in `RSP`, or, if using a frame pointer, the unscaled frame pointer.| +|.PUSHFRAME \[*code*]|Generates a `UWOP_PUSH_MACHFRAME` unwind code entry. If you specify the optional *code*, the unwind code entry gets a modifier of 1. Otherwise the modifier is 0.| |.ENDPROLOG|Signals the end of the prologue declarations. Must occur in the first 255 bytes of the function.| Here's a sample function prolog with proper usage of most of the opcodes: @@ -384,19 +388,19 @@ For more information about the epilog example, see [Epilog code](prolog-and-epil ### MASM macros -In order to simplify the use of the [Raw pseudo-operations](#raw-pseudo-operations), there's a set of macros, defined in ksamd64.inc, which can be used to create typical procedure prologues and epilogues. +To simplify the use of [Raw pseudo-operations](#raw-pseudo-operations), use the set of macros defined in `ksamd64.inc`. These macros help you create typical procedure prologues and epilogues. |Macro|Description| |-|-| -|alloc_stack(n)|Allocates a stack frame of n bytes (using `sub rsp, n`), and emits the appropriate unwind information (.allocstack n)| -|save_reg *reg*, *loc*|Saves a nonvolatile register *reg* on the stack at RSP offset *loc*, and emits the appropriate unwind information. (.savereg reg, loc)| -|push_reg *reg*|Pushes a nonvolatile register *reg* on the stack, and emits the appropriate unwind information. (.pushreg reg)| -|rex_push_reg *reg*|Saves a nonvolatile register on the stack using a 2-byte push, and emits the appropriate unwind information (.pushreg reg). Use this macro if the push is the first instruction in the function, to ensure that the function is hot-patchable.| -|save_xmm128 *reg*, *loc*|Saves a nonvolatile XMM register *reg* on the stack at RSP offset *loc*, and emits the appropriate unwind information (.savexmm128 reg, loc)| -|set_frame *reg*, *offset*|Sets the frame register *reg* to be the RSP + *offset* (using a `mov`, or an `lea`), and emits the appropriate unwind information (.set_frame reg, offset)| -|push_eflags|Pushes the eflags with a `pushfq` instruction, and emits the appropriate unwind information (.alloc_stack 8)| - -Here's a sample function prolog with proper usage of the macros: +|alloc_stack(n)|Allocates a stack frame of *n* bytes (using `sub rsp, n`), and emits the appropriate unwind information (.allocstack n)| +|save_reg *reg*, *loc*|Saves a nonvolatile register *reg* on the stack at `RSP` offset *loc*, and emits the appropriate unwind information (.savereg reg, loc)| +|push_reg *reg*|Pushes a nonvolatile register *reg* on the stack, and emits the appropriate unwind information (.pushreg reg)| +|rex_push_reg *reg*|Saves a nonvolatile register on the stack by using a 2-byte push, and emits the appropriate unwind information (.pushreg reg). Use this macro if the push is the first instruction in the function, to ensure that the function is hot-patchable.| +|save_xmm128 *reg*, *loc*|Saves a nonvolatile `XMM` register *reg* on the stack at `RSP` offset *loc*, and emits the appropriate unwind information (.savexmm128 reg, loc)| +|set_frame *reg*, *offset*|Sets the frame register *reg* to be the `RSP` + *offset* (using a `mov` or an `lea`), and emits the appropriate unwind information (.set_frame reg, offset)| +|push_eflags|Pushes the eflags by using a `pushfq` instruction, and emits the appropriate unwind information (.alloc_stack 8)| + +Here's a sample function prologue with proper usage of the macros: ```MASM sampleFrame struct diff --git a/docs/build/how-to-create-a-release-build.md b/docs/build/how-to-create-a-release-build.md index be26a6e5da9..9aec226e84f 100644 --- a/docs/build/how-to-create-a-release-build.md +++ b/docs/build/how-to-create-a-release-build.md @@ -1,18 +1,32 @@ --- -description: "Learn more about: How to: Create a Release Build" title: "How to: Create a Release Build" -ms.date: "11/04/2016" +description: Learn how to create a release build in Visual Studio. Switch configurations, optimize your program, and prepare it for distribution. +ms.date: "07/16/2026" +author: TimShererWithAquent +ms.author: v-tishe helpviewer_keywords: ["Win32, release build", "release builds, creating"] ms.assetid: 6a4c89b1-48f0-44d2-8703-ca0a4b0351bf +#customer intent: As a developer, I want to create a release build of my program, so that I can distribute an optimized version to my users. --- -# How to: Create a Release Build +# How to create a release build -### To generate a release build of your program +Visual Studio projects have separate release and debug configurations for your program: debug version and release version for distribution. -1. Select **Release** from the **Solution Configuration** drop-down list, which is on the **Standard** toolbar. +In debug configuration, your program has symbolic debug information and no optimization. The release configuration of your program has no symbolic debug information and is fully optimized. -1. On the **Build** menu, click **Build**. +To generate a release build of your program, follow these steps: + +1. Open your solution in Visual Studio. +1. In the **Solutions Configuration** menu under the toolbar, select **Release**. + + :::image type="content" source="media/vs-2026/configure-release-build.png" alt-text="Screenshot shows Visual Studio Solutions Configuration menu with Release highlighted."::: + +1. From the **Build** menu, select **Build**. + +You can instead select **Configuration Manager**, where you can edit the build and release configurations. You can also create custom configurations to debug and release your program for different contexts and platforms. ## See also -[Release Builds](release-builds.md) +- [Project and solution configurations](/visualstudio/ide/understanding-build-configurations) +- [Release Builds](release-builds.md) +- [Common problems](common-problems-when-creating-a-release-build.md) diff --git a/docs/build/how-to-enable-a-64-bit-visual-cpp-toolset-on-the-command-line.md b/docs/build/how-to-enable-a-64-bit-visual-cpp-toolset-on-the-command-line.md index e551b430faf..0467db81855 100644 --- a/docs/build/how-to-enable-a-64-bit-visual-cpp-toolset-on-the-command-line.md +++ b/docs/build/how-to-enable-a-64-bit-visual-cpp-toolset-on-the-command-line.md @@ -1,36 +1,41 @@ --- -description: "Learn more about: How to: Enable a 64-Bit, x64 hosted MSVC toolset on the command line" title: "How to: Enable a 64-Bit MSVC Toolset on the Command Line" -ms.date: "07/24/2019" +description: "Learn how to enable a 64-Bit, x64 hosted MSVC toolset on the command line. Use this toolset to create apps that run on 32-bit, 64-bit, or ARM-based systems." +ms.date: "05/28/2026" helpviewer_keywords: ["x64 [C++]", "64-bit compiler [C++], command line usage", "64-bit compiler [C++], toolset enabling at command line", "command line [C++], 64-bit compiler", "Itanium [C++], command-line compiler", "IPF", "Itanium [C++]", "IPF, command-line compiler", "x64 [C++], command-line compiler"] +#customer intent: As a developer, I need the toolset installed with Visual Studio to build code for x86, x64, or ARM processors. --- # How to: Enable a 64-Bit, x64 hosted MSVC toolset on the command line -Visual Studio includes C++ compilers, linkers, and other tools that you can use to create platform-specific versions of your apps that can run on 32-bit, 64-bit, or ARM-based Windows operating systems. Other optional Visual Studio workloads let you use C++ tools to target other platforms, such as iOS, Android, and Linux. The default build architecture uses 32-bit, x86-hosted tools to build 32-bit, x86-native Windows code. However, you probably have a 64-bit computer. When Visual Studio is installed on a 64-bit Windows operating system, additional developer command prompt shortcuts for the 64-bit, x64-hosted native and cross compilers are available. You can take advantage of the processor and memory space available to 64-bit code by using the 64-bit, x64-hosted toolset when you build code for x86, x64, or ARM processors. +Visual Studio includes C++ compilers, linkers, and other tools that you can use to create platform-specific versions of your apps. You can create versions that run on 32-bit, 64-bit, or ARM-based Windows operating systems. Other optional Visual Studio workloads let you use C++ tools to target other platforms, such as iOS, Android, and Linux. The default build architecture uses 32-bit, x86-hosted tools to build 32-bit, x86-native Windows code. + +You probably have a 64-bit computer. When Visual Studio is installed on a 64-bit Windows operating system, other developer command prompt shortcuts for the 64-bit, x64-hosted native, and cross compilers are available. You can take advantage of the processor and memory space available to 64-bit code by using the 64-bit, x64-hosted toolset when you build code for x86, x64, or ARM processors. ## Use a 64-bit hosted developer command prompt shortcut -To access these command prompts on Windows, on the **Start** menu type `x64` and then choose one of the x64 native or cross-tool developer command prompts. +To access these command prompts on Windows, on the **Start** menu, type `x64` and then choose one of the x64 native or cross-tool developer command prompts. :::image type="complex" source="./media/x64-native-tools-command-prompt.png" alt-text="Screenshot showing the start menu with x64 in the search box and the x64 Native Tools Command Prompt shortcut selected."::: If you have different versions of Visual Studio installed, other versions of the prompt appear. Choose the prompt for the version of Visual Studio that you want to use. :::image-end::: -On earlier versions of Windows, choose **Start**, expand **All Programs**, and then expand the folder for your version of **Visual Studio** (and on older versions of Visual Studio, **Visual Studio Tools**). For more information, see [Developer command prompt shortcuts](building-on-the-command-line.md#developer_command_prompt_shortcuts). +On earlier versions of Windows, choose **Start**, expand **All Programs**, and then expand the folder for your version of **Visual Studio**. For older versions of Visual Studio, this folder is **Visual Studio Tools**. For more information, see [Developer command prompt shortcuts](building-on-the-command-line.md#developer_command_prompt_shortcuts). -## Use Vcvarsall.bat to set a 64-bit hosted build architecture +## Use vcvarsall.bat to set a 64-bit hosted build architecture -Any of the native or cross compiler tools build configurations can be used on the command line by running the vcvarsall.bat command file. This command file configures the path and environment variables that enable a particular build architecture in an existing command prompt window. For specific instructions, see [Developer command file locations](building-on-the-command-line.md#developer_command_file_locations). +Any of the native or cross compiler tools build configurations can be used on the command line by running the `vcvarsall.bat` command file. This command file configures the path and environment variables that enable a particular build architecture in an existing command prompt window. For more information, see [Developer command file locations](building-on-the-command-line.md#developer_command_file_locations). ## Remarks +When you install a C++ workload in the Visual Studio installer, it always installs 32-bit, x86-hosted, native, and cross compiler tools to build x86 and x64 code. If you include the Universal Windows Platform workload, it also installs x86-hosted cross compiler tools to build ARM code. + +If you install these workloads on a 64-bit, x64 processor, you also get 64-bit native and cross compiler tools to build x86, x64, and ARM code. The 32-bit and 64-bit tools generate identical code, but the 64-bit tools support more memory for precompiled header symbols and the Whole Program Optimization ([/GL](reference/gl-whole-program-optimization.md) and [/LTCG](reference/ltcg-link-time-code-generation.md)) options. If you run into memory limits when you use the 32-bit tools, try the 64-bit tools. + > [!NOTE] -> For information about the specific tools that are included with each Visual Studio edition, see [Visual C++ Tools and Features in Visual Studio Editions](../overview/visual-cpp-tools-and-features-in-visual-studio-editions.md). +> For information about the specific tools that are included with each Visual Studio edition, see [C++ Tools and Features in Visual Studio Editions](../overview/visual-cpp-tools-and-features-in-visual-studio-editions.md). > -> For information about how to use the Visual Studio IDE to create 64-bit applications, see [How to: Configure Microsoft C++ Projects to Target 64-Bit, x64 Platforms](how-to-configure-visual-cpp-projects-to-target-64-bit-platforms.md). - -When you install a C++ workload in the Visual Studio installer, it always installs 32-bit, x86-hosted, native and cross compiler tools to build x86 and x64 code. If you include the Universal Windows Platform workload, it also installs x86-hosted cross compiler tools to build ARM code. If you install these workloads on a 64-bit, x64 processor, you also get 64-bit native and cross compiler tools to build x86, x64, and ARM code. The 32-bit and 64-bit tools generate identical code, but the 64-bit tools support more memory for precompiled header symbols and the Whole Program Optimization ([/GL](reference/gl-whole-program-optimization.md) and [/LTCG](reference/ltcg-link-time-code-generation.md)) options. If you run into memory limits when you use the 32-bit tools, try the 64-bit tools. +> For information about how to use the Visual Studio IDE to create 64-bit applications, see [How to: Configure Visual Studio C++ Projects to Target 64-Bit, x64 Platforms](how-to-configure-visual-cpp-projects-to-target-64-bit-platforms.md). ## See also -[Configure C++ projects for 64-bit, x64 targets](configuring-programs-for-64-bit-visual-cpp.md)
+- [Configure C++ projects for 64-bit, x64 targets](configuring-programs-for-64-bit-visual-cpp.md) diff --git a/docs/build/launch-vs-schema-reference-cpp.md b/docs/build/launch-vs-schema-reference-cpp.md index e7d4f24ef18..6313e0435a3 100644 --- a/docs/build/launch-vs-schema-reference-cpp.md +++ b/docs/build/launch-vs-schema-reference-cpp.md @@ -1,7 +1,7 @@ --- title: "launch.vs.json schema reference (C++)" description: "Describes the schema elements for the `launch.vs.json` file" -ms.date: 07/15/2021 +ms.date: 06/30/2026 helpviewer_keywords: ["launch.vs.json file [C++]"] --- # `launch.vs.json` schema reference (C++) @@ -40,6 +40,7 @@ To create the file, right-click on an executable file in **Solution Explorer** a | `sourceFileMap` | object | Optional source file mappings passed to the debug engine. Format: `{ "\": "\" }` or `{ "\": { "editorPath": "\", "useForBreakpoints": true } }`. Example: `{ "/home/user/foo": "C:\\foo" }` or `{ "/home/user/foo": { "editorPath": "c:\\foo", "useForBreakpoints": true } }`. For more information, see [Source file map options](#source_file_map_options). | | `additionalProperties` | string | One of the sourceFileMapOptions. (See below.) | | `MIMode` | string | Indicates the type of MI-enabled console debugger that the MIDebugEngine will connect to. Allowed values are `"gdb"`, `"lldb"`. | +| `debuginfod` | object | Controls how `gdb` uses [debuginfod](https://sourceware.org/elfutils/Debuginfod.html) to download missing debug symbols and source files from debuginfod servers. Visual Studio applies this option only when `MIMode` is `gdb`. For more information, see [debuginfod options](#debuginfod_options). | | `args` | array | Command-line arguments passed to the program. | | `environment` | array | Environment variables to add to the environment for the program. Example: `[ { "name": "squid", "value": "clam" } ]`. | | `targetArchitecture` | string | The architecture of the debuggee. The architecture is detected automatically unless this parameter is set. Allowed values are `x86`, `arm`, `arm64`, `mips`, `x64`, `amd64`, `x86_64`. | @@ -147,3 +148,21 @@ Use with the `sourceFileMap` property: |--|--|--| | `editorPath` | string | The location of the source code for the editor to locate. | | `useForBreakpoints` | boolean | When setting breakpoints, this source mapping should be used. If **`false`**, only the filename and line number is used for setting breakpoints. If **`true`**, breakpoints will be set with the full path to the file and line number only when this source mapping is used. Otherwise just filename and line number will be used when setting breakpoints. Default is **`true`**. | + +## debuginfod options + +Use with the `debuginfod` property to control how `gdb` downloads debug symbols from debuginfod servers. On Linux systems that configure debuginfod, such as Ubuntu, Fedora, or Arch Linux, this option lets `gdb` automatically retrieve debug symbols and source files from the distribution's debuginfod servers so you don't have to install debug symbol packages manually. Visual Studio applies this option only when `MIMode` is `gdb`. + +| Property | Type | Description | +|--|--|--| +| `enabled` | boolean | When `true`, `gdb` queries debuginfod servers for missing debug info and source files. The default value is **`false`**, which avoids delays caused by network requests. | +| `timeout` | integer | The timeout in seconds for debuginfod server requests. The default value is **`30`**. Set it to `0` to use `gdb`'s default timeout. | + +The following example enables debuginfod server support and sets the timeout to 10 seconds: + +```json +"debuginfod": { + "enabled": true, + "timeout": 10 +} +``` diff --git a/docs/build/media/add-new-project-property-sheet.png b/docs/build/media/add-new-project-property-sheet.png new file mode 100644 index 00000000000..3241dc98580 Binary files /dev/null and b/docs/build/media/add-new-project-property-sheet.png differ diff --git a/docs/build/media/github-copilot-fix-warning-accept.png b/docs/build/media/github-copilot-fix-warning-accept.png deleted file mode 100644 index bb8f3ded876..00000000000 Binary files a/docs/build/media/github-copilot-fix-warning-accept.png and /dev/null differ diff --git a/docs/build/media/github-copilot-fix-warning.png b/docs/build/media/github-copilot-fix-warning.png deleted file mode 100644 index 4751bafdf01..00000000000 Binary files a/docs/build/media/github-copilot-fix-warning.png and /dev/null differ diff --git a/docs/build/media/github-copilot-open-chat.png b/docs/build/media/github-copilot-open-chat.png deleted file mode 100644 index c89019f9abc..00000000000 Binary files a/docs/build/media/github-copilot-open-chat.png and /dev/null differ diff --git a/docs/build/media/normal-build-process.png b/docs/build/media/normal-build-process.png new file mode 100644 index 00000000000..fbf6c0d1796 Binary files /dev/null and b/docs/build/media/normal-build-process.png differ diff --git a/docs/build/media/sample-profile-guided-optimization-build-process.png b/docs/build/media/sample-profile-guided-optimization-build-process.png new file mode 100644 index 00000000000..9de3effdc4b Binary files /dev/null and b/docs/build/media/sample-profile-guided-optimization-build-process.png differ diff --git a/docs/build/media/sharingnew.png b/docs/build/media/sharingnew.png deleted file mode 100644 index 2316c884b97..00000000000 Binary files a/docs/build/media/sharingnew.png and /dev/null differ diff --git a/docs/build/media/vs-2022/choose-console-app.png b/docs/build/media/vs-2022/choose-console-app.png new file mode 100644 index 00000000000..067815d8e0f Binary files /dev/null and b/docs/build/media/vs-2022/choose-console-app.png differ diff --git a/docs/build/media/vs-2026/choose-console-app.png b/docs/build/media/vs-2026/choose-console-app.png new file mode 100644 index 00000000000..934f106be49 Binary files /dev/null and b/docs/build/media/vs-2026/choose-console-app.png differ diff --git a/docs/build/media/vs-2026/configure-release-build.png b/docs/build/media/vs-2026/configure-release-build.png new file mode 100644 index 00000000000..a67c06c8fa3 Binary files /dev/null and b/docs/build/media/vs-2026/configure-release-build.png differ diff --git a/docs/build/media/vs-2026/github-copilot-fix-warning-accept.png b/docs/build/media/vs-2026/github-copilot-fix-warning-accept.png new file mode 100644 index 00000000000..06c1d036e2d Binary files /dev/null and b/docs/build/media/vs-2026/github-copilot-fix-warning-accept.png differ diff --git a/docs/build/media/vs-2026/github-copilot-fix-warning.png b/docs/build/media/vs-2026/github-copilot-fix-warning.png new file mode 100644 index 00000000000..c5a5cbffd1f Binary files /dev/null and b/docs/build/media/vs-2026/github-copilot-fix-warning.png differ diff --git a/docs/build/media/vs-2026/github-copilot-open-chat.png b/docs/build/media/vs-2026/github-copilot-open-chat.png new file mode 100644 index 00000000000..b7855f695d7 Binary files /dev/null and b/docs/build/media/vs-2026/github-copilot-open-chat.png differ diff --git a/docs/build/media/vs-2026/output-error-list.png b/docs/build/media/vs-2026/output-error-list.png new file mode 100644 index 00000000000..f75a320cd7c Binary files /dev/null and b/docs/build/media/vs-2026/output-error-list.png differ diff --git a/docs/build/media/vs-2026/solution-explorer.png b/docs/build/media/vs-2026/solution-explorer.png new file mode 100644 index 00000000000..a6f561d740b Binary files /dev/null and b/docs/build/media/vs-2026/solution-explorer.png differ diff --git a/docs/build/media/vscpp-first-start-page-flag.png b/docs/build/media/vscpp-first-start-page-flag.png deleted file mode 100644 index e17924233c7..00000000000 Binary files a/docs/build/media/vscpp-first-start-page-flag.png and /dev/null differ diff --git a/docs/build/profile-guided-optimizations.md b/docs/build/profile-guided-optimizations.md index 065565ef0d9..2da31ddff99 100644 --- a/docs/build/profile-guided-optimizations.md +++ b/docs/build/profile-guided-optimizations.md @@ -1,18 +1,20 @@ --- description: "Learn more about: Profile-guided optimizations" title: "Profile-guided optimizations" -ms.date: "04/23/2019" +ms.date: 05/11/2026 helpviewer_keywords: ["profile-guided optimizations", "optimization, profile-guided [C++]"] -ms.assetid: 2225c307-d3ae-42c1-8345-a5a959d132dc --- # Profile-guided optimizations -Profile-guided optimization (PGO) lets you optimize a whole executable file, where the optimizer uses data from test runs of the .exe or .dll file. The data represents the likely performance of the program in a production environment. +Profile-guided optimization (PGO) lets you optimize a whole executable file. The optimizer uses data from test runs of the .exe or .dll file. The data represents the likely performance of the program in a production environment. + +> [!NOTE] +> SPGO (Sample Profile-Guided Optimization) is an alternative approach that uses hardware CPU Windows Performance Counters instead of instrumentation. SPGO requires no instrumented build - you profile an existing release binary by using `xperf`. For more information, see [Introducing Sample Profile Guided Optimization in MSVC](https://devblogs.microsoft.com/cppblog/introducing-sample-profile-guided-optimization-in-msvc/) and [Sample Profile-Guided Optimization (SPGO) tutorial](sample-profile-guided-optimization.md). Profile-guided optimizations are only available for x86, x64, or ARM64 native targets. Profile-guided optimizations aren't available for executable files that run on the common language runtime. Even if you produce an assembly with mixed native and managed code (by using the **/clr** compiler option), you can't use profile-guided optimization on just the native code. If you attempt to build a project with these options set in the IDE, a build error results. > [!NOTE] -> Information that's gathered from profiling test runs overrides optimizations that would otherwise be in effect if you specify **/Ob**, **/Os**, or **/Ot**. For more information, see [/Ob (Inline Function Expansion)](reference/ob-inline-function-expansion.md) and [/Os, /Ot (Favor Small Code, Favor Fast Code)](reference/os-ot-favor-small-code-favor-fast-code.md). +> Information gathered from profiling test runs overrides optimizations that would otherwise be in effect if you specify **/Ob**, **/Os**, or **/Ot**. For more information, see [/Ob (Inline Function Expansion)](reference/ob-inline-function-expansion.md) and [/Os, /Ot (Favor Small Code, Favor Fast Code)](reference/os-ot-favor-small-code-favor-fast-code.md). ## Steps to optimize your app @@ -20,36 +22,36 @@ To use profile-guided optimization, follow these steps to optimize your app: - Compile one or more source code files with [/GL](reference/gl-whole-program-optimization.md). - Each module built with **/GL** can be examined during profile-guided optimization test runs to capture run-time behavior. Every module in a profile-guided optimization build doesn't have to be compiled with **/GL**. However, only those modules compiled with **/GL** are instrumented and later available for profile-guided optimizations. + The compiler examines each module built with **/GL** during profile-guided optimization test runs to capture run-time behavior. You don't need to compile every module in a profile-guided optimization build with **/GL**. However, only modules compiled with **/GL** are instrumented and later available for profile-guided optimizations. -- Link using [/LTCG](reference/ltcg-link-time-code-generation.md) and [/GENPROFILE or /FASTGENPROFILE](reference/genprofile-fastgenprofile-generate-profiling-instrumented-build.md). +- Link by using [/LTCG](reference/ltcg-link-time-code-generation.md) and [/GENPROFILE or /FASTGENPROFILE](reference/genprofile-fastgenprofile-generate-profiling-instrumented-build.md). - Using both **/LTCG** and **/GENPROFILE** or **/FASTGENPROFILE** creates a `.pgd` file when the instrumented app is run. After test-run data is added to the `.pgd` file, it can be used as input to the next link step (creating the optimized image). When specifying **/GENPROFILE**, you can optionally add a **PGD=**_filename_ argument to specify a nondefault name or location for the `.pgd` file. The combination of **/LTCG** and **/GENPROFILE** or **/FASTGENPROFILE** linker options replaces the deprecated **/LTCG:PGINSTRUMENT** linker option. + When you use both **/LTCG** and **/GENPROFILE** or **/FASTGENPROFILE**, the instrumented app creates a `.pgd` file when it runs. After test-run data is added to the `.pgd` file, you can use it as input to the next link step (creating the optimized image). When you specify **/GENPROFILE**, you can optionally add a **PGD=**_filename_ argument to specify a nondefault name or location for the `.pgd` file. The combination of **/LTCG** and **/GENPROFILE** or **/FASTGENPROFILE** linker options replaces the deprecated **/LTCG:PGINSTRUMENT** linker option. - Profile the application. - Each time a profiled EXE session ends, or a profiled DLL is unloaded, a `appname!N.pgc` file is created. A `.pgc` file contains information about a particular application test run. *appname* is the name of your app, and *N* is a number starting with 1 that's incremented based on the number of other `appname!N.pgc` files in the directory. You can delete a `.pgc` file if the test run doesn't represent a scenario you want to optimize. + Each time a profiled EXE session ends, or a profiled DLL unloads, the process creates an `appname!N.pgc` file. A `.pgc` file contains information about a particular application test run. *appname* is the name of your app, and *N* is a number starting with 1. It increments based on the number of other `appname!N.pgc` files in the directory. You can delete a `.pgc` file if the test run doesn't represent a scenario you want to optimize. - During a test run, you can force closure of the currently open `.pgc` file and the creation of a new `.pgc` file with the [pgosweep](pgosweep.md) utility (for example, when the end of a test scenario doesn't coincide with application shutdown). + During a test run, you can force closure of the currently open `.pgc` file and the creation of a new `.pgc` file by using the [pgosweep](pgosweep.md) utility (for example, when the end of a test scenario doesn't coincide with application shutdown). Your application can also directly invoke a PGO function, [PgoAutoSweep](pgoautosweep.md), to capture the profile data at the point of the call as a `.pgc` file. It can give you finer control over the code covered by the captured data in your `.pgc` files. For an example of how to use this function, see the [PgoAutoSweep](pgoautosweep.md) documentation. When you create your instrumented build, by default, data collection is done in non-thread-safe mode, which is faster but may be imprecise. By using the **EXACT** argument to **/GENPROFILE** or **/FASTGENPROFILE**, you can specify data collection in thread-safe mode, which is more precise, but slower. This option is also available if you set the deprecated [PogoSafeMode](environment-variables-for-profile-guided-optimizations.md#pogosafemode) environment variable, or the deprecated **/POGOSAFEMODE** linker option, when you create your instrumented build. -- Link using **/LTCG** and **/USEPROFILE**. +- Link by using **/LTCG** and **/USEPROFILE**. - Use both the **/LTCG** and [/USEPROFILE](reference/useprofile.md) linker options to create the optimized image. This step takes as input the `.pgd` file. When you specify **/USEPROFILE**, you can optionally add a **PGD=**_filename_ argument to specify a non-default name or location for the `.pgd` file. You can also specify this name by using the deprecated **/PGD** linker option. The combination of **/LTCG** and **/USEPROFILE** replaces the deprecated **/LTCG:PGOPTIMIZE** and **/LTCG:PGUPDATE** linker options. + Use both the **/LTCG** and [/USEPROFILE](reference/useprofile.md) linker options to create the optimized image. This step takes the `.pgd` file as input. When you specify **/USEPROFILE**, you can optionally add a **PGD=**_filename_ argument to specify a nondefault name or location for the `.pgd` file. You can also specify this name by using the deprecated **/PGD** linker option. The combination of **/LTCG** and **/USEPROFILE** linker options replaces the deprecated **/LTCG:PGOPTIMIZE** and **/LTCG:PGUPDATE** linker options. -It's even possible to create the optimized executable file and later determine that additional profiling would be useful to create a more optimized image. If the instrumented image and its `.pgd` file are available, you can do additional test runs and rebuild the optimized image with the newer `.pgd` file, by using the same **/LTCG** and **/USEPROFILE** linker options. +It's even possible to create the optimized executable file and later determine that more profiling would be useful to create a more optimized image. If the instrumented image and its `.pgd` file are available, you can do more test runs and rebuild the optimized image with the newer `.pgd` file by using the same **/LTCG** and **/USEPROFILE** linker options. > [!NOTE] -> Both `.pgc` and `.pgd` files are binary file types. If stored in a source control system, avoid any automatic transformation that may be made to text files. +> Both `.pgc` and `.pgd` files are binary file types. If you store them in a source control system, avoid any automatic transformation that might be made to text files. ## Optimizations performed by PGO -The profile-guided optimizations include these checks and improvements: +Profile-guided optimizations include these checks and improvements: -- **Inlining** - For example, if a function A frequently calls function B, and function B is relatively small, then profile-guided optimizations inline function B in function A. +- **Inlining** - For example, if function A frequently calls function B, and function B is relatively small, the profile-guided optimizations inline function B in function A. - **Virtual Call Speculation** - If a virtual call, or other call through a function pointer, frequently targets a certain function, a profile-guided optimization can insert a conditionally executed direct call to the frequently targeted function, and the direct call can be inlined. @@ -61,33 +63,36 @@ The profile-guided optimizations include these checks and improvements: - **Function Layout** - Based on the call graph and profiled caller/callee behavior, functions that tend to be along the same execution path are placed in the same section. -- **Conditional Branch Optimization** - With the value probes, profile-guided optimizations can find if a given value in a switch statement is used more often than other values. This value can then be pulled out of the switch statement. The same can be done with **`if`**...**`else`** instructions where the optimizer can order the **`if`**...**`else`** so that either the **`if`** or **`else`** block is placed first, depending on which block is more frequently true. +- **Conditional Branch Optimization** - With the value probes, profile-guided optimizations can find if a given value in a switch statement is used more often than other values. This value can then be pulled out of the switch statement. The same optimization can be done with **`if`**...**`else`** instructions where the optimizer can order the **`if`**...**`else`** so that either the **`if`** or **`else`** block is placed first, depending on which block is more frequently true. -- **Dead Code Separation** - Code that isn't called during profiling is moved to a special section that's appended to the end of the set of sections. It effectively keeps this section out of the often-used pages. +- **Dead Code Separation** - Profile-guided optimization moves code that isn't called during profiling to a special section at the end of the section set. It effectively keeps this section out of the often-used pages. -- **EH Code Separation** - Because EH code is only exceptionally executed, it can often be moved to a separate section. It's moved when profile-guided optimizations can determine that the exceptions occur only on exceptional conditions. +- **EH Code Separation** - Because EH code is only exceptionally executed, it can often be moved to a separate section. Profile-guided optimizations move it when they determine that the exceptions occur only on exceptional conditions. -- **Memory Intrinsics** - Whether to expand an intrinsic or not depends on whether it's called frequently. An intrinsic can also be optimized based on the block size of moves or copies. +- **Memory Intrinsics** - Whether to expand an intrinsic or not depends on whether it gets called frequently. An intrinsic can also be optimized based on the block size of moves or copies. ## Next steps -Read more about these environment variables, functions, and tools you can use in profile-guided optimizations: +To learn more about these environment variables, functions, and tools you can use in profile-guided optimizations, see the following resources: -[Environment variables for profile-guided optimizations](environment-variables-for-profile-guided-optimizations.md)
-These variables were used to specify run-time behavior of testing scenarios. They're now deprecated and replaced by new linker options. This document shows you how to move from the environment variables to the linker options. +[Environment variables for profile-guided optimizations](environment-variables-for-profile-guided-optimizations.md)\ +These variables specify the run-time behavior of testing scenarios. They're now deprecated and replaced by new linker options. This document shows you how to move from the environment variables to the linker options. -[PgoAutoSweep](pgoautosweep.md)
+[PgoAutoSweep](pgoautosweep.md)\ A function you can add to your app to provide fine-grained `.pgc` file data capture control. -[pgosweep](pgosweep.md)
+[pgosweep](pgosweep.md)\ A command-line utility that writes all profile data to the `.pgc` file, closes the `.pgc` file, and opens a new `.pgc` file. -[pgomgr](pgomgr.md)
+[pgomgr](pgomgr.md)\ A command-line utility that adds profile data from one or more `.pgc` files to the `.pgd` file. -[How to: Merge multiple PGO profiles into a single profile](how-to-merge-multiple-pgo-profiles-into-a-single-profile.md)
+[How to: Merge multiple PGO profiles into a single profile](how-to-merge-multiple-pgo-profiles-into-a-single-profile.md)\ Examples of **pgomgr** usage. +[Sample Profile-Guided Optimization (SPGO) tutorial](sample-profile-guided-optimization.md)\ +Use CPU hardware performance counters instead of instrumentation. No instrumented build required - profile your existing release binary with `xperf`. + ## See also [Additional MSVC build tools](reference/c-cpp-build-tools.md) diff --git a/docs/build/reference/arch-x64.md b/docs/build/reference/arch-x64.md index 696f055f190..a48dc2984cc 100644 --- a/docs/build/reference/arch-x64.md +++ b/docs/build/reference/arch-x64.md @@ -7,7 +7,7 @@ helpviewer_keywords: ["/arch:SSE2 compiler option [C++]", "/arch:SSE4.2 compiler --- # `/arch` (x64) -Specifies the architecture for code generation on x64. These switches apply to the x64 targeting version of the compiler. For more information on **`/arch`** for other target architectures, see [`/arch` (x86)](arch-x86.md), [`/arch` (ARM64)](arch-arm64.md), and [`/arch` (ARM)](arch-arm.md). +Specifies the architecture for code generation on x64. These switches apply to version of the compiler that targets x64. For more information about **`/arch`** for other target architectures, see [`/arch` (x86)](arch-x86.md), [`/arch` (ARM64)](arch-arm64.md), and [`/arch` (ARM)](arch-arm.md). ## Syntax @@ -16,25 +16,25 @@ Specifies the architecture for code generation on x64. These switches apply to t ## Arguments **`/arch:SSE2`**\ -Enables Intel Streaming SIMD Extensions 2. The default instruction set is SSE2 if no **`/arch`** option is specified. +Enables x64 Streaming SIMD Extensions 2. If you don't specify a **`/arch`** option, the default instruction set is SSE2. **`/arch:SSE4.2`**\ -Enables Intel Streaming SIMD Extensions 4.2. +Enables x64 Streaming SIMD Extensions 4.2. **`/arch:AVX`**\ -Enables Intel Advanced Vector Extensions. +Enables x64 Advanced Vector Extensions. **`/arch:AVX2`**\ -Enables Intel Advanced Vector Extensions 2. +Enables x64 Advanced Vector Extensions 2. **`/arch:AVX512`**\ -Enables Intel Advanced Vector Extensions 512. +Enables x64 Advanced Vector Extensions 512. **`/arch:AVX10.1`**\ -Enables Intel Advanced Vector Extensions 10 version 1. +Enables x64 Advanced Vector Extensions 10 version 1. **`/arch:AVX10.2`**\ -Enables Intel Advanced Vector Extensions 10 version 2. +Enables x64 Advanced Vector Extensions 10 version 2. ## Remarks @@ -84,5 +84,6 @@ Support for **`/arch:AVX10.1`** was added in Visual Studio 2022. Support for **` ## See also [`/arch` (Minimum CPU Architecture)](arch-minimum-cpu-architecture.md)\ +[`/feature` (x64)](feature-x64.md)\ [MSVC compiler options](compiler-options.md)\ [MSVC compiler command-line syntax](compiler-command-line-syntax.md) diff --git a/docs/build/reference/arch-x86.md b/docs/build/reference/arch-x86.md index a133eda92db..411c90f5e4d 100644 --- a/docs/build/reference/arch-x86.md +++ b/docs/build/reference/arch-x86.md @@ -7,7 +7,7 @@ helpviewer_keywords: ["/arch:IA32 compiler option [C++]", "/arch:SSE compiler op --- # `/arch` (x86) -Specifies the architecture for code generation on x86. These switches apply to the x86 (32-bit) targeting version of the compiler. For more information on **`/arch`** for other target architectures, see [`/arch` (ARM64)](arch-arm64.md), [`/arch` (x64)](arch-x64.md), and [`/arch` (ARM)](arch-arm.md). +Specifies the architecture for code generation on x86. These switches apply to the version of the compiler that targets x86 (32-bit). For more information about **`/arch`** for other target architectures, see [`/arch` (ARM64)](arch-arm64.md), [`/arch` (x64)](arch-x64.md), and [`/arch` (ARM)](arch-arm.md). ## Syntax @@ -19,25 +19,25 @@ Specifies the architecture for code generation on x86. These switches apply to t Specifies no enhanced instructions and also specifies x87 for floating-point calculations. **`/arch:SSE`**\ -Enables Intel Streaming SIMD Extensions. +Enables Streaming SIMD Extensions. **`/arch:SSE2`**\ -Enables Intel Streaming SIMD Extensions 2. The default instruction set is SSE2 if no **`/arch`** option is specified. +Enables Streaming SIMD Extensions 2. If you don't specify an **`/arch`** option, the default instruction set is SSE2. **`/arch:AVX`**\ -Enables Intel Advanced Vector Extensions. +Enables Advanced Vector Extensions. **`/arch:AVX2`**\ -Enables Intel Advanced Vector Extensions 2. +Enables Advanced Vector Extensions 2. **`/arch:AVX512`**\ -Enables Intel Advanced Vector Extensions 512. +Enables Advanced Vector Extensions 512. **`/arch:AVX10.1`**\ -Enables Intel Advanced Vector Extensions 10 version 1. +Enables Advanced Vector Extensions 10 version 1. **`/arch:AVX10.2`**\ -Enables Intel Advanced Vector Extensions 10 version 2. +Enables Advanced Vector Extensions 10 version 2. ## Remarks diff --git a/docs/build/reference/common-macros-for-build-commands-and-properties.md b/docs/build/reference/common-macros-for-build-commands-and-properties.md index bb52c1458b4..5f3cd0fc40d 100644 --- a/docs/build/reference/common-macros-for-build-commands-and-properties.md +++ b/docs/build/reference/common-macros-for-build-commands-and-properties.md @@ -59,8 +59,8 @@ This table describes a commonly used subset of the available macros; there are m | **`$(TargetFileName)`** | The file name of the primary output file for the build (defined as base name + file extension). | | **`$(TargetName)`** | The base name of the primary output file for the build. | | **`$(TargetPath)`** | The absolute path name of the primary output file for the build (defined as drive + path + base name + file extension). | -| **`$(VCInstallDir)`** | The directory that contains the C++ content of your Visual Studio installation. This property contains the version of the targeted Microsoft C++ (MSVC) toolset, which might be different that the host Visual Studio. For example, when building with `$(PlatformToolset) = v140`, **`$(VCInstallDir)`** contains the path to the Visual Studio 2015 installation. | -| **`$(VSInstallDir)`** | The directory into which you installed Visual Studio. This property contains the version of the targeted Visual Studio toolset, which might be different that the host Visual Studio. For example, when building with `$(PlatformToolset) = v110`, **`$(VSInstallDir)`** contains the path to the Visual Studio 2012 installation. | +| **`$(VCInstallDir)`** | The directory that contains the C++ content of your Visual Studio installation. This property contains the version of the targeted Microsoft C++ (MSVC) toolset, which might be different than the host Visual Studio. For example, when building with `$(PlatformToolset) = v140`, **`$(VCInstallDir)`** contains the path to the Visual Studio 2015 installation. | +| **`$(VSInstallDir)`** | The directory into which you installed Visual Studio. This property contains the version of the targeted Visual Studio toolset, which might be different than the host Visual Studio. For example, when building with `$(PlatformToolset) = v110`, **`$(VSInstallDir)`** contains the path to the Visual Studio 2012 installation. | | **`$(WebDeployPath)`** | The relative path from the web deployment root to where the project outputs belong. | | **`$(WebDeployRoot)`** | The absolute path to the location of **``**. For example, *`c:\inetpub\wwwroot`*. | diff --git a/docs/build/reference/compiler-options-listed-alphabetically.md b/docs/build/reference/compiler-options-listed-alphabetically.md index 193a21544b1..8e2d8e81772 100644 --- a/docs/build/reference/compiler-options-listed-alphabetically.md +++ b/docs/build/reference/compiler-options-listed-alphabetically.md @@ -1,7 +1,8 @@ --- title: "Compiler options listed alphabetically" description: "Reference listing in alphabetical order of the Microsoft C/C++ compiler command-line options." -ms.date: 2/5/2025 +ms.date: 05/25/2026 +ai-usage: ai-assisted helpviewer_keywords: ["compiler options, C++"] --- # Compiler options listed alphabetically @@ -66,7 +67,7 @@ This table contains an alphabetical list of compiler options. For a list of comp | [`/FC`](fc-full-path-of-source-code-file-in-diagnostics.md) | Displays the full path of source code files passed to *cl.exe* in diagnostic text. | | [`/Fd`](fd-program-database-file-name.md) | Renames program database file. | | [`/Fe`](fe-name-exe-file.md) | Renames the executable file. | -| [`/feature`](feature-arm64.md) | Enable architecture features.17.10 | +| [`/feature`](feature-enable-architecture-features.md) | Enable architecture features. | | [`/forceInterlockedFunctions`](force-interlocked-functions.md) | Dynamically selects between Armv8.0 load, store exclusive instructions or Armv8.1 LSE atomic instructions based on target CPU.17.14 | | [`/FI`](fi-name-forced-include-file.md) | Preprocesses the specified include file. | | [`/Fi`](fi-preprocess-output-file-name.md) | Specifies the preprocessed output file name. | @@ -251,7 +252,7 @@ This table contains an alphabetical list of compiler options. For a list of comp | [`/Zc:zeroSizeArrayNew[-]`](zc-zerosizearraynew.md) | Call member `new`/`delete` for zero-size arrays of objects (on by default). | | [`/Ze`](za-ze-disable-language-extensions.md) | Deprecated. Enables C89 language extensions. | | [`/Zf`](zf.md) | Improves PDB generation time in parallel builds. | -| [`/ZH:[MD5|SHA1|SHA_256]`](zh.md) | Specifies MD5, SHA-1, or SHA-256 for checksums in debug info. | +| [`/ZH:[MD5|SHA1|SHA_256|SHA384|SHA512]`](zh.md) | Specifies MD5, SHA-1, SHA-256, SHA-38418.6.0, or SHA-51218.6.0 for checksums in debug info. | | [`/ZI`](z7-zi-zi-debug-information-format.md) | Includes debug information in a program database compatible with Edit and Continue. (x86 only) | | [`/Zi`](z7-zi-zi-debug-information-format.md) | Generates complete debugging information. | | [`/Zl`](zl-omit-default-library-name.md) | Removes the default library name from the *`.obj`* file. | @@ -261,8 +262,8 @@ This table contains an alphabetical list of compiler options. For a list of comp | [`/Zs`](zs-syntax-check-only.md) | Checks syntax only. | | [`/ZW`](zw-windows-runtime-compilation.md) | Produces an output file to run on the Windows Runtime. | -17.10 This option is available starting in Visual Studio 2022 version 17.10.\ -17.14 This option is available starting in Visual Studio 2022 version 17.14. +17.14 This option is available starting in Visual Studio 2022 version 17.14.\ +18.6.0 This option is available starting in Visual Studio 2026 version 18.6.0 and MSVC version 14.51. ## See also diff --git a/docs/build/reference/compiler-options-listed-by-category.md b/docs/build/reference/compiler-options-listed-by-category.md index 5b2a78c030d..2636a52da0e 100644 --- a/docs/build/reference/compiler-options-listed-by-category.md +++ b/docs/build/reference/compiler-options-listed-by-category.md @@ -1,7 +1,8 @@ --- title: "Compiler Options Listed by Category" description: "Reference listing by category of the Microsoft C/C++ compiler command-line options." -ms.date: 2/5/2025 +ms.date: 05/25/2026 +ai-usage: ai-assisted helpviewer_keywords: ["compiler options, C++"] --- # Compiler options listed by category @@ -43,7 +44,7 @@ This article contains a categorical list of compiler options. For an alphabetica | [`/EHc`](eh-exception-handling-model.md) | `extern "C"` defaults to `nothrow`. | | [`/EHr`](eh-exception-handling-model.md) | Always generate `noexcept` runtime termination checks. | | [`/EHs`](eh-exception-handling-model.md) | Enable C++ exception handling (no SEH exceptions). | -| [`/feature`](feature-arm64.md) | Enable architecture features.17.10 | +| [`/feature`](feature-enable-architecture-features.md) | Enable architecture features. | | [`/forceInterlockedFunctions`](force-interlocked-functions.md) | Dynamically selects between Armv8.0 load, store exclusive instructions or Armv8.1 LSE atomic instructions based on target CPU.17.14 | | [`/fp:contract`](fp-specify-floating-point-behavior.md) | Consider floating-point contractions when generating code. | | [`/fp:except[-]`](fp-specify-floating-point-behavior.md) | Consider floating-point exceptions when generating code. | @@ -210,7 +211,7 @@ This article contains a categorical list of compiler options. For an alphabetica | [`/Zc:zeroSizeArrayNew[-]`](zc-zerosizearraynew.md) | Call member `new`/`delete` for 0-size arrays of objects (on by default). | | [`/Ze`](za-ze-disable-language-extensions.md) | Deprecated. Enables C89 language extensions. | | [`/Zf`](zf.md) | Improves PDB generation time in parallel builds. | -| [`/ZH`:[MD5|SHA1|SHA_256]](zh.md) | Specifies MD5, SHA-1, or SHA-256 for checksums in debug info. | +| [`/ZH`:[MD5|SHA1|SHA_256|SHA384|SHA512]](zh.md) | Specifies MD5, SHA-1, SHA-256, SHA-38418.6.0, or SHA-51218.6.0 for checksums in debug info. | | [`/ZI`](z7-zi-zi-debug-information-format.md) | Includes debug information in a program database compatible with Edit and Continue. (x86 only) | | [`/Zi`](z7-zi-zi-debug-information-format.md) | Generates complete debugging information. | | [`/Zl`](zl-omit-default-library-name.md) | Removes the default library name from the *`.obj`* file. | @@ -219,6 +220,8 @@ This article contains a categorical list of compiler options. For an alphabetica | [`/Zs`](zs-syntax-check-only.md) | Checks syntax only. | | [`/ZW`](zw-windows-runtime-compilation.md) | Produces an output file to run on the Windows Runtime. | +18.6.0 This option is available starting in Visual Studio 2026 version 18.6.0 and MSVC version 14.51. + ## Linking | Option | Purpose | @@ -329,7 +332,6 @@ Experimental options may only be supported by certain versions of the compiler. | [`/Ze`](za-ze-disable-language-extensions.md) | Deprecated. Enables language extensions. | | [`/Zg`](zg-generate-function-prototypes.md) | Removed in Visual Studio 2015. Generates function prototypes. | -17.10 This option is available starting in Visual Studio 2022 version 17.10.\ 17.14 This option is available starting in Visual Studio 2022 version 17.14. ## See also diff --git a/docs/build/reference/feature-arm64.md b/docs/build/reference/feature-arm64.md index 2954b4fed11..b4a81178d93 100644 --- a/docs/build/reference/feature-arm64.md +++ b/docs/build/reference/feature-arm64.md @@ -16,6 +16,8 @@ To enable one or more features the targeted ARM64 extension supports, specify on | Feature argument | Feature identifier | Optional from | Enabled by default | Description | Supported in version |--|--|--|--|--|--| +|**`cssc`** | `FEAT_CSSC` | Armv8.7 | Armv8.9 | Common Short Sequence Compression instructions. | Visual Studio 2026 18.10 (MSVC 14.52) +|**`faminmax`** | `FEAT_FAMINMAX` | Armv9.2 | Armv9.5 | Floating-point maximum and minimum absolute value instructions. | Visual Studio 2026 18.10 (MSVC 14.52) |**`lse`** | `FEAT_LSE` | Armv8.0 | Armv8.1 | Large System Extensions. | Visual Studio 2022 17.10 |**`rcpc`** | `FEAT_LRCPC` | Armv8.2 | Armv8.3 | Load-Acquire RCpc instructions. | Visual Studio 2022 17.10 |**`rcpc2`** | `FEAT_LRCPC2` | Armv8.2 | Armv8.4 | Load-Acquire RCpc instructions v2. | Visual Studio 2022 17.11 diff --git a/docs/build/reference/feature-enable-architecture-features.md b/docs/build/reference/feature-enable-architecture-features.md new file mode 100644 index 00000000000..b9ca7324c68 --- /dev/null +++ b/docs/build/reference/feature-enable-architecture-features.md @@ -0,0 +1,23 @@ +--- +description: "Learn more about: /feature (Enable architecture features)" +title: "/feature (Enable architecture features)" +ms.date: 05/11/2026 +f1_keywords: ["/feature"] +helpviewer_keywords: ["-feature compiler option [C++]", "/feature compiler option [C++]", "feature compiler option [C++]"] +--- +# `/feature` (Enable architecture features) + +The **`/feature`** option enables specific architecture features for code generation. Select the target platform you're working with to see **`/feature`** options for that platform. + +- [`/feature` (ARM64)](feature-arm64.md)17.10 + +- [`/feature` (x64)](feature-x64.md)14.51 + +17.10 This option is available starting in Visual Studio 2022 version 17.10.\ +14.51 This option ships with MSVC Build Tools version 14.51. Available as part of Visual Studio starting with version 18.6. + +## See also + +[`/arch` (Minimum CPU architecture)](arch-minimum-cpu-architecture.md)\ +[MSVC compiler options](compiler-options.md)\ +[MSVC compiler command-line syntax](compiler-command-line-syntax.md) diff --git a/docs/build/reference/feature-x64.md b/docs/build/reference/feature-x64.md new file mode 100644 index 00000000000..676648ce4b5 --- /dev/null +++ b/docs/build/reference/feature-x64.md @@ -0,0 +1,57 @@ +--- +description: "Learn more about: /feature (x64)" +title: "/feature (x64)" +ms.date: 05/21/2026 +--- +# `/feature` (x64) + +Enable one or more architecture features for x64 code generation. + +> [!NOTE] +> **`/feature:APX`** support is experimental and subject to change. + +## Syntax + +> **`/feature:`** + +## Arguments + +To enable one or more features the x64 target supports, specify one or more of the following feature arguments: + +| Feature argument | Description | Supported in version | +|--|--|--| +| **`APX`** | Enables preview support for Intel APX (Advanced Performance Extensions). Enables the compiler to target various APX features like Extended General-Purpose Registers (EGPRs), New Data Destination (NDD), No-Flags Update (NF), new conditional ISA and optimized registers save/restore operations. For more information, see [Intel Advanced Performance Extensions (APX)](https://www.intel.com/content/www/us/en/developer/articles/technical/advanced-performance-extensions-apx.html). | MSVC Build Tools 14.51 (Preview Support) | + +## Remarks + +Example usage: to enable APX, specify **`/feature:APX`**. + +When **`/feature:APX`** is specified, the following preprocessor macros are defined: `__APX_F__`, `__CCMP__`, `__CF__`, `__EGPR__`, `__NDD__`, `__NF__`, `__PPX__`, `__PUSH2POP2__`, and `__ZU__`. For more information, see [Microsoft-specific predefined macros](../../preprocessor/predefined-macros.md). + +APX extends the x64 architecture with new registers and instructions, which affects how the compiler generates calls, preserves state across function boundaries, and emits unwind metadata. The following articles describe the x64 conventions and unwind information related to APX: + +- [Caller/callee saved registers](../x64-calling-convention.md#callercallee-saved-registers)\ + Describes which registers a callee must preserve and which the caller is responsible for saving across a call on x64. +- [setjmp/longjmp](../x64-calling-convention.md#setjmplongjmp)\ + Explains how nonlocal jumps capture and restore nonvolatile register state on x64, including the registers that participate in the jump buffer. +- [Register volatility and preservation](../x64-software-conventions.md#register-volatility-and-preservation)\ + Summarizes the x64 software conventions for volatile and nonvolatile general-purpose, `XMM`, `YMM`, and `ZMM` registers, and the rules callees must follow to preserve them. +- [Exception handling unwind information V3](../x64-unwind-information-v3.md)\ + Preview specification of the V3 unwind information format used to describe prologs, epilogs, and frame layout for x64 code, including the extended state introduced by APX. + +### To set the `/feature` compiler option in Visual Studio + +1. Open the **Property Pages** dialog box for the project. For more information, see [Set C++ compiler and build properties in Visual Studio](../working-with-project-properties.md). +1. Select the **Configuration Properties** > **C/C++** > **Command Line** property page. +1. In the **Additional options** box, add *`/feature:APX`*. Choose **OK** to save your changes. + +### To set this compiler option programmatically + +- See . + +## See also + +[`/arch` (x64)](arch-x64.md)\ +[`/arch` (Minimum CPU architecture)](arch-minimum-cpu-architecture.md)\ +[MSVC compiler options](compiler-options.md)\ +[MSVC compiler command-line syntax](compiler-command-line-syntax.md) diff --git a/docs/build/reference/fsanitize.md b/docs/build/reference/fsanitize.md index e1eef40728d..56a37b801fc 100644 --- a/docs/build/reference/fsanitize.md +++ b/docs/build/reference/fsanitize.md @@ -29,7 +29,9 @@ The **`/fsanitize=fuzzer`** compiler option enables experimental support for [Li The **`/fsanitize`** option doesn't allow comma-separated syntax, for example: **`/fsanitize=address,fuzzer`**. These options must be specified individually. -The **`/fsanitize-address-use-after-return`**, **`/fno-sanitize-address-vcasan-lib`**, **`/fsanitize-address-asan-compat-lib`**, and **`/fno-sanitize-address-asan-compat-lib`** compiler options, and the [`/INFERASANLIBS` (Use inferred sanitizer libs)](./inferasanlibs.md) and **`/INFERASANLIBS:NO`** linker options offer support for advanced users. For more information, see [AddressSanitizer build and language reference](../../sanitizers/asan-building.md). +The **`/fsanitize-address-use-after-return`** compiler option enables experimental support for detecting memory safety issues arising from using a variable that has left scope. This requires that the ASan runtime option `ASAN_OPTIONS=detect_stack_use_after_return=1` is also set and incurs an additional performance penalty. For more information, see [Error: stack-use-after-return](../../sanitizers/error-stack-use-after-return.md). + +The **`/fno-sanitize-address-vcasan-lib`**, **`/fsanitize-address-asan-compat-lib`**, and **`/fno-sanitize-address-asan-compat-lib`** compiler options, and the [`/INFERASANLIBS` (Use inferred sanitizer libs)](./inferasanlibs.md) and **`/INFERASANLIBS:NO`** linker options offer support for advanced users. For more information, see [AddressSanitizer build and language reference](../../sanitizers/asan-building.md). ### To set the **`/fsanitize=address`** compiler option in the Visual Studio development environment diff --git a/docs/build/reference/internal-partition.md b/docs/build/reference/internal-partition.md index 393c44956ac..9a91b9ebb7b 100644 --- a/docs/build/reference/internal-partition.md +++ b/docs/build/reference/internal-partition.md @@ -1,7 +1,7 @@ --- title: "/internalPartition" description: "Use the /internalPartition compiler option to treat the input file as an internal partition unit." -ms.date: 11/16/2022 +ms.date: 6/3/2026 author: "tylermsft" ms.author: "twhitney" f1_keywords: ["/internalPartition", "VC.Project.VCCLCompilerTool.Interface"] @@ -52,7 +52,7 @@ This option can't be used with the [`/interface`](interface.md) compiler option. ### To set this compiler option in the Visual Studio development environment -You normally shouldn't set this option in the Visual Studio development environment unless you use a different extension for your partition files. By default, the build system applies this option to files that have a *`.ixx`** extension. +You normally shouldn't set this option in the Visual Studio development environment unless you use a different extension for your partition files. By default, the build system applies this option to files that have a *`.ixx`* extension. 1. To apply the **`/internalPartition`** option to a file explicitly in the IDE, select the file in **Solution Explorer**. Right-click to open the context menu and select **Properties** to open the Property Pages dialog. @@ -66,4 +66,4 @@ You normally shouldn't set this option in the Visual Studio development environm [Overview of modules in C++](../../cpp/modules-cpp.md)\ [Using C++ Modules in MSVC from the Command Line](https://devblogs.microsoft.com/cppblog/using-cpp-modules-in-msvc-from-the-command-line-part-1/)\ -[C++ Modules conformance improvements with MSVC in Visual Studio 2019 16.5](https://devblogs.microsoft.com/cppblog/c-modules-conformance-improvements-with-msvc-in-visual-studio-2019-16-5/#module-partitions) \ No newline at end of file +[C++ Modules conformance improvements with MSVC in Visual Studio 2019 16.5](https://devblogs.microsoft.com/cppblog/c-modules-conformance-improvements-with-msvc-in-visual-studio-2019-16-5/#module-partitions) diff --git a/docs/build/reference/linker-options.md b/docs/build/reference/linker-options.md index 5749d0c2364..a647917101a 100644 --- a/docs/build/reference/linker-options.md +++ b/docs/build/reference/linker-options.md @@ -7,7 +7,7 @@ helpviewer_keywords: ["linker [C++]", "linker [C++], options listed", "libraries --- # Linker options -LINK.exe links Common Object File Format (COFF) object files and libraries to create an executable (EXE) file or a dynamic-link library (DLL). +`LINK.exe` links Common Object File Format (COFF) object files and libraries to create an executable (EXE) file or a dynamic-link library (DLL). The following table lists options for `LINK.exe`. For more information about LINK, see: @@ -16,9 +16,9 @@ The following table lists options for `LINK.exe`. For more information about LIN - [LINK output](link-output.md) - [Reserved words](reserved-words.md) -Linker options aren't case-sensitive; for example, `/base` and `/BASE` mean the same thing. For details on how to specify each option on the command line or in Visual Studio, see the documentation for that option. +Linker options aren't case-sensitive. For example, `/base` and `/BASE` mean the same thing. For details on how to specify each option on the command line or in Visual Studio, see the documentation for that option. -You can use the [`comment`](../../preprocessor/comment-c-cpp.md) pragma to specify some linker options. +Use the [`comment`](../../preprocessor/comment-c-cpp.md) pragma to specify some linker options. ## Linker options listed alphabetically @@ -112,6 +112,10 @@ You can use the [`comment`](../../preprocessor/comment-c-cpp.md) pragma to speci | [`/SAFESEH`](safeseh-image-has-safe-exception-handlers.md) | Specifies that the image will contain a table of safe exception handlers. | | [`/SECTION`](section-specify-section-attributes.md) | Overrides the attributes of a section. | | [`/SOURCELINK`](sourcelink.md) | Specifies a SourceLink file to add to the PDB. | +| [`/SPD`](spd-specify-sample-profile-database.md) | Specifies the name and location of the *`.spd`* file for Sample Profile-Guided Optimization. | +| [`/SPDEMBED`](spdembed-embed-sample-profile-database.md) | Embeds the Sample Profile Database into the PDB file during a Sample Profile-Guided Optimization (SPGO) build. | +| [`/SPDIN`](spdin-use-sample-profile-database.md) | Specifies a *`.spd`* file containing profiling data for an optimized Sample Profile-Guided Optimization (SPGO) build. | +| [`/SPGO`](spgo-enable-sample-profile-guided-optimization.md) | Enables Sample Profile-Guided Optimization and creates an empty *`.spd`* file. | | [`/STACK`](stack-stack-allocations.md) | Sets the size of the stack in bytes. | | [`/STUB`](stub-ms-dos-stub-file-name.md) | Attaches an MS-DOS stub program to a Win32 program. | | [`/SUBSYSTEM`](subsystem-specify-subsystem.md) | Tells the operating system how to run the *`.exe`* file. | diff --git a/docs/build/reference/manifest-tool-property-pages.md b/docs/build/reference/manifest-tool-property-pages.md index cdf705d3d85..fc70cc16669 100644 --- a/docs/build/reference/manifest-tool-property-pages.md +++ b/docs/build/reference/manifest-tool-property-pages.md @@ -22,6 +22,7 @@ f1_keywords: - VC.Project.VCManifestTool.ReplacementsFile - VC.Project.VCManifestTool.UpdateFileHashes - VC.Project.VCManifestTool.UpdateFileHashesSearchPath + - VC.Project.VCManifestTool.EnableSegmentHeap --- # Manifest Tool Property Pages @@ -97,6 +98,10 @@ Specifies whether the application is DPI-aware. By default, the setting is **Yes - **High DPI Aware** - **Per Monitor High DPI Aware** +### Segment Heap + +Specifies whether the application utilizes the Segment Heap. When enabled, applications benefit from improved memory efficiency, reduced fragmentation, and enhanced memory security. For new C++ projects, the setting is **Yes** by default. + ## Isolated COM Property Page For more information about isolated COM, see [Isolated applications](/windows/win32/SbsCs/isolated-applications) and [How to: Build isolated applications to consume COM components](../how-to-build-isolated-applications-to-consume-com-components.md). diff --git a/docs/build/reference/spd-specify-sample-profile-database.md b/docs/build/reference/spd-specify-sample-profile-database.md new file mode 100644 index 00000000000..f6afb2d2407 --- /dev/null +++ b/docs/build/reference/spd-specify-sample-profile-database.md @@ -0,0 +1,46 @@ +--- +title: "/SPD (Specify Sample Profile Database)" +description: "Learn more about: /SPD (Specify Sample Profile Database)" +ms.date: 05/05/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["/SPD linker option", "-SPD linker option", "sample profile-guided optimization, /SPD"] +--- +# /SPD (Specify Sample Profile Database) + +Specifies the name and location of the Sample Profile Database (SPD) file used by the Sample Profile-Guided Optimization (SPGO) workflow. + +## Syntax + +> **/SPD:**_filename_ + +## Argument + +`filename`\ +Specifies the name of the `.spd` file. When expanded, the fully qualified path must not exceed `MAX_PATH` (260 characters). + +## Remarks + +When you build with [`/SPGO`](spgo-enable-sample-profile-guided-optimization.md), the linker creates an empty SPD file alongside the output binary. By default, the SPD file uses the same base name as the output file and is created in the directory where you invoked the link. Use `/SPD` to specify a different name or path. + +When linking with [`/SPDIN`](spdin-use-sample-profile-database.md), use `/SPDIN` to specify the input SPD file and `/SPD` to specify the output SPD file. + +For more information about the SPGO workflow, see [Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md). + +### To set this linker option in the Visual Studio development environment + +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). +1. Select the **Configuration Properties** > **Linker** > **Command Line** property page. +1. Add `/SPD:filename` to the **Additional Options** box. Choose **OK** to save your changes. + +### To set this linker option programmatically + +- See . + +## See also + +[MSVC linker reference](linking.md)\ +[MSVC Linker Options](linker-options.md)\ +[/SPDEMBED (Embed Sample Profile Database)](spdembed-embed-sample-profile-database.md)\ +[/SPDIN (Use Sample Profile Database)](spdin-use-sample-profile-database.md)\ +[/SPGO (Enable Sample Profile-Guided Optimization)](spgo-enable-sample-profile-guided-optimization.md)\ +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md) \ No newline at end of file diff --git a/docs/build/reference/spdembed-embed-sample-profile-database.md b/docs/build/reference/spdembed-embed-sample-profile-database.md new file mode 100644 index 00000000000..db91e8359f1 --- /dev/null +++ b/docs/build/reference/spdembed-embed-sample-profile-database.md @@ -0,0 +1,41 @@ +--- +title: "/SPDEMBED (Embed Sample Profile Database)" +description: "Learn more about: /SPDEMBED (Embed Sample Profile Database)" +ms.date: 05/05/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["/SPDEMBED linker option", "-SPDEMBED linker option", "sample profile-guided optimization, /SPDEMBED"] +--- +# /SPDEMBED (Embed Sample Profile Database) + +Embeds the Sample Profile Database (SPD) data into the Program Database (PDB) file during a Sample Profile-Guided Optimization (SPGO) build. + +## Syntax + +> **/SPDEMBED** + +## Remarks + +When you build with [`/SPDIN`](spdin-use-sample-profile-database.md), the linker uses the profile data in the SPD file to make optimization decisions. Use `/SPDEMBED` together with `/SPGO` to embed the SPD data into the PDB file produced by the build. Embedding the SPD in the PDB keeps the profile data together with the debug symbols, which simplifies distribution and archiving of build artifacts. + +To extract an SPD file that you embedded in a PDB, use [`SPDConvert /extract`](../spdconvert.md). + +For more information about the SPGO workflow, see [Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md). + +### To set this linker option in the Visual Studio development environment + +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). +1. Select the **Configuration Properties** > **Linker** > **Command Line** property page. +1. Add `/SPDEMBED` to the **Additional Options** box. Choose **OK** to save your changes. + +### To set this linker option programmatically + +- See . + +## See also + +[MSVC linker reference](linking.md)\ +[MSVC Linker Options](linker-options.md)\ +[/SPD (Specify Sample Profile Database)](spd-specify-sample-profile-database.md)\ +[/SPDIN (Use Sample Profile Database)](spdin-use-sample-profile-database.md)\ +[/SPGO (Enable Sample Profile-Guided Optimization)](spgo-enable-sample-profile-guided-optimization.md)\ +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md) \ No newline at end of file diff --git a/docs/build/reference/spdin-use-sample-profile-database.md b/docs/build/reference/spdin-use-sample-profile-database.md new file mode 100644 index 00000000000..b8ba7989923 --- /dev/null +++ b/docs/build/reference/spdin-use-sample-profile-database.md @@ -0,0 +1,52 @@ +--- +title: "/SPDIN (Use Sample Profile Database)" +description: "Learn more about linker option: /SPDIN (Use Sample Profile Database)" +ms.date: 05/05/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["/SPDIN linker option", "-SPDIN linker option", "sample profile-guided optimization, /SPDIN"] +--- +# /SPDIN (Use Sample Profile Database) + +Specifies a Sample Profile Database (SPD) file that contains profiling data for use in a Sample Profile-Guided Optimization (SPGO) build. +Also used to override the default or file specified with `/SPD` for reading the sample profile database. + +## Syntax + +> **/SPDIN:**_filename_ + +## Argument + +`filename`\ +Specifies the path to the `.spd` file that contains the profiling data to use for optimization. When expanded, the fully qualified path must not exceed `MAX_PATH` (260 characters).\ +If the file doesn't exist, the linker creates an empty file that will be used to collect data. + +## Remarks + +After collecting a performance trace by using `xperf`, converting it by using [`SPTAggregate`](../sptaggregate.md), and importing the data into an SPD file by using [`SPDConvert`](../spdconvert.md), use `/SPDIN` and [`/SPGO`](spgo-enable-sample-profile-guided-optimization.md) to produce an optimized binary. + +The GUID and age of the binary recorded in the SPD file must match the SPT file. If they don't match, you may see a "SPD version incompatible" error. To diagnose this error, use [`SPTDump /progid`](../sptdump.md) to inspect the binary identifiers in the SPT file, and [`SPDDump /header`](../spddump.md) to inspect the SPD file. The linker uses a valid SPD file to the extent possible. Minor updates to the code that don't alter the program's control flow are tolerated. Unchanged functions also use the data for optimization. If you provide a valid, but otherwise unrelated SPD, the process works, but likely no data is usable for optimization. + +Use [`/SPDEMBED`](spdembed-embed-sample-profile-database.md) together with `/SPGO` to embed the SPD data into the PDB file produced by the build. + +Use [`/SPD`](spd-specify-sample-profile-database.md) to specify a nondefault name or location for the SPD file. `/SPDIN` overrides this option, if specified. + +For more information about the SPGO workflow, see [Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md). + +### To set this linker option in the Visual Studio development environment + +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). +1. Select the **Configuration Properties** > **Linker** > **Command Line** property page. +1. Add `/SPDIN:filename` to the **Additional Options** box. Choose **OK** to save your changes. + +### To set this linker option programmatically + +- See . + +## See also + +[MSVC linker reference](linking.md)\ +[MSVC Linker Options](linker-options.md)\ +[/SPD (Specify Sample Profile Database)](spd-specify-sample-profile-database.md)\ +[/SPDEMBED (Embed Sample Profile Database)](spdembed-embed-sample-profile-database.md)\ +[/SPGO (Enable Sample Profile-Guided Optimization)](spgo-enable-sample-profile-guided-optimization.md)\ +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md) \ No newline at end of file diff --git a/docs/build/reference/spgo-enable-sample-profile-guided-optimization.md b/docs/build/reference/spgo-enable-sample-profile-guided-optimization.md new file mode 100644 index 00000000000..e2eeaa48ed2 --- /dev/null +++ b/docs/build/reference/spgo-enable-sample-profile-guided-optimization.md @@ -0,0 +1,51 @@ +--- +title: "/SPGO (Enable Sample Profile-Guided Optimization)" +description: "Learn more about: /SPGO (Enable Sample Profile-Guided Optimization)" +ms.date: 05/05/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["/SPGO linker option", "-SPGO linker option", "sample profile-guided optimization, /SPGO"] +--- +# /SPGO (Enable Sample Profile-Guided Optimization) + +Enables Sample Profile-Guided Optimization (SPGO) and creates an empty Sample Profile Database (SPD) file alongside the output binary. + +## Syntax + +> **/SPGO** + +## Remarks + +The `/SPGO` linker option starts the SPGO workflow. It directs the linker to create an empty `.spd` file that acts as a placeholder for profiling data. After building with `/SPGO`, you collect a performance trace by using `xperf`, convert it to an SPT file by using [`SPTAggregate`](../sptaggregate.md), and then import the data into the SPD file by using [`SPDConvert`](../spdconvert.md). Once the SPD file contains profile data, rebuild by using the SPD file to produce an optimized binary. The compiler and linker look for an SPD input file, either default or specified by [`/SPD`](spd-specify-sample-profile-database.md). The [/SPDIN (Use Sample Profile Database)](spdin-use-sample-profile-database.md) option is available as a convenience when the input file is over-written and that isn't desirable. + +When you build by using `/SPGO` but the SPD file contains no profile data yet, you see a message such as: + +``` +Result: SPD .spd does not contain sample profile, compiling without profile guided optimizations +``` + +This message is expected on the first build and indicates that the SPD file is ready to receive profiling data. + +By default, the build process creates the SPD file with the same base name as the output file in the directory from which the link was invoked. Use [`/SPD`](spd-specify-sample-profile-database.md) to specify a different name or location. + +Use [`/SPDEMBED`](spdembed-embed-sample-profile-database.md) to embed the SPD data into the PDB file after profile data is collected. Ensure that the linker is producing a PDB file by specifying the `/DEBUG` option. + +For more information about the SPGO workflow, see [Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md). + +### To set this linker option in the Visual Studio development environment + +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). +1. Select the **Configuration Properties** > **Linker** > **Command Line** property page. +1. Add `/SPGO` to the **Additional Options** box. Choose **OK** to save your changes. + +### To set this linker option programmatically + +- See . + +## See also + +[MSVC linker reference](linking.md)\ +[MSVC Linker Options](linker-options.md)\ +[/SPD (Specify Sample Profile Database)](spd-specify-sample-profile-database.md)\ +[/SPDEMBED (Embed Sample Profile Database)](spdembed-embed-sample-profile-database.md)\ +[/SPDIN (Use Sample Profile Database)](spdin-use-sample-profile-database.md)\ +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](../sample-profile-guided-optimization.md) \ No newline at end of file diff --git a/docs/build/reference/volatile.md b/docs/build/reference/volatile.md index fb3cced8479..4f133333193 100644 --- a/docs/build/reference/volatile.md +++ b/docs/build/reference/volatile.md @@ -1,13 +1,13 @@ --- description: "Learn more about: /volatileMetadata" title: "/volatileMetadata (Generate metadata on volatile memory accesses)" -ms.date: 5/30/2024 +ms.date: 04/27/2026 f1_keywords: ["/volatileMetadata"] helpviewer_keywords: ["/volatileMetadata", "-volatileMetadata compiler option", "/volatileMetadata compiler option", "volatileMetadata"] --- # `/volatileMetadata` (Generate metadata on volatile memory accesses) -Generate metadata for volatile memory accesses to improve performance when running x64 code on ARM64. +Generate metadata for volatile memory accesses to improve performance when running x64 or x86 code on ARM64. ## Syntax @@ -15,20 +15,14 @@ Generate metadata for volatile memory accesses to improve performance when runni /volatileMetadata[-] ``` -## Arguments - -**`-`**\ -Turns off `/volatileMetadata`. This may result in worse performance when your code runs in emulation mode on ARM64 because the emulator pessimistically assumes that every load/store needs a barrier. - ## Remarks -Starting with Visual Studio 2019 16.10, `/volatileMetadata` is on by default when generating x64 code. It improves the emulation performance of x64 code on ARM64 by generating metadata that identifies volatile memory addresses. An emulator can use this metadata to improve performance by not using acquire/release semantics on those accesses it knows aren't volatile. Without this metadata, the emulator assumes that all addresses are volatile and uses acquire and release semantics. +Starting with Visual Studio 2022 18.6, `/volatileMetadata` is off by default and must be explicitly enabled. To explicitly disable it, use `/volatileMetadata-`. `/volatileMetadata` improves the emulation performance of x64 and x86 code on ARM64 by generating metadata that identifies volatile memory addresses. An emulator can use this metadata to improve performance by not using acquire/release semantics on those accesses it knows aren't volatile. Without this metadata, the emulator assumes that all addresses are volatile and uses acquire and release semantics. One side effect of `/volatileMetadata` is you may see `npad` macros used in the generated code. This macro expands to a specified number of `NOP` instructions that create an address to associate with a memory barrier. That address is then recorded in the metadata to indicate that acquire/release semantics should be used to access it. -`/volatileMetadata` is ignored when targeting x86. - -`/volatileMetadata` can be disabled by using `/volatileMetadata-`. +> [!NOTE] +> In Visual Studio 2019 version 16.10 through Visual Studio 2022, `/volatileMetadata` was on by default. Starting with Visual Studio 2022 18.6, `/volatileMetadata` is off by default. ## Requirements diff --git a/docs/build/reference/zc-conformance.md b/docs/build/reference/zc-conformance.md index 77534192bb9..b2d72372b20 100644 --- a/docs/build/reference/zc-conformance.md +++ b/docs/build/reference/zc-conformance.md @@ -16,7 +16,7 @@ You may set multiple **`/Zc`** options separated by commas in a single **`/Zc`** ## Remarks -When Visual Studio has implemented an extension to C or C++ that is incompatible with the standard, you can use a **`/Zc`** conformance option to specify standard-conforming or Microsoft-specific behavior. For some options, the Microsoft-specific behavior is the default, to prevent large-scale breaking changes to existing code. In other cases, the default is the standard behavior, where improvements in security, performance, or compatibility outweigh the costs of breaking changes. The default setting of each conformance option may change in newer versions of Visual Studio. For more information about each conformance option, see the article for the specific option. The [`/permissive-`](permissive-standards-conformance.md) compiler option implicitly sets the conformance options that aren't set by default to their conforming settings. +When Visual Studio implements an extension to C or C++ that's incompatible with the standard, you can use a **`/Zc`** conformance option to specify standard-conforming or Microsoft-specific behavior. For some options, the Microsoft-specific behavior is the default, to prevent large-scale breaking changes to existing code. In other cases, the default is the standard behavior, where improvements in security, performance, or compatibility outweigh the costs of breaking changes. The default setting of each conformance option may change in newer versions of Visual Studio. For more information about each conformance option, see the article for the specific option. The [`/permissive-`](permissive-standards-conformance.md) compiler option implicitly sets the conformance options that aren't set by default to their conforming settings. Here are the **`/Zc`** compiler options: @@ -27,7 +27,7 @@ Here are the **`/Zc`** compiler options: | [`/Zc:alignedNew[-]`](zc-alignednew.md) | Enable C++17 over-aligned dynamic allocation. Off by default unless **`/std:c++17`** or later is specified. | | [`/Zc:auto[-]`](zc-auto-deduce-variable-type.md) | Enforce the new Standard C++ meaning for **`auto`**. On by default. | | [`/Zc:char8_t[-]`](zc-char8-t.md) | Enable or disable C++20 native `u8` literal support as `const char8_t`. Off by default unless **`/std:c++20`** or later is specified. | -| [`/Zc:checkGwOdr[-]`](zc-check-gwodr.md) | Enforce Standard C++ ODR violations under `/Gw`. | +| [`/Zc:checkGwOdr[-]`](zc-check-gwodr.md) | Enforce Standard C++ One-Definition-Rule (ODR) violations under `/Gw`. | | [`/Zc:enumTypes[-]`](zc-enumtypes.md) | Enable Standard C++ rules for `enum` type deduction. Off by default. | | [`/Zc:externC[-]`](zc-externc.md) | Enforce Standard C++ rules for `extern "C"` functions. Off by default unless **`/permissive-`** is specified. | | [`/Zc:externConstexpr[-]`](zc-externconstexpr.md) | Enable external linkage for **`constexpr`** variables. Off by default unless **`/permissive-`** is specified. | @@ -40,7 +40,7 @@ Here are the **`/Zc`** compiler options: | [`/Zc:noexceptTypes[-]`](zc-noexcepttypes.md) | Enforce C++17 **`noexcept`** rules. Off by default unless **`/std:c++17`** or later is specified. | | [`/Zc:nrvo[-]`](zc-nrvo.md) | Enable optional copy and move elisions. Off by default unless **`/O2`**, **`/permissive-`**, or **`/std:c++20`** or later is specified. | | [`/Zc:preprocessor[-]`](zc-preprocessor.md) | Use the new conforming preprocessor. Off by default unless **`/std:c11`** or later is specified. | -| [`/Zc:referenceBinding[-]`](zc-referencebinding-enforce-reference-binding-rules.md) | A UDT temporary won't bind to a nonconst lvalue reference. Off by default unless **`/permissive-`** is specified. | +| [`/Zc:referenceBinding[-]`](zc-referencebinding-enforce-reference-binding-rules.md) | A temporary value of a user-defined type dosen't bind to a nonconst lvalue reference. Off by default unless **`/permissive-`** is specified. | | [`/Zc:rvalueCast[-]`](zc-rvaluecast-enforce-type-conversion-rules.md) | Enforce Standard C++ explicit type conversion rules. Off by default unless **`/permissive-`** is specified. | | [`/Zc:sizedDealloc[-]`](zc-sizeddealloc-enable-global-sized-dealloc-functions.md) | Enable C++14 global sized deallocation functions. On by default. | | [`/Zc:strictStrings[-]`](zc-strictstrings-disable-string-literal-type-conversion.md) | Disable string-literal to `char*` or `wchar_t*` conversion. Off by default unless **`/permissive-`** is specified. | @@ -52,8 +52,9 @@ Here are the **`/Zc`** compiler options: | [`/Zc:tlsGuards[-]`](zc-tlsguards.md) | Generate runtime checks for TLS variable initialization. On by default. | | [`/Zc:trigraphs[-]`](zc-trigraphs-trigraphs-substitution.md) | Enable trigraphs (obsolete, off by default). | | [`/Zc:twoPhase-`](zc-twophase.md) | Use nonconforming template parsing behavior (only applicable when **`/permissive-`** is specified, which defaults to conforming). | +| [`/Zc:u8EscapeEncoding[-]`](zc-u8escapeencoding.md) | Encode integer escape sequences in u8 string literals as-is instead of as utf-8 characters. Off by default. | | [`/Zc:wchar_t[-]`](zc-wchar-t-wchar-t-is-native-type.md) | **`wchar_t`** is a native type, not a typedef. On by default. | -| [`/Zc:zeroSizeArrayNew[-]`](zc-zerosizearraynew.md) | Call member `new`/`delete` for 0-size arrays of objects. On by default. | +| [`/Zc:zeroSizeArrayNew[-]`](zc-zerosizearraynew.md) | Call member `new`/`delete` for `0`-size arrays of objects. On by default. | For more information about conformance issues in MSVC, see [Nonstandard behavior](../../cpp/nonstandard-behavior.md). diff --git a/docs/build/reference/zc-u8escapeencoding.md b/docs/build/reference/zc-u8escapeencoding.md new file mode 100644 index 00000000000..361f7210eea --- /dev/null +++ b/docs/build/reference/zc-u8escapeencoding.md @@ -0,0 +1,53 @@ +--- +title: /Zc:u8EscapeEncoding (numeric escape sequence encoding in u8 strings) +description: "Learn more about the compiler option /Zc:u8EscapeEncoding (numeric escape sequence encoding in u8 strings)" +author: Rastaban +ms.author: philc +ms.service: visual-cpp +ms.topic: article +ms.date: 06/01/2026 +ms.subservice: cpp-lang +--- +# `/Zc:u8EscapeEncoding` (numeric escape sequence encoding in u8 strings) + +Keep the value of numeric escape sequences in `u8` string literals without encoding them as utf-8. + +Use this switch to increase cross compatibility or when a non-utf-8 character is embedded in an utf-8 string literal. + +## Syntax + +> **/Zc:u8EscapeEncoding**[**-**] + +## Remarks + +In C++, `u8` string literals are utf-8 encoded sequences of `char8_t`. This flag changes the way numeric escape sequences are interpreted in `u8` string literals. The behavior under `/Zc:u8EscapeEncoding` is to encode them in the string as a single 8-bit `char8_t` value. The behavior under `/Zc:u8EscapeEncoding-` is to interpret the value as a unicode code point. When the value is a higher code point in Unicode, it's encoded as a multibyte character. The behavior of universal-character sequences is always to encode them as utf-8 independent of `/Zc:u8EscapeEncoding[-]`. + +The following example contains both a hex escape sequence \\__x__ and a universal escape sequence \\__u__. `/Zc:u8EscapeEncoding[-]` affects the encoding of the hex escape sequence, but the universal escape sequence is always encoded as utf-8. The example string also includes the space character, which is encoded as `0x20` in utf-8. + +```cpp +#include +int main() +{ + const char8_t str[] = u8" \x00ff \u00ff "; + for(char8_t c : str) { + printf("0x%X ", c); + } + return 0; +} +``` + +Under `/Zc:u8EscapeEncoding`, the escape sequence `\x00ff` is encoded as `0xFF` and the universal-character sequence `\u00ff` is encoded as the utf-8 sequence `0xC3 0xBF`. The code example outputs: + +```output +0x20 0xFF 0x20 0xC3 0xBF 0x20 0x0 +``` + +Under `/Zc:u8EscapeEncoding-`, the values of both `\x00ff` and `\u00ff` are re-encoded as the utf-8 sequence `0xC3 0xBF`. The code example outputs: + +```output +0x20 0xC3 0xBF 0x20 0xC3 0xBF 0x20 0x0 +``` + +## See also + +[/Zc (Conformance)](zc-conformance.md) diff --git a/docs/build/reference/zh.md b/docs/build/reference/zh.md index 3cefaf8e712..3cfa06349a0 100644 --- a/docs/build/reference/zh.md +++ b/docs/build/reference/zh.md @@ -1,20 +1,37 @@ --- title: "/ZH (Hash algorithm for calculation of file checksum in debug info)" -description: "Use the /ZH compiler option to enable MD5, SHA-1, or SHA-256 source file checksums in debug info" -ms.date: 02/01/2022 -f1_keywords: ["/ZH", "/ZH:MD5", "/ZH:SHA1", "/ZH:SHA_256"] -helpviewer_keywords: ["/ZH", "/ZH:MD5", "/ZH:SHA1", "/ZH:SHA_256", "/ZH compiler option", "/ZH:MD5 compiler option", "/ZH:SHA1 compiler option", "/ZH:SHA_256 compiler option", "Hash algorithm for file checksum in debug info"] +description: "Use the /ZH compiler option to enable source file checksums in debug info" +ms.date: 05/25/2026 +f1_keywords: ["/ZH", "/ZH:MD5", "/ZH:SHA1", "/ZH:SHA_256", "/ZH:SHA384", "/ZH:SHA512"] +helpviewer_keywords: ["/ZH", "/ZH:MD5", "/ZH:SHA1", "/ZH:SHA_256", "/ZH:SHA384", "/ZH:SHA512", "/ZH compiler option", "/ZH:MD5 compiler option", "/ZH:SHA1 compiler option", "/ZH:SHA_256 compiler option", "/ZH:SHA384 compiler option", "/ZH:SHA512 compiler option", "Hash algorithm for file checksum in debug info"] --- # `/ZH` (Hash algorithm for calculation of file checksum in debug info) Specifies which cryptographic hash algorithm to use to generate a checksum of each source file. +> [!NOTE] +> The **`/ZH`** option is available in Visual Studio 2019 version 16.4 and later. + ## Syntax +::: moniker range="<=msvc-170" + > **`/ZH:MD5`**\ > **`/ZH:SHA1`**\ > **`/ZH:SHA_256`** +::: moniker-end + +::: moniker range=">=msvc-180" + +> **`/ZH:MD5`**\ +> **`/ZH:SHA1`**\ +> **`/ZH:SHA_256`**\ +> **`/ZH:SHA384`**\ +> **`/ZH:SHA512`** + +::: moniker-end + ## Arguments **`/ZH:MD5`**\ @@ -26,15 +43,36 @@ Use an SHA-1 hash for the checksum. **`/ZH:SHA_256`**\ Use an SHA-256 hash for the checksum. This option is the default in Visual Studio 2022 version 17.0 and later. +::: moniker range=">=msvc-180" + +**`/ZH:SHA384`**\ +Use an SHA-384 hash for the checksum. + +**`/ZH:SHA512`**\ +Use an SHA-512 hash for the checksum. + +::: moniker-end + ## Remarks -PDB files store a checksum for each source file, compiled into the object code in the associated executable. The checksum allows the debugger to verify that the source code it loads matches the executable. The compiler and debugger support MD5, SHA-1, and SHA-256 hash algorithms. By default, in Visual Studio 2019 the compiler uses an MD5 hash to generate the checksum. To specify this hash algorithm explicitly, use the **`/ZH:MD5`** option. +::: moniker range="<=msvc-170" -Because of a risk of collision problems in MD5 and SHA-1, Microsoft recommends you use the **`/ZH:SHA_256`** option. The SHA-256 hash might result in a small increase in compile times. The **`/ZH:SHA_256`** option is the default in Visual Studio 2022 version 17.0 and later. +PDB files store a checksum for each source file, compiled into the object code in the associated executable. The checksum allows the debugger to verify that the source code it loads matches the executable. The compiler and debugger support MD5, SHA-1, and SHA-256 hash algorithms. +Because of a risk of collision problems in MD5 and SHA-1, use the **`/ZH:SHA_256`** option or stronger. -When more than one **`/ZH`** option is specified, the last option is used. +::: moniker-end + +::: moniker range=">=msvc-180" + +PDB files store a checksum for each source file, compiled into the object code in the associated executable. The checksum allows the debugger to verify that the source code it loads matches the executable. The compiler and debugger support MD5, SHA-1, SHA-256, SHA-384, and SHA-512 hash algorithms. +Because of a risk of collision problems in MD5 and SHA-1, use the **`/ZH:SHA_256`** option or a stronger algorithm. SHA-384 and SHA-512 provide stronger checksums, but they can increase compile time. -The **`/ZH`** option is available in Visual Studio 2019 version 16.4 and later. +> [!NOTE] +> The **`/ZH:SHA384`** and **`/ZH:SHA512`** options aren't supported for IFC (module interface) files. If you compile modules with one of these options, the compiler emits [fatal error C1029](../../error-messages/compiler-errors-1/fatal-error-c1029.md). Use **`/ZH:SHA_256`** or a smaller hash algorithm when you compile C++ modules. + +::: moniker-end + +When more than one **`/ZH`** option is specified, the last option is used. ### To set this compiler option in the Visual Studio development environment @@ -44,9 +82,20 @@ The **`/ZH`** option is available in Visual Studio 2019 version 16.4 and later. 1. Select the **Configuration Properties** > **C/C++** > **Command Line** property page. +::: moniker range=">=msvc-180" + +1. Modify the **Additional options** property to add a **`/ZH:MD5`**, **`/ZH:SHA1`**, **`/ZH:SHA_256`**, **`/ZH:SHA384`**, or **`/ZH:SHA512`** option, and then choose **OK**. + +::: moniker-end + +::: moniker range=">=msvc-160 <=msvc-170" + 1. Modify the **Additional options** property to add a **`/ZH:MD5`**, **`/ZH:SHA1`**, or **`/ZH:SHA_256`** option, and then choose **OK**. +::: moniker-end + ## See also [Compiler options](compiler-options.md)\ +[Debug Interface Access SDK - IDiaSourceFile::get_checksumType](/visualstudio/debugger/debug-interface-access/idiasourcefile-get-checksumtype)\ [Source server](/windows/win32/debug/source-server-and-source-indexing) diff --git a/docs/build/sample-profile-guided-optimization.md b/docs/build/sample-profile-guided-optimization.md new file mode 100644 index 00000000000..9a9b7babe60 --- /dev/null +++ b/docs/build/sample-profile-guided-optimization.md @@ -0,0 +1,715 @@ +--- +description: "Learn how to use Sample Profile-Guided Optimization (SPGO) to improve the performance of C and C++ applications." +title: "Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve C++ performance" +ms.date: 05/20/2026 +ms.topic: tutorial +ai-usage: ai-assisted +helpviewer_keywords: ["SPGO", "sample profile-guided optimization", "profiling, SPGO", "SPDConvert", "SPTAggregate"] +--- +# Use Sample Profile Guided Optimization (SPGO) to improve C++ performance + +Profile-Guided Optimization (PGO) uses runtime data to help the compiler make better optimization decisions. By using execution profile data collected from representative workloads, PGO enables the compiler to make smarter decisions about inlining, code layout, and hot/cold code separation. These decisions are impossible to make from static analysis alone. + +SPGO takes a different approach. Instead of instrumenting your binary and running it through synthetic training scenarios, SPGO uses hardware performance counter sampling collected from your actual release binaries. Modern processors provide hardware sampling capabilities. You can collect these samples with negligible runtime overhead, making it practical to gather runtime profiles directly from production code. + +Because SPGO profiles release bits instead of instrumented builds, it enables much more flexibility in where and how you collect data. You can gather runtime profiles from production servers, developer machines, performance labs, or any combination. The result is a binary that runs hot paths more efficiently, with a typical performance speedup of 5-15% depending on the quality of the profile data. + +For more information about Sample Profile‑Guided Optimization (PGO) in MSVC and how it improves performance using sampling‑based profiling, see [Introducing Sample Profile Guided Optimization in MSVC](https://devblogs.microsoft.com/cppblog/introducing-sample-profile-guided-optimization-in-msvc/) + +In this tutorial, you walk through the complete SPGO workflow: build a sample app, profile it by using `xperf`, prepare the profile data, and rebuild with the profile data. When you finish, you can apply the same process to your own projects. + +## Prerequisites + +Before you start, make sure you have the following software and hardware. + +### Software + +- **MSVC build tools for x64/x86/ARM64 v14.51 or later**—Install them through the Visual Studio Installer. Under **Individual Components**, search for "MSVC build tools." +- **Windows Performance Toolkit (xperf.exe)**—The `xperf` profiler collects sample data during your program's execution. Download the Windows Assessment and Deployment Kit (ADK) from [ADK install](/windows-hardware/get-started/adk-install). When you run the ADK installer, select the **Windows Performance Toolkit** component to get `xperf`. You don't need to install the full ADK. +- **War and Peace text file**—Used as the sample workload to generate profiling data. Download it from Project Gutenberg: [https://www.gutenberg.org/ebooks/2600](https://www.gutenberg.org/ebooks/2600). Save it as a plain text file in your working directory. + +### Hardware requirements + +The tutorial has three profiling paths. Which path you use depends on your hardware. You run detection commands in [Choose your profiling method](#choose-your-profiling-method) to find out which path your machine supports. For now, use this table to confirm you meet at least one of the requirements. + +| Path | CPU requirement | Notes | +|------|----------------|-------| +| **LBR** (best results) | Last Branch Records (LBR) are performance counters provided on Intel Haswell CPUs (4th gen Core, 2013) or later; AMD Zen 4 (2022) or later, ARM64 ARMv9.2-A (2020) or later | Provides the best branch data. For more information about LBR, see [An introduction to last branch records](https://lwn.net/Articles/680985/) | +| **PMC/IP mode** (good results) | Performance Monitoring Counters (PMC) are supported on any x64 CPU with a performance monitoring unit (PMU) | Works on most modern CPUs where LBR is unavailable. For more information about PMC, see [Recording Hardware Performance (PMU) Events](/windows-hardware/test/wpt/recording-pmu-events) and [Recording Hardware Performance (PMU) Events with Complete Examples](https://devblogs.microsoft.com/performance-diagnostics/recording-hardware-performance-pmu-events-with-complete-examples/#configuring-extended-pmu-counter-configurations5) | +| **OS timer** (works everywhere) | Any x64 or ARM64 CPU, including Azure VMs and virtual machines | Lower-fidelity samples, but always available | + +Most developers on modern x64 desktop hardware have LBR support. VMs and some older hardware have PMC or an OS timer. + +## How SPGO works + +SPGO collects profile data from your running binary and feeds it back to the compiler when you next build. The compiler uses that data to make better decisions about inlining, code layout, and branch prediction. A convenience is that no instrumentation is required. + +The workflow is: + +1. Build your binary with the [/spgo](./reference/spgo-enable-sample-profile-guided-optimization.md) linker flag. This step creates an empty **sample profile database** (`.spd` file). +1. Profile the binary by using `xperf` to produce an ETL trace file. +1. Convert the ETL to an **SPT** file by using [`SPTAggregate.exe`](sptaggregate.md), then convert the SPT to an **SPD** file by using [`SPDConvert.exe`](spdconvert.md). +1. Rebuild with the [/spdin](./reference/spdin-use-sample-profile-database.md) linker flag pointing to the populated sample profile database (SPD). The linker applies SPGO optimizations. + +The optimizer uses the SPD to answer questions like: which branches are taken most often? Which functions are called in hot loops? This process produces better code layout and inlining decisions than static analysis alone. + +SPGO works with both C and C++. The workflow and flags are identical for both languages. + +**Best candidates for SPGO:** Large, branch-filled C/C++ applications with tight inner loops. Gains scale with codebase size and branch complexity. The small sample in this tutorial shows around 7% improvement. Larger production codebases often see more improvement. + +## Build Process Comparison + +This section covers how SPGO fits into the build pipeline if you want to understand the mechanics. + +### Normal build process + +In a standard C/C++ release build: + +- **Inputs:** Source code files (`.cpp`, `.h`) and release-mode compiler flags (`/O2`, `/GL`, and so on). +- **Process:** The compiler applies standard optimizations such as inlining heuristics, branch prediction assumptions, and code layout decisions based on static analysis alone. It has no data about how the program actually behaves when it runs. +- **Output:** Executable (`.exe`), DLL files (`.dll`), debug information (`.pdb`). + +:::image type="content" source="media/normal-build-process.png" alt-text="Diagram of the normal release build process showing source code files and example compiler switch /GL as inputs flowing to a build step, which produces .exe, .dll, and .pdb outputs." lightbox="media/normal-build-process.png"::: + +Without runtime data, hot paths and cold paths receive similar treatment. + +### SPGO-enabled build process + +SPGO adds profiling data as a new input to the build pipeline: + +- **Inputs:** Source code, the `.spd` profile file (sample counts from a profiling run), release-mode compiler flags, `/link /spgo`, and `/spdin:` to specify an input SPD file (if not specified, defaults to a .spd using the binary name and located in the obj folder). +- **Process:** The linker reads the SPD alongside the intermediate code. It uses branch-frequency data to make better inlining, code layout, and branch-ordering decisions. Hot functions get laid out for fast access; cold code moves out of the critical path. +- **Output:** Optimized executable (`.exe`), optimized DLL files (`.dll`), debug information (`.pdb`), **and a new `.spd` file** for future profiling iterations. + +:::image type="content" source="media/sample-profile-guided-optimization-build-process.png" alt-text="Diagram of the SPGO-enabled build process showing source code and profile data files (.spd) as inputs to the build step with an additional linker switch /spgo. The build process outputs optimized .exe, .dll, debug information (.pdb), and new profile data files (.spd)." lightbox="media/sample-profile-guided-optimization-build-process.png"::: + +The key insight: SPGO moves optimization decisions from compiler and linker heuristics to data-driven choices based on real execution. + +### Key flags + +| Flag | Type | Purpose | +|------|------|---------| +| [`/spgo`](./reference/spgo-enable-sample-profile-guided-optimization.md) | Linker | Enables SPGO. Embeds SPGO metadata in the binary and creates an empty `.spd` output file unless `/spdin` is specified, in which case the specified `.spd` file is used as input. | +| [`/spdin:`](./reference/spdin-use-sample-profile-database.md) | Linker | Input SPD - provides profile data to the linker for optimization | +| [`/spd:`](./reference/spd-specify-sample-profile-database.md) | Linker | Output SPD path - specifies where the new SPD is written (optional; defaults to the same directory as the binary). Serves as the input SPD path if `/spdin` isn't specified. | +| [`/GL`](./reference/gl-whole-program-optimization.md) | Compiler | Whole-program optimization-required for SPGO to work across translation units | +| [`/O1`, `/O2` (Minimize Size, Maximize Speed)](./reference/o1-o2-minimize-size-maximize-speed.md) | Compiler | Optimize for speed; enables aggressive optimizations that SPGO can enhance | + +### How SPGO differs from PGO + +PGO (Profile-Guided Optimization) requires you to compile your binary with instrumentation flags (`/GENPROFILE`), run the slower instrumented binary to collect `.pgc` execution count files, then relink with `/USEPROFILE`. The compiler gets exact execution counts but you have to instrument the code first. For more information about this process, see [Profile-guided optimizations](profile-guided-optimizations.md). + +SPGO uses hardware CPU performance counters to collect statistical samples from your uninstrumented release binary. Run your existing binary, profile it by using `xperf`, convert the trace to an SPD file, and rebuild. There's no instrumented build and no slowdown during profiling. The compiler gets statistical sampling data instead of exact counts, which is less precise but easier to get and requires no code changes. It also allows profiling of system components or realtime components that are difficult to collect data for with an instrumented approach. You can also profile final/shipping binaries. + +This tutorial covers three profiling methods: LBR, PMC, and OS timer. You choose your method in [Choose your profiling method](#choose-your-profiling-method). For a detailed comparison of the normal build process versus the SPGO build process, including a flag reference table, see [Build Process Comparison](#build-process-comparison). + +## Configure `perfcore.ini` + +> **⚠️ Required:** Without this step, `xperf` doesn't provide the necessary profiling data. Complete this step before running `xperf`. + +The Windows Performance Toolkit (WPT) uses `perfcore.ini`, located if you installed the WPT in the default location at `C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\perfcore.ini`, to register the DLL providers it needs for SPGO. + +Open Windows Notepad as Administrator. Then open `perfcore.ini`. Find the DLL list section and add the following entries, one per line: + +``` +perf_lbr.dll +perf_spt.dll +perf_hv.dll +``` + +If `xperf.exe` isn't installed, see [General issues](#general-issues-all-paths) to install it. + +Save and close `perfcore.ini`. The DLL files already ship in the same directory as `xperf.exe` so you don't need to copy them anywhere. You're only registering them in `perfcore.ini`. Ensure that `xperf` is in your path. + +## Create the sample app + +The sample app for this tutorial is a C++ program that reads text from standard input and produces a line count, word count, total character count, a character frequency table, and elapsed time to process the file in milliseconds. It's written in C++, but SPGO also works with C. The workflow is identical for C projects. + +Create a file named `textCount.cpp` in your working directory and add the following source code: + +```cpp +// textCount.cpp : Text Statistics Counter +// Counts words, lines, and character frequencies from standard input +// Usage: textCount < file.txt + +#include +#include +#include +#include +#include + +int main() +{ + auto start = std::chrono::steady_clock::now(); + + std::map charFrequency; + int wordCount = 0; + int lineCount = 0; + int totalChars = 0; + + std::string line; + bool inWord = false; + + while (std::getline(std::cin, line)) + { + lineCount++; + + for (char c : line) + { + totalChars++; + unsigned char uc = static_cast(c); + charFrequency[uc]++; + + if (std::isspace(static_cast(c))) + { + inWord = false; + } + else + { + if (!inWord) + { + wordCount++; + inWord = true; + } + } + } + + inWord = false; + } + + std::cout << "\n=== TEXT STATISTICS ===" << std::endl; + std::cout << "Lines: " << lineCount << std::endl; + std::cout << "Words: " << wordCount << std::endl; + std::cout << "Total Characters: " << totalChars << std::endl; + + std::cout << "\n=== CHARACTER FREQUENCIES ===" << std::endl; + + std::cout << "\nLetters:" << std::endl; + for (unsigned char ch = 'a'; ch <= 'z'; ch++) + { + unsigned char upperCh = static_cast(std::toupper(ch)); + int count = charFrequency[ch] + charFrequency[upperCh]; + if (count > 0) + { + std::cout << static_cast(ch) << ": " << count << std::endl; + } + } + + std::cout << "\nDigits:" << std::endl; + for (unsigned char ch = '0'; ch <= '9'; ch++) + { + if (charFrequency[ch] > 0) + { + std::cout << static_cast(ch) << ": " << charFrequency[ch] << std::endl; + } + } + + std::cout << "\nSpecial Characters:" << std::endl; + for (const auto& pair : charFrequency) + { + unsigned char ch = pair.first; + if (!std::isalnum(ch)) + { + std::string displayChar; + switch (ch) + { + case ' ': displayChar = "[space]"; break; + case '\t': displayChar = "[tab]"; break; + case '\n': displayChar = "[newline]"; break; + case '\r': displayChar = "[return]"; break; + default: + if (ch >= 32 && ch < 127) + { + displayChar = std::string(1, static_cast(ch)); + } + else + { + displayChar = "[byte:" + std::to_string(static_cast(ch)) + "]"; + } + break; + } + std::cout << displayChar << ": " << pair.second << std::endl; + } + } + + auto end = std::chrono::steady_clock::now(); + + auto elapsed = std::chrono::duration(end - start); + std::cout << "Elapsed time: " << std::fixed; + std::cout.precision(3); + std::cout << elapsed.count() << " ms\n"; + + return 0; +} +``` + +## Build and run the sample to get a baseline + +Before applying SPGO, build `textCount` and run it against a large text file, such as *War and Peace* (you can download it from Project Gutenberg), to see how fast it runs. This step shows you the performance before you optimize it by using SPGO: + +**Build:** + +```cmd +cl /Zi /EHsc /GL /O2 textCount.cpp /link /debug +``` + +**Run:** + +```cmd +textCount.exe < warAndPeace.txt +``` + +You see output similar to: + +``` +=== TEXT STATISTICS === +Lines: 66041 +Words: 566333 +Total Characters: 3227531 + +=== CHARACTER FREQUENCIES === + +Letters: +a: 202719 +... + +Elapsed time: 512.000 ms +``` + +Record the `Elapsed time` value. You'll compare it to the SPGO-optimized time in [Measure the results](#measure-the-results). + +## Build textCount with /spgo + +Now build textCount with SPGO enabled. This step lays the groundwork to gather profiling data. + +```cmd +cl /Zi /EHsc /GL /O2 textCount.cpp /link /debug /spgo +``` + +When the build finishes, you see a message like: + +``` +SPD textCount.spd not found, compiling without profile guided optimizations +``` + +This message appears on the first `/spgo` build. The linker creates the SPD file but it's still empty, so it doesn't apply any SPGO optimizations yet. After you run the binary, collect profile data, and convert it to SPD, you won't see this message. + +**Flag explanations:** + +| Flag | Purpose | +|------|---------| +| `/Zi` | Generate complete debugging information. This is necessary for SPGO to map profiling samples to source code. | +| `/EHsc` | Enable C++ exception handling | +| `/GL` | Whole-program optimization — required for SPGO. Defers final optimization to link time, enabling cross-module inlining, code layout, and dead code elimination decisions. | +| `/O2` | Optimize for speed — enables aggressive inlining, loop optimization, dead code removal, and related transforms. | +| `/link /debug` | Pass `/debug` to the linker to generate debug information (`.pdb`), which xperf uses to map profiling samples to source code. | +| `/spgo` | SPGO linker flag—embeds SPGO metadata in the binary and creates an empty `textCount.spd` file alongside the executable. | + +> [!NOTE] +> `/spgo` is a linker flag. Pass it to the linker via `/link /spgo` in the `cl` command. + +The `/spgo` flag doesn't optimize the binary yet. It prepares it for profiling. The optimization happens in [Rebuild textCount with /spdin](#rebuild-textcount-with-spdin) after the SPD is populated with real runtime data. + +> [!NOTE] +> To write the SPD to a specific location, add the optional `/spd:` linker flag. For example: `/link /debug /spgo /spd:.\profiles\textCount.spd`. If you omit this flag, the SPD is created alongside the `.exe`. + +## Choose your profiling method + +SPGO supports three profiling methods. Which method you use depends on your hardware. + +### The three profiling methods + +| Method | Sample quality | Hardware requirement | Best for | +|--------|----------------|---------------------|----------| +| **LBR** (Last Branch Record) | Highest—records sequences of recently taken branches, giving the optimizer rich control-flow data per sample | Intel Haswell (2013) or later; AMD Zen 4 (2022) or later; ARM64 ARMv9.2-A (2020) or later | Most modern desktop hardware | +| **PMC / IP mode** (Performance Monitoring Counter/Instruction pointer mode) | Good. Captures instruction-pointer samples with call stacks using the CPU's Performance Monitoring Unit (PMU), collected through Event Tracing for Windows (ETW) | Any x64 or ARM64 CPU with a PMU | Hardware without LBR support | +| **OS timer** | Basic—timer-based samples | Any x64 or ARM64 CPU, VMs without PMU passthrough | VMs and older hardware | + +With PMC / IP mode, each hardware interrupt gives you just one data point: "the CPU was at address 0x1A2B3C4D when the interrupt fired". With LBR, each interrupt gives you a stack of the last 16–32 branches the CPU took before the interrupt fired. The optimizer gets better control-flow data and can make better inlining and layout decisions. + +### Detect your path + +Run the following two commands to determine which profiling path your machine supports. These commands don't require an elevated prompt. + +**Step 1: Check for LBR support. This test works on Intel/AMD/ARM64.** + +Run the following from an **administrator** Visual Studio developer command prompt: + +```cmd +xperf.exe -on PMC_PROFILE -pmcprofile TotalIssues -LastBranch PmcInterrupt -setProfInt TotalIssues 2560000 +xperf -stop -d lbrtest.etl +xperf -tle -i lbrtest.etl -a dumper | findstr "LBR, TimeStamp" +``` + +- If this command finds a line containing `LBR, TimeStamp`, then your machine supports LBR. **Use the LBR path.** +- Otherwise, continue to Step 2. + +**Step 2: Check for PMC support (no LBR)** + +```cmd +xperf.exe -pmcsources | findstr TotalIssues +``` + +- If this command produces output, then your machine supports PMC counters but not LBR. **Use the PMC path.** +- If this command produces no output, then **Use the OS timer path.** + +For more information about PMU event collection with xperf, see [Recording hardware PMU events with xperf](https://devblogs.microsoft.com/performance-diagnostics/recording-hardware-performance-pmu-events-with-complete-examples/#configuring-extended-pmu-counter-configurations5). + +### Decision table + +| `LBR, TimeStamp` output | `TotalIssues` output | Your path | +|---------------------|-----------------------------|-----------| +| Not empty | (not checked) | LBR | +| Empty | Not empty | PMC | +| Empty | Empty | OS timer | +| ARM64 processor | N/A | PMC (if PMU available) or OS timer | + +### Choose your approach + +Decide whether to use the LBR, PMC, or OS timer path based on the detection results. Each path has different `xperf` start parameters to collect the appropriate profiling data. Follow the path that matches your hardware capabilities. + +> **Your path:** +> - **LBR users** (LBR detected in Step 1): Go to [LBR path](#lbr-path). +> - **PMC users** (InstructionRetired detected in Step 2): Go to [PMC path (no LBR)](#pmc-path-no-lbr). +> - **OS timer users** (VM or hardware without PMU): Go to [OS timer path](#os-timer-path). +> +> All paths rejoin at [Run the workload and stop xperf](#run-the-workload-and-stop-xperf-all-paths). + +The commands in this section depend on the profiling path you identified in [Choose your profiling method](#choose-your-profiling-method). Find the subsection that matches your path, run the `xperf` start command, and then continue to [Run the workload and stop xperf](#run-the-workload-and-stop-xperf-all-paths) to run the workload and stop xperf. + +> **⚠️ Run as Administrator:** `xperf` requires an elevated (Administrator) developer command prompt. Without elevation, `xperf` returns `"failed to configure counters"`. + +### LBR path + +Start `xperf` with LBR collection: + +```cmd +xperf -on LOADER+PROC_THREAD+PMC_PROFILE -MinBuffers 4096 -MaxBuffers 4096 -BufferSize 4096 -pmcprofile BranchInstructionRetired -LastBranch PmcInterrupt -setProfInt BranchInstructionRetired 16384 +``` + +**Parameter explanation:** + +| Parameter | Purpose | +|-----------|---------| +| `LOADER+PROC_THREAD+PMC_PROFILE` | Kernel providers: loader events (module mapping), process/thread events (execution context), and PMC profiling events | +| `-MinBuffers 4096 -MaxBuffers 4096 -BufferSize 4096` | Large ring buffers to avoid dropped samples during a full War and Peace run | +| `-pmcprofile BranchInstructionRetired` | PMC event trigger: generate a sample on every Nth retired branch instruction | +| `-LastBranch PmcInterrupt` | Enables LBR hardware recording: on each PMC interrupt, capture the hardware last-branch record stack | +| `-setProfInt BranchInstructionRetired 16384` | Sample interval: fire an interrupt every 16,384 retired branch instructions | + +After starting xperf, continue to [Run the workload and stop xperf](#run-the-workload-and-stop-xperf-all-paths). + +### PMC path (no LBR) + +Start `xperf` with PMC / IP-mode collection: + +```cmd +xperf -on LOADER+PROC_THREAD+PMC_PROFILE+PROFILE -MinBuffers 4096 -BufferSize 4096 -pmcprofile InstructionRetired -setProfInt InstructionRetired 16384 -stackwalk profile +``` + +**Parameter explanation:** + +| Parameter | Purpose | +|-----------|---------| +| `LOADER+PROC_THREAD+PMC_PROFILE+PROFILE` | Adds `PROFILE` (CPU sampling) and `PMC_PROFILE` for PMC events; no `-LastBranch` | +| `-pmcprofile InstructionRetired` | PMC event trigger: sample on retired instructions (instruction pointer mode) | +| `-setProfInt InstructionRetired 16384` | Fire an interrupt every 16,384 retired instructions | +| `-stackwalk profile` | Capture a call stack on each profile interrupt, providing call-chain data instead of branch sequences | + +Compared to LBR: no `-LastBranch` flag; uses `InstructionRetired` instead of `BranchInstructionRetired`. The result is instruction-pointer samples with call stacks, not branch sequences. This path still provides effective data for the optimizer, but it's slightly less rich. + +After starting `xperf`, continue to [Run the workload and stop xperf](#run-the-workload-and-stop-xperf-all-paths). + +### OS timer path + +Start xperf with OS timer-based sampling: + +```cmd +xperf -on LOADER+PROC_THREAD+PROFILE -MinBuffers 4096 -BufferSize 4096 -setProfInt Timer 1221 -stackwalk profile +``` + +**Parameter explanation:** + +| Parameter | Purpose | +|-----------|---------| +| `LOADER+PROC_THREAD+PROFILE` | No PMC events; CPU sampling via OS timer interrupt only | +| `-setProfInt Timer 1221` | Fire on the OS timer interrupt every 1,221 timer ticks (approximately 1 kHz) | +| `-stackwalk profile` | Capture a call stack on each timer interrupt | + +Compared to LBR and PMC, this method doesn't use hardware performance counters. The OS timer fires at roughly fixed time intervals regardless of CPU activity. Samples are less densely correlated to hot code but still provide useful control-flow data for the optimizer. + +### Run the workload and stop xperf (all paths) + +With `xperf` running, run `textCount` against War and Peace: + +```cmd +textCount.exe < warAndPeace.txt +``` + +After `textCount` finishes, stop `xperf` and write the trace file. Letting other processes run during profiling dilutes sample quality. For best results, close unnecessary applications before running the workload. + +```cmd +xperf -stop -d textCount.etl +``` + +After stopping `xperf` (it can take a while to write out the etl file), confirm that `textCount.etl` was created in the current directory. + +## Convert the ETL file to SPT + +This step is the same for all three profiling paths. + +Run `SPTAggregate.exe` to process the raw ETL trace and create an SPT profile file: + +```cmd +SPTAggregate.exe /binary textCount.exe /etl textCount.etl textCount.spt +``` + +**Parameter explanation:** + +| Parameter | Purpose | +|-----------|---------| +| `/binary textCount.exe` | The binary to extract samples from. The ETL might contain samples from all processes that ran during profiling | +| `/etl textCount.etl` | Input ETL trace file | +| `textCount.spt` | Output SPT profile file | + +`SPTAggregate` outputs a summary that shows how many samples it collected. This summary is your first confirmation that profiling worked. + +Check the output from `SPTAggregate` against the path you took: + +- **LBR path:** Look for a nonzero Used LBR Samples count. +- **PMC path:** Look for a nonzero PMC or stack sample count. +- **OS timer path:** Look for a nonzero used stack samples count. + +If all counts are zero, see [Troubleshooting](#troubleshooting) before continuing. + +## Convert the SPT file to SPD + +> **Your path:** +> - **LBR users** (use `/mode:LBR`): [LBR mode](#lbr-mode) +> - **PMC users** (use `/mode:IP`): [IP mode (PMC and OS timer)](#ip-mode-pmc-and-os-timer) +> - **OS timer users** (use `/mode:IP`): [IP mode (PMC and OS timer)](#ip-mode-pmc-and-os-timer) +> +> Both PMC and OS timer paths use `/mode:IP` because both produce instruction-pointer samples. + +The next step branches by profiling path, specifically on the `/mode` flag passed to `SPDConvert.exe`. + +### LBR mode + +```cmd +SPDConvert.exe /mode:LBR textCount.spd textCount.spt +``` + +`/mode:LBR` tells `SPDConvert` to interpret the SPT as containing LBR branch sequence data. + +### IP mode (PMC and OS timer) + +Both PMC and OS timer produce instruction-pointer samples, so both use the same conversion command: + +```cmd +SPDConvert.exe /mode:IP textCount.spd textCount.spt +``` + +`/mode:IP` tells `SPDConvert` to interpret the SPT as containing instruction-pointer samples. + +> [!WARNING] +> Using the wrong mode for your data type can produce an empty or malformed SPD. If you profiled with LBR, use `/mode:LBR`. +> If you profiled with PMC or OS timer, use `/mode:IP`. The `SPTAggregate` summary output from [Convert the ETL file to SPT](#convert-the-etl-file-to-spt) shows which sample types were collected and confirms the correct mode to use. + +After running `SPDConvert`, confirm that `textCount.spd` was created (or updated) in the current directory. + +### Interpreting SPDConvert output + +The command `SPDConvert textCount.spd textCount.spt` prints a before-and-after block coverage summary, for example: + +``` +Block coverage (before) : 33.90% ( 4507/ 13294) +Block coverage (after) : 45.64% ( 6067/ 13294) +``` + +This summary shows the percentage of the binary's code blocks that have associated profile data. A higher percentage is better. Coverage above 70% is excellent, while coverage below 40% might limit optimization effectiveness. If coverage is low, run the profiling workload longer or combine multiple SPT files from separate runs with different workloads. For example, you could run `textCount` against multiple text files to exercise different code paths. + +You might see a warning from `SPDConvert` like the following: + +``` +Compiler may be conservative on some hot functions due to sparse sample coverage. +SPGO is estimated to optimize better if sample density is increased to 5.4x of current level. +Sample density can be increased by sampling for longer period, or increasing sample rate. +``` + +This warning means your profiling run didn't collect enough samples for the optimizer to confidently optimize all hot functions. The SPD is still usable, but you can improve results by: + +- Running the workload longer (for example, 5 or more minutes instead of 1 minute) or using different workloads. +- Lowering the `-setProfInt` value in the `xperf` command to increase the sampling rate. The tradeoff is that this change produces a larger ETL file, which takes longer to process. +- Combining multiple SPT files from separate profiling runs by passing them all to `SPDConvert`. + +The SPT file is a binary format. To inspect its contents, you can run `SPTDump.exe textCount.spt`. Similarly, `PTDump.exe textCount.spt` shows the compiled profile data after running `SPDConvert`. Both tools are useful for verifying nonzero samples before proceeding. + +## Rebuild textCount with /spdin + +Rebuild `textCount` by using the populated SPD file. The linker reads the profile data and applies SPGO optimizations. + +This step is the same for all three profiling paths. + +```cmd +cl /Zi /EHsc /GL /O2 textCount.cpp /link /debug /spgo /spdin:textCount.spd +``` + +**New flag (compared to [Build textCount with /spgo](#build-textcount-with-spgo)):** + +| Flag | Purpose | +|------|---------| +| `/spdin:textCount.spd` | Provide the SPD profile data to the linker for optimization | + +The command still includes `/spgo`. It generates a new SPD file alongside the optimized binary, which you can use as the starting point for subsequent profiling iterations. + +> [!WARNING] +> The SPD file is associated with the exact binary it profiles against. If you rebuild `textCount` without `/spdin`, or rebuild from changed source, you must generate a new SPD file. The existing one doesn't match the new binary's GUID, and the linker won't use it. + +After the rebuild with `/spdin`, the linker outputs statistics about how much of your code was optimized using profile data. For example: + +``` +221 of 221 (100.00%) profiled functions will be compiled for speed +201 of 1383 inline instances were from dead/cold paths +474 of 474 profiled functions (100.0%) were optimized using profile data +202738780 of 202738780 instructions (100.0%) were optimized using profile data +``` + +A high percentage means the SPD covers your binary well. If the percentage is low (for example, below 90%), either the profiling workload didn't exercise enough of the binary, or the binary has changed significantly since the profile was collected. In both cases, reprofile against the current binary. + +### What SPGO does with your profile data + +SPGO uses the collected sample data to populate counts on each block and edge in the program's control flow graph. These counts drive optimizations such as: +- **Profile-guided inlining**: Aggressively inline hot call sites while avoiding code bloat from inlining cold paths. +- **Hot/cold code separation**: Move rarely executed code to separate sections of the binary, improving instruction cache utilization and paging behavior. +- **Function layout**: Place functions that call each other frequently near each other in the binary, reducing page faults and improving locality. Optimized functions are organized into high affinity COFF groups in the binary. +- **Size/speed decisions**: Compile hot functions for speed and cold functions for size. Routines with no observed profile hits might be compiled for size rather than speed, limiting optimizations like inlining and loop unrolling in those cold paths. +- **Speculative devirtualization**: When sampling reveals that an indirect call consistently targets the same function, SPGO can speculate on that target and inline it, with a fallback for the uncommon case. + +## Measure the results + +Run `textCount` again and compare elapsed times. + +```cmd +textCount.exe < warAndPeace.txt +``` + +Collect multiple runs for each configuration and use the median. A single run isn't reliable because OS scheduling and system noise can skew individual measurements. + +| Build | Representative elapsed time | +|-------|-----------------------------| +| Baseline (`cl /Zi /EHsc /O2 /link /debug`) | *(your measurement)* | +| `/spgo` build (no profile data yet) | *(should be close to baseline)* | +| SPGO-optimized (`/spdin`) | *(should show improvement)* | + +In one test, SPGO using the LBR method delivered approximately 7% reduction in elapsed time. Your results might vary with your own projects because SPGO gains depend on how well the profiling workload represents typical execution. Larger, branch filled codebases tend to see more improvement within the 5–10% range. The profiling method affects optimization quality. LBR typically produces better results than PMC, which produces better results than OS timer. If you're on the OS timer path, expect smaller gains. + +The LBR path followed in this tutorial was applied to the [SQLite](https://github.com/sqlite/sqlite) project, which is a production database library. The SPGO-optimized SQLite binary showed approximately a 7% improvement. + +## Apply SPGO to your own project + +Use this checklist to apply SPGO to your own C or C++ application. + +1. **Add `/Zi /link /debug /spgo` to your existing release build command.** Modify your build script or project file: + + ```cmd + cl /Zi /EHsc /GL /O2 myapp.cpp /link /debug /spgo + ``` + +1. **Choose a representative workload.** Select a real usage scenario that exercises the hot paths of your application. Use production-like data. Avoid the following as your primary profiling workload: code coverage tests (they don't stress performance bottlenecks), uncommon error paths, startup and shutdown phases, and deprecated code paths. This workload drives the profile that feeds the optimizer. +1. **Run xperf using your detected path.** Use the path you identified in [Choose your profiling method](#choose-your-profiling-method) (LBR, PMC, or OS timer). Start `xperf`, run the workload once, stop `xperf`, and capture the ETL file. +1. For the PMC or OS timer path, **run SPTAggregate and SPDConvert with the correct `/mode` flag.** Convert ETL to SPT then to SPD. Use `/mode:LBR` for LBR data; use `/mode:IP` for PMC or OS timer data. +1. **Rebuild with `/spdin:`.** Compile your application with the populated SPD: + + ```cmd + cl /Zi /EHsc /GL /O2 yourApp.cpp /link /debug /spgo /spdin:yourApp.spd + ``` + +1. **Measure before and after.** Run your workload with both the nonoptimized and SPGO-optimized binaries. Collect the **median of multiple runs** for each configuration. A single run isn't reliable for benchmarking. +1. **Store the `.spd` file in source control.** Check the `.spd` file into your source control system alongside your source code. +1. **Enable SPGO in developer Release builds.** Have your team's Release builds use the same SPGO-optimized binaries as production. This helps catch performance regressions early. +1. Disable SPGO in Debug builds. +1. **Watch the linker's profile completeness statistics.** After each build with `/spgo`, note the percentage of profiled functions optimized using profile data. If this drops significantly (below 90%), reprofile the current binary. Code changes accumulate and the SPD can become stale. + +### Alternative to using `xperf` + +Another way to gather profile data is to use a sampling profiler like Windows Performance Recorder (WPR). WPR is installed by default on Windows 10 and later. It collects similar data to `xperf`. You can configure WPR to collect CPU samples with call stacks, and then export the data to an ETL file that you can process with `SPTAggregate` and `SPDConvert` like the `xperf` ETL. Here's an example of using WPR to collect profile data: + +```cmd +wpr -start CPU.light -filemode +textCount.exe < warAndPeace.txt +wpr -stop spgo_data.etl +``` +For more information on using WPR, see [Using Windows Performance Recorder](/windows-hardware/test/wpt/recording-pmu-events). + +### SPD distribution + +You can: + +- Check the `.spd` file directly into source control alongside your source code. +- Share the `.spd` file with teammates so they can build with SPGO optimizations without reprofiling. +- Package the `.spd` file with your binaries as a versioned artifact (for example, a NuGet package) and record which version corresponds to which binary. +- Regenerate the `.spd` file at any time by repeating the profiling workflow. + +The SPD ties to the exact binary it was built from. After significant code changes, reprofile to generate a fresh SPD. During the `/spdin` build, the compiler also produces a new `.spd` file. Save this new SPD as a build artifact - it's the starting point for your next profiling iteration. + +## Reusing SPD information across builds + +The "carry forward" concept in SPGO allows you to add profiling data to an existing SPD file without profiling all your scenarios over again from scratch and without losing existing profile information. You can also adjust how much weight to give to older profile data. This flexibility is useful when there might be behavioral changes over time and you don't want to completely lose the profiling information from earlier scenario runs. For instance, a DLL might see different APIs called as the application that calls it evolves. You still want the optimizations from how it used to behave, but want to mix in optimization opportunities for how it sometimes behaves differently now. You can evolve the profile over time by mixing old and new data. + +When you run `SPDConvert` with a new SPT file, pass the name of the existing SPD file. Then use the `/retire:N` option to control how aggressively `SPDConvert` de-emphasizes older profile data when you add new SPT files: +- The default (`/retire:8`) weights newer data more heavily. +- Use `/retire:0` to give equal weight to all runs. +- Use `/retire:16` to let only the newest data count. + +## Troubleshooting + +> **Find your issue:** +> - **LBR path problems:** [LBR path problems](#lbr-path-problems) +> - **PMC path problems:** [PMC path problems](#pmc-path-problems) +> - **OS timer problems:** [OS timer path problems](#os-timer-path-problems) +> - **Issues affecting all paths:** [General issues](#general-issues-all-paths) + +### LBR path problems + +| Problem | Likely cause | Fix | +|---------|-------------|-----| +| Zero LBR samples in `SPTAggregate` output | CPU doesn't support LBR, or VM doesn't expose LBR | Run the detection command from [Detect your path](#detect-your-path). If in a Hyper-V VM, run `Set-VMProcessor MyVMName -Perfmon @("pmu", "lbr")` on the host. If LBR isn't available, switch to the PMC or OS timer path. | +| Processor supports LBR but `SPTAggregate` shows 0 LBR samples | `perfcore.ini` DLL registration incomplete | Complete the `perfcore.ini` setup in [Configure perfcore.ini](#configure-perfcoreini). Ensure `perf_lbr.dll` is registered. | +| `SPDConvert` fails or produces an empty SPD | Wrong `/mode` flag, or SPT contains only IP-mode samples | Confirm `SPTAggregate` output showed LBR samples. If the output shows only IP-mode samples, switch to `/mode:IP`. | + +### PMC path problems + +| Problem | Likely cause | Fix | +|---------|-------------|-----| +| Zero PMC samples in `SPTAggregate` output | `perfcore.ini` DLL registration incorrect | Complete the `perfcore.ini` setup in [Configure perfcore.ini](#configure-perfcoreini). Ensure `perf_spt.dll` is registered. Without this DLL, `xperf` produces zero PMC samples without an error message.
Run `xperf.exe -pmcsources` to see the list of Performance Counters sources available on your CPU. If you don't see entries like `SPT_OP_RETIRE_INSTR` or `SPT_OP_RETIRE_BR_INSTR` or `SPT_OP_ETW_INSTR`, then the DLL registration in `perfcore.ini` might be incomplete or your CPU might not support PMC. If you can't resolve the DLL registration, try the OS timer path, instead. | +| `findstr InstructionRetired` returns output but `xperf` produces no samples | VM masking PMC counters | Check if running in a VM. Enable PMU in Hyper-V with `Set-VMProcessor`, or switch to the OS timer path. | +| `SPDConvert` fails on PMC path | Using `/mode:LBR` on an IP-only SPT | Switch to `/mode:IP`. | + +### OS timer path problems + +| Problem | Likely cause | Fix | +|---------|-------------|-----| +| Less improvement than expected | Expected - OS timer is lower fidelity | This is normal. The optimizer has less branch-flow information from timer samples than from LBR or PMC. Performance gains are smaller. Consider upgrading to PMC or LBR if hardware supports it. | +| Zero timer samples | `xperf` wasn't run in an elevated prompt, or `PROFILE` provider missing | Confirm running as Administrator. Confirm `-stackwalk profile` was provided to the `xperf` command. | + +### General issues (all paths) + +| Problem | Likely cause | Fix | +|---------|-------------|-----| +| `"failed to configure counters"` error | `xperf` not running as administrator | Restart the command prompt as **Administrator** (right-click > Run as administrator). xperf requires elevated privileges to configure hardware performance counters. | +| `xperf` not found | `xperf.exe` not on PATH | Confirm the Windows ADK is installed. Check `C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\`. Add that directory to your PATH, or run xperf from it directly. | +| `textCount.etl` not created | xperf failed silently | Confirm running as administrator. Rerun the xperf start command and check for error output. | +| `SPTAggregate` fails with "binary not found" | `textCount.exe` not in current directory or wrong path | Confirm you're in the same directory as `textCount.exe`, or provide the full path to the `/binary` parameter. | +| SPD file not created | `SPDConvert` failed | Check that `textCount.spt` size is nonzero. Run `SPTDump.exe textCount.spt` to inspect its contents. | +| `/spdin` build produces no improvement | GUID/age mismatch between SPD and binary | The SPD was built from a different `textCount.exe`. Profile the current build again to generate a fresh SPD. | +| MSVC version error on `/spgo` | MSVC toolset earlier than v14.51 | Open the Visual Studio Installer > **Individual Components** > install **MSVC v14.51** or later. Reopen the Developer Command Prompt. | + +## Next steps + +After completing this tutorial, explore these capabilities to get more from SPGO: + +- **Profile blending:** Run multiple workloads, accumulate SPT files from each run, and pass all of them to `SPDConvert`. A blended SPD reflects the full range of real usage patterns and produces better optimizations than a single-scenario profile. Use the `/retire:N` option to control how aggressively `SPDConvert` de-emphasizes older profile data when you add new SPT files. The default (`/retire:8`) weights newer data more heavily. Use `/retire:0` to give equal weight to all runs; use `/retire:16` to let only the newest data count. +- The best results come from blending profiles from multiple sources such as benchmarks that stress key scenarios plus real-world data (where available). Pass SPT files from all sources to `SPDConvert`. Repeat an SPT file in the argument list to give it more weight (for example, `SPDConvert myapp.spd critical.spt critical.spt common.spt` weights `critical.spt` twice as heavily as `common.spt`). +- **Iterative optimization:** Each rebuild with `/spdin` produces a new SPD. You can repeat the run, profile, rebuild cycle. Later iterations might show diminishing returns, but a second pass can sometimes capture patterns the first missed. +- **Code changes:** After significant source changes, recollect profile data. The existing SPD is tied to the binary it was profiled against. It won't match a substantially rebuilt binary. +- **Profile freshness:** The linker reports the percentage of profiled functions optimized using profile data after each `/spdin` build. If this percentage drops significantly, it's a signal that the code has diverged from the profile. Reprofile the current binary. \ No newline at end of file diff --git a/docs/build/spdconvert.md b/docs/build/spdconvert.md new file mode 100644 index 00000000000..e886c1e1846 --- /dev/null +++ b/docs/build/spdconvert.md @@ -0,0 +1,119 @@ +--- +description: "Learn more about: SPDConvert" +title: "SPDConvert" +ms.date: 05/08/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["SPDConvert program", "sample profile-guided optimizations, SPDConvert", "SPGO"] +--- +# SPDConvert + +Use `SPDConvert` to prepare and manage sample profile data for Sample Profile-Guided Optimization (SPGO). + +This tool correlates the raw hardware samples in SPT files against the code structure in the SPD. This step performs sample correlation, flow smoothing, and size/speed decisions, and produces an enriched SPD file with execution counts annotated on the flow graph. + +You can combine data from multiple sources such as lab benchmarks, internal monitoring, and production telemetry, in a single conversion. To emphasize the importance of a particular scenario, you can specify its SPT file multiple times. Listing a critical benchmark SPT three times effectively triples its weight. + +This tool operates in three modes: + +- *import* .SPT data into an .SPD file for [/SPGO](sample-profile-guided-optimization.md) builds +- *extract* an embedded .SPD file from a .PDB +- *merge* multiple .SPD files from separate profiling runs + +`SPDConvert` works with three file types: +- **ETL** (Event Trace Log) Raw hardware performance events recorded by `xperf` +- **SPT** (Sample Profile Trace) Packaged sample events produced by [`SPTAggregate`](sptaggregate.md) from ETL files +- **SPD** (Sample Profile Database) Processed profile data used by the compiler during an optimized build. You can also embed SPD files in PDB symbol files during a `/spdembed` build + +## Syntax + +Import SPT data into an existing SPD file: + +> `SPDConvert` [*options*] *spdfile* *sptfile(s)* + +Extract an embedded SPD file from a PDB: + +> `SPDConvert` **/extract** *pdbfile* *spdfile* + +Merge multiple SPD files into one: + +> `SPDConvert` **/merge** *outputspdfile* *spdfile(s)* + +### Parameters + +**IMPORT MODE** + +*options*\ +Specify the following options in import mode: + +- **/mode:**\<**IP**\|**LBR**\> Select the profile mode. Use **IP** for instruction pointer profile data (default) or **LBR** for last branch record profile data. +- **/reset:** Reset the count to 0. This action ignores SPTs. Use this option to reset an SPD file before importing new data, or to create an empty SPD file if the specified file doesn't exist. +- **/sptlist:**\<*file*\> Specify SPT file names in a text file, with one file name per line. +- **/summary** Print a summary of the SPD file. +- **/help** Display help information. + +*spdfile*\ +The SPD file to import sample data into. + +*sptfiles*\ +One or more SPT files to import. SPT files are produced by [SPTAggregate](sptaggregate.md). + +**EXTRACT MODE (/extract)** + +*pdbfile*\ +The PDB file that contains an embedded SPD. + +*spdfile*\ +The output SPD file to create. + +**MERGE MODE (/merge)** + +*outputspdfile*\ +The output SPD file to create. + +**/retire:**\<*N*\> Set the profile data retire rate to *N*/16, where 0 ≤ *N* ≤ 16. The default is 8. This value controls how much of the existing data in an SPD to delete when adding new SPT data. For example, `/retire:8` deletes 8/16 (half) of the existing data before adding new SPT data. This setting weights newer profile data more heavily because it discards half of the older data. The two most common usages are `/retire:0` which gives equal weight to all profile runs, or `/retire:16` to make only the newest data count because it deletes all the old data. Use `/retire:N` to control how aggressively `SPDConvert` de-emphasizes older profile data. This "carry forward" concept allows you to refresh a profile using existing SPD data without starting over with new profiling data, which is time-consuming. This concept is discussed more in the [SPGO tutorial - Reusing SPD information across builds](sample-profile-guided-optimization.md#reusing-spd-information-across-builds). + +*spdfiles*\ +One or more SPD files to merge. + +## Remarks + +> [!NOTE] +> Run this tool from a Visual Studio developer command prompt. + +`SPDConvert` is the main conversion tool in the SPGO workflow. After collecting a trace by using `xperf` and converting it to an SPT file by using [`SPTAggregate`](sptaggregate.md), use `SPDConvert` to import the sample data into an SPD file. Pass the resulting SPD file to the compiler by using the [`/SPGO`](sample-profile-guided-optimization.md) flag to build an optimized binary. + +Use `/extract` to recover an SPD file that was embedded in a PDB during a `/SPGO` build. +Use `/merge` to combine SPD files from multiple profiling sessions before rebuilding. + +The GUID and age of a binary must match between the SPT and SPD files. If they don't match, `SPDConvert` reports an "SPD version incompatible" error. Use [`SPTDump /progid`](sptdump.md) to check the binary identifiers in the SPT file, and [`SPDDump /header`](spddump.md) to check the SPD file. + +The GUID and age of the binary recorded in the SPD file must match the SPT file. To diagnose this error, use [`SPTDump /progid`](sptdump.md) to inspect the binary identifiers in the SPT file, and [`SPDDump /header`](spddump.md) to inspect the SPD file. A valid SPD file is used to the extent possible. Minor updates to the code that don't alter the program's control flow are tolerated. Unchanged functions also use the data for optimization. If you provide a valid, but otherwise unrelated SPD, the process works, but likely no data is usable for optimization. + +## Example + +This example imports LBR profile data from an SPT file into an SPD file: + +`SPDConvert /mode:LBR sample.spd sample.spt` + +This example imports IP profile data by using a list of SPT files: + +`SPDConvert /mode:IP /sptlist:mysptfiles.txt sample.spd` + +This example prints a summary of the profile data in an SPD file: + +`SPDConvert /summary sample.spd` + +This example extracts the embedded SPD from a PDB file: + +`SPDConvert /extract sample.pdb sample_extracted.spd` + +This example merges two SPD files from different profiling runs: + +`SPDConvert /merge combined.spd run1.spd run2.spd` + +## See also + +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](sample-profile-guided-optimization.md)\ +[`SPDDump`](spddump.md)\ +[`SPTAggregate`](sptaggregate.md)\ +[`SPTDump`](sptdump.md) diff --git a/docs/build/spddump.md b/docs/build/spddump.md new file mode 100644 index 00000000000..f3cfdade2b3 --- /dev/null +++ b/docs/build/spddump.md @@ -0,0 +1,68 @@ +--- +description: "Learn more about: SPDDump" +title: "SPDDump" +ms.date: 04/30/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["SPDDump program", "sample profile-guided optimizations, SPDDump", "SPGO"] +--- +# SPDDump + +Use `SPDDump` to inspect Sample Profile Database (SPD) files and object files that contain sample profile data for Sample Profile-Guided Optimization (SPGO). Use this tool to verify SPD contents, troubleshoot SPD/PDB compatibility problems, and view profile details such as functions, flow graphs, coverage, and dynamic instruction estimates. Run `SPDDump` from a Visual Studio Developer Command Prompt. + +An SPD file contains processed profile data that the compiler uses to make optimization decisions during a build. + +## Syntax + +> `SPDDump` [*options*] *spdfile* + +### Parameters + +*options*\ +Specify the following options for `SPDDump`: + +- **/all** Output the entire SPD file. This option is the default. +- **/header** Output the SPD file header. +- **/module** Output the module header in the SPD file. Implies **/header**. +- **/symbol** Output the module symbol table. Implies **/module**. +- **/func** Output the function profile. Implies **/module**. +- **/funcid:**\<*fid*\> Output the function profile for the function with the given function ID. +- **/cg** Include callee information in function profile output. Implies **/func**. +- **/fg** Include the flow graph in function profile output. Implies **/func**. +- **/data** Output the data profile. Implies **/module**. +- **/minidump** Exclude sample correlation information such as RVA ranges from output. +- **/coverage** Output basic block coverage information. +- **/dyninst**[**:**\<*n*\>] Output a dynamic instruction estimate for the top 50 functions, or the top *n* functions if specified. +- **/help** Display help information. + +*spdfile*\ +The path to the SPD file or object file to inspect. + +## Remarks + +> [!NOTE] +> Run this tool from a Visual Studio developer command prompt. + +Use `SPDDump` to inspect the contents of a Sample Profile Database (SPD) file. [`SPDConvert`](spdconvert.md) produces SPD files. The build process that uses [`/SPGO`](sample-profile-guided-optimization.md) embeds these files in PDB files. + +To diagnose an "SPD version incompatible" error, use `/header` to examine the PDB GUID and age stored in the SPD file. Then, compare those values against the SPT file by using [`SPTDump /progid`](sptdump.md). + +## Example + +This example outputs estimated basic block coverage information for an SPD file: + +`SPDDump /coverage filename.spd` + +This example outputs the SPD header to check the PDB GUID and age: + +`SPDDump /header filename.spd` + +This example outputs a dynamic instruction estimate for the top 10 functions: + +`SPDDump /dyninst:10 filename.spd` + +## See also + +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](sample-profile-guided-optimization.md)\ +[SPDConvert](spdconvert.md)\ +[SPTDump](sptdump.md)\ +[SPTAggregate](sptaggregate.md) diff --git a/docs/build/sptaggregate.md b/docs/build/sptaggregate.md new file mode 100644 index 00000000000..1d5a67e8a6b --- /dev/null +++ b/docs/build/sptaggregate.md @@ -0,0 +1,69 @@ +--- +description: "Learn more about: SPTAggregate" +title: "SPTAggregate" +ms.date: 05/01/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["SPTAggregate program", "sample profile-guided optimizations, SPTAggregate", "SPGO"] +--- +# SPTAggregate + +`SPTAggregate` is a command-line tool for Sample Profile-Guided Optimization (SPGO). Use it to combine one or more ETL (Event Trace Log) files that `xperf` collects into a single SPT (Sample Profile Trace) file. You can optionally filter data by process or binary name and exclude kernel events. After you create the SPT file, use [SPDConvert](spdconvert.md) to import it into an SPD (Sample Profile Database) file for optimization workflows. + +ETL (Event Trace Log) files contain raw hardware performance events that `xperf` records. `SPTAggregate` converts those ETL files into SPT format, which packages the sample events for import into an SPD (Sample Profile Database) file by [SPDConvert](spdconvert.md). + +## Syntax + +> `SPTAggregate` [*options*] **/etl** *etlfiles* *sptfile* + +### Parameters + +*options*\ +Specify the following options to `SPTAggregate`: + +- **/process:**\<*processes*\> Filter events by process name. Specify one or more process names as a comma-separated list.\ + Example: `/process:myapp.exe` +- **/binary:**\<*binaries*\> Filter events by binary name. Specify one or more binary names as a comma-separated list.\ + Example: `/binary:mylib.dll,myapp.exe` +- **/nokernel** Exclude OS kernel events. +- **/help** Display help information. + +*etlfiles*\ +A comma-separated list of ETL (Event Trace Log) files to process. Collect ETL files by using `xperf`. + +*sptfile*\ +The output SPT file to create. + +## Remarks + +> [!NOTE] +> Run this tool from a Visual Studio developer command prompt. + +Use `SPTAggregate` to convert one or more ETL files collected by `xperf` into an SPT file. The `/etl` flag is required and must precede the list of ETL files. You can import the resulting SPT file into an SPD file by using [`SPDConvert`](spdconvert.md). + +`SPTAggregate` uses `xperf`, which must be in your path and set up with the `perfcore.ini` changes as described in [Configure perfcore.ini](sample-profile-guided-optimization.md#configure-perfcoreini). + +When `SPTAggregate` runs `xperf`, it uses parameters like: `xperf -a spt -genSPT outputfile.spt -binary application.exe,support.dll,companion.dll` where `-a spt` specifies generate a sample profile trace analysis report, `-genSPT` specifies the output SPT file, and `-binary` focuses analysis on the specified binaries. + +For more information about `xperf` flags, see the [Xperf Command-Line Reference](/windows-hardware/test/wpt/xperf-command-line-reference) documentation. + +## Example + +This example converts a single ETL file into an SPT file: + +`SPTAggregate /etl filename.etl filename.spt` + +This example filters events to a specific process: + +`SPTAggregate /process:filename.exe /etl filename.etl filename.spt` + +This example aggregates two ETL files and excludes kernel events: + +`SPTAggregate /nokernel /etl run1.etl,run2.etl filename.spt` + +## See also + +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](sample-profile-guided-optimization.md)\ +[Profile-Guided Optimizations](profile-guided-optimizations.md)\ +[`SPDConvert`](spdconvert.md)\ +[`SPDDump`](spddump.md)\ +[`SPTDump`](sptdump.md) diff --git a/docs/build/sptdump.md b/docs/build/sptdump.md new file mode 100644 index 00000000000..7ba096eee51 --- /dev/null +++ b/docs/build/sptdump.md @@ -0,0 +1,110 @@ +--- +description: "Learn more about: SPTDump" +title: "SPTDump" +ms.date: 05/05/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["SPTDump program", "sample profile-guided optimizations, SPTDump", "SPGO"] +--- +# SPTDump + +`SPTDump` is a command-line tool for inspecting Sample Profile Trace (SPT) files used in Sample Profile-Guided Optimization (SPGO) workflows. Use it to view SPT metadata and sample data. Validate trace contents before conversion to SPD, and troubleshoot issues such as SPD version mismatches. + +An SPT file contains raw hardware performance sample events collected from an application workload. + +## Syntax + +> `SPTDump` [*options*] *sptfile* + +### Parameters + +*options*\ +Specify the following options to `SPTDump`: + +- **/all** Output the entire SPT file. This option is the default. +- **/header** Output the SPT file header. +- **/progid** Output program IDs (GUID and age for each binary). +- **/strtab** Output the string table. +- **/event** Output sample events. +- **/help** Display help information. + +*sptfile*\ +The path to the SPT file to inspect. + +## Remarks + +> [!NOTE] +> Start this tool from a Visual Studio developer command prompt. + +Use `SPTDump` to inspect the contents of a Sample Profile Trace (SPT) file. [SPTAggregate](sptaggregate.md) produces SPT files from ETL event trace logs collected by `xperf`. Import SPT files into an SPD file (Sample Profile Database) by using [SPDConvert](spdconvert.md). + +To diagnose an "SPD version incompatible" error, use `/progid` to display the GUID and age for each binary in the SPT file, and then compare those values against the SPD file by using [`SPDDump /header`](spddump.md). + +## Example + +This example outputs the full contents of an SPT file: + +`SPTDump sample.spt` + +This example outputs only the program IDs (GUID and age) for binaries in an SPT file: + +`SPTDump /progid sample.spt` + +## SPT header format + +SPT file is a binary format with a 32-byte header, string table, program ID table, and sample event data stream. This document describes version 1 of the format. The version field updates if the layout changes in the future. + +The SPT header is 32 bytes: + +- `[0x00-0x03]` Signature (uint32 LE) = 0x5350543A ("SPT:") +- `[0x04-0x07]` Version (uint32 LE) = 1 +- `[0x08-0x0B]` RawDataId (uint32 LE) = 0 (unused/reserved) +- `[0x0C-0x0F]` TargetArch (uint32 LE) = 0 (unused/reserved) +- `[0x10-0x13]` StringTableOffset (uint32 LE) = offset to binary name string table (typically 0x20) +- `[0x14-0x17]` ProgramIdTableOffset (uint32 LE) = offset to RSDSKEY table (typically StringTableOffset+StringTableCapacity) +- `[0x18-0x19]` StringTableUsed (uint16 LE) = bytes used in string table +- `[0x1A-0x1B]` StringTableCapacity (uint16 LE) = bytes allocated in string table (typically 0x4000) +- `[0x1C-0x1D]` ProgramIdsUsed (uint16 LE) = number of program IDs (often just 1) +- `[0x1E-0x1F]` ProgramIdCapacity (uint16 LE) = capacity in count (not bytes) for program IDs (typically 0x100) + +The StringTable immediately follows the header at the specified offset. It contains a null-terminated UTF-8 binary filename. + +The ProgramIdTable follows the StringTable at the specified offset. Each entry is 24 bytes: 16-byte Rich Signature Data Stream (RSDS) GUID + 4-byte age + 4-byte string index into StringTable. + +The data stream starts at `ProgramIdTableOffset + (ProgramIdCapacity * 24)`, and starts with a `SPT_OP_BINARY_ID` opcode. + +**SPT Opcodes** + +In the following descriptions: +- RVA means the 32-bit relative virtual address of an instruction in the binary, that is, it's offset in the module. +- LE means little-endian byte order. + +`SPT_OP_REPEAT` (0x82)\ +Repeat the next record for the specified number of times. A repeat count of 2 means that there are 3 identical records in total. The repeat count resets after processing it.\ +Layout: 1 byte: opcode 0x82. 1 byte: padding. 8 bytes: repeat count (uint64 LE) + +`SPT_OP_UNHALT_CYCLE`, `SPT_OP_RETIRE_INSTR`, `SPT_OP_RETIRE_BR_INSTR`, `SPT_OP_L1_ICACHE_MISS`, `SPT_OP_L1_DCACHE_MISS`, `SPT_OP_ETW_INSTR` (0x01, 0x02, 0x03, 0x04, 0x05, 0x41)\ +Layout: 1 byte: opcode. 1 byte: RVA count (N). 4N bytes: N RVAs (uint32 LE each)\ +Each RVA represents an IP sample hit count = 1 + repeat count. + +`SPT_OP_LBR` (0x10)\ +Layout: 1 byte: opcode 0x10. 1 byte: event count (N). 8N bytes: N LBR pairs, each pair is: 4 bytes: To RVA (uint32 LE), 4 bytes: From RVA (uint32 LE)\ +Each pair represents a branch arc with hit count = 1 + repeat count. + +`SPT_OP_ETW_CALLSTACK` (0x42)\ +Layout: 1 byte: opcode 0x42. 1 byte: RVA count (N). 4N bytes: N RVAs (uint32 LE each, representing stack frames).\ +When: +- N = 2: Two RVAs form a single stack arc (RVA[0], RVA[1]) +- N > 2: Creates N-1 arcs from consecutive pairs: (RVA[0]->RVA[1]), (RVA[1]->RVA[2]), ..., (RVA[N-2]->RVA[N-1]) +Each series, whether it's a single arc or consecutive pairs, has hit count = 1 + repeat count. + +`SPT_OP_BINARY_ID` (0x81)\ +Layout: 1 byte: opcode 0x81. 1 byte: padding. 2 bytes: program ID (uint16 LE). 4 bytes: total data length in this segment (uint32 LE).\ +Marks the start of data records for a specific binary specified by an index ID. The index ID refers back to the RSDSKey and binary name string table in the SPT header.\ +The data length includes the 4-byte length field itself. This opcode can occur multiple times in a data stream. + +## See also + +[Tutorial: Use Sample Profile-Guided Optimization (SPGO) to improve performance](sample-profile-guided-optimization.md)\ +[`SPDConvert`](spdconvert.md)\ +[`SPDDump`](spddump.md)\ +[`SPTAggregate`](sptaggregate.md) \ No newline at end of file diff --git a/docs/build/toc.yml b/docs/build/toc.yml index 57a47a03ffb..1d69bdfe99a 100644 --- a/docs/build/toc.yml +++ b/docs/build/toc.yml @@ -137,6 +137,8 @@ items: items: - name: Profile-guided optimizations href: ../build/profile-guided-optimizations.md + - name: Sample profile-guided optimization tutorial + href: ../build/sample-profile-guided-optimization.md - name: Environment variables for profile-guided optimizations href: ../build/environment-variables-for-profile-guided-optimizations.md - name: PgoAutoSweep @@ -145,6 +147,14 @@ items: href: ../build/pgomgr.md - name: pgosweep href: ../build/pgosweep.md + - name: SPDConvert + href: ../build/spdconvert.md + - name: SPDDump + href: ../build/spddump.md + - name: SPTAggregate + href: ../build/sptaggregate.md + - name: SPTDump + href: ../build/sptdump.md - name: "How to: Merge multiple PGO profiles into a single profile" href: ../build/how-to-merge-multiple-pgo-profiles-into-a-single-profile.md - name: Use the MSVC toolset from the command line @@ -314,6 +324,8 @@ items: href: ../build/prolog-and-epilog.md - name: x64 exception handling href: ../build/exception-handling-x64.md + - name: x64 Unwind Information V3 + href: ../build/x64-unwind-information-v3.md - name: Configure C++ projects for ARM processors expanded: false items: @@ -561,7 +573,12 @@ items: - name: /FC (Full path of source code file in diagnostics) href: ../build/reference/fc-full-path-of-source-code-file-in-diagnostics.md - name: /feature (Enable architecture features) - href: ../build/reference/feature-arm64.md + href: ../build/reference/feature-enable-architecture-features.md + items: + - name: /feature (ARM64) + href: ../build/reference/feature-arm64.md + - name: /feature (x64) + href: ../build/reference/feature-x64.md - name: /forceInterlockedFunctions (Generate and link with out-of-line atomic functions) href: ./reference/force-interlocked-functions.md @@ -850,6 +867,8 @@ items: href: ../build/reference/zc-trigraphs-trigraphs-substitution.md - name: "/Zc:twoPhase- (disable two-phase name lookup)" href: ../build/reference/zc-twophase.md + - name: /Zc:u8EscapeEncoding (numeric escape sequence encoding in u8 strings) + href: ./reference/zc-u8escapeencoding.md - name: "/Zc:wchar_t (wchar_t is native type)" href: ../build/reference/zc-wchar-t-wchar-t-is-native-type.md - name: "/Zc:zeroSizeArrayNew (Call member new/delete on arrays)" @@ -1098,6 +1117,14 @@ items: href: ../build/reference/section-specify-section-attributes.md - name: /SOURCELINK (Include Sourcelink file in PDB) href: ../build/reference/sourcelink.md + - name: /SPD + href: ../build/reference/spd-specify-sample-profile-database.md + - name: /SPDEMBED + href: ../build/reference/spdembed-embed-sample-profile-database.md + - name: /SPDIN + href: ../build/reference/spdin-use-sample-profile-database.md + - name: /SPGO + href: ../build/reference/spgo-enable-sample-profile-guided-optimization.md - name: /STACK (Stack allocations) href: ../build/reference/stack-stack-allocations.md - name: /STUB (MS-DOS stub file name) diff --git a/docs/build/use-github-copilot-create-cpp-console-app.md b/docs/build/use-github-copilot-create-cpp-console-app.md index ab3637cfa2b..3cd09ebd3cb 100644 --- a/docs/build/use-github-copilot-create-cpp-console-app.md +++ b/docs/build/use-github-copilot-create-cpp-console-app.md @@ -1,13 +1,14 @@ --- title: Use AI to create a C++ console application in Visual Studio -description: "Learn how to use GitHub Copilot to create a C++ app using Microsoft C++ in Visual Studio." -ms.date: 10/24/2025 +description: "Learn how to use GitHub Copilot to create an example C++ console app using Microsoft C++ in Visual Studio." +ms.date: 05/28/2026 ms.topic: "tutorial" ms.collection: ce-skilling-ai-copilot ms.custom: - ai-assisted - copilot-scenario-highlight ms.update-cycle: 180-days +#customer intent: As a C++ developer, I want to use GitHub Copilot to create, troubleshoot, and understand C++ code in Microsoft Visual Studio. --- # Use AI to create a C++ console application in Visual Studio @@ -17,6 +18,7 @@ This tutorial shows you how to use GitHub Copilot to quickly create a C++ consol Conway's Game of Life was devised by mathematician John Conway. It consists of a grid of cells that can be either alive or dead. The game evolves automatically based on simple rules and produces complex, evolving patterns that demonstrate how intricate behavior can emerge from basic mathematical rules. GitHub Copilot is an AI-powered coding assistant that helps you write code faster, reduce errors, and explore new solutions. Some benefits of using Copilot when coding in C++: + - Generate entire C++ functions or classes as you type. - Suggest code completions based on plain-language comments or prompts. - Get help with complex algorithms, data structures, and standard library usage. @@ -31,11 +33,12 @@ GitHub Copilot is an AI-powered coding assistant that helps you write code faste - GitHub Copilot. For more information, see [Get started with GitHub Copilot](/visualstudio/ide/visual-studio-github-copilot-get-started). To verify you have the C++ workload installed: -1. Open Visual Studio Installer -1. Select **Modify** next to your Visual Studio installation + +1. Open Visual Studio Installer. +1. Select **Modify** next to your Visual Studio installation. 1. Ensure **Desktop development with C++** is checked: - :::image type="content" source="media/desktop-development-cpp-workload.png" alt-text="Screenshot of the Visual Studio Installer with the Workloads tab selected. Desktop development with c++ is selected."::: + :::image type="content" source="media/desktop-development-cpp-workload.png" alt-text="Screenshot of the Visual Studio Installer with the Workloads tab selected and Desktop Development with C++ selected."::: 1. If it isn't installed, select it and choose **Modify**. @@ -43,30 +46,31 @@ For more information about installing Copilot, see [Manage GitHub Copilot instal ## Create a project -Visual Studio uses *projects* to organize the code for an app, and *solutions* to organize your projects. A project contains all the options, configurations, and rules used to build your apps. It manages the relationship between all the project's files and any external files. To create your app, first, create a new project and solution. +Visual Studio uses *projects* to organize the code for an app, and *solutions* to organize your projects. A project contains the options, configurations, and rules used to build your apps. It manages the relationship between the project's files and any external files. To create your app, first, create a new project and solution. 1. Open Visual Studio and select **Create a new project**. -1. Search for "Console App" and select the **Console App** template for C++. +1. Search for *Console App* and select the **Console App** template for C++. - :::image type="complex" source="media/vs2019-choose-console-app.png" alt-text="Screenshot of the Create a new project dialog."::: - The Create a new project dialog is shown with the Console App template selected. The template says: Run code in a windows terminal. Prints hello world by default. Has the tags c++, Windows, and Console. + :::image type="complex" source="media/vs-2026/choose-console-app.png" alt-text="Screenshot of the Create a new project dialog."::: + The Create a new project dialog is shown with the Console App template selected. The template says: Run code in a Windows Terminal. Prints Hello World by default. Has the tags C++, Windows, and Console. :::image-end::: 1. Select **Next**. -1. Set the project name to **Life** and choose the location for the project. +1. Set the project name to `Life` and choose the location for the project. 1. Select **Create**. -1. Once the project opens, find the `Life.cpp` file in Solution Explorer. +1. After the project opens, find the `Life.cpp` file in Solution Explorer. 1. Open `Life.cpp` and delete the default "Hello, World!" code to start with a clean slate. ## Use Copilot to create an app -You prompt Copilot by describing the functionality you want. In this section, you'll learn how to prompt Copilot to generate an implementation of Conway's Game of Life. +You prompt Copilot by describing the functionality you want. In this section, you learn how to prompt Copilot to generate an implementation of Conway's Game of Life. 1. Open the Copilot chat window by selecting the Copilot icon in the toolbar: - :::image type="content" source="media/github-copilot-open-chat.png" alt-text="Screenshot of the GitHub icon dropdown. Open Chat Window is selected."::: + :::image type="content" source="media/vs-2026/github-copilot-open-chat.png" alt-text="Screenshot of the GitHub icon with Open Chat selected."::: 1. In the chat window, enter the following prompt: + ```copilot-prompt Create a C++ console application that implements Conway's Game of Life. The program should: - Use a 40x20 grid displayed with asterisks (*) for live cells and spaces for dead cells @@ -76,17 +80,17 @@ You prompt Copilot by describing the functionality you want. In this section, yo - Include proper headers and use standard C++ practices - Clear the console between generations to provide an animation effect ``` -1. Copilot generates C++ code for Conway's Game of Life. -1. Copy the generated code and paste it into your empty `Life.cpp` file. -1. Build the project by pressing **F6** or selecting **Build > Build Solution**. -1. Run the program by pressing **F5** or **Ctrl+F5**. + +1. Copilot generates C++ code for Conway's Game of Life. Copy the generated code and paste it into your empty `Life.cpp` file. +1. Build the project by pressing **F6** or selecting **Build** > **Build Solution**. +1. Run the program by pressing **F5** or **Ctrl**+**F5**. > [!NOTE] -> The exact code generated by Copilot may vary slightly from run to run and model to model, but the core functionality should be consistent. If the generated code doesn't compile immediately, you can ask Copilot to fix any compilation errors. Copilot is powered by AI, so surprises and mistakes are possible. For more information, see [Copilot FAQs](https://aka.ms/copilot-general-use-faqs). +> The exact code generated by Copilot might vary slightly from run to run and model to model, but the core functionality should be consistent. If the generated code doesn't compile immediately, you can ask Copilot to fix any compilation errors. Copilot is powered by AI, so surprises and mistakes are possible. For more information, see [Copilot FAQs](https://aka.ms/copilot-general-use-faqs). ### Example of typical generated code structure -Your generated code will likely include these key components: +Your generated code likely includes these key components: - Headers for console manipulation, random number generation, and timing - A 2D array or vector to represent the game grid @@ -200,17 +204,18 @@ int main() return 0; } ``` + When you run the application, you should see an animated display of Conway's Game of Life with patterns evolving over time. To exit the program, press a key. :::image type="content" source="./media/life-exe.png" alt-text="Screenshot of Conway Life running in a command window, displaying the evolving grid of cells."::: In the preceding code example, the code generates a warning: `Return value ignored: '_getch'`. You can ask Copilot to fix it. Select the code editor and press **Alt+/** (Windows) to open the Copilot chat, then enter: -:::image type="content" source="./media/github-copilot-fix-warning.png" alt-text="Screenshot of the Copilot chat window. The text: Fix warning C6031 is in the chat window."::: +:::image type="content" source="./media/vs-2026/github-copilot-fix-warning.png" alt-text="Screenshot of the Copilot chat window where you can ask Copilot to fix an issue."::: Copilot suggests a fix to handle the return value properly. To accept the changes, select **Tab**: -:::image type="content" source="./media/github-copilot-fix-warning-accept.png" alt-text="Screenshot of the Copilot proposed changes. Tab to accept. Alt+Del to discard."::: +:::image type="content" source="./media/vs-2026/github-copilot-fix-warning-accept.png" alt-text="Screenshot of the Copilot proposed changes, explanation to use Tab to accept or Alt+Del to discard."::: Congratulations! You successfully used GitHub Copilot to create a fully functional Conway's Game of Life console application in C++. You learned how to: @@ -230,22 +235,22 @@ For better results with Copilot, see these prompting resources: ### Missing console app template -The **New Project** dialog should show a **Console App** template that has **C++**, **Windows**, and **Console** tags. If you don't see it, it might be filtered out of the list, or it might not be installed. First, check the filter dropdowns at the top of the list of templates. Set them to **C++**, **Windows**, and **Console**. The C++ **Console App** template should appear; otherwise, the **Desktop development with C++** workload isn't installed. +The **New Project** dialog should show a **Console App** template that has **C++**, **Windows**, and **Console** tags. If you don't see it, it might be filtered out of the list, or it might not be installed. First, check the filter menus at the top of the list of templates. Set them to **C++**, **Windows**, and **Console**. The C++ **Console App** template should appear; otherwise, the **Desktop development with C++** workload isn't installed. To install **Desktop development with C++**, you can run the installer right from the **Create a new project** dialog. Choose the **Install more tools and features** link at the bottom of the **Create a new project** dialog, beneath the list of templates. If the **User Account Control** dialog requests permissions, choose **Yes**. In the installer, make sure the **Desktop development with C++** workload is checked. Then choose **Modify** to update your Visual Studio installation. ### Copilot not responding - Ensure you have an active GitHub Copilot subscription. -- Try signing out and back into your GitHub account in Visual Studio +- Try signing out and back into your GitHub account in Visual Studio. ### Generated code doesn't compile - Ask Copilot to fix specific compilation errors by pasting the error message into Copilot chat. - Try refining your prompt to be more specific about what you want the app to do. -## Next steps +## See also - [GitHub Copilot in Visual Studio](/visualstudio/ide/visual-studio-github-copilot-install-and-states) -- [GitHub Copilot documentation](https://docs.github.com/en/copilot) - Dive deeper into AI-assisted development -- [Awesome ChatGPT Prompts](https://github.com/f/awesome-chatgpt-prompts) - Community-driven prompting examples for inspiration \ No newline at end of file +- [GitHub Copilot documentation](https://docs.github.com/copilot) - Dive deeper into AI-assisted development +- [Awesome ChatGPT Prompts](https://github.com/f/awesome-chatgpt-prompts) - Community-driven prompting examples for inspiration diff --git a/docs/build/vscpp-step-0-installation.md b/docs/build/vscpp-step-0-installation.md index 903016883ab..c7ea3bbe0ce 100644 --- a/docs/build/vscpp-step-0-installation.md +++ b/docs/build/vscpp-step-0-installation.md @@ -1,7 +1,7 @@ --- title: Install C and C++ support in Visual Studio -description: "Learn how to install Visual Studio with support for Microsoft C and C++ and related workloads." -ms.date: 09/09/2025 +description: Install C++ support in Visual Studio on Windows. Learn to select workloads, customize components, change install locations, and start building apps. +ms.date: 07/15/2026 ms.topic: tutorial ms.devlang: "cpp" ms.custom: @@ -14,16 +14,14 @@ ms.custom: If you haven't installed Visual Studio and the Microsoft C and C++ tools yet, here's how to get started. -::: moniker range="msvc-170" +## Visual Studio installation -## Visual Studio 2022 installation - -Welcome to Visual Studio 2022! In this version, it's easy to choose and install just the features you need. Because of its reduced minimum footprint, Visual Studio installs quickly and with less system impact. +Welcome to Visual Studio! It's easy to choose and install just the features you need. Because of its reduced minimum footprint, Visual Studio installs quickly and with less system impact. > [!NOTE] > This article applies to installation of Visual Studio on Windows. [Visual Studio Code](https://code.visualstudio.com) is a lightweight, cross-platform development environment that runs on Windows, Mac, and Linux systems. The Microsoft [C/C++ for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension supports IntelliSense, debugging, code formatting, autocompletion. Visual Studio for Mac doesn't support Microsoft C++, but does support .NET languages and cross-platform development. For installation instructions, see [Install Visual Studio for Mac](/visualstudio/mac/installation/). -To learn what else is new in this version, see the Visual Studio [release notes](/visualstudio/releases/2022/release-notes/). +To learn what's new in this version, see [Visual Studio 2026 release notes](/visualstudio/releases/2026/release-notes). Ready to install? Use the following step-by-step guide. @@ -31,7 +29,7 @@ Ready to install? Use the following step-by-step guide. Before you begin installing Visual Studio: -1. Check the [system requirements](/visualstudio/releases/2022/system-requirements). These requirements help you know whether your computer supports Visual Studio 2022. +1. Check the [system requirements for Visual Studio](/visualstudio/releases/2026/vs-system-requirements). These requirements help you know whether your computer supports Visual Studio. 1. Apply the latest Windows updates. These updates ensure that your computer has both the latest security updates and the required system components for Visual Studio. @@ -39,7 +37,7 @@ Before you begin installing Visual Studio: 1. Free up disk space. Remove unneeded files and applications from your %SystemDrive% by, for example, running the Disk Cleanup app. -For questions about running previous versions of Visual Studio side by side with Visual Studio 2022, see the [Visual Studio 2022 Platform Targeting and Compatibility](/visualstudio/releases/2022/compatibility/) page. +For questions about running previous versions of Visual Studio side by side, see [Visual Studio Platform Targeting and Compatibility](/visualstudio/releases/2026/compatibility/). ### Step 2 - Download Visual Studio @@ -49,29 +47,32 @@ Select the following button to go to the Visual Studio download page, and downlo > [Download Visual Studio](https://visualstudio.microsoft.com/downloads/) >[!TIP] -> The Community edition is for individual developers, classroom learning, academic research, and open source development. For other uses, install Visual Studio 2022 Professional or Visual Studio 2022 Enterprise. +> The Community edition is for individual developers, classroom learning, academic research, and open source development. For other uses, install Visual Studio Professional or Visual Studio Enterprise. ### Step 3 - Install the Visual Studio Installer Run the bootstrapper file you downloaded to install the Visual Studio Installer. This new lightweight installer includes everything you need to both install and customize Visual Studio. -1. From your *Downloads* folder, double-click the bootstrapper file called *VisualStudioSetup.exe*. +1. From your **Downloads** folder, double-click the bootstrapper file named `VisualStudioSetup.exe`. - If you receive a User Account Control notice, choose **Yes** to allow the bootstrapper to run. + If you receive a User Account Control notice, select **Yes** to allow the bootstrapper to run. -1. We ask you to acknowledge the Microsoft [License Terms](https://visualstudio.microsoft.com/license-terms/) and the Microsoft [Privacy Statement](https://privacy.microsoft.com/privacystatement). Choose **Continue**. +1. Agree to the Microsoft [License Terms](https://visualstudio.microsoft.com/license-terms/) and the Microsoft [Privacy Statement](https://privacy.microsoft.com/privacystatement). Select **Continue**. ### Step 4 - Choose workloads -You can use the installer to customize your installation by selecting the *workloads*, or feature sets, that you want. +Use the installer to customize your installation by selecting the *workloads*, or feature sets, that you want. 1. Find the workload you want in the **Installing Visual Studio** screen. - :::image type="content" source="../get-started/media/vs2022-installer-workloads.png" alt-text="Screenshot of the Visual Studio 2022 installer with the Desktop development with C plus plus workload selected." lightbox="../get-started/media/vs2022-installer-workloads.png"::: + :::image type="content" source="../get-started/media/vs-2026/visual-studio-installer-cpp-workload.png" alt-text="Screenshot showing the Visual Studio installer with the Desktop development with C plus plus workload selected."::: For core C and C++ support, choose the **Desktop development with C++** workload. It comes with the default core editor, which includes basic code editing support for more than 20 languages, the ability to open and edit code from any folder without requiring a project, and integrated source code control. - The **Installation details** pane lists the included and optional components installed by each workload. You can select or deselect optional components in this list. For example, to support development by using the Visual Studio 2017 or 2015 compiler toolsets, choose the MSVC v141 or MSVC v140 optional components. You can add support for MFC, the experimental Modules language extension, IncrediBuild, and more. + The **Installation details** pane lists the included and optional components that each workload installs. You can select or deselect optional components in this list. For example, to support development by using the Visual Studio 2017 or 2015 compiler toolsets, choose the MSVC v141 or MSVC v140 optional components. You can add support for MFC, the experimental Modules language extension, IncrediBuild, and more. + + > [!TIP] + > To install a specific MSVC Build Tools version (Preview, latest release, or an older in-support release), see [Install the Microsoft C++ (MSVC) Build Tools](../overview/acquire-msvc.md). Other workloads support more kinds of development. For example, choose the **Universal Windows Platform development** workload to create apps that use the Windows Runtime for the Microsoft Store. Choose **Game development with C++** to create games that use DirectX, Unreal, or Cocos2d. Choose **Linux development with C++** to target Linux platforms, including IoT development. @@ -84,30 +85,30 @@ You can use the installer to customize your installation by selecting the *workl ### Step 5 - Choose individual components (optional) -If you don't want to use the Workloads feature to customize your Visual Studio installation, or you want to add more components than a workload installs, you can do so by installing or adding individual components from the **Individual components** tab. Choose what you want, and then follow the prompts. +If you don't want to use the Workloads feature to customize your Visual Studio installation, or you want to add more components than a workload installs, you can install or add individual components from the **Individual components** tab. Choose what you want, and then follow the prompts. ### Step 6 - Install language packs (optional) -By default, the installer program tries to match the language of the operating system when it runs for the first time. To install Visual Studio in a language of your choosing, choose the **Language packs** tab from the Visual Studio Installer, and then follow the prompts. +By default, the Visual Studio Installer tries to match the language of the operating system when it runs for the first time. To install Visual Studio in a language that you choose, select the **Language packs** tab from the Visual Studio Installer, and then follow the prompts. :::image type="content" source="../get-started/media/vs-installer-language-packs.png" alt-text="Screenshot of the Visual Studio Installer, showing the Install language packs tab view and the languages you can choose from like English, Spanish, Chinese (simplified or traditional)." lightbox="../get-started/media/vs-installer-language-packs.png"::: #### Change the installer language from the command line -Another way that you can change the default language is by running the installer from the command line. For example, you can force the installer to run in English by using the following command: `vs_installer.exe --locale en-US`. The installer remembers this setting when it's run the next time. The installer supports the following language tokens: zh-cn, zh-tw, cs-cz, en-us, es-es, fr-fr, de-de, it-it, ja-jp, ko-kr, pl-pl, pt-br, ru-ru, and tr-tr. +You can change the default language by running the installer from the command line. For example, you can force the installer to run in English by using the following command: `vs_installer.exe --locale en-US`. The installer remembers this setting the next time it runs. The installer supports the following language tokens: zh-cn, zh-tw, cs-cz, en-us, es-es, fr-fr, de-de, it-it, ja-jp, ko-kr, pl-pl, pt-br, ru-ru, and tr-tr. ### Step 7 - Change the installation location (optional) -You can reduce the installation footprint of Visual Studio on your system drive. You can choose to move the download cache, shared components, SDKs, and tools to different drives, and keep Visual Studio on the drive that runs it the fastest. +You can reduce the installation footprint of Visual Studio on your system drive. Move the download cache, shared components, SDKs, and tools to different drives, and keep Visual Studio on the drive that runs it the fastest. > [!IMPORTANT] -> You can select a different drive only when you first install Visual Studio. If you've already installed it and want to change drives, you must uninstall Visual Studio and then reinstall it. +> You can select a different drive only when you first install Visual Studio. If you already installed it and want to change drives, you must uninstall Visual Studio and then reinstall it. ### Step 8 - Start developing -1. After Visual Studio installation is complete, choose the **Launch** button to get started developing with Visual Studio. +1. After Visual Studio installation is complete, select the **Launch** button to get started developing with Visual Studio. -1. On the start window, choose **Create a new project**. +1. On the start window, select **Create a new project**. 1. In the search box, enter the type of app you want to create to see a list of available templates. The list of templates depends on the workloads that you chose during installation. To see different templates, choose different workloads. @@ -130,164 +131,6 @@ Some benefits of using Copilot for your C++ coding scenarios: To try GitHub copilot to create a C++ app, follow the instructions in [Use AI to create a C++ console application in Visual Studio](../build/use-github-copilot-create-cpp-console-app.md). -::: moniker-end - -::: moniker range="msvc-160" - -## Visual Studio 2019 installation - -Welcome to Visual Studio 2019! In this version, it's easy to choose and install just the features you need. Because of its reduced minimum footprint, Visual Studio installs quickly and with less system impact. - -> [!NOTE] -> This article applies to installation of Visual Studio on Windows. [Visual Studio Code](https://code.visualstudio.com) is a lightweight, cross-platform development environment that runs on Windows, Mac, and Linux systems. The Microsoft [C/C++ for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension supports IntelliSense, debugging, code formatting, autocompletion. Visual Studio for Mac doesn't support Microsoft C++, but does support .NET languages and cross-platform development. For installation instructions, see [Install Visual Studio for Mac](/visualstudio/mac/installation/). - -To learn what else is new in this version, see the Visual Studio [release notes](/visualstudio/releases/2019/release-notes/). - -Ready to install? Use the following step-by-step guide. - -### Step 1 - Prepare your computer for Visual Studio - -Before you begin installing Visual Studio: - -1. Check the [system requirements](/visualstudio/releases/2019/system-requirements). These requirements help you know whether your computer supports Visual Studio 2019. - -1. Apply the latest Windows updates. These updates ensure that your computer has both the latest security updates and the required system components for Visual Studio. - -1. Reboot your computer. The reboot ensures that any pending installs or updates don't hinder the Visual Studio install. - -1. Free up disk space. Remove unneeded files and applications from your %SystemDrive% by, for example, running the Disk Cleanup app. - -For questions about running previous versions of Visual Studio side by side with Visual Studio 2019, see the [Visual Studio 2019 Platform Targeting and Compatibility](/visualstudio/releases/2019/compatibility/) page. - -### Step 2 - Download Visual Studio - -Select the following button to go to the Visual Studio older downloads page, and download the Visual Studio 2019 bootstrapper file. - - > [!div class="button"] - > [Download Visual Studio 2019](https://visualstudio.microsoft.com/vs/older-downloads/#visual-studio-2019-and-other-products) - -### Step 3 - Install the Visual Studio Installer - -Run the bootstrapper file you downloaded to install the Visual Studio Installer. This new lightweight installer includes everything you need to both install and customize Visual Studio. - -1. From your *Downloads* folder, double-click the bootstrapper file. - - If you receive a User Account Control notice, choose **Yes** to allow the bootstrapper to run. - -1. We ask you to acknowledge the Microsoft [License Terms](https://visualstudio.microsoft.com/license-terms/) and the Microsoft [Privacy Statement](https://privacy.microsoft.com/privacystatement). Choose **Continue**. - -### Step 4 - Choose workloads - -You can use the installer to customize your installation by selecting the *workloads*, or feature sets, that you want. - -1. Find the workload you want in the **Installing Visual Studio** screen. - - :::image type="content" source="../get-started/media/vs-installer-workloads.png" alt-text="Screenshot of the Visual Studio 2019 installer." lightbox="../get-started/media/vs-installer-workloads.png"::: - - For core C and C++ support, choose the **Desktop development with C++** workload. It comes with the default core editor, which includes basic code editing support for over 20 languages, the ability to open and edit code from any folder without requiring a project, and integrated source code control. - - The **Installation details** pane lists the included and optional components installed by each workload. You can select or deselect optional components in this list. For example, to support development by using the Visual Studio 2017 or 2015 compiler toolsets, choose the MSVC v141 or MSVC v140 optional components. You can add support for MFC, the experimental Modules language extension, IncrediBuild, and more. - - Other workloads support more kinds of development. For example, choose the **Universal Windows Platform development** workload to create apps that use the Windows Runtime for the Microsoft Store. Choose **Game development with C++** to create games that use DirectX, Unreal, and Cocos2d. Choose **Linux development with C++** to target Linux platforms, including IoT development. - -1. After you choose the workloads and optional components you want, choose **Install**. - - Next, status screens appear that show the progress of your Visual Studio installation. - -> [!TIP] -> At any time after installation, you can install workloads or components that you didn't install initially. If you have Visual Studio open, go to **Tools** > **Get Tools and Features...** which opens the Visual Studio Installer. Or, open **Visual Studio Installer** from the Start menu. From there, you can choose the workloads or components that you wish to install. Then, choose **Modify**. - -### Step 5 - Choose individual components (optional) - -If you don't want to use the Workloads feature to customize your Visual Studio installation, or if you want to add more components than a workload installs, you can do so by installing or adding individual components from the **Individual components** tab. Choose what you want, and then follow the prompts. - -:::image type="content" source="../get-started/media/vs-installer-individual-components.png" alt-text="Screenshot of the Visual Studio Installer, showing the Install individual components tab view." lightbox="../get-started/media/vs-installer-individual-components.png"::: - -### Step 6 - Install language packs (optional) - -By default, the installer program tries to match the language of the operating system when it runs for the first time. To install Visual Studio in a language of your choosing, choose the **Language packs** tab from the Visual Studio Installer, and then follow the prompts. - -:::image type="content" source="../get-started/media/vs-installer-language-packs.png" alt-text="Screenshot of the Visual Studio Installer, showing the Install language packs tab view." lightbox="../get-started/media/vs-installer-language-packs.png"::: - -#### Change the installer language from the command line - -Another way that you can change the default language is by running the installer from the command line. For example, you can force the installer to run in English by using the following command: `vs_installer.exe --locale en-US`. The installer will remember this setting when it's run the next time. The installer supports the following language tokens: zh-cn, zh-tw, cs-cz, en-us, es-es, fr-fr, de-de, it-it, ja-jp, ko-kr, pl-pl, pt-br, ru-ru, and tr-tr. - -### Step 7 - Change the installation location (optional) - -You can reduce the installation footprint of Visual Studio on your system drive. You can choose to move the download cache, shared components, SDKs, and tools to different drives, and keep Visual Studio on the drive that runs it the fastest. - -:::image type="content" source="../get-started/media/vs-installer-installation-locations.png" alt-text="Screenshot of the Visual Studio Installer, showing the installation locations tab view." lightbox="../get-started/media/vs-installer-installation-locations.png"::: - -> [!IMPORTANT] -> You can select a different drive only when you first install Visual Studio. If you've already installed it and want to change drives, you must uninstall Visual Studio and then reinstall it. - -### Step 8 - Start developing - -1. After Visual Studio installation is complete, choose the **Launch** button to get started developing with Visual Studio. -1. On the start window, choose **Create a new project**. -1. In the search box, enter the type of app you want to create to see a list of available templates. The list of templates depends on the workloads that you chose during installation. To see different templates, choose different workloads. - - You can also filter your search for a specific programming language by using the **Language** dropdown list. You can filter by using the **Platform** list and the **Project type** list, too. - -1. Visual Studio opens your new project, and you're ready to code! - -::: moniker-end - -::: moniker range="msvc-150" - -## Visual Studio 2017 installation - -In Visual Studio 2017, it's easy to choose and install just the features you need. Because of its reduced minimum footprint, it installs quickly and with less system impact. - -### Prerequisites - -- A computer that runs Microsoft Windows 7 or later versions. We recommend the latest version of Windows for the best development experience. Make sure that the latest updates are applied to your system before you install Visual Studio. - -- Enough free disk space. Visual Studio requires at least 7 GB of disk space, and can take 50 GB or more if many common options are installed. We recommend you install it on your C: drive. - -For details on the disk space and operating system requirements, see [Visual Studio Product Family System Requirements](/visualstudio/productinfo/vs2017-system-requirements-vs). The installer reports how much disk space is required for the options you select. - -### Download and install - -1. To download the Visual Studio 2017 installer for Windows, go to the Visual Studio [older downloads](https://visualstudio.microsoft.com/vs/older-downloads/#visual-studio-2017-and-other-products) page. Expand the **2017** section, and choose the **Download** button. - -1. Find the installer file you downloaded and run it. The downloaded file might be displayed in your browser, or you might find it in your *Downloads* folder. The installer needs Administrator privileges to run. You might see a **User Account Control** dialog asking you to give permission to let the installer make changes to your system; choose **Yes**. If you're having trouble, find the downloaded file in File Explorer, right-click on the installer icon, and choose **Run as Administrator** from the context menu. - - :::image type="content" source="media/vscpp-concierge-run-installer.gif" alt-text="Animation that shows the Visual Studio Installer."::: - -1. The installer presents you with a list of workloads, which are groups of related options for specific development areas. Support for C++ is now part of optional workloads that aren't installed by default. - - :::image type="content" source="media/desktop-development-with-cpp.png" alt-text="Screenshot showing the Desktop development with C plus plus workload."::: - - For C and C++, select the **Desktop development with C++** workload and then choose **Install**. - - :::image type="content" source="media/vscpp-concierge-choose-workload.gif" alt-text="Animation that shows the Desktop development with C plus plus workload then choose the Install button."::: - -1. When the installation completes, choose the **Launch** button to start Visual Studio. - - The first time you run Visual Studio, you're asked to sign in with a Microsoft Account. If you don't have one, you can create one for free. You must also choose a theme. Don't worry, you can change it later if you want to. - - It might take Visual Studio several minutes to get ready for use the first time you run it. - -1. When Visual Studio opens, check to see if the flag icon in the title bar is highlighted: - - :::image type="content" source="media/vscpp-first-start-page-flag.png" alt-text="Screenshot of the Visual Studio notification flag."::: - - If it's highlighted, select it to open the **Notifications** window. If there are any updates available for Visual Studio, we recommend you install them now. Once the installation is complete, restart Visual Studio. - -::: moniker-end - -::: moniker range=" [!NOTE] > A developer command prompt shortcut automatically sets the correct paths for the compiler and tools, and for any required headers and libraries. You must set these environment values yourself if you use a regular **Command Prompt** window. For more information, see [Use the MSVC toolset from the command line](./building-on-the-command-line.md). We recommend you use a developer command prompt shortcut instead of building your own. ### Open a developer command prompt -1. If you have installed Visual Studio 2017 or later on Windows 10 or later, open the Start menu and choose **All apps**. Scroll down and open the **Visual Studio** folder (not the Visual Studio application). Choose **Developer Command Prompt for VS** to open the command prompt window. +1. If you have Visual Studio 2017 or later on Windows 10 or later, open the **Start** menu and choose **All apps**. Scroll down and open the **Visual Studio** folder (not the Visual Studio application). Choose **Developer Command Prompt for VS** to open the command prompt window. - If you have installed Microsoft Visual Studio Build Tools 2015 on Windows 10 or later, open the **Start** menu and choose **All apps**. Scroll down and open the **Visual Studio Build Tools** folder. Choose **x86 Native Tools Command Prompt** to open the command prompt window. + If you have Microsoft Visual Studio Build Tools 2015 on Windows 10 or later, open the **Start** menu and choose **All apps**. Scroll down and open the **Visual Studio Build Tools** folder. Choose **x86 Native Tools Command Prompt** to open the command prompt window. - You can also use the Windows search function to search for "developer command prompt" and choose one that matches your installed version of Visual Studio. Use the shortcut to open the command prompt window. + You can also use the Windows search function to search for *developer command prompt* and choose one that matches your installed version of Visual Studio. Use the shortcut to open the command prompt window. -1. Next, verify that the C++ developer command prompt is set up correctly. In the command prompt window, enter `cl` and verify that the output looks something like this: +1. Verify that the C++ developer command prompt is set up correctly. In the command prompt window, enter `cl` and verify that the output looks something like this: ```Output C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise>cl @@ -45,25 +48,25 @@ Before you can build a C or C++ program on the command line, verify that the too usage: cl [ option... ] filename... [ /link linkoption... ] ``` - There may be differences in the current directory or version numbers. These values depend on the version of MSVC and any updates installed. If the above output is similar to what you see, then you're ready to build C or C++ programs at the command line. +There might be differences in the current directory or version numbers. These values depend on the version of MSVC and any updates installed. If the output is similar to what you see, then you're ready to build C or C++ programs at the command line. - > [!NOTE] - > If you get an error such as "'cl' is not recognized as an internal or external command, operable program or batch file," error C1034, or error LNK1104 when you run the **`cl`** command, then either you are not using a developer command prompt, or something is wrong with your installation of MSVC. You must fix this issue before you can continue. +> [!NOTE] +> If you get an error such as "'cl' isn't recognized as an internal or external command, operable program or batch file," error C1034, or error LNK1104 when you run the `cl` command, you aren't using a developer command prompt, or something is wrong with your installation of MSVC. You must fix this issue before you can continue. - If you can't find the developer command prompt shortcut, or if you get an error message when you enter `cl`, then your MSVC installation may have a problem. Try reinstalling the MSVC component in Visual Studio or Visual Studio Build Tools. Don't go on to the next section until the **`cl`** command works. For more information about installing and troubleshooting MSVC, see [Install Visual Studio](/visualstudio/install/install-visual-studio). +If you can't find the developer command prompt shortcut, or if you get an error message when you enter `cl`, then your MSVC installation might have a problem. Try reinstalling the MSVC component in Visual Studio or Visual Studio Build Tools. Don't go on to the next section until the `cl` command works. For more information about installing and troubleshooting MSVC, see [Install Visual Studio](/visualstudio/install/install-visual-studio). - > [!NOTE] - > Depending on the version of Windows on the computer and the system security configuration, you might have to right-click to open the shortcut menu for the developer command prompt shortcut and then choose **Run as administrator** to successfully build and run the program that you create by following this walkthrough. +> [!NOTE] +> Depending on the version of Windows on the computer and the system security configuration, you might have to right-click to open the shortcut menu for the developer command prompt shortcut and then choose **Run as administrator** to successfully build and run the program that you create by following this walkthrough. ### Create a C++ source file and compile it on the command line -1. In the developer command prompt window, enter `md c:\hello` to create a directory, and then enter `cd c:\hello` to change to that directory. This directory is where both your source file and the compiled program get created. +1. In the developer command prompt window, enter `md C:\hello` to create a directory, and then enter `cd C:\hello` to change to that directory. This directory is where both your source file and the compiled program get created. 1. Enter `notepad hello.cpp` in the command prompt window. - Choose **Yes** when Notepad prompts you to create a new file. This step opens a blank Notepad window, ready for you to enter your code in a file named hello.cpp. + Choose **Yes** when Notepad prompts you to create a new file. This step opens a blank Notepad window, ready for you to enter your code in a file named `hello.cpp`. -1. In Notepad, enter the following lines of code: +1. In Notepad, enter the following code: ```cpp #include @@ -74,40 +77,42 @@ Before you can build a C or C++ program on the command line, verify that the too } ``` - This code is a simple program that will write one line of text on the screen and then exit. To minimize errors, copy this code and paste it into Notepad. + This code is a simple program that writes one line of text on the screen and then exits. To minimize errors, copy this code and paste it into Notepad. 1. Save your work! In Notepad, on the **File** menu, choose **Save**. - Congratulations, you've created a C++ source file, hello.cpp, that is ready to compile. + Congratulations! You created a C++ source file, `hello.cpp`, that's ready to compile. -1. Switch back to the developer command prompt window. Enter `dir` at the command prompt to list the contents of the c:\hello directory. You should see the source file hello.cpp in the directory listing, which looks something like: +1. Switch back to the developer command prompt window. Enter `dir` at the command prompt to list the contents of the `C:\hello` directory. You should see the source file `hello.cpp` in the directory listing, which looks something like: ```Output - c:\hello>dir - Volume in drive C has no label. - Volume Serial Number is CC62-6545 - - Directory of c:\hello + C:\hello>dir + Volume in drive C is Local Disk + Volume Serial Number is AA11-BB22 - 05/24/2016 05:36 PM . - 05/24/2016 05:36 PM .. - 05/24/2016 05:37 PM 115 hello.cpp - 1 File(s) 115 bytes - 2 Dir(s) 571,343,446,016 bytes free + Directory of C:\hello + 04/28/2026 01:26 PM . + 04/28/2026 01:26 PM .. + 04/28/2026 01:27 PM 117 hello.cpp + 1 File(s) 117 bytes ``` The dates and other details will differ on your computer. > [!NOTE] - > If you don't see your source code file, *`hello.cpp`*, make sure the current working directory in your command prompt is the *`C:\hello`* directory you created. Also make sure that this is the directory where you saved your source file. And make sure that you saved the source code with a *`.cpp`* file name extension, not a *`.txt`* extension. Your source file gets saved in the current directory as a *`.cpp`* file automatically if you open Notepad at the command prompt by using the **`notepad hello.cpp`** command. Notepad's behavior is different if you open it another way: By default, Notepad appends a *`.txt`* extension to new files when you save them. It also defaults to saving files in your *Documents* directory. To save your file with a *`.cpp`* extension in Notepad, choose **File** > **Save As**. In the **Save As** dialog, navigate to your *`C:\hello`* folder in the directory tree view control. Then use the **Save as type** dropdown control to select **All Files (\*.\*)**. Enter *`hello.cpp`* in the **File name** edit control, and then choose **Save** to save the file. + > If you don't see your source code file, `hello.cpp`, make sure the current working directory in your command prompt is the `C:\hello` directory you created. Also make sure that this location is the directory where you saved your source file. + > + > Make sure that you saved the source code with a `.cpp` file name extension, not a `.txt` extension. Your source file gets saved in the current directory as a `.cpp` file automatically if you open Notepad at the command prompt by using the `notepad hello.cpp` command. + > + > Notepad's behavior is different if you open it another way: By default, Notepad appends a `.txt` extension to new files when you save them. It also defaults to saving files in your `Documents` directory. To save your file with a `.cpp` extension in Notepad, choose **File** > **Save As**. In the **Save As** dialog, navigate to your *C:\hello* folder in the directory tree view control. Then use the **Save as type** dropdown control to select **All Files (\*.\*)**. Enter `hello.cpp` in the **File name** edit control, and then choose **Save** to save the file. 1. At the developer command prompt, enter `cl /EHsc hello.cpp` to compile your program. The cl.exe compiler generates an .obj file that contains the compiled code, and then runs the linker to create an executable program named hello.exe. This name appears in the lines of output information that the compiler displays. The output of the compiler should look something like: ```Output - c:\hello>cl /EHsc hello.cpp + C:\hello>cl /EHsc hello.cpp Microsoft (R) C/C++ Optimizing Compiler Version 19.10.25017 for x86 Copyright (C) Microsoft Corporation. All rights reserved. @@ -120,9 +125,8 @@ Before you can build a C or C++ program on the command line, verify that the too ``` > [!NOTE] - > If you get an error such as "'cl' is not recognized as an internal or external command, operable program or batch file," error C1034, or error LNK1104, your developer command prompt is not set up correctly. For information on how to fix this issue, go back to the **Open a developer command prompt** section. - - > [!NOTE] + > If you get an error such as "'cl' isn't recognized as an internal or external command, operable program or batch file," error C1034, or error LNK1104, your developer command prompt isn't set up correctly. For information on how to fix this issue, go back to the **Open a developer command prompt** section. + > > If you get a different compiler or linker error or warning, review your source code to correct any errors, then save it and run the compiler again. For information about specific errors, use the search box to look for the error number. 1. To run the hello.exe program, at the command prompt, enter `hello`. @@ -133,27 +137,33 @@ Before you can build a C or C++ program on the command line, verify that the too Hello, world, from Microsoft C++! ``` - Congratulations, you've compiled and run a C++ program by using the command-line tools. + Congratulations! You compiled and ran a C++ program by using the command-line tools. ## Next steps This "Hello, World" example is about as simple as a C++ program can get. Real world programs usually have header files, more source files, and link to libraries. -You can use the steps in this walkthrough to build your own C++ code instead of typing the sample code shown. These steps also let you build many C++ code sample programs that you find elsewhere. You can put your source code and build your apps in any writeable directory. By default, the Visual Studio IDE creates projects in your user folder, in a *source\\repos* subfolder. Older versions may put projects in a *Documents\\Visual Studio \\\Projects* folder. +You can use the steps in this walkthrough to build your own C++ code instead of typing the sample code shown. These steps also let you build many C++ code sample programs that you find elsewhere. You can put your source code and build your apps in any writable directory. By default, the Visual Studio IDE creates projects in your user folder, in a `source\repos` subfolder. Older versions might put projects in a `Documents\Visual Studio \{version}\Projects` folder. -To compile a program that has additional source code files, enter them all on the command line, like: +To compile a program that has other source code files, enter them all on the command line, like: -`cl /EHsc file1.cpp file2.cpp file3.cpp` +```cmd +cl /EHsc file1.cpp file2.cpp file3.cpp +``` The `/EHsc` command-line option instructs the compiler to enable standard C++ exception handling behavior. Without it, thrown exceptions can result in undestroyed objects and resource leaks. For more information, see [/EH (Exception Handling Model)](reference/eh-exception-handling-model.md). -When you supply additional source files, the compiler uses the first input file to create the program name. In this case, it outputs a program called file1.exe. To change the name to program1.exe, add an [/out](reference/out-output-file-name.md) linker option: +When you supply other source files, the compiler uses the first input file to create the program name. In this case, it outputs a program called `file1.exe`. To change the name to `program1.exe`, add an [/out](reference/out-output-file-name.md) linker option: -`cl /EHsc file1.cpp file2.cpp file3.cpp /link /out:program1.exe` +```cmd +cl /EHsc file1.cpp file2.cpp file3.cpp /link /out:program1.exe +``` -And to catch more programming mistakes automatically, we recommend you compile by using either the [/W3](reference/compiler-option-warning-level.md) or [/W4](reference/compiler-option-warning-level.md) warning level option: +To catch more programming mistakes automatically, we recommend you compile by using either the [/W3](reference/compiler-option-warning-level.md) or [/W4](reference/compiler-option-warning-level.md) warning level option: -`cl /W4 /EHsc file1.cpp file2.cpp file3.cpp /link /out:program1.exe` +```cmd +cl /W4 /EHsc file1.cpp file2.cpp file3.cpp /link /out:program1.exe +``` The compiler, cl.exe, has many more options. You can apply them to build, optimize, debug, and analyze your code. For a quick list, enter `cl /?` at the developer command prompt. You can also compile and link separately and apply linker options in more complex build scenarios. For more information on compiler and linker options and usage, see [C/C++ Building Reference](reference/c-cpp-building-reference.md). @@ -165,6 +175,6 @@ The MSVC compiler includes a C Runtime Library (CRT) that conforms to the ISO C9 ## See also -[C++ Language Reference](../cpp/cpp-language-reference.md)
-[Projects and build systems](projects-and-build-systems-cpp.md)
-[MSVC Compiler Options](reference/compiler-options.md) +- [C++ Language Reference](../cpp/cpp-language-reference.md) +- [Projects and build systems](projects-and-build-systems-cpp.md) +- [MSVC Compiler Options](reference/compiler-options.md) diff --git a/docs/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp.md b/docs/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp.md index ac858bc073f..93f493a1816 100644 --- a/docs/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp.md +++ b/docs/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp.md @@ -1,10 +1,11 @@ --- -title: "Create and Use Your Own Dynamic-Link Library (C++)" -description: "Learn how to use C++ to create a Windows dynamic-link library (DLL) in Visual Studio." +title: Create and Use Your Own Dynamic-Link Library (C++) +description: Learn how to build a C++ DLL in Visual Studio. This tutorial walks you through creating exported functions, a console client app, and running the finished project. ms.topic: tutorial -ms.date: 03/17/2025 +ms.date: 07/28/2026 helpviewer_keywords: ["libraries [C++], DLLs", "DLLs [C++], walkthroughs"] ms.custom: sfi-image-nochange +#customer intent: As a C++ developer, I want to create a dynamic-link library in Visual Studio, so that I can share code and resources across multiple apps. --- # Walkthrough: Create and use your own dynamic-link library (C++) @@ -20,23 +21,23 @@ This walkthrough covers the following steps: - Use the functions and variables imported from the DLL in the console app. - Run the completed app. -Like a statically linked library, a DLL _exports_ variables, functions, and resources by name. A client app _imports_ the names to use those variables, functions, and resources. Unlike a statically linked library, Windows connects the imports in your app to the exports in a DLL at load time or at run time, instead of connecting them at link time. Windows requires extra information that isn't part of the standard C++ compilation model to make these connections. The MSVC compiler implements some Microsoft-specific extensions to C++ to provide this extra information. We explain these extensions as we go. +Like a statically linked library, a DLL _exports_ variables, functions, and resources by name. A client app _imports_ the names to use those variables, functions, and resources. Unlike a statically linked library, Windows connects the imports in your app to the exports in a DLL at load time or at run time, instead of connecting them at link time. Windows requires extra information that isn't part of the standard C++ compilation model to make these connections. The MSVC compiler implements some Microsoft-specific extensions to C++ to provide this extra information. The walkthrough explains these extensions as you go. This walkthrough creates two Visual Studio solutions: one that builds the DLL, and one that builds the client app. The DLL uses the C calling convention. It can be called from apps written in other programming languages, as long as the platform, calling conventions, and linking conventions match. The client app uses _implicit linking_, where Windows links the app to the DLL at load time. This linking lets the app call the DLL-supplied functions just like the functions in a statically linked library. This walkthrough doesn't cover some common situations. The code doesn't show the use of C++ DLLs by other programming languages. It doesn't show how to [create a resource-only DLL](creating-a-resource-only-dll.md), or how to use [explicit linking](linking-an-executable-to-a-dll.md#linking-explicitly) to load DLLs at run time rather than at load time. Rest assured, you can use MSVC and Visual Studio to do all these things. -Even though the code of the DLL is written in C++, we use C-style interfaces for the exported functions. There are two main reasons for this: First, many other languages support imports of C-style functions. The client app doesn't have to be written in C++. Second, it avoids some common pitfalls related to exported classes and member functions. It's easy to make hard-to-diagnose errors when exporting classes, since everything referred to within a class declaration has to have an instantiation that's also exported. This restriction applies to DLLs, but not static libraries. If your classes are plain-old-data style, you shouldn't run into this issue. +Even though the code of the DLL is written in C++, use C-style interfaces for the exported functions. There are two main reasons for this choice: First, many other languages support imports of C-style functions. The client app doesn't have to be written in C++. Second, it avoids some common pitfalls related to exported classes and member functions. It's easy to make hard-to-diagnose errors when exporting classes, since everything referred to within a class declaration has to have an instantiation that's also exported. This restriction applies to DLLs, but not static libraries. If your classes are plain-old-data style, you shouldn't run into this issue. For links to more information about DLLs, see [Create C/C++ DLLs in Visual Studio](dlls-in-visual-cpp.md). For more information about implicit linking and explicit linking, see [Determine which linking method to use](linking-an-executable-to-a-dll.md#determining-which-linking-method-to-use). For information about creating C++ DLLs for use with programming languages that use C-language linkage conventions, see [Exporting C++ functions for use in C-language executables](exporting-cpp-functions-for-use-in-c-language-executables.md). For information about how to create DLLs for use with .NET languages, see [Calling DLL Functions from Visual Basic Applications](calling-dll-functions-from-visual-basic-applications.md). ## Prerequisites -- Microsoft Windows 7 or later. We recommend the latest version of Windows for the best development experience. +- Windows 7 or later. For the best development experience, use the latest version of Windows. ::: moniker range=">=msvc-150" -- Visual Studio. To learn how to download and install Visual Studio, see [Install Visual Studio](/visualstudio/install/install-visual-studio). When you run the installer, make sure that the **Desktop development with C++** workload is checked. Don't worry if you didn't install this workload when you installed Visual Studio. You can run the installer again and install it now. +- Visual Studio. To learn how to download and install Visual Studio, see [Install Visual Studio](/visualstudio/install/install-visual-studio). When you run the installer, make sure that the **Desktop development with C++** workload is checked. If you didn't install this workload when you installed Visual Studio, don't worry. You can run the installer again and install it now. :::image type="content" source="media/desktop-development-with-cpp.png" alt-text="Screenshot of the Visual Studio Installer, Desktop development with C++ workload."::: @@ -48,9 +49,9 @@ For links to more information about DLLs, see [Create C/C++ DLLs in Visual Studi ::: moniker-end -- An understanding of the basics of using the Visual Studio IDE. If you've used Windows desktop apps before, you can probably keep up. For an introduction, see [Visual Studio IDE feature tour](/visualstudio/ide/visual-studio-ide). +- An understanding of the basics of using the Visual Studio IDE. If you used Windows desktop apps before, you can probably keep up. For an introduction, see [Visual Studio IDE feature tour](/visualstudio/ide/visual-studio-ide). -- Some familiarity with the C++ language. Don't worry, we don't do anything too complicated. +- Some familiarity with the C++ language. Don't worry, the walkthrough doesn't cover anything too complicated. ::: moniker range="msvc-150" @@ -67,17 +68,19 @@ In the following set of tasks, you create a project for your DLL, add code, and ### To create a DLL project in Visual Studio -1. On the menu bar, choose **File** > **New** > **Project** to open the **Create a New Project** dialog box. +1. On the menu bar, select **File** > **New** > **Project** to open the **Create a New Project** dialog. - :::image type="content" source="media/create-new-dll-project-2019.png" alt-text="Screenshot of the Create a new project dialog box with the dynamic-link library template highlighted."::: + :::image type="content" source="media/create-new-dll-project-2019.png" alt-text="Screenshot of the Create a new project dialog with the dynamic-link library template highlighted."::: 1. At the top of the dialog, set **Language** to **C++**, set **Platform** to **Windows**, and set **Project type** to **Library**. -1. From the filtered list of project types, select **Dynamic-link Library (DLL)**, and then choose **Next**. +1. From the filtered list of project types, select **Dynamic-link Library (DLL)**, and then select **Next**. + + If you don't see that type, make sure you have **Desktop development with C++** installed, as described in the prerequisites. 1. In the **Configure your new project** page, enter *MathLibrary* in the **Project name** box to specify a name for the project. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Uncheck **Place solution and project in the same directory** if it's checked. -1. Choose the **Create** button to create the project. +1. Select the **Create** button to create the project. When the solution is created, you can see the generated project and source files in the **Solution Explorer** window in Visual Studio. @@ -89,13 +92,13 @@ When the solution is created, you can see the generated project and source files ### To create a DLL project in Visual Studio 2017 -1. On the menu bar, choose **File** > **New** > **Project** to open the **New Project** dialog box. +1. On the menu bar, select **File** > **New** > **Project** to open the **New Project** dialog. -1. In the left pane of the **New Project** dialog box, select **Installed** > **Visual C++** > **Windows Desktop**. In the center pane, select **Dynamic-Link Library (DLL)**. Enter *MathLibrary* in the **Name** box to specify a name for the project. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Check **Create directory for solution** if it's unchecked. +1. In the left pane of the **New Project** dialog, select **Installed** > **Visual C++** > **Windows Desktop**. In the center pane, select **Dynamic-Link Library (DLL)**. Enter *MathLibrary* in the **Name** box to specify a name for the project. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Check **Create directory for solution** if it's unchecked. - :::image type="content" source="media/mathlibrary-new-project-name-159.png" alt-text="Screenshot of the New Project dialog box in Visual Studio 2017 showing Math Library in the Name text box."::: + :::image type="content" source="media/mathlibrary-new-project-name-159.png" alt-text="Screenshot of the New Project dialog in Visual Studio 2017 showing Math Library in the Name text box."::: -1. Choose the **OK** button to create the project. +1. Select the **OK** button to create the project. When the solution is created, you can see the generated project and source files in the **Solution Explorer** window in Visual Studio. @@ -107,23 +110,23 @@ When the solution is created, you can see the generated project and source files ### To create a DLL project in Visual Studio 2015 and older versions -1. On the menu bar, choose **File** > **New** > **Project**. +1. On the menu bar, select **File** > **New** > **Project**. -1. In the left pane of the **New Project** dialog box, expand **Installed** > **Templates**, and select **Visual C++**, and then in the center pane, select **Win32 Console Application**. Enter *MathLibrary* in the **Name** edit box to specify a name for the project. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Check **Create directory for solution** if it's unchecked. +1. In the left pane of the **New Project** dialog, expand **Installed** > **Templates**, and select Visual C++. In the center pane, select **Win32 Console Application**. Enter *MathLibrary* as the **Name** for the project. Don't change the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Select **Create directory for solution**. - :::image type="content" source="media/mathlibrary-project-name.png" alt-text="Screenshot of the New Project dialog box in Visual Studio 2015 showing MathLibrary in the Name text box."::: + :::image type="content" source="media/mathlibrary-project-name.png" alt-text="Screenshot of the New Project dialog in Visual Studio 2015 showing MathLibrary in the Name text box."::: -1. Choose the **OK** button to dismiss the **New Project** dialog and start the **Win32 Application Wizard**. +1. Select **OK** to dismiss the **New Project** dialog and start the **Win32 Application Wizard**. :::image type="content" source="media/mathlibrary-project-wizard-1.png" alt-text="Screenshot of the Win32 Application Wizard Overview page."::: -1. Choose the **Next** button. On the **Application Settings** page, under **Application type**, select **DLL**. +1. Select **Next**. On the **Application Settings** page, under **Application type**, select **DLL**. :::image type="content" source="media/mathlibrary-project-wizard-2.png" alt-text="Screenshot of the Win32 Application Wizard Application Settings Page."::: -1. Choose the **Finish** button to create the project. +1. Select **Finish** to create the project. -When the wizard completes the solution, you can see the generated project and source files in the **Solution Explorer** window in Visual Studio. +When the wizard finishes the solution, you can see the generated project and source files in the **Solution Explorer** window in Visual Studio. :::image type="content" source="media/mathlibrary-solution-explorer-153.png" alt-text="Screenshot of the Solution Explorer window in Visual Studio 2015 with the MathLibrary highlighted."::: @@ -133,13 +136,13 @@ Right now, this DLL doesn't do very much. Next, you'll create a header file to d ### To add a header file to the DLL -1. To create a header file for your functions, on the menu bar, choose **Project** > **Add New Item**. +1. To create a header file for your functions, on the menu bar, select **Project** > **Add New Item**. -1. In the **Add New Item** dialog box, in the left pane, select **Visual C++**. In the center pane, select **Header File (.h)**. Specify *`MathLibrary.h`* as the name for the header file. +1. In the **Add New Item** dialog, in the left pane, select **Visual C++**. In the center pane, select **Header File (.h)**. Specify *`MathLibrary.h`* as the name for the header file. :::image type="content" source="media/mathlibrary-add-new-item-header-file.png" alt-text="Screenshot of the Add New Item dialog with the C plus plus Header File template selected, and MathLibrary.h entered in the Name textbox."::: -1. Choose the **Add** button to generate a blank header file, which is displayed in a new editor window. +1. Select the **Add** button to generate a blank header file, which is displayed in a new editor window. :::image type="content" source="media/edit-empty-mathlibrary-header.png" alt-text="Screenshot of the empty MathLibrary.h file in the editor."::: @@ -192,7 +195,7 @@ When the `MATHLIBRARY_EXPORTS` macro is defined, the `MATHLIBRARY_API` macro set ::: moniker range=">=msvc-160" -1. In **Solution Explorer**, right-click on the **Source Files** node and choose **Add** > **New Item**. Create a new *`.cpp`* file called *`MathLibrary.cpp`*, in the same way that you added a new header file in the previous step. +1. In **Solution Explorer**, right-click the **Source Files** node and select **Add** > **New Item**. Create a new *`.cpp`* file named *`MathLibrary.cpp`*, just like you added a new header file in the previous step. 1. In the editor window, select the *`MathLibrary.cpp`* tab if it's already open. If not, in **Solution Explorer**, double-click *`MathLibrary.cpp`* in the **Source Files** folder of the **MathLibrary** project to open it. @@ -326,7 +329,7 @@ When the `MATHLIBRARY_EXPORTS` macro is defined, the `MATHLIBRARY_API` macro set ::: moniker-end -To verify that everything works so far, compile the DLL. To compile, choose **Build** > **Build Solution** on the menu bar. The DLL and related compiler output are placed in a folder called `Debug` directly below the solution folder. If you create a Release build, the output is placed in a folder called `Release`. The output should look something like this: +To verify that everything works so far, compile the DLL. To compile, select **Build** > **Build Solution** on the menu bar. The DLL and related compiler output are placed in a folder called `Debug` directly below the solution folder. If you create a Release build, the output is placed in a folder called `Release`. The output should look something like this: ::: moniker range=">=msvc-160" @@ -373,7 +376,7 @@ To verify that everything works so far, compile the DLL. To compile, choose **Bu ::: moniker-end -Congratulations, you've created a DLL using Visual Studio! Next, you'll create a client app that uses the functions exported by the DLL. +Congratulations, you created a DLL by using Visual Studio! Next, you create a client app that uses the functions the DLL exports. ## Create a client app that uses the DLL @@ -381,23 +384,23 @@ When you create a DLL, think about how client apps might use it. To call the fun Whether it's your own or from a third-party, your client app project needs several pieces of information to use a DLL. It needs to find the headers that declare the DLL exports, the import libraries for the linker, and the DLL itself. One solution is to copy all of these files into your client project. For third-party DLLs that are unlikely to change while your client is in development, this method might be the best way to use them. However, when you also build the DLL, it's better to avoid duplication. If you make a local copy of DLL files that are under development, you might accidentally change a header file in one copy but not the other, or use an out-of-date library. -To avoid out-of-sync code, we recommend you set the include path in your client project to include the DLL header files directly from your DLL project. Also, set the library path in your client project to include the DLL import libraries from the DLL project. And finally, copy the built DLL from the DLL project into your client build output directory. This step allows your client app to use the same DLL code you build. +To avoid out-of-sync code, set the include path in your client project to include the DLL header files directly from your DLL project. Also, set the library path in your client project to include the DLL import libraries from the DLL project. Finally, copy the built DLL from the DLL project into your client build output directory. This step allows your client app to use the same DLL code you build. ::: moniker range=">=msvc-160" ### To create a client app in Visual Studio -1. On the menu bar, choose **File** > **New** > **Project** to open the **Create a new project** dialog box. +1. On the menu bar, select **File** > **New** > **Project** to open the **Create a new project** dialog. 1. At the top of the dialog, set **Language** to **C++**, set **Platform** to **Windows**, and set **Project type** to **Console**. -1. From the filtered list of project types, choose **Console App** then choose **Next**. +1. From the filtered list of project types, select **Console App** then select **Next**. 1. In the **Configure your new project** page, enter *MathClient* in the **Project name** box to specify a name for the project. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Uncheck **Place solution and project in the same directory** if it's checked. - :::image type="content" source="media/mathclient-project-name-2019.png" alt-text="Screenshot of the Create a new project dialog box with the Console App option highlighted."::: + :::image type="content" source="media/mathclient-project-name-2019.png" alt-text="Screenshot of the Create a new project dialog with the Console App option highlighted."::: -1. Choose the **Create** button to create the client project. +1. Select the **Create** button to create the client project. A minimal console application project is created for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named *`MathClient.cpp`*. You can build it, but it doesn't use your DLL yet. @@ -407,13 +410,13 @@ A minimal console application project is created for you. The name for the main ### To create a client app in Visual Studio 2017 -1. To create a C++ app that uses the DLL that you created, on the menu bar, choose **File** > **New** > **Project**. +1. To create a C++ app that uses the DLL you created, on the menu bar, select **File** > **New** > **Project**. -1. In the left pane of the **New Project** dialog, select **Windows Desktop** under **Installed** > **Visual C++**. In the center pane, select **Windows Console Application**. Specify the name for the project, *MathClient*, in the **Name** edit box. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Check **Create directory for solution** if it's unchecked. +1. In the left pane of the **New Project** dialog, select **Windows Desktop** under **Installed** > Visual C++. In the center pane, select **Windows Console Application**. Enter *MathClient* in the **Name** box. Keep the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Check **Create directory for solution** if it's unchecked. - :::image type="content" source="media/mathclient-new-project-name-159.png" alt-text="Screenshot of the New Project dialog box with Windows Console Application highlighted, and Math Client typed in the Name text box."::: + :::image type="content" source="media/mathclient-new-project-name-159.png" alt-text="Screenshot of the New Project dialog with Windows Console Application highlighted, and Math Client typed in the Name text box."::: -1. Choose **OK** to create the client app project. +1. Select **OK** to create the client app project. A minimal console application project is created for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named *`MathClient.cpp`*. You can build it, but it doesn't use your DLL yet. @@ -423,39 +426,39 @@ A minimal console application project is created for you. The name for the main ### To create a client app in Visual Studio 2015 -1. To create a C++ app that uses the DLL that you created, on the menu bar, choose **File** > **New** > **Project**. +1. To create a C++ app that uses the DLL you created, on the menu bar, select **File** > **New** > **Project**. 1. In the left pane of the **New Project** dialog, select **Win32** under **Installed** > **Templates** > **Visual C++**. In the center pane, select **Win32 Console Application**. Specify the name for the project, *MathClient*, in the **Name** edit box. Leave the default **Location** and **Solution name** values. Set **Solution** to **Create new solution**. Check **Create directory for solution** if it's unchecked. - :::image type="content" source="media/mathclient-project-name.png" alt-text="Screenshot of the New Project dialog box with Win32 Console Application Visual C plus plus highlighted, and Math Client typed in the Name text box."::: + :::image type="content" source="media/mathclient-project-name.png" alt-text="Screenshot of the New Project dialog with Win32 Console Application Visual C plus plus highlighted, and Math Client typed in the Name text box."::: -1. Choose the **OK** button to dismiss the **New Project** dialog and start the **Win32 Application Wizard**. On the **Overview** page of the **Win32 Application Wizard** dialog box, choose the **Next** button. +1. Select the **OK** button to dismiss the **New Project** dialog and start the **Win32 Application Wizard**. On the **Overview** page of the **Win32 Application Wizard** dialog, select the **Next** button. 1. On the **Application Settings** page, under **Application type**, select **Console application** if it isn't already selected. -1. Choose the **Finish** button to create the project. +1. Select **Finish** to create the project. -When the wizard finishes, a minimal console application project is created for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named *`MathClient.cpp`*. You can build it, but it doesn't use your DLL yet. +When the wizard finishes, it creates a minimal console application project for you. The name for the main source file is the same as the project name that you entered earlier. In this example, it's named *`MathClient.cpp`*. You can build it, but it doesn't use your DLL yet. ::: moniker-end -Next, to call the MathLibrary functions in your source code, your project must include the *`MathLibrary.h`* file. You could copy this header file into your client app project, then add it to the project as an existing item. This method can be a good choice for third-party libraries. However, if you're working on the code for your DLL and your client at the same time, the header files could get out of sync. To avoid this issue, set the **Additional Include Directories** path in your project to include the path to the original header. +Next, to call the MathLibrary functions in your source code, your project must include the *`MathLibrary.h`* file. You can copy this header file into your client app project, then add it to the project as an existing item. This method can be a good choice for third-party libraries. However, if you're working on the code for your DLL and your client at the same time, the header files can get out of sync. To avoid this issue, set the **Additional Include Directories** path in your project to include the path to the original header. ### To add the DLL header to your include path -1. Right-click on the **MathClient** node in **Solution Explorer** to open the **Property Pages** dialog. +1. Right-click the **MathClient** node in **Solution Explorer** to open the **Property Pages** dialog. 1. In the **Configuration** dropdown box, select **All Configurations** if it's not already selected. 1. In the left pane, select **Configuration Properties** > **C/C++** > **General**. -1. In the property pane, select the dropdown control next to the **Additional Include Directories** edit box, and then choose **Edit**. +1. In the property pane, select the dropdown control next to the **Additional Include Directories** edit box, and then select **Edit**. :::image type="content" source="media/mathclient-additional-include-directories-property.png" alt-text="Screenshot of the Property Pages dialog showing the Edit command in the Additional Include Directories property dropdown."::: -1. Double-click in the top pane of the **Additional Include Directories** dialog box to enable an edit control. Or, choose the folder icon to create a new entry. +1. Double-click in the top pane of the **Additional Include Directories** dialog to enable an edit control. Or, select the folder icon to create a new entry. -1. In the edit control, specify the path to the location of the *`MathLibrary.h`* header file. You can choose the ellipsis (**...**) control to browse to the correct folder. +1. In the edit control, specify the path to the location of the *`MathLibrary.h`* header file. You can select the ellipsis (**...**) control to browse to the correct folder. You can also enter a relative path from your client source files to the folder that contains the DLL header files. If you followed the directions to put your client project in a separate solution from the DLL, the relative path should look like this: @@ -469,7 +472,7 @@ Next, to call the MathLibrary functions in your source code, your project must i :::image type="content" source="media/mathclient-additional-include-directories.png" alt-text="Screenshot of the Additional Include Directories dialog showing the relative path to the MathLibrary directory."::: -1. After you've entered the path to the header file in the **Additional Include Directories** dialog box, choose the **OK** button. In the **Property Pages** dialog box, choose the **OK** button to save your changes. +1. After you enter the path to the header file in the **Additional Include Directories** dialog, select **OK**. In the **Property Pages** dialog, select **OK** to save your changes. You can now include the *`MathLibrary.h`* file and use the functions it declares in your client application. Replace the contents of *`MathClient.cpp`* by using this code: @@ -495,31 +498,31 @@ int main() } ``` -This code can be compiled, but not linked. If you build the client app now, the error list shows several LNK2019 errors. That's because your project is missing some information: You haven't specified that your project has a dependency on the *`MathLibrary.lib`* library yet. And, you haven't told the linker how to find the *`MathLibrary.lib`* file. +This code can be compiled, but not linked. If you build the client app now, the error list shows several LNK2019 errors. That's because your project is missing some information: You didn't specify that your project has a dependency on the *`MathLibrary.lib`* library yet. And, you didn't tell the linker how to find the *`MathLibrary.lib`* file. -To fix this issue, you could copy the library file directly into your client app project. The linker would find and use it automatically. However, if both the library and the client app are under development, that might lead to changes in one copy that aren't shown in the other. To avoid this issue, you can set the **Additional Dependencies** property to tell the build system that your project depends on *`MathLibrary.lib`*. And, you can set an **Additional Library Directories** path in your project to include the path to the original library when you link. +To fix this problem, you could copy the library file directly into your client app project. The linker would find and use it automatically. However, if both the library and the client app are under development, that action might lead to changes in one copy that aren't shown in the other. To avoid this problem, set the **Additional Dependencies** property to tell the build system that your project depends on *`MathLibrary.lib`*. And, set an **Additional Library Directories** path in your project to include the path to the original library when you link. ### To add the DLL import library to your project -1. Right-click on the **MathClient** node in **Solution Explorer** and choose **Properties** to open the **Property Pages** dialog. +1. Right-click the **MathClient** node in **Solution Explorer** and select **Properties** to open the **Property Pages** dialog. -1. In the **Configuration** dropdown box, select **All Configurations** if it's not already selected. It ensures that any property changes apply to both Debug and Release builds. +1. In the **Configuration** dropdown box, select **All Configurations** if it's not already selected. This selection ensures that any property changes apply to both Debug and Release builds. -1. In the left pane, select **Configuration Properties** > **Linker** > **Input**. In the property pane, select the dropdown control next to the **Additional Dependencies** edit box, and then choose **Edit**. +1. In the left pane, select **Configuration Properties** > **Linker** > **Input**. In the property pane, select the dropdown control next to the **Additional Dependencies** edit box, and then select **Edit**. - :::image type="content" source="media/mathclient-additional-dependencies-property.png" alt-text="Screenshot of the Property Pages dialog box under Input that shows the Edit command in the Additional Dependencies property dropdown."::: + :::image type="content" source="media/mathclient-additional-dependencies-property.png" alt-text="Screenshot of the Property Pages dialog under Input that shows the Edit command in the Additional Dependencies property dropdown."::: 1. In the **Additional Dependencies** dialog, add *`MathLibrary.lib`* to the list in the top edit control. - :::image type="content" source="media/mathclient-additional-dependencies.png" alt-text="Screenshot of the Additional Dependencies dialog box showing the MathLibrary.lib file."::: + :::image type="content" source="media/mathclient-additional-dependencies.png" alt-text="Screenshot of the Additional Dependencies dialog showing the MathLibrary.lib file."::: -1. Choose **OK** to go back to the **Property Pages** dialog box. +1. Select **OK** to go back to the **Property Pages** dialog. -1. In the left pane, select **Configuration Properties** > **Linker** > **General**. In the property pane, select the dropdown control next to the **Additional Library Directories** edit box, and then choose **Edit**. +1. In the left pane, select **Configuration Properties** > **Linker** > **General**. In the property pane, select the dropdown control next to the **Additional Library Directories** edit box, and then select **Edit**. - :::image type="content" source="media/mathclient-additional-library-directories-property.png" alt-text="Screenshot of the Property Pages dialog box under General that shows the Edit command in the Additional Library Directories property dropdown."::: + :::image type="content" source="media/mathclient-additional-library-directories-property.png" alt-text="Screenshot of the Property Pages dialog under General that shows the Edit command in the Additional Library Directories property dropdown."::: -1. Double-click in the top pane of the **Additional Library Directories** dialog box to enable an edit control. In the edit control, specify the path to the location of the *`MathLibrary.lib`* file. By default, it's in a folder called *Debug* directly under the DLL solution folder. If you create a release build, the file is placed in a folder called *Release*. You can use the `$(IntDir)` macro so that the linker can find your DLL, no matter which kind of build you create. If you followed the directions to put your client project in a separate solution from the DLL project, the relative path should look like this: +1. Double-click in the top pane of the **Additional Library Directories** dialog to enable an edit control. In the edit control, specify the path to the location of the *`MathLibrary.lib`* file. By default, it's in a folder called *Debug* directly under the DLL solution folder. If you create a release build, the file is placed in a folder called *Release*. You can use the `$(IntDir)` macro so that the linker can find your DLL, no matter which kind of build you create. If you followed the directions to put your client project in a separate solution from the DLL project, the relative path should look like this: `..\..\MathLibrary\$(IntDir)` @@ -527,23 +530,23 @@ To fix this issue, you could copy the library file directly into your client app :::image type="content" source="media/mathclient-additional-library-directories.png" alt-text="Screenshot of the Additional Library Directories dialog."::: -1. Once you've entered the path to the library file in the **Additional Library Directories** dialog box, choose the **OK** button to go back to the **Property Pages** dialog box. Choose **OK** to save the property changes. +1. After you enter the path to the library file in the **Additional Library Directories** dialog, select **OK** to go back to the **Property Pages** dialog. Select **OK** to save the property changes. -Your client app can now compile and link successfully, but it still doesn't have everything it needs to run. When the operating system loads your app, it looks for the MathLibrary DLL. If it can't find the DLL in certain system directories, the environment path, or the local app directory, the load fails. Depending on the operating system, you'll see an error message like this: +Your client app can now compile and link successfully, but it still doesn't have everything it needs to run. When the operating system loads your app, it looks for the MathLibrary DLL. If it can't find the DLL in certain system directories, the environment path, or the local app directory, the load fails. Depending on the operating system, you see an error message like this: :::image type="content" source="media/mathclient-system-error-mathlibrary-dll-not-found.png" alt-text="Screenshot of the error dialog, MathLibrary DLL not found."::: -One way to avoid this issue is to copy the DLL to the directory that contains your client executable as part of the build process. You can add a *post-build event* to your project, to add a command that copies the DLL to your build output directory. The command specified here copies the DLL only if it's missing or has changed. It uses macros to copy to and from the Debug or Release locations, based on your build configuration. +One way to avoid this problem is to copy the DLL to the directory that contains your client executable as part of the build process. You can add a *post-build event* to your project, to add a command that copies the DLL to your build output directory. The command you specify here copies the DLL only if it's missing or changed. It uses macros to copy to and from the Debug or Release locations, based on your build configuration. ### To copy the DLL in a post-build event -1. Right-click on the **MathClient** node in **Solution Explorer** and choose **Properties** to open the **Property Pages** dialog. +1. Right-click the **MathClient** node in **Solution Explorer** and select **Properties** to open the **Property Pages** dialog. 1. In the **Configuration** dropdown box, select **All Configurations** if it isn't already selected. 1. In the left pane, select **Configuration Properties** > **Build Events** > **Post-Build Event**. -1. In the property pane, select the edit control in the **Command Line** field. If you followed the directions to put your client project in a separate solution from the DLL project, then enter this command: +1. In the property pane, select the edit control in the **Command Line** field. If you followed the directions to put your client project in a separate solution from the DLL project, enter this command: `xcopy /y /d "..\..\MathLibrary\$(IntDir)MathLibrary.dll" "$(OutDir)"` @@ -551,9 +554,9 @@ One way to avoid this issue is to copy the DLL to the directory that contains yo :::image type="content" source="media/mathclient-post-build-command-line.png" alt-text="Screenshot of the Property Pages dialog showing the post build event command line property."::: -1. Choose the **OK** button to save your changes to the project properties. +1. Select **OK** to save your changes to the project properties. -Now your client app has everything it needs to build and run. Build the application by choosing **Build** > **Build Solution** on the menu bar. The **Output** window in Visual Studio should have something like the following example depending on your version of Visual Studio: +Your client app now has everything it needs to build and run. Build the application by selecting **Build** > **Build Solution** on the menu bar. The **Output** window in Visual Studio shows something like the following example depending on your version of Visual Studio: ```Output 1>------ Build started: Project: MathClient, Configuration: Debug Win32 ------ @@ -563,15 +566,15 @@ Now your client app has everything it needs to build and run. Build the applicat ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== ``` -Congratulations, you've created an application that calls functions in your DLL. Now run your application to see what it does. On the menu bar, choose **Debug** > **Start Without Debugging**. Visual Studio opens a command window for the program to run in. The last part of the output should look like: +You created an application that calls functions in your DLL. Now run your application to see what it does. On the menu bar, select **Debug** > **Start Without Debugging**. Visual Studio opens a command window for the program to run in. The last part of the output looks like: :::image type="content" source="media/mathclient-run-without-debugging.png" alt-text="Screenshot of the command window output when you start the client app without debugging."::: Press any key to dismiss the command window. -Now that you've created a DLL and a client application, you can experiment. Try setting breakpoints in the code of the client app, and run the app in the debugger. See what happens when you step into a library call. Add other functions to the library, or write another client app that uses your DLL. +Now that you created a DLL and a client application, you can experiment. Try setting breakpoints in the code of the client app, and run the app in the debugger. See what happens when you step into a library call. Add other functions to the library, or write another client app that uses your DLL. -When you deploy your app, you must also deploy the DLLs it uses. The simplest way to make the DLLs that you build, or that you include from third parties, available is to put them in the same directory as your app. It's known as *app-local deployment*. For more information about deployment, see [Deployment in Microsoft C++](../windows/deployment-in-visual-cpp.md). +When you deploy your app, you must also deploy the DLLs it uses. The simplest way to make the DLLs that you build, or that you include from third parties, available is to put them in the same directory as your app. This approach is known as *app-local deployment*. For more information about deployment, see [Deployment in Microsoft C++](../windows/deployment-in-visual-cpp.md). ## See also diff --git a/docs/build/walkthrough-creating-and-using-a-static-library-cpp.md b/docs/build/walkthrough-creating-and-using-a-static-library-cpp.md index 6ca15699093..80c6daafcfe 100644 --- a/docs/build/walkthrough-creating-and-using-a-static-library-cpp.md +++ b/docs/build/walkthrough-creating-and-using-a-static-library-cpp.md @@ -1,14 +1,15 @@ --- title: "Walkthrough: Create and use a static library (C++)" -description: "Use C++ to create a static library (.lib) in Visual Studio." +description: Learn to create and use a static library in C++ using Visual Studio. This walkthrough covers building a .lib file, adding a class, and referencing it in an app. ms.custom: "get-started-article" -ms.date: 10/28/2021 +ms.date: 07/14/2026 helpviewer_keywords: ["libraries [C++], static", "static libraries [C++]"] ms.assetid: 3cc36411-7d66-4240-851e-dacb9a8fd6ac +#customer intent: As a C++ developer, I want to create a static library in Visual Studio, so that I can reuse common code across multiple apps. --- # Walkthrough: Create and use a static library -This step-by-step walkthrough shows how to create a static library (.lib file) for use with C++ apps. Using a static library is a great way to reuse code. Rather than reimplementing the same routines in every app that requires the functionality, you write them one time in a static library and then reference it from the apps. Code linked from a static library becomes part of your app—you don't have to install another file to use the code. +This step-by-step walkthrough shows how to create a static library (.lib file) for use with C++ apps. Using a static library is a great way to reuse code. Rather than reimplementing the same routines in every app that requires the functionality, write them one time in a static library and then reference it from the apps. Code linked from a static library becomes part of your app. You don't have to install another file to use the code. This walkthrough covers these tasks: @@ -32,19 +33,19 @@ The instructions for how to create the project vary depending on your version of ::: moniker range=">=msvc-160" -### To create a static library project in Visual Studio +To create a static library project in Visual Studio: -1. On the menu bar, choose **File** > **New** > **Project** to open the **Create a New Project** dialog. +1. On the menu bar, choose **File** > **New** > **Project** to open the **Create a new project** dialog. 1. At the top of the dialog, set **Language** to **C++**, set **Platform** to **Windows**, and set **Project type** to **Library**. -1. From the filtered list of project types, select **Windows Desktop Wizard**, then choose **Next**. +1. From the filtered list of project types, select **Windows Desktop Wizard**, and then choose **Next**. 1. In the **Configure your new project** page, enter *MathLibrary* in the **Project name** box to specify a name for the project. Enter *StaticMath* in the **Solution name** box. Choose the **Create** button to open the **Windows Desktop Project** dialog. 1. In the **Windows Desktop Project** dialog, under **Application type**, select **Static Library (.lib)**. -1. Under **Additional options**, uncheck the **Precompiled header** check box if it's checked. Check the **Empty project** box. +1. Under **Additional options**, clear the **Precompiled header** check box if it's selected. Select **Empty project**. 1. Choose **OK** to create the project. @@ -52,17 +53,17 @@ The instructions for how to create the project vary depending on your version of ::: moniker range="msvc-150" -### To create a static library project in Visual Studio 2017 +To create a static library project in Visual Studio 2017: 1. On the menu bar, choose **File** > **New** > **Project**. -1. In the **New Project** dialog box, select **Installed** > **Visual C++** > **Windows Desktop**. In the center pane, select **Windows Desktop Wizard**. +1. In the **New Project** dialog, select **Installed** > **Visual C++** > **Windows Desktop**. In the center pane, select **Windows Desktop Wizard**. -1. Specify a name for the project—for example, *MathLibrary*—in the **Name** box. Specify a name for the solution—for example, *StaticMath*—in the **Solution Name** box. Choose the **OK** button. +1. Specify a name for the project, such as *MathLibrary*, in the **Name** box. Specify a name for the solution, such as *StaticMath*, in the **Solution Name** box. Choose **OK**. 1. In the **Windows Desktop Project** dialog, under **Application type**, select **Static Library (.lib)**. -1. Under **Additional Options**, uncheck the **Precompiled header** check box if it's checked. Check the **Empty project** box. +1. Under **Additional Options**, clear the **Precompiled header** check box if it's selected. Select **Empty project**. 1. Choose **OK** to create the project. @@ -70,27 +71,27 @@ The instructions for how to create the project vary depending on your version of ::: moniker range="msvc-140" -### To create a static library project in Visual Studio 2015 +To create a static library project in Visual Studio 2015: 1. On the menu bar, choose **File** > **New** > **Project**. -1. In the **New Project** dialog box, select **Installed** > **Templates** > **Visual C++** > **Win32**. In the center pane, select **Win32 Console Application**. +1. In the **New Project** dialog, select **Installed** > **Templates** > **Visual C++** > **Win32**. In the center pane, select **Win32 Console Application**. -1. Specify a name for the project—for example, *MathLibrary*—in the **Name** box. Specify a name for the solution—for example, *StaticMath*—in the **Solution Name** box. Choose the **OK** button. +1. Specify a name for the project, such as *MathLibrary*, in the **Name** box. Specify a name for the solution, such as *StaticMath*, in the **Solution Name** box. Choose **OK**. 1. In the **Win32 Application Wizard**, choose **Next**. -1. In the **Application Settings** page, under **Application type**, select **Static library**. Under **Additional options**, uncheck the **Precompiled header** checkbox. Choose **Finish** to create the project. +1. In the **Application Settings** page, under **Application type**, select **Static library**. Under **Additional options**, clear the **Precompiled header** checkbox. Choose **Finish** to create the project. ::: moniker-end ## Add a class to the static library -### To add a class to the static library +To add a class to the static library: -1. To create a header file for a new class, right-click to open the shortcut menu for the **MathLibrary** project in **Solution Explorer**, and then choose **Add** > **New Item**. +1. Create a header file for a new class. In **Solution Explorer**, right-click **MathLibrary** to open the context menu for the project. Select **Add** > **New Item**. -1. In the **Add New Item** dialog box, select **Visual C++** > **Code**. In the center pane, select **Header File (.h)**. Specify a name for the header file—for example, *MathLibrary.h*—and then choose the **Add** button. A nearly blank header file is displayed. +1. In the **Add New Item** dialog, select **Visual C++** > **Code**. In the center pane, select **Header File (.h)**. Specify a name for the header file, such as *MathLibrary.h*, and then select **Add**. A nearly blank header file is displayed. 1. Add a declaration for a class named `Arithmetic` to do common mathematical operations such as addition, subtraction, multiplication, and division. The code should resemble: @@ -118,9 +119,9 @@ The instructions for how to create the project vary depending on your version of } ``` -1. To create a source file for the new class, open the shortcut menu for the **MathLibrary** project in **Solution Explorer**, and then choose **Add** > **New Item**. +1. To create a source file for the new class, open the context menu for the **MathLibrary** project in **Solution Explorer**, and then choose **Add** > **New Item**. -1. In the **Add New Item** dialog box, in the center pane, select **C++ File (.cpp)**. Specify a name for the source file—for example, *MathLibrary.cpp*—and then choose the **Add** button. A blank source file is displayed. +1. In the **Add New Item** dialog, in the center pane, select **C++ File (.cpp)**. Specify a name for the source file, such as *MathLibrary.cpp*. Then select **Add**. A blank source file is displayed. 1. Use this source file to implement the functionality for class `Arithmetic`. The code should resemble: @@ -155,42 +156,45 @@ The instructions for how to create the project vary depending on your version of } ``` -1. To build the static library, select **Build** > **Build Solution** on the menu bar. The build creates a static library, *MathLibrary.lib*, that can be used by other programs. +1. To build the static library, select **Build** > **Build Solution** on the menu bar. The build creates a static library, *MathLibrary.lib*, that other programs can use. > [!NOTE] - > When you build on the Visual Studio command line, you must build the program in two steps. First, run `cl /c /EHsc MathLibrary.cpp` to compile the code and create an object file that's named *MathLibrary.obj*. (The `cl` command invokes the compiler, Cl.exe, and the `/c` option specifies compile without linking. For more information, see [/c (Compile Without Linking)](../build/reference/c-compile-without-linking.md).) Second, run `lib MathLibrary.obj` to link the code and create the static library *MathLibrary.lib*. (The `lib` command invokes the Library Manager, Lib.exe. For more information, see [LIB Reference](../build/reference/lib-reference.md).) + > When you build on the Visual Studio command line, you must build the program in two steps. + > + > 1. Run `cl /c /EHsc MathLibrary.cpp` to compile the code and create an object file named *MathLibrary.obj*. The `cl` command invokes the compiler, Cl.exe, and the `/c` option specifies compile without linking. For more information, see [/c (Compile Without Linking)](../build/reference/c-compile-without-linking.md). + > 1. Run `lib MathLibrary.obj` to link the code and create the static library *MathLibrary.lib*. The `lib` command invokes the Library Manager, Lib.exe. For more information, see [LIB Reference](../build/reference/lib-reference.md). ## Create a C++ console app that references the static library ::: moniker range=">=msvc-160" -### To create a C++ console app that references the static library in Visual Studio +To create a C++ console app that references the static library in Visual Studio: -1. In **Solution Explorer**, right-click on the top node, **Solution 'StaticMath'**, to open the shortcut menu. Choose **Add** > **New Project** to open the **Add a New Project** dialog. +1. In **Solution Explorer**, right-click on the top node, **Solution 'StaticMath'**, to open the context menu. Choose **Add** > **New Project** to open the **Add a New Project** dialog. 1. At the top of the dialog, set the **Project type** filter to **Console**. -1. From the filtered list of project types, choose **Console App** then choose **Next**. In the next page, enter *MathClient* in the **Name** box to specify a name for the project. +1. From the filtered list of project types, choose **Console App** then choose **Next**. In the next page, enter *MathClient* as the name for the project. -1. Choose the **Create** button to create the client project. +1. Choose **Create** to create the client project. -1. After you create a console app, an empty program is created for you. The name for the source file is the same as the name that you chose earlier. In the example, it's named `MathClient.cpp`. + After you create a console app, an empty program is created for you. The name for the source file is the same as the name that you chose earlier. In the example, it's named `MathClient.cpp`. ::: moniker-end ::: moniker range="msvc-150" -### To create a C++ console app that references the static library in Visual Studio 2017 +To create a C++ console app that references the static library in Visual Studio 2017: -1. In **Solution Explorer**, right-click on the top node, **Solution 'StaticMath'**, to open the shortcut menu. Choose **Add** > **New Project** to open the **Add a New Project** dialog box. +1. In **Solution Explorer**, right-click on the top node, **Solution 'StaticMath'**, to open the context menu. Choose **Add** > **New Project** to open the **Add a New Project** dialog. -1. In the **Add New Project** dialog box, select **Installed** > **Visual C++** > **Windows Desktop**. In the center pane, select **Windows Desktop Wizard**. +1. In the **Add New Project** dialog, select **Installed** > **Visual C++** > **Windows Desktop**. In the center pane, select **Windows Desktop Wizard**. 1. Specify a name for the project—for example, *MathClient*—in the **Name** box. Choose the **OK** button. 1. In the **Windows Desktop Project** dialog, under **Application type**, select **Console Application (.exe)**. -1. Under **Additional Options**, uncheck the **Precompiled header** check box if it's checked. +1. Under **Additional Options**, clear the **Precompiled header** check box if it's selected. 1. Choose **OK** to create the project. @@ -200,35 +204,35 @@ The instructions for how to create the project vary depending on your version of ::: moniker range="msvc-140" -### To create a C++ console app that references the static library in Visual Studio 2015 +To create a C++ console app that references the static library in Visual Studio 2015: -1. In **Solution Explorer**, right-click on the top node, **Solution 'StaticMath'**, to open the shortcut menu. Choose **Add** > **New Project** to open the **Add a New Project** dialog box. +1. In **Solution Explorer**, right-click on the top node, **Solution 'StaticMath'**, to open the context menu. Choose **Add** > **New Project** to open the **Add a New Project** dialog. -1. In the **Add New Project** dialog box, select **Installed** > **Visual C++** > **Win32**. In the center pane, select **Win32 Console Application**. +1. In the **Add New Project** dialog, select **Installed** > **Visual C++** > **Win32**. In the center pane, select **Win32 Console Application**. 1. Specify a name for the project—for example, *MathClient*—in the **Name** box. Choose the **OK** button. 1. In the **Win32 Application Wizard** dialog, choose **Next**. -1. On the **Application Settings** page, under **Application type**, make sure **Console application** is selected. Under **Additional options**, uncheck **Precompiled header**, then check the **Empty Project** checkbox. Choose **Finish** to create the project. +1. On the **Application Settings** page, under **Application type**, make sure **Console application** is selected. Under **Additional options**, clear **Precompiled header**, and then select **Empty Project**. Choose **Finish** to create the project. -1. To add a source file to the empty project, right-click to open the shortcut menu for the **MathClient** project in **Solution Explorer**, and then choose **Add** > **New Item**. +1. To add a source file to the empty project, right-click to open the context menu for the **MathClient** project in **Solution Explorer**, and then choose **Add** > **New Item**. -1. In the **Add New Item** dialog box, select **Visual C++** > **Code**. In the center pane, select **C++ File (.cpp)**. Specify a name for the source file—for example, *MathClient.cpp*—and then choose the **Add** button. A blank source file is displayed. +1. In the **Add New Item** dialog, select **Visual C++** > **Code**. In the center pane, select **C++ File (.cpp)**. Specify a name for the source file—for example, *MathClient.cpp*—and then choose the **Add** button. A blank source file is displayed. ::: moniker-end ## Use the functionality from the static library in the app -### To use the functionality from the static library in the app +To use the functionality from the static library in the app: -1. Before you can use the math routines in the static library, you must reference it. Open the shortcut menu for the **MathClient** project in **Solution Explorer**, and then choose **Add** > **Reference**. +1. Reference the static library before using the math routines in it. Open the context menu for the **MathClient** project in **Solution Explorer**, and then choose **Add** > **Reference**. -1. The **Add Reference** dialog box lists the libraries that you can reference. The **Projects** tab lists the projects in the current solution and any libraries they reference. Open the **Projects** tab, select the **MathLibrary** check box, and then choose the **OK** button. +1. The **Add Reference** dialog lists the libraries that you can reference. The **Projects** tab lists the projects in the current solution and any libraries they reference. Open the **Projects** tab, select **MathLibrary**, and then select **OK**. -1. To reference the `MathLibrary.h` header file, you must modify the included directories path. In **Solution Explorer**, right-click on **MathClient** to open the shortcut menu. Choose **Properties** to open the **MathClient Property Pages** dialog box. +1. Modify the included directories path to reference the `MathLibrary.h` header file. In **Solution Explorer**, right-click on **MathClient** to open the context menu. Choose **Properties** to open the **MathClient Property Pages** dialog. -1. In the **MathClient Property Pages** dialog box, set the **Configuration** drop-down to **All Configurations**. Set the **Platform** drop-down to **All Platforms**. +1. In the **MathClient Property Pages** dialog, set the **Configuration** value to **All Configurations**. Set **Platform** to **All Platforms**. 1. Select the **Configuration Properties** > **C/C++** > **General** property page. In the **Additional Include Directories** property, specify the path of the **MathLibrary** directory, or browse for it. @@ -236,13 +240,13 @@ The instructions for how to create the project vary depending on your version of 1. Open the **Additional Include Directories** property value drop-down list, and then choose **Edit**. - 1. In the **Additional Include Directories** dialog box, double-click in the top of the text box. Then choose the ellipsis button (**...**) at the end of the line. + 1. In the **Additional Include Directories** dialog, double-click in the top of the text box. Then choose the ellipsis button (**...**) at the end of the line. - 1. In the **Select Directory** dialog box, navigate up a level, and then select the **MathLibrary** directory. Then choose the **Select Folder** button to save your selection. + 1. In the **Select Directory** dialog, navigate up a level, and then select the **MathLibrary** directory. Then choose the **Select Folder** button to save your selection. - 1. In the **Additional Include Directories** dialog box, choose the **OK** button. + 1. In the **Additional Include Directories** dialog, choose the **OK** button. - 1. In the **Property Pages** dialog box, choose the **OK** button to save your changes to the project. + 1. In the **Property Pages** dialog, choose the **OK** button to save your changes to the project. 1. You can now use the `Arithmetic` class in this app by including the `#include "MathLibrary.h"` header in your code. Replace the contents of `MathClient.cpp` with this code: @@ -275,11 +279,11 @@ The instructions for how to create the project vary depending on your version of ## Run the app -### To run the app +To run the app: -1. Make sure that **MathClient** is selected as the default project. To select it, right-click to open the shortcut menu for **MathClient** in **Solution Explorer**, and then choose **Set as StartUp Project**. +1. Make sure that **MathClient** is selected as the default project. To select it, right-click **MathClient** in **Solution Explorer** to open the context menu, and then choose **Set as StartUp Project**. -1. To run the project, on the menu bar, choose **Debug** > **Start Without Debugging**. The output should resemble: +1. On the menu bar, choose **Debug** > **Start Without Debugging** to run the project. The output should resemble: ```Output a + b = 106.4 @@ -290,4 +294,4 @@ The instructions for how to create the project vary depending on your version of ## See also -[Walkthrough: Creating and Using a Dynamic Link Library (C++)](../build/walkthrough-creating-and-using-a-dynamic-link-library-cpp.md) \ No newline at end of file +[Walkthrough: Creating and Using a Dynamic Link Library (C++)](../build/walkthrough-creating-and-using-a-dynamic-link-library-cpp.md) diff --git a/docs/build/working-with-project-properties.md b/docs/build/working-with-project-properties.md index b6ca518f4c8..900afd80d16 100644 --- a/docs/build/working-with-project-properties.md +++ b/docs/build/working-with-project-properties.md @@ -1,7 +1,7 @@ --- -title: "Set C++ Compiler and Build Properties in Visual Studio" -description: "Use the Visual Studio IDE to change C++ compiler and linker options and other build settings." -ms.date: 03/19/2025 +title: Set C++ Compiler and Build Properties in Visual Studio +description: Use the Visual Studio IDE to change C++ compiler and linker options and other build settings. Modify these settings in the Properties pages for your project. +ms.date: 07/13/2026 ms.topic: concept-article helpviewer_keywords: ["project properties [C++], modifying", "properties [C++]", "Visual C++ projects, properties", "projects [C++], properties"] --- @@ -9,31 +9,31 @@ helpviewer_keywords: ["project properties [C++], modifying", "properties [C++]", In the Visual Studio IDE, you can view and edit the properties needed to compile and build a project. This information includes the application name, extension (such as DLL, LIB, EXE), compiler options, linker options, debugger settings, and custom build steps. -You can view and modify these properties by using *property pages*. To access the property pages, choose **Project** > **_project-name_ Properties** from the main menu, or right-click on the project node in **Solution Explorer** and choose **Properties**. +You can view and modify these properties by using *property pages*. To access the property pages, in the main menu, select **Project**, and then select **Properties**. Or, in **Solution Explorer**, right-click the project node and choose **Properties**. ## Default properties -When you create a project, the system assigns values for various properties. The defaults vary somewhat depending on the kind of project and what options you choose in the app wizard. For example, an Active Template Library (ATL) project has properties related to Microsoft Interface Definition Language (MIDL) files, but these properties are absent in a basic console application. The default properties are shown in the Advanced pane in the **Property Pages** window: +When you create a project, the system assigns values for various properties. The defaults vary somewhat depending on the kind of project and what options you choose in the app wizard. For example, an Active Template Library (ATL) project has properties related to Microsoft Interface Definition Language (MIDL) files, but these properties are absent in a basic console application. The Advanced pane in the **Property Pages** window shows the default properties: :::image type="content" source="media/visual-c---project-defaults.png" alt-text="Screenshot of the Visual Studio project properties dialog box with the Advanced pane selected. Properties such as Use of MFC, Character Set, and so on are highlighted." lightbox="media/visual-c---project-defaults.png"::: ## Apply properties to build configurations and target platforms -Some properties, such as the application name, apply to all build variations and target platforms, whether it's a debug or release build. But most properties are configuration-dependent. To generate the correct code, the compiler has to know both the specific platform the program runs on and which specific compiler options to use. So when you set a property, it's important to pay attention to which configuration and platform the new value should apply to. Should it apply only to Debug Win32 builds, or should it also apply to Debug ARM64 and Debug x64? For example, the **Optimization** property, by default, is set to **Maximize Speed (/O2)** in a Release configuration, but is disabled in the Debug configuration. +Some properties, such as the application name, apply to all build variations and target platforms, whether it's a debug or release build. But most properties are configuration-dependent. To generate the correct code, the compiler needs to know both the specific platform the program runs on and which specific compiler options to use. So when you set a property, pay attention to which configuration and platform the new value should apply to. Should it apply only to Debug Win32 builds, or should it also apply to Debug ARM64 and Debug x64? For example, the **Optimization** property, by default, is set to **Maximize Speed (/O2)** in a Release configuration, but is disabled in the Debug configuration. -You can always see and change the configuration and platform a property value should apply to. The following illustration shows the property pages with the configuration and platform information controls at the top. When the **Optimization** property is set here, it only applies to Debug x64 builds, the currently active configuration, as shown by the red arrows. +You can always see and change the configuration and platform a property value should apply to. The following illustration shows the property pages with the configuration and platform information controls at the top. When you set the **Optimization** property here, it only applies to Debug x64 builds, the currently active configuration, as shown by the red arrows. :::image type="complex" source="media/visual-c---property-pages-showing-active-configuration.png" alt-text="Screenshot of the Visual Studio Property Pages dialog."::: The page is open to C/C++, Optimization. The Optimization setting is set to Disabled (/Od), which is called out. An arrow calls out the relationship between the Configuration setting in the project property page, which is set to Active(Debug), and the setting in the Solution configuration dropdown on the toolbar, which is set to Debug. Another arrow calls out the relationship between the Platform setting in the project property page, which is set to Active(x64), and the setting in the Solutions platform dropdown on the toolbar, which is set to x64. :::image-end::: -The following illustration shows the same project property page, but the configuration has been changed to Release. Note the different value for the Optimization property. Also note that the active configuration is still Debug. You can set properties for any configuration here; it doesn't have to be the active one. +The following illustration shows the same project property page, but the configuration is changed to Release. Note the different value for the Optimization property. Also note that the active configuration is still Debug. You can set properties for any configuration here; it doesn't have to be the active one. :::image type="content" source="media/visual-c---property-pages-showing-release-config.png" alt-text="Screenshot of the Visual Studio project Property Pages dialog. The Configuration dropdown is called out and is set to Release. The optimization setting is set to Maximize Speed slash O2."::: ## Target platforms -*Target platform* refers to the kind of device and operating system that the executable runs on. You can build a project for more than one platform. The available target platforms for C++ projects depend on the kind of project. They include but aren't limited to Win32, x64, ARM, ARM64, Android, and iOS. The **x86** target platform that you might see in **Configuration Manager** is identical to **Win32** in native C++ projects. Win32 means 32-bit Windows and **x64** means 64-bit Windows. For more information about these two platforms, see [Running 32-bit applications](/windows/win32/WinProg64/running-32-bit-applications). +*Target platform* refers to the kind of device and operating system that the executable runs on. You can build a project for more than one platform. The available target platforms for C++ projects depend on the kind of project. They include but aren't limited to Win32, x64, ARM, ARM64, Android, and iOS. The **x86** target platform that you might see in **Microsoft Configuration Manager** is identical to **Win32** in native C++ projects. Win32 means 32-bit Windows and **x64** means 64-bit Windows. For more information about these two platforms, see [Running 32-bit applications](/windows/win32/WinProg64/running-32-bit-applications). The **Any CPU** target platform value that you might see in **Configuration Manager** has no effect on native C++ projects. It's only relevant for C++/CLI and other .NET project types. For more information, see [`/CLRIMAGETYPE` (Specify Type of CLR Image)](reference/clrimagetype-specify-type-of-clr-image.md). @@ -46,21 +46,21 @@ For more information about setting properties for a Debug build, see: ## C++ compiler and linker options -C++ compiler and linker options are located under the **C/C++** and **Linker** nodes in the left pane under **Configuration Properties**. These options translate directly to command-line options that are passed to the compiler. To read documentation about a specific option, select the option in the center pane and press **F1**. Or, you can browse documentation for all the options at [MSVC compiler options](reference/compiler-options.md) and [MSVC linker options](reference/linker-options.md). +C++ compiler and linker options are located under the **C/C++** and **Linker** nodes in the left pane under **Configuration Properties**. These options translate directly to command-line options that the compiler receives. To read documentation about a specific option, select the option in the center pane and press **F1**. Or, you can browse documentation for all the options at [MSVC compiler options](reference/compiler-options.md) and [MSVC linker options](reference/linker-options.md). The **Property Pages** dialog box shows only the property pages that are relevant to the current project. For example, if the project doesn't have an *`.idl`* file, the MIDL property page isn't displayed. For more information about the settings on each property page, see [Property Pages (C++)](reference/property-pages-visual-cpp.md). ## Directory and path values -MSBuild supports the use of compile-time constants for certain string values, such as include directories and paths, called *macros*. A macro can refer to a value that's defined by Visual Studio or the MSBuild system, or to a user-defined value. Macros look like `$(macro-name)` or `%(item-macro-name)`. They're exposed in the property pages, where you can refer to and modify them by using the [Property Editor](#property_editor). Use macros instead of hard-coded values such as directory paths. Macros make it easier to share property settings between machines and between versions of Visual Studio. You can also better ensure that your project settings participate correctly in [property inheritance](project-property-inheritance.md). +MSBuild supports the use of compile-time constants for certain string values, such as include directories and paths, called *macros*. A macro can refer to a value that's defined by Visual Studio or the MSBuild system, or to a user-defined value. Macros look like `$(macro-name)` or `%(item-macro-name)`. The property pages expose these macros, where you can refer to and modify them by using the [Property Editor](#property_editor). Use macros instead of hard-coded values such as directory paths. Macros make it easier to share property settings between machines and between versions of Visual Studio. You can also better ensure that your project settings participate correctly in [property inheritance](project-property-inheritance.md). The following illustration shows the property pages for a Visual Studio C++ project. In the left pane, the **VC++ Directories** *rule* is selected, and the right pane lists the properties that are associated with that rule. The property values are often macros, such as `$(VC_SourcePath)`: :::image type="complex" source="media/project_property_pages_vc.png" alt-text="Screenshot of the Visual Studio Property Pages dialog for rules for various directories."::: -The VC plus plus Directories page is open, which has properties for the VC++ Directories rules. An example rule is Source directories, which is set to $(VC_SourcePath). There are rules for the include directories, library directories, executable directories, and so on. +The VC++ Directories page is open, which has properties for the VC++ Directories rules. An example rule is Source directories, which is set to `$(VC_SourcePath)`. There are rules for the include directories, library directories, executable directories, and so on. :::image-end::: -You can use the [Property Editor](#property_editor) to view the values of all available macros. +Use the [Property Editor](#property_editor) to view the values of all available macros. ### Predefined macros @@ -72,7 +72,7 @@ You can use the [Property Editor](#property_editor) to view the values of all av ### User-defined macros -You can create *user-defined macros* to use as variables in project builds. For example, you could create a user-defined macro that provides a value to a custom build step or a custom build tool. A user-defined macro is a name-value pair. In a project file, use the `$(name)` notation to access the value. +Create *user-defined macros* to use as variables in project builds. For example, you could create a user-defined macro that provides a value to a custom build step or a custom build tool. A user-defined macro is a name-value pair. In a project file, use the `$(name)` notation to access the value. A user-defined macro is stored in a property sheet. If your project doesn't already contain a property sheet, you can create one by following the steps under [Share or reuse Visual Studio project settings](create-reusable-property-configurations.md). @@ -86,13 +86,13 @@ A user-defined macro is stored in a property sheet. If your project doesn't alre ## Property Editor -You can use the Property Editor to modify certain string properties and select macros as values. To access the Property Editor, select a property on a property page and then choose the down arrow button on the right. If the drop-down list contains **\**, then you can choose it to display the Property Editor for that property. +Use the Property Editor to modify certain string properties and select macros as values. To access the Property Editor, select a property on a property page and then choose the down arrow button on the right. If the drop-down list contains **\**, you can choose it to display the Property Editor for that property. :::image type="complex" source="media/property_editor_dropdown.png" alt-text="Screenshot of the Visual Studio project properties page for VC plus plus Directories."::: The Property Editor for the Include Directories setting is open. It shows the evaluated value for the Include Directories, which is C:\Program Files(x86)\Microsoft Visual Studio 14.0\VC\Include. It shows the two inherited values: $(VC_IncludePath) and $(WindowsSDK_IncludePath). A checkbox for 'Inherit from parent or project defaults' is selected. :::image-end::: -In the Property Editor, you can choose the **Macros** button to view the available macros and their current values. The following illustration shows the Property Editor for the **Additional Include Directories** property after the **Macros** button was chosen. When the **Inherit from parent or project defaults** check box is selected and you add a new value, it's appended to any values that are currently being inherited. If you clear the check box, your new value replaces the inherited values. In most cases, leave the check box selected. +In the Property Editor, choose the **Macros** button to view the available macros and their current values. The following illustration shows the Property Editor for the **Additional Include Directories** property after the **Macros** button was chosen. When the **Inherit from parent or project defaults** check box is selected and you add a new value, it appends to any values that are currently being inherited. If you clear the check box, your new value replaces the inherited values. In most cases, leave the check box selected. :::image type="complex" source="media/propertyeditorvc.png" alt-text="Screenshot of the Property Editor dialog after selecting the Macros button."::: The property editor for Include Directories is open. The evaluated value is displayed along with the inherited values. A listbox contains various macros and their values, such as $(CharacterSet) which is set to Unicode. @@ -100,7 +100,7 @@ The property editor for Include Directories is open. The evaluated value is disp ## Add an include directory to the set of default directories -When you add an include directory to a project, it's important not to override all the default directories. The correct way to add a directory is to append the new path, for example `C:\MyNewIncludeDir\`, and then to append the `$(IncludePath)` macro to the property value. +When you add an include directory to a project, don't override all the default directories. Append the new path, such as `C:\MyNewIncludeDir\`, and then append the `$(IncludePath)` macro to the property value. ## Quickly browse and search all properties @@ -114,7 +114,7 @@ The **All Options** property page (under the **Configuration Properties** > **C/ ## Set environment variables for a build -The MSVC compiler (cl.exe) recognizes certain environment variables, specifically `LIB`, `LIBPATH`, `PATH`, and `INCLUDE`. When you build with the IDE, the properties that are set in the [VC++ Directories Property Page](reference/vcpp-directories-property-page.md) are used to set those environment variables. If `LIB`, `LIBPATH`, and `INCLUDE` values have already been set, for example by a Developer Command Prompt, they're replaced with the values of the corresponding MSBuild properties. The build then prepends the value of the VC++ Directories executable directories property to `PATH`. You can set a user-defined environment variable by creating a user-defined macro and then checking the box that says **Set this macro as an environment variable in the build environment**. +The MSVC compiler (cl.exe) recognizes certain environment variables, specifically `LIB`, `LIBPATH`, `PATH`, and `INCLUDE`. When you build with the IDE, the properties that you set in the [VC++ Directories Property Page](reference/vcpp-directories-property-page.md) set those environment variables. If `LIB`, `LIBPATH`, and `INCLUDE` values are already set, for example by a Developer Command Prompt, the build process replaces them with the values of the corresponding MSBuild properties. The build process prepends the value of the VC++ Directories executable directories property to `PATH`. You can set a user-defined environment variable by creating a user-defined macro and then checking the box that says **Set this macro as an environment variable in the build environment**. ## Set environment variables for a debugging session diff --git a/docs/build/x64-calling-convention.md b/docs/build/x64-calling-convention.md index ff47e9dfd76..a1265ca7cfc 100644 --- a/docs/build/x64-calling-convention.md +++ b/docs/build/x64-calling-convention.md @@ -19,7 +19,7 @@ There's a strict one-to-one correspondence between a function call's arguments a The x87 register stack is unused. It might be used by the callee, but consider it volatile across function calls. All floating point operations are done using the 16 XMM registers. -Integer arguments are passed in registers RCX, RDX, R8, and R9. Floating point arguments are passed in XMM0L, XMM1L, XMM2L, and XMM3L. 16-byte arguments are passed by reference. Parameter passing is described in detail in [Parameter passing](#parameter-passing). These registers, and RAX, R10, R11, XMM4, and XMM5, are considered *volatile*, or potentially changed by a callee on return. Register usage is documented in detail in [x64 register usage](x64-software-conventions.md#x64-register-usage) and [Caller/callee saved registers](#callercallee-saved-registers). +Integer arguments are passed in registers `RCX`, `RDX`, `R8`, and `R9`. Floating point arguments are passed in `XMM0L`, `XMM1L`, `XMM2L`, and `XMM3L`. 16-byte arguments are passed by reference. Parameter passing is described in detail in [Parameter passing](#parameter-passing). These registers, and `RAX`, `R10`, `R11`, `XMM4`, and `XMM5`, are considered *volatile*, or potentially changed by a callee on return. Register usage is documented in detail in [x64 register usage](x64-software-conventions.md#x64-register-usage) and [Caller/callee saved registers](#callercallee-saved-registers). For prototyped functions, all arguments are converted to the expected callee types before passing. The caller is responsible for allocating space for the callee's parameters. The caller must always allocate sufficient space to store four register parameters, even if the callee doesn't take that many parameters. This convention simplifies support for unprototyped C-language functions and vararg C/C++ functions. For vararg or unprototyped functions, any floating point values must be duplicated in the corresponding general-purpose register. Any parameters beyond the first four must be stored on the stack after the shadow store before the call. Vararg function details can be found in [Varargs](#varargs). Unprototyped function information is detailed in [Unprototyped functions](#unprototyped-functions). @@ -29,7 +29,7 @@ Most structures are aligned to their natural alignment. The primary exceptions a ## Unwindability -Leaf functions are functions that don't change any nonvolatile registers. A nonleaf function might change nonvolatile RSP, for example, by calling a function. Or, it could change RSP by allocating more stack space for local variables. To recover nonvolatile registers when an exception is handled, nonleaf functions are annotated with static data. The data describes how to properly unwind the function at an arbitrary instruction. This data is stored as *pdata*, or procedure data, which in turn refers to *xdata*, the exception handling data. The xdata contains the unwinding information, and can point to additional pdata or an exception handler function. +Leaf functions are functions that don't change any nonvolatile registers. A nonleaf function might change nonvolatile `RSP`, for example, by calling a function. Or, it could change `RSP` by allocating more stack space for local variables. To recover nonvolatile registers when an exception is handled, nonleaf functions are annotated with static data. The data describes how to properly unwind the function at an arbitrary instruction. This data is stored as *pdata*, or procedure data, which in turn refers to *xdata*, the exception handling data. The xdata contains the unwinding information, and can point to additional pdata or an exception handler function. Prologs and epilogs are highly restricted so that they can be properly described in xdata. The stack pointer must remain 16-byte aligned in any region of code that isn't part of an epilog or prolog, except within leaf functions. Leaf functions can be unwound simply by simulating a return, so pdata and xdata aren't required. For details about the proper structure of function prologs and epilogs, see [x64 prolog and epilog](../build/prolog-and-epilog.md). For more information about exception handling, and the exception handling and unwinding of pdata and xdata, see [x64 exception handling](../build/exception-handling-x64.md). @@ -37,9 +37,9 @@ Prologs and epilogs are highly restricted so that they can be properly described By default, the x64 calling convention passes the first four arguments to a function in registers. The registers used for these arguments depend on the position and type of the argument. Remaining arguments are passed on the stack in right-to-left order. The caller reserves the required stack space and writes these arguments to stack memory using store or move instructions, maintaining 8-byte alignment for each argument. -Integer valued arguments in the leftmost four positions are passed in left-to-right order in RCX, RDX, R8, and R9, respectively. The fifth and higher arguments are passed on the stack as previously described. All integer arguments in registers are right-justified, so the callee can ignore the upper bits of the register and access only the portion of the register necessary. +Integer valued arguments in the leftmost four positions are passed in left-to-right order in `RCX`, `RDX`, `R8`, and `R9`, respectively. The fifth and higher arguments are passed on the stack as previously described. All integer arguments in registers are right-justified, so the callee can ignore the upper bits of the register and access only the portion of the register necessary. -Any floating-point and double-precision arguments in the first four parameters are passed in XMM0 - XMM3, depending on position. Floating-point values are only placed in the integer registers RCX, RDX, R8, and R9 when there are varargs arguments. For details, see [Varargs](#varargs). Similarly, the XMM0 - XMM3 registers are ignored when the corresponding argument is an integer or pointer type. +Any floating-point and double-precision arguments in the first four parameters are passed in `XMM0` - `XMM3`, depending on position. Floating-point values are only placed in the integer registers `RCX`, `RDX`, `R8`, and `R9` when there are varargs arguments. For details, see [Varargs](#varargs). Similarly, the `XMM0` - `XMM3` registers are ignored when the corresponding argument is an integer or pointer type. [`__m128`](../cpp/m128.md) types, arrays, and strings are never passed by immediate value. Instead, a pointer is passed to memory allocated by the caller. Structs and unions of size 8, 16, 32, or 64 bits, and **`__m64`** types, are passed as if they were integers of the same size. Structs or unions of other sizes are passed as a pointer to memory allocated by the caller. For these aggregate types passed as a pointer, including **`__m128`**, the caller-allocated temporary memory must be 16-byte aligned. @@ -51,11 +51,11 @@ The following table summarizes how parameters are passed, by type and position f | Parameter type | fifth and higher | fourth | third | second | leftmost | |-|-|-|-|-|-| -| floating-point | stack | XMM3 | XMM2 | XMM1 | XMM0 | -| integer | stack | R9 | R8 | RDX | RCX | -| Aggregates (8, 16, 32, or 64 bits) and **`__m64`** | stack | R9 | R8 | RDX | RCX | -| Other aggregates, as pointers | stack | R9 | R8 | RDX | RCX | -| **`__m128`**, as a pointer | stack | R9 | R8 | RDX | RCX | +| floating-point | stack | `XMM3` | `XMM2` | `XMM1` | `XMM0` | +| integer | stack | `R9` | `R8` | `RDX` | `RCX` | +| Aggregates (8, 16, 32, or 64 bits) and **`__m64`** | stack | `R9` | `R8` | `RDX` | `RCX` | +| Other aggregates, as pointers | stack | `R9` | `R8` | `RDX` | `RCX` | +| **`__m128`**, as a pointer | stack | `R9` | `R8` | `RDX` | `RCX` | ### Example of argument passing 1 - all integers @@ -103,9 +103,9 @@ func2() { // RCX = 2, RDX = XMM1 = 1.0, and R8 = 7 ## Return values -A scalar return value that can fit into 64 bits, including the `__m64` type, is returned through RAX. Nonscalar types including floats, doubles, and vector types such as [`__m128`](../cpp/m128.md), [`__m128i`](../cpp/m128i.md), [`__m128d`](../cpp/m128d.md) are returned in XMM0. The state of unused bits in the value returned in RAX or XMM0 is undefined. +A scalar return value that can fit into 64 bits, including the `__m64` type, is returned through `RAX`. Nonscalar types including floats, doubles, and vector types such as [`__m128`](../cpp/m128.md), [`__m128i`](../cpp/m128i.md), [`__m128d`](../cpp/m128d.md) are returned in `XMM0`. The state of unused bits in the value returned in `RAX` or `XMM0` is undefined. -User-defined types can be returned by value from global functions and static member functions. To return a user-defined type by value in RAX, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator. It can have no private or protected nonstatic data members, and no nonstatic data members of reference type. It can't have base classes or virtual functions. And, it can only have data members that also meet these requirements. This definition is essentially the same as a C++03 POD type. Because the definition has changed in the C++11 standard, we don't recommend using `std::is_pod` for this test. Otherwise, the caller must allocate memory for the return value and pass a pointer to it as the first argument. The remaining arguments are then shifted one argument to the right. The same pointer must be returned by the callee in RAX. +User-defined types can be returned by value from global functions and static member functions. To return a user-defined type by value in `RAX`, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator. It can have no private or protected nonstatic data members, and no nonstatic data members of reference type. It can't have base classes or virtual functions. And, it can only have data members that also meet these requirements. This definition is essentially the same as a C++03 POD type. Because the definition has changed in the C++11 standard, we don't recommend using `std::is_pod` for this test. Otherwise, the caller must allocate memory for the return value and pass a pointer to it as the first argument. The remaining arguments are then shifted one argument to the right. The same pointer must be returned by the callee in `RAX`. These examples show how parameters and return values are passed for functions with the specified declarations: @@ -150,9 +150,11 @@ Struct2 func4(int a, double b, int c, float d); ## Caller/callee saved registers -The x64 ABI considers the registers RAX, RCX, RDX, R8, R9, R10, R11, and XMM0-XMM5 volatile. When present, the upper portions of YMM0-YMM15 and ZMM0-ZMM15 are also volatile. On AVX512VL, the ZMM, YMM, and XMM registers 16-31 are also volatile. When AMX support is present, the TMM tile registers are volatile. Consider volatile registers destroyed on function calls unless otherwise safety-provable by analysis such as whole program optimization. +The x64 ABI considers the registers `RAX`, `RCX`, `RDX`, `R8`, `R9`, `R10`, `R11`, and `XMM0`-`XMM5` volatile. When present, the upper portions of `YMM0`-`YMM15` and `ZMM0`-`ZMM15` are also volatile. On AVX512VL, the `ZMM`, `YMM`, and `XMM` registers 16-31 are also volatile. When AMX support is present, the `TMM` tile registers are volatile. Consider volatile registers destroyed on function calls unless otherwise safety-provable by analysis such as whole program optimization. -The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile. They must be saved and restored by a function that uses them. +The x64 ABI considers registers `RBX`, `RBP`, `RDI`, `RSI`, `RSP`, `R12`, `R13`, `R14`, `R15`, and `XMM6`-`XMM15` nonvolatile. They must be saved and restored by a function that uses them. + +When APX support is present, registers `R16`-`R29` are volatile. `R30` and `R31` are nonvolatile. ## Function pointers @@ -160,7 +162,7 @@ Function pointers are simply pointers to the label of the respective function. T ## Floating-point support for older code -The MMX and floating-point stack registers (MM0-MM7/ST0-ST7) are preserved across context switches. There's no explicit calling convention for these registers. The use of these registers is strictly prohibited in kernel mode code. +The MMX and floating-point stack registers (`MM0`-`MM7`/`ST0`-`ST7`) are preserved across context switches. There's no explicit calling convention for these registers. The use of these registers is strictly prohibited in kernel mode code. ## FPCSR @@ -170,48 +172,84 @@ The x87 FPU control word register gets set using the following standard values a | Register\[bits] | Setting | |-|-| -| FPCSR\[0:6] | Exception masks all 1s (all exceptions masked) | -| FPCSR\[7] | Reserved - 0 | -| FPCSR\[8:9] | Precision Control - 10B (double precision) | -| FPCSR\[10:11] | Rounding control - 0 (round to nearest) | -| FPCSR\[12] | Infinity control - 0 (not used) | +| `FPCSR\[0:6]` | Exception masks all 1s (all exceptions masked) | +| `FPCSR\[7]` | Reserved - 0 | +| `FPCSR\[8:9]` | Precision Control - 10B (double precision) | +| `FPCSR\[10:11]` | Rounding control - 0 (round to nearest) | +| `FPCSR\[12]` | Infinity control - 0 (not used) | -A callee that modifies any of the fields within FPCSR must restore them before returning to its caller. Furthermore, a caller that has modified any of these fields must restore them to their standard values before invoking a callee, unless by agreement the callee expects the modified values. +A callee that modifies any of the fields within `FPCSR` must restore them before returning to its caller. Furthermore, a caller that has modified any of these fields must restore them to their standard values before invoking a callee, unless by agreement the callee expects the modified values. There are two exceptions to the rules about the nonvolatility of the control flags: -- In functions where the documented purpose of the given function is to modify the nonvolatile FPCSR flags. +- In functions where the documented purpose of the given function is to modify the nonvolatile `FPCSR` flags. - When it's provably correct that the violation of these rules results in a program that behaves the same as a program that doesn't violate the rules, for example, through whole-program analysis. +Despite being considered nonvolatile, there is no static unwind descriptor describing where it was saved and where it should be restored from. Exception-safe code which modifies `FPCSR` should resort to an exception finalizer (e.g. C++ destructor or a `__finally` clause) to restore it explicitly, when unwinding the stack. + ## MXCSR -The register state also includes MXCSR. The calling convention divides this register into a volatile portion and a nonvolatile portion. The volatile portion consists of the six status flags, in MXCSR\[0:5], while the rest of the register, MXCSR\[6:15], is considered nonvolatile. +The register state also includes `MXCSR`. The calling convention divides this register into a volatile portion and a nonvolatile portion. The volatile portion consists of the six status flags, in `MXCSR\[0:5]`, while the rest of the register, `MXCSR\[6:15]`, is considered nonvolatile. The nonvolatile portion is set to the following standard values at the start of program execution: | Register\[bits] | Setting | |-|-| -| MXCSR\[6] | Denormals are zeros - 0 | -| MXCSR\[7:12] | Exception masks all 1s (all exceptions masked) | -| MXCSR\[13:14] | Rounding control - 0 (round to nearest) | -| MXCSR\[15] | Flush to zero for masked underflow - 0 (off) | +| `MXCSR\[6]` | Denormals are zeros - 0 | +| `MXCSR\[7:12]` | Exception masks all 1s (all exceptions masked) | +| `MXCSR\[13:14]` | Rounding control - 0 (round to nearest) | +| `MXCSR\[15]` | Flush to zero for masked underflow - 0 (off) | -A callee that modifies any of the nonvolatile fields within MXCSR must restore them before returning to its caller. Furthermore, a caller that has modified any of these fields must restore them to their standard values before invoking a callee, unless by agreement the callee expects the modified values. +A callee that modifies any of the nonvolatile fields within `MXCSR` must restore them before returning to its caller. Furthermore, a caller that has modified any of these fields must restore them to their standard values before invoking a callee, unless by agreement the callee expects the modified values. There are two exceptions to the rules about the nonvolatility of the control flags: -- In functions where the documented purpose of the given function is to modify the nonvolatile MXCSR flags. +- In functions where the documented purpose of the given function is to modify the nonvolatile `MXCSR` flags. - When it's provably correct that the violation of these rules results in a program that behaves the same as a program that doesn't violate the rules, for example, through whole-program analysis. -Make no assumptions about the MXCSR register's volatile portion state across a function boundary, unless the function documentation explicitly describes it. +Make no assumptions about the `MXCSR` register's volatile portion state across a function boundary, unless the function documentation explicitly describes it. + +Despite parts of `MXCSR` being considered nonvolatile, there is no static unwind descriptor describing where it was saved and where it should be restored from. Exception-safe code which modifies the nonvolatile portions of `MXCSR` should resort to an exception finalizer (e.g. C++ destructor or a `__finally` clause) to restore it explicitly, when unwinding the stack. ## setjmp/longjmp When you include `setjmpex.h` or `setjmp.h`, all calls to [`setjmp`](../c-runtime-library/reference/setjmp.md) or [`longjmp`](../c-runtime-library/reference/longjmp.md) result in an unwind that invokes destructors and `__finally` calls. This behavior differs from x86, where including `setjmp.h` results in `__finally` clauses and destructors not being invoked. -A call to `setjmp` preserves the current stack pointer, nonvolatile registers, and MXCSR registers. Calls to `longjmp` return to the most recent `setjmp` call site and resets the stack pointer, nonvolatile registers, and MXCSR registers, back to the state as preserved by the most recent `setjmp` call. +A call to `setjmp` preserves the current stack pointer, nonvolatile registers, and `MXCSR` registers. Calls to `longjmp` return to the most recent `setjmp` call site and resets the stack pointer, nonvolatile registers, and `MXCSR` registers, back to the state as preserved by the most recent `setjmp` call. + +If APX is supported, `R30` and `R31` should not be modified in a function from the point `setjmp` is called to the point where the call which ultimately results in `longjmp` is made. This limitation is the result of `R30` and `R31` not being saved as part of `jmp_buf` - this structure definition cannot change. Instead, they are restored via the unwinder. The following example demonstrates how the difference on how the data is restored influences this restriction: + +```c +jmp_buf jmpbuffer; + +void function_a() { + ... + + int val = setjmp(jmpbuffer); // At this time R30 is 10 + + ... + + if (val == 0) { + function_b(); // At this time R30 is 20 + } + + ... +} + +void function_b() { + ... + + longjmp(jmpbuffer, 1); + + ... +} +``` + +In this example, the value of `R30` changes from the point where `setjmp` is called to the point `function_b` is called. In `function_b`, `longjmp` unwinds the stack until it reaches the function which called `setjmp` (`function_a` in this case). The value restored for `R30` will be `20` (the value at the point `function_b` was called), not `10` (the value at which `setjmp` was called). This means that when `setjmp` returns for the second time (as the result of `longjmp`) the value of `R30` will be set to `20` instead of `10`, which is incorrect. This is why compilers must ensure `R30` and `R31` remain constant from the point `setjmp` is called to the last place in the function which could ultimately result in `longjmp` being called. + +Since `longjmp` can be called from an exception filter (not just a sub-routine), this effectively dictates that `R30` and `R31` should remain constant from the point `setjmp` is called through the rest of the function. ## See also diff --git a/docs/build/x64-software-conventions.md b/docs/build/x64-software-conventions.md index 7f8229a5313..89bb5eb1397 100644 --- a/docs/build/x64-software-conventions.md +++ b/docs/build/x64-software-conventions.md @@ -187,7 +187,7 @@ If you require more strict alignment, use `__declspec(align(N))` on your variabl ## x64 register usage -The x64 architecture provides for 16 general-purpose registers (hereafter referred to as integer registers) as well as 16 XMM/YMM registers available for floating-point use. Volatile registers are scratch registers presumed by the caller to be destroyed across a call. Nonvolatile registers are required to retain their values across a function call and must be saved by the callee if used. +The x64 architecture provides for 16 general-purpose registers (hereafter referred to as integer registers) as well as 16 `XMM`/`YMM` registers available for floating-point use. Volatile registers are scratch registers presumed by the caller to be destroyed across a call. Nonvolatile registers are required to retain their values across a function call and must be saved by the callee if used. ### Register volatility and preservation @@ -195,25 +195,27 @@ The following table describes how each register is used across function calls: |Register|Status|Use| |-|-|-| -|RAX|Volatile|Return value register| -|RCX|Volatile|First integer argument| -|RDX|Volatile|Second integer argument| -|R8|Volatile|Third integer argument| -|R9|Volatile|Fourth integer argument| -|R10:R11|Volatile|Must be preserved as needed by caller; used in syscall/sysret instructions| -|R12:R15|Nonvolatile|Must be preserved by callee| -|RDI|Nonvolatile|Must be preserved by callee| -|RSI|Nonvolatile|Must be preserved by callee| -|RBX|Nonvolatile|Must be preserved by callee| -|RBP|Nonvolatile|May be used as a frame pointer; must be preserved by callee| -|RSP|Nonvolatile|Stack pointer| -|XMM0, YMM0|Volatile|First FP argument; first vector-type argument when **`__vectorcall`** is used| -|XMM1, YMM1|Volatile|Second FP argument; second vector-type argument when **`__vectorcall`** is used| -|XMM2, YMM2|Volatile|Third FP argument; third vector-type argument when **`__vectorcall`** is used| -|XMM3, YMM3|Volatile|Fourth FP argument; fourth vector-type argument when **`__vectorcall`** is used| -|XMM4, YMM4|Volatile|Must be preserved as needed by caller; fifth vector-type argument when **`__vectorcall`** is used| -|XMM5, YMM5|Volatile|Must be preserved as needed by caller; sixth vector-type argument when **`__vectorcall`** is used| -|XMM6:XMM15, YMM6:YMM15|Nonvolatile (XMM), Volatile (upper half of YMM)|Must be preserved by callee. YMM registers must be preserved as needed by caller.| +|`RAX`|Volatile|Return value register| +|`RCX`|Volatile|First integer argument| +|`RDX`|Volatile|Second integer argument| +|`R8`|Volatile|Third integer argument| +|`R9`|Volatile|Fourth integer argument| +|`R10`:`R11`|Volatile|Must be preserved as needed by caller; used in syscall/sysret instructions| +|`R12`:`R15`|Nonvolatile|Must be preserved by callee| +|`R16`:`R29`|Volatile|Must be preserved as needed by caller (APX Register)| +|`R30`:`R31`|Nonvolatile|Must be preserved by callee (APX Register)| +|`RDI`|Nonvolatile|Must be preserved by callee| +|`RSI`|Nonvolatile|Must be preserved by callee| +|`RBX`|Nonvolatile|Must be preserved by callee| +|`RBP`|Nonvolatile|May be used as a frame pointer; must be preserved by callee| +|`RSP`|Nonvolatile|Stack pointer| +|`XMM0`, `YMM0`|Volatile|First FP argument; first vector-type argument when **`__vectorcall`** is used| +|`XMM1`, `YMM1`|Volatile|Second FP argument; second vector-type argument when **`__vectorcall`** is used| +|`XMM2`, `YMM2`|Volatile|Third FP argument; third vector-type argument when **`__vectorcall`** is used| +|`XMM3`, `YMM3`|Volatile|Fourth FP argument; fourth vector-type argument when **`__vectorcall`** is used| +|`XMM4`, `YMM4`|Volatile|Must be preserved as needed by caller; fifth vector-type argument when **`__vectorcall`** is used| +|`XMM5`, `YMM5`|Volatile|Must be preserved as needed by caller; sixth vector-type argument when **`__vectorcall`** is used| +|`XMM6`:`XMM15`, `YMM6`:`YMM15`|Nonvolatile (`XMM`), Volatile (upper half of `YMM`)|Must be preserved by callee. `YMM` registers must be preserved as needed by caller.| On function exit and on function entry to C Runtime Library calls and Windows system calls, the direction flag in the CPU flags register is expected to be cleared. diff --git a/docs/build/x64-unwind-information-v3.md b/docs/build/x64-unwind-information-v3.md new file mode 100644 index 00000000000..81fe1c65beb --- /dev/null +++ b/docs/build/x64-unwind-information-v3.md @@ -0,0 +1,422 @@ +--- +title: x64 Unwind Information V3 +description: Exception Handling Unwind Information V3 - Preview Specification +ms.date: 05/18/2026 +author: pmsjt +ms.author: pedrot +ms.reviewer: pedrot +--- + +# Exception Handling Unwind Information V3 + +## Scope + +Unwind Information V3 adds support for the Intel APX (Advanced Performance Extensions). It also brings additional flexibility to the code generation allowed in both function prologues and epilogues, enabling compilers to better optimize functions as a whole. + +Unwind V3 is required for code supporting APX. Non-APX enabled code should still use the [conventional (pre-V3) Unwind Information](../build/exception-handling-x64.md). + +> [!WARNING] +> Unwind Information V3 is a preview specification. There's still a risk of breaking changes or omissions. Code produced under this guidance should itself be considered preview code. + +## Terminology + +| Term | Definition | +|------|------------| +| **Fragment** | A contiguous region of machine code described by a single `RUNTIME_FUNCTION` / `UNWIND_INFO_V3` pair. A function might consist of a *main fragment* and zero or more *subfragments* chained together. For more information, see [Chained unwind info structures](../build/exception-handling-x64.md#chained-unwind-info-structures). | +| **WOD** | The Winding Operation Descriptor is a variable-length packed encoding of a single unwind operation (push, alloc, save, and so on). | +| **WOD pool** | The byte array within the payload that stores all WODs for a fragment's prolog and epilog(s). | +| **IP Offset** | The unsigned byte offset of an instruction relative to the start of the prolog or epilog. | +| **Payload** | The variable-length region immediately after the 4-byte `UNWIND_INFO_V3` header, sized by `PayloadWords` 16-bit words. Contains the large prolog extension, prolog IP offsets, epilog descriptors (with their IP offsets), and the WOD pool. | +| **RVA** | Relative Virtual Address is the offset from the base address of the image at load time. | + +## Overall Object-File Layout + +Unwind V3 reuses the existing PE/COFF `.pdata` and `.xdata` section conventions unchanged: + +``` +.pdata - sorted array of IMAGE_AMD64_RUNTIME_FUNCTION_ENTRY (12 bytes each) +.xdata - UNWIND_INFO_V3 structures referenced by .pdata entries +``` + +Each `RUNTIME_FUNCTION` entry is: + +| Offset | Size | Field | +|--------|------|-------| +| 0 | 4 | `BeginAddress` - RVA of fragment start | +| 4 | 4 | `EndAddress` - RVA of first byte past fragment end | +| 8 | 4 | `UnwindInfoAddress` - RVA of `UNWIND_INFO_V3` in `.xdata` | + +No changes from V1 or V2. + +## `UNWIND_INFO_V3` Header + +All multi-byte fields are little-endian. Bit 0 is the LSB of each byte. + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0 | [2:0] | `Version` (= 3) | 3 bits | +| 0 | [7:3] | `Flags` | 5 bits | +| 1 | [7:0] | `SizeOfProlog` | 8 bits | +| 2 | [7:0] | `PayloadWords` | 8 bits | +| 3 | [4:0] | `NumberOfOps` | 5 bits | +| 3 | [7:5] | `NumberOfEpilogs` | 3 bits | + +### Field Semantics + +| Field | Description | +|-------|-------------| +| `Version` | Must be `3`. | +| `Flags` | Same flag definitions as V1 or V2: `UNW_FLAG_EHANDLER` (0x01), `UNW_FLAG_UHANDLER` (0x02), `UNW_FLAG_CHAININFO` (0x04). New in V3: `UNW_FLAG_LARGE` (0x08). Bit 4 reserved (zero). | +| `SizeOfProlog` | Byte offset to the start of the first instruction that isn't part of the prolog. When `UNW_FLAG_LARGE` is set, this 8-bit field is the low byte of a 16-bit prolog size. For more information on the 16-bit form, see [`UNW_FLAG_LARGE` and `UNWIND_INFO_LARGE_V3`](#unw_flag_large-and-unwind_info_large_v3). | +| `PayloadWords` | Number of 16-bit words of payload following this header. The payload contains prolog IP offsets, all epilog descriptors (including their IP offsets), and the WOD pool. Doesn't include the exception-handler RVA or chained `RUNTIME_FUNCTION` that might follow. The algorithm to locate the handler/chain data is the same as V1 or V2: `header + 4 + PayloadWords * 2`, DWORD-aligned. | +| `NumberOfOps` | Count of WODs in the prolog (0–31). Zero means no prolog. If a function needs more than 31 prolog operations, use a subfragment. | +| `NumberOfEpilogs` | Count of `EPILOG_INFO_V3` descriptors that follow the prolog IP offsets (0–7). Zero means no epilogs in this fragment. If more than 7 are needed, use a subfragment. | + +### `UNW_FLAG_LARGE` and `UNWIND_INFO_LARGE_V3` + +When `UNW_FLAG_LARGE` is set in the header `Flags`, the first byte of the payload is a 1-byte `UNWIND_INFO_LARGE_V3` extension: + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0 | [7:0] | `SizeOfPrologHighByte` | 8 bits | + +`SizeOfPrologHighByte` is combined with `UNWIND_INFO_V3.SizeOfProlog` to form a 16-bit prolog size: `SizeOfProlog16 = (SizeOfPrologHighByte << 8) | SizeOfProlog`. + +Additionally, when `UNW_FLAG_LARGE` is set: + +- Prolog IP offset entries are 16-bit unsigned (2 bytes each) instead of 8-bit. + +The `UNWIND_INFO_LARGE_V3` byte is part of the payload and is included in `PayloadWords`. The handler-offset formula remains unchanged. + +This flag is only necessary for prologs exceeding 255 bytes. + +### Locating Exception Handler / Chain Info + +Identical to V1 or V2: + +``` +handler_offset = ALIGN_UP(sizeof(UNWIND_INFO_V3) + PayloadWords * 2, 4) +``` + +If `UNW_FLAG_EHANDLER` or `UNW_FLAG_UHANDLER` is set, a 4-byte handler RVA is at `handler_offset`, followed by language-specific handler data. + +If `UNW_FLAG_CHAININFO` is set, a 12-byte `RUNTIME_FUNCTION` is at `handler_offset`. + +## Payload Layout + +Immediately after the 4-byte header, the payload is arranged in the following order (all packed, `#pragma pack(1)` semantics): + +1. `UNWIND_INFO_LARGE_V3` - 1 byte, present only if `UNW_FLAG_LARGE` is set. +1. Prolog IP Offsets - `NumberOfOps` bytes (or 16-bit words if `UNW_FLAG_LARGE`). +1. For each epilog (repeated `NumberOfEpilogs` times): + - `EPILOG_INFO_V3` descriptor. + - `EPILOG_INFO_EX_V3` or `EPILOG_INFO_LARGE_EX_V3` extended descriptor (present only when `NumberOfOps > 0`). + - IP Offset array - `NumberOfOps` bytes (or 16-bit words if `EPILOG_INFO_LARGE`). +1. WOD Pool - remaining bytes. + +Total size = `PayloadWords` × 2 bytes (may include padding to fill words). + +### Prolog IP Offsets + +An array of `NumberOfOps` entries. Each entry is an unsigned byte giving the IP offset from the start of the fragment of the instruction that performs the corresponding unwind operation. When `UNW_FLAG_LARGE` is set, each entry is an unsigned 16-bit word instead. + +**Ordering:** The first entry corresponds to the operation closest to the function body (the *last* prolog instruction with an unwind effect). The last entry corresponds to the operation closest to the function entry point (the *first* prolog instruction). This matches the V1 or V2 convention of listing unwind codes in reverse execution order. The prolog WODs always start at byte offset zero of the WOD pool, and this same ordering applies. + +### Epilog Descriptors + +Zero or more `EPILOG_INFO_V3` structures follow the prolog IP offsets. Each can have an optional `EPILOG_INFO_EX_V3` (or `EPILOG_INFO_LARGE_EX_V3` when the `EPILOG_INFO_LARGE` flag is set) plus its own variable-size IP offset array, of size `NumberOfOps`: + +#### When `NumberOfOps > 0` (full descriptor) + +**Standard form** (`EPILOG_INFO_LARGE` not set): + +`EPILOG_INFO_V3`: + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0 | [2:0] | `Flags` | 3 bits | +| 0 | [7:3] | `NumberOfOps` | 5 bits | +| 1–2 | [15:0] | `EpilogOffset` | 16-bit signed | + +`EPILOG_INFO_EX_V3`: + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0–1 | [15:0] | `FirstOp` | 16-bit unsigned | +| 2 | [7:0] | `IpOffsetOfLastInstruction` | 8 bits unsigned | +| 3 .. | - | IP Offset array | `NumberOfOps` bytes, unsigned | + +**Large form** (`EPILOG_INFO_LARGE` set): + +`EPILOG_INFO_V3`: + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0 | [2:0] | `Flags` | 3 bits | +| 0 | [7:3] | `NumberOfOps` | 5 bits | +| 1–2 | [15:0] | `EpilogOffset` | 16-bit signed | + +`EPILOG_INFO_LARGE_EX_V3`: + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0–1 | [15:0] | `FirstOp` | 16-bit unsigned | +| 2–3 | [15:0] | `IpOffsetOfLastInstruction` | 16 bits unsigned | +| 4 .. | - | IP Offset array | `NumberOfOps` × 2 bytes, unsigned 16-bit | + +#### When `NumberOfOps == 0` (inherited descriptor) + +`EPILOG_INFO_V3`: + +| Byte | Bits | Field | Width | +|------|------|-------|-------| +| 0 | [2:0] | `Flags` | 3 bits | +| 0 | [7:3] | `NumberOfOps` (= 0) | 5 bits | +| 1–2 | [15:0] | `EpilogOffset` | 16-bit signed | + +An `EPILOG_INFO_V3` record with `NumberOfOps == 0` inherits the effective values for `NumberOfOps`, `FirstOp`, `IpOffsetOfLastInstruction` fields, and IP offset array from the first preceding `EPILOG_INFO_V3` with `NumberOfOps != 0`. The compiler must ensure `Flags` bits 0 and 1 on an epilog record with `NumberOfOps == 0` have the same value as those from the first preceding `EPILOG_INFO_V3` with `NumberOfOps != 0`. + +#### Epilog Field Semantics + +| Field | Description | +|-------|-------------| +| `Flags` | Bit 0: `EPILOG_INFO_PARENT_FRAGMENT_TRANSFER` - set if this epilog transfers control back to the parent fragment (for example, via JMP) rather than returning to the caller. Bit 1: `EPILOG_INFO_LARGE` - when set, the extended descriptor uses `EPILOG_INFO_LARGE_EX_V3` (16-bit `IpOffsetOfLastInstruction`) and each IP offset entry is 16-bit, accommodating epilogs exceeding 255 bytes. Bit 2: reserved (zero). | +| `NumberOfOps` | Number of WODs for this epilog (0–31). Zero is a special value meaning "inherit from previous epilog descriptor." | +| `EpilogOffset` | 16-bit signed displacement to the first instruction of this epilog. For the first epilog descriptor: positive values are byte offsets from the fragment start, and negative values are byte offsets from the fragment tail, that is, the first byte past the end. For subsequent epilog descriptors: delta from the start of the previous epilog. All epilogs must use the same sign - either all sorted ascending from start, or all sorted descending from tail. | +| `FirstOp` | Byte index into the WOD pool where the first WOD for this epilog resides. This is a byte offset, not a WOD index. Epilogs may share WODs with the prolog or with each other by pointing into the same pool region. | +| `IpOffsetOfLastInstruction` | Unsigned byte offset from the epilog start of the last instruction in the epilog, typically RET, or JMP. 8-bit in `EPILOG_INFO_EX_V3`; 16-bit in `EPILOG_INFO_LARGE_EX_V3`. The unwinder uses this value to determine where the epilog ends and the function body resumes. | + +#### Epilog IP Offsets + +Immediately after each full epilog descriptor (when `NumberOfOps > 0`), an array of `NumberOfOps` entries gives the IP offset of each epilog instruction that has a corresponding WOD. Each entry is an unsigned byte, or an unsigned 16-bit word when `EPILOG_INFO_LARGE` is set. Ordering: first entry = operation closest to the body (first epilog instruction with an unwind effect), last entry = operation closest to the control-transfer instruction. + +### WOD Pool + +The remaining bytes in the payload form the WOD pool. The prolog's WODs implicitly start at byte offset 0 of this pool. Each epilog's WOD list start at the byte offset given by its `FirstOp` field. WODs are packed with no alignment or padding between them. + +The number of WODs consumed for the prolog is `UNWIND_INFO_V3.NumberOfOps`. The number consumed for each epilog is its respective `EPILOG_INFO_V3.NumberOfOps` (or inherited). + +## WOD Encoding Reference + +WODs are variable-length (1–5 bytes), packed with `#pragma pack(1)`. The opcode is encoded in the **low-order bits** of the first byte. Decoding requires multi-level bit inspection. + +### Opcode Dispatch Table + +To decode a WOD, read the first byte and test its low bits in the following order: + +| Test | Opcode Value | WOD Type | Size | +|------|--------------|----------|------| +| `byte[0] == 0x00` | 0 | `WOD_SET_FPREG` | 2 bytes | +| `byte[0] == 0x01` | 1 | `WOD_ALLOC_HUGE` | 5 bytes | +| `byte[0] == 0x02` | 2 | `WOD_ALLOC_LARGE` | 3 bytes | +| `byte[0] == 0x03` | 3 | `WOD_PUSH_CANONICAL_FRAME` | 2 bytes | +| `(byte[0] & 0x07) == 0x04` | 4 | `WOD_PUSH` | 1 byte | +| `(byte[0] & 0x07) == 0x05` | 5 | `WOD_SAVE_NONVOL_FAR` | 5 bytes | +| `(byte[0] & 0x07) == 0x06` | 6 | `WOD_SAVE_NONVOL` | 3 bytes | +| `(byte[0] & 0x07) == 0x07` | 7 | `WOD_PUSH_CONSECUTIVE_2` | 1 byte | +| `(byte[0] & 0x0F) == 0x08` | 8 | `WOD_ALLOC_SMALL` | 1 byte | +| `(byte[0] & 0x0F) == 0x09` | 9 | `WOD_SAVE_XMM128_FAR` | 5 bytes | +| `(byte[0] & 0x0F) == 0x0A` | 10 | `WOD_SAVE_XMM128` | 3 bytes | +| `(byte[0] & 0x3F) == 0x20` | 32 | `WOD_PUSH2` | 2 bytes | + +** WOD decoding algorithm (pseudocode):** + +```c +uint8_t b0 = pool[offset]; +uint8_t op3 = b0 & 0x07; + +switch (op3) +{ +case 4: return WOD_PUSH; // 3-bit opcode = 100b +case 5: return WOD_SAVE_NONVOL_FAR;// 3-bit opcode = 101b +case 6: return WOD_SAVE_NONVOL; // 3-bit opcode = 110b +case 7: return WOD_PUSH_CONSECUTIVE_2; // 3-bit opcode = 111b +default: break; // bits[2:0] are 0b000, 0b001, 0b010, or 0b011 +} + +uint8_t op4 = b0 & 0x0F; +switch (op4) +{ +case 0x08: return WOD_ALLOC_SMALL; +case 0x09: return WOD_SAVE_XMM128_FAR; +case 0x0A: return WOD_SAVE_XMM128; +default: break; +} + +uint8_t op6 = b0 & 0x3F; +if (op6 == 0x20) return WOD_PUSH2; + +// 8-bit opcode (full byte match) +switch (b0) +{ +case 0x00: return WOD_SET_FPREG; +case 0x01: return WOD_ALLOC_HUGE; +case 0x02: return WOD_ALLOC_LARGE; +case 0x03: return WOD_PUSH_CANONICAL_FRAME; +default: return INVALID; +} +``` + +### WOD layouts (Bit-Level) + +All bit positions are numbered LSB-first within each byte. Multi-byte integer fields are little-endian. + +#### `WOD_PUSH` - 1 byte + +``` +Byte 0: [2:0] = 100b (opcode 4) + [7:3] = Register (5 bits, AMD64 integer register number) +``` + +**Effect:** `PUSH ` adjusts RSP by 8 and stores register. + +#### `WOD_PUSH2` - 2 bytes + +``` +Byte 0: [5:0] = 100000b (opcode 32) + [7:6] = Register1[1:0] (low 2 bits) +Byte 1: [2:0] = Register1[4:2] (high 3 bits) + [7:3] = Register2 (5 bits) +``` + +**Effect:** `PUSH2 , ` pushes two registers with a single instruction (APX). Adjusts RSP by 16. + +#### `WOD_PUSH_CONSECUTIVE_2` - 1 byte + +``` +Byte 0: [2:0] = 111b (opcode 7) + [7:3] = Register (5 bits) +``` + +**Effect:** Pushes `Register` and `Register+1` consecutively. Adjusts `RSP` by 16 total. `Register` value must be limited to [0, 30], as value of 31 would place `Register+1` out of bounds. + +#### `WOD_ALLOC_SMALL` - 1 byte + +``` +Byte 0: [3:0] = 1000b (opcode 8) + [7:4] = Size (4 bits) +``` + +**Actual allocation:** `(Size + 1) * 8` bytes. Range: 8–128 bytes in steps +of 8. + +#### `WOD_ALLOC_LARGE` - 3 bytes + +``` +Byte 0: [7:0] = 0x02 (opcode 2) +Bytes 1–2: Size (16-bit unsigned, little-endian) +``` + +**Actual allocation:** `Size * 8` bytes. Range: up to 524,280 bytes. + +#### `WOD_ALLOC_HUGE` - 5 bytes + +``` +Byte 0: [7:0] = 0x01 (opcode 1) +Bytes 1–4: Size (32-bit unsigned, little-endian) +``` + +**Actual allocation:** Raw byte count (no scaling). Range: up to 4 GiB. + +#### `WOD_SET_FPREG` - 2 bytes + +``` +Byte 0: [7:0] = 0x00 (opcode 0) +Byte 1: [3:0] = Register (4 bits, 0–15) + [7:4] = Offset (4 bits) +``` + +**Effect:** Establishes a frame pointer. ` = RSP + Offset * 16`. + +#### `WOD_SAVE_NONVOL` - 3 bytes + +``` +Byte 0: [2:0] = 110b (opcode 6) + [7:3] = Register (5 bits) +Bytes 1–2: Displacement (16-bit unsigned, little-endian) +``` + +**Effect:** `MOV [RSP + Displacement * 8], ` saves a nonvolatile +integer register to the stack. + +#### `WOD_SAVE_NONVOL_FAR` - 5 bytes + +``` +Byte 0: [2:0] = 101b (opcode 5) + [7:3] = Register (5 bits) +Bytes 1–4: Displacement (32-bit unsigned, little-endian) +``` + +**Effect:** Same as `WOD_SAVE_NONVOL` but with a 32-bit unscaled byte displacement. Used when the offset doesn't fit in 16 bits scaled by 8. + +#### `WOD_SAVE_XMM128` - 3 bytes + +``` +Byte 0: [3:0] = 1010b (opcode 10) + [7:4] = Register (4 bits, XMM0–XMM15) +Bytes 1–2: Displacement (16-bit unsigned, little-endian) +``` + +**Effect:** `MOVAPS [RSP + Displacement * 16], ` saves a 128-bit +XMM register. + +#### `WOD_SAVE_XMM128_FAR` - 5 bytes + +``` +Byte 0: [3:0] = 1001b (opcode 9) + [7:4] = Register (4 bits, XMM0–XMM15) +Bytes 1–4: Displacement (32-bit unsigned, little-endian) +``` + +**Effect:** Same as `WOD_SAVE_XMM128` but with a 32-bit unscaled byte displacement. + +#### `WOD_PUSH_CANONICAL_FRAME` - 2 bytes + +``` +Byte 0: [7:0] = 0x03 (opcode 3) +Byte 1: [7:0] = Type (8 bits) +``` + +**Effect:** Indicates the hardware/OS pushed a canonical frame onto the stack. Type values distinguish: +- Machine frame without error code +- Machine frame with error code +- Machine frame with shadow-stack push +- Context record + +(Exact type values are defined by the OS; consult the Windows SDK headers.) + +### Opcode Constant Summary + +```c +#define WOD_OP_SET_FPREG 0 // 8-bit opcode, 2 bytes +#define WOD_OP_ALLOC_HUGE 1 // 8-bit opcode, 5 bytes +#define WOD_OP_ALLOC_LARGE 2 // 8-bit opcode, 3 bytes +#define WOD_OP_PUSH_CANONICAL_FRAME 3 // 8-bit opcode, 2 bytes +#define WOD_OP_PUSH 4 // 3-bit opcode, 1 byte +#define WOD_OP_SAVE_NONVOL_FAR 5 // 3-bit opcode, 5 bytes +#define WOD_OP_SAVE_NONVOL 6 // 3-bit opcode, 3 bytes +#define WOD_OP_PUSH_CONSECUTIVE_2 7 // 3-bit opcode, 1 byte +#define WOD_OP_ALLOC_SMALL 8 // 4-bit opcode, 1 byte +#define WOD_OP_SAVE_XMM128_FAR 9 // 4-bit opcode, 5 bytes +#define WOD_OP_SAVE_XMM128 10 // 4-bit opcode, 3 bytes +#define WOD_OP_PUSH2 32 // 6-bit opcode, 2 bytes +``` + +### Register Encoding + +Integer registers use the standard AMD64 numbering (5 bits, 0–31): + +| Value | Register | +|-------|----------| +| 0 | RAX | +| 1 | RCX | +| 2 | RDX | +| 3 | RBX | +| 4 | RSP | +| 5 | RBP | +| 6 | RSI | +| 7 | RDI | +| 8 - 15 | R8 - R15 +| 16 - 31 | R16 - R31 (APX) | + +XMM register fields are 4 bits (0–15), mapping directly to XMM0–XMM15. diff --git a/docs/c-runtime-library/reference/atexit.md b/docs/c-runtime-library/reference/atexit.md index 1264498d49f..392566beb4d 100644 --- a/docs/c-runtime-library/reference/atexit.md +++ b/docs/c-runtime-library/reference/atexit.md @@ -1,7 +1,7 @@ --- description: "Learn more about: atexit" title: "atexit" -ms.date: "11/04/2016" +ms.date: "8/18/2026" api_name: ["atexit"] api_location: ["msvcrt.dll", "msvcr80.dll", "msvcr90.dll", "msvcr100.dll", "msvcr100_clr0400.dll", "msvcr110.dll", "msvcr110_clr0400.dll", "msvcr120.dll", "msvcr120_clr0400.dll", "ucrtbase.dll"] api_type: ["DLLExport"] @@ -28,25 +28,27 @@ Function to be called. ## Return value -**`atexit`** returns 0 if successful, or a nonzero value if an error occurs. +`atexit` returns 0 if successful, or a nonzero value if an error occurs. ## Remarks -The **`atexit`** function is passed the address of a function *`func`* to be called when the program terminates normally. Successive calls to **`atexit`** create a register of functions that are executed in last-in, first-out (LIFO) order. The functions passed to **`atexit`** can't take parameters. **`atexit`** and **`_onexit`** use the heap to hold the register of functions. Thus, the number of functions that can be registered is limited only by heap memory. +The `atexit` function gets the address of a function *`func`* to call when the program terminates normally. Successive calls to `atexit` create a register of functions that execute in last-in, first-out (LIFO) order. The functions passed to `atexit` can't take parameters. `atexit` and `_onexit` use the heap to hold the register of functions. Thus, the number of functions you can register is limited only by heap memory. -The code in the **`atexit`** function shouldn't contain any dependency on any DLL that could have already been unloaded when the **`atexit`** function is called. +The code in the `atexit` function shouldn't contain any dependency on any DLL that could already be unloaded when the `atexit` function is called. -To generate an ANSI-conformant application, use the ANSI-standard **`atexit`** function (rather than the similar **`_onexit`** function). +**Microsoft-specific DLL behavior**: When a DLL unloads, after `DllMain` receives `DLL_PROCESS_DETACH`, the DLL's `atexit` callbacks run in reverse registration order, with the last callback registered running first. + +To generate an ANSI-conformant application, use the ANSI-standard `atexit` function (rather than the similar `_onexit` function). ## Requirements | Routine | Required header | |---|---| -| **`atexit`** | `` | +| `atexit` | `` | ## Example -This program pushes four functions onto the stack of functions to be executed when **`atexit`** is called. When the program exits, these programs are executed on a last in, first out basis. +This program pushes four functions onto the stack of functions to execute when `atexit` is called. When the program exits, it executes these functions in last-in, first-out order. ```C // crt_atexit.c diff --git a/docs/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s.md b/docs/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s.md index 36f21d43df4..2ce6ef33317 100644 --- a/docs/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s.md +++ b/docs/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s.md @@ -72,6 +72,9 @@ Each of the structure fields is of type **`int`**, as shown in the following tab **`_gmtime64_s`**, which uses the **`__time64_t`** structure, allows dates to be expressed up through 23:59:59, December 31, 3000, UTC; whereas **`gmtime32_s`** only represent dates through 23:59:59 January 18, 2038, UTC. Midnight, January 1, 1970, is the lower bound of the date range for both these functions. +The Microsoft-specific **`gmtime_s`** has a different signature than the C standard version. To enable the standard-conforming variant, define **`_CRT_USE_CONFORMING_ANNEX_K_TIME`** to a nonzero value before including **``**. + + **`gmtime_s`** is an inline function that evaluates to **`_gmtime64_s`** and **`time_t`** is equivalent to **`__time64_t`**. If you need to force the compiler to interpret **`time_t`** as the old 32-bit **`time_t`**, you can define `_USE_32BIT_TIME_T`. `_USE_32BIT_TIME_T` causes **`gmtime_s`** to be inlined as **`_gmtime32_s`**. We don't recommend `_USE_32BIT_TIME_T`, because your application may fail after January 18, 2038, and because it isn't allowed on 64-bit platforms. By default, this function's global state is scoped to the application. To change this behavior, see [Global state in the CRT](../global-state.md). diff --git a/docs/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s.md b/docs/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s.md index 430f90328b3..14d4aaaa5df 100644 --- a/docs/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s.md +++ b/docs/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s.md @@ -62,6 +62,8 @@ The **`localtime_s`** function converts a time stored as a [`time_t`](../standar > [!NOTE] > The target environment should try to determine whether daylight saving time is in effect. +The Microsoft-specific **`localtime_s`** has a different signature than the C standard version. To enable the standard-conforming variant, define **`_CRT_USE_CONFORMING_ANNEX_K_TIME`** to a nonzero value before including **``**. + **`_localtime64_s`**, which uses the **`__time64_t`** structure, allows dates to be expressed up through 23:59:59, January 18, 3001, coordinated universal time (UTC), whereas **`_localtime32_s`** represents dates through 23:59:59 January 18, 2038, UTC. **`localtime_s`** is an inline function that evaluates to **`_localtime64_s`**, and **`time_t`** is equivalent to **`__time64_t`**. If you need to force the compiler to interpret **`time_t`** as the old 32-bit **`time_t`**, you can define `_USE_32BIT_TIME_T`, which causes **`localtime_s`** to evaluate to **`_localtime32_s`**. We don't recommend `_USE_32BIT_TIME_T`, because your application may fail after January 18, 2038, and it isn't allowed on 64-bit platforms. diff --git a/docs/cpp/attributes.md b/docs/cpp/attributes.md index 84be79ffc4b..5e6cfc32fc0 100644 --- a/docs/cpp/attributes.md +++ b/docs/cpp/attributes.md @@ -1,9 +1,9 @@ --- title: "Attributes in C++" description: "Learn more about: Attributes in C++" -f1_keywords: ["deprecated", "noreturn", "carries_dependency", "fallthrough", "nodiscard", "maybe_unused", "likely", "unlikely", "gsl::suppress", "msvc::flatten", "msvc::forceinline", "msvc::forceinline_calls", "msvc::intrinsic", "msvc::noinline", "msvc::noinline_calls", "msvc::no_tls_guard", "msvc::musttail"] -helpviewer_keywords: ["deprecated", "noreturn", "carries_dependency", "fallthrough", "nodiscard", "maybe_unused", "likely", "unlikely", "gsl::suppress", "msvc::flatten", "msvc::forceinline", "msvc::forceinline_calls", "msvc::intrinsic", "msvc::noinline", "msvc::noinline_calls", "msvc::no_tls_guard", "msvc::musttail"] -ms.date: 12/9/2025 +f1_keywords: ["deprecated", "noreturn", "carries_dependency", "fallthrough", "nodiscard", "maybe_unused", "likely", "unlikely", "gsl::suppress", "msvc::disable", "msvc::enable", "msvc::flatten", "msvc::forceinline", "msvc::forceinline_calls", "msvc::intrinsic", "msvc::noinline", "msvc::noinline_calls", "msvc::no_tls_guard", "msvc::musttail"] +helpviewer_keywords: ["deprecated", "noreturn", "carries_dependency", "fallthrough", "nodiscard", "maybe_unused", "likely", "unlikely", "gsl::suppress", "msvc::disable", "msvc::enable", "msvc::flatten", "msvc::forceinline", "msvc::forceinline_calls", "msvc::intrinsic", "msvc::noinline", "msvc::noinline_calls", "msvc::no_tls_guard", "msvc::musttail"] +ms.date: 05/15/2026 --- # Attributes in C++ @@ -114,6 +114,63 @@ Both `#pragma warning(suppress)` and `[[gsl::suppress]]` offer fine-grained cont Whenever possible, use `[[gsl::suppress]]` for suppressing Microsoft C++ Code Analysis warnings. +### `[[msvc::disable(feature:APX)]]` + +The `[[msvc::disable(feature:APX)]]` attribute, introduced in [MSVC Build Tools version 14.51](../overview/what-s-new-for-msvc.md#whats-new-for-msvc-build-tools-version-1451) (Visual Studio version 18.6.0), is an x64-only Microsoft-specific attribute that disables Intel Advanced Performance Extensions (APX) instruction generation for a specific function. When applied to a function declaration or definition, it prevents the compiler from emitting APX instructions in that function's body, even if APX is globally enabled via the `/feature:APX` compiler option. Other functions in the same translation unit continue to use APX instructions unless they are similarly attributed. If a function with `[[msvc::disable(feature:APX)]]` calls inlined functions, the inlined code is also compiled without APX instructions. + +#### Example + +```cpp +// The following shows how to disable APX instructions for specific functions, +// even when APX is enabled globally with /feature:APX +​int test(int argc) +{ + auto lambda = + [] + [[msvc::disable(feature:APX)]] + (int argc) + { + return argc + 42; + }; + return lambda(argc); +} + +[[msvc::disable(feature:APX)]] +int test2(int x) +{ + return x + 42; +} +``` + +### `[[msvc::enable(feature:APX)]]` + +The `[[msvc::enable(feature:APX)]]` attribute, introduced in [MSVC Build Tools version 14.51](../overview/what-s-new-for-msvc.md#whats-new-for-msvc-build-tools-version-1451) (Visual Studio version 18.6.0), is an x64-only Microsoft-specific attribute that enables Intel Advanced Performance Extensions (APX) instruction generation for a specific function. When applied to a function declaration or definition, it allows the compiler to emit APX instructions in that function's body, even when APX is not globally enabled. This provides per-function opt-in to APX features without requiring `/arch:APX` for the entire translation unit. If a function with `[[msvc::enable(feature:APX)]]` has calls that are inlined into it, the inlined code is also compiled with APX instructions. + +#### `[[msvc::enable(feature:APX)]]` example + +```cpp +// The following shows how to enable APX instructions for specific functions, +// even when APX isn't enabled globally with /feature:APX + +​int test(int argc) +{ + auto lambda = + [] + [[msvc::enable(feature:APX)]] + (int argc) + { + return argc + 42; + }; + return lambda(argc); +} + +[[msvc::enable(feature:APX), msvc::noinline]] +int test2(int x) +{ + return x + 42; +} +``` + ### `[[msvc::flatten]]` The Microsoft-specific attribute `[[msvc::flatten]]` is similar to `[[msvc::forceinline_calls]]`, and can be used in the same places and in the same way. The difference is that `[[msvc::flatten]]` will `[[msvc::forceinline_calls]]` all calls in the scope it's applied to recursively, until no calls are left. This may have consequences for the resulting code size growth of the function or the throughput of the compiler, which you must manage manually. diff --git a/docs/cpp/function-call-cpp.md b/docs/cpp/function-call-cpp.md index 804b63b3b5e..8c0cd68810a 100644 --- a/docs/cpp/function-call-cpp.md +++ b/docs/cpp/function-call-cpp.md @@ -17,7 +17,7 @@ primary-expression ( expression-list ) ## Remarks -In this context, `primary-expression` is the first operand, and `expression-list`, a possibly empty list of arguments, is the second operand. The function-call operator is used for operations that require a number of parameters. This works because `expression-list` is a list instead of a single operand. The function-call operator must be a nonstatic member function. +In this context, `primary-expression` is the first operand, and `expression-list`, a possibly empty list of arguments, is the second operand. The function-call operator is useful for operations that require a number of parameters. This usefulness comes from the fact that `expression-list` is a list instead of a single operand. Before C++23, the function-call operator had to be a nonstatic member function. In C++23 and later, it can be a static member function. For more information, see [Static function call operator](static-function-call-operator.md). The function-call operator, when overloaded, does not modify how functions are called; rather, it modifies how the operator is to be interpreted when applied to objects of a given class type. For example, the following code would usually be meaningless: @@ -73,4 +73,5 @@ int main() ## See also +[Static function call operator](static-function-call-operator.md)\ [Operator Overloading](../cpp/operator-overloading.md) diff --git a/docs/cpp/header-files-cpp.md b/docs/cpp/header-files-cpp.md index b0460d00fd4..72fe57771e4 100644 --- a/docs/cpp/header-files-cpp.md +++ b/docs/cpp/header-files-cpp.md @@ -94,7 +94,7 @@ namespace N #endif /* MY_CLASS_H */ ``` -## What to put in a header file +## What to avoid in a header file Because a header file might potentially be included by multiple files, it cannot contain definitions that might produce multiple definitions of the same name. The following are not allowed, or are considered very bad practice: diff --git a/docs/cpp/smart-pointers-modern-cpp.md b/docs/cpp/smart-pointers-modern-cpp.md index 2551bba44a0..86b821bb7a3 100644 --- a/docs/cpp/smart-pointers-modern-cpp.md +++ b/docs/cpp/smart-pointers-modern-cpp.md @@ -1,9 +1,9 @@ --- -description: "Learn more about: Smart pointers (Modern C++)" title: "Smart pointers (Modern C++)" -ms.date: "11/19/2019" +description: "Learn more about how smart pointers in modern C++ help ensure that programs are free of memory and resource leaks and are exception-safe." +ms.date: 05/28/2026 ms.topic: "concept-article" -ms.assetid: 909ef870-904c-49b6-b8cd-e9d0b7dc9435 +#customer intent: As a C++ developer, I want to understand how smart pointers in modern C++ help prevent memory and resource leaks and are exception-safe. --- # Smart pointers (Modern C++) @@ -11,22 +11,26 @@ In modern C++ programming, the Standard Library includes *smart pointers*, which ## Uses for smart pointers -Smart pointers are defined in the `std` namespace in the [\](../standard-library/memory.md) header file. They are crucial to the [RAII](./object-lifetime-and-resource-management-modern-cpp.md) or *Resource Acquisition Is Initialization* programming idiom. The main goal of this idiom is to ensure that resource acquisition occurs at the same time that the object is initialized, so that all resources for the object are created and made ready in one line of code. In practical terms, the main principle of RAII is to give ownership of any heap-allocated resource—for example, dynamically-allocated memory or system object handles—to a stack-allocated object whose destructor contains the code to delete or free the resource and also any associated cleanup code. +Smart pointers are defined in the `std` namespace in the [\](../standard-library/memory.md) header file. They're crucial to the *Resource Acquisition Is Initialization* [(RAII)](./object-lifetime-and-resource-management-modern-cpp.md) programming idiom. The main goal of this idiom is to ensure that resource acquisition occurs at the same time that the object is initialized. All resources for the object are created and made ready in one line of code. -In most cases, when you initialize a raw pointer or resource handle to point to an actual resource, pass the pointer to a smart pointer immediately. In modern C++, raw pointers are only used in small code blocks of limited scope, loops, or helper functions where performance is critical and there is no chance of confusion about ownership. +In practical terms, the main principle of RAII is to give ownership of any heap-allocated resource to a stack-allocated object whose destructor contains the code to delete or free the resource and also any associated cleanup code. Such objects include dynamically allocated memory or system object handles. + +In most cases, when you initialize a raw pointer or resource handle to point to an actual resource, pass the pointer to a smart pointer immediately. In modern C++, raw pointers are only used in small code blocks of limited scope, loops, or helper functions where performance is critical and there's no chance of confusion about ownership. The following example compares a raw pointer declaration to a smart pointer declaration. [!code-cpp[smart_pointers_intro#1](codesnippet/CPP/smart-pointers-modern-cpp_1.cpp)] -As shown in the example, a smart pointer is a class template that you declare on the stack, and initialize by using a raw pointer that points to a heap-allocated object. After the smart pointer is initialized, it owns the raw pointer. This means that the smart pointer is responsible for deleting the memory that the raw pointer specifies. The smart pointer destructor contains the call to delete, and because the smart pointer is declared on the stack, its destructor is invoked when the smart pointer goes out of scope, even if an exception is thrown somewhere further up the stack. +As shown in the example, a smart pointer is a class template that you declare on the stack, and initialize by using a raw pointer that points to a heap-allocated object. After the smart pointer is initialized, it owns the raw pointer. This approach means that the smart pointer is responsible for deleting the memory that the raw pointer specifies. + +The smart pointer destructor contains the call to `delete`. Because the smart pointer is declared on the stack, its destructor is invoked when the smart pointer goes out of scope. It's invoked even if an exception is thrown somewhere further up the stack. -Access the encapsulated pointer by using the familiar pointer operators, `->` and `*`, which the smart pointer class overloads to return the encapsulated raw pointer. +Access the encapsulated pointer by using the familiar pointer operators: `->` and `*`. The smart pointer class overloads these operators to return the encapsulated raw pointer. -The C++ smart pointer idiom resembles object creation in languages such as C#: you create the object and then let the system take care of deleting it at the correct time. The difference is that no separate garbage collector runs in the background; memory is managed through the standard C++ scoping rules so that the runtime environment is faster and more efficient. +The C++ smart pointer idiom resembles object creation in languages such as C#. You create the object and then let the system take care of deleting it at the correct time. The difference is that no separate garbage collector runs in the background. Memory is managed through the standard C++ scoping rules so that the runtime environment is faster and more efficient. > [!IMPORTANT] -> Always create smart pointers on a separate line of code, never in a parameter list, so that a subtle resource leak won't occur due to certain parameter list allocation rules. +> Always create smart pointers on a separate line of code, never in a parameter list. This approach prevents a subtle resource leak due to certain parameter list allocation rules. The following example shows how a `unique_ptr` smart pointer type from the C++ Standard Library could be used to encapsulate a pointer to a large object. @@ -34,23 +38,23 @@ The following example shows how a `unique_ptr` smart pointer type from the C++ S The example demonstrates the following essential steps for using smart pointers. -1. Declare the smart pointer as an automatic (local) variable. (Do not use the **`new`** or `malloc` expression on the smart pointer itself.) +1. Declare the smart pointer as an automatic (local) variable. Don't use the `new` or `malloc` expression on the smart pointer itself. 1. In the type parameter, specify the pointed-to type of the encapsulated pointer. -1. Pass a raw pointer to a **`new`**-ed object in the smart pointer constructor. (Some utility functions or smart pointer constructors do this for you.) +1. Pass a raw pointer to a `new`-ed object in the smart pointer constructor. Some utility functions or smart pointer constructors do this action for you. 1. Use the overloaded `->` and `*` operators to access the object. 1. Let the smart pointer delete the object. -Smart pointers are designed to be as efficient as possible both in terms of memory and performance. For example, the only data member in `unique_ptr` is the encapsulated pointer. This means that `unique_ptr` is exactly the same size as that pointer, either four bytes or eight bytes. Accessing the encapsulated pointer by using the smart pointer overloaded * and -> operators is not significantly slower than accessing the raw pointers directly. +Smart pointers are designed to be as efficient as possible both in terms of memory and performance. For example, the only data member in `unique_ptr` is the encapsulated pointer. This fact means that `unique_ptr` is exactly the same size as that pointer, either four bytes or eight bytes. Accessing the encapsulated pointer by using the smart pointer overloaded `*` and `->` operators isn't significantly slower than accessing the raw pointers directly. -Smart pointers have their own member functions, which are accessed by using "dot" notation. For example, some C++ Standard Library smart pointers have a reset member function that releases ownership of the pointer. This is useful when you want to free the memory owned by the smart pointer before the smart pointer goes out of scope, as shown in the following example. +Smart pointers have their own member functions, which are accessed by using dot notation. For example, some C++ Standard Library smart pointers have a `reset` member function that releases ownership of the pointer. This aspect is useful when you want to free the memory owned by the smart pointer before the smart pointer goes out of scope, as shown in the following example. [!code-cpp[smart_pointers_intro#3](codesnippet/CPP/smart-pointers-modern-cpp_3.cpp)] -Smart pointers usually provide a way to access their raw pointer directly. C++ Standard Library smart pointers have a `get` member function for this purpose, and `CComPtr` has a public `p` class member. By providing direct access to the underlying pointer, you can use the smart pointer to manage memory in your own code and still pass the raw pointer to code that does not support smart pointers. +Smart pointers usually provide a way to access their raw pointer directly. C++ Standard Library smart pointers have a `get` member function for this purpose. `CComPtr` has a public `p` class member. By providing direct access to the underlying pointer, you can use the smart pointer to manage memory in your own code and still pass the raw pointer to code that doesn't support smart pointers. [!code-cpp[smart_pointers_intro#4](codesnippet/CPP/smart-pointers-modern-cpp_4.cpp)] @@ -62,55 +66,74 @@ The following section summarizes the different kinds of smart pointers that are Use these smart pointers as a first choice for encapsulating pointers to plain old C++ objects (POCO). -- `unique_ptr`
- Allows exactly one owner of the underlying pointer. Use as the default choice for POCO unless you know for certain that you require a `shared_ptr`. Can be moved to a new owner, but not copied or shared. Replaces `auto_ptr`, which is deprecated. Compare to `boost::scoped_ptr`. `unique_ptr` is small and efficient; the size is one pointer and it supports rvalue references for fast insertion and retrieval from C++ Standard Library collections. Header file: ``. For more information, see [How to: Create and Use unique_ptr Instances](how-to-create-and-use-unique-ptr-instances.md) and [unique_ptr Class](../standard-library/unique-ptr-class.md). +- `unique_ptr` + + Allows exactly one owner of the underlying pointer. Use as the default choice for POCO unless you know for certain that you require a `shared_ptr`. Can be moved to a new owner, but not copied or shared. Replaces `auto_ptr`, which is deprecated. Compare to `boost::scoped_ptr`. + + `unique_ptr` is small and efficient. The size is one pointer and it supports rvalue references for fast insertion and retrieval from C++ Standard Library collections. Header file: ``. For more information, see [How to: Create and use unique_ptr instances](how-to-create-and-use-unique-ptr-instances.md) and [unique_ptr Class](../standard-library/unique-ptr-class.md). + +- `shared_ptr` -- `shared_ptr`
- Reference-counted smart pointer. Use when you want to assign one raw pointer to multiple owners, for example, when you return a copy of a pointer from a container but want to keep the original. The raw pointer is not deleted until all `shared_ptr` owners have gone out of scope or have otherwise given up ownership. The size is two pointers; one for the object and one for the shared control block that contains the reference count. Header file: ``. For more information, see [How to: Create and Use shared_ptr Instances](how-to-create-and-use-shared-ptr-instances.md) and [shared_ptr Class](../standard-library/shared-ptr-class.md). + Reference-counted smart pointer. Use when you want to assign one raw pointer to multiple owners. For example, you can return a copy of a pointer from a container but also keep the original. The raw pointer isn't deleted until all `shared_ptr` owners go out of scope or otherwise give up ownership. -- `weak_ptr`
- Special-case smart pointer for use in conjunction with `shared_ptr`. A `weak_ptr` provides access to an object that is owned by one or more `shared_ptr` instances, but does not participate in reference counting. Use when you want to observe an object, but do not require it to remain alive. Required in some cases to break circular references between `shared_ptr` instances. Header file: ``. For more information, see [How to: Create and Use weak_ptr Instances](how-to-create-and-use-weak-ptr-instances.md) and [weak_ptr Class](../standard-library/weak-ptr-class.md). + The size is two pointers: one for the object and one for the shared control block that contains the reference count. Header file: ``. For more information, see [How to: Create and use shared_ptr instances](how-to-create-and-use-shared-ptr-instances.md) and [shared_ptr Class](../standard-library/shared-ptr-class.md). + +- `weak_ptr` + + Special-case smart pointer for use with `shared_ptr`. A `weak_ptr` provides access to an object that one or more `shared_ptr` instances own, but doesn't participate in reference counting. Use when you want to observe an object, but don't require it to remain alive. Required in some cases to break circular references between `shared_ptr` instances. + + Header file: ``. For more information, see [How to: Create and use weak_ptr instances](how-to-create-and-use-weak-ptr-instances.md) and [weak_ptr Class](../standard-library/weak-ptr-class.md). ### Smart pointers for COM objects (classic Windows programming) -When you work with COM objects, wrap the interface pointers in an appropriate smart pointer type. The Active Template Library (ATL) defines several smart pointers for various purposes. You can also use the `_com_ptr_t` smart pointer type, which the compiler uses when it creates wrapper classes from .tlb files. It's the best choice when you do not want to include the ATL header files. +When you work with COM objects, wrap the interface pointers in an appropriate smart pointer type. The Active Template Library (ATL) defines several smart pointers for various purposes. You can also use the `_com_ptr_t` smart pointer type, which the compiler uses when it creates wrapper classes from .tlb files. It's the best choice when you don't want to include the ATL header files. + +- [CComPtr Class](../atl/reference/ccomptr-class.md) -[CComPtr Class](../atl/reference/ccomptr-class.md)
-Use this unless you cannot use ATL. Performs reference counting by using the `AddRef` and `Release` methods. For more information, see [How to: Create and Use CComPtr and CComQIPtr Instances](how-to-create-and-use-ccomptr-and-ccomqiptr-instances.md). + Use this class unless you can't use ATL. Performs reference counting by using the `AddRef` and `Release` methods. For more information, see [How to: Create and use CComPtr and CComQIPtr instances](how-to-create-and-use-ccomptr-and-ccomqiptr-instances.md). -[CComQIPtr Class](../atl/reference/ccomqiptr-class.md)
-Resembles `CComPtr` but also provides simplified syntax for calling `QueryInterface` on COM objects. For more information, see [How to: Create and Use CComPtr and CComQIPtr Instances](how-to-create-and-use-ccomptr-and-ccomqiptr-instances.md). +- [CComQIPtr Class](../atl/reference/ccomqiptr-class.md) -[CComHeapPtr Class](../atl/reference/ccomheapptr-class.md)
-Smart pointer to objects that use `CoTaskMemFree` to free memory. + Resembles `CComPtr` but also provides simplified syntax for calling `QueryInterface` on COM objects. For more information, see [How to: Create and use CComPtr and CComQIPtr instances](how-to-create-and-use-ccomptr-and-ccomqiptr-instances.md). -[CComGITPtr Class](../atl/reference/ccomgitptr-class.md)
-Smart pointer for interfaces that are obtained from the global interface table (GIT). +- [CComHeapPtr Class](../atl/reference/ccomheapptr-class.md) -[_com_ptr_t Class](com-ptr-t-class.md)
-Resembles `CComQIPtr` in functionality but does not depend on ATL headers. + Smart pointer to objects that use `CoTaskMemFree` to free memory. + +- [CComGITPtr Class](../atl/reference/ccomgitptr-class.md) + + Smart pointer for interfaces that are obtained from the global interface table (GIT). + +- [_com_ptr_t Class](com-ptr-t-class.md) + + Resembles `CComQIPtr` in functionality but doesn't depend on ATL headers. ### ATL smart pointers for POCO objects -In addition to smart pointers for COM objects, ATL also defines smart pointers, and collections of smart pointers, for plain old C++ objects (POCO). In classic Windows programming, these types are useful alternatives to the C++ Standard Library collections, especially when code portability is not required or when you do not want to mix the programming models of the C++ Standard Library and ATL. +In addition to smart pointers for COM objects, ATL also defines smart pointers, and collections of smart pointers, for plain old C++ objects (POCO). In classic Windows programming, these types are useful alternatives to the C++ Standard Library collections, especially when code portability isn't required or when you don't want to mix the programming models of the C++ Standard Library and ATL. + +- [CAutoPtr Class](../atl/reference/cautoptr-class.md) + + Smart pointer that enforces unique ownership by transferring ownership on copy. Comparable to the deprecated `std::auto_ptr` Class. + +- [CHeapPtr Class](../atl/reference/cheapptr-class.md) + + Smart pointer for objects that are allocated by using the C [malloc](../c-runtime-library/reference/malloc.md) function. + +- [CAutoVectorPtr Class](../atl/reference/cautovectorptr-class.md) -[CAutoPtr Class](../atl/reference/cautoptr-class.md)
-Smart pointer that enforces unique ownership by transferring ownership on copy. Comparable to the deprecated `std::auto_ptr` Class. + Smart pointer for arrays that are allocated by using `new[]`. -[CHeapPtr Class](../atl/reference/cheapptr-class.md)
-Smart pointer for objects that are allocated by using the C [malloc](../c-runtime-library/reference/malloc.md) function. +- [CAutoPtrArray Class](../atl/reference/cautoptrarray-class.md) -[CAutoVectorPtr Class](../atl/reference/cautovectorptr-class.md)
-Smart pointer for arrays that are allocated by using `new[]`. + Class that encapsulates an array of `CAutoPtr` elements. -[CAutoPtrArray Class](../atl/reference/cautoptrarray-class.md)
-Class that encapsulates an array of `CAutoPtr` elements. +- [CAutoPtrList Class](../atl/reference/cautoptrlist-class.md) -[CAutoPtrList Class](../atl/reference/cautoptrlist-class.md)
-Class that encapsulates methods for manipulating a list of `CAutoPtr` nodes. + Class that encapsulates methods for manipulating a list of `CAutoPtr` nodes. ## See also -[Pointers](pointers-cpp.md)
-[C++ Language Reference](../cpp/cpp-language-reference.md)
-[C++ Standard Library](../standard-library/cpp-standard-library-reference.md) +- [Pointers](pointers-cpp.md) +- [C++ Language Reference](../cpp/cpp-language-reference.md) +- [C++ Standard Library](../standard-library/cpp-standard-library-reference.md) diff --git a/docs/cpp/static-function-call-operator.md b/docs/cpp/static-function-call-operator.md new file mode 100644 index 00000000000..2d81842a941 --- /dev/null +++ b/docs/cpp/static-function-call-operator.md @@ -0,0 +1,90 @@ +--- +description: "Learn how to declare and use the static function call operator in C++." +title: "Static function call operator (C++23)" +ms.date: 08/26/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["static function call operator [C++]", "static operator() [C++]", "operator overloading [C++]"] +--- + +# Static function call operator (C++) + +In C++23, you can declare the function call operator, `operator()`, as a static member function. A static function call operator doesn't have an implicit object parameter. Use it when a callable type doesn't need to access instance data. + +Support for this feature was introduced in Visual Studio 2022 version 17.14 (MSVC 14.44). Use the `/std:c++latest` or `/std:c++23preview` compiler option. + +## Syntax + +```cpp +static return-type operator()(parameter-list); +``` + +You can also declare the function call operator generated for a lambda expression as static: + +```cpp +[](parameter-list) static { function-body } +[] static { function-body } +``` + +## Remarks + +A static function call operator doesn't have a `this` pointer. It can't be `virtual` or have a cv-qualifier (`const` or `volatile`) or ref-qualifier (`&`, `&&`). + +You can call a static function call operator by using an object of its class, which allows the object to work as a function object. You can also call it by using its qualified name. Taking its address produces a regular function pointer instead of a pointer-to-member function. + +A lambda expression can specify `static` after its parameter list. When the lambda has no parameters, you can omit the empty parameter list and specify `static` after the lambda introducer (`[]`). A static lambda can't have captures or be declared `mutable`. Declaring a captureless lambda doesn't make it static automatically; you must specify `static` to opt in to this behavior. + +The feature-test macro `__cpp_static_call_operator` is defined when the static function call operator is available. + +## Static function call operator example + +The following example defines a stateless function object and calls its static function call operator in three ways. It also defines a static lambda expression and calls it: + +```cpp +// Compile with: /std:c++latest + +#include + +struct Multiply +{ + static constexpr int operator()(int left, int right) noexcept + { + return left * right; + } +}; + +int main() +{ + Multiply multiply; + + std::cout << "multiply(6, 7) = " << multiply(6, 7) << std::endl; + std::cout << "Multiply::operator()(3, 4) = " + << Multiply::operator()(3, 4) << std::endl; + + auto multiply_function = &Multiply::operator(); + std::cout << "multiply_function(5, 5) = " + << multiply_function(5, 5) << std::endl; + + // A static lambda expression that doubles its argument + auto twice = [](int value) static noexcept + { + return value * 2; + }; + + std::cout << "twice(21) = " << twice(21) << std::endl; +} +``` + +```output +multiply(6, 7) = 42 +Multiply::operator()(3, 4) = 12 +multiply_function(5, 5) = 25 +twice(21) = 42 +``` + +## See also + +[Function call](function-call-cpp.md)\ +[Function-call operator](function-call-operator-parens.md)\ +[Operator overloading](operator-overloading.md)\ +[`static` members](static-members-cpp.md)\ +[Proposal P1169R4: static `operator()`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1169r4.html) \ No newline at end of file diff --git a/docs/cpp/static-subscript-operator.md b/docs/cpp/static-subscript-operator.md new file mode 100644 index 00000000000..2498d9490b6 --- /dev/null +++ b/docs/cpp/static-subscript-operator.md @@ -0,0 +1,76 @@ +--- +description: "Learn how to declare and use the static subscript operator in C++." +title: "Static subscript operator (C++)" +ms.date: 08/26/2026 +ai-usage: ai-assisted +helpviewer_keywords: ["static subscript operator [C++]", "static operator[] [C++]", "operator overloading [C++]"] +--- + +# Static subscript operator (C++) + +In C++23, you can declare the subscript operator, `operator[]`, as a static member function. A static subscript operator doesn't have an implicit object parameter. Use it when a subscript operation doesn't need to access instance data. + +Support for this feature was introduced in Visual Studio 2022 version 17.14 (MSVC 14.44). Use the `/std:c++latest` compiler option. + +## Syntax + +```cpp +static return-type operator[](parameter-list); +``` + +## Remarks + +A static subscript operator doesn't have a `this` pointer. It can't be `virtual` or have a cv-qualifier (`const` or `volatile`) or ref-qualifier (`&`, `&&`). + +You can call a static subscript operator through an object or by using its qualified name. Taking its address produces a regular function pointer instead of a pointer-to-member function. + +The feature-test macro `__cpp_multidimensional_subscript` has a value of at least `202211L` when the static subscript operator is available. Simply checking whether the macro is defined is insufficient because its earlier value of `202110L` covers multidimensional subscripting but not `static operator[]`: + +```cpp +#if defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202211L +// static subscript operator is available +#endif +``` + +## Static subscript operator example + +The following example defines a stateless type that calculates powers of two and calls its static subscript operator in three ways: + +```cpp +// Compile with: /std:c++latest + +#include + +struct PowersOfTwo +{ + static constexpr unsigned int operator[](unsigned int exponent) noexcept + { + return 1U << exponent; + } +}; + +int main() +{ + PowersOfTwo powers_of_two; + + std::cout << "powers_of_two[6] = " << powers_of_two[6] << std::endl; + std::cout << "PowersOfTwo::operator[](4) = " + << PowersOfTwo::operator[](4) << std::endl; + + auto power_function = &PowersOfTwo::operator[]; + std::cout << "power_function(5) = " << power_function(5) << std::endl; +} +``` + +```output +powers_of_two[6] = 64 +PowersOfTwo::operator[](4) = 16 +power_function(5) = 32 +``` + +## See also + +[Subscripting](subscripting.md)\ +[Operator overloading](operator-overloading.md)\ +[`static` members](static-members-cpp.md)\ +[Proposal P2589R1: static `operator[]`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2589r1.pdf) \ No newline at end of file diff --git a/docs/cpp/string-and-character-literals-cpp.md b/docs/cpp/string-and-character-literals-cpp.md index 643fd31daea..9917d28c495 100644 --- a/docs/cpp/string-and-character-literals-cpp.md +++ b/docs/cpp/string-and-character-literals-cpp.md @@ -1,10 +1,9 @@ --- title: "String and character literals (C++)" description: "How to declare and define string and character literals in C++." -ms.date: 08/27/2021 +ms.date: 07/01/2026 f1_keywords: ["R", "L", "u", "u8", "LR", "uR", "u8R"] helpviewer_keywords: ["literal strings [C++]", "string literals [C++]"] -ms.assetid: 61de8f6f-2714-4e7b-86b6-a3f885d3b9df --- # String and character literals (C++) @@ -59,64 +58,57 @@ int main() } ``` -String literals can have no prefix, or `u8`, `L`, `u`, and `U` prefixes to denote narrow character (single-byte or multi-byte), UTF-8, wide character (UCS-2 or UTF-16), UTF-16 and UTF-32 encodings, respectively. A raw string literal can have `R`, `u8R`, `LR`, `uR`, and `UR` prefixes for the raw version equivalents of these encodings. To create temporary or static `std::string` values, you can use string literals or raw string literals with an `s` suffix. For more information, see the [String literals](#string-literals) section below. For more information on the basic source character set, universal character names, and using characters from extended codepages in your source code, see [Character sets](../cpp/character-sets.md). +String literals can have no prefix, or `u8`, `L`, `u`, and `U` prefixes to denote narrow character (single-byte or multibyte), UTF-8, wide character (UCS-2 or UTF-16), UTF-16, and UTF-32 encodings, respectively. A raw string literal can have `R`, `u8R`, `LR`, `uR`, and `UR` prefixes for the raw version equivalents of these encodings. To create temporary or static `std::string` values, you can use string literals or raw string literals with an `s` suffix. For more information on the basic source character set, universal character names, and using characters from extended codepages in your source code, see [Character sets](../cpp/character-sets.md). ## Character literals A *character literal* is composed of a constant character. It's represented by the character surrounded by single quotation marks. There are five kinds of character literals: - Ordinary character literals of type **`char`**, for example `'a'` - - UTF-8 character literals of type **`char`** (**`char8_t`** in C++20), for example `u8'a'` - - Wide-character literals of type **`wchar_t`**, for example `L'a'` - - UTF-16 character literals of type **`char16_t`**, for example `u'a'` - - UTF-32 character literals of type **`char32_t`**, for example `U'a'` The character used for a character literal may be any character, except for the reserved characters backslash (**`\`**), single quotation mark (**`'`**), or newline. Reserved characters can be specified by using an escape sequence. Characters may be specified by using universal character names, as long as the type is large enough to hold the character. ### Encoding -Character literals are encoded differently based their prefix. - -- A character literal without a prefix is an ordinary character literal. The value of an ordinary character literal containing a single character, escape sequence, or universal character name that can be represented in the execution character set has a value equal to the numerical value of its encoding in the execution character set. An ordinary character literal that contains more than one character, escape sequence, or universal character name is a *multicharacter literal*. A multicharacter literal or an ordinary character literal that can't be represented in the execution character set has type **`int`**, and its value is implementation-defined. For MSVC, see the **Microsoft-specific** section below. - -- A character literal that begins with the `L` prefix is a wide-character literal. The value of a wide-character literal containing a single character, escape sequence, or universal character name has a value equal to the numerical value of its encoding in the execution wide-character set unless the character literal has no representation in the execution wide-character set, in which case the value is implementation-defined. The value of a wide-character literal containing multiple characters, escape sequences, or universal character names is implementation-defined. For MSVC, see the **Microsoft-specific** section below. +Character literals are encoded differently based on their prefix. +- A character literal without a prefix is an ordinary character literal. The value of an ordinary character literal containing a single character, escape sequence, or universal character name that the execution character set can represent has a value equal to the numerical value of its encoding in the execution character set. An ordinary character literal that contains more than one character, escape sequence, or universal character name is a *multicharacter literal*. If the character can't be represented in the execution character set, it's a *non-encodable character literal*. A multicharacter literal and a non-encodable character literal have type **`int`**, and their value is implementation-defined. For MSVC, see the **Microsoft-specific** section below. The execution character set is defined at compile time and defaults to the codepage of the host machine. You can set the execution charset by using the [`/execution-charset`](../build/reference/execution-charset-set-execution-character-set.md) switch. +- A character literal that begins with the `L` prefix is a wide-character literal. The value of a wide-character literal containing a single character, escape sequence, or universal character name has a value equal to the numerical value of its encoding in what the standard calls the *execution wide-character set*, which on Windows is defined as UTF-16. If the character has no representation in the execution wide-character set, it's an error. - A character literal that begins with the `u8` prefix is a UTF-8 character literal. The value of a UTF-8 character literal containing a single character, escape sequence, or universal character name has a value equal to its ISO 10646 code point value if it can be represented by a single UTF-8 code unit (corresponding to the C0 Controls and Basic Latin Unicode block). If the value can't be represented by a single UTF-8 code unit, the program is ill-formed. A UTF-8 character literal containing more than one character, escape sequence, or universal character name is ill-formed. - - A character literal that begins with the `u` prefix is a UTF-16 character literal. The value of a UTF-16 character literal containing a single character, escape sequence, or universal character name has a value equal to its ISO 10646 code point value if it can be represented by a single UTF-16 code unit (corresponding to the basic multi-lingual plane). If the value can't be represented by a single UTF-16 code unit, the program is ill-formed. A UTF-16 character literal containing more than one character, escape sequence, or universal character name is ill-formed. - - A character literal that begins with the `U` prefix is a UTF-32 character literal. The value of a UTF-32 character literal containing a single character, escape sequence, or universal character name has a value equal to its ISO 10646 code point value. A UTF-32 character literal containing more than one character, escape sequence, or universal character name is ill-formed. -### Escape sequences - -There are three kinds of escape sequences: simple, octal, and hexadecimal. Escape sequences may be any of the following values: - -|Value|Escape sequence| -|-----------|---------------------| -| newline | \\n | -| backslash | \\\\ | -| horizontal tab | \\t | -| question mark | ? or \\? | -| vertical tab | \\v | -| single quote | \\' | -| backspace | \\b | -| double quote | \\" | -| carriage return | \\r | -| the null character | \\0 | -| form feed | \\f | -| octal | \\ooo | -| alert (bell) | \\a | -| hexadecimal | \\xhhh | - -An octal escape sequence is a backslash followed by a sequence of one to three octal digits. An octal escape sequence terminates at the first character that's not an octal digit, if encountered sooner than the third digit. The highest possible octal value is `\377`. - -A hexadecimal escape sequence is a backslash followed by the character `x`, followed by a sequence of one or more hexadecimal digits. Leading zeroes are ignored. In an ordinary or u8-prefixed character literal, the highest hexadecimal value is 0xFF. In an L-prefixed or u-prefixed wide character literal, the highest hexadecimal value is 0xFFFF. In a U-prefixed wide character literal, the highest hexadecimal value is 0xFFFFFFFF. - -This sample code shows some examples of escaped characters using ordinary character literals. The same escape sequence syntax is valid for the other character literal types. +### Escape sequences + +There are three kinds of escape sequences: simple, numeric, and universal. Escape sequences can be any of the following values: + +| Value | Escape sequence | +| --- | --- | +| newline | `\n` | +| backslash | `\\` | +| horizontal tab | `\t` | +| question mark | `?` or `\?` | +| vertical tab | `\v` | +| single quote | `\'` | +| backspace | `\b` | +| double quote | `\"` | +| carriage return | `\r` | +| form feed | `\f` | +| alert (bell) | `\a` | +| the null character | `\0` | +| octal | `\ooo` | +| delimited octal (C++23) | `\o{OOO}` | +| hexadecimal | `\xhhh` | +| delimited hexadecimal (C++23) | `\x{hhhh}` | +| universal character | `\uHHHH` or `\UHHHHHHHH` | +| delimited universal (C++23) | `\u{HHHH}` | +| named universal (C++23) | `\N{UNIVERSAL CHARACTER NAME}` | + +This sample code shows examples of simple escape sequences using ordinary character literals. The same escape sequence syntax is valid for the other character literal types. ```cpp #include @@ -141,129 +133,164 @@ ending Tab character: ending Backspace character:ending Backslash character: \ending -Null character: ending +Null character: ending */ ``` The backslash character (**`\`**) is a line-continuation character when it's placed at the end of a line. If you want a backslash character to appear as a character literal, you must type two backslashes in a row (**`\\`**). For more information about the line continuation character, see [Phases of Translation](../preprocessor/phases-of-translation.md). -#### Microsoft-specific +Numeric escape sequences include octal and hexadecimal escape sequences. These sequences result in a numeric value when the compiler evaluates them. + +An octal escape sequence is a backslash followed by a sequence of one to three octal digits. An octal escape sequence terminates at the first character that's not an octal digit, if encountered sooner than the third digit. The highest possible octal value is `\377`. C++23 added delimited octal sequences which consist of a backslash followed by the characters `o{`, followed by a sequence of octal characters, and then a matching `}`. The highest possible value in a delimited octal sequence is determined by the type of the character literal it is part of. -To create a value from a narrow multicharacter literal, the compiler converts the character or character sequence between single quotes into 8-bit values within a 32-bit integer. Multiple characters in the literal fill corresponding bytes as needed from high-order to low-order. The compiler then converts the integer to the destination type following the usual rules. For example, to create a **`char`** value, the compiler takes the low-order byte. To create a **`wchar_t`** or **`char16_t`** value, the compiler takes the low-order word. The compiler warns that the result is truncated if any bits are set above the assigned byte or word. +A common mistake when using octal escape sequences is expecting the sequence to allow more than three octal digits, or to terminate the sequence early with a non-octal digit. When you make this mistake in what would otherwise be an ordinary character literal, it turns the literal into a multicharacter literal. ```cpp -char c0 = 'abcd'; // C4305, C4309, truncates to 'd' -wchar_t w0 = 'abcd'; // C4305, C4309, truncates to '\x6364' -int i0 = 'abcd'; // 0x61626364 +char c1 = '\100'; // Okay, '@' +char c2 = '\1000'; // multicharacter literal, truncates to '0' +char c3 = '\009'; // multicharacter literal, truncates to '9' ``` - -An octal escape sequence that appears to contain more than three digits is treated as a 3-digit octal sequence, followed by the subsequent digits as characters in a multicharacter literal, which can give surprising results. For example: - +You can avoid this mistake by using delimited octal sequences. ```cpp -char c1 = '\100'; // '@' -char c2 = '\1000'; // C4305, C4309, truncates to '0' +char c1 = '\o{100}'; // Okay, '@' +char c2 = '\o{1000}'; // error, value is out of range for char +char c3 = '\o{009}'; // error, non-octal value inside octal sequence. ``` -Escape sequences that appear to contain non-octal characters are evaluated as an octal sequence up to the last octal character, followed by the remaining characters as the subsequent characters in a multicharacter literal. Warning C4125 is generated if the first non-octal character is a decimal digit. For example: +A hexadecimal escape sequence is a backslash followed by the character `x`, followed by a sequence of one or more hexadecimal digits. Leading zeroes are ignored. C++23 added delimited hexadecimal sequences, which consist of a backslash, followed by the characters `x{`, followed by a sequence of hexadecimal characters, and then a matching `}`. In an ordinary or `u8`-prefixed character literal, the highest hexadecimal value is `0xFF`. In an `L`-prefixed or `u`-prefixed character literal, the highest hexadecimal value is `0xFFFF`. In a `U`-prefixed character literal, the highest hexadecimal value is `0xFFFFFFFF`. + +### Universal character names + +In character literals and native (non-raw) string literals, use a universal character name to represent any character. Universal character names use the prefix `\U` followed by an eight-digit Unicode code point, or the prefix `\u` followed by a four-digit Unicode code point. You must include all eight or four digits to create a well-formed universal character name. +C++23 introduced delimited universal characters and named universal characters. A delimited universal character consists of the prefix `\u{`, followed by a series of hexadecimal characters, followed by `}`. A named universal character consists of the prefix `\N{`, followed by a universal character name, followed by `}`. The case-sensitive universal character name must match a name from the Unicode character database from the Unicode Consortium. The compiler uses the version of Unicode installed on your system to determine the value of the character. ```cpp -char c3 = '\009'; // '9' -char c4 = '\089'; // C4305, C4309, truncates to '9' -char c5 = '\qrs'; // C4129, C4305, C4309, truncates to 's' +char u1 = 'A'; // 'A' +char u2 = '\101'; // octal, 'A' +char u3 = '\x41'; // hexadecimal, 'A' +char u4 = '\u0041'; // UCN 'A' +char u5 = '\U00000041'; // UCN 'A' +char u6 = '\u{41}'; // UCN 'A' +char u7 = '\N{LATIN CAPITAL LETTER A}'; // UCN 'A' ``` -An octal escape sequence that has a higher value than `\377` causes error C2022: '*value-in-decimal*': too big for character. +### Multicharacter and non-encodable character literals + +A *multicharacter literal* is an ordinary character literal with multiple characters and no prefix. `'AB'` is an example of a multicharacter literal. + +A *non-encodable character literal* is a character literal with no prefix that contains a character that isn't encodable as a single `char` value. An example is the Unicode character U+1F609 `'😉'`, because it takes four bytes to represent in UTF-8 so it can't be encoded in a single 8-bit `char` value. + +The compiler treats multicharacter and non-encodable character literals similarly. Their type is `int` and their value at runtime is implementation defined. See the Microsoft-specific section below for details. You can avoid implementation defined behavior by using a character prefix such as `U'😉'`. + +#### Microsoft-specific -An escape sequence that appears to have hexadecimal and non-hexadecimal characters is evaluated as a multicharacter literal that contains a hexadecimal escape sequence up to the last hexadecimal character, followed by the non-hexadecimal characters. A hexadecimal escape sequence that contains no hexadecimal digits causes compiler error C2153: "hex literals must have at least one hex digit". +The maximum sequence of characters in a multicharacter literal is four because the value maps to a 32-bit integer value. When there are fewer than four characters, the compiler pads the high-order bits with 0. ```cpp -char c6 = '\x0050'; // 'P' -char c7 = '\x0pqr'; // C4305, C4309, truncates to 'r' +int c1 = 'a'; // 0x00000061 (not a multicharacter literal) +int c2 = 'ab'; // 0x00006162 +int c3 = 'abc'; // 0x00616263 +int c4 = 'abcd';// 0x61626364 ``` -If a wide character literal prefixed with `L` contains a multicharacter sequence, the value is taken from the first character, and the compiler raises warning C4066. Subsequent characters are ignored, unlike the behavior of the equivalent ordinary multicharacter literal. +The mapping of ordinary characters into an integer guarantees the value of the resulting integer is independent of the endianness of the target machine. As a result, on little endian machines, the order of the individual character values in memory is flipped and doesn't match the equivalent string value. ```cpp -wchar_t w1 = L'\100'; // L'@' -wchar_t w2 = L'\1000'; // C4066 L'@', 0 ignored -wchar_t w3 = L'\009'; // C4066 L'\0', 9 ignored -wchar_t w4 = L'\089'; // C4066 L'\0', 89 ignored -wchar_t w5 = L'\qrs'; // C4129, C4066 L'q' escape, rs ignored -wchar_t w6 = L'\x0050'; // L'P' -wchar_t w7 = L'\x0pqr'; // C4066 L'\0', pqr ignored +int ch = 'abcd'; // 'd' is first in memory on little endian machines +const char* str = "abcd"; +// compare the first byte of str with the last byte of ch +if(str[0] == reinterpret_cast(&ch)[3]) +{ + printf("little-endian\n"); +} ``` +Integer escape sequences used in multicharacter literals must fit into an 8-bit `char` value. Unlike ordinary character sequences, the escaped values inside a multicharacter literal are encoded according to the endianness of the target machine. This means the resulting value of the sequence is flipped in little endian machines. The compiler pads the high-order bits with 0. +```cpp +int ch1 = '\x61'; // 0x00000061 (not a multicharacter literal) +int ch2 = '\x61\x62'; // 0x00006261 +int ch3 = '\x61\x62\x63'; // 0x00636261 +int ch4 = '\x61\x62\x63\x64';// 0x64636261 +``` +Don't mix ordinary and integer escape sequences in a single multicharacter literal. Their encoding rules are different based on the endianness of the machine so the result is not defined. -The **Microsoft-specific** section ends here. +The range of values that qualify as a non-encodable character literal depend on the current execution character set. The Japanese half width kanji `ツ` (U+FF82) is a non-encodable character under `/execution-charset:utf-8` because it takes three bytes to represent. The same character is considered an ordinary character literal under `/execution-charset:shift_jis` because it can be represented in a single byte. -### Universal character names +The compiler computes the integer value by first converting the character into the multibyte execution character set representation, then maps the sequence of bytes to the integer. The compiler pads the high-order bytes with 0. -In character literals and native (non-raw) string literals, any character may be represented by a universal character name. Universal character names are formed by a prefix `\U` followed by an eight-digit Unicode code point, or by a prefix `\u` followed by a four-digit Unicode code point. All eight or four digits, respectively, must be present to make a well-formed universal character name. +Use the Japanese full width kanji `ツ` (U+30C4) as an example. `ツ` is represented in UTF-8 as the three-byte sequence `0xe3 0x83 0x84` and in shift_jis as the two-byte sequence `0x83 0x63`. ```cpp -char u1 = 'A'; // 'A' -char u2 = '\101'; // octal, 'A' -char u3 = '\x41'; // hexadecimal, 'A' -char u4 = '\u0041'; // \u UCN 'A' -char u5 = '\U00000041'; // \U UCN 'A' +int tsu = 'ツ'; // non-encodable character literal +if (tsu == 0xe38384) +{ + printf("detected /execution-charset:utf-8"); +} +else if (tsu == 0x8363) +{ + printf("detected /execution-charset:shift_jis"); +} ``` +To avoid implementation defined behavior and get the Unicode value of a character that isn't affected by the execution character set, use a character prefix such as `U'ツ'`. -#### Surrogate Pairs - -Universal character names can't encode values in the surrogate code point range D800-DFFF. For Unicode surrogate pairs, specify the universal character name by using `\UNNNNNNNN`, where NNNNNNNN is the eight-digit code point for the character. The compiler generates a surrogate pair if necessary. - -In C++03, the language only allowed a subset of characters to be represented by their universal character names, and allowed some universal character names that didn't actually represent any valid Unicode characters. This mistake was fixed in the C++11 standard. In C++11, both character and string literals and identifiers can use universal character names. For more information on universal character names, see [Character Sets](../cpp/character-sets.md). For more information about Unicode, see [Unicode](/windows/win32/intl/unicode). For more information about surrogate pairs, see [Surrogate Pairs and Supplementary Characters](/windows/win32/Intl/surrogates-and-supplementary-characters). +The **Microsoft-specific** section ends here. -## String literals +## String literals A string literal represents a sequence of characters that together form a null-terminated string. The characters must be enclosed between double quotation marks. There are the following kinds of string literals: -### Narrow string literals +### Ordinary string literals -A narrow string literal is a non-prefixed, double-quote delimited, null-terminated array of type `const char[n]`, where n is the length of the array in bytes. A narrow string literal may contain any graphic character except the double quotation mark (`"`), backslash (`\`), or newline character. A narrow string literal may also contain the escape sequences listed above, and universal character names that fit in a byte. +An ordinary string literal is a non-prefixed, double-quote delimited, null-terminated array of type `const char[n]`, where *n* is the length of the array in bytes. An ordinary string literal can contain any graphic character except the double quotation mark (`"`), backslash (`\`), or newline character. An ordinary string literal can also contain escape sequences. The encoding of universal character names in ordinary string literals depends on the execution character set. ```cpp -const char *narrow = "abcd"; +const char *ordinary = "abcd"; // represents the string: yes\no const char *escaped = "yes\\no"; ``` -#### UTF-8 encoded strings +### UTF-8 string literal -A UTF-8 encoded string is a u8-prefixed, double-quote delimited, null-terminated array of type `const char[n]`, where *n* is the length of the encoded array in bytes. A u8-prefixed string literal may contain any graphic character except the double quotation mark (`"`), backslash (`\`), or newline character. A u8-prefixed string literal may also contain the escape sequences listed above, and any universal character name. +A UTF-8 encoded string is a `u8`-prefixed, double-quote delimited, null-terminated array of type `const char[n]`, where *n* is the length of the encoded array in bytes. A `u8`-prefixed string literal can contain any graphic character except the double quotation mark (`"`), backslash (`\`), or newline character. A `u8`-prefixed string literal can also contain escape sequences. C++20 introduces the portable **`char8_t`** (UTF-8 encoded 8-bit Unicode) character type. In C++20, `u8` literal prefixes specify characters or strings of **`char8_t`** instead of **`char`**. ```cpp // Before C++20 const char* str1 = u8"Hello World"; -const char* str2 = u8"\U0001F607 is O:-)"; +const char* str2 = u8"\U0001F607 is 😇"; // C++20 and later const char8_t* u8str1 = u8"Hello World"; -const char8_t* u8str2 = u8"\U0001F607 is O:-)"; +const char8_t* u8str2 = u8"\U0001F607 is 😇"; ``` ### Wide string literals -A wide string literal is a null-terminated array of constant **`wchar_t`** that is prefixed by '`L`' and contains any graphic character except the double quotation mark (**`"`**), backslash (**`\`**), or newline character. A wide string literal may contain the escape sequences listed above and any universal character name. +A wide string literal is a null-terminated array of constant **`wchar_t`** that's prefixed by '`L`' and contains any graphic character except the double quotation mark (**`"`**), backslash (**`\`**), or newline character. A wide string literal can also contain escape sequences. ```cpp const wchar_t* wide = L"zyxw"; const wchar_t* newline = L"hello\ngoodbye"; ``` -#### char16_t and char32_t (C++11) +### UTF-16 string literals + +A UTF-16 string literal is a null-terminated array of constant **`char16_t`** that's prefixed by '`u`' and contains any graphic character except the double quotation mark (**`"`**), backslash (**`\`**), or newline character. A UTF-16 string literal can also contain escape sequences. + +```cpp +const char16_t* utf_16 = u"hello 🌍"; +``` +### UTF-32 string literals -C++11 introduces the portable **`char16_t`** (16-bit Unicode) and **`char32_t`** (32-bit Unicode) character types: +A UTF-32 string literal is a null-terminated array of constant **`char32_t`** that's prefixed by '`U`' and contains any graphic character except the double quotation mark (**`"`**), backslash (**`\`**), or newline character. A UTF-32 string literal can also contain escape sequences. ```cpp -auto s3 = u"hello"; // const char16_t* -auto s4 = U"hello"; // const char32_t* +const char32_t* utf_32 = U"hello 🌏"; ``` ### Raw string literals (C++11) -A raw string literal is a null-terminated array—of any character type—that contains any graphic character, including the double quotation mark (**`"`**), backslash (**`\`**), or newline character. Raw string literals are often used in regular expressions that use character classes, and in HTML strings and XML strings. For examples, see the following article: [Bjarne Stroustrup's FAQ on C++11](https://www.stroustrup.com/C++11FAQ.html). +A raw string literal is a null-terminated array, of any character type, that contains any graphic character, including the double quotation mark (**`"`**), backslash (**`\`**), or newline character. Use raw string literals for regular expressions that use character classes, and in HTML strings and XML strings. ```cpp // represents the string: An unescaped \ character @@ -275,7 +302,7 @@ const char16_t* raw_utf16 = uR"(An unescaped \ character)"; const char32_t* raw_utf32 = UR"(An unescaped \ character)"; ``` -A delimiter is a user-defined sequence of up to 16 characters that immediately precedes the opening parenthesis of a raw string literal, and immediately follows its closing parenthesis. For example, in `R"abc(Hello"\()abc"` the delimiter sequence is `abc` and the string content is `Hello"\(`. You can use a delimiter to disambiguate raw strings that contain both double quotation marks and parentheses. This string literal causes a compiler error: +A delimiter is a user-defined sequence of up to 16 characters that immediately precedes the opening parenthesis of a raw string literal, and immediately follows its closing parenthesis. For example, in `R"abc(Hello"\()abc"` the delimiter sequence is `abc` and the string content is `Hello"\(`. Use a delimiter to disambiguate raw strings that contain both double quotation marks and parentheses. This string literal causes a compiler error: ```cpp // meant to represent the string: )" @@ -299,7 +326,7 @@ goodbye)"; ### std::string literals (C++14) -`std::string` literals are Standard Library implementations of user-defined literals (see below) that are represented as `"xyz"s` (with a `s` suffix). This kind of string literal produces a temporary object of type `std::string`, `std::wstring`, `std::u32string`, or `std::u16string`, depending on the prefix that is specified. When no prefix is used, as above, a `std::string` is produced. `L"xyz"s` produces a `std::wstring`. `u"xyz"s` produces a [std::u16string](../standard-library/string-typedefs.md#u16string), and `U"xyz"s` produces a [std::u32string](../standard-library/string-typedefs.md#u32string). +`std::string` literals are Standard Library implementations of user-defined literals (see below) that are represented as `"xyz"s` (with a `s` suffix). This kind of string literal produces a temporary object of type `std::string`, `std::wstring`, `std::u32string`, or `std::u16string`, depending on the prefix that you specify. When you don't use a prefix, as in the preceding example, the literal produces a `std::string`. `L"xyz"s` produces a `std::wstring`. `u"xyz"s` produces a [std::u16string](../standard-library/string-typedefs.md#u16string), and `U"xyz"s` produces a [std::u32string](../standard-library/string-typedefs.md#u32string). ```cpp //#include @@ -318,11 +345,11 @@ The `s` suffix may also be used on raw string literals: u32string str6{ UR"(She said "hello.")"s }; ``` -`std::string` literals are defined in the namespace `std::literals::string_literals` in the \ header file. Because `std::literals::string_literals`, and `std::literals` are both declared as [inline namespaces](../cpp/namespaces-cpp.md), `std::literals::string_literals` is automatically treated as if it belonged directly in namespace `std`. +`std::string` literals are defined in the namespace `std::literals::string_literals` in the `` header file. Because `std::literals::string_literals` and `std::literals` are both declared as [inline namespaces](../cpp/namespaces-cpp.md), the compiler automatically treats `std::literals::string_literals` as if it belonged directly in namespace `std`. ### Size of string literals -For ANSI `char*` strings and other single-byte encodings (but not UTF-8), the size (in bytes) of a string literal is the number of characters plus 1 for the terminating null character. For all other string types, the size isn't strictly related to the number of characters. UTF-8 uses up to four **`char`** elements to encode some *code units*, and **`char16_t`** or **`wchar_t`** encoded as UTF-16 may use two elements (for a total of four bytes) to encode a single *code unit*. This example shows the size of a wide string literal in bytes: +For ASCII `char*` strings and other single-byte encodings, the size (in bytes) of a string literal is the number of characters plus 1 for the terminating null character. For all other string literals, the size isn't strictly related to the number of characters. UTF-8 uses up to four **`char`** elements to encode some *code units*, and **`char16_t`** or **`wchar_t`** encoded as UTF-16 may use two elements (for a total of four bytes) to encode a single *code unit*. This example shows the size of a wide string literal in bytes: ```cpp const wchar_t* str = L"Hello!"; @@ -333,8 +360,9 @@ Notice that `strlen()` and `wcslen()` don't include the size of the terminating Maximum length of a string literal after concatenation: -* Visual Studio prior to 2022 version 17.0: the maximum length of a string literal after concatenation is 65,535 bytes. This applies to both narrow and wide string literals. -* From Visual Studio 2022 version 17.0 onwards: the maximum length of a string literal after concatenation is only limited by available memory. However, the size limit before concatenation is still 16,384 bytes +- Visual Studio before 2022 version 17.0: the maximum length of a string literal after concatenation is 65,535 bytes. This applies to both narrow and wide string literals. +- Before MSVC 14.51: the maximum length of a string literal after concatenation is only limited by available memory. However, the size limit before concatenation is still 16,384 bytes. +- From MSVC 14.51 onwards: the maximum length limitation for a string literal before concatenation is removed and is only limited by available memory. ### Modifying string literals @@ -353,7 +381,7 @@ You can cause the compiler to emit an error when a string literal is converted t ```cpp auto str = L"hello"; -str[2] = L'a'; // C3892: you cannot assign to a variable that is const. +str[2] = L'a'; // C3892: you cannot assign to a variable that's const. ``` In some cases, identical string literals may be pooled to save space in the executable file. In string-literal pooling, the compiler causes all references to a particular string literal to point to the same location in memory, instead of having each reference point to a separate instance of the string literal. To enable string pooling, use the [`/GF`](../build/reference/gf-eliminate-duplicate-strings.md) compiler option. @@ -374,7 +402,7 @@ is identical to this declaration: char atr[] = "1234"; ``` -and to this declaration: +and is identical to this declaration: ```cpp char atr[] = "12\ @@ -392,40 +420,52 @@ The actual result is a hexadecimal 5F, which is the ASCII code for an underscore ```cpp "\005five" // Use octal literal. "\x05" "five" // Use string splicing. +"\x{05}five" // (C++23) delimited escape sequence ``` - -`std::string` literals (and the related `std::u8string`, `std::u16string`, and `std::u32string`) can be concatenated with the **`+`** operator that's defined for [`basic_string`](../standard-library/basic-string-class.md) types. They can also be concatenated in the same way as adjacent string literals. In both cases, the string encoding and the suffix must match: +Concatenate `std::string` literals (and the related `std::u8string`, `std::u16string`, and `std::u32string`) at runtime using the **`+`** operator that's defined for [`basic_string`](../standard-library/basic-string-class.md) types. You can also concatenate them at compile time in the same way as adjacent string literals. In both cases, the string encoding and the suffix of each literal must not conflict: ```cpp -auto x1 = "hello" " " " world"; // OK +auto x1 = "hello" " " " world"s; // OK, results in std::string "hello world"s auto x2 = U"hello" " " L"world"; // C2308: disagree on prefix auto x3 = u8"hello" " "s u8"world"z; // C3688, disagree on suffixes ``` ### String literals with universal character names -Native (non-raw) string literals may use universal character names to represent any character, as long as the universal character name can be encoded as one or more characters in the string type. For example, a universal character name representing an extended character can't be encoded in a narrow string using the ANSI code page, but it can be encoded in narrow strings in some multi-byte code pages, or in UTF-8 strings, or in a wide string. In C++11, Unicode support is extended by the `char16_t*` and `char32_t*` string types, and C++20 extends it to the `char8_t` type: +Native (non-raw) string literals can use universal character names to represent any character, as long as the universal character name can be encoded as one or more characters in the string type. For example, a universal character name representing an extended character can't be encoded in an ordinary string when using the ANSI code page, but it can be encoded in narrow strings in some multibyte code pages, or in UTF-8 strings, or in a wide string. In C++11, Unicode support is extended by the `char16_t*` and `char32_t*` string types, and C++20 extends it to the `char8_t` type: ```cpp // ASCII smiling face const char* s1 = ":-)"; // UTF-16 (on Windows) encoded WINKING FACE (U+1F609) -const wchar_t* s2 = L"😉 = \U0001F609 is ;-)"; +const wchar_t* s2 = L"😉 = \U0001F609"; // UTF-8 encoded SMILING FACE WITH HALO (U+1F607) -const char* s3a = u8"😇 = \U0001F607 is O:-)"; // Before C++20 -const char8_t* s3b = u8"😇 = \U0001F607 is O:-)"; // C++20 +const char* s3a = u8"😇 = \U0001F607"; // Before C++20 +const char8_t* s3b = u8"😇 = \U0001F607"; // C++20 // UTF-16 encoded SMILING FACE WITH OPEN MOUTH (U+1F603) -const char16_t* s4 = u"😃 = \U0001F603 is :-D"; +const char16_t* s4 = u"😃 = \U0001F603"; // UTF-32 encoded SMILING FACE WITH SUNGLASSES (U+1F60E) -const char32_t* s5 = U"😎 = \U0001F60E is B-)"; +const char32_t* s5 = U"😎 = \U0001F60E"; ``` +In C++11 and later, Universal characters can be any *Unicode scalar value* when used in a string literal. Unicode scalar values include the full Unicode codespace from U+0000 to U+10FFFF other than the surrogate code point range (U+D800 through U+DFFF). Before C++11, Universal characters can be any value in the Unicode codespace, except those in the basic source character set and control characters (ranges U+0000 to U+0001F and U+007F to 0x9F). For more information on universal character names, see [Character Sets](../cpp/character-sets.md). For more information about Unicode, see [Unicode](/windows/win32/intl/unicode). + +When used inside an ordinary string literal `""`, the Unicode code point is encoded in the codepage of the execution character set. The codepage controls the value as well as the number of bytes used to represent the code point. If the Unicode code point can't be represented in the execution character set codepage, then a warning is emitted and the character is replaced by the default replacement character for the codepage. The default replacement character is defined by the codepage and is typically a character equivelent to U+FFFD (�) or '?'. The execution character set can be set by the compiler switch [`/execution-charset`](../build/reference/execution-charset-set-execution-character-set.md). + +When used in a utf-8 literal type `u8""`, the Unicode code point is encoded in a possibly multibyte utf-8 sequence. + +When used in a 16-bit string literal type `L""` or `u""`, the Unicode code point is encoded in UTF-16. A universal characters that does not fit in 16-bits is automatically encoded as a UTF-16 surrogate pair. For more information about surrogate pairs, see [Surrogate Pairs and Supplementary Characters](/windows/win32/Intl/surrogates-and-supplementary-characters) + +When used in a UTF-32 literal type `U""`, the Unicode code point is encoded in UTF-32. + ## See also [Character sets](../cpp/character-sets.md)\ [Numeric, Boolean, and pointer literals](../cpp/numeric-boolean-and-pointer-literals-cpp.md)\ +[Surrogate Pairs and Supplementary Characters](/windows/win32/Intl/surrogates-and-supplementary-characters)\ +[Unicode](/windows/win32/intl/unicode)\ [User-defined literals](../cpp/user-defined-literals-cpp.md) diff --git a/docs/cpp/subscripting.md b/docs/cpp/subscripting.md index 62fc228c211..bb36ccb61a5 100644 --- a/docs/cpp/subscripting.md +++ b/docs/cpp/subscripting.md @@ -7,7 +7,9 @@ ms.assetid: eb151281-6733-401d-9787-39ab6754c62c --- # Subscripting -The subscript operator (**[ ]**), like the function-call operator, is considered a binary operator. The subscript operator must be a nonstatic member function that takes a single argument. This argument can be of any type and designates the desired array subscript. +The built-in subscript operator (**[ ]**) is a binary operator. Before C++23, you had to overload the subscript operator (`operator[]`) by using a nonstatic subscript operator member function. In C++23 and later, you can also overload it by using a static subscript operator member function. For more information, see [Static subscript operator](static-subscript-operator.md). + +The argument can be any type and designates the desired array subscript. ## Example @@ -86,4 +88,5 @@ Note that the function **operator[]** returns a reference type. This causes it t ## See also +[Static subscript operator](static-subscript-operator.md)\ [Operator Overloading](../cpp/operator-overloading.md) diff --git a/docs/cpp/toc.yml b/docs/cpp/toc.yml index 1f17ade4e51..111d9c465ec 100644 --- a/docs/cpp/toc.yml +++ b/docs/cpp/toc.yml @@ -336,8 +336,12 @@ items: href: ../cpp/assignment.md - name: Function call href: ../cpp/function-call-cpp.md + - name: Static function call operator + href: ../cpp/static-function-call-operator.md - name: Subscripting href: ../cpp/subscripting.md + - name: Static subscript operator + href: ../cpp/static-subscript-operator.md - name: Member access href: ../cpp/member-access.md - name: Classes and structs diff --git a/docs/cpp/welcome-back-to-cpp-modern-cpp.md b/docs/cpp/welcome-back-to-cpp-modern-cpp.md index dad330d014a..b619c962491 100644 --- a/docs/cpp/welcome-back-to-cpp-modern-cpp.md +++ b/docs/cpp/welcome-back-to-cpp-modern-cpp.md @@ -1,22 +1,35 @@ --- -title: "Welcome back to C++ - Modern C++" -description: "Describes the new programming idioms in Modern C++ and their rationale." -ms.date: 06/02/2022 +title: "Welcome Back to C++ - Modern C++" +description: "Learn about the new programming idioms in modern C++ and their rationale. Understand some of the advantages of modern C++." +ms.date: 05/28/2026 ms.topic: "concept-article" +#customer intent: As a developer, I want to understand advantages of modern C++ and how modern C++ differs from previous versions of the language. --- # Welcome back to C++ - Modern C++ -Since its creation, C++ has become one of the most widely used programming languages in the world. Well-written C++ programs are fast and efficient. The language is more flexible than other languages: It can work at the highest levels of abstraction, and down at the level of the silicon. C++ supplies highly optimized standard libraries. It enables access to low-level hardware features, to maximize speed and minimize memory requirements. C++ can create almost any kind of program: Games, device drivers, HPC, cloud, desktop, embedded, and mobile apps, and much more. Even libraries and compilers for other programming languages get written in C++. +Since its creation, C++ has become one of the most widely used programming languages in the world. Well-written C++ programs are fast and efficient. The language is more flexible than other languages: It can work at the highest levels of abstraction, and down at the level of the silicon. -One of the original requirements for C++ was backward compatibility with the C language. As a result, C++ has always permitted C-style programming, with raw pointers, arrays, null-terminated character strings, and other features. They may enable great performance, but can also spawn bugs and complexity. The evolution of C++ has emphasized features that greatly reduce the need to use C-style idioms. The old C-programming facilities are still there when you need them. However, in modern C++ code you should need them less and less. Modern C++ code is simpler, safer, more elegant, and still as fast as ever. +C++ supplies highly optimized standard libraries. It enables access to low-level hardware features, to maximize speed and minimize memory requirements. C++ can create almost any kind of program: Games, device drivers, High-Performance Computing, cloud, desktop, embedded, and mobile apps, and much more. Even libraries and compilers for other programming languages are written in C++. + +One of the original requirements for C++ was backward compatibility with the C language. As a result, C++ permits C-style programming, with raw pointers, arrays, null-terminated character strings, and other features. They can enable great performance, but can also spawn bugs and complexity. + +The evolution of C++ emphasizes features that greatly reduce the need to use C-style idioms. The old C-programming facilities are still there when you need them. However, in modern C++ code you should need them less and less. Modern C++ code is simpler, safer, more elegant, and still as fast as ever. The following sections provide an overview of the main features of modern C++. Unless noted otherwise, the features listed here are available in C++11 and later. In the Microsoft C++ compiler, you can set the [`/std`](../build/reference/std-specify-language-standard-version.md) compiler option to specify which version of the standard to use for your project. ## Resources and smart pointers -One of the major classes of bugs in C-style programming is the *memory leak*. Leaks are often caused by a failure to call **`delete`** for memory that was allocated with **`new`**. Modern C++ emphasizes the principle of *resource acquisition is initialization* (RAII). The idea is simple. Resources (heap memory, file handles, sockets, and so on) should be *owned* by an object. That object creates, or receives, the newly allocated resource in its constructor, and deletes it in its destructor. The principle of RAII guarantees that all resources get properly returned to the operating system when the owning object goes out of scope. +One of the major classes of bugs in C-style programming is the *memory leak*. Leaks are often caused by a failure to call `delete` for memory that was allocated with `new`. Modern C++ emphasizes the principle of *resource acquisition is initialization* (RAII). + +The idea is simple. Resources, such as heap memory, file handles, and sockets, should be *owned* by an object. That object creates, or receives, the newly allocated resource in its constructor, and deletes it in its destructor. The principle of RAII guarantees that all resources get properly returned to the operating system when the owning object goes out of scope. + +To support easy adoption of RAII principles, the C++ Standard Library provides three smart pointer types: -To support easy adoption of RAII principles, the C++ Standard Library provides three smart pointer types: [`std::unique_ptr`](../standard-library/unique-ptr-class.md), [`std::shared_ptr`](../standard-library/shared-ptr-class.md), and [`std::weak_ptr`](../standard-library/weak-ptr-class.md). A smart pointer handles the allocation and deletion of the memory it owns. The following example shows a class with an array member that is allocated on the heap in the call to `make_unique()`. The calls to **`new`** and **`delete`** are encapsulated by the `unique_ptr` class. When a `widget` object goes out of scope, the unique_ptr destructor will be invoked and it will release the memory that was allocated for the array. +- [`std::unique_ptr`](../standard-library/unique-ptr-class.md) +- [`std::shared_ptr`](../standard-library/shared-ptr-class.md) +- [`std::weak_ptr`](../standard-library/weak-ptr-class.md) + +A *smart pointer* handles the allocation and deletion of the memory it owns. The following example shows a class with an array member that is allocated on the heap in the call to `make_unique()`. The `unique_ptr` class encapsulates the calls to `new` and `delete`. When a `widget` object goes out of scope, the `unique_ptr` destructor will be invoked and it releases the memory that was allocated for the array. ```cpp #include @@ -38,7 +51,7 @@ void functionUsingWidget() { } // automatic destruction and deallocation for w and w.data ``` -Whenever possible, use a smart pointer to manage heap memory. If you must use the **`new`** and **`delete`** operators explicitly, follow the principle of RAII. For more information, see [Object lifetime and resource management (RAII)](object-lifetime-and-resource-management-modern-cpp.md). +Whenever possible, use a smart pointer to manage heap memory. If you must use the `new` and `delete` operators explicitly, follow the principle of RAII. For more information, see [Object lifetime and resource management (RAII)](object-lifetime-and-resource-management-modern-cpp.md). ## `std::string` and `std::string_view` @@ -46,7 +59,7 @@ C-style strings are another major source of bugs. By using [`std::string` and `s ## `std::vector` and other Standard Library containers -The standard library containers all follow the principle of RAII. They provide iterators for safe traversal of elements. And, they're highly optimized for performance and have been thoroughly tested for correctness. By using these containers, you eliminate the potential for bugs or inefficiencies that might be introduced in custom data structures. Instead of raw arrays, use [`vector`](../standard-library/vector-class.md) as a sequential container in C++. +The standard library containers all follow the principle of RAII. They provide iterators for safe traversal of elements. They're highly optimized for performance and thoroughly tested for correctness. By using these containers, you eliminate the potential for bugs or inefficiencies that might be introduced in custom data structures. Instead of raw arrays, use [`vector`](../standard-library/vector-class.md) as a sequential container in C++. ```cpp vector apples; @@ -61,25 +74,25 @@ map apple_color; apple_color["Granny Smith"] = "Green"; ``` -When performance optimization is needed, consider using: +When you need performance optimization, consider using: -- Unordered associative containers such as [`unordered_map`](../standard-library/unordered-map-class.md). These have lower per-element overhead and constant-time lookup, but they can be harder to use correctly and efficiently. +- Unordered associative containers such as [`unordered_map`](../standard-library/unordered-map-class.md). These containers have lower per-element overhead and constant-time lookup, but they can be harder to use correctly and efficiently. - Sorted `vector`. For more information, see [Algorithms](../standard-library/algorithms.md). Don't use C-style arrays. For older APIs that need direct access to the data, use accessor methods such as `f(vec.data(), vec.size());` instead. For more information about containers, see [C++ Standard Library Containers](../standard-library/stl-containers.md). ## Standard Library algorithms -Before you assume that you need to write a custom algorithm for your program, first review the C++ Standard Library [algorithms](../standard-library/algorithm.md). The Standard Library contains an ever-growing assortment of algorithms for many common operations such as searching, sorting, filtering, and randomizing. The math library is extensive. In C++17 and later, parallel versions of many algorithms are provided. +Before you assume that you need to write a custom algorithm for your program, review the C++ Standard Library [algorithms](../standard-library/algorithm.md). The Standard Library contains an ever-growing assortment of algorithms for many common operations such as searching, sorting, filtering, and randomizing. The math library is extensive. In C++17 and later, parallel versions of many algorithms are provided. Here are some important examples: -- `for_each`, the default traversal algorithm (along with range-based `for` loops). -- `transform`, for not-in-place modification of container elements -- `find_if`, the default search algorithm. +- `for_each`: the default traversal algorithm, along with range-based `for` loops. +- `transform`: for not-in-place modification of container elements. +- `find_if`: the default search algorithm. - `sort`, `lower_bound`, and the other default sorting and searching algorithms. -To write a comparator, use strict **`<`** and use *named lambdas* when you can. +To write a comparator, use strict `<` and use *named lambdas* when you can. ```cpp auto comp = [](const widget& w1, const widget& w2) @@ -92,7 +105,7 @@ auto i = lower_bound( v.begin(), v.end(), widget{0}, comp ); ## `auto` instead of explicit type names -C++11 introduced the [`auto`](auto-cpp.md) keyword for use in variable, function, and template declarations. **`auto`** tells the compiler to deduce the type of the object so that you don't have to type it explicitly. **`auto`** is especially useful when the deduced type is a nested template: +C++11 introduced the [`auto`](auto-cpp.md) keyword for use in variable, function, and template declarations. `auto` tells the compiler to deduce the type of the object so that you don't have to type it explicitly. `auto` is especially useful when the deduced type is a nested template: ```cpp map>::iterator i = m.begin(); // C-style @@ -101,7 +114,7 @@ auto i = m.begin(); // modern C++ ## Range-based `for` loops -C-style iteration over arrays and containers is prone to indexing errors and is also tedious to type. To eliminate these errors, and make your code more readable, use range-based **`for`** loops with both Standard Library containers and raw arrays. For more information, see [Range-based `for` statement](../cpp/range-based-for-statement-cpp.md). +C-style iteration over arrays and containers is prone to indexing errors and is also tedious to type. To eliminate these errors, and make your code more readable, use range-based `for` loops with both Standard Library containers and raw arrays. For more information, see [Range-based `for` statement](../cpp/range-based-for-statement-cpp.md). ```cpp #include @@ -173,11 +186,15 @@ For more information, see [Brace initialization](initializing-classes-and-struct ## Move semantics -Modern C++ provides *move semantics*, which make it possible to eliminate unnecessary memory copies. In earlier versions of the language, copies were unavoidable in certain situations. A *move* operation transfers ownership of a resource from one object to the next without making a copy. Some classes own resources such as heap memory, file handles, and so on. When you implement a resource-owning class, you can define a *move constructor* and *move assignment operator* for it. The compiler chooses these special members during overload resolution in situations where a copy isn't needed. The Standard Library container types invoke the move constructor on objects if one is defined. For more information, see [Move Constructors and Move Assignment Operators (C++)](move-constructors-and-move-assignment-operators-cpp.md). +Modern C++ provides *move semantics*, which make it possible to eliminate unnecessary memory copies. In earlier versions of the language, copies were unavoidable in certain situations. A *move* operation transfers ownership of a resource from one object to the next without making a copy. Some classes own resources such as heap memory, file handles, and so on. + +When you implement a resource-owning class, you can define a *move constructor* and *move assignment operator* for it. The compiler chooses these special members during overload resolution in situations where a copy isn't needed. The Standard Library container types invoke the move constructor on objects if one is defined. For more information, see [Move Constructors and Move Assignment Operators (C++)](move-constructors-and-move-assignment-operators-cpp.md). ## Lambda expressions -In C-style programming, a function can be passed to another function by using a *function pointer*. Function pointers are inconvenient to maintain and understand. The function they refer to may be defined elsewhere in the source code, far away from the point at which it's invoked. Also, they're not type-safe. Modern C++ provides *function objects*, classes that override the [`operator()`](function-call-operator-parens.md) operator, which enables them to be called like a function. The most convenient way to create function objects is with inline [lambda expressions](../cpp/lambda-expressions-in-cpp.md). The following example shows how to use a lambda expression to pass a function object, that the `find_if` function will invoke on each element in the vector: +In C-style programming, a function can be passed to another function by using a *function pointer*. Function pointers are inconvenient to maintain and understand. The function they refer to might be defined elsewhere in the source code, far away from the point at which it's invoked. Also, they're not type-safe. + +Modern C++ provides *function objects*, classes that override the [`operator()`](function-call-operator-parens.md) operator, which enables them to be called like a function. The most convenient way to create function objects is with inline [lambda expressions](../cpp/lambda-expressions-in-cpp.md). The following example shows how to use a lambda expression to pass a function object that the `find_if` function invokes on each element in the vector: ```cpp std::vector v {1,2,3,4,5}; @@ -186,7 +203,7 @@ In C-style programming, a function can be passed to another function by using a auto result = find_if(begin(v), end(v), [=](int i) { return i > x && i < y; }); ``` -The lambda expression `[=](int i) { return i > x && i < y; }` can be read as "function that takes a single argument of type **`int`** and returns a boolean that indicates whether the argument is greater than `x` and less than `y`." Notice that the variables `x` and `y` from the surrounding context can be used in the lambda. The `[=]` specifies that those variables are *captured* by value; in other words, the lambda expression has its own copies of those values. +The lambda expression `[=](int i) { return i > x && i < y; }` can be read as "function that takes a single argument of type `int` and returns a boolean that indicates whether the argument is greater than `x` and less than `y`." Notice that the variables `x` and `y` from the surrounding context can be used in the lambda. The `[=]` specifies that those variables are *captured* by value. In other words, the lambda expression has its own copies of those values. ## Exceptions @@ -198,11 +215,11 @@ Use the C++ Standard Library [`std::atomic`](../standard-library/atomic-structur ## `std::variant` (C++17) -Unions are commonly used in C-style programming to conserve memory by enabling members of different types to occupy the same memory location. However, unions aren't type-safe and are prone to programming errors. C++17 introduces the [`std::variant`](../standard-library/variant-class.md) class as a more robust and safe alternative to unions. The [`std::visit`](../standard-library/variant-functions.md#visit) function can be used to access the members of a `variant` type in a type-safe manner. +Unions are commonly used in C-style programming to conserve memory by enabling members of different types to occupy the same memory location. Unions aren't type-safe and are prone to programming errors. C++17 introduces the [`std::variant`](../standard-library/variant-class.md) class as a more robust and safe alternative to unions. The [`std::visit`](../standard-library/variant-functions.md#visit) function can be used to access the members of a `variant` type in a type-safe manner. ## See also -[C++ Language Reference](../cpp/cpp-language-reference.md)\ -[Lambda Expressions](../cpp/lambda-expressions-in-cpp.md)\ -[C++ Standard Library](../standard-library/cpp-standard-library-reference.md)\ -[Microsoft C/C++ language conformance](../overview/visual-cpp-language-conformance.md) +- [C++ Language Reference](../cpp/cpp-language-reference.md) +- [Lambda Expressions](../cpp/lambda-expressions-in-cpp.md) +- [C++ Standard Library](../standard-library/cpp-standard-library-reference.md) +- [Microsoft C/C++ language conformance](../overview/visual-cpp-language-conformance.md) diff --git a/docs/dotnet/how-to-access-characters-in-a-system-string.md b/docs/dotnet/how-to-access-characters-in-a-system-string.md index c16e9e87202..9191503a10d 100644 --- a/docs/dotnet/how-to-access-characters-in-a-system-string.md +++ b/docs/dotnet/how-to-access-characters-in-a-system-string.md @@ -9,6 +9,10 @@ helpviewer_keywords: ["characters [C++], accessing in System::String", "examples You can access characters of a object for high-performance calls to unmanaged functions that take `wchar_t*` strings. The method yields an interior pointer to the first character of the object. This pointer can be manipulated directly or pinned and passed to a function expecting an ordinary **`wchar_t`** string. +> [!IMPORTANT] +> Interior pointers into objects must be treated as `const`. A object is considered immutable and changing its content can destabilize the runtime. +> For more information, see [Unsafe code best practices - 17. String mutations](/dotnet/standard/unsafe-code/best-practices#17-string-mutations). + ## Examples `PtrToStringChars` returns a , which is an interior pointer (also known as a `byref`). As such, it is subject to garbage collection. You don't have to pin this pointer unless you're going to pass it to a native function. diff --git a/docs/error-messages/compiler-errors-1/compiler-error-c2001.md b/docs/error-messages/compiler-errors-1/compiler-error-c2001.md index 6f34a4fc3d2..cdbee1f1bde 100644 --- a/docs/error-messages/compiler-errors-1/compiler-error-c2001.md +++ b/docs/error-messages/compiler-errors-1/compiler-error-c2001.md @@ -1,13 +1,13 @@ --- title: "Compiler Error C2001" description: "Learn more about: Compiler Error C2001" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C2001"] helpviewer_keywords: ["C2001"] --- # Compiler Error C2001 -> newline in constant +> newline in string literal ## Remarks diff --git a/docs/error-messages/compiler-errors-1/compiler-error-c2002.md b/docs/error-messages/compiler-errors-1/compiler-error-c2002.md index 418f0bc0552..c4f33d4d9f3 100644 --- a/docs/error-messages/compiler-errors-1/compiler-error-c2002.md +++ b/docs/error-messages/compiler-errors-1/compiler-error-c2002.md @@ -1,13 +1,13 @@ --- title: "Compiler Error C2002" description: "Learn more about: Compiler Error C2002" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C2002"] helpviewer_keywords: ["C2002"] --- # Compiler Error C2002 -> invalid wide-character constant +> expected an ordinary string literal ## Remarks diff --git a/docs/error-messages/compiler-errors-1/compiler-error-c2017.md b/docs/error-messages/compiler-errors-1/compiler-error-c2017.md index d659ba2526b..243e763f9af 100644 --- a/docs/error-messages/compiler-errors-1/compiler-error-c2017.md +++ b/docs/error-messages/compiler-errors-1/compiler-error-c2017.md @@ -1,13 +1,13 @@ --- title: "Compiler Error C2017" description: "Learn more about: Compiler Error C2017" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C2017"] helpviewer_keywords: ["C2017"] --- # Compiler Error C2017 -> illegal escape sequence +> unknown escape sequence ## Remarks diff --git a/docs/error-messages/compiler-errors-1/compiler-error-c2018.md b/docs/error-messages/compiler-errors-1/compiler-error-c2018.md index 16c19e66bfb..710b354414b 100644 --- a/docs/error-messages/compiler-errors-1/compiler-error-c2018.md +++ b/docs/error-messages/compiler-errors-1/compiler-error-c2018.md @@ -1,13 +1,13 @@ --- title: "Compiler Error C2018" description: "Learn more about: Compiler Error C2018" -ms.date: 06/21/2025 +ms.date: 06/01/2026 f1_keywords: ["C2018"] helpviewer_keywords: ["C2018"] --- # Compiler Error C2018 -> unknown character 'hexnumber' +> character 'U+*value*' is not permitted here ## Remarks diff --git a/docs/error-messages/compiler-errors-1/compiler-error-c2043.md b/docs/error-messages/compiler-errors-1/compiler-error-c2043.md index 5cc6bae8010..2b457e6fd6b 100644 --- a/docs/error-messages/compiler-errors-1/compiler-error-c2043.md +++ b/docs/error-messages/compiler-errors-1/compiler-error-c2043.md @@ -1,13 +1,13 @@ --- title: "Compiler Error C2043" description: "Learn more about: Compiler Error C2043" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C2043"] helpviewer_keywords: ["C2043"] --- # Compiler Error C2043 -> illegal break +> break statement not within loop or switch statement ## Remarks diff --git a/docs/error-messages/compiler-errors-1/compiler-errors-c2001-through-c2099.md b/docs/error-messages/compiler-errors-1/compiler-errors-c2001-through-c2099.md index d12d6a6217b..e79ce476750 100644 --- a/docs/error-messages/compiler-errors-1/compiler-errors-c2001-through-c2099.md +++ b/docs/error-messages/compiler-errors-1/compiler-errors-c2001-through-c2099.md @@ -1,7 +1,7 @@ --- description: "Learn more about: Compiler errors C2001 through C2099" title: "Compiler errors C2001 through C2099" -ms.date: 08/24/2022 +ms.date: 06/01/2026 f1_keywords: ["C2029"] helpviewer_keywords: ["C2029"] --- @@ -15,8 +15,8 @@ The articles in this section of the documentation explain a subset of the error | Error | Message | |--|--| -| [Compiler error C2001](compiler-error-c2001.md) | newline in constant | -| [Compiler error C2002](compiler-error-c2002.md) | invalid wide-character constant | +| [Compiler error C2001](compiler-error-c2001.md) | newline in string literal | +| [Compiler error C2002](compiler-error-c2002.md) | expected an ordinary string literal | | [Compiler error C2003](compiler-error-c2003.md) | expected 'defined id' | | [Compiler error C2004](compiler-error-c2004.md) | expected 'defined(id)' | | [Compiler error C2005](compiler-error-c2005.md) | #line expected a line number, found '*token*' | @@ -31,8 +31,8 @@ The articles in this section of the documentation explain a subset of the error | [Compiler error C2014](compiler-error-c2014.md) | preprocessor command must start as first nonwhite space | | [Compiler error C2015](compiler-error-c2015.md) | too many characters in constant | | [Compiler error C2016](compiler-error-c2016.md) | C requires that a struct or union has at least one member | -| [Compiler error C2017](compiler-error-c2017.md) | illegal escape sequence | -| [Compiler error C2018](compiler-error-c2018.md) | unknown character '0x*value*' | +| [Compiler error C2017](compiler-error-c2017.md) | unknown escape sequence | +| [Compiler error C2018](compiler-error-c2018.md) | character 'U+*value*' is not permitted here | | [Compiler error C2019](compiler-error-c2019.md) | expected preprocessor directive, found '*character*' | | [Compiler error C2020](compiler-error-c2020.md) | '*member*': '*class*' member redefinition | | [Compiler error C2021](compiler-error-c2021.md) | expected exponent value, not '*character*' | @@ -57,7 +57,7 @@ The articles in this section of the documentation explain a subset of the error | [Compiler error C2040](compiler-error-c2040.md) | '*operator*': '*identifier1*' differs in levels of indirection from '*identifier2*' | | [Compiler error C2041](compiler-error-c2041.md) | illegal digit '*character*' for base '*number*' | | [Compiler error C2042](compiler-error-c2042.md) | signed/unsigned keywords mutually exclusive | -| [Compiler error C2043](compiler-error-c2043.md) | illegal break | +| [Compiler error C2043](compiler-error-c2043.md) | break statement not within loop or `switch` statement | | [Compiler error C2044](compiler-error-c2044.md) | illegal continue | | [Compiler error C2045](compiler-error-c2045.md) | '*identifier*': label redefined | | [Compiler error C2046](compiler-error-c2046.md) | illegal case | diff --git a/docs/error-messages/compiler-errors-1/compiler-fatal-errors-c999-through-c1999.md b/docs/error-messages/compiler-errors-1/compiler-fatal-errors-c999-through-c1999.md index 8ba3fceb817..e95220adc30 100644 --- a/docs/error-messages/compiler-errors-1/compiler-fatal-errors-c999-through-c1999.md +++ b/docs/error-messages/compiler-errors-1/compiler-fatal-errors-c999-through-c1999.md @@ -43,6 +43,7 @@ The articles in this section of the documentation explain a subset of the error | [Fatal error C1026](fatal-error-c1026.md) | parser stack overflow, program too complex | | Fatal error C1027 | **(Obsolete)** Inconsistent values for /Ym between creation and use of precompiled header | | Fatal error C1028 | missing IFC for analysis. Please rebuild *module* '*ifc filename*' with `/analyze`. | +| [Fatal error C1029](fatal-error-c1029.md) | '*filename*': source file hash (*number* bytes) exceeds the IFC format's maximum supported hash size (*number* bytes); use a smaller hash algorithm such as SHA-256 | | Fatal error C1030 | WMMX types not allowed in the function signature by the calling convention | | Fatal error C1032 | `__eabi` requires VFP code generation (`/QRfpe-`) | | [Fatal error C1033](fatal-error-c1033.md) | cannot open program database '*file*' | @@ -130,6 +131,7 @@ The articles in this section of the documentation explain a subset of the error | [Fatal error C1126](fatal-error-c1126.md) | automatic allocation exceeds *size* | | Fatal error C1127 | *Operation* requires *option* | | [Fatal error C1128](fatal-error-c1128.md) | number of sections exceeded object file format limit: compile with `/bigobj` | +|Compiler error C1188|'`#warning`' requires '*language version*' or later| | [Fatal error C1189](fatal-error-c1189.md) | `#error`: *message* | | [Fatal error C1190](fatal-error-c1190.md) | `System::Object` not found, missing `/clr` option or missing import of standard assemblies? | | [Fatal error C1191](fatal-error-c1191.md) | '*file*' can only be imported at global scope | @@ -197,7 +199,7 @@ The articles in this section of the documentation explain a subset of the error | Fatal error C1604 | fatal lambda parsing error: see the lambda definition beginning on line *number* | | Fatal error C1605 | compiler limit: object file size cannot exceed 4 GB | | [Fatal error C1852](fatal-error-c1852.md) | '*file*' is not a valid precompiled header file | -| [Fatal error C1853](fatal-error-c1853.md) | '*file*' precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa) | +| [Fatal error C1853](fatal-error-c1853.md) | '*file*' precompiled header file is from a different version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa) | | [Fatal error C1854](fatal-error-c1854.md) | cannot overwrite information formed during creation of the precompiled header in object file: '*file*' | | Fatal error C1859 | **(Obsolete)** '*Message*' unexpected precompiled header error, simply rerunning the compiler might fix this problem | | [Fatal error C1900](fatal-error-c1900.md) | IL mismatch between '*tool*' version '*number*' and '*tool*' version '*number*' | diff --git a/docs/error-messages/compiler-errors-1/fatal-error-c1029.md b/docs/error-messages/compiler-errors-1/fatal-error-c1029.md new file mode 100644 index 00000000000..c5e1b7e5018 --- /dev/null +++ b/docs/error-messages/compiler-errors-1/fatal-error-c1029.md @@ -0,0 +1,17 @@ +--- +title: "Fatal error C1029" +description: "Learn more about: Fatal error C1029" +ms.date: 05/25/2026 +ai-usage: ai-assisted +f1_keywords: ["C1029"] +helpviewer_keywords: ["C1029"] +--- +# Fatal error C1029 + +> '*filename*': source file hash (*number* bytes) exceeds the IFC format's maximum supported hash size (*number* bytes); use a smaller hash algorithm such as SHA-256 + +## Remarks + +This error occurs when you compile a C++ module (or header unit) with a [`/ZH`](../../build/reference/zh.md) hash algorithm that produces a checksum larger than the current IFC format supports. The **`/ZH:SHA384`** and **`/ZH:SHA512`** options produce checksums that exceed this limit. These algorithms are available starting in Visual Studio 2026 version 18.6.0 and MSVC version 14.51. + +To fix this error, use **`/ZH:SHA_256`** or a smaller hash algorithm (such as **`/ZH:SHA1`** or **`/ZH:MD5`**) when you compile modules or header units. The default **`/ZH:SHA_256`** option works correctly with IFC files. diff --git a/docs/error-messages/compiler-errors-1/fatal-error-c1853.md b/docs/error-messages/compiler-errors-1/fatal-error-c1853.md index 6ff6d7e1dd8..8f6338a544d 100644 --- a/docs/error-messages/compiler-errors-1/fatal-error-c1853.md +++ b/docs/error-messages/compiler-errors-1/fatal-error-c1853.md @@ -1,13 +1,13 @@ --- title: "Fatal Error C1853" description: "Learn more about: Fatal Error C1853" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C1853"] helpviewer_keywords: ["C1853"] --- # Fatal Error C1853 -> '*filename*' precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa) +> '*file*' precompiled header file is from a different version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa) ## Remarks diff --git a/docs/error-messages/compiler-errors-2/compiler-errors-c2900-through-c3499.md b/docs/error-messages/compiler-errors-2/compiler-errors-c2900-through-c3499.md index f426601753e..2f76058d57c 100644 --- a/docs/error-messages/compiler-errors-2/compiler-errors-c2900-through-c3499.md +++ b/docs/error-messages/compiler-errors-2/compiler-errors-c2900-through-c3499.md @@ -1,7 +1,7 @@ --- description: "Learn more about: Compiler errors C2900 Through C2999" title: "Compiler errors C2900 Through C2999" -ms.date: 06/01/2022 +ms.date: 06/01/2026 f1_keywords: ["C2900", "C2901", "C2905", "C2907", "C2915", "C2916", "C2922", "C2924", "C2925", "C2926", "C2938", "C2949", "C2950", "C2954", "C2960", "C2961", "C2963", "C2964", "C2965", "C2966", "C2967", "C2968", "C2972", "C2980", "C2981", "C2982", "C2983", "C2984", "C2985", "C2986", "C2987", "C2997"] helpviewer_keywords: ["C2900", "C2901", "C2905", "C2907", "C2915", "C2916", "C2922", "C2924", "C2925", "C2926", "C2938", "C2949", "C2950", "C2954", "C2960", "C2961", "C2963", "C2964", "C2965", "C2966", "C2967", "C2968", "C2972", "C2980", "C2981", "C2982", "C2983", "C2984", "C2985", "C2986", "C2987", "C2997"] --- @@ -114,6 +114,7 @@ The articles in this section of the documentation explain a subset of the error | [Compiler error C2996](compiler-error-c2996.md) | '*function*': recursive function template definition | | Compiler error C2997 | '*function*': array bound cannot be deduced from a default member initializer | | [Compiler error C2998](compiler-error-c2998.md) | '*identifier*': cannot be a template definition | +|Compiler error C2999|maximum template instantiation depth of *depth* exceeded (see '`/templateDepth:N`')| ## See also diff --git a/docs/error-messages/compiler-errors-2/compiler-errors-c3500-through-c3999.md b/docs/error-messages/compiler-errors-2/compiler-errors-c3500-through-c3999.md index e1469d0230f..22cfa875782 100644 --- a/docs/error-messages/compiler-errors-2/compiler-errors-c3500-through-c3999.md +++ b/docs/error-messages/compiler-errors-2/compiler-errors-c3500-through-c3999.md @@ -1,7 +1,7 @@ --- title: "Compiler errors C3500 through C3999" description: "Learn more about: Compiler errors C3500 through C3999" -ms.date: 05/25/2022 +ms.date: 06/01/2026 f1_keywords: ["C3502", "C3503", "C3504", "C3511", "C3512", "C3513", "C3514", "C3515", "C3516", "C3517", "C3518", "C3520", "C3521", "C3522", "C3523", "C3524", "C3525", "C3526", "C3527", "C3528", "C3529", "C3534", "C3542", "C3543", "C3544", "C3545", "C3546", "C3547", "C3548", "C3549", "C3557", "C3558", "C3559", "C3560", "C3561", "C3562", "C3563", "C3564", "C3565", "C3566", "C3567", "C3568", "C3569", "C3570", "C3571", "C3572", "C3573", "C3574", "C3575", "C3576", "C3577", "C3578", "C3579", "C3580", "C3581", "C3582", "C3583", "C3584", "C3585", "C3586", "C3587", "C3588", "C3589", "C3590", "C3591", "C3592", "C3593", "C3594", "C3595", "C3596", "C3597", "C3598", "C3599", "C3600", "C3601", "C3602", "C3604", "C3605", "C3606", "C3613", "C3614", "C3616", "C3617", "C3620", "C3621", "C3629", "C3635", "C3636", "C3639", "C3643", "C3647", "C3649", "C3658", "C3659", "C3660", "C3663", "C3664", "C3667", "C3674", "C3676", "C3677", "C3678", "C3679", "C3680", "C3681", "C3682", "C3683", "C3684", "C3685", "C3686", "C3687", "C3688", "C3689", "C3690", "C3691", "C3692", "C3693", "C3694", "C3695", "C3696", "C3700", "C3716", "C3720", "C3725", "C3726", "C3729", "C3730", "C3735", "C3742", "C3746", "C3750", "C3751", "C3756", "C3757", "C3758", "C3759", "C3760", "C3770", "C3773", "C3774", "C3775", "C3776", "C3777", "C3778", "C3780", "C3781", "C3782", "C3783", "C3784", "C3785", "C3786", "C3787", "C3788", "C3789", "C3790", "C3791", "C3792", "C3793", "C3794", "C3795", "C3796", "C3801", "C3802", "C3806", "C3810", "C3811", "C3814", "C3819", "C3822", "C3823", "C3826", "C3827", "C3829", "C3835", "C3837", "C3840", "C3841", "C3843", "C3844", "C3845", "C3847", "C3863", "C3864", "C3870", "C3871", "C3875", "C3876", "C3877", "C3878", "C3879", "C3881", "C3882", "C3884", "C3885", "C3897", "C3905", "C3906", "C3907", "C3916", "C3921", "C3924", "C3925", "C3926", "C3927", "C3928", "C3930", "C3931", "C3932", "C3933", "C3934", "C3935", "C3936", "C3937", "C3938", "C3939", "C3940", "C3941", "C3945", "C3946", "C3947", "C3948", "C3949", "C3950", "C3951", "C3952", "C3953", "C3954", "C3955", "C3956", "C3957", "C3958", "C3959", "C3960", "C3961", "C3962", "C3963", "C3964", "C3965", "C3966", "C3967", "C3968", "C3969", "C3970", "C3971", "C3972", "C3973", "C3974", "C3975", "C3976", "C3977", "C3978", "C3979", "C3980", "C3981", "C3982", "C3983", "C3984", "C3985", "C3986", "C3987", "C3988", "C3989", "C3990", "C3991", "C3992", "C3993", "C3994", "C3995", "C3996", "C3997", "C3998"] helpviewer_keywords: ["C3502", "C3503", "C3504", "C3511", "C3512", "C3513", "C3514", "C3515", "C3516", "C3517", "C3518", "C3520", "C3521", "C3522", "C3523", "C3524", "C3525", "C3526", "C3527", "C3528", "C3529", "C3534", "C3542", "C3543", "C3544", "C3545", "C3546", "C3547", "C3548", "C3549", "C3557", "C3558", "C3559", "C3560", "C3561", "C3562", "C3563", "C3564", "C3565", "C3566", "C3567", "C3568", "C3569", "C3570", "C3571", "C3572", "C3573", "C3574", "C3575", "C3576", "C3577", "C3578", "C3579", "C3580", "C3581", "C3582", "C3583", "C3584", "C3585", "C3586", "C3587", "C3588", "C3589", "C3590", "C3591", "C3592", "C3593", "C3594", "C3595", "C3596", "C3597", "C3598", "C3599", "C3600", "C3601", "C3602", "C3604", "C3605", "C3606", "C3613", "C3614", "C3616", "C3617", "C3620", "C3621", "C3629", "C3635", "C3636", "C3639", "C3643", "C3647", "C3649", "C3658", "C3659", "C3660", "C3663", "C3664", "C3667", "C3674", "C3676", "C3677", "C3678", "C3679", "C3680", "C3681", "C3682", "C3683", "C3684", "C3685", "C3686", "C3687", "C3688", "C3689", "C3690", "C3691", "C3692", "C3693", "C3694", "C3695", "C3696", "C3700", "C3716", "C3720", "C3725", "C3726", "C3729", "C3730", "C3735", "C3742", "C3746", "C3750", "C3751", "C3756", "C3757", "C3758", "C3759", "C3760", "C3770", "C3773", "C3774", "C3775", "C3776", "C3777", "C3778", "C3780", "C3781", "C3782", "C3783", "C3784", "C3785", "C3786", "C3787", "C3788", "C3789", "C3790", "C3791", "C3792", "C3793", "C3794", "C3795", "C3796", "C3801", "C3802", "C3806", "C3810", "C3811", "C3814", "C3819", "C3822", "C3823", "C3826", "C3827", "C3829", "C3835", "C3837", "C3840", "C3841", "C3843", "C3844", "C3845", "C3847", "C3863", "C3864", "C3870", "C3871", "C3875", "C3876", "C3877", "C3878", "C3879", "C3881", "C3882", "C3884", "C3885", "C3897", "C3905", "C3906", "C3907", "C3916", "C3921", "C3924", "C3925", "C3926", "C3927", "C3928", "C3930", "C3931", "C3932", "C3933", "C3934", "C3935", "C3936", "C3937", "C3938", "C3939", "C3940", "C3941", "C3945", "C3946", "C3947", "C3948", "C3949", "C3950", "C3951", "C3952", "C3953", "C3954", "C3955", "C3956", "C3957", "C3958", "C3959", "C3960", "C3961", "C3962", "C3963", "C3964", "C3965", "C3966", "C3967", "C3968", "C3969", "C3970", "C3971", "C3972", "C3973", "C3974", "C3975", "C3976", "C3977", "C3978", "C3979", "C3980", "C3981", "C3982", "C3983", "C3984", "C3985", "C3986", "C3987", "C3988", "C3989", "C3990", "C3991", "C3992", "C3993", "C3994", "C3995", "C3996", "C3997", "C3998"] --- @@ -122,6 +122,7 @@ The articles in this section explain a subset of the error messages generated by |Compiler error C3604|'*identifier*': can only create a managed object on the gc heap| |Compiler error C3605|The total number of samplers (*number* captured and *number* predefined) exceed *number* when compiling the call graph for the concurrency::parallel_for_each at: '*function*'| | Compiler error C3606 | intrinsic function '*function*' cannot be mapped to HLSL | +|Compiler error C3607|a structured binding declaration cannot have constraints| |[Compiler error C3609](compiler-error-c3609.md)|'*identifier*': a 'sealed/final' function must be virtual| |[Compiler error C3610](compiler-error-c3610.md)|'*identifier*': value type must be 'boxed' before method '*method*' can be called| |[Compiler error C3611](compiler-error-c3611.md)|'*identifier*': a sealed function cannot have a pure-specifier| @@ -512,6 +513,7 @@ The articles in this section explain a subset of the error messages generated by |Compiler error C3996|Obsolete.| | Compiler error C3997 | Warbird: *message* | |Compiler error C3998|'c++*version*': unsupported C++ version; defaulting to 'c++*version*'| +|Compiler error C3999|expected at least one argument, but observed zero for attribute `[[`*attribute*`]]`| ## See also diff --git a/docs/error-messages/compiler-errors-2/compiler-errors-c7500-through-c7999.md b/docs/error-messages/compiler-errors-2/compiler-errors-c7500-through-c7999.md index 02b5801c7bd..670e726bd3c 100644 --- a/docs/error-messages/compiler-errors-2/compiler-errors-c7500-through-c7999.md +++ b/docs/error-messages/compiler-errors-2/compiler-errors-c7500-through-c7999.md @@ -1,7 +1,7 @@ --- title: "Compiler errors C7500 through C7999" description: "Learn more about: Compiler errors C7500 through C7999" -ms.date: 10/13/2023 +ms.date: 06/01/2026 f1_keywords: ["C7500", "C7501", "C7502", "C7503", "C7504", "C7505", "C7506", "C7507", "C7508", "C7509", "C7511", "C7512", "C7513", "C7514", "C7515", "C7516", "C7517", "C7518", "C7519", "C7520", "C7521", "C7522", "C7523", "C7524", "C7525", "C7526", "C7527", "C7528", "C7529", "C7530", "C7531", "C7532", "C7533", "C7534", "C7535", "C7537", "C7538", "C7539", "C7540", "C7541", "C7542", "C7543", "C7544", "C7545", "C7546", "C7547", "C7548", "C7549", "C7550", "C7551", "C7552", "C7554", "C7555", "C7556", "C7557", "C7558", "C7559", "C7560", "C7561", "C7562", "C7563", "C7564", "C7565", "C7566", "C7567", "C7568", "C7569", "C7570", "C7571", "C7572", "C7573", "C7574", "C7575", "C7576", "C7577", "C7578", "C7579", "C7580", "C7581", "C7582", "C7583", "C7584", "C7585", "C7586", "C7587", "C7588", "C7589", "C7590", "C7591", "C7592", "C7593", "C7594", "C7595", "C7596", "C7597", "C7598", "C7599", "C7600", "C7601", "C7602", "C7603", "C7604", "C7605", "C7606", "C7607", "C7608", "C7609", "C7610", "C7611", "C7612", "C7613", "C7614", "C7615", "C7616", "C7617", "C7618", "C7619", "C7620", "C7621", "C7622", "C7623", "C7624", "C7625", "C7627", "C7628", "C7629", "C7630", "C7631", "C7632", "C7633", "C7634", "C7635", "C7636", "C7637", "C7638", "C7639", "C7640", "C7641", "C7642", "C7643", "C7644", "C7645", "C7646", "C7647", "C7648", "C7649", "C7650", "C7651", "C7652", "C7653", "C7654", "C7655", "C7656", "C7657", "C7658", "C7659", "C7660", "C7661", "C7662", "C7665", "C7666", "C7667", "C7668", "C7669", "C7670", "C7671", "C7672", "C7673", "C7674", "C7675", "C7676", "C7677", "C7678", "C7679", "C7680", "C7682", "C7683", "C7684", "C7685", "C7686", "C7687", "C7689", "C7690", "C7691", "C7692", "C7693", "C7694", "C7695", "C7696", "C7697", "C7698", "C7699", "C7700", "C7701", "C7702", "C7703", "C7704", "C7705", "C7706", "C7707", "C7708", "C7709", "C7710", "C7711", "C7712", "C7713", "C7714", "C7720", "C7730", "C7731", "C7732", "C7733", "C7734", "C7735", "C7736", "C7737", "C7738", "C7739", "C7740", "C7741", "C7800", "C7801", "C7802", "C7803", "C7804", "C7806", "C7807"] helpviewer_keywords: ["C7500", "C7501", "C7502", "C7503", "C7504", "C7505", "C7506", "C7507", "C7508", "C7509", "C7511", "C7512", "C7513", "C7514", "C7515", "C7516", "C7517", "C7518", "C7519", "C7520", "C7521", "C7522", "C7523", "C7524", "C7525", "C7526", "C7527", "C7528", "C7529", "C7530", "C7531", "C7532", "C7533", "C7534", "C7535", "C7537", "C7538", "C7539", "C7540", "C7541", "C7542", "C7543", "C7544", "C7545", "C7546", "C7547", "C7548", "C7549", "C7550", "C7551", "C7552", "C7554", "C7555", "C7556", "C7557", "C7558", "C7559", "C7560", "C7561", "C7562", "C7563", "C7564", "C7565", "C7566", "C7567", "C7568", "C7569", "C7570", "C7571", "C7572", "C7573", "C7574", "C7575", "C7576", "C7577", "C7578", "C7579", "C7580", "C7581", "C7582", "C7583", "C7584", "C7585", "C7586", "C7587", "C7588", "C7589", "C7590", "C7591", "C7592", "C7593", "C7594", "C7595", "C7596", "C7597", "C7598", "C7599", "C7600", "C7601", "C7602", "C7603", "C7604", "C7605", "C7606", "C7607", "C7608", "C7609", "C7610", "C7611", "C7612", "C7613", "C7614", "C7615", "C7616", "C7617", "C7618", "C7619", "C7620", "C7621", "C7622", "C7623", "C7624", "C7625", "C7627", "C7628", "C7629", "C7630", "C7631", "C7632", "C7633", "C7634", "C7635", "C7636", "C7637", "C7638", "C7639", "C7640", "C7641", "C7642", "C7643", "C7644", "C7645", "C7646", "C7647", "C7648", "C7649", "C7650", "C7651", "C7652", "C7653", "C7654", "C7655", "C7656", "C7657", "C7658", "C7659", "C7660", "C7661", "C7662", "C7665", "C7666", "C7667", "C7668", "C7669", "C7670", "C7671", "C7672", "C7673", "C7674", "C7675", "C7676", "C7677", "C7678", "C7679", "C7680", "C7682", "C7683", "C7684", "C7685", "C7686", "C7687", "C7689", "C7690", "C7691", "C7692", "C7693", "C7694", "C7695", "C7696", "C7697", "C7698", "C7699", "C7700", "C7701", "C7702", "C7703", "C7704", "C7705", "C7706", "C7707", "C7708", "C7709", "C7710", "C7711", "C7712", "C7713", "C7714", "C7720", "C7730", "C7731", "C7732", "C7733", "C7734", "C7735", "C7736", "C7737", "C7738", "C7739", "C7740", "C7741", "C7800", "C7801", "C7802", "C7803", "C7804", "C7806", "C7807"] --- @@ -178,6 +178,8 @@ The articles in this section of the documentation explain a subset of the error | Compiler error C7660 | '%s': requires '%s' command line option(s) | | Compiler error C7661 | header-name '%s' has an ambiguous resolution to header '%s' | | Compiler error C7662 | '%$S': a coroutine cannot be constexpr or consteval | +|Compiler error C7663|'*version*': unsupported ABI version; using default| +|Compiler error C7664|'*operator*': ordered comparison of pointer and integer zero ('*type*' and '*type*')| | Compiler error C7665 | '*operator*': you cannot assign to '`this`' as it is not an lvalue | | Compiler error C7666 | you cannot apply '*operator*' to '`this`' as it is not an lvalue | | Compiler error C7667 | no global `operator delete` function found | @@ -242,6 +244,33 @@ The articles in this section of the documentation explain a subset of the error | Compiler error C7741 | ABI inconsistency: '*function*' was originally assumed to use '`C`' return semantics but now it requires '`C++`' return semantics | | [Compiler error C7742](compiler-error-c7742.md) | '*identifier*': a forward declaration of an enum can only use a simple identifier | | Compiler error C7743 | [`__preserve_none` calling convention](../../cpp/preserve-none.md) is not supported | +|Compiler error C7744|escape sequence '*sequence*' out of range| +|Compiler error C7745|attribute `[[msvc::musttail]]` may only be applied to return statements that return a function call expression| +|Compiler error C7746|'*symbol*': cannot appear in its own initializer| +|Compiler error C7747|a type name cannot include the '*specifier*' specifier| +|Compiler error C7748|a type name cannot include the '`__declspec(`*specifier*`)`' specifier| +|Compiler error C7749|'*identifier*': a lambda template parameter cannot have the same name as a capture| +|Compiler error C7750|'*identifier*': a lambda parameter cannot have the same name as a capture| +|Compiler error C7751|'*function*': overriding virtual function has different ref-qualifier from base class virtual member function '*function*'| +|Compiler error C7752|call stack overflow due to excessive template instantiation| +|Compiler error C7753|ill-formed conversion-function-id| +|Compiler error C7754|'*type*' a type cannot be defined as a return or parameter type| +|Compiler error C7755|'*function*': noexcept-specifier depends on itself| +|Compiler error C7756|'*symbol*': declaration attached to module '*name*' conflicts with '*name*' attached to the global module| +|Compiler error C7757|an array of unknown size cannot be initialized by an empty initializer| +|Compiler error C7758|'*type*': cannot be used as the type of an explicit object parameter for a lambda| +|Compiler error C7759|linkage specification is not allowed on an explicit specialization, an explicit instantiation or an export declaration| +|Compiler error C7760|export declaration is not allowed on an explicit specialization, an explicit instantiation, a partial specialization or an export declaration| +|Compiler error C7762|'`\`*escape sequence*`{`' not terminated with '`}`'| +|Compiler error C7763|empty delimited escape sequence| +|Compiler error C7765|'`\o`' not followed by '`{`'| +|Compiler error C7766|incomplete universal character name *name*| +|Compiler error C7767|incomplete named universal character| +|Compiler error C7768|'*name*' is not a valid Unicode character name: names are sensative to casing and whitespace| +|Compiler error C7769|unable to look up Unicode character name, Unicode name support is missing on host machine| +|Compiler error C7770|invalid `[[`*attribute*`]]` attribute| +|Compiler error C7771|ill-formed attribute `[[`*attribute*`]]`| +|Compiler error C7772|invalid string literal| | Compiler error C7800 | duplicate explicit instantiation definition of '*name*' | | Compiler error C7801 | '*function*': if one declaration of '*identifier*' has the '`[[msvc::disptach]]`' attribute then all functions must have the attribute | | Compiler error C7802 | '*identifier*': a capability must resolve to an enumerator | @@ -249,6 +278,12 @@ The articles in this section of the documentation explain a subset of the error | Compiler error C7804 | '*identifier*': cannot find a matching default dispatch function | | Compiler error C7806 | support for the '`msvc::dispatch`' attribute requires '`/experimental:loadTimeSelection`' | | Compiler error C7807 | expecting a narrow string literal | +|Compiler error C7808|'*identifier*': a non-default dispatch function cannot be declared with '*keyword*'| +|Compiler error C7809|'*identifier*': a non-default dispatch function cannot have any default arguments| +|Compiler error C7810|decltype cannot be used in declarative nested name specifiers| +|Compiler error C7811|value of intrinsic immediate argument '*argument number*' is out of range '*number* - *number*'| +|Compiler error C7812|a non-default dispatch function cannot be declared to have `'C'` linkage| +|Compiler error C7813|'*attribute*': attribute only applies for x64 target| ## See also diff --git a/docs/error-messages/compiler-warnings/compiler-warning-c5089.md b/docs/error-messages/compiler-warnings/compiler-warning-c5089.md new file mode 100644 index 00000000000..4551d2ccd60 --- /dev/null +++ b/docs/error-messages/compiler-warnings/compiler-warning-c5089.md @@ -0,0 +1,29 @@ +--- +title: "Compiler Warning (level 1) C5089" +description: "Learn more about: Compiler Warning (level 1) C5089" +ms.date: 07/29/2026 +f1_keywords: ["C5089"] +helpviewer_keywords: ["C5089"] +--- +# Compiler warning (level 1) C5089 + +> using `/fsanitize=address` with `/clr` is experimental and may result in unexpected behavior. + +## Remarks + +This warning occurs when you compile with both [`/fsanitize=address`](../../build/reference/fsanitize.md) (AddressSanitizer) and [`/clr`](../../build/reference/clr-common-language-runtime-compilation.md) (Common Language Runtime compilation). Although you can use AddressSanitizer with managed C++, support is still experimental. This limitation can lead to missed detections and unpredictable application behavior. For more information on ASan compatibility, see [AddressSanitizer known issues](../../sanitizers/asan-known-issues.md#incompatible-options). + +## Example + +The following command line generates warning C5089: + +```cmd +cl /fsanitize=address /clr test.cpp +``` + +To fix it, remove either [`/fsanitize=address`](../../build/reference/fsanitize.md) or [`/clr`](../../build/reference/clr-common-language-runtime-compilation.md) from the command line. + +## See also + +[Address Sanitizer (ASAN)](../../sanitizers/asan.md)\ +[AddressSanitizer known issues](../../sanitizers/asan-known-issues.md) diff --git a/docs/error-messages/compiler-warnings/compiler-warning-level-1-c4630.md b/docs/error-messages/compiler-warnings/compiler-warning-level-1-c4630.md index 43df3fea625..ecb2bb48b85 100644 --- a/docs/error-messages/compiler-warnings/compiler-warning-level-1-c4630.md +++ b/docs/error-messages/compiler-warnings/compiler-warning-level-1-c4630.md @@ -1,13 +1,13 @@ --- title: "Compiler Warning (level 1) C4630" description: "Learn more about: Compiler Warning (level 1) C4630" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C4630"] helpviewer_keywords: ["C4630"] --- # Compiler Warning (level 1) C4630 -> 'symbol' : 'extern' storage class specifier illegal on member definition +> '*symbol*': '*extern*' storage-class specifier cannot be applied to a member ## Remarks diff --git a/docs/error-messages/compiler-warnings/compiler-warning-level-4-c4709.md b/docs/error-messages/compiler-warnings/compiler-warning-level-4-c4709.md index 4061b8eaabb..640cc04d437 100644 --- a/docs/error-messages/compiler-warnings/compiler-warning-level-4-c4709.md +++ b/docs/error-messages/compiler-warnings/compiler-warning-level-4-c4709.md @@ -1,17 +1,17 @@ --- title: "Compiler Warning (level 4) C4709" description: "Learn more about: Compiler Warning (level 4) C4709" -ms.date: 11/04/2016 +ms.date: 06/01/2026 f1_keywords: ["C4709"] helpviewer_keywords: ["C4709"] --- # Compiler Warning (level 4) C4709 -> comma operator within array index expression +> comma operator within a subscript expression ## Remarks -When a comma occurs in an array index expression, the compiler uses the value after the last comma. +When a comma occurs in a subscript expression, the compiler uses the value after the last comma. ## Example diff --git a/docs/error-messages/compiler-warnings/compiler-warnings-by-compiler-version.md b/docs/error-messages/compiler-warnings/compiler-warnings-by-compiler-version.md index d5706dfc19c..647a6c116cf 100644 --- a/docs/error-messages/compiler-warnings/compiler-warnings-by-compiler-version.md +++ b/docs/error-messages/compiler-warnings/compiler-warnings-by-compiler-version.md @@ -1,7 +1,7 @@ --- title: "Compiler Warnings by compiler version" description: "Table of Microsoft C/C++ compiler warnings by compiler version." -ms.date: 01/18/2024 +ms.date: 06/01/2026 helpviewer_keywords: ["warnings, by compiler version", "cl.exe compiler, setting warning options"] --- # Compiler Warnings by compiler version @@ -12,6 +12,9 @@ These versions of the compiler introduced new warnings: | Product | Compiler version number | |--|--| +| MSVC version 14.51 | 19.51 | +| Visual Studio 2026 version 18.1 | 19.46 | +| Visual Studio 2026 version 18.0 | 19.45 | | Visual Studio 2022 version 17.14 | 19.44 | | Visual Studio 2022 version 17.13 | 19.43 | | Visual Studio 2022 version 17.12 | 19.42 | @@ -64,13 +67,73 @@ The following sections list the warnings introduced by each version of Visual C+ ::: moniker range=">= msvc-170" +## Warnings introduced in MSVC version 14.51 (compiler version 19.51) + +These warnings, and all warnings in later versions, are suppressed by using the compiler option **`/Wv:19.51`**. + +| Warning | Message | +|--|--| +|C4876|incomplete or invalid multi-byte character in string literal. Use an escape sequence to preserve these byte values.| +|C5299|a label appearing at the end of a compound statement requires at least '`/std:c++23`'| + +## Warnings introduced in Visual Studio 2026 version 18.1 (compiler version 19.46) + +These warnings, and all warnings in later versions, are suppressed by using the compiler option **`/Wv:19.46`**. + +| Warning | Message | +|--|--| +|C5296|parsing resumes here after skipping tokens for error recovery| +|C5297|value in string literal is not a valid character in code page *codepage* or can not be re-encoded in code page *codepage*. Switching to permissive character translation.| + +## Warnings introduced in Visual Studio 2026 version 18.0 (compiler version 19.45) + +These warnings, and all warnings in later versions, are suppressed by using the compiler option **`/Wv:19.45`**. + +| Warning | Message | +|--|--| +|C4864|expected '`template`' keyword before dependent template name| +|C4865|the underlying type of '*type*' will change when '`/Zc:enumTypes`' is specified on the command line| +|C4873|'*identifier*' cannot be a function template| +|C4874|assignment used as a condition| +|C4875|a non-string literal argument to `[[gsl::suppress]]` is deprecated and will be removed in a future release| +|C5290|an alias-declaration in this context requires at least '`/std:c++23`'| +|C5291|'*derived*': deriving from the base class '*base*' can cause potential runtime issues due to an ABI bug. Recommend adding a *number*-byte data member to the base class for the padding at the end of it to work around this bug.| +|C5295|`#warning` *message*| +|C5298|ignoring spurious 'U+*NNNNNNNN*' character in source| +|C5311|A literal-operator-id of the form '`operator string-literal identifier`' has been deprecated| +|C5322|'*identifier*': dynamic initialization of a variable in a readonly custom section '*segment*' is not supported| +|C5332|delimited escape sequences are only valid in C++23| +|C5333|backslash and newline separated by space is treated as a line continuation in C++23 and later| +|C5334|named universal characters require at least '`/std:c++23`'| +|C5335|incomplete named universal character| +|C5336|invalid string literal created by '`#`' operator, ignoring final '`\`'| + ## Warnings introduced in Visual Studio 2022 version 17.14 (compiler version 19.44) These warnings, and all warnings in later versions, are suppressed by using the compiler option **`/Wv:19.43`**. | Warning | Message | |--|--| -| C4862 | justification property is not allowed with more than one warning number | +|C4862 | justification property is not allowed with more than one warning number| +|C4863|unknown property in `#pragma warning`: '*property*'| +|C5278 | adding a specialization for '*type*' has undefined behavior| +|C5279 | a lambda declarator without a parameter list requires at least '*language version*'| +|C5280 | a static operator '*operator name*' requires at least '*language version*'| +|C5281 | a static lambda requires at least '*language version*'| +|C5282 | '`if consteval`' requires at least '*language version*'| +|C5283 | an attribute in this position requires at least '*language version*'| +|C5284 | conversion from value '*value*' of type '*type 1*' to '*type 2*' requires a narrowing conversion| +|C5285 | cannot declare a specialization for '*template name*': *template argument*| +|C5286 | implicit conversion from `enum` type '*type 1*' to `enum` type '*type 2*'; use an explicit cast to silence this warning| +|C5287 | operands are different `enum` types '*type 1*' and '*type 2*'; use an explicit cast to silence this warning| +|C5288|only '`= 0`' is allowed as a pure specifier| +|C5289|'*identifier*' after '`template`' keyword does not refer to a template| +|C5292|'*operator*': '*type*' to '*type*' differs in indirection: one is the unique plain '`char`' type and the other is not| +|C5293|function parameter *parameter number* type '*type*' differs from declaration parameter type '*type*': one is the unique plain '`char`' type and the other is not| +|C5294|'*identifier*': benign redefinition of type from '*type*' to '*type*': one is the unique plain '`char`' type and the other is not| +|C5310|The experimental standard library modules have been deprecated. The core language Modules facility is available with '`/std:c++20`' or higher, allowing '`import std;`' to be used. See: https://aka.ms/import-std| +|C5320|'*escape sequence*' in a u8 string is encoded as 0x*NNNN*, which is not a valid utf-8 code point. For a multi-byte unicode character use `\u`.| +|C5321|nonstandard extension used: encoding '*escape sequence*' as a multi-byte utf-8 character. Use `\u` instead for cross platform compatibility and '`/Zc:u8EscapeEncoding`' to disable the extension.| ## Warnings introduced in Visual Studio 2022 version 17.13 (compiler version 19.43) diff --git a/docs/error-messages/compiler-warnings/compiler-warnings-c4600-through-c4799.md b/docs/error-messages/compiler-warnings/compiler-warnings-c4600-through-c4799.md index 26ff337deb2..b57fb7793da 100644 --- a/docs/error-messages/compiler-warnings/compiler-warnings-c4600-through-c4799.md +++ b/docs/error-messages/compiler-warnings/compiler-warnings-c4600-through-c4799.md @@ -1,7 +1,7 @@ --- title: "Microsoft C/C++ compiler (MSVC) warnings C4600 through C4799" description: "Table of Microsoft C/C++ compiler (MSVC) warnings C4600 through C4799" -ms.date: 05/03/2021 +ms.date: 06/01/2026 f1_keywords: ["C4604", "C4605", "C4609", "C4631", "C4642", "C4643", "C4644", "C4647", "C4648", "C4649", "C4654", "C4658", "C4671", "C4676", "C4689", "C4695", "C4696", "C4719", "C4720", "C4721", "C4725", "C4726", "C4728", "C4729", "C4732", "C4734", "C4735", "C4736", "C4745", "C4749", "C4751", "C4752", "C4753", "C4755", "C4757", "C4761", "C4767", "C4771", "C4774", "C4775", "C4776", "C4777", "C4778", "C4792", "C4798"] helpviewer_keywords: ["C4604", "C4605", "C4609", "C4631", "C4642", "C4643", "C4644", "C4647", "C4648", "C4649", "C4654", "C4658", "C4671", "C4676", "C4689", "C4695", "C4696", "C4719", "C4720", "C4721", "C4725", "C4726", "C4728", "C4729", "C4732", "C4734", "C4735", "C4736", "C4745", "C4749", "C4751", "C4752", "C4753", "C4755", "C4757", "C4761", "C4767", "C4771", "C4774", "C4775", "C4776", "C4777", "C4778", "C4792", "C4798"] --- @@ -41,7 +41,7 @@ The articles in this section describe Microsoft C/C++ compiler warning messages |[Compiler warning (level 1, no longer emitted) C4627](compiler-warning-level-1-c4627.md)|'`identifier`': skipped when looking for precompiled header use| |[Compiler warning (level 1, off) C4628](compiler-warning-level-1-c4628.md)|digraphs not supported with `-Ze`. Character sequence '*digraph*' not interpreted as alternate token for '*token*'| |[Compiler warning (level 4, no longer emitted) C4629](compiler-warning-level-4-c4629.md)|digraph used, character sequence '*digraph*' interpreted as token '*char*' (insert a space between the two characters if this is not what you intended)| -|[Compiler warning (level 1) C4630](compiler-warning-level-1-c4630.md)|'*symbol*': '*extern*' storage-class specifier illegal on member definition| +|[Compiler warning (level 1) C4630](compiler-warning-level-1-c4630.md)|'*symbol*': '*extern*' storage-class specifier cannot be applied to a member| |Compiler warning (level 2) C4631|`MSXML` or `XPath` unavailable, XML document comments will not be processed. *reason*| |[Compiler warning (level 1) C4632](compiler-warning-level-1-c4632.md)|XML document comment: *file* - access denied: *reason*| |[Compiler warning (level 3 and level 4) C4633](compiler-warning-level-3-c4633.md)|XML document comment *target*: error: *reason*| @@ -108,7 +108,7 @@ The articles in this section describe Microsoft C/C++ compiler warning messages |[Compiler warning (level 4) C4702](compiler-warning-level-4-c4702.md)|unreachable code| |[Compiler warning (level 4) C4703](compiler-warning-level-4-c4703.md)|potentially uninitialized local pointer variable '*identifier*' used| |[Compiler warning (level 4) C4706](compiler-warning-level-4-c4706.md)|assignment used as a condition| -|[Compiler warning (level 4) C4709](compiler-warning-level-4-c4709.md)|comma operator within array index expression| +|[Compiler warning (level 4) C4709](compiler-warning-level-4-c4709.md)|comma operator within a subscript expression| |[Compiler warning (level 4, off) C4710](compiler-warning-level-4-c4710.md)|'*function*': function not inlined| |[Compiler warning (level 1) C4711](compiler-warning-level-1-c4711.md)|function 'function' selected for automatic inline expansion| |[Compiler warning (level 4) C4714](compiler-warning-level-4-c4714.md)|function '*function*' marked as `__forceinline` not inlined| diff --git a/docs/error-messages/compiler-warnings/compiler-warnings-c4800-through-c4999.md b/docs/error-messages/compiler-warnings/compiler-warnings-c4800-through-c4999.md index 3ac4f3718a5..0f1ccf793d7 100644 --- a/docs/error-messages/compiler-warnings/compiler-warnings-c4800-through-c4999.md +++ b/docs/error-messages/compiler-warnings/compiler-warnings-c4800-through-c4999.md @@ -1,7 +1,7 @@ --- title: "Microsoft C/C++ compiler (MSVC) warnings C4800 through C4999" description: "Table of Microsoft C/C++ compiler (MSVC) warnings C4800 through C4999." -ms.date: 04/17/2024 +ms.date: 06/01/2026 f1_keywords: ["C4801", "C4808", "C4809", "C4815", "C4826", "C4827", "C4828", "C4837", "C4842", "C4844", "C4845", "C4846", "C4847", "C4848", "C4849", "C4854", "C4855", "C4856", "C4857", "C4858", "C4859", "C4860", "C4861", "C4862", "C4869", "C4872", "C4880", "C4881", "C4882", "C4883", "C4907", "C4916", "C4921", "C4934", "C4954", "C4955", "C4963", "C4966", "C4970", "C4971", "C4973", "C4974", "C4975", "C4976", "C4981", "C4983", "C4987", "C4988", "C4989", "C4990", "C4991", "C4992", "C4998"] helpviewer_keywords: ["C4801", "C4808", "C4809", "C4815", "C4826", "C4827", "C4828", "C4837", "C4842", "C4844", "C4845", "C4846", "C4847", "C4848", "C4849", "C4854", "C4855", "C4856", "C4857", "C4858", "C4859", "C4860", "C4861", "C4862", "C4869", "C4872", "C4880", "C4881", "C4882", "C4883", "C4907", "C4916", "C4921", "C4934", "C4954", "C4955", "C4963", "C4966", "C4970", "C4971", "C4973", "C4974", "C4975", "C4976", "C4981", "C4983", "C4987", "C4988", "C4989", "C4990", "C4991", "C4992", "C4998"] --- @@ -64,11 +64,18 @@ The articles in this section describe Microsoft C/C++ compiler warning messages | Compiler warning (level 4) C4860 | '*object name*': compiler zero initialized '*number*' bytes of storage | | Compiler warning (level 4) C4861 | compiler zero initialized '*number*' bytes of storage | | Compiler warning (level 1) C4862 | justification property is not allowed with more than one warning number | +|Compiler warning (level 1) C4863|unknown property in `#pragma warning`: '*property*'| +|Compiler warning (level 4) C4864|expected '`template`' keyword before dependent template name| +|Compiler warning (level 4, off) C4865|the underlying type of '*type*' will change when '`/Zc:enumTypes`' is specified on the command line| | [Compiler warning (level 4) C4866](c4866.md) | compiler may not enforce left-to-right evaluation order for call to *operator_name* | | [Compiler warning (level 1, error) C4867](compiler-warning-c4867.md) |'*function name*': non-standard syntax; use '`&`' to create a pointer to member| | [Compiler warning (level 4) C4868](compiler-warning-c4868.md) | '*file*(*line_number*)' compiler may not enforce left-to-right evaluation order in braced initialization list | | Compiler warning (level 3) C4869 | '`nodiscard`' may only be applied to classes, enumerations, and functions | | Compiler warning (level 2) C4872 | floating point division by zero detected when compiling the call graph for the `concurrency::parallel_for_each` at: '*location*' | +|Compiler warning (level 4, off) C4873|'*identifier*' cannot be a function template| +|Compiler warning (level 4) C4874|assignment used as a condition| +|Compiler warning (level 1) C4875|a non-string literal argument to `[[gsl::suppress]]` is deprecated and will be removed in a future release| +|Compiler warning (level 1) C4876|incomplete or invalid multi-byte character in string literal. Use an escape sequence to preserve these byte values.| | Compiler warning (level 1) C4880 | casting from '*const type_1*' to '*type_2*': casting away constness from a pointer or reference may result in undefined behavior in an `amp` restricted function | | Compiler warning (level 4) C4881 | the constructor and/or the destructor will not be invoked for `tile_static` variable '*variable-name*' | | Compiler warning (level 1) C4882 | passing functors with non-const call operators to `concurrency::parallel_for_each` is deprecated | diff --git a/docs/error-messages/compiler-warnings/compiler-warnings-c5000-through-c5199.md b/docs/error-messages/compiler-warnings/compiler-warnings-c5000-through-c5199.md index 38f4e448954..01e7052c4aa 100644 --- a/docs/error-messages/compiler-warnings/compiler-warnings-c5000-through-c5199.md +++ b/docs/error-messages/compiler-warnings/compiler-warnings-c5000-through-c5199.md @@ -59,6 +59,7 @@ The articles in this section describe Microsoft C/C++ compiler warning messages | Compiler warning (level 1) C5063 | '`std::is_constant_evaluated`' always evaluates to true in manifestly constant-evaluated expressions | | [Compiler warning (level 1) C5072](compiler-warning-c5072.md) | ASAN enabled without debug information emission. Enable debug info for better ASAN error reporting | | Compiler warning (level 1) C5081 | Secure hotpatch is not supported with `/GENPROFILE`, `/FASTGENPROFILE` or `/LTCG:PGI`, disabling secure hotpatch. | +| [Compiler warning (level 1) C5089](compiler-warning-c5089.md) | using `/fsanitize=address` with `/clr` is experimental and may result in unexpected behavior. | | Compiler warning (level 1) C5100 | `__VA_ARGS__` is reserved for use in variadic macros | | Compiler warning (level 1) C5101 | use of preprocessor directive in function-like macro argument list is undefined behavior | | Compiler warning (level 1) C5102 | ignoring invalid command-line macro definition '*value*' | diff --git a/docs/error-messages/compiler-warnings/compiler-warnings-c5200-through-c5399.md b/docs/error-messages/compiler-warnings/compiler-warnings-c5200-through-c5399.md index 0bebc97caa6..bac0dc66260 100644 --- a/docs/error-messages/compiler-warnings/compiler-warnings-c5200-through-c5399.md +++ b/docs/error-messages/compiler-warnings/compiler-warnings-c5200-through-c5399.md @@ -1,7 +1,7 @@ --- title: "Microsoft C/C++ compiler (MSVC) compiler warnings C5200 through C5399" description: "Table of Microsoft C/C++ compiler (MSVC) warnings C5200 through C5399." -ms.date: 04/19/2024 +ms.date: 06/01/2026 f1_keywords: ["C5200", "C5201", "C5202", "C5203", "C5204", "C5205", "C5206", "C5207", "C5209", "C5210", "C5212", "C5213", "C5214", "C5215", "C5216", "C5217", "C5218", "C5219", "C5220", "C5221", "C5222", "C5223", "C5224", "C5225", "C5226", "C5227", "C5228", "C5229", "C5230", "C5231", "C5232", "C5233", "C5234", "C5235", "C5236", "C5237", "C5238", "C5239", "C5241", "C5242", "C5244", "C5245", "C5246", "C5249", "C5250", "C5251", "C5252", "C5253", "C5254", "C5255", "C5256", "C5257", "C5258", "C5259", "C5260", "C5261", "C5263", "C5264", "C5265", "C5268", "C5269", "C5270", "C5271", "C5272", "C5273", "C5274", "C5275", "C5276", "C5277", "C5278", "C5279", "C5280", "C5281", "C5282", "C5283", "C5284", "C5285", "C5286", "C5287", "C5300", "C5303", "C5304", "C5305", "C5306", "C5307", "C5308", "C5309"] helpviewer_keywords: ["C5200", "C5201", "C5202", "C5203", "C5204", "C5205", "C5206", "C5207", "C5209", "C5210", "C5212", "C5213", "C5214", "C5215", "C5216", "C5217", "C5218", "C5219", "C5220", "C5221", "C5222", "C5223", "C5224", "C5225", "C5226", "C5227", "C5228", "C5229", "C5230", "C5231", "C5232", "C5233", "C5234", "C5235", "C5236", "C5237", "C5238", "C5239", "C5241", "C5242", "C5244", "C5245", "C5246", "C5249", "C5250", "C5251", "C5252", "C5253", "C5254", "C5255", "C5256", "C5257", "C5258", "C5259", "C5260", "C5261", "C5263", "C5264", "C5265", "C5268", "C5269", "C5270", "C5271", "C5272", "C5273", "C5274", "C5275", "C5276", "C5277", "C5278", "C5279", "C5280", "C5281", "C5282", "C5283", "C5284", "C5285", "C5286", "C5287", "C5300", "C5303", "C5304", "C5305", "C5306", "C5307", "C5308", "C5309"] --- @@ -102,6 +102,18 @@ The articles in this section describe Microsoft C/C++ compiler warning messages | Compiler warning (level 1) C5285 | cannot declare a specialization for '*template name*': *template argument* | | Compiler warning (level 1) C5286 | implicit conversion from `enum` type '*type 1*' to `enum` type '*type 2*'; use an explicit cast to silence this warning | | Compiler warning (level 1) C5287 | operands are different `enum` types '*type 1*' and '*type 2*'; use an explicit cast to silence this warning | +|Compiler warning (level 4) C5288|only '`= 0`' is allowed as a pure specifier| +|Compiler warning (level 4) C5289|'*identifier*' after '`template`' keyword does not refer to a template| +|Compiler warning (level 1) C5290|an alias-declaration in this context requires at least '`/std:c++23`'| +|Compiler warning (level 1, off) C5291|'*derived*': deriving from the base class '*base*' can cause potential runtime issues due to an ABI bug. Recommend adding a *number*-byte data member to the base class for the padding at the end of it to work around this bug.| +|Compiler warning (level 4) C5292|'*operator*': '*type*' to '*type*' differs in indirection: one is the unique plain '`char`' type and the other is not| +|Compiler warning (level 4) C5293|function parameter *parameter number* type '*type*' differs from declaration parameter type '*type*': one is the unique plain '`char`' type and the other is not| +|Compiler warning (level 4) C5294|'*identifier*': benign redefinition of type from '*type*' to '*type*': one is the unique plain '`char`' type and the other is not| +|Compiler warning (level 1) C5295|`#warning` *message*| +|Compiler warning (level 4) C5296|parsing resumes here after skipping tokens for error recovery| +|Compiler warning (level 1) C5297|value in string literal is not a valid character in code page *codepage* or can not be re-encoded in code page *codepage*. Switching to permissive character translation.| +|Compiler warning (level 1) C5298|ignoring spurious 'U+*NNNNNNNN*' character in source| +|Compiler warning (level 1, error) C5299|a label appearing at the end of a compound statement requires at least '`/std:c++23`'| | Compiler warning (error) C5300 | '`#pragma omp atomic` *clause*': expression mismatch for lvalue being updated | | [Compiler warning (level 1) C5301](c5301-c5302.md) | '`#pragma omp for`': '*loop-index*' increases while loop condition uses '*comparison*'; non-terminating loop? | | [Compiler warning (level 1) C5302](c5301-c5302.md) | '`#pragma omp for`': '*loop-index*' decreases while loop condition uses '*comparison*'; non-terminating loop? | @@ -112,6 +124,16 @@ The articles in this section describe Microsoft C/C++ compiler warning messages | Compiler warning (level 3) C5307 | '*function*': argument (*argument number*) converted from '*type 1*' to '*type 2*'. Missing '`L`' encoding-prefix for character literal? | | Compiler warning (level 1, error) C5308 | Modifying reserved macro name '*macro name*' may cause undefined behavior | | Compiler warning (level 1, error) C5309 | literal suffix '*name*' requires at least '*language version*'| +|Compiler warning (level 1) C5310|The experimental standard library modules have been deprecated. The core language Modules facility is available with '`/std:c++20`' or higher, allowing '`import std;`' to be used. See: https://aka.ms/import-std| +|Compiler warning (level 4) C5311|A literal-operator-id of the form '`operator string-literal identifier`' has been deprecated| +|Compiler warning (level 4, off) C5320|'*escape sequence*' in a u8 string is encoded as 0x*NNNN*, which is not a valid utf-8 code point. For a multi-byte unicode character use `\u`.| +|Compiler warning (level 4) C5321|nonstandard extension used: encoding '*escape sequence*' as a multi-byte utf-8 character. Use `\u` instead for cross platform compatibility and '`/Zc:u8EscapeEncoding`' to disable the extension.| +|Compiler warning (level 4, off) C5322|'*identifier*': dynamic initialization of a variable in a readonly custom section '*segment*' is not supported| +|Compiler warning (level 1) C5332|delimited escape sequences are only valid in C++23| +|Compiler warning (level 1) C5333|backslash and newline separated by space is treated as a line continuation in C++23 and later| +|Compiler warning (level 1) C5334|named universal characters require at least '`/std:c++23`'| +|Compiler warning (level 1) C5335|incomplete named universal character| +|Compiler warning (level 1) C5336|invalid string literal created by '`#`' operator, ignoring final '`\`'| ## See also diff --git a/docs/error-messages/toc.yml b/docs/error-messages/toc.yml index acb65fcdd54..71c6190ca58 100644 --- a/docs/error-messages/toc.yml +++ b/docs/error-messages/toc.yml @@ -136,6 +136,8 @@ items: href: compiler-errors-1/fatal-error-c1025-c1115.md - name: Fatal error C1026 href: compiler-errors-1/fatal-error-c1026.md + - name: Fatal error C1029 + href: compiler-errors-1/fatal-error-c1029.md - name: Fatal error C1033 href: compiler-errors-1/fatal-error-c1033.md - name: Fatal error C1035 @@ -4356,6 +4358,8 @@ items: href: compiler-warnings/c5056.md - name: Compiler warning (level 1) C5072 href: compiler-warnings/compiler-warning-c5072.md + - name: Compiler warning (level 1) C5089 + href: compiler-warnings/compiler-warning-c5089.md - name: Compiler warning (level 1) C5105 href: compiler-warnings/c5105.md - name: Compiler warnings C5200 through C5399 diff --git a/docs/get-started/includes/git-source-control.md b/docs/get-started/includes/git-source-control.md index c1d17bec684..579f433cfea 100644 --- a/docs/get-started/includes/git-source-control.md +++ b/docs/get-started/includes/git-source-control.md @@ -7,22 +7,22 @@ ms.topic: include ## Add Git source control -Now that you've created an app, you might want to add it to a Git repository. We've got you covered. Visual Studio makes that process easy with Git tools you can use directly from the IDE. +After you create an app, you might want to add it to a Git repository. We've got you covered. Visual Studio makes that process easy with Git tools you can use directly from the IDE. > [!TIP] -> Git is the most widely used modern version control system, so whether you're a professional developer or you're learning how to code, Git can be very useful. If you're new to Git, the [https://git-scm.com/](https://git-scm.com/) website is a good place to start. There, you can find cheat sheets, a popular online book, and Git Basics videos. +> Git is the most widely used modern version control system. Whether you're a professional developer or you're learning how to code, Git can be useful. If you're new to Git, the [Git website](https://git-scm.com/) is a good place to start. There, you can find cheat sheets, a popular online book, and Git Basics videos. -To associate your code with Git, you start by creating a new Git repository where your code is located. Here's how: +To associate your code with Git, you start by creating a new Git repository where your code is located. 1. In the status bar at the bottom-right corner of Visual Studio, select **Add to Source Control**, and then select **Git**. - :::image type="content" source="../media/vs-2022/git-add-source-control.png" alt-text="Screenshot of the Git source control buttons below the Solution Explorer pane, with the Add to Source Control button highlighted."::: + :::image type="content" source="../media/vs-2026/git-add-source-control.png" alt-text="Screenshot of the Git source control buttons below the Solution Explorer pane, with the Add to Source Control button highlighted."::: -1. In the **Create a Git repository** dialog box, sign in to GitHub. +1. In the **Create a Git repository** dialog, sign in to GitHub. - :::image type="content" source="../media/vs-2022/git-create-repo.png" alt-text="Screenshot of the Create a Git Repository dialog window where you create a new GitHub repository."::: + :::image type="content" source="../media/vs-2026/git-create-repository.png" alt-text="Screenshot of the Create a Git Repository dialog window where you create a new GitHub repository."::: - The repository name auto-populates based on your folder location. By default, your new repository is private, which means you're the only one who can access it. + The repository name autopopulates based on your folder location. By default, your new repository is private, which means you're the only one who can access it. > [!TIP] > Whether your repository is public or private, it's best to have a remote backup of your code stored securely on GitHub. Even if you aren't working with a team, a remote repository makes your code available to you from any computer. @@ -31,7 +31,7 @@ To associate your code with Git, you start by creating a new Git repository wher After you create your repository, status details appear in the status bar. - :::image type="content" source="../media/vs-2022/git-new-private-repo-status-details.png" alt-text="Screenshot of the repo status bar located below the Visual Studio Solution Explorer pane, showing the branch name and number of outstanding changes."::: + :::image type="content" source="../media/vs-2026/git-new-private-repository-status-details.png" alt-text="Screenshot of the repo status bar located below the Visual Studio Solution Explorer pane, showing the branch name and number of outstanding changes."::: The first icon with the arrows shows how many outgoing/incoming commits are in your current branch. You can use this icon to pull any incoming commits or push any outgoing commits. You can also choose to view these commits first. To do so, select the icon, and then select **View Outgoing/Incoming**. diff --git a/docs/get-started/media/vs-2026/calculator-autos.png b/docs/get-started/media/vs-2026/calculator-autos.png new file mode 100644 index 00000000000..bbd771c6933 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-autos.png differ diff --git a/docs/get-started/media/vs-2026/calculator-build-project.png b/docs/get-started/media/vs-2026/calculator-build-project.png new file mode 100644 index 00000000000..e205c295fa3 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-build-project.png differ diff --git a/docs/get-started/media/vs-2026/calculator-choose-console-app.png b/docs/get-started/media/vs-2026/calculator-choose-console-app.png new file mode 100644 index 00000000000..e74f21d38f5 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-choose-console-app.png differ diff --git a/docs/get-started/media/vs-2026/calculator-conditional-breakpoint.png b/docs/get-started/media/vs-2026/calculator-conditional-breakpoint.png new file mode 100644 index 00000000000..0b3e8fce9cd Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-conditional-breakpoint.png differ diff --git a/docs/get-started/media/vs-2026/calculator-constructor.png b/docs/get-started/media/vs-2026/calculator-constructor.png new file mode 100644 index 00000000000..a3a26548ec9 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-constructor.png differ diff --git a/docs/get-started/media/vs-2026/calculator-create-calculator-class.png b/docs/get-started/media/vs-2026/calculator-create-calculator-class.png new file mode 100644 index 00000000000..176be2766ba Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-create-calculator-class.png differ diff --git a/docs/get-started/media/vs-2026/calculator-create-definition.png b/docs/get-started/media/vs-2026/calculator-create-definition.png new file mode 100644 index 00000000000..5194d1ce318 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-create-definition.png differ diff --git a/docs/get-started/media/vs-2026/calculator-debug-breakpoint.png b/docs/get-started/media/vs-2026/calculator-debug-breakpoint.png new file mode 100644 index 00000000000..445e461a8cb Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-debug-breakpoint.png differ diff --git a/docs/get-started/media/vs-2026/calculator-debug-infinite.png b/docs/get-started/media/vs-2026/calculator-debug-infinite.png new file mode 100644 index 00000000000..ad1be8e0521 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-debug-infinite.png differ diff --git a/docs/get-started/media/vs-2026/calculator-debug-locals.png b/docs/get-started/media/vs-2026/calculator-debug-locals.png new file mode 100644 index 00000000000..fb54d5c544c Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-debug-locals.png differ diff --git a/docs/get-started/media/vs-2026/calculator-divide-zero-fail.png b/docs/get-started/media/vs-2026/calculator-divide-zero-fail.png new file mode 100644 index 00000000000..328fe304fa5 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-divide-zero-fail.png differ diff --git a/docs/get-started/media/vs-2026/calculator-final-verification.png b/docs/get-started/media/vs-2026/calculator-final-verification.png new file mode 100644 index 00000000000..bea2593f699 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-final-verification.png differ diff --git a/docs/get-started/media/vs-2026/calculator-five-plus-five.png b/docs/get-started/media/vs-2026/calculator-five-plus-five.png new file mode 100644 index 00000000000..a06f85c40e0 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-five-plus-five.png differ diff --git a/docs/get-started/media/vs-2026/calculator-hello-world-console.png b/docs/get-started/media/vs-2026/calculator-hello-world-console.png new file mode 100644 index 00000000000..3248255fa59 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-hello-world-console.png differ diff --git a/docs/get-started/media/vs-2026/calculator-hover-tooltip.png b/docs/get-started/media/vs-2026/calculator-hover-tooltip.png new file mode 100644 index 00000000000..7f65a54b48f Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-hover-tooltip.png differ diff --git a/docs/get-started/media/vs-2026/calculator-initial-dialog.png b/docs/get-started/media/vs-2026/calculator-initial-dialog.png new file mode 100644 index 00000000000..ac835a41c1a Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-initial-dialog.png differ diff --git a/docs/get-started/media/vs-2026/calculator-name-project.png b/docs/get-started/media/vs-2026/calculator-name-project.png new file mode 100644 index 00000000000..92e3c8e57f9 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-name-project.png differ diff --git a/docs/get-started/media/vs-2026/calculator-set-breakpoint.png b/docs/get-started/media/vs-2026/calculator-set-breakpoint.png new file mode 100644 index 00000000000..5d63205bdb7 Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-set-breakpoint.png differ diff --git a/docs/get-started/media/vs-2026/calculator-solution-explorer.png b/docs/get-started/media/vs-2026/calculator-solution-explorer.png new file mode 100644 index 00000000000..65de83b604b Binary files /dev/null and b/docs/get-started/media/vs-2026/calculator-solution-explorer.png differ diff --git a/docs/get-started/media/vs-2026/git-add-source-control.png b/docs/get-started/media/vs-2026/git-add-source-control.png new file mode 100644 index 00000000000..20a3d180b4f Binary files /dev/null and b/docs/get-started/media/vs-2026/git-add-source-control.png differ diff --git a/docs/get-started/media/vs-2026/git-create-repository.png b/docs/get-started/media/vs-2026/git-create-repository.png new file mode 100644 index 00000000000..e3a1d7f324a Binary files /dev/null and b/docs/get-started/media/vs-2026/git-create-repository.png differ diff --git a/docs/get-started/media/vs-2026/git-new-private-repository-status-details.png b/docs/get-started/media/vs-2026/git-new-private-repository-status-details.png new file mode 100644 index 00000000000..e9aa279c45e Binary files /dev/null and b/docs/get-started/media/vs-2026/git-new-private-repository-status-details.png differ diff --git a/docs/get-started/media/vs-2026/visual-studio-installer-cpp-workload.png b/docs/get-started/media/vs-2026/visual-studio-installer-cpp-workload.png new file mode 100644 index 00000000000..c742e014d68 Binary files /dev/null and b/docs/get-started/media/vs-2026/visual-studio-installer-cpp-workload.png differ diff --git a/docs/get-started/media/vs-installer-individual-components.png b/docs/get-started/media/vs-installer-individual-components.png deleted file mode 100644 index 30c65048f6c..00000000000 Binary files a/docs/get-started/media/vs-installer-individual-components.png and /dev/null differ diff --git a/docs/get-started/media/vs-installer-installation-locations.png b/docs/get-started/media/vs-installer-installation-locations.png deleted file mode 100644 index 5929045cb9a..00000000000 Binary files a/docs/get-started/media/vs-installer-installation-locations.png and /dev/null differ diff --git a/docs/get-started/media/vs-installer-workloads.png b/docs/get-started/media/vs-installer-workloads.png deleted file mode 100644 index 4f575c27412..00000000000 Binary files a/docs/get-started/media/vs-installer-workloads.png and /dev/null differ diff --git a/docs/get-started/media/vs2022-installer-workloads.png b/docs/get-started/media/vs2022-installer-workloads.png deleted file mode 100644 index 020d57cb6b5..00000000000 Binary files a/docs/get-started/media/vs2022-installer-workloads.png and /dev/null differ diff --git a/docs/get-started/tutorial-console-cpp.md b/docs/get-started/tutorial-console-cpp.md index 608ab706e06..5f577d958f9 100644 --- a/docs/get-started/tutorial-console-cpp.md +++ b/docs/get-started/tutorial-console-cpp.md @@ -1,46 +1,47 @@ --- title: "Create a console calculator in C++" -description: "Create a Hello World console app and a calculator app in Visual Studio C++" +description: Learn how to create and troubleshoot a Hello World console app and a calculator app in Visual Studio using C++. ms.custom: "acquisition, mvc" -ms.date: 10/08/2024 +ms.date: 04/28/2026 ms.topic: "tutorial" ms.devlang: "cpp" +#customer intent: As a developer working in C++, I want a straight-forward starter project to understand how to use Visual Studio for development. --- # Create a console calculator in C++ ::: moniker range=">=msvc-160" -The usual starting point for a C++ programmer is a "Hello, world!" application that runs on the command line. You start with that in this article, and then move on to something more challenging: a calculator app. +The usual starting point for a C++ programmer is a "Hello, world!" application that runs on the command line. You start with that app in this article, and then move on to something more challenging: a calculator app. ## Prerequisites -- Visual Studio with the **Desktop development with C++** workload installed and running on your computer. To install it, see [Install C++ support in Visual Studio](../build/vscpp-step-0-installation.md). -- This tutorial demonstrates a feature called edit and continue which allows you to make changes to your code while the app is running. To enable edit and continue, from the main menu select **Tools** > **Options** > **Debugging** > **General** and ensure that **Require source files to exactly match the original version** is checked. +- Visual Studio with the **Desktop development with C++** workload installed. For more information, see [Install C++ support in Visual Studio](../build/vscpp-step-0-installation.md). +- This tutorial demonstrates a feature called *edit and continue* which allows you to make changes to your code while the app is running. To enable edit and continue, from the main menu select **Tools** > **Options** > **Debugging** > **General** and select **Require source files to exactly match the original version**. ## Create your app project -Visual Studio uses *projects* to organize the code for an app, and *solutions* to organize one or more projects. A project contains all the options, configurations, and rules used to build an app. It also manages the relationship between all the project's files and any external files. To create your app, first, create a new project and solution. +Visual Studio uses *projects* to organize the code for an app, and *solutions* to organize one or more projects. A project contains the options, configurations, and rules used to build an app. It also manages the relationship between the project's files and any external files. To create your app, first, create a new project and solution. -1. Start Visual Studio--the Visual Studio Start dialog box appears. Select **Create a new project** to get started. +1. Start Visual Studio. The Visual Studio Start dialog appears. Select **Create a new project**. - :::image type="complex" source="./media/calc-vs2022-initial-dialog.png" alt-text="Screenshot of dialog that appears when Visual Studio 2022 starts."::: + :::image type="complex" source="./media/vs-2026/calculator-initial-dialog.png" alt-text="Screenshot of dialog that appears when Visual Studio starts with Create a new project highlighted."::: The dialog has options to clone a repository, open a project or solution, open a local folder, and create a new project." :::image-end::: -1. In the **Create a new project** dialog, set the language dropdown to **C++**, set the platform dropdown to **Windows**, select **Console App** from the list of project types, then select **Next**. +1. In the **Create a new project** dialog, set the language to **C++**, set the platform to **Windows**, select **Console App** from the list of project types, then select **Next**. - :::image type="complex" source="./media/calc-vs2022-choose-console-app.png" alt-text="Screenshot of the Visual Studio Create a new project dialog."::: - The language dropdown is set to C++, the platform dropdown is set to Windows, and project types like Empty Project, Console App, CMake Project, Windows Desktop Wizard, and so on, appear in the list of project types." + :::image type="complex" source="./media/vs-2026/calculator-choose-console-app.png" alt-text="Screenshot of the Visual Studio Create a new project dialog with Console App highlighted."::: + The language is set to C++, the platform is set to Windows, and project types like Empty Project, Console App, CMake Project, and Windows Desktop Wizard, appear in the list of project types." :::image-end::: > [!Important] > Make sure you select the C++ version of the **Console App** template. It has the **C++**, **Windows**, and **Console** tags, and the icon has "++" in the corner. -1. In the **Configure your new project** dialog box, select the **Project name** text box, name your new project *CalculatorTutorial*, then select **Create**. +1. In **Configure your new project**, select the **Project name** text box, name your new project *CalculatorTutorial*, then select **Create**. - :::image type="content" source="./media/calc-vs2019-name-your-project.png" alt-text="Screenshot of the Visual Studio Configure your new project dialog. It has fields for project name, project location, and Solution name."::: + :::image type="content" source="./media/vs-2026/calculator-name-project.png" alt-text="Screenshot of the Visual Studio Configure your new project dialog, which has fields for project name, project location, and Solution name."::: - An empty C++ Windows console application 'Hello World' app is created. Console applications use a Windows console window to display output and accept user input. In Visual Studio, an editor window opens and shows the generated code: + An empty C++ Windows console application "Hello World" app is created. Console applications use a Windows console window to display output and accept user input. In Visual Studio, an editor window opens and shows the generated code: ```cpp // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there. @@ -69,13 +70,13 @@ Visual Studio uses *projects* to organize the code for an app, and *solutions* t The template for a new Windows console application creates a simple C++ "Hello World" app. At this point, you can see how Visual Studio builds and runs the apps you create right from the IDE. -1. To build your project, select **Build Solution** from the **Build** menu. The **Output** window shows the results of the build process. +1. To build your project, from the **Build** menu, select **Build Solution**. The **Output** window shows the results of the build process. - :::image type="content" source="./media/calc-vs2019-build-your-project.png" alt-text="Screenshot of the Visual Studio Output window. It's displaying a message that the build succeeded."::: + :::image type="content" source="./media/vs-2026/calculator-build-project.png" alt-text="Screenshot of the Visual Studio Output window, displaying a message that the build succeeded."::: 1. To run the code, on the menu bar, select **Debug** > **Start without debugging** (Ctrl+F5). - :::image type="content" source="./media/calc-vs2019-hello-world-console.png" alt-text="Screenshot of the Visual Studio Debug Console displaying the output of the application: Hello World!"::: + :::image type="content" source="./media/vs-2026/calculator-hello-world-console.png" alt-text="Screenshot of the Visual Studio Debug Console displaying the output of the application: Hello World!"::: A console window opens and your app runs within it. @@ -85,11 +86,11 @@ The template for a new Windows console application creates a simple C++ "Hello W 1. Press a key to dismiss the console window and return to Visual Studio. -You now have the tools to build and run your app after every change, to verify that the code still works as you expect. Later, we show you how to debug it if it doesn't. +You now have the tools to build and run your app after every change, to verify that the code still works as you expect. Later, you learn how to debug the code if it doesn't. ## Edit the code -Now let's modify the code in this template to be a calculator app. +Now modify the code in this template to be a calculator app. 1. Replace the contents of the *`CalculatorTutorial.cpp`* file with the following code so that it matches this example: @@ -122,41 +123,41 @@ Now let's modify the code in this template to be a calculator app. > Understanding the code: > - > - The `#include` statement brings in code in other files. Sometimes, you may see a filename surrounded by angle brackets like ``. The angle brackets instruct the compiler to look for the `iostream` header file first in the standard system directories, and if not found, to look in directories specific to the project. Other times, you may see a filename surrounded by quotes like `"someHeader.h"`. The quotes instruct the compiler to skip looking in the standard system directories and instead only look in directories specific to the project. - > - The `using namespace std;` tells the compiler to expect code from the C++ Standard Library to be used in this file. Without this line, each keyword from the library would have to be preceded with `std::` to denote its scope. For instance, without that line, each reference to `cout` would be written as `std::cout`. The **`using`** statement is added to make it more convenient to access code in another namespace. + > - The `#include` statement brings in code in other files. Sometimes, you might see a filename surrounded by angle brackets like ``. The angle brackets instruct the compiler to look for the `iostream` header file first in the standard system directories, and if not found, to look in directories specific to the project. Other times, you might see a filename surrounded by quotes like `"someHeader.h"`. The quotes instruct the compiler to skip looking in the standard system directories and instead only look in directories specific to the project. + > - The `using namespace std;` tells the compiler to expect code from the C++ Standard Library to be used in this file. Without this line, each keyword from the library would have to be preceded with `std::` to denote its scope. For instance, without that line, each reference to `cout` would be written as `std::cout`. The `using` statement is added to make it more convenient to access code in another namespace. > - The `cout` keyword is used to print to standard output in C++. The `<<` operator tells the compiler to send whatever is to the right of it to the standard output. - > - The `endl` keyword is like the Enter key; it ends the line and moves the cursor to the next line. It's a better practice to put a `\n` inside the string (contained by `""`) to do the same thing because `endl` always flushes the buffer which can hurt the performance of the program. But since this is a very small app, `endl` is used instead. + > - The `endl` keyword is like the Enter key. It ends the line and moves the cursor to the next line. It's a better practice to put a `\n` inside the string (contained by `""`) to do the same thing because `endl` always flushes the buffer which can hurt the performance of the program. Since this is a very small app, `endl` is used instead. > - All C++ statements must end with semicolons and all C++ applications must contain a `main()` function. This function is what the program runs at the start. All code must be accessible from `main()` in order to be used. -1. To save the file, press **Ctrl+S**, or select the floppy disk icon in the toolbar under the menu bar. +1. To save the file, press **Ctrl**+**S**, or select the floppy disk icon in the toolbar under the menu bar. -1. To run the application, press **Ctrl+F5** or go to the **Debug** menu and select **Start Without Debugging**. You should see a console window appear that looks like this. +1. To run the application, press **Ctrl**+**F5** or go to the **Debug** menu and select **Start Without Debugging**. You should see a console window appear. 1. Close the console window when you're done. ## Add code to do some math -A class is like a blueprint for an object that does something. In this case, we define a calculator class to contain the math logic. +A class is like a blueprint for an object that does something. In this case, define a calculator class to contain the math logic. ### Add a Calculator class -1. Go to the **Project** menu and select **Add Class**. In the **Class Name** edit box, enter *Calculator*. Select **OK**. +1. Go to the **Project** menu and select **Add Class**. For **Class Name**, enter *Calculator*. Select **OK**. - :::image type="complex" source="./media/calc-vs2022-create-calculator-class.png" alt-text="Screenshot of the Visual Studio Add Class dialog box."::: + :::image type="complex" source="./media/vs-2026/calculator-create-calculator-class.png" alt-text="Screenshot of the Visual Studio Add Class dialog box."::: The class name field contains the text calculator. The .h file field contains Calculator.h. The .cpp file field contains Calculator.cpp. The base class field is empty. The options for inline, and Managed are unchecked. :::image-end::: - Two new files get added to your project. To save all your changed files at once, press **Ctrl+Shift+S**. It's a keyboard shortcut for **File** > **Save All**. There's also a toolbar button for **Save All**, an icon of two floppy disks, found beside the **Save** button. In general, it's good practice to do **Save All** frequently, so you don't miss saving any changes. + Two new files get added to your project. To save all your changed files at once, press **Ctrl**+**Shift**+**S**. It's a keyboard shortcut for **File** > **Save All**. There's also a toolbar button for **Save All**, an icon of two floppy disks, found beside the **Save** button. In general, it's good practice to do **Save All** frequently, so you don't miss saving any changes. - The **Add Class** wizard creates `.h` and `.cpp` files that have the same name as the class. You can see a full list of your project files in the **Solution Explorer** window, visible on the side of the IDE. If the window isn't visible, open it from the menu bar via **View** > **Solution Explorer**. + The **Add Class** dialog creates `.h` and `.cpp` files that have the same name as the class. You can see a full list of your project files in the **Solution Explorer** window, visible on the side of the IDE. If the window isn't visible, open it from the menu bar by selecting **View** > **Solution Explorer**. - :::image type="complex" source="./media/calc-vs2019-solution-explorer.png" alt-text="Screenshot of the Visual Studio Solution Explorer window."::: + :::image type="complex" source="./media/vs-2026/calculator-solution-explorer.png" alt-text="Screenshot of the Visual Studio Solution Explorer window."::: The calculator tutorial project has a header files node containing Calculator.h. A Source Files node contains Calculator.cpp and CalculatorTutorial.cpp. Nodes for references, external dependencies, and resource files are visible but closed. :::image-end::: - You can open a file by double-clicking it in the **Solution Explorer** window. Double-click `Calculator.h` to open it. + You can open a file by double-clicking it in the **Solution Explorer** window. To open `Calculator.h`, double-click it. -1. Replace the contents of **`Calculator.h`** with the following code so that the file now looks like this: +1. Replace the contents of `Calculator.h` with the following code so that the file now looks like this: ```cpp #pragma once @@ -171,21 +172,21 @@ A class is like a blueprint for an object that does something. In this case, we > > - This code declares a new function called `Calculate`, which handles math operations for addition, subtraction, multiplication, and division. > - C++ code is organized into *header* (`.h`) files and *source* (`.cpp`) files. Some other file extensions are supported by various compilers, but these are the main ones to know about. Functions and variables are normally *declared*, that is, given a name and a type, in header files, and *implemented*, or given a definition, in source files. To access code defined in another file, you can use `#include "filename.h"`, where `filename.h` is the name of the file that declares the variables or functions you want to use. - > - It's good practice to organize your code into different files based on what it does, so it's easy to find the code you need later. In our case, we define the `Calculator` class separately from the file containing the `main()` function, but we plan to reference the `Calculator` class in `main()`. + > - It's good practice to organize your code into different files based on what it does, so it's easy to find the code you need later. In this case, you define the `Calculator` class separately from the file containing the `main()` function, but you plan to reference the `Calculator` class in `main()`. -1. A green squiggle appears under `Calculate` because although the `Calculate` function is *declared*, it isn't *defined*. Hover over `Calculate`, click the down arrow on the screwdriver icon, and select **Create definition of 'Calculate' in `Calculator.cpp`**. +1. A green squiggle appears under `Calculate` because although the `Calculate` function is *declared*, it isn't *defined*. Hover over `Calculate`, select the down arrow on the screwdriver icon, and select **Create definition of 'Calculate' in `Calculator.cpp`**. - :::image type="content" source="./media/calc-vs2022-create-definition.png" alt-text="Screenshot of a screwdriver dropdown in the Visual Studio editor window. The option 'Create definition of Calculate in Calculator.cpp' is highlighted."::: + :::image type="content" source="./media/vs-2026/calculator-create-definition.png" alt-text="Screenshot of a screwdriver dropdown in the Visual Studio editor window with the option 'Create definition of Calculate in Calculator.cpp' highlighted."::: - This code is added to *`Calculator.cpp`*: + This code is added to `Calculator.cpp`: - :::image type="complex" source="./media/calc-vs2022-ctor-definition.png" alt-text="Screenshot of the Visual Studio editor showing the definition of the 'Calculate' function."::: + :::image type="complex" source="./media/vs-2026/calculator-constructor.png" alt-text="Screenshot of the Visual Studio editor showing the definition of the 'Calculate' function."::: The definition of the function is: double Calculator::Calculate( double x, char oper, double y) { return 0.0; } :::image-end::: Currently, it just returns 0.0. Let's change that. -1. Switch to the *`Calculator.cpp`* file in the editor window. Replace the contents of *`Calculator::Calculate(double x, char oper, double y)`* with: +1. Switch to the `Calculator.cpp` file in the editor window. Replace the contents of `Calculator::Calculate(double x, char oper, double y)` with: ```cpp double Calculator::Calculate(double x, char oper, double y) @@ -210,14 +211,14 @@ A class is like a blueprint for an object that does something. In this case, we > > - The function `Calculate` takes a number, an operator, and a second number. Then it performs the requested operation on the two numbers. > - The `switch` statement checks which operator was provided, and executes the case corresponding to that operation. The `default:` case is a fallback in case the user types an operator that isn't handled by any of the preceding `case` statements. It's best to handle invalid user input in a more elegant way, but this is beyond the scope of this tutorial. - > - The **`double`** keyword denotes a type of number that supports decimals. This type of number is called a floating-point number, and `double` means a floating point number that has extra precision. This way, the calculator can handle both decimal math and integer math. The `Calculate` function is required to always return a double-precision floating point number due to the **`double`** at the start of the code (this denotes the function's return type), which is why we return 0.0 in the default case. + > - The `double` keyword denotes a type of number that supports decimals. This type of number is called a *floating-point number*, and `double` means a floating point number that has extra precision. This way, the calculator can handle both decimal math and integer math. The `Calculate` function is required to always return a double-precision floating point number due to the `double` at the start of the code (this denotes the function's return type), which is why the program returns 0.0 in the default case. > - The `.h` file declares the function *prototype*, which tells the compiler upfront what parameters it requires, and what return type to expect from it. The `.cpp` file has all the implementation details of the function. If you build and run the code again at this point, it immediately exits after asking which operation to perform. So, modify the `main` function to do multiple calculations. ### Call the `Calculator` class member functions -1. Update the `main` function in *`CalculatorTutorial.cpp`* as follows: +1. Update the `main` function in `CalculatorTutorial.cpp` as follows: ```cpp // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there. @@ -253,10 +254,10 @@ If you build and run the code again at this point, it immediately exits after as > Understanding the code > - > - Since C++ programs always start at the `main()` function, we need to call our other code from there, so an `#include` statement is needed to make that code visible to our `main()` function. + > - Since C++ programs always start at the `main()` function, you need to call other code from there, so an `#include` statement is needed to make that code visible to our `main()` function. > - The variables `x`, `y`, `oper`, and `result` are declared to store the first number, second number, operator, and final result, respectively. It's always good practice to give them some initial values to avoid undefined behavior, which is what is done here. - > - The `Calculator c;` line declares an object named `c` as an instance of the `Calculator` class. The class itself is just a blueprint for how calculators work; the object is the specific calculator that does the math. - > - The `while (true)` statement is a loop. The code inside the loop executes over and over again as long as the condition inside the `()` holds true. Since the condition is simply listed as **`true`**, it's always true, so the loop runs forever. To close the program, the user must manually close the console window. Otherwise, the program always waits for new input. + > - The `Calculator c;` line declares an object named `c` as an instance of the `Calculator` class. The class itself is just a blueprint for how calculators work. The object is the specific calculator that does the math. + > - The `while (true)` statement is a loop. The code inside the loop runs over and over again as long as the condition inside the `()` holds true. Since the condition is simply listed as **`true`**, it's always true, so the loop runs forever. To close the program, the user must manually close the console window. Otherwise, the program always waits for new input. > - The `cin` keyword accepts input from the user. The input stream is smart enough to process a line of text entered in the console window and place it inside each of the variables listed, in order. > - The `c.Calculate(x, oper, y);` expression calls the `Calculate` function defined earlier, and supplies the entered input values and the requested operation. The function then returns a number that is stored in `result`. > - Finally, `result` is printed to the console and the user sees the result of the calculation. @@ -265,73 +266,73 @@ If you build and run the code again at this point, it immediately exits after as Now test the program again to make sure everything works properly. -1. Press **Ctrl+F5** to rebuild and start the app. +1. Press **Ctrl**+**F5** to rebuild and start the app. 1. Enter `5+5`, and press **Enter**. Verify that the result is 10. - :::image type="complex" source="./media/calc-vs2019-five-plus-five.png" alt-text="Screenshot of a command window showing the results of running the program."::: + :::image type="complex" source="./media/vs-2026/calculator-five-plus-five.png" alt-text="Screenshot of a command window showing the results of running the program."::: The app output the message: Please enter the operation to perform. Format: a+b | a-b | a*b | a/b. The user entered 5+5. The app output: Result of 5+5 is: 10 :::image-end::: 1. Stop the program by closing the console window. ## Debug the app -Since the user is free to type anything into the console window, let's make sure the calculator handles unexpected input. Instead of running the program, let's debug it so we can inspect what it's doing step-by-step. +Since the user is free to type anything into the console window, make sure the calculator handles unexpected input. Instead of running the program, debug it so you can see what it's doing step-by-step. ### Run the app in the debugger -1. In `CalcuatorTutorial.cpp`, set a breakpoint on the line: `result = c.Calculate(x, oper, y);`. To set the breakpoint, click next to the line in the gray vertical bar along the left edge of the editor window so that a red dot appears. +1. In `CalcuatorTutorial.cpp`, set a breakpoint on the line: `result = c.Calculate(x, oper, y);`. To set the breakpoint, select next to the line in the vertical bar along the left edge of the editor window so that a red dot appears. - :::image type="content" source="./media/calc-vs2022-set-breakpoint.png" alt-text="Screenshot of the Visual Studio editor. A red dot representing a breakpoint appears on the line: result = c.Calculate(x, oper, y)."::: + :::image type="content" source="./media/vs-2026/calculator-set-breakpoint.png" alt-text="Screenshot of the Visual Studio editor. A red dot representing a breakpoint appears on the line: result = c.Calculate(x, oper, y)."::: - Now when we debug the program, execution pauses at that line. We already have a rough idea that the program works for simple cases. Since we don't want to pause execution every time we call `Calculate()`, let's make the breakpoint conditional. + Now when you debug the program, execution pauses at that line. You already have a rough idea that the program works for simple cases. Since you don't want to pause execution every time you call `Calculate()`, make the breakpoint conditional. -1. Right-click the red dot that represents the breakpoint, and select **Conditions**. In the edit box for the condition, enter `(y == 0) && (oper == '/')`. Select the **Close** button to save the breakpoint condition. +1. Right-click the red dot that represents the breakpoint, and select **Conditions**. In the edit box for the condition, enter `(y == 0) && (oper == '/')`. Select **Close** to save the breakpoint condition. - :::image type="complex" source="./media/calc-vs2022-conditional-breakpoint.png" alt-text="Screenshot of a set breakpoint"::: + :::image type="complex" source="./media/vs-2026/calculator-conditional-breakpoint.png" alt-text="Screenshot of a set breakpoint."::: The breakpoint is on the line: result = c dot Calculate ( x, oper, y). 'Conditions...' The Condition option is checked. The Conditions dropdown is set to "Conditional Expression". The condition dropdown is set to "Is true". The condition is set to y == 0 && oper == '/'. :::image-end::: Now, execution pauses at the breakpoint when the app tries to divide by 0. -1. To debug the program, press **F5**, or select the **Local Windows Debugger** debugger toolbar button that has the green arrow icon. In your console app, if you enter something like "5 - 0", the program behaves normally and keeps running. However, if you type "10 / 0", it pauses at the breakpoint. You can put any number of spaces between the operator and numbers: `cin` is smart enough to parse the input appropriately. +1. To debug the program, press **F5**, or select the **Local Windows Debugger** debugger toolbar button that has the green arrow icon. In your console app, if you enter something like *5 - 0*, the program behaves normally and keeps running. However, if you type *10 / 0*, it pauses at the breakpoint. You can put any number of spaces between the operator and numbers: `cin` is smart enough to parse the input appropriately. - :::image type="content" source="./media/calc-vs2022-debug-breakpoint.png" alt-text="Screenshot of Visual Studio editor. Program execution halted at the conditional breakpoint on the line: result = c.Calculate(x, oper, y);."::: + :::image type="content" source="./media/vs-2026/calculator-debug-breakpoint.png" alt-text="Screenshot of Visual Studio editor with program execution halted at the conditional breakpoint on the line: result = c.Calculate(x, oper, y);."::: ### Useful windows in the debugger -When you debug your code, you may notice that some new windows appear. These windows can assist your debugging experience. Take a look at the **Autos** window. The **Autos** window shows you the current values of variables used at least three lines before and up to the current line. If you don't see the **Autos** window, from the main menu select **Debug** > **Windows** > **Autos**. +When you debug your code, you might notice that some new windows appear. These windows can assist your debugging experience. Look at the **Autos** window. The **Autos** window shows you the current values of variables used at least three lines before and up to the current line. If you don't see the **Autos** window, from the main menu select **Debug** > **Windows** > **Autos**. - :::image type="complex" source="./media/calc-vs2022-autos.png" alt-text="Screenshot of the Visual Studio debugger Autos window."::: + :::image type="complex" source="./media/vs-2026/calculator-autos.png" alt-text="Screenshot of the Visual Studio debugger Autos window."::: The value of oper is 47 '/', result is 5, x is 10, and y is 0. :::image-end::: -To see all of the variables from that function, switch to the **Locals** window. Because this is a small function, the Autos and Locals window show the same variables. But you can modify the values of these variables in the Locals window while debugging to see what effect they would have on the program. In this case, we leave them alone. Open the **Locals** window by selecting **Locals** at the bottom of the **Autos** window, or by selecting from the main menu **Debug** > **Windows** > **Locals**. +To see all of the variables from that function, switch to the **Locals** window. Because this function is small, the Autos and Locals windows show the same variables. You can modify the values of these variables in the Locals window while debugging to see what effect they would have on the program. In this case, leave them alone. Open the **Locals** window by selecting **Locals** at the bottom of the **Autos** window, or by selecting from the main menu **Debug** > **Windows** > **Locals**. - :::image type="complex" source="./media/calc-vs2019-debug-locals.png" alt-text="Screenshot of the Locals window in Visual Studio, displaying the current values of local variables while debugging."::: + :::image type="complex" source="./media/vs-2026/calculator-debug-locals.png" alt-text="Screenshot of the Locals window in Visual Studio, displaying the current values of local variables while debugging."::: The value of oper is 47 '/', result is 0, x is 10, and y is 0. :::image-end::: -You can also hover over variables in the code to see their current values at the point where execution is currently paused. Make sure the editor window is in focus by clicking on it first. +You can also hover over variables in the code to see their current values at the point where execution is currently paused. Make sure the editor window is in focus by selecting it first. - :::image type="content" source="./media/calc-vs2019-hover-tooltip.png" alt-text="Screenshot of a tooltip showing the value of the variable 'oper', which is 47 or '/'."::: + :::image type="content" source="./media/vs-2026/calculator-hover-tooltip.png" alt-text="Screenshot of a tooltip showing the value of the variable 'oper', which is 47 or '/'."::: ### Continue debugging -1. The yellow arrow on the left shows the current point of execution. The current line calls `Calculate`, so press **F11** to **Step Into** the function. Now you're executing code in the body of the `Calculate` function. Be careful with **Step Into** because it steps into any functions on the line you're on, including standard library functions. It's fine to step into the standard library, but you may be more interested in focusing on your code instead of library code. +1. The yellow arrow on the left shows the current point of execution. The current line calls `Calculate`, so press **F11** to **Step Into** the function. Now you're executing code in the body of the `Calculate` function. Be careful with **Step Into** because it steps into any functions on the line you're on, including standard library functions. It's fine to step into the standard library, but you might be more interested in focusing on your code instead of library code. -1. Now that the point of execution is at the start of the `Calculate` function, press **F10** to move to the next line in the program's execution. **F10** is also known as **Step Over**. You can use **Step Over** to move from line to line, without delving into the details of what is occurring in each part of the line. In general, you should use **Step Over** instead of **Step Into** unless you want to dive more deeply into code that is being called from elsewhere (as you did to reach the body of `Calculate`). +1. Now that the point of execution is at the start of the `Calculate` function, press **F10** to move to the next line in the program's execution. **F10** is also known as **Step Over**. You can use **Step Over** to move from line to line, without delving into the details of what is occurring in each part of the line. In general, you should use **Step Over** instead of **Step Into** unless you want to dive more deeply into code that's being called from elsewhere as you did to reach the body of `Calculate`. 1. Continue using **F10** to **Step Over** each line until you get back to the `main()` function in the other file, and stop on the `cout` line. - The program is doing what's expected: it takes the first number, and divides it by the second. On the `cout` line, hover over the `result` variable or take a look at `result` in the **Autos** window. Its value is `inf`, which doesn't look right. + The program is doing what you expect: it takes the first number, and divides it by the second. On the `cout` line, hover over the `result` variable or take a look at `result` in the **Autos** window. Its value is `inf`, which doesn't look right. - :::image type="complex" source="./media/calc-vs2022-debug-inf.png" alt-text="Screenshot of debugging the calculator."::: + :::image type="complex" source="./media/vs-2026/calculator-debug-infinite.png" alt-text="Screenshot of debugging the calculator."::: The current statement in the debugger is cout << "Result is: " << result << endl; In the autos window, result is inf. :::image-end::: - Let's fix it. The `cout` line outputs whatever value is stored in `result`, so when you step one more line forward using **F10**, the console window displays: + You can fix it. The `cout` line outputs whatever value is stored in `result`. When you step one more line forward using **F10**, the console window displays: - :::image type="complex" source="./media/calc-divide-by-zero-fail.png" alt-text="Screenshot of the Visual Studio Debug Console displaying the result of a division by zero operation."::: + :::image type="complex" source="./media/vs-2026/calculator-divide-zero-fail.png" alt-text="Screenshot of the Visual Studio Debug Console displaying the result of a division by zero operation."::: The app outputs: Please enter the operation to perform. Format: a+b | a-b | a*b | a/b. The user entered 5-0. The app output: Result is: 5. The user entered 10/0. The app output: Result is: inf :::image-end::: @@ -339,9 +340,9 @@ You can also hover over variables in the code to see their current values at the ### Fix the "divide by zero" error -Let's handle division by zero more gracefully so that it's easier for the user to understand the problem. +You can handle division by zero more gracefully so that it's easier for the user to understand the problem. -1. Make the following changes in *`CalculatorTutorial.cpp`*. You can leave the program running as you edit, thanks to a debugger feature called **Edit and Continue**. Add an `if` statement following `cin >> x >> oper >> y;` to check for division by zero and output a message to the user if it happens. Otherwise, the result is printed. +1. Make the following changes in *`CalculatorTutorial.cpp`*. You can leave the program running as you edit, thanks to a debugger feature called *Edit and Continue*. Add an `if` statement following `cin >> x >> oper >> y;` to check for division by zero and output a message to the user if it happens. Otherwise, the result is printed. ```cpp // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there. @@ -384,19 +385,21 @@ Let's handle division by zero more gracefully so that it's easier for the user t 1. Press **F5** once. Program execution continues until it has to pause to ask for user input. Enter `10 / 0` again. Now, a more helpful message is printed. The user is asked for more input, and the program continues executing normally. - :::image type="complex" source="./media/calc-final-verification.png" alt-text="Screenshot of a console window showing the final output after implementing changes to handle division by zero."::: + :::image type="complex" source="./media/vs-2026/calculator-final-verification.png" alt-text="Screenshot of a console window showing the final output after implementing changes to handle division by zero."::: The console window displays two lines: 10 / 0 Result is: inf, followed by, 10 / 0 Math error: Attempted to divide by zero. :::image-end::: > [!Note] - > When you edit code while in debugging mode, there's a risk of code becoming stale. This happens when the debugger is still running your old code, and has not yet updated it with your changes. The debugger displays a dialog to inform you when this happens. Sometimes, you may need to press **F5** to refresh the code being executed. In particular, if you make a change inside a function while the point of execution is inside that function, you need to step out of the function, then back into it again to get the updated code. If that doesn't work and you see an error message, you can stop debugging by clicking on the red square in the toolbar under the menus at the top of the IDE, then start debugging again by entering **F5** or by choosing the green "play" arrow beside the stop button on the toolbar. + > When you edit code while in debugging mode, there's a risk of code becoming stale. This happens when the debugger is still running your old code, and has not yet updated it with your changes. The debugger displays a dialog to inform you when this happens. Sometimes, you need to press **F5** to refresh the code being executed. + > + > In particular, if you make a change inside a function while the point of execution is inside that function, you need to step out of the function, then back into it again to get the updated code. If that doesn't work and you see an error message, select the red square to stop debugging, then start debugging again by pressing **F5** or by choosing the green play arrow beside the stop button on the toolbar. > > Another reason edit and continue may fail is if you see a message that says "The Require source files to exactly match the original version setting under Debug->Options->General needs to be enabled..." To fix this, from the main menu select **Tools** > **Options** > **Debugging** > **General** and ensure that **Require source files to exactly match the original version** is checked. > Understanding the Run and Debug shortcuts > - > - **F5**, or **Debug** > **Start Debugging**, starts a debugging session, if one isn't already active, and runs the program until a breakpoint is hit or the program needs user input. If no user input is needed and no breakpoint is available to hit, the program terminates and the console window closes itself when the program finishes running. If your program outputs to the console, use **Ctrl+F5** or set a breakpoint before you press **F5** to keep the window open. - > - **Ctrl+F5**, or **Debug** > **Start Without Debugging**, runs the application without going into debug mode. This is slightly faster than debugging, and the console window stays open after the program finishes executing. + > - **F5**, or **Debug** > **Start Debugging**, starts a debugging session, if one isn't already active, and runs the program until a breakpoint is hit or the program needs user input. If no user input is needed and no breakpoint is available to hit, the program terminates and the console window closes itself when the program finishes running. If your program outputs to the console, use **Ctrl**+**F5** or set a breakpoint before you press **F5** to keep the window open. + > - **Ctrl**+**F5**, or **Debug** > **Start Without Debugging**, runs the application without going into debug mode. This is slightly faster than debugging, and the console window stays open after the program finishes executing. > - **F10**, known as **Step Over**, lets you iterate through code, line-by-line, and visualize how the code is run and what variable values are at each step of execution. > - **F11**, known as **Step Into**, works similarly to **Step Over**, except it steps into any functions called on the line of execution. For example, if the line being executed calls a function, pressing **F11** moves the pointer into the body of the function, so you can follow the function's code being run before coming back to the line you started at. Pressing **F10** steps over the function call and just moves to the next line; the function call still happens, but the program doesn't pause to show you what it's doing. @@ -410,7 +413,7 @@ Let's handle division by zero more gracefully so that it's easier for the user t Congratulations! You completed the code for the calculator app, built and debugged it, and added it to a repo, all in Visual Studio. -## Next steps +## Next step [Learn more about Visual Studio for C++](https://devblogs.microsoft.com/cppblog/getting-started-with-visual-studio-for-c-and-cpp-development/) @@ -418,7 +421,7 @@ Congratulations! You completed the code for the calculator app, built and debugg ::: moniker range=" **New** > **Project**. The **New Project** window opens. -2. On the left sidebar, ensure that **Visual C++** is selected. In the center, select **Console App**. -3. In the **Name** textbox at the bottom, name the new project *CalculatorTutorial*, then select **OK**. +1. On the menu in Visual Studio, select **File** > **New** > **Project**. The **New Project** window opens. +1. On the left sidebar, ensure that **Visual C++** is selected. In the center, select **Console App**. +1. In the **Name** box at the bottom, name the new project *CalculatorTutorial*, then select **OK**. :::image type="complex" source="./media/calc-vs2017-new-project-dialog.png" alt-text="Screenshot of the New Project dialog."::: On the left, Other Languages > Visual C++ is selected. In the center, the Console App project type is selected. The Name text box contains CalculatorTutorial. :::image-end::: - An empty C++ Windows console application 'Hello World' app is created. Console applications use a Windows console window to display output and accept user input. In Visual Studio, an editor window opens and shows the generated code: + An empty C++ Windows console application "Hello World" app is created. Console applications use a Windows console window to display output and accept user input. In Visual Studio, an editor window opens and shows the generated code: ```cpp // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there. @@ -465,11 +468,11 @@ Visual Studio uses *projects* to organize the code for an app, and *solutions* t The template for a new windows console application creates a simple C++ "Hello World" app. At this point, you can see how Visual Studio builds and runs the apps you create right from the IDE. -1. To build your project, select **Build Solution** from the **Build** menu. The **Output** window shows the results of the build process. +1. To build your project, from the **Build** menu, select **Build Solution**. The **Output** window shows the results of the build process. :::image type="content" source="./media/calculator-initial-build-output.png" alt-text="Screenshot of the Visual Studio Output window showing that the build was successful."::: -1. To run the code, on the menu bar, select **Debug**, **Start without debugging** (Ctrl+F5). +1. To run the code, on the menu bar, select **Debug**, **Start without debugging** (**Ctrl**+**F5**). :::image type="content" source="./media/calculator-hello-world-console.png" alt-text="Screenshot of the Visual Studio Debug Console showing the output: Hello World!"::: @@ -481,13 +484,13 @@ The template for a new windows console application creates a simple C++ "Hello W 1. Press a key to dismiss the console window and return to Visual Studio. -You now have the tools to build and run your app after every change, to verify that the code still works as you expect. Later, we show you how to debug it if it doesn't. +You now have the tools to build and run your app after every change, to verify that the code still works as you expect. Later, you learn how to debug it if it doesn't. ## Edit the code -Now let's turn the code in this template to be a calculator app. +Now modify the code in this template to be a calculator app. -1. Replace the contents of the *`CalculatorTutorial.cpp`* file with the following code so that it matches this example: +1. Replace the contents of the `CalculatorTutorial.cpp` file with the following code so that it matches this example: ```cpp // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there. @@ -517,25 +520,25 @@ Now let's turn the code in this template to be a calculator app. > Understanding the code: > - > - The `#include` statement brings in code in other files. Sometimes, you may see a filename surrounded by angle brackets like ``. The angle brackets instruct the compiler to look for the `iostream` header file first in the standard system directories, and if not found, to look in directories specific to the project. Other times, you may see a filename surrounded by quotes like `"someHeader.h"`. The quotes instruct the compiler to skip looking in the standard system directories and instead only look in directories specific to the project. - > - The `using namespace std;` tells the compiler to expect code from the C++ Standard Library to be used in this file. Without this line, each keyword from the library would have to be preceded with `std::` to denote its scope. For instance, without that line, each reference to `cout` would be written as `std::cout`. The **`using`** statement is added to make it more convenient to access code in another namespace. + > - The `#include` statement brings in code in other files. Sometimes, you might see a filename surrounded by angle brackets like ``. The angle brackets instruct the compiler to look for the `iostream` header file first in the standard system directories, and if not found, to look in directories specific to the project. Other times, you might see a filename surrounded by quotes like `"someHeader.h"`. The quotes instruct the compiler to skip looking in the standard system directories and instead only look in directories specific to the project. + > - The `using namespace std;` tells the compiler to expect code from the C++ Standard Library to be used in this file. Without this line, each keyword from the library would have to be preceded with `std::` to denote its scope. For instance, without that line, each reference to `cout` would be written as `std::cout`. The `using` statement is added to make it more convenient to access code in another namespace. > - The `cout` keyword prints to standard output in C++. The `<<` operator tells the compiler to send whatever is to the right of it to the standard output. - > - The `endl` keyword is like the Enter key; it ends the line and moves the cursor to the next line. It's a better practice to put a `\n` inside the string (contained by `""`) to do the same thing because `endl` always flushes the buffer and can hurt the performance of the program. But since this is a very small app, `endl` is used instead. + > - The `endl` keyword is like the Enter key. It ends the line and moves the cursor to the next line. It's a better practice to put a `\n` inside the string (contained by `""`) to do the same thing because `endl` always flushes the buffer and can hurt the performance of the program. But since this is a very small app, `endl` is used instead. > - All C++ statements must end with semicolons and all C++ applications must contain a `main()` function. This function is what the program runs at the start. All code must be accessible from `main()` in order to be used. -1. To save the file, press **Ctrl+S**, or select the floppy disk icon in the toolbar under the menu bar. +1. To save the file, press **Ctrl**+**S**, or select the floppy disk icon in the toolbar under the menu bar. -1. To run the application, press **Ctrl+F5** or go to the **Debug** menu and select **Start Without Debugging**. If you get a pop-up that says **This project is out of date**, you may select **Do not show this dialog again**, and then select **Yes** to build your application. You should see a console window appear that looks like this: +1. To run the application, press **Ctrl**+**F5** or go to the **Debug** menu and select **Start Without Debugging**. If you get a dialog that says **This project is out of date**, you can select **Do not show this dialog again**, and then select **Yes** to build your application. You should see a console window appear that looks like this: :::image type="complex" source="./media/calculator-first-launch.png" alt-text="Screenshot of the calculator app running in a console window."::: - The console app shows the output which is: Calculator Console Application. Please enter the operation to perform. Format: a+b | a-b | a*b | a/b. The process exited with code 0 and there's a message that to automatically close the console when debugging stops, enable Tools > Options > Debugging > Automatically close the console when debugging stops. Lastly, there's a message to press any key to close this window. + The console app shows the output, which is: Calculator Console Application. Please enter the operation to perform. Format: a+b | a-b | a*b | a/b. The process exited with code 0 and there's a message that to automatically close the console when debugging stops, enable Tools > Options > Debugging > Automatically close the console when debugging stops. Lastly, there's a message to press any key to close this window. :::image-end::: 1. Close the console window when you're done. ## Add code to do some math -A class is like a blueprint for an object that does something. In this case, we define a calculator class to contain the math logic. +A class is like a blueprint for an object that does something. In this case, define a calculator class to contain the math logic. ### Add a Calculator class @@ -545,19 +548,19 @@ A class is like a blueprint for an object that does something. In this case, we The class name field contains the text calculator. The .h file field contains Calculator.h. The .cpp file field contains Calculator.cpp. The base class field is empty. The options for inline, and Managed are unchecked. :::image-end::: - A class is like a blueprint for an object that does something. In this case, we define a calculator and how it should work. + A class is like a blueprint for an object that does something. In this case, it defines a calculator and how it should work. - Two new files get added to your project. To save all your changed files at once, press **Ctrl+Shift+S**. It's a keyboard shortcut for **File** > **Save All**. There's also a toolbar button for **Save All**, an icon of two floppy disks, found beside the **Save** button. In general, it's good practice to do **Save All** frequently, so you don't miss any files when you save. + Two new files get added to your project. To save all your changed files at once, press **Ctrl**+**Shift**+**S**. It's a keyboard shortcut for **File** > **Save All**. There's also a toolbar button for **Save All**, an icon of two floppy disks, found beside the **Save** button. In general, it's good practice to do **Save All** frequently, so you don't miss any files when you save. - The **Add Class** wizard creates `.h` and `.cpp` files that have the same name as the class. You can see a full list of your project files in the **Solution Explorer** window, visible on the side of the IDE. If the **Solution Explorer** isn't visible, open it from the menu bar: select **View** > **Solution Explorer**. + The **Add Class** dialog creates `.h` and `.cpp` files that have the same name as the class. You can see a full list of your project files in the **Solution Explorer** window, visible on the side of the IDE. If the **Solution Explorer** isn't visible, open it from the menu bar: select **View** > **Solution Explorer**. :::image type="complex" source="./media/calculator-solution-explorer.png" alt-text="Screenshot of the Visual Studio Solution Explorer window."::: The calculator tutorial project has a header files node containing Calculator.h, stdafx.h, and targetver.h. A Source Files node contains Calculator.cpp, CalculatorTutorial.cpp, and stdafx.cpp. Nodes for references, external dependencies, and resource files are visible but closed. :::image-end::: - You can open a file by double-clicking it in the **Solution Explorer** window. Double-click `Calculator.h` to open it. + You can open a file by double-clicking it in the **Solution Explorer** window. To open `Calculator.h`, double-click it. -1. Replace the contents of **`Calculator.h`** with the following code so that the file now looks like this: +1. Replace the contents of `Calculator.h` the following code so that the file now looks like this: ```cpp #pragma once @@ -572,9 +575,9 @@ A class is like a blueprint for an object that does something. In this case, we > > - This code declares a new function called `Calculate`, which handles math operations for addition, subtraction, multiplication, and division. > - C++ code is organized into *header* (`.h`) files and *source* (`.cpp`) files. Some other file extensions are supported by various compilers, but these are the main ones to know about. Functions and variables are normally *declared*, that is, given a name and a type, in header files, and *implemented*, or given a definition, in source files. To access code defined in another file, you can use `#include "filename.h"`, where `filename.h` is the name of the file that declares the variables or functions you want to use. - > - It's good practice to organize your code into different files based on what it does, so it's easy to find the code you need later. In our case, we define the `Calculator` class separately from the file containing the `main()` function, but we plan to reference the `Calculator` class in `main()`. + > - It's good practice to organize your code into different files based on what it does, so it's easy to find the code you need later. In this case, you define the `Calculator` class separately from the file containing the `main()` function, but you reference the `Calculator` class in `main()`. -1. A green squiggle appears under `Calculate` because although the `Calculate` function is *declared*, it isn't *defined*. Hover over `Calculate`, click the down arrow on the light bulb, and select **Create definition of 'Calculate' in `Calculator.cpp`**. A pop-up appears that gives you a peek of the code change that was made in the other file. The code was added to *`Calculator.cpp`*. +1. A green squiggle appears under `Calculate` because although the `Calculate` function is *declared*, it isn't *defined*. Hover over `Calculate`, select the down arrow on the light bulb, and select **Create definition of 'Calculate' in `Calculator.cpp`**. A pop-up appears that gives you a peek of the code change that was made in the other file. The code was added to *`Calculator.cpp`*. :::image type="content" source="./media/calc-vs2017-create-definition.png" alt-text="Video showing using the light bulb dropdown to select Create definition of Calculate in Calculator.cpp."::: @@ -607,7 +610,7 @@ A class is like a blueprint for an object that does something. In this case, we > > - The function `Calculate` takes a number, an operator, and a second number. Then it performs the requested operation on the two numbers. > - The `switch` statement checks which operator was provided, and executes the case corresponding to that operation. The `default:` case is a fallback in case the user types an operator that isn't handled by any of the preceding `case` statements. It's best to handle invalid user input in a more elegant way, but this is beyond the scope of this tutorial. - > - The **`double`** keyword denotes a type of number that supports decimals. This type of number is called a floating-point number, and `double` means a floating point number that has extra precision. This way, the calculator can handle both decimal math and integer math. The `Calculate` function is required to always return a double-precision floating point number due to the **`double`** at the start of the code (this denotes the function's return type), which is why we return 0.0 in the default case. + > - The `double` keyword denotes a type of number that supports decimals. This type of number is called a **floating-point number**, and `double` means a floating point number that has extra precision. This way, the calculator can handle both decimal math and integer math. The `Calculate` function is required to always return a double-precision floating point number due to the `double` at the start of the code (this denotes the function's return type), which is why the program returns 0.0 in the default case. > - The `.h` file declares the function *prototype*, which tells the compiler upfront what parameters it requires, and what return type to expect from it. The `.cpp` file has all the implementation details of the function. If you build and run the code again at this point, it still exits after asking which operation to perform. Next, modify the `main` function to do some calculations. @@ -649,10 +652,10 @@ If you build and run the code again at this point, it still exits after asking w > Understanding the code > - > - Since C++ programs always start at the `main()` function, we need to call our other code from there, so an `#include` statement is needed to make that code visible to our `main()` function. + > - Since C++ programs always start at the `main()` function, you need to call our other code from there, so an `#include` statement is needed to make that code visible to our `main()` function. > - The variables `x`, `y`, `oper`, and `result` are declared to store the first number, second number, operator, and final result, respectively. It's always good practice to give them some initial values to avoid undefined behavior, which is what is done here. > - The `Calculator c;` line declares an object named `c` as an instance of the `Calculator` class. The class itself is just a blueprint for how calculators work; the object is the specific calculator that does the math. - > - The `while (true)` statement is a loop. The code inside the loop execute over and over again as long as the condition inside the `()` holds true. Since the condition is simply listed as **`true`**, it's always true, so the loop runs forever. To close the program, the user must manually close the console window. Otherwise, the program always waits for new input. + > - The `while (true)` statement is a loop. The code inside the loop execute over and over again as long as the condition inside the `()` holds true. Since the condition is simply listed as `true`, it's always true, so the loop runs forever. To close the program, the user must manually close the console window. Otherwise, the program always waits for new input. > - The `cin` keyword accepts input from the user. The input stream is smart enough to process a line of text entered in the console window and place it inside each of the variables listed, in order. > - The `c.Calculate(x, oper, y);` expression calls the `Calculate` function defined earlier, and supplies the entered input values and the requested operation. The function then returns a number that is stored in `result`. > - Finally, `result` is printed to the console and the user sees the result of the calculation. @@ -661,23 +664,24 @@ If you build and run the code again at this point, it still exits after asking w Test the program again to make sure everything works properly. -1. Press **Ctrl+F5** to rebuild and start the app. +1. Press **Ctrl**+**F5** to rebuild and start the app. 1. Enter `5+5`, and press **Enter**. Verify that the result is 10. - :::image type="content" source="./media/calculator-five-plus-five.png" alt-text="Screenshot of a command window running the Calculator app. It shows that the result of 5 + 5 is 10."::: + :::image type="content" source="./media/calculator-five-plus-five.png" alt-text="Screenshot of a command window running the Calculator app, showing that the result of 5 + 5 is 10."::: + 1. Stop the program by closing the console window. ## Debug the app -Since the user is free to type anything into the console window, let's make sure the calculator handles unexpected input. Instead of running the program, let's debug it instead, so we can inspect what it's doing step-by-step. +Since the user is free to type anything into the console window, make sure the calculator handles unexpected input. Instead of running the program, debug it, so you can see what it's doing step-by-step. ### Run the app in the debugger -1. In `CalcuatorTutorial.cpp`, set a breakpoint on the `result = c.Calculate(x, oper, y);` line. To set the breakpoint, click next to the line in the gray vertical bar along the left edge of the editor window so that a red dot appears. +1. In `CalcuatorTutorial.cpp`, set a breakpoint on the `result = c.Calculate(x, oper, y);` line. To set the breakpoint, select next to the line in the gray vertical bar along the left edge of the editor window so that a red dot appears. :::image type="content" source="./media/calc-vs2017-set-breakpoint.png" alt-text="Screenshot of the user setting a breakpoint on line 23: result = c.Calculate(x, oper, y);."::: - Now when you debug the program, it always pauses execution at that line. We already have a rough idea that the program works for simple cases. Since we don't want to pause execution every time, let's make the breakpoint conditional. + Now when you debug the program, it always pauses execution at that line. You already have a rough idea that the program works for simple cases. Since you don't want to pause execution every time, make the breakpoint conditional. 1. Right-click the red dot that represents the breakpoint, and select **Conditions**. In the edit box for the condition, enter `(y == 0) && (oper == '/')`. Select the **Close** button when you're done to save the breakpoint condition. @@ -685,47 +689,47 @@ Since the user is free to type anything into the console window, let's make sure The breakpoint is on the line: result = c dot Calculate ( x, oper, y). 'Conditions...' The Condition option is checked. The Conditions dropdown is set to "Conditional Expression". The condition dropdown is set to "Is true". The condition is set to y == 0 && oper == '/'. :::image-end::: - Execution will pause at the breakpoint if a division by 0 is attempted. + Execution pauses at the breakpoint if a division by 0 is attempted. -1. To debug the program, press **F5**, or select the **Local Windows Debugger** toolbar button that has the green arrow icon. In your console app, if you enter something like "5 - 0", the program behaves normally and keeps running. However, if you type "10 / 0", it pauses at the breakpoint. You can even put any number of spaces between the operator and numbers; `cin` is smart enough to parse the input appropriately. +1. To debug the program, press **F5**, or select the **Local Windows Debugger** toolbar button that has the green arrow icon. In your console app, if you enter something like *5 - 0*, the program behaves normally and keeps running. However, if you type *10 / 0*, it pauses at the breakpoint. You can even put any number of spaces between the operator and numbers; `cin` is smart enough to parse the input appropriately. - :::image type="complex" source="./media/calc-vs2017-debug-breakpoint.png" alt-text="Video showing the program execution paused at the conditional breakpoint."::: + :::image type="complex" source="./media/calc-vs2017-debug-breakpoint.png" alt-text="Screenshot showing the program execution paused at the conditional breakpoint."::: The user enters 5 - 0. The app outputs: Result is 5. The user then enters 10/0 and because the condition for the conditional breakpoint is met, execution stops on the line: result = c.Calculate(x, oper, y); :::image-end::: ### Useful windows in the debugger -When you debug your code, you may notice that some new windows appear. These windows can assist your debugging experience. Take a look at the **Autos** window. The **Autos** window shows you the current values of variables used at least three lines before and up to the current line. If you don't see the **Autos** window, from the main menu select **Debug** > **Windows** > **Autos**. +When you debug your code, you might notice that some new windows appear. These windows can assist your debugging experience. Take a look at the **Autos** window. The **Autos** window shows you the current values of variables used at least three lines before and up to the current line. If you don't see the **Autos** window, from the main menu, select **Debug** > **Windows** > **Autos**. :::image type="complex" source="./media/calculator-autos.png" alt-text="Screenshot of the Visual Studio debugger Autos window."::: The value of oper is 47 '/', result is 5, x is 10, and y is 0. :::image-end::: -To see all of the variables from that function, switch to the **Locals** window. Because this is a small function, the Autos and Locals window show the same variables. But you can modify the values of these variables while debugging, to see what effect they would have on the program. In this case, we leave them alone. Open the **Locals** window by selecting **Locals** at the bottom of the **Autos** window, or by selecting from the main menu **Debug** > **Windows** > **Locals**. +To see all of the variables from that function, switch to the **Locals** window. Because this function is small, the Autos and Locals window show the same variables. But you can modify the values of these variables while debugging, to see what effect they would have on the program. In this case, leave them alone. Open the **Locals** window by selecting **Locals** at the bottom of the **Autos** window, or by selecting from the main menu **Debug** > **Windows** > **Locals**. :::image type="complex" source="./media/calculator-locals.png" alt-text="Screenshot of the Locals window in Visual Studio, displaying the current values of local variables while debugging."::: The value of oper is 47 '/', result is 0, x is 10, and y is 0. :::image-end::: -You can also hover over variables in the code itself to see their current values where the execution is currently paused. Make sure the editor window is in focus by clicking on it first. +You can also hover over variables in the code itself to see their current values where the execution is currently paused. Select the editor window first to be sure it is in focus. - :::image type="content" source="./media/calc-vs2017-hover-tooltip.png" alt-text="Video demonstrating a tooltip that appears while hovering over the variable y. It displays y's current value, which is 0."::: + :::image type="content" source="./media/calc-vs2017-hover-tooltip.png" alt-text="Screenshot demonstrating a tooltip that appears while hovering over the variable y, which displays y's current value, which is 0."::: ### Continue debugging -1. The yellow arrow on the left shows the current point of execution. The current line calls `Calculate`, so press **F11** to **Step Into** the function, which takes you into the body of the `Calculate` function. Be careful with **Step Into** because it steps into any functions on the line you're on, including standard library functions. It's fine to step into the standard library, but you may be more interested in focusing on your code instead of library code. +1. The yellow arrow on the left shows the current point of execution. The current line calls `Calculate`, so press **F11** to **Step Into** the function, which takes you into the body of the `Calculate` function. Be careful with **Step Into** because it steps into any functions on the line you're on, including standard library functions. It's fine to step into the standard library, but you might be more interested in focusing on your code instead of library code. -1. Now that the point of execution is at the start of the `Calculate` function, press **F10** to move to the next line in the program's execution. **F10** is also known as **Step Over**. You can use **Step Over** to move from line to line, without delving into the details of what is occurring in each part of the line. In general you should use **Step Over** instead of **Step Into**, unless you want to dive more deeply into code that is being called from elsewhere (as you did to reach the body of `Calculate`). +1. Now that the point of execution is at the start of the `Calculate` function, press **F10** to move to the next line in the program's execution. **F10** is also known as **Step Over**. You can use **Step Over** to move from line to line, without delving into the details of what is occurring in each part of the line. In general you should use **Step Over** instead of **Step Into**, unless you want to dive more deeply into code that's being called from elsewhere (as you did to reach the body of `Calculate`). 1. Continue using **F10** to **Step Over** each line until you get back to the `main()` function in the other file, and stop on the `cout` line. - The program is doing what's expected: it takes the first number, and divides it by the second. On the `cout` line, hover over the `result` variable or take a look at `result` in the **Autos** window. Its value is `inf`, which doesn't look right. + The program is doing what you expect: it takes the first number, and divides it by the second. On the `cout` line, hover over the `result` variable or take a look at `result` in the **Autos** window. Its value is `inf`, which doesn't look right. :::image type="complex" source="./media/calc-vs2017-debug-inf.png" alt-text="Screenshot of debugging the calculator."::: The current statement in the debugger is cout << "Result is: " << result << endl; In the autos window, result is inf. :::image-end::: - Let's fix it. The `cout` line outputs whatever value is stored in `result`, so when you step one more line forward using **F10**, the console window displays: + You can fix it. The `cout` line outputs whatever value is stored in `result`, so when you step one more line forward using **F10**, the console window displays: :::image type="complex" source="./media/calc-divide-by-zero-fail.png" alt-text="Screenshot of the Visual Studio Debug Console displaying the result of a division by zero operation."::: The app outputs: Please enter the operation to perform. Format: a+b | a-b | a*b | a/b. The user entered 5-0. The app output: Result is: 5. The user entered 10/0. The app output: Result is: inf @@ -735,9 +739,9 @@ You can also hover over variables in the code itself to see their current values ### Fix the "divide by zero" error -Let's handle division by zero more gracefully so that it's easier for the user to understand the problem. +Handle division by zero more gracefully so that it's easier for the user to understand the problem. -1. Make the following changes in *`CalculatorTutorial.cpp`*. (You can leave the program running as you edit, thanks to a debugger feature called **Edit and Continue**). The change is to add an `if` statement following `cin >> x >> oper >> y;` to check for division by zero and output a message to the user if it happens. Otherwise, the result is printed: +1. Make the following changes in *`CalculatorTutorial.cpp`*. You can leave the program running as you edit, thanks to a debugger feature called *Edit and Continue*. The change is to add an `if` statement following `cin >> x >> oper >> y;` to check for division by zero and output a message to the user if it happens. Otherwise, the result is printed: ```cpp // CalculatorTutorial.cpp : This file contains the 'main' function. Program execution begins and ends there. @@ -783,9 +787,11 @@ Let's handle division by zero more gracefully so that it's easier for the user t :::image type="content" source="./media/calc-final-verification.png" alt-text="Video of the Debug Console showing the final result after code changes. 10 / 0 is entered and the program displays 'Division by 0 exception'."::: > [!Note] - > When you edit code while in debugging mode, there's a risk of code becoming stale. This happens when the debugger is still running your old code, and has not yet updated it with your changes. The debugger pops up a dialog to inform you when this happens. Sometimes, you may need to press **F5** to refresh the code being executed. In particular, if you make a change inside a function while the point of execution is inside that function, step out of the function, then back into it again to get the updated code. If that doesn't work for some reason and you see an error message, you can stop debugging by clicking on the red square in the toolbar under the menus at the top of the IDE, then start debugging again by entering **F5** or by choosing the green "play" arrow beside the stop button on the toolbar. + > When you edit code while in debugging mode, there's a risk of code becoming stale. This happens when the debugger is still running your old code, and has not yet updated it with your changes. The debugger provides a dialog to inform you when this happens. Sometimes, you need to press **F5** to refresh the code being executed. + > + > In particular, if you make a change inside a function while the point of execution is inside that function, step out of the function, then back into it again to get the updated code. If that doesn't work for some reason and you see an error message, select the red square to stop debugging, then start again by entering **F5** or by choosing the green "play" arrow beside the stop button on the toolbar. > - > Another reason edit and continue may fail is that you need to go to the main menu and select **Tools** > **Options** > **Debugging** > **General** and ensure that **Require source files to exactly match the original version** is checked. + > Another reason edit and continue might fail is that you need to go to the main menu and select **Tools** > **Options** > **Debugging** > **General** and ensure that **Require source files to exactly match the original version** is checked. > Understanding the Run and Debug shortcuts > @@ -802,7 +808,7 @@ Let's handle division by zero more gracefully so that it's easier for the user t Congratulations! You completed the code for the calculator app, and built and debugged it in Visual Studio. -## Next steps +## Next step [Learn more about Visual Studio for C++](https://devblogs.microsoft.com/cppblog/getting-started-with-visual-studio-for-c-and-cpp-development/) diff --git a/docs/ide/include-cleanup-config.md b/docs/ide/include-cleanup-config.md index 0f2b6d59871..e6fd5c9a978 100644 --- a/docs/ide/include-cleanup-config.md +++ b/docs/ide/include-cleanup-config.md @@ -1,14 +1,14 @@ --- title: "Configure C/C++ Include Cleanup in Visual Studio" description: "Learn how to configure C/C++ Include Cleanup." -ms.date: 01/23/2026 +ms.date: 07/15/2026 ms.topic: "how-to" f1_keywords: ["config include cleanup"] helpviewer_keywords: ["config include cleanup"] --- # Configure C/C++ Include Cleanup in Visual Studio -Starting with 17.8 Preview 1, Visual Studio can clean up your `#include`s to improve the quality of your C and C++ code in the following ways: +Starting with 17.8 Preview 1, Visual Studio can clean up which files you `#include` to improve the quality of your C and C++ code in the following ways: - Offers to add header files for code that compiles only because a needed header file is included indirectly by another header file. - Offers to remove unused header files--improving build times. @@ -16,50 +16,133 @@ This article describes how to configure Include Cleanup in Visual Studio. For mo ## Turn on Include Cleanup -The Include Cleanup feature is on by default. If it isn't active, you can turn it on via **Tools** > **Options** > **Text Editor** > **C/C++** > **Code Cleanup** and select **Enable #include cleanup**. +The Include Cleanup feature is off by default. -Then use the dropdowns to configure how you want to be notified about opportunities to add indirect headers or remove unused headers: +::: moniker range="<=msvc-170" + +Turn it on by selecting **Tools** > **Options** > **Text Editor** > **C/C++** > **Code Cleanup** and selecting **Enable #include cleanup**. + +Then use the dropdowns to configure the severity of the notifications about opportunities to add indirect headers or remove unused headers: :::image type="complex" source="media/vs2022-include-cleanup-option.png" alt-text="The Tools options dialog opened at Text Editor > C/C++ > Code Cleanup."::: -The Enable # include cleanup checkbox is checked. The dropdowns for Remove unused includes suggestion level, and Add missing includes suggestion level, are shown. The contents of the dropdown are shown, which are: **Refactoring only**, **Suggestion**, **Warning**, and **Error**. The **Remove unused includes suggestion level** dropdown offers the same options but also adds dimmed. +The **Enable #include cleanup** checkbox is selected. The dropdowns for **Remove unused includes suggestion level** and **Add missing includes suggestion level** are shown. The contents of the dropdown are shown, which are: **Refactoring only**, **Suggestion**, **Warning**, and **Error**. The **Remove unused includes suggestion level** dropdown offers the same options but also adds **Dimmed**. :::image-end::: -The meanings of the suggestion level options are: +These options control the kind of notification that the Include Cleanup feature provides about unused headers: + +**Dimmed** -**Refactoring only**: Include Cleanup offers actions you can take through the quick action menu when you hover the mouse pointer over an `#include`, or place the cursor on the `#include` line and press Ctrl+period: +Include Cleanup shows unused headers by dimming the line of the unused header file in the code editor, and with a message in the **Error List** window. In the code editor, hover your cursor over the dimmed `#include` to bring up the quick action menu and choose **Show potential fixes**, or click on the light bulb dropdown, to see actions related to the unused file. -:::image type="complex" source="media/include-cleanup-refactor-lightbulb.png" alt-text="A screenshot of the quick action to remove an unused header"::: +:::image type="complex" source="media/include-cleanup-dimmed-include.png" alt-text="A screenshot of a dimmed #include < iostream > line."::: +The line for #include < iostream > is dimmed because the line of code that uses iostream is commented out. That line of code is // std::cout << "charSize = " << charSize; The quick action menu is also visible for this line. It says the #include < iostream > isn't used in this file, and has a link to Show potential fixes. +:::image-end::: + +**Refactoring only**: Include Cleanup offers actions you can take through the quick action menu in the code editor when you hover the mouse pointer over an `#include`, or place the cursor on the `#include` line and press Ctrl+period: + +:::image type="complex" source="media/include-cleanup-refactor-lightbulb.png" alt-text="A screenshot of the quick action to remove an unused header."::: When hovering the cursor over # include iostream, a light bulb appears with the text that # include iostream isn't used in this file." :::image-end::: -**Suggestion, Warning, Error**: Include Cleanup offers actions it can take via suggestions, warnings, or errors in the Error List window. You determine which. In the following screenshot of the Error List, Include Cleanup is configured to show unused headers with a warning. Ensure that **Build + Intellisense** is selected in the dropdown filter so that you can see the Include Cleanup output: +**Suggestion, Warning, Error**: Include Cleanup can show Include Cleanup messages as suggestions, warnings, or errors in the **Error List** window. You determine which. In the following screenshot of the **Error List**, Include Cleanup is configured to show unused headers with a warning. Ensure that **Build + Intellisense** is selected in the dropdown filter so that you can see the Include Cleanup output: :::image type="complex" source="media/include-cleanup-error-list.png" alt-text="A screenshot of the Error List window."::: -The dropdown filter is set to Build + IntelliSense. A warning is visible: VCIC002 - #include < iostream > isn't used in this file." +The dropdown filter is set to **Build + IntelliSense**. A warning is visible: VCIC002 - `#include ` isn't used in this file." :::image-end::: +::: moniker-end +::: moniker range=">=msvc-180" + +Turn it on by selecting **Tools** > **Options** > **All Settings** > **Languages** > **C/C++** > **Code cleanup** > **Include cleanup**. Use the dropdowns to configure how you want to be notified about opportunities to highlight unused `#include` statements, `#include` statements that can be optimized (removed after their required transitive includes are added directly), and missing `#include` statements that are transitively included. + +:::image type="complex" source="media/vs-include-cleanup-option.png" alt-text="A screenshot of the Tools options dialog opened at All Settings > Languages > C/C++ > Code cleanup > Include cleanup."::: +Screenshot showing dropdowns for choosing how to highlight an unused header in the code editor, those that can be optimized, and those that are transitively included. +:::image-end::: + +The meaning of the options: **Dimmed** -Include Cleanup shows unused headers by dimming the line of the unused header file in the code editor. Hover your cursor over the dimmed `#include` to bring up the quick action menu and choose **Show potential fixes**, or click on the light bulb dropdown, to see actions related to the unused file. +Include Cleanup shows unused headers by dimming the line of the unused header file in the code editor, and as a message in the **Error List** window. In the code editor, hover your cursor over the dimmed `#include` to bring up the quick action menu and choose **Show potential fixes**, or click on the light bulb dropdown, to see actions related to the unused file. :::image type="complex" source="media/include-cleanup-dimmed-include.png" alt-text="A screenshot of a dimmed #include < iostream > line."::: -The line for #include < iostream > is dimmed because the line of code that uses iostream is commented out. That line of code is // std::cout << "charSize = " << charSize; The quick action menu is also visible for this line. It says the #include < iostream > isn't used in this file, and has a link to Show potential fixes. +The line for `#include ` is dimmed because the line of code that uses `iostream` is commented out. That line of code is `// std::cout << "charSize = " << charSize;`. The quick action menu is also visible for this line. It says the `#include ` isn't used in this file, and has a link to **Show potential fixes**. +:::image-end::: + +**None**: Take no action. Include Cleanup still offers actions you can take in the code editor via the quick action menu when you hover the mouse pointer over an `#include`, or place the cursor on the `#include` line and press Ctrl+period: + +**Suggestion, Warning, Error**: Include Cleanup can show Include Cleanup messages as suggestions, warnings, or errors in the Error List window. You determine which. In the following screenshot of the **Error List**, Include Cleanup is configured to show unused headers with a warning. Ensure that **Build + Intellisense** is selected in the dropdown filter so that you can see the Include Cleanup output: + +:::image type="complex" source="media/include-cleanup-error-list.png" alt-text="A screenshot of the Error List window."::: +The dropdown filter is set to **Build + IntelliSense**. A warning is visible: VCIC002 - `#include ` isn't used in this file." :::image-end::: +::: moniker-end + +## Other configuration options + +::: moniker range="<=msvc-170" + +More **Include Cleanup** settings are available under **Tools** > **Options** > **Text Editor** > **C/C++** > **Code Cleanup**: + +- **Sort includes**: Flags `#include` directives that need sorting. Choose the severity notification level of the message that appears in the **Error List** window: **None** (feature is off), **Suggestion**, **Warning**, or **Error**. +- **Style**: Controls how `#include` statements are sorted. Choose **Ignore** to sort without considering bracket style, **Quotes** to sort quoted includes above angle-bracket includes, or **Angle brackets** to sort angle-bracket includes above quoted includes. +- **Case sensitive**: When selected, sorting compares include filenames case-sensitively. When cleared, sorting is case-insensitive. + +:::image type="content" source="media/other-include-cleanup-options.png" alt-text="Screenshot of Visual Studio Options with Advanced filtering, Sort after edits, Sort Includes, Sorting priority, Style, and Case sensitive settings highlighted."::: +::: moniker-end +::: moniker range=">=msvc-180" + +More **Include Cleanup** settings are available under **Tools** > **Options** > **All Settings** > **Languages** > **C/C++** > **Code cleanup** > **Include cleanup**: + +- **Advanced Filtering**: When selected, if you call a member function on a derived class object but the function is defined in the base class, the tool doesn't suggest adding the base-class header. Turn this option on to reduce noisy suggestions when the symbols you use come from base classes rather than the type you directly reference. +- **Sort the #include directives after making any edits for include cleanup**: When selected, the built-in sort-includes feature runs after any Include Cleanup action. +- **Format the #include directives after making any edits for include cleanup**: When selected, the format command runs after any Include Cleanup action. + +:::image type="content" source="media/vs-other-include-cleanup-options.png" alt-text="Screenshot of Visual Studio Include cleanup options with Advanced filtering, Sort, and Format settings highlighted."::: + +::: moniker-end ## Configure Include Cleanup with `.editorconfig` -There are more options for configuring Include Cleanup such as excluding specified includes from cleanup suggestions, indicating that some header files are required so that the tool doesn't mark them as unused, and so on. These options are defined in an `.editorconfig` file, that you can add to your project to, among other things, enforce consistent coding styles for everyone that works in the codebase. For more information about adding an `.editorconfig` file to your project, see [Create portable, custom editor settings with EditorConfig](/visualstudio/ide/create-portable-custom-editor-options). +The Include Cleanup feature has more options, such as excluding specified includes from cleanup suggestions and indicating that some header files are required so the tool doesn't mark them as unused. Define these options in an `.editorconfig` file. Add this file to your project to enforce consistent coding styles for everyone that works in the codebase. For more information about adding an `.editorconfig` file to your project, see [Create portable, custom editor settings with EditorConfig](/visualstudio/ide/create-portable-custom-editor-options). The `.editorconfig` settings that you can use with Include Cleanup are: | Setting | Values | Example | -|--|--|--|--| -| `cpp_include_cleanup_add_missing_error_tag_type`

Sets the error level of add transitive include messages. | `none`
`suggestion`
`warning`
`error` | `cpp_include_cleanup_add_missing_error_tag_type = suggestion` | -| `cpp_include_cleanup_remove_unused_error_tag_type`

Sets the error level of remove unused include messages. | `none`
`suggestion`
`warning`
`error`
`dimmed` | `cpp_include_cleanup_remove_unused_error_tag_type = dimmed` | +|--|--|--| +| `cpp_include_cleanup_add_missing_error_tag_type`

Sets the error level for add transitive include messages. | `none`
`suggestion`
`warning`
`error` | `cpp_include_cleanup_add_missing_error_tag_type = suggestion` | +| `cpp_include_cleanup_alternate_files`

Suppress messages for indirect includes. For example, if you `#include ` and only use content from its indirectly included headers `winerror.h` or `minwindef.h`, the tool doesn't suggest adding them. | *file1*:*file2*[:*file3*...][,*file4*:*file5*...] | `cpp_include_cleanup_alternate_files = windows.h:winerror.h:minwindef.h`
or
`cpp_include_cleanup_alternate_files = windows.h:winerror.h:minwindef.h,umbrella.h:internal.h`| | `cpp_include_cleanup_excluded_files`

Excludes the specified files from Include Cleanup messages. You won't get a suggestion related to the header at all, whether to add it or that it's unused. | *filename* | `cpp_include_cleanup_excluded_files = vcruntime.h, vcruntime_string.h` | -| `cpp_include_cleanup_required_files`

Specify that usage of *file1* requires *file2*. For example, specify that if you use `atlwin.h` that `altbase.h` must also be included. | *file1*:*file2* | `cpp_include_cleanup_required_files = atlwin.h:altbase.h, atlcom.h:altbase.h` | +| `cpp_include_cleanup_remove_unused_error_tag_type`

Sets the error level for remove unused include messages. | `none`
`suggestion`
`warning`
`error`
`dimmed` | `cpp_include_cleanup_remove_unused_error_tag_type = dimmed` | | `cpp_include_cleanup_replacement_files`

Replaces *file1* with *file2* during Include Cleanup processing. For example, you may prefer using `cstdio` over `stdio.h`. If you have a file with both `#include ` and `#include ` and you consume content only from `stdio.h`, with this setting Include Cleanup will tell you to remove `stdio.h` because it replaced the usage of `cstdio` with `stdio.h` during processing. If you don't use the contents from either, Include Cleanup will tell you to remove both.| *file1*:*file2* | `cpp_include_cleanup_replacement_files = stdio.h:cstdio,stdint.h:cstdint` | -| `cpp_include_cleanup_alternate_files`

Suppress messages for indirect includes. For example, if you `#include ` and only use content from its indirectly included headers `winerror.h` or `minwindef.h`, the tool won't suggest adding them. | *file1*:*file2*[:*file3*...][,*file4*:*file5*...] | `cpp_include_cleanup_alternate_files = windows.h:winerror.h:minwindef.h`
or
`cpp_include_cleanup_alternate_files = windows.h:winerror.h:minwindef.h,umbrella.h:internal.h`| +| `cpp_include_cleanup_required_files`

Specify that usage of *file1* requires *file2*. For example, specify that if you use `atlwin.h` that `altbase.h` must also be included. | *file1*:*file2* | `cpp_include_cleanup_required_files = atlwin.h:altbase.h, atlcom.h:altbase.h` | +| `cpp_sort_includes_error_tag_type`

Sets the error level of sort-includes messages. `none` turns the feature off. `suggestion` shows a **`...`** squiggle and adds a message to the error list. `warning` shows a green squiggle and adds a warning. `error` shows a red squiggle and adds an error. | `none`
`suggestion`
`warning`
`error` | `cpp_sort_includes_error_tag_type = suggestion` | +| `cpp_sort_includes_priority_case_sensitive`

When `true`, sort compares include filenames case-sensitively. When `false`, sort is case-insensitive. | `true`
`false` | `cpp_sort_includes_priority_case_sensitive = false` | +| `cpp_sort_includes_priority_style`

Controls whether the sort takes bracket style into account. `ignore` sorts without considering brackets. `quoted` sorts quoted includes above angle-bracket includes. `angle_brackets` sorts angle-bracket includes above quoted includes. | `ignore`
`quoted`
`angle_brackets` | `cpp_sort_includes_priority_style = quoted` | + +::: moniker range=">=msvc-180" + +The following settings are available starting in Visual Studio 2026: + +| Setting | Values | Example | +|--|--|--| +| `cpp_include_cleanup_format_after_edits`

When `true`, runs the format command after any Include Cleanup action. Useful when you have clang-format configured to sort your `#include` directives. | `true`
`false` | `cpp_include_cleanup_format_after_edits = true` | +| `cpp_include_cleanup_sort_after_edits`

When `true`, runs the built-in sort-includes feature after any Include Cleanup action. Useful when you're not using clang-format to sort your `#include` directives. | `true`
`false` | `cpp_include_cleanup_sort_after_edits = true` | + +## Suppress unused-include messages through code + +Starting in Visual Studio 2026, you can suppress **Include Cleanup** messages on a single `#include` directive by adding a `// VCIC-Excluded` comment on the same line. The Include Cleanup tool doesn't suggest removing that include, even if it appears unused. Provide optional justification text after the marker so future readers know why the include is there: + +```cpp +#include "Header2.h" // VCIC-Excluded: needed for the ATL macros used below +``` + +You can also use the light-bulb menu to add the `// VCIC-Excluded` comment to a `#include` directive. Ensure that Include Cleanup is turned on via **Tools** > **Options** > **All Settings** > **Languages** > **C/C++** > **Code cleanup** > **Include cleanup** because it's off by default. Then, hover your cursor over the `#include` line, select **Other Fixes** > **Suppress VCIC002 in source**:: + +:::image type="content" source="media/include-cleanup-lightbulb-suppress.png" alt-text="Screenshot of Visual Studio light-bulb menu, showing Suppress VCIC002 in source."::: + +The `// VCIC-Excluded` comment only applies to the `#include` for the file. Setting `cpp_include_cleanup_excluded_files` in `.editorconfig` applies that exclusion in every file governed by the `.editorconfig`. + +::: moniker-end ## See also diff --git a/docs/ide/include-cleanup-overview.md b/docs/ide/include-cleanup-overview.md index 423b16a3440..9f595b37d97 100644 --- a/docs/ide/include-cleanup-overview.md +++ b/docs/ide/include-cleanup-overview.md @@ -1,7 +1,7 @@ --- title: "Clean up C/C++ #includes in Visual Studio" description: "Learn about using C/C++ Include Cleanup in Visual Studio to remove unused headers, and transitively add indirect headers needed in your project." -ms.date: 10/5/2023 +ms.date: 07/27/2026 ms.topic: "overview" ms.custom: intro-overview f1_keywords: ["include cleanup"] @@ -9,19 +9,24 @@ helpviewer_keywords: ["include cleanup"] --- # Clean up C/C++ includes in Visual Studio +::: moniker range="` and ``, so those are indirect headers. -The issue is that `myProgram.cpp` uses `std::string` and `std::cout`, but doesn't directly include the headers that define them. This code happens to compile because `myHeader.h` includes those headers. This code is brittle because if `myHeader.h` ever stopped including either one, `myProgram.cpp` wouldn't compile anymore. +The problem is that `myProgram.cpp` uses `std::string` and `std::cout`, but doesn't directly include the headers that define them. This code compiles because `myHeader.h` includes those headers. This code is brittle because if `myHeader.h` ever stopped including either one, `myProgram.cpp` wouldn't compile anymore. -Per the C++ guidelines, it's better to explicitly include headers for all of your dependencies so that your code isn't subject to brittleness caused by changes to header files. For more information, see [SF.10: Avoid dependencies on implicitly `#include`d names](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#sf10-avoid-dependencies-on-implicitly-included-names) in the C++ Core Guidelines. +Per the C++ guidelines, it's better to explicitly include headers for all of your dependencies so that your code isn't subject to brittleness caused by changes to header files. For more information about the guideline, see [SF.10: Avoid dependencies on implicitly `#include`d names](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#sf10-avoid-dependencies-on-implicitly-included-names) in the C++ Core Guidelines. -Include Cleanup analyzes your code to identify unused and indirectly included headers. It provides feedback based on the settings described in [Config the C++ #include tool in Visual Studio](include-cleanup-config.md). Feedback can be in the form of error list warnings, suggestions, etc. For more details on the feedback provided by Include Cleanup, refer [Include Cleanup messages](include-cleanup-messages.md). +Include Cleanup analyzes your code to identify unused and indirectly included headers. It provides feedback based on the settings described in [Config the C++ #include tool in Visual Studio](include-cleanup-config.md). The feedback comes in the form of error list warnings and suggestions. For more details on the feedback provided by Include Cleanup, see [Include Cleanup messages](include-cleanup-messages.md). ## Unused headers -As your code evolves, you may no longer need some header files. This is hard to keep track of in a complex project. Over time, your builds may take longer because the compiler is processing unnecessary header files. Include Cleanup helps you find and remove unused headers. For example, what if `myFunc()` is commented out in `myProgram.cpp`: +As your code evolves, you might no longer need some header files. It's hard to keep track of these headers in a complex project. Over time, your builds might take longer because the compiler processes unnecessary header files. **Include Cleanup** helps you find and remove unused headers. For example, what if you comment out `myFunc()` in `myProgram.cpp`: ```cpp // myProgram.cpp @@ -76,15 +81,15 @@ int main() } ``` -In the following screenshot, `#include "myHeader.h"` is dimmed (a setting described in [Config the C++ #include tool in Visual Studio](include-cleanup-config.md)) because it isn't used since `myFunc()` is commented out. +In the following screenshot, `#include "myHeader.h"` appears dimmed (a setting described in [Config the C++ #include tool in Visual Studio](include-cleanup-config.md)) because it's no longer necessary since `myFunc()` is commented out. -Hover your cursor over the dimmed `#include` to bring up the quick action menu. Click the light bulb (or choose the **Show potential fixes** link) to see actions related to the unused file: +Hover your cursor over the dimmed `#include` to bring up the quick action menu. Select the light bulb (or choose the **Show potential fixes** link) to see actions related to the unused file: :::image type="content" source="media/vs2022-include-cleanup-refactor-options.png" alt-text="Three refactoring options are shown: Remove # include myHeader.h, remove all unused includes, and Add all transitively used and remove all unused # includes."::: ## Add transitively used headers -We could choose to remove the unused header file, but that breaks the code since `` and `` are indirectly included via `myheader.h`. +You might choose to remove the unused header file, but that action breaks the code since `` and `` are indirectly included by `myheader.h`. Instead, we can choose **Add all transitively used and remove all unused #includes**. This removes the unused header `myHeader.h`, but also adds any headers being used that are indirectly included via `myHeader.h`. The result, in this case, is adding `#include ` and `#include ` to `myProgram.cpp`, and removing `#include "myHeader.h"`: @@ -105,9 +110,20 @@ The tool doesn't update the comments, but you can see that the code is now using ## Best practice -Don't remove what appear to be unused header files without first adding indirectly included header files. That's because your code may rely on indirect includes in a header file that is otherwise unused. Add transitively used headers first. Then, when you remove unused headers, you don't get compilation errors due to missing header files that are included indirectly by a header file you've removed. +Don't remove what appear to be unused header files without first adding indirectly included header files. Your code might rely on indirect includes in a header file that is otherwise unused. Add transitively used headers first. Then, when you remove unused headers, you don't get compilation errors due to missing header files that are included indirectly by a header file you removed. -One way to do this is to set the Include Cleanup setting for **Add missing includes suggestion level** to **Suggestion** (**Tools** > **Options** > **Text Editor** > **C/C++** > **Code Cleanup**). Also set **Remove unused includes suggestion level** to **Suggestion**. Then: +::: moniker range="<=msvc-170" +One way to do this is: +- Set the Include Cleanup setting for **Add missing includes suggestion level** to **Suggestion** (**Tools** > **Options** > **Text Editor** > **C/C++** > **Code Cleanup**). +- Set **Remove unused includes suggestion level** to **Suggestion**. +::: moniker-end +::: moniker range=">=msvc-180" +One way to do this is: +- Set the dropdown for the Include Cleanup setting for **Choose how to highlight missing #include statements that are transitively included** to **Suggestion** (**Tools** > **Options** > **All Settings** > **Languages** > **C/C++** > **Code cleanup** > **Include cleanup**). +- Set **Choose how to highlight #include statements that are unused** to **Suggestion**. +::: moniker-end + +Then: 1. In the error list, make sure the filter is set to **Build + IntelliSense**. 1. Look for instances of "Content from #include x is used in this file and transitively included." @@ -117,7 +133,7 @@ One way to do this is to set the Include Cleanup setting for **Add missing inclu 1. Hover your cursor over the unused header. From the light bulb dropdown, select **Remove all unused includes**. 1. Repeat these steps in your project until all Include Cleanup suggestions are addressed. -In this brief overview, you've seen how Include Cleanup can help you remove unused headers, and add headers that were indirectly included. This helps you keep your code clean, potentially build faster, and reduces the brittleness of your code. +In this brief overview, you saw how **Include Cleanup** can help you remove unused headers and add headers that were indirectly included. This process helps you keep your code clean, potentially build faster, and reduces the brittleness of your code. ## See also diff --git a/docs/ide/media/include-cleanup-lightbulb-suppress.png b/docs/ide/media/include-cleanup-lightbulb-suppress.png new file mode 100644 index 00000000000..d539fc19cda Binary files /dev/null and b/docs/ide/media/include-cleanup-lightbulb-suppress.png differ diff --git a/docs/ide/media/other-include-cleanup-options.png b/docs/ide/media/other-include-cleanup-options.png new file mode 100644 index 00000000000..7406930a549 Binary files /dev/null and b/docs/ide/media/other-include-cleanup-options.png differ diff --git a/docs/ide/media/vs-include-cleanup-option.png b/docs/ide/media/vs-include-cleanup-option.png new file mode 100644 index 00000000000..5f45bb9ec30 Binary files /dev/null and b/docs/ide/media/vs-include-cleanup-option.png differ diff --git a/docs/ide/media/vs-other-include-cleanup-options.png b/docs/ide/media/vs-other-include-cleanup-options.png new file mode 100644 index 00000000000..c3cd863422f Binary files /dev/null and b/docs/ide/media/vs-other-include-cleanup-options.png differ diff --git a/docs/linux/linux-asan-configuration.md b/docs/linux/linux-asan-configuration.md index 11c959116f9..1926b8bcbc4 100644 --- a/docs/linux/linux-asan-configuration.md +++ b/docs/linux/linux-asan-configuration.md @@ -3,6 +3,7 @@ title: "Configure Linux projects to use Address Sanitizer" description: "Describes how to configure C++ Linux projects in Visual Studio to use Address Sanitizer." ms.date: "10/7/2020" ms.topic: how-to +f1_keywords: ["VC.Project.RaspberryDebugger.ASANRuntimeFlags"] --- # Configure Linux projects to use Address Sanitizer diff --git a/docs/linux/prop-pages/debugging-linux.md b/docs/linux/prop-pages/debugging-linux.md index e6ca60889fd..2e309b8721f 100644 --- a/docs/linux/prop-pages/debugging-linux.md +++ b/docs/linux/prop-pages/debugging-linux.md @@ -1,8 +1,9 @@ --- title: Debugger Properties (Linux C++) description: "Describes the Microsoft Visual Studio Linux C++ debugger properties" -ms.date: "06/07/2019" +ms.date: "07/08/2026" ms.assetid: 0c1c0fcc-a49b-451c-a5cb-ce9711fac064 +f1_keywords: ["VC.Project.RaspberryDebugger.LaunchActivity", "VC.Project.RaspberryDebugger.LaunchActivity", "VC.Project.RaspberryDebugger.DebuggerType", "VC.Project.AndroidDebugger.LaunchActivity", "VC.Project.LinuxDebugger.DebugChildProcesses", "VC.Project.RaspberryDebugger.EnablePrettyPrinting", "VC.Project.RaspberryDebugger.LinuxNatvisFile", "VC.Project.RaspberryDebugger.SourceMap", "VC.Project.RaspberryDebugger.MIMode", "VC.Project.RaspberryDebugger.SymbolLoadList", "VC.Project.RaspberryDebugger.LoadAllSymbols", "VC.Project.RaspberryDebugger.ShowDisplayString", "VC.Project.RaspberryDebugger.EnableDebugInfoD", "VC.Project.RaspberryDebugger.DebugInfoDTimeout"] --- # C++ Debugging Properties (Linux C++) @@ -16,20 +17,26 @@ Linux support is available in Visual Studio 2017 and later. | Property | Description | Choices | |--|--|--| -| Remote debug machine | **Visual Studio 2019 version 16.1**: Specifies the machine to debug the program on. Can be different than the remote build machine that's specified on the [General](general-linux.md) page. You can add or edit a target machine connection by using **Tools** > **Options** > **Cross Platform** > **Connection Manager**. | -| Pre-Launch Command | A command that's run on the shell before the debugger starts, that can be used to affect the debugging environment. | -| Program | The full path on the remote system to the program to debug. If left empty or unchanged, it defaults to the current project output. | -| Program Arguments | The command-line arguments to pass to the program being debugged. | -| Working Directory | The remote application's working directory. By default, the user home directory. | | Additional Debugger Commands | Additional `gdb` commands for the debugger to run before starting debugging. | -| Debugger Port Number | The port number for debugger communication with the remote debugger. The port must not be in use locally. This value must be positive, and between 1 and 65535. If not supplied, a free port number is used. | -| Remote Debugger Port Number | The port number on which the remote debugger server `gdbserver` is listening on the remote system. The port must not be in use on the remote system. This value must be positive, and between 1 and 65535. If not supplied, a free port number starting from 4444 is used. | -| Debugging Mode | Specifies how the debugger interfaces with `gdb`. In *gdb mode*, the debugger drives `gdb` over the shell on the remote system. In *gdbserver mode*, `gdb` runs locally and connects to `gdbserver` running remotely. | **gdbserver**
**gdb** | +| Additional Sources File Path Map | Additional path equivalences for the debugger to use to map Windows source file names to Linux source file names. The format is "\=\;...". A source file name found under the Windows path is referenced as if it's found in the same relative position under the Linux path. Files found in the local project don't require additional mapping. | | Additional Symbol Search Paths | Additional search path for debug symbols (solib-search-path). | | Debug Child Processes | Specifies whether to enable debugging of child processes. | +| Debugger Port Number | The port number for debugger communication with the remote debugger. The port must not be in use locally. This value must be positive, and between 1 and 65535. If you don't supply a value, a free port number is used. | +| Debugging Mode | Specifies how the debugger interfaces with `gdb`. In *gdb mode*, the debugger drives `gdb` over the shell on the remote system. In *gdbserver mode*, `gdb` runs locally and connects to `gdbserver` running remotely. | **gdbserver**
**gdb** | +| Debuginfod timeout (seconds) | Set the timeout, in seconds, for debuginfod server requests when you enable debuginfod. Use `0` to keep the default `gdb` timeout. This property only supports `gdb`. | Integer value in seconds. Default: 30 | +| Enable debuginfod | Let `gdb` query debuginfod servers for missing debug information and source files. This property only supports `gdb`. | | Enable Python Pretty Printing | Enable pretty printing of expression values. Only supported in gdb debugging mode. | -| Visualization File | Default native visualization file (.natvis) containing visualization directives for SLT types. Other .natvis files that belong to the current solution are loaded automatically. | -| Additional Sources File Path Map | Additional path equivalences for the debugger to use to map Windows source file names to Linux source file names. The format is "\=\;...". A source file name found under the Windows path is referenced as if it's found in the same relative position under the Linux path. Files found in the local project don't require additional mapping. | | GDB Path | **Visual Studio 2019 version 16.9**: Specifies the path to the GDB executable to be used by Visual Studio. | +| Pre-Launch Command | A command that runs in the shell before the debugger starts. Use this command to affect the debugging environment. | +| Program | The full path on the remote system to the program to debug. If you leave this property empty or unchanged, it defaults to the current project output. | +| Program Arguments | The command-line arguments to pass to the program being debugged. | +| Remote debug machine | **Visual Studio 2019 version 16.1**: Specifies the machine to debug the program on. This machine can be different from the remote build machine that you specify on the [General](general-linux.md) page. To add or edit a target machine connection, use **Tools** > **Options** > **Cross Platform** > **Connection Manager**. | +| Remote Debugger Port Number | The port number on which the remote debugger server `gdbserver` is listening on the remote system. The port must not be in use on the remote system. This value must be positive, and between 1 and 65535. If you don't supply a value, a free port number starting from 4444 is used. | +| Remote Debugger Type | **Visual Studio 2022 version 17.3**: Select the debugger that Visual Studio uses to debug your Linux project. | `gdb`
`lldb` | +| Show Natvis DisplayString | **Visual Studio 2019 version 16.0**: Show the `.natvis` `DisplayString` element by default in the **DataTips**, **Locals**, **Watch**, and similar debugger windows. Natvis is an XML-based format that customizes how native C++ types appear in the debugger. `DisplayString` defines a type's summary string. | +| Symbol List | **Visual Studio 2019 version 16.0**: Specify a semicolon-separated list of shared library (`solib`) names that the Symbol Loading Preference property uses to control symbol loading. The names can include the `*` and `?` wildcards. Full glob patterns aren't supported. | +| Symbol Loading Preference | **Visual Studio 2019 version 16.0**: Choose whether the debugger loads symbols for all shared libraries except the names in Symbol List, or only for the shared libraries named in Symbol List. | **Load all symbols except those in Symbol List**
**Load only those symbols specified in Symbol List** | +| Visualization File | Default native visualization file (.natvis) containing visualization directives for SLT types. The debugger automatically loads other .natvis files that belong to the current solution. | +| Working Directory | The remote application's working directory. By default, the user home directory. | ::: moniker-end diff --git a/docs/linux/set-up-fips-compliant-secure-remote-linux-development.md b/docs/linux/set-up-fips-compliant-secure-remote-linux-development.md index aa4ba4bf66e..c771087b836 100644 --- a/docs/linux/set-up-fips-compliant-secure-remote-linux-development.md +++ b/docs/linux/set-up-fips-compliant-secure-remote-linux-development.md @@ -147,7 +147,7 @@ It's possible to enable FIPS mode globally in Windows. 1. In the **Local Security Setting** tab, select **Enabled** or **Disabled**, and then choose **OK** to save your changes. > [!WARNING] -> Enabling FIPS mode may cause some applications to break or behave unexpectedly. For more information, see the blog post [Why We're Not Recommending "FIPS mode" Anymore](https://techcommunity.microsoft.com/t5/microsoft-security-baselines/why-we-8217-re-not-recommending-8220-fips-mode-8221-anymore/ba-p/701037). +> Enabling FIPS mode may cause some applications to break or behave unexpectedly. ## Additional resources @@ -157,8 +157,6 @@ It's possible to enable FIPS mode globally in Windows. [Cryptographic Algorithm Validation Program: Validation Notes](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/Validation-Notes) (from NIST) -Microsoft blog post on [Why We're Not Recommending "FIPS mode" Anymore](https://techcommunity.microsoft.com/t5/microsoft-security-baselines/why-we-8217-re-not-recommending-8220-fips-mode-8221-anymore/ba-p/701037) - [SSH Server Configuration](https://www.ssh.com/ssh/sshd_config) ## See also diff --git a/docs/mfc/how-to-update-user-interface-objects.md b/docs/mfc/how-to-update-user-interface-objects.md index 0a9e902847d..11d935d65cb 100644 --- a/docs/mfc/how-to-update-user-interface-objects.md +++ b/docs/mfc/how-to-update-user-interface-objects.md @@ -11,7 +11,7 @@ helpviewer_keywords: ["menus [MFC], updating as context changes", "user interfac Typically, menu items and toolbar buttons have more than one state. For example, a menu item is grayed (dimmed) if it is unavailable in the present context. Menu items can also be checked or unchecked. A toolbar button can also be disabled if unavailable, or it can be checked. -Who updates the state of these items as program conditions change Logically, if a menu item generates a command that is handled by, say, a document, it makes sense to have the document update the menu item. The document probably contains the information on which the update is based. +Who updates the state of these items as program conditions change? Logically, if a menu item generates a command that is handled by, say, a document, it makes sense to have the document update the menu item. The document probably contains the information on which the update is based. If a command has multiple user-interface objects (perhaps a menu item and a toolbar button), both are routed to the same handler function. This encapsulates your user-interface update code for all of the equivalent user-interface objects in a single place. diff --git a/docs/overview/acquire-msvc.md b/docs/overview/acquire-msvc.md new file mode 100644 index 00000000000..e26f0ab46b2 --- /dev/null +++ b/docs/overview/acquire-msvc.md @@ -0,0 +1,249 @@ +--- +title: "Install the Microsoft C++ (MSVC) Build Tools" +description: "Install the MSVC Build Tools using the Visual Studio Installer UI, command line, winget, or a .vsconfig file. Choose Preview, latest release, or an older in-support toolset, and target it from MSBuild, CMake, or the Visual Studio Command Prompt." +ms.date: 08/20/2026 +ms.topic: how-to +ai-usage: ai-assisted +ms.service: "visual-cpp" +ms.subservice: "tools" +ms.custom: intro-installation +#customer intent: As a C++ developer, I want to install a specific MSVC Build Tools version (Preview, latest release, or an older in-support release) and target it from my build system. +--- +# Install the Microsoft C++ (MSVC) Build Tools + +The Visual Studio Installer lets you install multiple Microsoft C++ (MSVC) Build Tools versions side by side: + +- A preview version of the next MSVC Build Tools release. +- The latest released, in-support MSVC Build Tools version. This version is the default toolset used for C++ projects. +- Earlier MSVC Build Tools releases that are still in support. + +Previews are updated regularly with new features and fixes. The latest release and in-support build tools receive servicing fixes, as needed, for the duration of their support lifecycle. + +For details about the versioning scheme, servicing policy, and how often the latest released MSVC toolset changes, see [Microsoft C++ (MSVC) compiler versioning](compiler-versions.md). For a summary of features added in each release, see [What's new for MSVC Build Tools](what-s-new-for-msvc.md). + +> [!NOTE] +> All MSVC Build Tools versions are available in both Visual Studio channels, but the Insiders channel receives updates sooner than the Stable channel. Changes applied in the MSVC development branches take one to two weeks to ship in the preview Build Tools on Visual Studio Insiders. + +You can acquire MSVC through the Visual Studio Installer UI, through the Visual Studio Installer command line, or through `winget`. + +## Install by using the Visual Studio Installer UI + +Download the Visual Studio Installer from [visualstudio.microsoft.com/downloads](https://visualstudio.microsoft.com/downloads/) (Stable channel) or [visualstudio.microsoft.com/insiders](https://visualstudio.microsoft.com/insiders/) (Insiders channel). + +In the installer, choose **Desktop development with C++** to install the latest released C++ toolset. + +In the **Installation details** panel, the **MSVC Build Tools for x64/x86 (Preview)** option installs the preview tools. Similar options exist for ARM64 installs. + +:::image type="content" source="media/acquire-msvc/installer-workload-desktop-cpp-msvc-preview.png" alt-text="Screenshot of the Visual Studio Installer with the Desktop development with C++ workload and the MSVC Build Tools for x64/x86 (Preview) component selected."::: + +To install an older in-support toolset, select the **Individual components** tab, search for `MSVC`, and scroll to find the version you want to install. For example, **MSVC Build Tools v14.50 for x64/x86**. Out-of-support toolsets are marked as such. + +:::image type="content" source="media/acquire-msvc/installer-individual-components-msvc-versions.png" alt-text="Screenshot of the Individual components tab in the Visual Studio Installer filtered to msvc, with MSVC Build Tools v14.50 for x64/x86 checked."::: + +## Install by using the Visual Studio Installer from the command line + +Use the Visual Studio Installer to perform a scripted, unattended install of MSVC. + +**To install the latest Insiders build:** + +1. Download [`vs_enterprise.exe`](https://aka.ms/vs/insiders/vs_enterprise.exe) (the same installer as above, sometimes named `VisualStudioSetup.exe`). +1. Create a `.vsconfig` file that lists the components to install. For more information, see [Create a .vsconfig file](#create-a-vsconfig-file). +1. Open an administrator Command Prompt. +1. Run the installer: + + ```cmd + .\vs_enterprise.exe --passive --config .\.vsconfig --installPath + ``` + +1. If an earlier **Visual Studio Build Tools** installation exists on the machine, uninstall it first. + +**Channel-specific installer links:** + +| Channel | Command-line build tools only | Full Visual Studio | +|---|---|---| +| Insiders | [`vs_buildtools.exe`](https://aka.ms/vs/insiders/vs_buildtools.exe) | [`vs_enterprise.exe`](https://aka.ms/vs/insiders/vs_enterprise.exe) | +| Stable | [`vs_buildtools.exe`](https://aka.ms/vs/stable/vs_buildtools.exe) | [`vs_enterprise.exe`](https://aka.ms/vs/stable/vs_enterprise.exe) | + +- Use the Visual Studio Installer to update or uninstall. +- For more information, see [Use command-line parameters to install, update, and manage Visual Studio](/visualstudio/install/use-command-line-parameters-to-install-visual-studio). + +## Install MSVC by using winget + +To install MSVC by using `winget`: + +1. Create a `.vsconfig` file that lists the components to install. For more information, see [Create a .vsconfig file](#create-a-vsconfig-file). +1. Open an administrator Command Prompt. +1. Run the following script: + + ```cmd + winget install -e --id Microsoft.VisualStudio.Enterprise.Insiders --override "--passive --config .\.vsconfig --installPath " + ``` + +**Winget install options:** + +- Use `--id Microsoft.VisualStudio.BuildTools` to install the Build Tools on the Stable channel. +- Use `--id Microsoft.VisualStudio.Enterprise` to install Visual Studio Enterprise on the Stable channel. +- Use `-v ` to specify an exact version, for example, `-v 18.6.2`. +- Use `winget search Microsoft.VisualStudio.BuildTools --versions` to list all available versions. + +## Create a .vsconfig file + +A `.vsconfig` file specifies the component IDs to install. You can find component IDs in the [Visual Studio Enterprise component directory](/visualstudio/install/workload-component-id-vs-enterprise) and the [Visual Studio Build Tools component directory](/visualstudio/install/workload-component-id-vs-build-tools). + +For example, in the Visual Studio Installer's **Individual components** tab, the **MSVC Build Tools v14.50 for x64/x86** component ID is `Microsoft.VisualStudio.Component.VC.14.50.18.0.x86.x64`. + +The Visual Studio Installer also supports [importing or exporting installation configurations](/visualstudio/install/import-export-installation-configurations) from an existing Visual Studio installation. + +The following `.vsconfig` file downloads the x86 and x64 tools for the preview toolset, the latest release, and the 14.50 release: + +```json +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.VC.Preview.Tools.x86.x64", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.VC.14.50.18.0.x86.x64" + ] +} +``` + +This configuration installs very few dependencies. Just the compilers, runtimes, and command prompts. + +A more complete installation with ARM64 tools, MFC/ATL, C++/CLI support, and a Windows SDK is: + +```json +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.VC.Preview.Tools.x86.x64", + "Microsoft.VisualStudio.Component.VC.Preview.ARM64", + "Microsoft.VisualStudio.Component.VC.Preview.CLI.Support", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64", + "Microsoft.VisualStudio.Component.VC.ATLMFC", + "Microsoft.VisualStudio.Component.VC.CLI.Support", + "Microsoft.VisualStudio.Component.VC.14.50.18.0.x86.x64", + "Microsoft.VisualStudio.Component.VC.14.50.18.0.ARM64", + "Microsoft.VisualStudio.Component.VC.14.50.18.0.CLI.Support", + "Microsoft.VisualStudio.Component.Windows11SDK.26100" + ] +} +``` + +## Use an installed MSVC toolset + +Toolsets are installed under `\VC\Tools\MSVC\`. + +The following files under `\VC\Auxiliary\Build\` identify the default and preview toolsets: + +- `Microsoft.VCToolsVersion.default.txt` contains the `` folder of the latest in-support MSVC toolset. +- `Microsoft.VCToolsVersion.default.props` contains MSBuild properties for the in-support MSVC toolset. +- `Microsoft.VCToolsVersion.Preview.txt` contains the `` folder of the MSVC preview toolset. +- `Microsoft.VCToolsVersion.Preview.props` contains MSBuild properties for the MSVC preview toolset. + +After you install the toolsets, configure your projects to use the toolset you want. + +### Visual Studio (MSBuild) + +In the project properties, select **Configuration Properties** > **General** > **MSVC Build Tools Version** and choose a supported Build Tools version. The dropdown is populated from `\VC\Tools\MSVC\`. + +:::image type="content" source="media/acquire-msvc/project-properties-msvc-build-tools-version.png" alt-text="Screenshot of C++ project property pages > General with the MSVC Build Tools Version dropdown expanded to show Latest supported, 14.50.35717, and 14.51.36231."::: + +To use the MSVC Build Tools preview, set **Use MSVC Build Tools Preview** to **Yes**. + +:::image type="content" source="media/acquire-msvc/project-properties-use-msvc-build-tools-preview.png" alt-text="Screenshot of C++ project property pages > General with the Use MSVC Build Tools Preview property set to Yes."::: + +Save these property changes to your `.vcxproj` file. Later builds from the Visual Studio IDE or command line use the saved project settings. + +### MSBuild command line + +To build with a supported MSVC version from a Visual Studio Command Prompt, add `/p:VCToolsVersion=`. For example: + +```cmd +msbuild /p:Platform= /p:Configuration= /p:VCToolsVersion=14.50.35717 +``` + +`` matches the folder name under `\VC\Tools\MSVC\`. + +#### Discover an MSVC toolset in another installation + +> [!NOTE] +> Cross-install discovery requires Visual Studio version 18.8 or later. + +The current Visual Studio installation might not find the exact `VCToolsVersion` you specify. To search all Visual Studio and Visual Studio Build Tools installations, add the following properties to your `.vcxproj` file or a `Directory.Build.props` file: + +```xml + + true + 14.43.34604 + +``` + +With discovery enabled, Visual Studio finds the specified version, potentially from a different installation. This behavior supports reproducible builds without manually setting `VCToolsInstallDir`. The requested MSVC toolset must already be installed on the machine. + +To build with the MSVC preview tools, add `/p:MSVCPreviewEnabled=true`: + +```cmd +msbuild /p:Platform= /p:Configuration= /p:MSVCPreviewEnabled=true +``` + +### CMake + +Configure CMake with the `-T "version="` toolset argument. For example: + +```cmd +cmake -G "Visual Studio 18 2026" -T "version=14.50" ..\ +cmake -G "Visual Studio 18 2026" -T "version=14.51" ..\ +cmake -G "Visual Studio 18 2026" -T "version=14.52" ..\ +``` + +### vcpkg + +Configure vcpkg with the [VCPKG_PLATFORM_TOOLSET_VERSION](/vcpkg/users/triplets#vcpkg_platform_toolset_version) triplet. For example: + +``` +set(VCPKG_PLATFORM_TOOLSET_VERSION "14.50") +``` + +or + +``` +set(VCPKG_PLATFORM_TOOLSET_VERSION "14.51") +``` + +### Visual Studio Command Prompt + +Some build systems need the command prompt to have the `PATH`, `LIB`, `INCLUDE`, and related environment variables set before you run them. + +To start a Visual Studio Command Prompt that targets a supported Build Tools version, add `-vcvars_ver=` where `` matches the prefix of a folder name under `\VC\Tools\MSVC\`. + +```cmd +\VC\Auxiliary\Build\vcvars64.bat -vcvars_ver=14.50 +``` + +To start a Visual Studio Command Prompt targeting the MSVC preview tools, use `-vcvars_ver=preview`: + +```cmd +\VC\Auxiliary\Build\vcvars64.bat -vcvars_ver=preview +``` + +## Uninstall MSVC + +To uninstall Visual Studio by using the Installer UI, select **More** > **Uninstall**. + +:::image type="content" source="media/acquire-msvc/installer-more-menu-uninstall.png" alt-text="Screenshot of the Visual Studio Installer Installed tab showing the More menu expanded with the Uninstall command highlighted."::: + +To uninstall Visual Studio from the command line, use any version of the Visual Studio installer: + +```cmd +.\vs_enterprise.exe uninstall --passive --installPath +``` + +## See also + +- [What's new for MSVC Build Tools](what-s-new-for-msvc.md) +- [Microsoft C++ (MSVC) compiler versioning](compiler-versions.md) +- [Install C and C++ support in Visual Studio](../build/vscpp-step-0-installation.md) +- [Visual Studio Enterprise component directory](/visualstudio/install/workload-component-id-vs-enterprise) +- [Visual Studio Build Tools component directory](/visualstudio/install/workload-component-id-vs-build-tools) +- [Use command-line parameters to install, update, and manage Visual Studio](/visualstudio/install/use-command-line-parameters-to-install-visual-studio) diff --git a/docs/overview/compiler-versions.md b/docs/overview/compiler-versions.md index f1502c60088..c33877fac8c 100644 --- a/docs/overview/compiler-versions.md +++ b/docs/overview/compiler-versions.md @@ -1,39 +1,144 @@ --- -description: "Learn more about Microsoft C++ compiler versioning." title: "Microsoft C++ (MSVC) compiler versioning" -ms.date: 02/12/2025 +description: "Visual Studio includes a Microsoft C++ (MSVC) compiler. Learn about the versioning system used for the compiler." +ms.date: 05/28/2026 ms.service: "visual-cpp" ms.subservice: "tools" helpviewer_keywords: ["Visual C++, platforms supported", "platforms [C++]"] +#customer intent: As a C++ developer using Visual Studio, I need to be aware of different versions of the Microsoft C++ compiler for consistency in my organization's production process. --- # Microsoft C++ (MSVC) compiler versioning The Microsoft C++ (MSVC) compiler version consists of four fields: -M - major version (two digits)\ -N - minor version (two digits)\ -B - build version (five digits)\ -R - revision version +- M: major version (two digits) +- N: minor version (two digits) +- B: build version (five digits) +- R: revision version Microsoft-specific compiler macros encode these fields as follows: -`_MSC_VER` = MMNN\ -`_MSC_FULL_VER` = MMNNBBBBB\ -`_MSC_BUILD` = R +- `_MSC_VER` = MMNN +- `_MSC_FULL_VER` = MMNNBBBBB +- `_MSC_BUILD` = R For example, the compiler version for Visual Studio 2022 version 17.9.0 is 19.39.33519: + - The major version is 19 - The minor version is 39 - The build version is 33519 - The revision version is 0 The macros reflect these values like this: + - `_MSC_VER = 1939` - `_MSC_FULL_VER = 193933519` -- `_MSC_BUILD` (the revision) is 0. +- `_MSC_BUILD` (the revision) is 0 + +> [!NOTE] +> Visual Studio 2019 versions 16.8 and 16.9 share the same major and minor versions, and so have the same value for `_MSC_VER`. This is also true for Visual Studio 2019 versions 16.10 and 16.11. To distinguish them, use `_MSC_FULL_VER` as described in [Service releases starting with Visual Studio 2017](#service-releases-starting-with-visual-studio-2017). + +## Visual Studio channels + +All MSVC Build Tools are available through the Visual Studio Installer. + +The [Visual Studio Stable Channel](https://visualstudio.microsoft.com) gets monthly updates and includes the latest supported MSVC Build Tools. The [Visual Studio Insiders Channel](https://visualstudio.microsoft.com/insiders) updates more often, so you can try upcoming MSVC changes sooner. For more information about the release cadence, see [Visual Studio 2026 release rhythm](/visualstudio/releases/2026/release-rhythm) and [Visual Studio Insiders release notes](/visualstudio/releases/2026/release-notes-insiders). + +Each Visual Studio update receives updates to all of the MSVC build toolsets: +- The **preview** toolset receives new features and fixes that the development team completed since the previous update. +- The **default** and **older in-support** toolsets receive only targeted bug fixes. + +Visual Studio Insiders users get early access to MSVC releases: +- On the Insiders Channel, preview toolsets update approximately weekly. +- On the Insiders Channel, new toolsets are available as release candidates about a month before they reach the Stable Channel, giving Insiders users time to validate the toolset and report issues. + +### Install specific MSVC toolsets + +- To install only the default MSVC toolset, install the `Desktop development with C++` workload. +- To install the preview toolset, run the Visual Studio Installer and select **MSVC Build Tools for <arch> (Preview)**. For more information, see [MSVC Build Tools Preview](https://aka.ms/msvc/preview). +- To install an older in-support 14.5x toolset, run the Visual Studio Installer, open the **Individual Components** tab, and select the specific 14.5x toolset. +- To restore a previously installed toolset after an upgrade—for example, when 14.50 is replaced by 14.51—add the older toolset back from the **Individual Components** tab. +- To install only the Build Tools without the full Visual Studio IDE, use the [Visual Studio Stable Build Tools SKU](https://aka.ms/vs/stable/vs_BuildTools.exe). +- Some out-of-support toolsets (labeled **(Out of support)**) may also be available in the Visual Studio Installer. These toolsets don't receive any updates and may be removed in the future. We strongly recommend moving to a supported version. + +## Version macros + +Recall that the version number consists of four fields: + +- M: major version (two digits) +- N: minor version (two digits) +- B: build version (five digits) +- R: revision version + +[`_MSC_VER`](../preprocessor/predefined-macros.md) distinguishes between major and minor releases. It has the form: MMNN. + +[`_MSC_FULL_VER`](../preprocessor/predefined-macros.md) represents the major, minor, and build version of the compiler. It has the form: MMNNBBBBB. Use it to distinguish between different versions of the compiler, including servicing releases. For more information about Visual Studio 2019 versions 16.8, 16.9, 16.10 and 16.11, see [Service releases starting with Visual Studio 2017](#service-releases-starting-with-visual-studio-2017). ->[!Note] ->Visual Studio 2019 versions 16.8 and 16.9 share the same major and minor versions, and so have the same value for `_MSC_VER`. As do Visual Studio 2019 versions 16.10 and 16.11. To distinguish them, use `_MSC_FULL_VER` as described in [Service releases starting with Visual Studio 2017](#service-releases-starting-with-visual-studio-2017). +**[`_MSC_BUILD`](../preprocessor/predefined-macros.md)** represents the revision version of the compiler. It has the form: R. Use it to distinguish between compiler revisions. + +When the major version changed between Visual Studio 2013 and Visual Studio 2015, `_MSC_VER` reflects the change by going from 1800 to 1900. + +An example of a minor change is from Visual Studio 2022 version 17.1 to Visual Studio 2022 version 17.2. In that case, `_MSC_VER` changed from 1931 to 1932. + +The following table lists the Visual Studio version that corresponds to each MSVC compiler (`_MSC_VER`) and MSVC Build Tools release, together with support status. EOL means end of life. + +| Visual Studio version | `_MSC_VER` | MSVC Build Tools version | Support | More info | +|--|--|--|--|--| +| Visual Studio 6.0 | 1200 | 6.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio .NET 2002 (7.0) | 1300 | 7.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio .NET 2003 (7.1) | 1310 | 7.1 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2005 (8.0) | 1400 | 8.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2008 (9.0) | 1500 | 9.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2010 (10.0) | 1600 | 10.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2012 (11.0) | 1700 | 11.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2013 (12.0) | 1800 | 12.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2015 (14.0) | 1900 | 14.0 | EOL | [Visual Studio lifecycle policy](/visualstudio/releases/2026/servicing-vs#support-for-older-versions) | +| Visual Studio 2017 RTW (15.0) | 1910 | 14.10 | EOL | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2017 version 15.3 | 1911 | 14.11 | EOL | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2017 version 15.5 | 1912 | 14.12 | EOL | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2017 version 15.6 | 1913 | 14.13 | EOL | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2017 version 15.7 | 1914 | 14.14 | EOL | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2017 version 15.8 | 1915 | 14.15 | EOL | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2017 version 15.9 | 1916 | 14.16 | Apr 13, 2027 | [Visual Studio 2017 lifecycle](/lifecycle/products/visual-studio-2017) | +| Visual Studio 2019 RTW (16.0) | 1920 | 14.20 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.1 | 1921 | 14.21 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.2 | 1922 | 14.22 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.3 | 1923 | 14.23 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.4 | 1924 | 14.24 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.5 | 1925 | 14.25 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.6 | 1926 | 14.26 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.7 | 1927 | 14.27 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.8, 16.9 a | 1928 | 14.28 | EOL | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2019 version 16.10, 16.11 b | 1929 | 14.29 | Apr 10, 2029 | [Visual Studio 2019 lifecycle](/lifecycle/products/visual-studio-2019) | +| Visual Studio 2022 RTW 17.0 | 1930 | 14.30 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.1 | 1931 | 14.31 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.2 | 1932 | 14.32 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.3 | 1933 | 14.33 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.4 | 1934 | 14.34 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.5 | 1935 | 14.35 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.6 | 1936 | 14.36 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.7 | 1937 | 14.37 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.8 | 1938 | 14.38 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.9 | 1939 | 14.39 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.10 | 1940 | 14.40 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.11 | 1941 | 14.41 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.12 | 1942 | 14.42 | Jul 14, 2026 | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.13 | 1943 | 14.43 | EOL | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | +| Visual Studio 2022 version 17.14 | 1944 | 14.44 | Jan 13, 2032 | [Visual Studio 2022 lifecycle](/lifecycle/products/visual-studio-2022) | + +The following table lists MSVC Build Tools versions for Visual Studio 2026 and later. Starting with Visual Studio 2026, MSVC versioning is decoupled from Visual Studio versioning. EOL (end of life) dates are defined by the [MSVC lifecycle policy](https://aka.ms/msvc/lifecycle). + +| MSVC Build Tools version | `_MSC_VER` | Support | EOL date | More info | +|--|--|--|--|--| +| 14.50 | 1950 | Long-term | Nov 2028 | [What's New for C++ developers in Visual Studio 2026 version 18.0](https://devblogs.microsoft.com/cppblog/whats-new-for-cpp-developers-in-visual-studio-2026-version-18-0/) | +| 14.51 | 1951 | Standard | Feb 2027 | [MSVC lifecycle policy](https://aka.ms/msvc/lifecycle) | +| 14.52 | 1952 | Standard | Previewc | [MSVC lifecycle policy](https://aka.ms/msvc/lifecycle) | + +a Visual Studio 2019 versions 16.8 and 16.9 share the same major and minor versions, and so have the same value for `_MSC_VER`. To distinguish them, use `_MSC_FULL_VER`. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.8 is 192829333. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.9 is 192829910. + +b Visual Studio 2019 versions 16.10 and 16.11 share the same major and minor versions, and so have the same value for `_MSC_VER`. To distinguish them, use `_MSC_FULL_VER`. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.10 is 192929917. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.11 is 192930129. + +c MSVC Build Tools version 14.52 is in preview. The EOL date will be established upon general availability. ## A brief history of Microsoft C++ compiler versioning @@ -52,90 +157,41 @@ The macros reflect these values like this: ### Visual Studio 2026 and later -- The compiler minor version is no longer incremented in relation to Visual Studio version updates. -- The minor version increments by 1 with each new MSVC release. -- Not every new Visual Studio version will ship a new MSVC compiler version. +The MSVC build tools that ship with Visual Studio 2026 and later start at version 14.50, and `_MSC_VER` starts at 1950. A new MSVC version—14.51/1951, 14.52/1952, and so on, ships every six months. Support follows the [MSVC lifecycle policy](https://aka.ms/msvc/lifecycle). -### Service releases starting with Visual Studio 2017 +This versioning system differs from earlier Visual Studio releases because MSVC versioning is now separate from Visual Studio versioning. That means the compiler minor version can stay the same across multiple Visual Studio updates. -Servicing releases are distinguished by `_MSC_FULL_VER`. The build field (the BBBBB in the MMNNBBBBB version number) typically increases by 1. +At any given time, the Visual Studio Installer can offer several MSVC versions: -For example, two cases where `_MSC_FULL_VER` is useful is to distinguish Visual Studio 2019 version 16.8 from 16.9, and Visual Studio 2019 version 16.10 from 16.11. That's because those versions share the same major and minor versions, and so have the same value for `_MSC_VER`. +- A preview toolset with the newest changes +- The current default toolset +- Earlier toolsets that are still in support -To distinguish these versions, use `_MSC_FULL_VER`.\ -The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.8 is 192829333.\ -The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.9 is 192829910. +For example, as of May 2026: -## Version macros +- **14.52** is the preview toolset and gets regular feature and fix updates. +- **14.51** is the default toolset released in May 2026, with 9 months of support. +- **14.50** is the toolset released in November 2025, with 3 years of support. -Recall that the version number consists of four fields: - -M - major version (two digits)\ -N - minor version (two digits)\ -B - build version (five digits)\ -R - revision version +By November 2026, we expect **14.53** to become the new preview toolset, **14.52** to become the default toolset, and **14.51** and **14.50** to remain in support under the [MSVC lifecycle policy](https://aka.ms/msvc/lifecycle). -**[`_MSC_VER`](../preprocessor/predefined-macros.md)** distinguishes between major and minor releases. It has the form: MMNN. +Microsoft changed to this model for three reasons: +- It shortens the time between MSVC feature development and preview availability from months to a week or so. +- It keeps the MSVC release cadence aligned with Visual Studio and long-term servicing releases aligned with .NET Long Term Support (LTS) releases. +- It reduces the complexity of servicing older compilers. -**[`_MSC_FULL_VER`](../preprocessor/predefined-macros.md)** represents the major, minor, and build version of the compiler. It has the form: MMNNBBBBB. Use it to distinguish between different versions of the compiler, including servicing releases. For more information about Visual Studio 2019 versions 16.8, 16.9, 16.10 and 16.11, see [Service releases starting with Visual Studio 2017](#service-releases-starting-with-visual-studio-2017). - -**[`_MSC_BUILD`](../preprocessor/predefined-macros.md)** represents the build version of the compiler. It has the form: R. Use it to distinguish between servicing releases. +### Service releases starting with Visual Studio 2017 -When the major version changed between Visual Studio 2013 and Visual Studio 2015, `_MSC_VER` reflected the change by going from 1800 to 1900. +Use `_MSC_FULL_VER` to distinguish servicing releases. The build field (the BBBBB in the MMNNBBBBB version number) typically increases by 1. -An example of a minor change is from Visual Studio 2022 version 17.1 to Visual Studio 2022 version 17.2. In that case, `_MSC_VER` changed from 1931 to 1932. +For example, `_MSC_FULL_VER` is useful to distinguish Visual Studio 2019 version 16.8 from 16.9, and Visual Studio 2019 version 16.10 from 16.11. Those versions share the same major and minor versions, so they have the same value for `_MSC_VER`. -The following table lists the Visual Studio version corresponding to each Microsoft C++ compiler (`_MSC_VER`) and MSVC Build Tools release: - -| Visual Studio version | `_MSC_VER` | MSVC Build Tools version | -|--|--|--| -| Visual Studio 6.0 | 1200 | 6.0 | -| Visual Studio .NET 2002 (7.0) | 1300 | 7.0 | -| Visual Studio .NET 2003 (7.1) | 1310 | 7.1 | -| Visual Studio 2005 (8.0) | 1400 | 8.0 | -| Visual Studio 2008 (9.0) | 1500 | 9.0 | -| Visual Studio 2010 (10.0) | 1600 | 10.0 | -| Visual Studio 2012 (11.0) | 1700 | 11.0 | -| Visual Studio 2013 (12.0) | 1800 | 12.0 | -| Visual Studio 2015 (14.0) | 1900 | 14.0 | -| Visual Studio 2017 RTW (15.0) | 1910 | 14.10 | -| Visual Studio 2017 version 15.3 | 1911 | 14.11 | -| Visual Studio 2017 version 15.5 | 1912 | 14.12 | -| Visual Studio 2017 version 15.6 | 1913 | 14.13 | -| Visual Studio 2017 version 15.7 | 1914 | 14.14 | -| Visual Studio 2017 version 15.8 | 1915 | 14.15 | -| Visual Studio 2017 version 15.9 | 1916 | 14.16 | -| Visual Studio 2019 RTW 16.0 | 1920 | 14.20 | -| Visual Studio 2019 version 16.1 | 1921 | 14.21 | -| Visual Studio 2019 version 16.2 | 1922 | 14.22 | -| Visual Studio 2019 version 16.3 | 1923 | 14.23 | -| Visual Studio 2019 version 16.4 | 1924 | 14.24 | -| Visual Studio 2019 version 16.5 | 1925 | 14.25 | -| Visual Studio 2019 version 16.6 | 1926 | 14.26 | -| Visual Studio 2019 version 16.7 | 1927 | 14.27 | -| Visual Studio 2019 version 16.8, 16.9 a | 1928 | 14.28 | -| Visual Studio 2019 version 16.10, 16.11 b | 1929 | 14.29 | -| Visual Studio 2022 RTW 17.0 | 1930 | 14.30 | -| Visual Studio 2022 version 17.1 | 1931 | 14.31 | -| Visual Studio 2022 version 17.2 | 1932 | 14.32 | -| Visual Studio 2022 version 17.3 | 1933 | 14.33 | -| Visual Studio 2022 version 17.4 | 1934 | 14.34 | -| Visual Studio 2022 version 17.5 | 1935 | 14.35 | -| Visual Studio 2022 version 17.6 | 1936 | 14.36 | -| Visual Studio 2022 version 17.7 | 1937 | 14.37 | -| Visual Studio 2022 version 17.8 | 1938 | 14.38 | -| Visual Studio 2022 version 17.9 | 1939 | 14.39 | -| Visual Studio 2022 version 17.10 | 1940 | 14.40 | -| Visual Studio 2022 version 17.11 | 1941 | 14.41 | -| Visual Studio 2022 version 17.12 | 1942 | 14.42 | -| Visual Studio 2022 version 17.13 | 1943 | 14.43 | -| Visual Studio 2022 version 17.14 | 1944 | 14.44 | - -a Visual Studio 2019 versions 16.8 and 16.9 share the same major and minor versions (and so have the same value for `_MSC_VER`). To distinguish them, use `_MSC_FULL_VER`. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.8 is 192829333. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.9 is 192829910. - -b Visual Studio 2019 versions 16.10 and 16.11 share the same major and minor versions (and so have the same value for `_MSC_VER`). To distinguish them, use `_MSC_FULL_VER`. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.10 is 192929917. The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.11 is 192930129. +To distinguish these versions, use `_MSC_FULL_VER`.\ +The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.8 is 192829333.\ +The minimum value of `_MSC_FULL_VER` for Visual Studio 2019 version 16.9 is 192829910. ## See also -[`_MSC_VER`](../preprocessor/predefined-macros.md)\ -[Visual C++ compiler version blog post](https://devblogs.microsoft.com/cppblog/visual-c-compiler-version/) +- [Install the Microsoft C++ (MSVC) Build Tools](acquire-msvc.md) +- [`_MSC_VER`](../preprocessor/predefined-macros.md) +- [Visual C++ compiler version blog post](https://devblogs.microsoft.com/cppblog/visual-c-compiler-version/) diff --git a/docs/overview/how-to-report-a-problem-with-the-visual-cpp-toolset.md b/docs/overview/how-to-report-a-problem-with-the-visual-cpp-toolset.md index 5664f47bcee..579d8db1796 100644 --- a/docs/overview/how-to-report-a-problem-with-the-visual-cpp-toolset.md +++ b/docs/overview/how-to-report-a-problem-with-the-visual-cpp-toolset.md @@ -422,6 +422,6 @@ To maintain your privacy and keep your sensitive information out of public view, ## How to report a C++ documentation issue -If you see an issue with a document, a bad code sample, a confusing explanation, a critical omission, or even just a typo, you can easily let us know by using the feedback buttons on the page. Since 2024, we no longer use GitHub issues to track problems reported. For more information, see [Announcing a new way to give feedback on Microsoft Learn](https://techcommunity.microsoft.com/blog/microsoftlearnblog/announcing-a-new-way-to-give-feedback-on-microsoft-learn/4027635). +If you see an issue with a document, a bad code sample, a confusing explanation, a critical omission, or even just a typo, you can easily let us know by using the feedback buttons on the page. Since 2024, we no longer use GitHub issues to track problems reported. For more information, see [Announcing a new way to give feedback on Microsoft Learn](https://techcommunity.microsoft.com/blog/skills-hub-blog/announcing-a-new-way-to-give-feedback-on-microsoft-learn/4027635). [Our C++ docs are open source](https://github.com/MicrosoftDocs/cpp-docs/), so if you'd like to submit a fix yourself, you can. For more information about how you can contribute to our documentation, see our [Contributing guide](https://github.com/MicrosoftDocs/cpp-docs/blob/main/CONTRIBUTING.md) on GitHub. diff --git a/docs/overview/media/acquire-msvc/installer-individual-components-msvc-versions.png b/docs/overview/media/acquire-msvc/installer-individual-components-msvc-versions.png new file mode 100644 index 00000000000..8112225dd1b Binary files /dev/null and b/docs/overview/media/acquire-msvc/installer-individual-components-msvc-versions.png differ diff --git a/docs/overview/media/acquire-msvc/installer-more-menu-uninstall.png b/docs/overview/media/acquire-msvc/installer-more-menu-uninstall.png new file mode 100644 index 00000000000..3c8ffba9a7c Binary files /dev/null and b/docs/overview/media/acquire-msvc/installer-more-menu-uninstall.png differ diff --git a/docs/overview/media/acquire-msvc/installer-workload-desktop-cpp-msvc-preview.png b/docs/overview/media/acquire-msvc/installer-workload-desktop-cpp-msvc-preview.png new file mode 100644 index 00000000000..28da4760edd Binary files /dev/null and b/docs/overview/media/acquire-msvc/installer-workload-desktop-cpp-msvc-preview.png differ diff --git a/docs/overview/media/acquire-msvc/project-properties-msvc-build-tools-version.png b/docs/overview/media/acquire-msvc/project-properties-msvc-build-tools-version.png new file mode 100644 index 00000000000..3ad4fe497ca Binary files /dev/null and b/docs/overview/media/acquire-msvc/project-properties-msvc-build-tools-version.png differ diff --git a/docs/overview/media/acquire-msvc/project-properties-use-msvc-build-tools-preview.png b/docs/overview/media/acquire-msvc/project-properties-use-msvc-build-tools-preview.png new file mode 100644 index 00000000000..ca7583ec473 Binary files /dev/null and b/docs/overview/media/acquire-msvc/project-properties-use-msvc-build-tools-preview.png differ diff --git a/docs/overview/msvc-conformance-improvements.md b/docs/overview/msvc-conformance-improvements.md index e9f57255dfa..71c66d185d9 100644 --- a/docs/overview/msvc-conformance-improvements.md +++ b/docs/overview/msvc-conformance-improvements.md @@ -1,13 +1,13 @@ --- title: "/C++ Conformance improvements, behavior changes, and bug fixes in Microsoft C++ (MSVC) Build Tools" description: "Summary of conformance improvements in Microsoft C/C++ (MSVC)" -ms.date: 11/03/2025 +ms.date: 05/12/2026 ms.service: "visual-cpp" ms.subservice: "cpp-lang" --- # C/C++ Conformance improvements, behavior changes, and bug fixes in Microsoft C++ (MSVC) Build Tools -Microsoft C++ (MSVC) Build Tools makes conformance improvements and bug fixes in every release. Starting with Visual Studio 2026 version 18.0, major improvements are organized by MSVC Build Tools version number. To jump directly to the changes for a specific version, use the **In this article** links at the top of this article. +We make conformance improvements and bug fixes in every release of Microsoft C++ (MSVC) Build Tools. Starting with Visual Studio 2026 version 18.0, we organize major improvements by MSVC Build Tools version number. Use the **In this article** links at the top of this article to jump directly to the changes for a specific version. For changes in earlier versions of Visual Studio: @@ -18,9 +18,51 @@ For changes in earlier versions of Visual Studio: | 2017 | [C++ conformance improvements in Visual Studio 2017](cpp-conformance-improvements-2017.md) | | 2003-2015 | [Visual C++ What's New 2003 through 2015](../porting/visual-cpp-what-s-new-2003-through-2015.md) | +## C++ conformance improvements, behavior changes, and bug fixes in MSVC Build Tools v14.51 + +MSVC Build Tools v14.51 continues the progress toward C++23 conformance with several key language feature implementations and numerous Core Working Group (CWG) issue resolutions. This release focuses on compile-time evaluation improvements, Unicode support enhancements, and refined `consteval` handling. + +This version shipped first with Visual Studio 2026 version 18.6 and includes version 19.51 of the MSVC compiler. + +Key highlights of this release include: +- Static `constexpr` variables in `constexpr` functions (P2647R1) +- Relaxed `constexpr` restrictions (P2448R2) +- Unicode support improvements (P2029R4, P2071R2, P2314R4) +- Improved `consteval` function handling with default-enabled experimental features +- New standard library headers `` and `` + +For more information about library features and other updates, see [C++23 Support in MSVC Build Tools 14.51](https://devblogs.microsoft.com/cppblog/c23-support-in-msvc-build-tools-14-51) and [STL Changelog](https://github.com/microsoft/STL/wiki/Changelog). + +### P2647R1: Static constexpr variables in constexpr functions + +[P2647R1](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2647r1.html) allows static local variables to be declared `constexpr` within `constexpr` functions, reducing friction when marking existing functions as `constexpr`. + +```cpp +constexpr char xdigit(int n) +{ + static constexpr char digits[] = "0123456789abcdef"; + return digits[n]; +} +``` + +This feature improves both compile-time evaluation and run-time optimization. Previously, static local variables couldn't be marked `constexpr`, which made it difficult to declare lookup tables inside `constexpr` functions. Now the compiler can evaluate these functions at compile time when possible, while also generating optimized run-time code that accesses the static storage directly. + +### Other C++23 features + +Other C++23 features implemented in this release include Unicode support improvements, labels at the end of compound statements for C compatibility, Class Template Argument Deduction (CTAD) from inherited constructors, and meaningful exports for modules. For more information and related Core Working Group (CWG) issue resolutions, see the [C++23 Support in MSVC Build Tools 14.51](https://devblogs.microsoft.com/cppblog/c23-support-in-msvc-build-tools-14-51). + +### Standard Library + +MSVC Build Tools v14.51 adds new standard library features including: +- `` and `` headers +- Type traits for detecting references binding to temporaries ([P2255R2](https://wg21.link/p2255r2)) +- Explicit lifetime management ([P2590R2](https://wg21.link/p2590r2)), and `is_implicit_lifetime` ([P2674R1](https://wg21.link/P2674R1)). +- Major `` overhaul, SIMD-vectorized STL algorithms using NEON for ARM64/ARM64EC, and 18 Library Working Group (LWG) issue resolutions. +For the complete list, see the [STL Changelog](https://github.com/microsoft/STL/wiki/Changelog). + ## C++ conformance improvements, behavior changes, and bug fixes in MSVC Build Tools v14.50 -MSVC Build Tools v14.50 introduces improvements to the MSVC compiler and standard library, including better C++23 standards conformance, enhanced reliability, and improved correctness. This release also includes numerous bug fixes and updates that benefit large-scale C++ development. +MSVC Build Tools v14.50 introduces improvements to the MSVC compiler and standard library including better C++23 standards conformance, enhanced reliability, and improved correctness. This release also includes numerous bug fixes and updates that benefit large-scale C++ development. This version shipped first with Visual Studio 2026 version 18.0 and includes version 19.50 of the MSVC compiler. @@ -35,7 +77,7 @@ Key highlights of this release include: For more information about performance improvements, bug fixes, and conformance updates in the standard library, see [STL Changelog](https://github.com/microsoft/STL/wiki/Changelog), which is updated regularly. -## C++23 Features +## C++23 features MSVC Build Tools v14.50 adds support for several C++23 features, bringing the compiler closer to full C++23 conformance. diff --git a/docs/overview/toc.yml b/docs/overview/toc.yml index 39072bdc2eb..e5c15d2a106 100644 --- a/docs/overview/toc.yml +++ b/docs/overview/toc.yml @@ -8,6 +8,8 @@ items: href: ../overview/overview-of-cpp-development.md - name: What's new for MSVC Build Tools href: ../overview/what-s-new-for-msvc.md + - name: Install the Microsoft C++ (MSVC) Build Tools + href: ../overview/acquire-msvc.md - name: What's new for C++ in Visual Studio 2022 href: ../overview/what-s-new-for-visual-cpp-in-visual-studio.md - name: What's new for C++ in Visual Studio 2019 diff --git a/docs/overview/what-s-new-for-msvc.md b/docs/overview/what-s-new-for-msvc.md index e9563fdf67e..31aabe88305 100644 --- a/docs/overview/what-s-new-for-msvc.md +++ b/docs/overview/what-s-new-for-msvc.md @@ -1,7 +1,7 @@ --- title: "What's new for MSVC Build Tools" description: "The new features and fixes in the Microsoft C/C++ compiler and tools (MSVC)." -ms.date: 11/11/2025 +ms.date: 05/15/2026 ms.service: "visual-cpp" ms.subservice: "cpp-lang" ms.custom: intro-whats-new @@ -9,10 +9,76 @@ ms.custom: intro-whats-new # What's new for MSVC Build Tools -Version 14.50 brings many updates and fixes to the Microsoft C++ compiler and other build tools. +Version 14.51 brings many updates and fixes to the Microsoft C++ compiler and other build tools. - For more information about what's new in all of Visual Studio, see [Visual Studio 2026 release notes](/visualstudio/releases/2026/release-notes). +## What's new for MSVC Build Tools version 14.51 + +* Introduced in Visual Studio 2026 version 18.6 released May 2026. + +Visual Studio 2026 version 18.6 ships with the v145 platform toolset for MSBuild C++ projects and Microsoft C++ (MSVC) Build Tools version 14.51. To access all the new language features, build with `/std:c++latest`. Or, if you want to be restricted to features up to C++23, use `/std:c++23preview`. + +MSVC Build Tools version 14.51 preserves binary compatibility with code built with MSVC tools shipped in Visual Studio 2015 or later. For more information about binary compatibility, see [C++ binary compatibility between Visual Studio versions](/cpp/porting/binary-compat-2015-2017). + +| For detailed information about | See | +|---|---| +| What's new for C++ developers | [MSVC Build Tools version 14.51 Release Candidate Now Available](https://devblogs.microsoft.com/cppblog/msvc-build-tools-version-14-51-release-candidate-now-available/) | +| Standard Library (STL) improvements | [STL Changelog MSVC Build Tools 14.51](https://github.com/microsoft/STL/wiki/Changelog#msvc-build-tools-1451) | +| C++ language conformance improvements | [C/C++ Conformance improvements, behavior changes, and bug fixes in Microsoft C++ (MSVC) Build Tools](msvc-conformance-improvements.md) | + +Here's a quick highlight of some of the new features in MSVC Build Tools version 14.51: + +### C++ language enhancements + +- More C++23 and C++20 features and conformance issue fixes. For full C++23 details, see [C++23 Support in MSVC Build Tools 14.51](https://devblogs.microsoft.com/cppblog/c23-support-in-msvc-build-tools-14-51). +- Multiple fixes to `consteval` function handling, including support for constexpr `new`/`delete` in modules. The `/experimental:constevalVfuncVtable` behavior is now enabled by default. +- Added support for C language features: `_Atomic` qualifier and `__typeof__` for function types. +- Fixed incorrect diagnostics for C99 flexible array members. +- MSVC now generates IFC files according to [version 0.44](https://github.com/microsoft/ifc-spec/releases/tag/0.44) of the [IFC specification](https://github.com/microsoft/ifc-spec). +- Improved parser error recovery. + +## C language enhancements + +Added `_Atomic` qualifier support and added `__typeof__` support for function types. +Fixed [C4319](/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4319) not being emitted when compiling C code. + +### Standard Library enhancements + +- Added new C++23 headers: `` ([P0429R9](https://wg21.link/P0429R9)) and `` ([P1222R4](https://wg21.link/P1222R4)). +- **Massive `` overhaul:** Fixed long-standing correctness and performance problems. The implementation includes significant performance improvements. +- **ARM64 NEON vectorization:** First release shipping NEON-vectorized STL algorithms for ARM64/ARM64EC. Previously, only x64/x86 received SIMD optimizations with SSE4.2 and AVX2. Vectorized implementations are now available for algorithms including `swap_ranges()`, `rotate()`, `reverse()`, `min_element()`, `max_element()`, `find()`, `count()`, and more. +- Implemented 18 Library Working Group (LWG) issue resolutions, including fixes for duration conversion overflow, `construct_at` array support, and `optional` const overloads. +- Optimized integer-to-string conversions by printing digits in pairs. The Standard Template Library is now optimized for speed instead of size. +- Added type traits to detect references binding to temporaries ([P2255R2](https://wg21.link/P2255R2)). +- Added explicit lifetime management support ([P2590R2](https://wg21.link/P2590R2)). +- Enhanced debugger visualizations, including a `c_str()` intrinsic function for `basic_string` that enables conditional breakpoints. + +### Build enhancements + +- **Arm SVE support:** First Arm Scalable Vector Extension (SVE) support in MSVC, including frontend type support, intrinsic lowering, callee-saved register unwinding, and DIA SDK support. +- **Sample-based PGO:** Preview support for sample-based profile guided optimizations. For more information, see [Use Sample Profile Guided Optimization (SPGO) to improve C++ performance](../build/sample-profile-guided-optimization.md). +- The C++ backend optimizer improves code generation, including better inlining, loop optimizations, and pattern matching. +- **Experimental support for x64 Unwind Version 3 MASM directives**. For more information, see [Unwind Version 3 directives (experimental)](../assembler/masm/directives-reference.md#x64-unwind-version-3-experimental) +- **Intel APX preview:** Preview support for Intel Advanced Performance Extensions. For more information, see [/feature (x64)](../build/reference/feature-x64.md), [`[[msvc::enable(feature:APX)]]`](../cpp/attributes.md#msvcenablefeatureapx), and [`[[msvc::disable(feature:APX)]]`](../cpp/attributes.md#msvcdisablefeatureapx). +- Enabled debug info pruning to reduce PDB sizes. + +### Deprecations + +- The following experimental coroutine headers are now deprecated: ``, ``, and ``. Transition to standard C++20 coroutines using the `` header. + +### Removed features + +The following long-deprecated non-Standard features have been removed: + +- **TR1** including the `std::tr1` namespace, old `array::assign()`, and old `` engines and distributions. Deprecated since VS 2017 15.5 (December 2017). +- **`_ALLOW_RTCc_IN_STL`** macro removed. The Standard Template Library doesn't support the `/RTCc` compiler option, but `/RTCs` and `/RTCu`/`/RTC1` remain supported. +- **`` and ``**. Deprecated since VS 2015 (July 2015). +- **``**. Deprecated since VS 2019 16.3 (September 2019). +- **`stdext::checked_array_iterator` and `stdext::unchecked_array_iterator`**. Deprecated since VS 2022 17.8 (November 2023) for C++17 and later. +- **`basic_istream::ipfx()`/`isfx()` and `basic_ostream::opfx()`/`osfx()`**. Deprecated since VS 2022 17.9 (February 2024) for C++17 and later. +- **`locale::empty()`**. Deprecated since VS 2022 17.14 (May 2025). + ## What's new for MSVC Build Tools version 14.50 * Introduced in Visual Studio 2026 version 18.0 released November 2025. @@ -24,7 +90,7 @@ MSVC Build Tools version 14.50 preserves binary compatibility with code built wi | For detailed information about | See | |---|---| | What's new for C++ developers | [What’s New for C++ Developers in Visual Studio 2026 version 18.0](https://devblogs.microsoft.com/cppblog/whats-new-for-cpp-developers-in-visual-studio-2026-version-18-0) | -| Standard Library (STL) improvements | [STL Changelog MSVC Build Tools 14.50](https://github.com/microsoft/STL/wiki/Changelog#msvc-build-tools-1450) | +| C++ Standard Library (STL) improvements | [STL Changelog MSVC Build Tools 14.50](https://github.com/microsoft/STL/wiki/Changelog#msvc-build-tools-1450) | | C++ language updates | [C++ Language Updates in MSVC Build Tools v14.50](https://devblogs.microsoft.com/cppblog/c-language-updates-in-msvc-build-tools-v14-50/) | | C++ language conformance improvements | [C/C++ Conformance improvements, behavior changes, and bug fixes in Microsoft C++ (MSVC) Build Tools](msvc-conformance-improvements.md) | @@ -46,7 +112,7 @@ Here's a quick highlight of some of the new features in MSVC Build Tools version - Copilot Chat allows you to use natural language to get answers to questions (Ask mode) or even implement changes for you automatically (Agent Mode). - Copilot Chat is smarter with improved context for everyday tasks. Expect better results when searching your codebase and referencing specific lines in your code. - A **Copilot Actions** option was added to the right-click context menu in the Visual Studio editor. Use it to quickly bring a specific file or lines of code you select to the attention of Copilot Chat. You can then ask Copilot to explain what the code does, make optimizations, generate comments, generate unit tests, and more. -- Better AI code completions for C++. GitHub Copilot uses context from relevant files to improve inline autocomplete for C++. GitHub Copilot includes other relevant files as context which reduces hallucinations while offering more relevant and accurate suggestions. +- Better AI code completions for C++. GitHub Copilot uses context from relevant files to improve inline autocomplete for C++. GitHub Copilot includes other relevant files as context, which reduces hallucinations while offering more relevant and accurate suggestions. - For more information, see [New GitHub Copilot capabilities for C++ developers: Upgrade MSVC, improve build performance, and refactor C++ code](https://devblogs.microsoft.com/cppblog/new-github-copilot-capabilities-for-c-developers-upgrade-msvc-improve-build-performance-and-refactor-c-code/). ### Build enhancements @@ -64,7 +130,7 @@ Here's a quick highlight of some of the new features in MSVC Build Tools version - Access the new options from **Project Properties** > **Code Analysis** > **Clang-Tidy**: ![Screenshot of Project Properties dialog showing clang-tidy configuration options including processor allocation and custom command line arguments](./media/clang-tidy-improvements.png) -- AddressSanitizer support for ARM64 Builds (Preview): For some time, the MSVC Build Tools have supported building projects that target x64 and x86 with [AddressSanitizer](/cpp/sanitizers/asan), which allows you to identify hard-to-find memory safety issues with zero false positives at runtime and increase memory safety. Now you can use AddressSanitizer to target ARM64. This feature is in preview. +- AddressSanitizer support for ARM64 Builds (Preview): For some time, the MSVC Build Tools supported building projects that target x64 and x86 with [AddressSanitizer](/cpp/sanitizers/asan), which allows you to identify hard-to-find memory safety issues with zero false positives at runtime and increase memory safety. Now you can use AddressSanitizer to target ARM64. This feature is in preview. ### Productivity enhancements @@ -102,4 +168,6 @@ We'd love to hear from you! You can [Report a Problem or Suggest a Feature](/vis ## Blogs -Take advantage of the insights and recommendations available in the [Microsoft Developer Blogs](https://devblogs.microsoft.com/) site to stay up to date on all new releases. The blogs include deep dive posts on a broad range of features. The [C++ Team Blog](https://devblogs.microsoft.com/cppblog) and the [Visual Studio Blog](https://devblogs.microsoft.com/visualstudio) are of particular interest. +Stay up to date on all new releases by taking advantage of the insights and recommendations available in at [Microsoft Developer Blogs](https://devblogs.microsoft.com/). The blogs include deep dive posts on a broad range of features. + +The [C++ Team Blog](https://devblogs.microsoft.com/cppblog) and the [Visual Studio Blog](https://devblogs.microsoft.com/visualstudio) are of particular interest. diff --git a/docs/porting/copilot-app-modernization-cpp.md b/docs/porting/copilot-app-modernization-cpp.md deleted file mode 100644 index d6e23461baf..00000000000 --- a/docs/porting/copilot-app-modernization-cpp.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: "Modernize your C++ project with GitHub Copilot modernization" -description: "Instructions on effectively using GitHub Copilot modernization in your C++ projects" -ms.date: 03/12/2026 -ms.topic: upgrade-and-migration-article -author: michaelbprice -ms.author: miprice ---- - -# Using GitHub Copilot modernization for C++ - -GitHub Copilot modernization for C++ helps you upgrade C++ projects to newer MSVC Build Tools versions. If necessary, Copilot will upgrade your project's settings to use the latest MSVC, and then conduct a thorough assessment of the impact of those changes after executing a build. It develops a plan on how to address each identified problem. Once you approve the plan, the agent completes a sequence of tasks and validates that any changes resolved the identified problems. If there remains work to be done, the agent continues iterating until the problems are resolved or you discontinue the conversation. - -> [!NOTE] -> GitHub Copilot modernization for C++ is currently in preview. - -## Requirements - -- Visual Studio 2026 version 18.3 or later -- A GitHub Copilot account -- A MSBuild-based codebase (`.sln`, `.vcxproj`) OR a CMake-based codebase - -## Enable GitHub Copilot modernization for C++ - -GitHub Copilot modernization for C++ is enabled by default. To disable or explicitly enable the feature, follow these steps. - -1. From Visual Studio, select **Tools > Options...** to open the **Options** window. -1. Navigate to **All Settings > GitHub > Copilot > C/C++**. -1. Select (to enable) or clear (to disable) the checkbox for **Enable GitHub Copilot modernization for C++ (preview)**. -1. Restart Visual Studio for the setting change to take effect. - -:::image type="content" source="media/enable-copilot-app-modernization-cpp.png" alt-text="Screenshot of Visual Studio Options dialog. GitHub > Copilot > C/C++ settings are visible. The modernization for C++ checkbox is enabled." lightbox="media/enable-copilot-app-modernization-cpp.png"::: - -## Upgrade your codebase by using GitHub Copilot modernization for C++ - -This section describes how to start the Modernize agent and the stages it goes through to upgrade your codebase. - -### Start the Modernize agent - -GitHub Copilot modernization is an agent that operates inside the GitHub Copilot Chat window. You can start the agent in any of the following ways: - -- **From the Solution Explorer context menu**: Right-click on the solution or a loaded project in the Solution Explorer, and choose **Modernize** from the context menu. This automatically launches a GitHub Copilot Chat window, activates the Modernize agent, and provides you with relevant prompts to choose from to get you started. - -:::image type="content" source="media/copilot-app-modernization-context-menu.png" alt-text="Screenshot of Visual Studio Solution Explorer showing a right-click context menu with Modernize selected to start the Copilot agent."::: - -- **From GitHub Copilot Chat**: Open the GitHub Copilot Chat Window by selecting **View > GitHub Copilot Chat**. After the GitHub Copilot Chat window opens, mention `@Modernize` in a prompt to activate the Modernize agent. For example, type this prompt: - - `Use @Modernize to update MSVC Build Tools.` - -#### For MSBuild-based codebases targeting an earlier version of MSVC Build Tools - -The first time that you load a `.vcxproj` project that targets an earlier version of the MSVC Build Tools, you see an option to [upgrade project settings to use a newer version of the MSVC Build Tools](/visualstudio/install/setup-assistant). If you retarget any of your projects to a new version of MSVC Build Tools and GitHub Copilot modernization for C++ is enabled, you receive an infobar in Visual Studio prompting you to use GitHub Copilot modernization for C++ to resolve any newly introduced build problems. Selecting **Run GitHub Copilot modernization for C++** launches the GitHub Copilot Chat window, activates the Modernize agent, and provides you with relevant prompts to choose from to get you started. - -### Start the upgrade - -Once the Modernize agent is active, you can instruct it via a prompt to upgrade your MSVC Build Tools, or select the already constructed prompt from the list shown in the window. If you launched the agent directly in the GitHub Copilot Chat window by mentioning `@Modernize` in your prompt, you probably don't need to provide more prompting. - -:::row::: -:::column::: - -**MSBuild Projects** - -:::column-end::: -:::column::: - -**CMake Projects** - -:::column-end::: -:::row-end::: -:::row::: -:::column::: - -:::image type="content" source="media/app-modernization-msbuild-ice-breaker.png" alt-text="Screenshot of GitHub Copilot Chat window. The dropdown is set to Modernize experience and Upgrade MSVC Build Tools to the latest version is highlighted."::: - -:::column-end::: -:::column::: - -:::image type="content" source="media/app-modernization-cmake-ice-breaker.png" alt-text="Screenshot of GitHub Copilot Chat window. The dropdown is set to Modernize experience and Resolve build issues by migrating to modern alternatives is highlighted."::: - -:::column-end::: -:::row-end::: - - -### Assessment stage - -The agent first assesses what kinds of problems show up after upgrading. If you didn't already upgrade the project, the agent guides you through that process before creating its assessment. After ensuring that your project is upgraded, the agent builds your codebase, analyzes the reported warnings and errors, and generates an `assessment.md` file that describes the problems that it found, their severity, and other useful information. This is your opportunity to tell the agent any other context that could help it make a plan. - -One of the things you might choose to do here is to tell the agent not to fix certain discovered problems, because you know that resolving them involves some strategic decisions or because they were preexisting warnings that you decided are acceptable for your project. You should carefully read through the plan, making sure to provide that extra context where it is needed. Once you approve the assessment, the agent moves on to creating a concrete plan on addressing the problems. - -### Planning stage - -Based on the approved assessment and any other context or instructions you provide, the agent creates a `plan.md` file that proposes a detailed plan for resolving each of the identified problems. If the agent produces a plan that doesn't match your organization's coding style or practices, you can provide that guidance to the agent and have it solve the problem differently. After you agree on the plan, the agent moves to the execution stage. - -### Execution stage - -Now that the agent has a plan, it breaks down the necessary tasks to execute the plan. You can define these tasks as finely as you want. The tasks can even include steps to work on a branch or to commit specific changes together in the same commit. After making any changes, the agent builds the project again to confirm that the problems are resolved. If the problems aren't resolved, the agent iterates with you until they're resolved to your satisfaction. - -### Post-upgrade validation - -When the agent finishes, run the changes through any testing infrastructure you have. Have a colleague review the changes in a pull request. Since this feature is currently in preview, you might receive an infobar to complete a product survey to let the product team know how the agent performed on your codebase. The product team looks forward to hearing how they can improve the agent to solve your problems and accelerate your upgrade and modernization efforts. \ No newline at end of file diff --git a/docs/porting/features-deprecated-in-visual-studio.md b/docs/porting/features-deprecated-in-visual-studio.md index c4054812aae..21848bb9152 100644 --- a/docs/porting/features-deprecated-in-visual-studio.md +++ b/docs/porting/features-deprecated-in-visual-studio.md @@ -1,30 +1,44 @@ --- description: "Learn more about: C++ features deprecated or removed from Visual Studio" title: "C++ features deprecated or removed from Visual Studio" -ms.date: 10/29/2025 +ms.date: 05/11/2026 helpviewer_keywords: ["Features deprecated or removed from Visual Studio"] --- # C++ features deprecated or removed from Visual Studio -This article is a non-exhaustive list of C++ features deprecated or removed from Visual Studio 2019 and later. For information on breaking changes and conformance improvements for C++ in the latest version of Visual Studio, see [C++ conformance improvements in Visual Studio](../overview/cpp-conformance-improvements.md). - -## Visual Studio 2019 +This article is a nonexhaustive list of C++ features deprecated or removed from Visual Studio 2019 and later. For information on breaking changes and conformance improvements for C++ in the latest version of Visual Studio, see [C++ conformance improvements in Visual Studio](../overview/cpp-conformance-improvements.md). ### Support for Windows XP development Visual Studio 2019 and later versions don't include current build tools support for creating code for Windows XP. Support for Windows XP development by using the v141_xp build tools that shipped in Visual Studio 2017 is still available as an optional component in the Visual Studio Installer. For information on how to install the v141_xp Windows XP platform toolset, see [Configuring programs for Windows XP](../build/configuring-programs-for-windows-xp.md). +## Visual Studio 2026 (MSVC 14.51) + +- The following experimental coroutine headers are now deprecated: ``, ``, and ``. Transition to standard C++20 coroutines using the `` header. + +### Removed features + +The following long-deprecated non-Standard features are removed: + +- **TR1** including the `std::tr1` namespace, old `array::assign()`, and old `` engines and distributions. Deprecated since VS 2017 15.5 (December 2017). +- **`_ALLOW_RTCc_IN_STL`** macro removed. The Standard Template Library doesn't support the `/RTCc` compiler option, but `/RTCs` and `/RTCu`/`/RTC1` remain supported. +- **`` and ``**. Deprecated since VS 2015 (July 2015). +- **``**. Deprecated since VS 2019 16.3 (September 2019). +- **`stdext::checked_array_iterator` and `stdext::unchecked_array_iterator`**. Deprecated since VS 2022 17.8 (November 2023) for C++17 and later. +- **`basic_istream::ipfx()`/`isfx()` and `basic_ostream::opfx()`/`osfx()`**. Deprecated since VS 2022 17.9 (February 2024) for C++17 and later. +- **`locale::empty()`**. Deprecated since VS 2022 17.14 (May 2025). + ## Visual Studio 2022 ### Support for project upgrade from Visual C++ 6 -Visual Studio 2022 and later versions don't support upgrades from Visual C++ 6 Workspace (*`.dsw`*) and Project (*`.dsp`*) files. Visual Studio no longer registers the *`.dsw`* and *`.dsp`* file extensions as Visual Studio file types. To upgrade a project with these extensions, first use Visual Studio 2019 to upgrade the project to modern Solution (*`.sln`*) and C++ Project (*`.vcxproj`*) files. Then use the current version of Visual Studio to upgrade the project again. +Visual Studio 2022 and later versions don't support upgrades from Visual C++ 6 Workspace (*`.dsw`*) and Project (*`.dsp`*) files. Visual Studio no longer registers the *`.dsw`* and *`.dsp`* file extensions as Visual Studio file types. To upgrade a project with these extensions, first use Visual Studio 2019 to upgrade the project to modern Solution (*`.sln`*) and C++ Project (*`.vcxproj`*) files. Then upgrade the project again using the current version of Visual Studio. ## Visual Studio 2026 -### Support for C++AMP, ARM32 toolchain, and /DEBUG:FASTLINK +### Support for C++AMP, ARM32 toolchain, and `/DEBUG:FASTLINK` -Visual Studio 2026 and later versions don't support C++AMP, the ARM32 toolchain, and /DEBUG:FASTLINK. If you're utilizing `/DEBUG:FASTLINK`, it's recommended to switch to [`/DEBUG:FULL`](/cpp/build/reference/debug-generate-debug-info) for improved debugging support. Developers needing to target ARM32 can continue using the Visual Studio 2022 v143 build tools as detailed in this [Microsoft blog post](https://devblogs.microsoft.com/cppblog/side-by-side-minor-version-msvc-toolsets-in-visual-studio-2019/). +Visual Studio 2026 and later versions don't support C++AMP, the ARM32 toolchain, and /DEBUG:FASTLINK. If you're utilizing `/DEBUG:FASTLINK`, switch to [`/DEBUG:FULL`](/cpp/build/reference/debug-generate-debug-info) for improved debugging support. Developers needing to target ARM32 can continue using the Visual Studio 2022 v143 build tools as detailed in this [Microsoft blog post](https://devblogs.microsoft.com/cppblog/side-by-side-minor-version-msvc-toolsets-in-visual-studio-2019/). ### Deprecation of `/await` @@ -44,4 +58,4 @@ These changes allow for better performance, enhanced security, and alignment wit ### Support for Mobile development with C++ and Embedded and IoT tools -Starting with Visual Studio 2026 (version 18.0), the **Mobile development with C++** workload for iOS and Android targeting in the Visual Studio installer and the **Embedded and IoT tools**--including RTOS Viewer, Serial Monitor, Peripheral Viewer, and ST Project Import--are no longer supported and will be removed in a future update. However, the Android NDKs listed in the Mobile development with C++ workload continue to be supported. \ No newline at end of file +Starting with Visual Studio 2026 (version 18.0), the **Mobile development with C++** workload for iOS and Android targeting in the Visual Studio installer and the **Embedded and IoT tools**--including RTOS Viewer, Serial Monitor, Peripheral Viewer, and ST Project Import--are no longer supported and will be removed in a future update. However, the Android NDKs listed in the Mobile development with C++ workload continue to be supported. diff --git a/docs/porting/github-copilot-modernization-cpp/faq.md b/docs/porting/github-copilot-modernization-cpp/faq.md new file mode 100644 index 00000000000..8a797d09537 --- /dev/null +++ b/docs/porting/github-copilot-modernization-cpp/faq.md @@ -0,0 +1,104 @@ +--- +title: "GitHub Copilot modernization for C++ FAQ" +description: "Frequently asked questions about GitHub Copilot modernization for C++." +author: michaelbprice +ms.author: miprice +ms.date: 05/27/2026 +ms.topic: faq +ai-usage: ai-assisted +--- + +# GitHub Copilot modernization for C++ FAQ + +This FAQ answers common questions C++ users might have about GitHub Copilot modernization. + +## General + +### What is GitHub Copilot modernization for C++? + +GitHub Copilot modernization for C++ is a GitHub Copilot agent for Visual Studio that helps you modernize and upgrade C++ projects to newer tools, libraries, and patterns. It recognizes specific tasks such as upgrading MSVC Build Tools to newer versions and provides additional tools and instructions to accomplish those tasks. It automates assessment, planning, and execution to accomplish the modernization task, and you can run it in a fully automated mode or a guided mode that allows you to approve each step and provide additional guidance. + +### What development environments are supported? + +GitHub Copilot modernization for C++ is available in Visual Studio 2026 version 18.7 and later. + +### Do I need a GitHub Copilot subscription? + +Yes. You need an active GitHub Copilot subscription to use the modernization agent. + +### Is my code sent to external services? + +GitHub Copilot processes code snippets according to [GitHub's Copilot privacy policy](https://docs.github.com/copilot/responsible-use-of-github-copilot-features/responsible-use-of-github-copilot-chat-in-your-ide). Code isn't retained beyond the immediate session. Workflow files such as `scenario-instructions.md` and `tasks.md` stay in your repository and aren't transmitted to external services. + +## MSVC upgrade scenarios + +### What project types are supported? + +The agent supports these project types: + +- MSBuild-based projects (`.sln` and `.vcxproj`). +- CMake-based projects. + +The agent does not currently support Unreal Engine projects (`.uproject`). + +### What does the agent actually change in my code? + +The agent modifies source code to resolve build errors and warnings introduced by upgrading to a newer version of MSVC Build Tools. Common changes include replacing deprecated APIs, fixing issues caused by using a more conformant compiler, updating include directives for removed or relocated headers, and resolving linker errors caused by library changes. When your project is in a git repository, all changes are committed so you can review and revert individual modifications. + +### Can I control what the agent changes? + +Yes. You can review and approve the plan before execution starts, tell the agent to skip specific issues or tasks, and provide preferences in `scenario-instructions.md`. You can also pause execution, redirect the agent, or revert any commit it makes. + +### Does the agent run tests? + +The agent validates changes by building the project after each task. If your project runs tests as part of the build, those tests run too. You can also tell the agent to skip test validation for specific tasks. + +### What if the agent makes a mistake? + +Stop the agent and tell it right away. It will adapt and apply corrections when you tell the agent to resume. You can also run `git revert HEAD`, ask the agent to try a different approach, or make a manual fix. + +For more information, see [Troubleshoot GitHub Copilot modernization for C++](./troubleshooting.md). + +### Can I upgrade only part of my solution? + +Yes. Tell the agent which projects to upgrade, for example, `Upgrade only the CoreLib project to the latest MSVC Build Tools.` The agent scopes its work to the projects you specify. + +## State and sessions + +### Where does the agent store its state? + +All state lives in `.github/upgrades/{SCENARIO ID}` inside your repository. This includes the assessment, plan, task progress, your preferences, and execution logs. + +### Can I resume an interrupted upgrade? + +Yes. You can close Visual Studio or end the chat session at any time. When you start a new conversation, the agent detects the existing state and picks up where it left off. + +### Should I commit the `.github/upgrades` folder? + +Yes. Committing the folder to your branch backs up upgrade progress, lets team members view the upgrade state, and helps the agent resume from the correct state. You can remove the folder after the upgrade is complete. + +### Can multiple people work on the same upgrade? + +The state files in `.github/upgrades` are shareable through Git. However, only one person should actively interact with the agent at a time to avoid conflicting changes. + +## Compatibility + +### Which MSVC Build Tools versions can I upgrade from? + +The agent supports upgrading from any earlier version of the MSVC Build Tools to the latest version supported by your Visual Studio installation. + +### Does the agent handle third-party library compatibility? + +The agent identifies third-party library compatibility issues during assessment. It suggests alternatives or workarounds when they're available. If a library isn't compatible with the target toolset, the agent documents the issue so you can decide how to proceed. + +### Can I use the agent with precompiled headers? + +Yes. The agent understands precompiled header configurations and accounts for them during the upgrade process. + +## Related content + +- [GitHub Copilot modernization for C++ overview](./overview.md) +- [Install GitHub Copilot modernization for C++](./install.md) +- [Scenarios and skills reference](./scenarios-and-skills.md) +- [Walkthrough - Hilo](./walkthrough-hilo.md) +- [Troubleshoot GitHub Copilot modernization for C++](./troubleshooting.md) diff --git a/docs/porting/github-copilot-modernization-cpp/install.md b/docs/porting/github-copilot-modernization-cpp/install.md new file mode 100644 index 00000000000..7aece28c21b --- /dev/null +++ b/docs/porting/github-copilot-modernization-cpp/install.md @@ -0,0 +1,54 @@ +--- +title: "Install GitHub Copilot modernization for C++" +description: "Set up GitHub Copilot modernization for C++ in Visual Studio to start upgrading your C++ projects." +ms.date: 6/11/2026 +ms.topic: how-to +author: michaelbprice +ms.author: miprice +ai-usage: ai-assisted +--- + +# Install GitHub Copilot modernization for C++ + +GitHub Copilot modernization helps you modernize your C++ codebase. Follow these steps to install the feature in Visual Studio. + +## Prerequisites + +- Windows operating system. +- [Visual Studio 2026 version 18.7 or later](https://aka.ms/vs/download). +- One or more of the following C++ development workloads: + - **Desktop development with C++** + - **Game development with C++** + - **Linux, Mac, and embedded development with C++** +- These optional components must be enabled: **GitHub Copilot**, **GitHub Copilot modernization** +- GitHub Copilot subscription (paid or free). +- [Sign in to Visual Studio with a GitHub account](/visualstudio/ide/work-with-github-accounts) that has [Copilot access](https://docs.github.com/copilot/get-started/plans#ready-to-choose-a-plan). +- Code written in C or C++ and in either a MSBuild-based codebase that uses `.sln` or `.vcxproj`, or a CMake-based codebase. Unreal Engine projects (`.uproject`) are not currently supported. + +## Verify your Visual Studio version + +If you need to update Visual Studio, select **Help** > **Check for Updates**, or download the latest version from [Visual Studio downloads](https://aka.ms/vs/download). + +## Enable or disable the feature + +GitHub Copilot modernization for C++ is enabled by default. To disable or explicitly enable the feature: + +1. In Visual Studio, select **Tools** > **Options** to open the **Options** dialog. +1. Navigate to **GitHub** > **Copilot** > **C/C++**. +1. Select the **Enable GitHub Copilot modernization for C++** checkbox to enable the feature, or clear it to disable the feature. +1. Restart Visual Studio for the setting change to take effect. + +## Verify the agent is available + +After setup, verify that the modernization agent is accessible: + +1. Open a C++ solution or project in Visual Studio. +1. Open **GitHub Copilot Chat** by selecting **View** > **GitHub Copilot Chat**. +1. Type `@Modernize` in the chat input. If the agent responds, setup is complete. + +Alternatively, right-click your solution or project in **Solution Explorer**. If **Modernize** appears in the context menu, the agent is ready. + +## Related content + +- [GitHub Copilot modernization for C++ overview](./overview.md) +- [Troubleshoot GitHub Copilot modernization for C++](./troubleshooting.md) diff --git a/docs/porting/github-copilot-modernization-cpp/overview.md b/docs/porting/github-copilot-modernization-cpp/overview.md new file mode 100644 index 00000000000..198394da51f --- /dev/null +++ b/docs/porting/github-copilot-modernization-cpp/overview.md @@ -0,0 +1,103 @@ +--- +title: "GitHub Copilot modernization for C++ overview" +description: "Learn how GitHub Copilot modernization helps you upgrade C++ projects to newer MSVC Build Tools versions through automated assessment, planning, and execution." +author: michaelbprice +ms.author: miprice +ms.date: 05/27/2026 +ms.topic: overview +ai-usage: ai-assisted +--- + +# What is GitHub Copilot modernization? + +GitHub Copilot modernization is a GitHub Copilot agent that helps you upgrade and modernize your C++ projects. It guides you through assessment, solution recommendations, code fixes, and validation within Visual Studio. + +## Scenarios + +The agent provides end-to-end modernization workflows called _scenarios_. Each scenario guides you through a specific type of modernization task. + +| Scenario | Description | Example prompt | +| --- | --- | --- | +| **MSVC Build Tools upgrade (MSBuild)** | Upgrades MSBuild-based projects (`.sln`, `.vcxproj`) to a newer version of MSVC Build Tools and resolves upgrade-related build issues. | _"Upgrade my projects to use the latest, installed version of the MSVC Build Tools"_ | +| **MSVC Build Tools upgrade (CMake)** | Resolves upgrade-related build issues in your CMake-based projects after configuring the project with a newer version of MSVC Build Tools. | _"Resolve any build issues caused by upgrading my project to use the newer MSVC Build Tools"_ | + +> [!NOTE] +> If you'd like to propose or upvote other modernization scenarios, visit [Developer Community](https://developercommunity.microsoft.com/cpp). + +For a full reference of all scenarios, see [Scenarios and skills reference](./scenarios-and-skills.md). + +## Prerequisites + +Before you start, make sure you have: + +- Visual Studio 2026 version 18.7 or later. +- A GitHub Copilot subscription. +- An MSBuild-based codebase (`.sln`, `.vcxproj`) or a CMake-based codebase. + +For detailed setup steps, see [Install GitHub Copilot modernization for C++](./install.md). + +## How it works + +To start the modernization workflow: + +1. Open your C++ project or solution in Visual Studio. +1. Start the agent: In **Solution Explorer**, right-click your solution or project and select **Modernize**. Or, in **GitHub Copilot Chat**, type `@Modernize`. +1. Tell the agent what to upgrade. + +If your Visual Studio installation is missing the MSVC Build Tools that your project currently uses, the Setup Assistant should appear when you load your project. You can use the Setup Assistant to either install the missing MSVC version or to retarget to the installed MSVC version. If you retarget any projects, you will get an infobar message that can launch you directly into the Modernize agent workflow. + +When you ask the agent to upgrade your project, it prompts you to create a new branch if you're in a Git repository. Then it runs a three-stage workflow. Each stage produces Markdown files under `.github/upgrades/{scenarioId}` in your repository so you can review what comes next before you continue. If `.github/upgrades/{scenarioId}` already exists from an earlier attempt, the agent asks whether you want to continue or start fresh. + +### Stage 1: Assessment + +The agent examines your project structure, dependencies, and code patterns and saves a comprehensive assessment to `assessment.md`. The agent also presents strategy decisions for your review, such as upgrade strategy and compatibility handling. + +### Stage 2: Planning + +The agent converts the assessment into a detailed specification. The `plan.md` file documents upgrade strategies, refactoring approaches, and risk mitigations. + +### Stage 3: Execution + +The agent breaks the plan into sequential tasks with validation criteria in `tasks.md`. Each task describes a single change and how the agent confirms it succeeded. + +## Flow modes + +The agent supports two flow modes: + +- **Automatic**: Works through all stages without pausing, stopping only at genuine blockers. This mode is best for straightforward upgrades. +- **Guided**: Pauses at each stage boundary for your review. This mode is best for larger or more complex upgrades. + +You can switch modes at any time by modifying `scenario-instructions.md` or by instructing the agent to switch modes. If running in **Automatic** mode, you may have to stop the agent with the Cancel button in the Copilot Chat prompt window and instruct the agent to resume in **Guided** mode. + +## State management + +The agent stores all state in `.github/upgrades/{scenarioId}`. + +| File | Purpose | +| --- | --- | +| `assessment.md` | Analysis of your solution. | +| `plan.md` | Ordered task plan. | +| `tasks.md` | Live progress dashboard. | +| `scenario-instructions.md` | Agent's persistent memory. | +| `execution-log.md` | Audit trail of all changes. | + +You can close Visual Studio and resume later. The agent picks up where it left off by reading the state files. + +> [!TIP] +> If you want to work on your upgrade over a longer period of time while doing other work, consider committing the `.github/upgrades` folder to your branch in distinct commits. The committed state serves as a backup and lets team members view upgrade progress. Distinct commits allow you to easily remove them from your local git history before merging your branch if you do not want them permanently committed to your repository. + +## Provide feedback + +Microsoft values your feedback and uses it to improve the agent. Leave feedback using either of these options: + +- In Visual Studio, use the [Suggest a feature](/visualstudio/ide/suggest-a-feature) and [Report a problem](/visualstudio/ide/report-a-problem) options. + +- File an issue on [Developer Community](https://developercommunity.visualstudio.com/cpp). + +## Related content + +- [Install GitHub Copilot modernization for C++](./install.md) +- [Scenarios and skills reference](./scenarios-and-skills.md) +- [Walkthrough - Hilo](./walkthrough-hilo.md) +- [Troubleshoot GitHub Copilot modernization for C++](./troubleshooting.md) +- [FAQ](./faq.md) diff --git a/docs/porting/github-copilot-modernization-cpp/scenarios-and-skills.md b/docs/porting/github-copilot-modernization-cpp/scenarios-and-skills.md new file mode 100644 index 00000000000..5e0959d12cf --- /dev/null +++ b/docs/porting/github-copilot-modernization-cpp/scenarios-and-skills.md @@ -0,0 +1,84 @@ +--- +title: "GitHub Copilot modernization for C++ scenarios and skills" +description: "Reference of available upgrade scenarios and skills for GitHub Copilot modernization for C++." +ms.date: 05/27/2026 +ms.topic: reference +author: michaelbprice +ms.author: miprice +ai-usage: ai-assisted +--- + +# Scenarios and skills reference + +GitHub Copilot modernization agent provides managed, end-to-end modernization workflows called _scenarios_. Each scenario guides you through a specific type of activity in practical C++ modernization work. This page documents the available scenarios and skills so you can understand what the agent can do for your project. + +## Scenarios + +A _scenario_ is a managed workflow that guides you through a specific type of modernization activity. + +### How scenarios are discovered + +You don't need to memorize scenario names. The agent detects your project type and suggests the relevant scenario automatically. + +To list the scenarios the agent supports, ask _"What scenarios are available for my project?"_ in the GitHub Copilot chat window. + +### Available scenarios + +| Scenario | Project type | Description | Example prompt | +|---|---|---|---| +| **MSVC Build Tools upgrade (MSBuild)** | `.sln`, `.vcxproj` | Upgrades MSBuild-based projects (`.sln`, `.vcxproj`) to a newer version of MSVC Build Tools and resolves upgrade-related build issues. | _"Upgrade my projects to use the latest, installed version of the MSVC Build Tools"_ | +| **MSVC Build Tools upgrade (CMake)** | CMake | Resolves upgrade-related build issues in your CMake-based projects after configuring the project with a newer version of MSVC Build Tools. | _"Resolve any build issues caused by upgrading my project to use the newer MSVC Build Tools"_ | + +> [!NOTE] +> If you'd like to propose or upvote other modernization scenarios, visit [Developer Community](https://developercommunity.microsoft.com/cpp). + +#### MSVC Build Tools upgrade (MSBuild) + +This scenario handles the complete upgrade workflow for MSBuild-based C++ projects: + +1. **Retargeting**: Updates project settings to target the latest, installed MSVC Build Tools and Platform Toolset. +1. **Build analysis**: Builds the solution and catalogs all errors and warnings introduced by the upgrade. +1. **Updating code**: Replaces deprecated APIs, addresses conformance issues, and helps with breaking changes. +1. **Validation**: Rebuilds to confirm all issues are resolved. + +For example, this scenario addresses issues like: + +- Deprecated CRT functions, for example, `sprintf` to `sprintf_s`. +- C++ conformance changes, for example, stricter template parsing. +- Standard library changes between MSVC versions, such as removed, experimental namespaces (e.g. `std::tr1`). +- Warning-as-error promotions in newer toolsets. +- Linker errors for APIs removed from the Windows SDK. + +#### MSVC Build Tools upgrade (CMake) + +This scenario handles upgrade workflows for CMake-based C++ projects: + +1. **Build analysis**: Builds the project and catalogs all errors and warnings introduced by the upgrade. +1. **Updating code**: Replaces deprecated APIs, addresses conformance issues, and helps with breaking changes. +1. **Validation**: Rebuilds to confirm all issues are resolved. + +For example, this scenario addresses issues like: + +- Deprecated CRT functions, for example, `sprintf` to `sprintf_s`. +- C++ conformance changes, for example, stricter template parsing. +- Standard library changes between MSVC versions, such as removed, experimental namespaces (e.g. `std::tr1`). +- Warning-as-error promotions in newer toolsets. +- Linker errors for APIs removed from the Windows SDK. + +### Scenario persistence + +Each active scenario gets its own folder at `.github/upgrades/{scenarioId}`. The scenario folder contains the plan, task progress, your preferences, and execution logs. The folder becomes part of your Git repository. + +## Skills + +_Skills_ are smaller, targeted modernization capabilities that the agent uses within a scenario. When the agent encounters a specific pattern during an upgrade, it loads the relevant skill with detailed instructions. + +Skills load automatically based on what the agent detects in your codebase. You don't need to manage skill loading. + +> [!NOTE] +> There are currently no additional skills specific to C++ modernization scenarios. + +## Related content + +- [GitHub Copilot modernization for C++ overview](./overview.md) +- [Troubleshoot GitHub Copilot modernization for C++](./troubleshooting.md) \ No newline at end of file diff --git a/docs/porting/github-copilot-modernization-cpp/troubleshooting.md b/docs/porting/github-copilot-modernization-cpp/troubleshooting.md new file mode 100644 index 00000000000..60278df9659 --- /dev/null +++ b/docs/porting/github-copilot-modernization-cpp/troubleshooting.md @@ -0,0 +1,129 @@ +--- +title: "Troubleshoot GitHub Copilot modernization for C++" +description: "Solutions to common problems when using GitHub Copilot modernization to upgrade C++ projects." +ms.date: 05/27/2026 +ms.topic: troubleshooting +author: michaelbprice +ms.author: miprice +ai-usage: ai-assisted +--- + +# Troubleshoot GitHub Copilot modernization for C++ + +This article helps you resolve common issues when you use GitHub Copilot modernization to upgrade your C++ projects. If you run into a problem that isn't covered here, use **Help** > **Send Feedback** > **Report a problem** in Visual Studio. + +## Before you start + +### Verify that your solution or project builds + +For MSVC upgrade scenarios, the agent validates changes by building your solution or project. If your solution or project is already broken before you start, the agent will have greater difficulty distinguishing pre-existing issues from problems introduced by the upgrade. + +If you have known build issues, document them in [custom instructions](https://docs.github.com/copilot/concepts/prompting/response-customization?tool=visualstudio), provide them in your response when the agent asks for context during the assessment stage, or add them to `scenario-instructions.md` so the agent knows to ignore them. + +### Commit or stash uncommitted work + +Start with a clean working directory. The agent makes commits as it works, and mixing uncommitted changes with the agent's modifications makes it harder to review or revert changes. + +```git +git stash +git status +``` + +### Back up non-Git repositories + +The agent can also work with folders that aren't under source control. If your project isn't in a Git repository, the agent skips branching and commit operations. Back up your project folder before you start so you can restore it if needed. + +> [!TIP] +> Consider initializing a local Git repository before you start, even if you don't push to a remote. This gives you a way to roll back individual changes and track progress step by step. +> +> Example: +> ```git +> git init +> git add +> git commit -m "Initial Commit" +> ``` +> +> When you and the agent are done, if you don't want to continue using git, just make sure the code currently in your working tree is what you want, and delete the `.git` directory in the directory where you ran `git init`. + +## Common problems + +### Agent doesn't appear in Copilot Chat + +**Symptoms**: Typing @Modernize in the GitHub Copilot chat window doesn't activate the agent, or **Modernize** doesn't appear in the **Solution Explorer** context menu. + +**Solutions**: + +1. Verify that Visual Studio is version 18.7 or later in **Help** > **About Microsoft Visual Studio**. +1. Verify that GitHub Copilot is active by checking for the Copilot icon in the status bar. +1. Check that the feature is enabled in **Tools** > **Options** > **GitHub** > **Copilot** > **C/C++**. Then select **Enable GitHub Copilot modernization for C++**. +1. Restart Visual Studio after you change settings. + + +### Agent gets stuck in a loop + +**Symptoms**: The agent repeatedly tries the same fix without making progress. + +**Solutions**: + +- Stop the agent with the cancel button in the Copilot Chat prompt window, describe what you're observing in the prompt, and send the prompt to resume the agent. +- Provide a manual fix, and tell the agent what you changed. The agent learns from your correction. +- Ask the agent to try a different approach. For example, type in the GitHub Copilot chat window: _"That fix isn't working. Try a different strategy."_ +- If needed, revert or undo the last changes, and restart the task. + +### Large solutions take too long + +**Symptoms**: The upgrade of a large solution with many projects takes a very long time or seems to stall. + +**Solutions**: + +- Start with one representative project as a pilot. This surfaces systemic issues early. +- Monitor progress by reviewing `tasks.md` in `.github/upgrades/{SCENARIO ID}`. +- If a session times out, start a new session. The agent picks up where it left off. + +## Recovery strategies + +### Undo all changes + +If you used a Git branch for the upgrade, undo everything: + +```git +git checkout your-original-branch +git branch -D upgrade-branch +``` + +Your original code is untouched. + +### Undo the last change + +Revert the most recent commit: + +```git +git revert HEAD +``` + +Or tell the agent, `Revert the last change.` + +### Restart from a specific stage + +If the agent's plan isn't working, restart from an earlier stage by sending a prompt similar to: + +- `Let's redo the plan. I want a different approach to the conformance issues.` +- `Go back to the assessment and reconsider the upgrade strategy.` + +### Start fresh + +Delete the `.github/upgrades/{SCENARIO ID}` folder, and start a new conversation with the agent. It begins from scratch. + +## Get help + +If you can't resolve an issue: + +1. Use **Help** > **Send Feedback** > **Report a problem** in Visual Studio. +1. Include the contents of `execution-log.md` from `.github/upgrades/{SCENARIO ID}` if possible. + +## Related content + +- [Install GitHub Copilot modernization for C++](./install.md) +- [GitHub Copilot modernization for C++ overview](./overview.md) +- [Walkthrough - Hilo](./walkthrough-hilo.md) +- [FAQ](./faq.md) diff --git a/docs/porting/github-copilot-modernization-cpp/walkthrough-hilo.md b/docs/porting/github-copilot-modernization-cpp/walkthrough-hilo.md new file mode 100644 index 00000000000..f27161c2f88 --- /dev/null +++ b/docs/porting/github-copilot-modernization-cpp/walkthrough-hilo.md @@ -0,0 +1,167 @@ +--- +title: "Walkthrough: Using GitHub Copilot modernization for C++ to upgrade MSVC for the sample Hilo project" +description: "Demonstrates how to use GitHub Copilot to upgrade the Hilo sample project to use the most recent version of the MSVC Build Tools." +author: michaelbprice +ms.author: miprice +ms.date: 06/04/2026 +ms.topic: overview +ai-usage: ai-assisted +--- + +# Walkthrough: Upgrading Microsoft C++ (MSVC) Build Tools for the Hilo sample project + +This walkthrough shows how to use GitHub Copilot to modernize the Hilo sample project by upgrading it to the latest MSVC Build Tools. You'll use the modernization agent to identify and resolve issues, then use the Debugger agent to fix a runtime problem. + +## About Hilo + +Hilo was a sample project developed by Microsoft in 2012 to demonstrate creating applications targeting Windows 8 using "modern" C++, XAML, and the Windows Runtime. The Hilo application is a photo browsing application that also includes annotation and sharing features. We stopped updating the sample in 2015 and archived the source code for this sample and other previously shipped C++ samples in the [VCSamples GitHub repository](https://github.com/microsoft/VCSamples). + +![Screenshot of the main Hilo application window showing the contents of the user's Pictures folder.](../media/walkthrough-hilo-window.png) + +## Modernization challenges + +There are several issues that the agent discovers and resolves after upgrading Hilo to use a newer MSVC Build Tools version. Here are the issues when building with Microsoft C++ (MSVC) Build Tools version 14.51. + +- The `std::tr1::is_base_of` class template is used in several places, but is no longer available in MSVC's C++ standard library since `is_base_of` class template was promoted to be a part of the full standard. This is a blocking error. +- The `ID2D1Factory::GetDesktopDpi` function is deprecated. +- The`[uuid(_string_)]`syntax for ATL attributes on types is deprecated. +- There's a project that the Setup Assistant fails to upgrade. If you don't have the v120 MSVC Build Tools installed (which is likely), then this is a blocking error. +- There's a pointer truncation in window handling code that causes a runtime memory access exception. + +There are a few other warnings that may not be strictly related to the upgrade, but that the agent can optionally fix. These warnings include: + +- Narrowing warnings around multi-byte character strings and wide character strings. +- A typo in the name of an output file in a custom build step. + +## Setup + +### Install development tools + +In order to complete this walkthrough, you need to follow the [installation directions for the GitHub Copilot modernization agent for C++](./install.md). + +### Clone the repository + +Open Visual Studio and from the Start Window select **Clone a repository**. If the Start Window didn't appear, you can open it via **File** > **Start Window**. + +![Screenshot of the Visual Studio Start Window with the Clone a repository link highlighted.](../media/walkthrough-hilo-vs-start-window.png) + +For repository location, enter: **https://github.com/microsoft/VCSamples.git**. Choose an appropriate path on your system to clone the repository to and click the **Clone** button + +![Screenshot of the Visual Studio Clone a repository window with necessary fields completed and the Clone button highlighted.](../media/walkthrough-hilo-clone-window.png) + +## Start the upgrade + +### Load Hilo.sln in Visual Studio + +After you clone the repository, load the solution file at the `/VC2013Samples/Hilo/C++/Hilo.sln`. We're using the version that shipped with Visual Studio 2013 for this walkthrough. + +### Use the Setup Assistant to upgrade project files + +If you don't have the v120 tools installed, Visual Studio should launch the Setup assistant window to guide you through dealing with the missing components. When you see this window, you should choose to **Retarget all** and click **Apply**. If the window doesn't appear, you can open it from the file menu by clicking **Project** > **Retarget solution**. + +![Screenshot of the Setup assistant window showing the Hilo projects. All are selected for retargeting and the Apply button is highlighted.](../media/walkthrough-hilo-setup-assistant.png) + +### Launch the Copilot modernization agent + +After the Setup assistant has retargets the project, you should receive an infobar message with a link to start the modernization agent. Clicking the `Run GitHub Copilot modernization for C++` link starts the upgrade process. + +![Screenshot of the infobar message in Visual Studio for launching the modernization agent.](../media/walkthrough-hilo-infobar.png) + +If the infobar doesn't appear, you can launch the agent by right clicking the solution in the **Solution Explorer** and clicking **Modernize**. If you go that route, you can start the upgrade by sending the prompt `I just updated MSVC Build Tools. Resolve any upgrade issues.` to Copilot Chat. + +## Working with the agent + +### How to interact with the agent to get the best results + +The .NET modernization agent shares the same underlying interaction model as the C++ agent. The [Work with the modernization agent](/dotnet/core/porting/github-copilot-app-modernization/working-with-agent) documentation for .NET covers the general patterns in detail. Keep in mind that the examples and scenarios in that article are .NET-specific and don't apply directly to C++. + +For C++ upgrades, a few more tips can help the agent perform well: + +- **Be specific about scope.** Rather than asking the agent to upgrade everything at once, tell it which projects, libraries, or diagnostics to focus on. For example: _"Fix the C4996 deprecation warnings in the `NetworkClient` project."_ +- **Describe the diagnostics you expect the agent to fix.** If you know the specific warning or error codes introduced by the toolset upgrade, tell the agent upfront. These additional instructions help the agent prioritize and avoids time being spent on unrelated issues. +- **Make sure C/C++ code editing tools are enabled.** Verify the required tools are available in your setup before starting. For details, see [C/C++ code editing tools](/visualstudio/ide/copilot-agent-mode#c-code-editing-tools). +- **Encode coding conventions using custom instructions.** Encode guidelines such as naming conventions, preferred APIs, or patterns to avoid, in [custom instructions](https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot). The agent reads and follows these instructions throughout the upgrade. Useful C++ examples include conventions like _"Prefer `auto` where the type is obvious"_ and _"Follow Rule of Zero (or Rule of Three/Five where resource ownership requires it)."_ + +## Expected behaviors + +> [!NOTE] +> Due to the nature of LLM-based AI agents, the steps that the agent takes and the output it produces may differ from what is shown here. + +### Pre-assessment + +The agent first determines the environment that it's running in, such as your source control system, and to understand its goal. In our case, it detects that you're trying to upgrade your project to use the latest MSVC and initializes the appropriate scenario. It creates a `scenario.md` file and a `scenario-instructions.md` file to contain metadata about the scenario. + +These files contain information such as whether the agent should operate in **Automatic** or **Guided** mode, what the strategy for making commits is, and other information that affects _how_ the agent should proceed. If you express any preferences later on during the operation of the agent, the agent may add those preferences to the `scenario-instructions.md` file. + +![Screenshot of the contents of a scenario-instructions.md file.](../media/walkthrough-hilo-scenario-instructions.png) + +### Assessment + +After initialization, the agent does an assessment of the project by doing a clean rebuild of the project and inspecting the build output for errors and warnings. Using that information, and context the agent collects from the repository, it produces an `assessment.md` file that describes the issues that it found and whether or not it considers them to be in-scope or out-of-scope for the upgrade task. + +![Screenshot of the rendered contents of an assessment.md file.](../media/walkthrough-hilo-assessment.png) + +If the agent is operating in **Guided** mode, the agent stops here and requests your review of the assessment. Make any desired changes by prompting the agent or by editing the Markdown file directly, and then to continue on to the _Planning_ stage. If the agent is operating in **Automatic** mode, the agent continues on to the next stage automatically. If you want to change something, you need to stop the agent by pressing the cancel button, make the changes, and resume the agent by typing the prompt _"Resume"_ in the Copilot chat window. + +The assessment identifies several of the issues mentioned earlier in the walkthrough. Some issues don't appear until later since they're hidden by existing errors. Don't worry, they're discovered later on. If you'd like for the agent to pause to get your approval for any late-discovered issues, you can specify those instructions in your `scenario-instructions.md` file. + +### Planning + +Once the agent starts the Planning stage, it does a deeper analysis of the in-scope issues and proposes possible solutions in a generated `plan.md` file. It also generates a `tasks.md` file that provides more structured steps and instructions for executing the plan. + +![Screenshot of the rendered contents of a plan.md file.](../media/walkthrough-hilo-plan.png) + +Like with Assessment, what the agent does depends on if it's operating in **Guided** or **Automatic** mode. If running in **Guided** mode, the agent gives you the opportunity to direct it to fix issues in certain ways or even to ask it to come up with alternative options with more detailed descriptions of trade-offs. You can also specify other constraints such as coding conventions or special validation steps for some issues. + +### Execution + +After you approve the plan (or once Planning is completed in **Automatic** mode), the agent moves to the Execution stage. Here, it begins handling the tasks that it has in front of it, adapting to new information discovered while executing. With careful observation, you'll see that the agent discovers the previously hidden issues and adjusts its plan accordingly. + +![Screenshot of the agent in the middle of the Execution stage, reacting to newly discovered issues.](../media/walkthrough-hilo-execution.png) + +The end result of the Execution stage is a series of commits to your repository that resolve the in-scope issues, and a project that can now build successfully. However, a clean compilation is just one of the steps towards upgrading your project. It also needs to run correctly. + +## Use the Debugger agent to resolve runtime issues + +### Launch the Browser + +In the **Solution Explorer**, right-click the **Browser** project and click **Set as startup project**. Then launch a debugger session of the Hilo Browser by pressing **F5** or selecting **Debug** > **Start Debugging** from the file menu. + +The debugging session should almost immediately break on an unhandled memory access exception. + +:::image type="content" source="../media/walkthrough-hilo-exception.png" alt-text="Screenshot of the memory read access exception when first launching the Hilo browser." lightbox="../media/walkthrough-hilo-exception.png"::: + +### Examine memory read access exception + +We're going to use the Debugger agent to analyze this exception and implement a fix. Click on the **Analyze with Copilot** button on the exception information window to launch the Debugger agent. + +![Screenshot of the exception window for the Hilo browser with the Analyze with Copilot button highlighted.](../media/walkthrough-hilo-analyze-with-copilot.png) + +The Debugger agent uses debug and program state information to determine the root cause of runtime errors and then analyzes the source code to implement a solution. In this case, the agent identifies that the invalid memory access is due to an improper cast operation that truncated a 64-bit pointer to only 32 bits. That pointer is now invalid and points at an invalid memory location, which causes the exception. It proposes a different method of getting the correct type and avoids the truncation. + +### Apply changes + +Accept the changes it suggests, stop the debugging session by pressing *Shift + F5**, and then start a new session by pressing **F5**. The project is recompiled with the change and Visual Studio launches the updated application. You should now see the Hilo Browser window appear. + +![Screenshot of the main Hilo application window showing the contents of the user's Pictures folder.](../media/walkthrough-hilo-window.png) + +If you spend time exploring the application, you may discover more runtime issues. We leave any other issues as exercises for the reader. Just remember to use your new agentic tools to get to your end goal faster. + +## Summary + +This walkthrough demonstrated how GitHub Copilot agents can significantly accelerate the modernization of older C++ projects. The modernization agent and debugger agent can work together to streamline the upgrade process from initial assessment through runtime validation. + +### Key benefits + +- **Automated problem detection**: The agents systematically identify breaking changes, deprecations, and compatibility issues that arise from upgrades. +- **Intelligent solutions**: Rather than requiring manual fixes, the agents analyze code context and propose appropriate solutions tailored to your codebase. +- **Efficiency**: What might take days or weeks of manual work is completed in hours, with the agent handling both build errors and runtime issues. +- **Guided or automatic modes**: Choose between hands-on guidance or fully automated execution based on your comfort level and project requirements. +- **Learning and adaptation**: The agents discover hidden issues as they progress and adjust their approach accordingly, ensuring comprehensive coverage. + +## Related content + +- [GitHub Copilot modernization for C++ overview](./overview.md) +- [Install GitHub Copilot modernization for C++](./install.md) +- [Troubleshoot GitHub Copilot modernization for C++](./troubleshooting.md) +- [FAQ](./faq.md) diff --git a/docs/porting/media/walkthrough-hilo-analyze-with-copilot.png b/docs/porting/media/walkthrough-hilo-analyze-with-copilot.png new file mode 100644 index 00000000000..7e410c89454 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-analyze-with-copilot.png differ diff --git a/docs/porting/media/walkthrough-hilo-assessment.png b/docs/porting/media/walkthrough-hilo-assessment.png new file mode 100644 index 00000000000..7dba9355ac0 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-assessment.png differ diff --git a/docs/porting/media/walkthrough-hilo-clone-window.png b/docs/porting/media/walkthrough-hilo-clone-window.png new file mode 100644 index 00000000000..5e0e43934ca Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-clone-window.png differ diff --git a/docs/porting/media/walkthrough-hilo-exception.png b/docs/porting/media/walkthrough-hilo-exception.png new file mode 100644 index 00000000000..71784961277 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-exception.png differ diff --git a/docs/porting/media/walkthrough-hilo-execution.png b/docs/porting/media/walkthrough-hilo-execution.png new file mode 100644 index 00000000000..645956927e1 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-execution.png differ diff --git a/docs/porting/media/walkthrough-hilo-infobar.png b/docs/porting/media/walkthrough-hilo-infobar.png new file mode 100644 index 00000000000..30161f70184 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-infobar.png differ diff --git a/docs/porting/media/walkthrough-hilo-plan.png b/docs/porting/media/walkthrough-hilo-plan.png new file mode 100644 index 00000000000..2bc0aaf0cd8 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-plan.png differ diff --git a/docs/porting/media/walkthrough-hilo-scenario-instructions.png b/docs/porting/media/walkthrough-hilo-scenario-instructions.png new file mode 100644 index 00000000000..89c00cb9e28 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-scenario-instructions.png differ diff --git a/docs/porting/media/walkthrough-hilo-setup-assistant.png b/docs/porting/media/walkthrough-hilo-setup-assistant.png new file mode 100644 index 00000000000..4dabcdcb7f5 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-setup-assistant.png differ diff --git a/docs/porting/media/walkthrough-hilo-vs-start-window.png b/docs/porting/media/walkthrough-hilo-vs-start-window.png new file mode 100644 index 00000000000..f791838f476 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-vs-start-window.png differ diff --git a/docs/porting/media/walkthrough-hilo-window.png b/docs/porting/media/walkthrough-hilo-window.png new file mode 100644 index 00000000000..b4406880640 Binary files /dev/null and b/docs/porting/media/walkthrough-hilo-window.png differ diff --git a/docs/porting/toc.yml b/docs/porting/toc.yml index 6f05b7a6724..2d7ce6cafb6 100644 --- a/docs/porting/toc.yml +++ b/docs/porting/toc.yml @@ -9,8 +9,20 @@ items: href: ../porting/overview-of-potential-upgrade-issues-visual-cpp.md - name: Upgrade your code to the Universal CRT href: ../porting/upgrade-your-code-to-the-universal-crt.md - - name: Modernize your C++ project with GitHub Copilot modernization - href: ../porting/copilot-app-modernization-cpp.md + - name: GitHub Copilot modernization for C++ + items: + - name: Overview + href: ../porting/github-copilot-modernization-cpp/overview.md + - name: Install + href: ../porting/github-copilot-modernization-cpp/install.md + - name: Scenarios and skills reference + href: ../porting/github-copilot-modernization-cpp/scenarios-and-skills.md + - name: Walkthrough - Hilo + href: ../porting/github-copilot-modernization-cpp/walkthrough-hilo.md + - name: Troubleshooting + href: ../porting/github-copilot-modernization-cpp/troubleshooting.md + - name: FAQ + href: ../porting/github-copilot-modernization-cpp/faq.md - name: Update WINVER and _WIN32_WINNT href: ../porting/modifying-winver-and-win32-winnt.md - name: Fix your dependencies on library internals diff --git a/docs/porting/upgrading-projects-from-earlier-versions-of-visual-cpp.md b/docs/porting/upgrading-projects-from-earlier-versions-of-visual-cpp.md index 471d6105610..5aabda3b232 100644 --- a/docs/porting/upgrading-projects-from-earlier-versions-of-visual-cpp.md +++ b/docs/porting/upgrading-projects-from-earlier-versions-of-visual-cpp.md @@ -14,6 +14,8 @@ In Visual Studio 2026, this experience is enhanced with a setup assistant. The s With the setup assistant open, choose an action for each target or select **Retarget all** to set all projects at once. Then select **Apply** to complete the upgrade in place. Once your projects are retargeted, they can't be converted back to the earlier version. It's good practice to make a backup copy of the existing project and solution files before upgrading them. +The [GitHub Copilot modernization agent](./github-copilot-modernization-cpp/overview.md) can assist you with any changes that need to be made after your project files are upgraded. It will analyze your project for any new compilation warnings or errors and will iterate along with you to resolve them to complete your upgrade process. + > [!NOTE] > Visual Studio 2022 and later have deprecated support for the upgrade of project types that have *`.dsw`* or *`.dsp`* extensions. You can use an earlier version of Visual Studio, such as Visual Studio 2019, to upgrade these projects, then upgrade them again in Visual Studio 2022 or later to use the latest tools and features of Visual Studio. diff --git a/docs/porting/visual-cpp-porting-and-upgrading-guide.md b/docs/porting/visual-cpp-porting-and-upgrading-guide.md index 64aa8a53e5e..17b0491189f 100644 --- a/docs/porting/visual-cpp-porting-and-upgrading-guide.md +++ b/docs/porting/visual-cpp-porting-and-upgrading-guide.md @@ -61,7 +61,7 @@ ms.author: twhitney - [⬆️ Upgrading C++ Projects to Visual Studio 2026](https://devblogs.microsoft.com/cppblog/upgrading-c-projects-to-visual-studio-2026/) - [⬆️ Upgrade projects from earlier versions](upgrading-projects-from-earlier-versions-of-visual-cpp.md) -- [🤖 Upgrade with an AI agent (preview)](copilot-app-modernization-cpp.md) +- [🤖 Upgrade with an AI agent](github-copilot-modernization-cpp/overview.md) - [🛠️ IDE tools for upgrading C++ code](ide-tools-for-upgrading-code.md) - [🔄 Upgrade to Universal CRT](upgrade-your-code-to-the-universal-crt.md) - [🔧 Update WINVER and _WIN32_WINNT](modifying-winver-and-win32-winnt.md) diff --git a/docs/preprocessor/predefined-macros.md b/docs/preprocessor/predefined-macros.md index f76713d42fa..4c1b0170f87 100644 --- a/docs/preprocessor/predefined-macros.md +++ b/docs/preprocessor/predefined-macros.md @@ -2,9 +2,9 @@ title: "Predefined macros" description: "Lists and describes the Microsoft C++ compiler predefined preprocessor macros." ms.custom: "update_every_version" -ms.date: 06/18/2025 -f1_keywords: ["__ARM_ARCH", "_ATL_VER", "__ATOM__", "__AVX__", "__AVX2__", "__AVX512BW__", "__AVX512CD__", "__AVX512DQ__", "__AVX512F__", "__AVX512VL__", "_CHAR_UNSIGNED", "__CLR_VER", "_CONTROL_FLOW_GUARD", "__COUNTER__", "__cplusplus", "__cplusplus_cli", "__cplusplus_winrt", "_CPPRTTI", "_CPPUNWIND", "__DATE__", "_DEBUG", "_DLL", "__FILE__", "__FUNCDNAME__", "__FUNCSIG__", "__FUNCTION__", "_INTEGRAL_MAX_BITS", "_ISO_VOLATILE", "_KERNEL_MODE", "__LINE__", "_M_AMD64", "_M_ARM", "_M_ARM_ARMV7VE", "_M_ARM_FP", "_M_ARM64", "_M_CEE", "_M_CEE_PURE", "_M_CEE_SAFE", "_M_FP_EXCEPT", "_M_FP_FAST", "_M_FP_PRECISE", "_M_FP_STRICT", "_M_IX86", "_M_IX86_FP", "_M_X64", "_MANAGED", "_MFC_VER", "_MSC_BUILD", "_MSC_EXTENSIONS", "_MSC_FULL_VER", "_MSC_VER", "_MSVC_LANG", "__MSVC_RUNTIME_CHECKS", "_MT", "_NATIVE_WCHAR_T_DEFINED", "_NO_SIZED_DEALLOCATION", "_OPENMP", "_PREFAST_", "_RESUMABLE_FUNCTIONS_SUPPORTED", "_RTC_CONVERSION_CHECKS_ENABLED", "__SANITIZE_ADDRESS__", "__STDC__", "__STDC_HOSTED__", "__STDC_NO_ATOMICS__", "__STDC_NO_COMPLEX__", "__STDC_NO_THREADS__", "__STDC_NO_VLA__", "__STDC_VERSION__", "__STDCPP_DEFAULT_NEW_ALIGNMENT__", "__STDCPP_THREADS__", "__TIME__", "__TIMESTAMP__", "__VA_ARGS__", "_VC_NODEFAULTLIB", "_WCHAR_T_DEFINED", "_WIN32", "_WIN64", "_WINRT_DLL"] -helpviewer_keywords: ["__ARM_ARCH macro", "timestamps, preprocessor macro", "cl.exe compiler, version number", "version numbers, C/C++ compiler (cl.exe)", "macros, predefined C++", "preprocessor, macros", "predefined macros", "_ATL_VER macro", "__ATOM__ macro", "__AVX__ macro", "__AVX2__ macro", "__AVX512BW__ macro", "__AVX512CD__ macro", "__AVX512DQ__ macro", "__AVX512F__ macro", "__AVX512VL__ macro", "_CHAR_UNSIGNED macro", "__CLR_VER macro", "_CONTROL_FLOW_GUARD macro", "__COUNTER__ macro", "__cplusplus macro", "__cplusplus_cli macro", "__cplusplus_winrt macro", "_CPPRTTI macro", "_CPPUNWIND macro", "__DATE__ macro", "_DEBUG macro", "_DLL macro", "__FILE__ macro", "__FUNCDNAME__ macro", "__FUNCSIG__ macro", "__FUNCTION__ macro", "_INTEGRAL_MAX_BITS macro", "_ISO_VOLATILE macro", "_KERNEL_MODE macro", "__LINE__ macro", "_M_AMD64 macro", "_M_ARM macro", "_M_ARM_ARMV7VE macro", "_M_ARM_FP macro", "_M_ARM64 macro", "_M_ARM64EC macro", "_M_CEE macro", "_M_CEE_PURE macro", "_M_CEE_SAFE macro", "_M_FP_EXCEPT macro", "_M_FP_FAST macro", "_M_FP_PRECISE macro", "_M_FP_STRICT macro", "_M_IX86 macro", "_M_IX86_FP macro", "_M_X64 macro", "_MANAGED macro", "_MFC_VER macro", "_MSC_BUILD macro", "_MSC_EXTENSIONS macro", "_MSC_FULL_VER macro", "_MSC_VER macro", "_MSVC_LANG macro", "__MSVC_RUNTIME_CHECKS macro", "_MT macro", "_NATIVE_WCHAR_T_DEFINED macro", "_NO_SIZED_DEALLOCATION macro", "_OPENMP macro", "_PREFAST_ macro", "_RESUMABLE_FUNCTIONS_SUPPORTED macro", "_RTC_CONVERSION_CHECKS_ENABLED macro", "__SANITIZE_ADDRESS__ macro", "__STDC__ macro", "__STDC_HOSTED__ macro", "__STDC_NO_ATOMICS__ macro", "__STDC_NO_COMPLEX__ macro", "__STDC_NO_THREADS__ macro", "__STDC_NO_VLA__ macro", "__STDC_VERSION__ macro", "__STDCPP_DEFAULT_NEW_ALIGNMENT__", "__STDCPP_THREADS__ macro", "__TIME__ macro", "__TIMESTAMP__ macro", "__VA_ARGS__ macro", "_VC_NODEFAULTLIB macro", "_WCHAR_T_DEFINED macro", "_WIN32 macro", "_WIN64 macro", "_WINRT_DLL macro", "__func__ identifier"] +ms.date: 05/12/2026 +f1_keywords: ["__APX_F__", "__ARM_ARCH", "_ATL_VER", "__ATOM__", "__AVX__", "__AVX2__", "__AVX512BW__", "__AVX512CD__", "__AVX512DQ__", "__AVX512F__", "__AVX512VL__", "__CCMP__", "__CF__", "_CHAR_UNSIGNED", "__CLR_VER", "_CONTROL_FLOW_GUARD", "__COUNTER__", "__cplusplus", "__cplusplus_cli", "__cplusplus_winrt", "_CPPRTTI", "_CPPUNWIND", "__DATE__", "_DEBUG", "_DLL", "__EGPR__", "__FILE__", "__FUNCDNAME__", "__FUNCSIG__", "__FUNCTION__", "_INTEGRAL_MAX_BITS", "_ISO_VOLATILE", "_KERNEL_MODE", "__LINE__", "_M_AMD64", "_M_ARM", "_M_ARM_ARMV7VE", "_M_ARM_FP", "_M_ARM64", "_M_CEE", "_M_CEE_PURE", "_M_CEE_SAFE", "_M_FP_EXCEPT", "_M_FP_FAST", "_M_FP_PRECISE", "_M_FP_STRICT", "_M_IX86", "_M_IX86_FP", "_M_X64", "_MANAGED", "_MFC_VER", "_MSC_BUILD", "_MSC_EXTENSIONS", "_MSC_FULL_VER", "_MSC_VER", "_MSVC_LANG", "__MSVC_RUNTIME_CHECKS", "_MT", "_NATIVE_WCHAR_T_DEFINED", "__NDD__", "__NF__", "_NO_SIZED_DEALLOCATION", "_OPENMP", "__PPX__", "_PREFAST_", "__PUSH2POP2__", "_RESUMABLE_FUNCTIONS_SUPPORTED", "_RTC_CONVERSION_CHECKS_ENABLED", "__SANITIZE_ADDRESS__", "__STDC__", "__STDC_HOSTED__", "__STDC_NO_ATOMICS__", "__STDC_NO_COMPLEX__", "__STDC_NO_THREADS__", "__STDC_NO_VLA__", "__STDC_VERSION__", "__STDCPP_DEFAULT_NEW_ALIGNMENT__", "__STDCPP_THREADS__", "__TIME__", "__TIMESTAMP__", "__VA_ARGS__", "_VC_NODEFAULTLIB", "_WCHAR_T_DEFINED", "_WIN32", "_WIN64", "_WINRT_DLL", "__ZU__"] +helpviewer_keywords: ["__APX_F__ macro", "__ARM_ARCH macro", "_ATL_VER macro", "__ATOM__ macro", "__AVX__ macro", "__AVX2__ macro", "__AVX512BW__ macro", "__AVX512CD__ macro", "__AVX512DQ__ macro", "__AVX512F__ macro", "__AVX512VL__ macro", "__CCMP__ macro", "__CF__ macro", "_CHAR_UNSIGNED macro", "cl.exe compiler, version number", "__CLR_VER macro", "_CONTROL_FLOW_GUARD macro", "__COUNTER__ macro", "__cplusplus macro", "__cplusplus_cli macro", "__cplusplus_winrt macro", "_CPPRTTI macro", "_CPPUNWIND macro", "__DATE__ macro", "_DEBUG macro", "_DLL macro", "__EGPR__ macro", "__FILE__ macro", "__func__ identifier", "__FUNCDNAME__ macro", "__FUNCSIG__ macro", "__FUNCTION__ macro", "_INTEGRAL_MAX_BITS macro", "_ISO_VOLATILE macro", "_KERNEL_MODE macro", "__LINE__ macro", "_M_AMD64 macro", "_M_ARM macro", "_M_ARM_ARMV7VE macro", "_M_ARM_FP macro", "_M_ARM64 macro", "_M_ARM64EC macro", "_M_CEE macro", "_M_CEE_PURE macro", "_M_CEE_SAFE macro", "_M_FP_EXCEPT macro", "_M_FP_FAST macro", "_M_FP_PRECISE macro", "_M_FP_STRICT macro", "_M_IX86 macro", "_M_IX86_FP macro", "_M_X64 macro", "macros, predefined C++", "_MANAGED macro", "_MFC_VER macro", "_MSC_BUILD macro", "_MSC_EXTENSIONS macro", "_MSC_FULL_VER macro", "_MSC_VER macro", "_MSVC_LANG macro", "__MSVC_RUNTIME_CHECKS macro", "_MT macro", "_NATIVE_WCHAR_T_DEFINED macro", "__NDD__ macro", "__NF__ macro", "_NO_SIZED_DEALLOCATION macro", "_OPENMP macro", "__PPX__ macro", "predefined macros", "_PREFAST_ macro", "preprocessor, macros", "__PUSH2POP2__ macro", "_RESUMABLE_FUNCTIONS_SUPPORTED macro", "_RTC_CONVERSION_CHECKS_ENABLED macro", "__SANITIZE_ADDRESS__ macro", "__STDC__ macro", "__STDC_HOSTED__ macro", "__STDC_NO_ATOMICS__ macro", "__STDC_NO_COMPLEX__ macro", "__STDC_NO_THREADS__ macro", "__STDC_NO_VLA__ macro", "__STDC_VERSION__ macro", "__STDCPP_DEFAULT_NEW_ALIGNMENT__", "__STDCPP_THREADS__ macro", "__TIME__ macro", "__TIMESTAMP__ macro", "timestamps, preprocessor macro", "__VA_ARGS__ macro", "_VC_NODEFAULTLIB macro", "version numbers, C/C++ compiler (cl.exe)", "_WCHAR_T_DEFINED macro", "_WIN32 macro", "_WIN64 macro", "_WINRT_DLL macro", "__ZU__ macro"] ms.assetid: 1cc5f70a-a225-469c-aed0-fe766238e23f no-loc: [_ATL_VER, __ATOM__, __AVX__, __AVX2__, __AVX512BW__, __AVX512CD__, __AVX512DQ__, __AVX512F__, __AVX512VL__, _CHAR_UNSIGNED, __CLR_VER, _CONTROL_FLOW_GUARD, __COUNTER__, __cplusplus, __cplusplus_cli, __cplusplus_winrt, _CPPRTTI, _CPPUNWIND, __DATE__, _DEBUG, _DLL, __FILE__, __FUNCDNAME__, __FUNCSIG__, __FUNCTION__, _INTEGRAL_MAX_BITS, _ISO_VOLATILE, _KERNEL_MODE, __LINE__, _M_AMD64, _M_ARM, _M_ARM_ARMV7VE, _M_ARM_FP, _M_ARM64, _M_ARM64EC, _M_CEE, _M_CEE_PURE, _M_CEE_SAFE, _M_FP_EXCEPT, _M_FP_FAST, _M_FP_PRECISE, _M_FP_STRICT, _M_IX86, _M_IX86_FP, _M_X64, _MANAGED, _MFC_VER, _MSC_BUILD, _MSC_EXTENSIONS, _MSC_FULL_VER, _MSC_VER, _MSVC_LANG, __MSVC_RUNTIME_CHECKS, _MT, _NATIVE_WCHAR_T_DEFINED, _NO_SIZED_DEALLOCATION, _OPENMP, _PREFAST_, _RESUMABLE_FUNCTIONS_SUPPORTED, _RTC_CONVERSION_CHECKS_ENABLED, __SANITIZE_ADDRESS__, __STDC__, __STDC_HOSTED__, __STDC_NO_ATOMICS__, __STDC_NO_COMPLEX__, __STDC_NO_THREADS__, __STDC_NO_VLA__, __STDC_VERSION__, __STDCPP_DEFAULT_NEW_ALIGNMENT__, __STDCPP_THREADS__, __TIME__, __TIMESTAMP__, __VA_ARGS__, _VC_NODEFAULTLIB, _WCHAR_T_DEFINED, _WIN32, _WIN64, _WINRT_DLL, __func__] --- @@ -65,6 +65,8 @@ The compiler supports these predefined macros specified by the ISO C99, C11, C17 MSVC supports other predefined macros: +- `__APX_F__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + - `__ARM_ARCH` Defined as an integer literal that represents the ARM architecture version. The value is defined as 8 for the Armv8-A architecture. For 8.1 and onwards, the value is scaled for minor versions, such as X.Y, by using the formula X * 100 + Y as defined by the ARM C language extension. For example, for Armv8.1, `__ARM_ARCH` is 8 * 100 + 1 or 801. To set the ARM architecture version, see [`/arch (ARM64)`](../build/reference/arch-arm64.md). This macro was introduced in Visual Studio 2022 version 17.10. - `__ATOM__` Defined as 1 when the [`/favor:ATOM`](../build/reference/favor-optimize-for-architecture-specifics.md) compiler option is set and the compiler target is x86 or x64. Otherwise, undefined. @@ -85,6 +87,10 @@ MSVC supports other predefined macros: - `__AVX10_VER__` Defined as an integer that represents version of AVX10 when the [`/arch:AVX10.1`](../build/reference/arch-x86.md) or [`/arch:AVX10.2`](../build/reference/arch-x86.md) compiler option is set and the compiler target is x86 or x64. Otherwise, undefined. +- `__CCMP__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + +- `__CF__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + - `_CHAR_UNSIGNED` Defined as 1 if the default **`char`** type is unsigned. This value is defined when the [**`/J`** (Default char type is unsigned)](../build/reference/j-default-char-type-is-unsigned.md) compiler option is set. Otherwise, undefined. - `__CLR_VER` Defined as an integer literal that represents the version of the Common Language Runtime (CLR) used to compile the app. The value is encoded in the form `Mmmbbbbb`, where `M` is the major version of the runtime, `mm` is the minor version of the runtime, and `bbbbb` is the build number. `__CLR_VER` is defined if the [`/clr`](../build/reference/clr-common-language-runtime-compilation.md) compiler option is set. Otherwise, undefined. @@ -169,6 +175,8 @@ MSVC supports other predefined macros: - `_DLL` Defined as 1 when the [`/MD`](../build/reference/md-mt-ld-use-run-time-library.md) or [`/MDd`](../build/reference/md-mt-ld-use-run-time-library.md) (Multithreaded DLL) compiler option is set. Otherwise, undefined. +- `__EGPR__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + - `__FUNCDNAME__` Defined as a string literal that contains the [decorated name](../build/reference/decorated-names.md) of the enclosing function. The macro is defined only within a function. The `__FUNCDNAME__` macro isn't expanded if you use the [`/EP`](../build/reference/ep-preprocess-to-stdout-without-hash-line-directives.md) or [`/P`](../build/reference/p-preprocess-to-a-file.md) compiler option. This example uses the `__FUNCDNAME__`, `__FUNCSIG__`, and `__FUNCTION__` macros to display function information. @@ -287,6 +295,10 @@ MSVC supports other predefined macros: - `_MT` Defined as 1 when [**`/MD`** or **`/MDd`** (Multithreaded DLL)](../build/reference/md-mt-ld-use-run-time-library.md) or [**`/MT`** or **`/MTd`** (Multithreaded)](../build/reference/md-mt-ld-use-run-time-library.md) is specified. Otherwise, undefined. +- `__NDD__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + +- `__NF__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + - `_NATIVE_WCHAR_T_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. - `_OPENMP` Defined as integer literal 200203, if the [**`/openmp`** (Enable OpenMP 2.0 Support)](../build/reference/openmp-enable-openmp-2-0-support.md) compiler option is set. This value represents the date of the OpenMP specification implemented by MSVC. Otherwise, undefined. @@ -300,8 +312,12 @@ MSVC supports other predefined macros: } ``` +- `__PPX__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + - `_PREFAST_` Defined as 1 when the [`/analyze`](../build/reference/analyze-code-analysis.md) compiler option is set. Otherwise, undefined. +- `__PUSH2POP2__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + - `__SANITIZE_ADDRESS__` Available beginning with Visual Studio 2019 version 16.9. Defined as 1 when the [`/fsanitize=address`](../build/reference/fsanitize.md) compiler option is set. Otherwise, undefined. - `__TIMESTAMP__` Defined as a string literal that contains the date and time of the last modification of the current source file, in the abbreviated, constant length form returned by the CRT [`asctime`](../c-runtime-library/reference/asctime-wasctime.md) function, for example, `Fri 19 Aug 13:32:58 2016`. This macro is always defined. @@ -316,6 +332,8 @@ MSVC supports other predefined macros: - `_WINRT_DLL` Defined as 1 when compiled as C++ and both [**`/ZW`** (Windows Runtime Compilation)](../build/reference/zw-windows-runtime-compilation.md) and [**`/LD`** or **`/LDd`**](../build/reference/md-mt-ld-use-run-time-library.md) compiler options are set. Otherwise, undefined. +- `__ZU__` Defined as 1 when the [`/feature:APX`](../build/reference/feature-x64.md) compiler option is set and the compiler target is x64. Otherwise, undefined. + No preprocessor macros that identify the ATL or MFC library version are predefined by the compiler. ATL and MFC library headers define these version macros internally. They're undefined in preprocessor directives made before the required header is included. - `_ATL_VER` Defined in `` as an integer literal that encodes the ATL version number. diff --git a/docs/sanitizers/asan-known-issues.md b/docs/sanitizers/asan-known-issues.md index 7d3b22a2e7a..20608c02b2d 100644 --- a/docs/sanitizers/asan-known-issues.md +++ b/docs/sanitizers/asan-known-issues.md @@ -1,7 +1,7 @@ --- title: "AddressSanitizer known issues and limitations" description: "Technical description of the AddressSanitizer for Microsoft C/C++ known issues." -ms.date: 11/19/2025 +ms.date: 8/18/2026 helpviewer_keywords: ["AddressSanitizer known issues"] --- @@ -19,7 +19,7 @@ The following options and functionality are incompatible with [`/fsanitize=addre - [Edit-and-Continue](/visualstudio/debugger/edit-and-continue-visual-cpp) is unsupported, and should be disabled. - [Coroutines](https://devblogs.microsoft.com/cppblog/category/coroutine/) are incompatible with AddressSanitizer, and resumable functions are exempt from instrumentation. - [OpenMP](../build/reference/openmp-enable-openmp-2-0-support.md) is unsupported, and should be disabled. -- [Managed C++](../build/reference/clr-common-language-runtime-compilation.md) is unsupported, and should be disabled. +- [Managed C++](../build/reference/clr-common-language-runtime-compilation.md) is not fully supported, and should be disabled. See [Compiler Warning (level 1) C5089](../error-messages/compiler-warnings/compiler-warning-c5089.md) for more information. - [C++ AMP](../parallel/amp/cpp-amp-overview.md) is unsupported, and should be disabled. - [Universal Windows Platform](../cppcx/universal-windows-apps-cpp.md) (UWP) applications are unsupported. - [Special case list](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html) files are unsupported. @@ -105,6 +105,19 @@ On x64, MSVC ASan's [shadow bytes](./asan-shadow-bytes.md) region occupies sever The Visual Studio debugger handles this gracefully, and doesn't show these traces. However, debuggers like WinDbgX may break on every exception by default. Disabling breaking on first-chance exceptions is recommended. For example, in WinDbgX, this corresponds to the [`sxd av`](/windows-hardware/drivers/debuggercmds/sx--sxd--sxe--sxi--sxn--sxr--sx---set-exceptions-) command. +## ASan support for C++/CLI is experimental + +For reliable AddressSanitizer (ASan) diagnostics, isolate memory-unsafe code in native translation units or DLLs compiled without `/clr` and with `/fsanitize=address`. Call the native code from C++/CLI wrappers. + + +The CLR manages memory and JIT-generated code, so C++/CLI code isn't guaranteed to receive ASan load and store instrumentation. As a result: + +- C++/CLI and STL code: Memory accesses within C++/CLI methods might not be instrumented, including accesses performed by STL code. +- Managed arrays: Out-of-range access produces CLR behavior, such as `IndexOutOfRangeException`, rather than an ERROR: AddressSanitizer report. +- Managed threads: Native memory accesses emitted within C++/CLI method bodies might not produce ASan diagnostics. +- Finalization and shutdown: Reports during finalization, process shutdown, or mixed-mode unloading might not reliably indicate user-code memory bugs. +- Native hosts: Loading an ASan-enabled C++/CLI wrapper DLL from a native host might produce misleading runtime failures, such as access-violation reports for unknown addresses. + ## See also [AddressSanitizer overview](asan.md)\ diff --git a/docs/sanitizers/asan.md b/docs/sanitizers/asan.md index 63d7c1cb7f2..ba00ca39d31 100644 --- a/docs/sanitizers/asan.md +++ b/docs/sanitizers/asan.md @@ -1,17 +1,18 @@ --- title: "AddressSanitizer" -description: "Top-level description of the AddressSanitizer feature for Microsoft C/C++." -ms.date: 09/06/2024 +description: "Learn how to locate hard-to-find bugs with this top-level description of the AddressSanitizer feature for Microsoft C/C++." +ms.date: 05/28/2026 ms.topic: overview f1_keywords: ["AddressSanitizer"] helpviewer_keywords: ["ASan", "AddressSanitizer", "Address Sanitizer", "compiling for AddressSanitizer"] +#customer intent: As a C/C++ developer, I want to understand the advantages of using Address Sanitizer to avoid hard-to-find bugs in my code by using Visual Studio or the developer command line. --- # AddressSanitizer ## Overview -The C & C++ languages are powerful, but can suffer from a class of bugs that affect program correctness and program security. Starting in Visual Studio 2019 version 16.9, the Microsoft C/C++ compiler (MSVC) and IDE supports the *AddressSanitizer* sanitizer. AddressSanitizer (ASan) is a compiler and runtime technology that exposes many hard-to-find bugs with **zero** false positives: +The C and C++ languages are powerful, but can suffer from a class of bugs that affect program correctness and program security. Starting in Visual Studio 2019 version 16.9, the Microsoft C/C++ compiler (MSVC) and IDE support the *AddressSanitizer* sanitizer. AddressSanitizer (ASan) is a compiler and runtime technology that exposes many hard-to-find bugs with **zero** false positives: - [Alloc/dealloc mismatches](error-alloc-dealloc-mismatch.md) and [`new`/`delete` type mismatches](error-new-delete-type-mismatch.md) - [Allocations too large for the heap](error-allocation-size-too-big.md) @@ -25,17 +26,23 @@ The C & C++ languages are powerful, but can suffer from a class of bugs that aff - [Stack use after `return`](error-stack-use-after-return.md) and [use after scope](error-stack-use-after-scope.md) - [Memory use after it's poisoned](error-use-after-poison.md) +### Why use AddressSanitizer + Use AddressSanitizer to reduce your time spent on: - Basic correctness -- Cross platform portability +- Cross-platform portability - Security - Stress testing - Integrating new code AddressSanitizer, originally [introduced by Google](https://www.usenix.org/conference/atc12/technical-sessions/presentation/serebryany), provides runtime bug-finding technologies that use your existing build systems and existing test assets directly. -AddressSanitizer is integrated with the Visual Studio project system, the CMake build system, and the IDE. Projects can enable AddressSanitizer by setting a project property, or by using one extra compiler option: **`/fsanitize=address`**. The new option is compatible with all levels of optimization and configurations of x86 and x64. However, it isn't compatible with [edit-and-continue](/visualstudio/debugger/edit-and-continue-visual-cpp), [incremental linking](../build/reference/incremental-link-incrementally.md), and [`/RTC`](../build/reference/rtc-run-time-error-checks.md). +### Build integration and compatibility + +AddressSanitizer is integrated with the Visual Studio project system, the CMake build system, and the IDE. Projects can enable AddressSanitizer by setting a project property or by using one extra compiler option: `/fsanitize=address`. This option is compatible with all levels of optimization and configurations of x86 and x64. However, it isn't compatible with [edit-and-continue](/visualstudio/debugger/edit-and-continue-visual-cpp), [incremental linking](../build/reference/incremental-link-incrementally.md), and [`/RTC`](../build/reference/rtc-run-time-error-checks.md). + +### Crash dump support Starting in Visual Studio 2019 version 16.9, Microsoft's AddressSanitizer technology enables integration with the Visual Studio IDE. The functionality can optionally create a crash dump file when the sanitizer finds a bug at runtime. If you set the `ASAN_SAVE_DUMPS=MyFileName.dmp` environment variable before you run your program, a crash dump file is created with extra metadata for efficient [post-mortem debugging](#crash-dumps) of precisely diagnosed bugs. These dump files make extended use of AddressSanitizer easier for: @@ -45,24 +52,24 @@ Starting in Visual Studio 2019 version 16.9, Microsoft's AddressSanitizer techno ### Install AddressSanitizer -C++ workloads in the Visual Studio Installer install the AddressSanitizer libraries and IDE integration by default. However, if you're upgrading from an older version of Visual Studio 2019, use the Installer to enable ASan support after the upgrade. You can open the installer from the Visual Studio main menu via **Tools** > **Get Tools and Features...** Choose **Modify** on your existing Visual Studio installation from the Visual Studio Installer to get to the following screen. +C++ workloads in the Visual Studio Installer install the AddressSanitizer libraries and IDE integration by default. However, if you're upgrading from an older version of Visual Studio 2019, use the Installer to enable ASan support after the upgrade. You can open the installer from the Visual Studio main menu by selecting **Tools** > **Get Tools and Features**. Choose **Modify** on your existing Visual Studio installation from the Visual Studio Installer to get to the following screen. -:::image type="content" source="media/asan-installer-option.png" alt-text="Screenshot of the Visual Studio Installer. The C++ AddressSanitizer component, under the Optional section, is highlighted."::: +:::image type="content" source="media/asan-installer-option.png" alt-text="Screenshot showing the Visual Studio Installer with the C++ AddressSanitizer component, under the Optional section, highlighted." lightbox="media/asan-installer-option.png"::: > [!NOTE] -> If you run Visual Studio on the new update but haven't installed ASan, you'll get an error when you run your code: +> If you run Visual Studio on the new update but haven't installed ASan, you get an error when you run your code: > > LNK1356: cannot find library 'clang_rt.asan_dynamic-i386.lib' ### Use AddressSanitizer -Start building your executables with the **`/fsanitize=address`** compiler option using any of these common development methods: +Start building your executables with the `/fsanitize=address` compiler option using any of these common development methods: - Command line builds - Visual Studio project system - Visual Studio CMake integration - Recompile, then run your program normally. This code generation exposes [many types of precisely diagnosed bugs](#error-types). These errors get reported in three ways: in the debugger IDE, on the command line, or stored in a [new type of dump file](#crash-dumps) for precise off-line processing. +Recompile your code, and then run your program normally to expose [many types of precisely diagnosed bugs](#error-types). You can review the issues in the debugger IDE, the command line, or the [dump file](#crash-dumps). Microsoft recommends you use AddressSanitizer in these three standard workflows: @@ -71,21 +78,21 @@ Microsoft recommends you use AddressSanitizer in these three standard workflows: - Visual Studio - [Project system](#ide-msbuild) - Visual Studio - [CMake](#ide-cmake) -- **CI/CD** - continuous integration / continuous development - - Error reporting - [New AddressSanitizer dump files](#crash-dumps) +- **CI/CD** - continuous integration and continuous delivery + - Error reporting - [AddressSanitizer dump files](#crash-dumps) - **Fuzzing** - building with the [libFuzzer](https://llvm.org/docs/LibFuzzer.html) wrapper - [Azure OneFuzz](https://www.microsoft.com/security/blog/2020/09/15/microsoft-onefuzz-framework-open-source-developer-tool-fix-bugs/) - Local Machine -This article covers the information you require to enable the three workflows listed previously. The information is specific to the **platform-dependent** Windows 10 (and later) implementation of AddressSanitizer. This documentation supplements the excellent documentation from [Google, Apple, and GCC](#external-docs) already published. +This article covers the information you require to enable the three workflows listed previously. The information is specific to the *platform-dependent* Windows 10 (and later) implementation of AddressSanitizer. This documentation supplements the documentation from [Google, Apple, and GCC](#external-docs). > [!NOTE] -> Support is limited to x86 and x64 on Windows 10 and later. [Send us feedback](https://aka.ms/vsfeedback/browsecpp) on what you'd like to see in future releases. Your feedback helps us prioritize other sanitizers for the future, such as **`/fsanitize=thread`**, **`/fsanitize=leak`**, **`/fsanitize=memory`**, **`/fsanitize=undefined`**, or **`/fsanitize=hwaddress`**. You can [report bugs here](https://aka.ms/feedback/report?space=62) if you run into issues. +> Support is limited to x86 and x64 on Windows 10 and later. [Send us feedback](https://aka.ms/vsfeedback/browsecpp) on what you'd like to see in future releases. Your feedback helps us prioritize other sanitizers for the future, such as `/fsanitize=thread`, `/fsanitize=leak`, `/fsanitize=memory`, `/fsanitize=undefined`, or `/fsanitize=hwaddress`. You can [report bugs here](https://aka.ms/feedback/report?space=62) if you run into issues. ## Use AddressSanitizer from a developer command prompt -Use the **`/fsanitize=address`** compiler option in a [developer command prompt](../build/building-on-the-command-line.md#developer_command_prompt_shortcuts) to enable compiling for the AddressSanitizer runtime. The **`/fsanitize=address`** option is compatible with existing C++ or C optimization levels (for example, `/Od`, `/O1`, `/O2`, and `/O2 /GL`). The option works with static and dynamic CRTs (for example, `/MD`, `/MDd`, `/MT`, and `/MTd`). It works whether you create an EXE or a DLL. Debug information is required for optimal formatting of call stacks. In the following example, `cl /fsanitize=address /Zi` is passed on the command line. +Use the `/fsanitize=address` compiler option in a [developer command prompt](../build/building-on-the-command-line.md#developer_command_prompt_shortcuts) to enable compiling for the AddressSanitizer runtime. The `/fsanitize=address` option is compatible with existing C++ or C optimization levels, for example, `/Od`, `/O1`, `/O2`, and `/O2 /GL`. The option works with static and dynamic CRTs (for example, `/MD`, `/MDd`, `/MT`, and `/MTd`). It works whether you create an EXE or a DLL. Debug information is required for optimal formatting of call stacks. In the following example, `cl /fsanitize=address /Zi` is passed on the command line. > [!NOTE] > AddressSanitizer doesn't support Profile-guided optimization (PGO). AddressSanitizer shouldn't be used in production. @@ -105,15 +112,15 @@ int main() { } ``` -Using a developer command prompt for Visual Studio 2019, compile *`main.cpp`* using `/fsanitize=address /Zi` +Using a developer command prompt for Visual Studio 2019, compile *basic-global-overflow.cpp* using `/fsanitize=address /Zi`. -:::image type="content" source="media/asan-command-basic-global-overflow.png" alt-text="Screenshot of a command prompt showing the command to compile with AddressSanitizer options. The command is: `cl main.cpp -faanitize-address /Zi`."::: +:::image type="content" source="media/asan-command-basic-global-overflow.png" alt-text="Screenshot showing a command prompt with the command `cl basic-global-overflow.cpp /fsanitize=address /Zi`."::: -When you run the resulting *`main.exe`* at the command line, it creates the formatted error report that follows. +When you run the resulting *`basic-global-overflow.exe`* at the command line, it creates the formatted error report that follows. Consider the overlaid, red boxes that highlight seven key pieces of information: -:::image type="complex" source="media/asan-basic-global-overflow.png" alt-text="Screenshot of the debugger showing a basic global overflow error."::: +:::image type="complex" source="media/asan-basic-global-overflow.png" alt-text="Screenshot of the debugger showing a basic global overflow error." lightbox="media/asan-basic-global-overflow.png"::: There are seven red highlights identifying key pieces of information in the error report. They map to the numbered list that follows this screenshot. The numbered boxes highlight the following text: 1) global-buffer-overflow 2) WRITE of size 4 3) basic-global-overflow.cpp 7 4) to the right of global variable 'x' defined in 'basic-global-overflow.cpp:3:8' 5) of size 400 6) 00 00[f9]f9 f9 7) Box is in the shadow byte legend area and contains Global redzone: f9 :::image-end::: @@ -122,13 +129,13 @@ There are seven red highlights identifying key pieces of information in the erro 1. The memory safety bug is a global-buffer-overflow. 2. There were **4 bytes** (32 bits) **stored** outside any user-defined variable. 3. The store took place in function `main()` defined in file `basic-global-overflow.cpp` on line 7. -4. The variable named `x` gets defined in basic-global-overflow.cpp on line 3, starting at column 8 -5. This global variable `x` is of size 400 bytes -6. The exact [shadow byte](./asan-shadow-bytes.md) describing the address targeted by the store had a value of `0xf9` -7. The shadow byte legend says `0xf9` is an area of padding to the right of `int x[100]` +4. The variable named `x` gets defined in basic-global-overflow.cpp on line 3, starting at column 8. +5. This global variable `x` is of size 400 bytes. +6. The exact [shadow byte](./asan-shadow-bytes.md) describing the address targeted by the store had a value of `0xf9`. +7. The shadow byte legend says `0xf9` is an area of padding to the right of `int x[100]`. > [!NOTE] -> The function names in the call stack are produced through the [LLVM symbolizer](https://llvm.org/docs/CommandGuide/llvm-symbolizer.html) that's invoked by the runtime upon error. +> When AddressSanitizer reports an error, the ASan runtime invokes the [LLVM symbolizer](https://llvm.org/docs/CommandGuide/llvm-symbolizer.html) to produce the function names in the call stack. ## Use AddressSanitizer in Visual Studio @@ -136,7 +143,7 @@ AddressSanitizer is integrated with the Visual Studio IDE. To turn on AddressSan :::image type="content" source="media/asan-project-system-dialog.png" alt-text="Screenshot of the Property Pages dialog showing the Enable AddressSanitizer property."::: -To build from the IDE, opt out of any [incompatible options](./asan-known-issues.md#incompatible-options). For an existing project compiled by using **`/Od`** (or Debug mode), you may need to turn off these options: +To build from the IDE, opt out of any [incompatible options](./asan-known-issues.md#incompatible-options). For an existing project compiled by using `/Od` (or Debug mode), you might need to turn off these options: - Turn off [`/ZI` (Debug Information Format)](../build/reference/z7-zi-zi-debug-information-format.md) - Turn off [`/RTC1` (runtime checks)](../build/reference/rtc-run-time-error-checks.md) @@ -144,21 +151,21 @@ To build from the IDE, opt out of any [incompatible options](./asan-known-issues To build and run the debugger, press **F5**. An **Exception Thrown** window appears in Visual Studio: -:::image type="content" source="media/asan-global-buffer-overflow-F5.png" alt-text="Screenshot of the debugger showing a global buffer overflow error."::: +:::image type="content" source="media/asan-global-buffer-overflow-f5.png" alt-text="Screenshot of the debugger showing a global buffer overflow error."::: ## Use AddressSanitizer from Visual Studio: CMake To enable AddressSanitizer for a [CMake project created to target Windows](../build/cmake-projects-in-visual-studio.md), follow these steps: -1. Open the **Configurations** dropdown in the toolbar at the top of the IDE and select **Manage Configurations**. +1. Open the **Configurations** dropdown menu in the toolbar at the top of the IDE and select **Manage Configurations**. - :::image type="content" source="media/asan-cmake-configuration-drop-down.png" alt-text="Screenshot of the CMake configuration dropdown. It displays options like x64 Debug, x64 Release, and so on. At the bottom of the list, Manage Configurations... is highlighted."::: + :::image type="content" source="media/asan-cmake-configuration-drop-down.png" alt-text="Screenshot showing the CMake configuration dropdown menu that displays options like x64 Debug, x64 Release, and, at the bottom of the list, Manage Configurations... is highlighted."::: - That opens the CMake Project Settings editor, which reflects the contents of your project's `CMakeSettings.json` file. + That action opens the CMake Project Settings editor, which reflects the contents of your project's `CMakeSettings.json` file. -1. Choose the **Edit JSON** link in the editor. This selection switches the view to raw JSON. +1. Choose the **Edit JSON** link. This selection switches the view to raw JSON. -1. Add the following snippet to the `"windows-base"` preset, inside `"configurePresets":` to turn on AddressSanitizer: +1. To turn on AddressSanitizer, add the following snippet to the `"windows-base"` preset, inside `"configurePresets":`. ```json "environment": { @@ -193,15 +200,15 @@ To enable AddressSanitizer for a [CMake project created to target Windows](../bu }, ``` -1. AddressSanitizer doesn't work if edit-and-continue is specified (`/ZI`), which is enabled by default for new CMake projects. In `CMakeLists.txt`, comment out (prefix with `#`) the line that starts with `set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"`. That line looks something like this, afterwards: +1. AddressSanitizer doesn't work if edit-and-continue is specified (`/ZI`), which is enabled by default for new CMake projects. In `CMakeLists.txt`, comment out (prefix with `#`) the line that starts with `set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"`. That line looks something like this: ```json # set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") ``` -1. Enter **Ctrl+S** to save this JSON file +1. Use **Ctrl**+**S** to save this JSON file. 1. Clear your CMake cache directory and reconfigure by choosing from the Visual Studio menu: **Project** > **Delete cache and Reconfigure**. Choose **Yes** when the prompt appears to clear your cache directory and reconfigure. -1. Replace the contents of the source file (for example, `CMakeProject1.cpp`) with the following: +1. Replace the contents of the source file, for example, `CMakeProject1.cpp`, with the following code: ```cpp // CMakeProject1.cpp : Defines the entry point for the application @@ -222,27 +229,27 @@ To enable AddressSanitizer for a [CMake project created to target Windows](../bu This screenshot captures the error from the CMake build. - :::image type="content" source="media/asan-cmake-error-f5.png" alt-text="Screenshot of an exception that says: Address Sanitizer Error: Global buffer overflow. In the background, address sanitizer output is visible in command window."::: + :::image type="content" source="media/asan-cmake-error-f5.png" alt-text="Screenshot showing an exception that says: Address Sanitizer Error: Global buffer overflow." lightbox="media/asan-cmake-error-f5.png"::: ## AddressSanitizer crash dumps -We introduced new functionality in AddressSanitizer for use with cloud and distributed workflows. This functionality allows offline viewing of an AddressSanitizer error in the IDE. The error gets overlaid on top of your source, just as you would experience in a live debug session. +AddressSanitizer includes functionality for use with cloud and distributed workflows. This functionality allows offline viewing of an AddressSanitizer error in the IDE. The error gets overlaid on top of your source, just as you would experience in a live debug session. -These new dump files can lead to efficiencies when analyzing a bug. You don't need to rerun, or find remote data or look for a machine that went off-line. +These dump files can lead to efficiencies when you analyze a bug. You don't need to rerun, find remote data, or look for a machine that went offline. -To produce a new type of dump file that can be viewed in Visual Studio on another machine at a later date: +To produce a dump file that you can view in Visual Studio on another machine at a later date: ```cmd set ASAN_SAVE_DUMPS=MyFileName.dmp ``` -Starting with Visual Studio 16.9 you can display **a precisely diagnosed error**, stored in your *`*.dmp`* file, on top of your source code. +Starting with Visual Studio 16.9, you can display *a precisely diagnosed error*, stored in your `*.dmp` file, on top of your source code. -[This new crash dump functionality](./asan-offline-crash-dumps.md) enables cloud-based workflows, or distributed testing. It can also be used to file a detailed, actionable bug in any scenario. +[This crash dump functionality](./asan-offline-crash-dumps.md) enables cloud-based workflows or distributed testing. It can also be used to file a detailed, actionable bug in any scenario. ## Example errors -AddressSanitizer can detect several kinds of memory misuse errors. Here are many of the runtime errors reported when you run your binaries compiled by using the AddressSanitizer (**`/fsanitize=address`**) compiler option: +AddressSanitizer can detect several kinds of memory misuse errors. Here are many of the runtime errors reported when you run your binaries compiled by using the AddressSanitizer (`/fsanitize=address`) compiler option: - [`alloc-dealloc-mismatch`](error-alloc-dealloc-mismatch.md) - [`allocation-size-too-big`](error-allocation-size-too-big.md) @@ -268,12 +275,12 @@ For more information about the examples, see [AddressSanitizer error examples](. MSVC currently differs from Clang 12.0 in two functional areas: -- **stack-use-after-scope** - this setting is on by default and can't be turned off. -- **stack-use-after-return** - this functionality requires an extra compiler option, and isn't available by only setting `ASAN_OPTIONS`. +- **stack-use-after-scope**: this setting is on by default and can't be turned off. +- **stack-use-after-return**: this functionality requires an extra compiler option, and isn't available by only setting `ASAN_OPTIONS`. These decisions were made to reduce the test matrix required to deliver this first version. -Features that could lead to false positives in Visual Studio 2019 16.9 weren't included. That discipline enforced the effective testing integrity necessary when considering interop with decades of existing code. More capabilities may be considered in later releases: +Features that could lead to false positives in Visual Studio 2019 16.9 weren't included. That discipline enforced the effective testing integrity necessary when considering interop with decades of existing code. More capabilities might be considered in later releases: - [Initialization Order Fiasco](https://github.com/google/sanitizers/wiki/AddressSanitizerInitializationOrderFiasco) - [Intra Object Overflow](https://github.com/google/sanitizers/wiki/AddressSanitizerIntraObjectOverflow) @@ -282,9 +289,9 @@ Features that could lead to false positives in Visual Studio 2019 16.9 weren't i For more information, see [Building for AddressSanitizer with MSVC](./asan-building.md). -## Existing industry documentation +## Industry documentation -Extensive documentation already exists for these language and platform-dependent implementations of the AddressSanitizer technology. +Extensive documentation exists for these language and platform-dependent implementations of the AddressSanitizer technology. - [Google](https://github.com/google/sanitizers/wiki/AddressSanitizer) - [Apple](https://developer.apple.com/documentation/xcode/diagnosing_memory_thread_and_crash_issues_early) @@ -294,10 +301,10 @@ This seminal paper on the [AddressSanitizer (external)](https://www.usenix.org/s ## See also -[AddressSanitizer known issues](./asan-known-issues.md)\ -[AddressSanitizer build and language reference](./asan-building.md)\ -[AddressSanitizer runtime reference](./asan-runtime.md)\ -[AddressSanitizer shadow bytes](./asan-shadow-bytes.md)\ -[AddressSanitizer cloud or distributed testing](./asan-offline-crash-dumps.md)\ -[AddressSanitizer debugger integration](./asan-debugger-integration.md)\ -[AddressSanitizer error examples](./asan-error-examples.md) +- [AddressSanitizer known issues](./asan-known-issues.md) +- [AddressSanitizer build and language reference](./asan-building.md) +- [AddressSanitizer runtime reference](./asan-runtime.md) +- [AddressSanitizer shadow bytes](./asan-shadow-bytes.md) +- [AddressSanitizer cloud or distributed testing](./asan-offline-crash-dumps.md) +- [AddressSanitizer debugger integration](./asan-debugger-integration.md) +- [AddressSanitizer error examples](./asan-error-examples.md) diff --git a/docs/sanitizers/media/asan-cmake-configuration-drop-down.png b/docs/sanitizers/media/asan-cmake-configuration-drop-down.png index dea084d7050..b7ea695f4ca 100644 Binary files a/docs/sanitizers/media/asan-cmake-configuration-drop-down.png and b/docs/sanitizers/media/asan-cmake-configuration-drop-down.png differ diff --git a/docs/sanitizers/media/asan-cmake-error-f5.png b/docs/sanitizers/media/asan-cmake-error-f5.png index c82b594749d..16c8e5a6054 100644 Binary files a/docs/sanitizers/media/asan-cmake-error-f5.png and b/docs/sanitizers/media/asan-cmake-error-f5.png differ diff --git a/docs/sanitizers/media/asan-command-basic-global-overflow.png b/docs/sanitizers/media/asan-command-basic-global-overflow.png index f419e814a5b..7fcabcfab0d 100644 Binary files a/docs/sanitizers/media/asan-command-basic-global-overflow.png and b/docs/sanitizers/media/asan-command-basic-global-overflow.png differ diff --git a/docs/sanitizers/media/asan-global-buffer-overflow-f5.png b/docs/sanitizers/media/asan-global-buffer-overflow-f5.png index 6aa808aa5a5..1b7cc39c1fc 100644 Binary files a/docs/sanitizers/media/asan-global-buffer-overflow-f5.png and b/docs/sanitizers/media/asan-global-buffer-overflow-f5.png differ diff --git a/docs/sanitizers/media/asan-project-system-dialog.png b/docs/sanitizers/media/asan-project-system-dialog.png index 61d01b04fd9..0ab58b42e4e 100644 Binary files a/docs/sanitizers/media/asan-project-system-dialog.png and b/docs/sanitizers/media/asan-project-system-dialog.png differ diff --git a/docs/standard-library/vectorized-stl-algorithms.md b/docs/standard-library/vectorized-stl-algorithms.md index 13cad087a01..1291e5ab6c1 100644 --- a/docs/standard-library/vectorized-stl-algorithms.md +++ b/docs/standard-library/vectorized-stl-algorithms.md @@ -24,7 +24,7 @@ Algorithms like `transform`, `reduce`, and `accumulate` benefit heavily from aut ## Manual vectorization in the MSVC STL -Certain algorithms for x64 and x86 include manual vectorization. This implementation is separately compiled and relies on runtime CPU dispatch, so it applies only to suitable CPUs. +Certain algorithms include manual vectorization. This implementation is separately compiled and relies on runtime CPU dispatch, so it applies only to suitable CPUs. Manually vectorized algorithms use template metaprogramming to detect if the element type is suitable for vectorization. As a result, they're only vectorized for simple types such as standard integer types. @@ -35,17 +35,18 @@ Assign the same value to `_USE_STD_VECTOR_ALGORITHMS` for all linked translation The `_USE_STD_VECTOR_ALGORITHMS` macro controls the behavior of these manually vectorized algorithms: - `contains`, `contains_subrange` - - `find`, `find_last`, `find_end`, `find_first_of`, `adjacent_find` + - `find`, `find_last`, `find_first_of`, `adjacent_find` - `count` - `mismatch` - - `search`, `search_n` + - `search`, `search_n`, `find_end` - `swap_ranges` - - `replace` + - `replace`, `replace_copy` - `remove`, `remove_copy` - `unique`, `unique_copy` - `reverse`, `reverse_copy` - `rotate` - `is_sorted`, `is_sorted_until` + - `includes` - `lexicographical_compare`, `lexicographical_compare_three_way` - `max`, `min`, `minmax` - `max_element`, `min_element`, `minmax_element` diff --git a/docs/windows/latest-supported-vc-redist.md b/docs/windows/latest-supported-vc-redist.md index 9e2e4b234e0..d3d4394bb6a 100644 --- a/docs/windows/latest-supported-vc-redist.md +++ b/docs/windows/latest-supported-vc-redist.md @@ -1,6 +1,6 @@ --- title: Latest Supported Visual C++ Redistributable Downloads -description: This article provides download links for the latest Visual C++ Redistributable packages. +description: If you need to install Visual C++ Runtime libraries with you app, this article includes downloads for ARM64, x86, and x64, plus legacy packages. ms.date: 12/03/2025 helpviewer_keywords: [