Skip to content

Commit 366ffba

Browse files
authored
[C++20] [Modules] [Driver] Don't enable -fdelayed-template-parsing by default on windows with C++20 (#69431)
There are already 3 issues about the broken state of -fdelayed-template-parsing and C++20 modules: - #61068 - #64810 - #65027 The problem is more complex than I thought. I am not sure how to fix it properly now. Given the complexities and -fdelayed-template-parsing is actually an extension to support old MS codes, I think it may make sense to not enable the -fdelayed-template-parsing option by default with C++20 modules to give more user friendly experience. Users who still want -fdelayed-template-parsing can specify it explicitly. Also according to https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-170, MSVC actually defaults to -fno-delayed-template-parsing (/Zc:twoPhase- with MSVC CLI) if using C++20. So we match the behavior with MSVC here to not enable -fdelayed-template-parsing by default after C++20.
1 parent 86bb713 commit 366ffba

File tree

4 files changed

+51
-21
lines changed

4 files changed

+51
-21
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ C++ Specific Potentially Breaking Changes
121121
system headers and macros. It will be turned into a hard (non-downgradable)
122122
error in the next Clang release.
123123

124+
- The flag `-fdelayed-template-parsing` won't be enabled by default with C++20
125+
when targetting MSVC to match the behavior of MSVC.
126+
(`MSVC Docs <https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-170>`_)
127+
124128
ABI Changes in This Version
125129
---------------------------
126130
- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ def err_test_module_file_extension_format : Error<
527527
def err_drv_module_output_with_multiple_arch : Error<
528528
"option '-fmodule-output' can't be used with multiple arch options">;
529529

530+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
531+
"-fdelayed-template-parsing is deprecated after C++20">,
532+
InGroup<DiagGroup<"delayed-template-parsing-in-cxx20">>;
533+
530534
def err_drv_extract_api_wrong_kind : Error<
531535
"header file '%0' input '%1' does not match the type of prior input "
532536
"in api extraction; use '-x %2' to override">;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3724,20 +3724,10 @@ bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
37243724

37253725
static bool RenderModulesOptions(Compilation &C, const Driver &D,
37263726
const ArgList &Args, const InputInfo &Input,
3727-
const InputInfo &Output, const Arg *Std,
3727+
const InputInfo &Output, bool HaveStd20,
37283728
ArgStringList &CmdArgs) {
37293729
bool IsCXX = types::isCXX(Input.getType());
3730-
// FIXME: Find a better way to determine whether the input has standard c++
3731-
// modules support by default.
3732-
bool HaveStdCXXModules =
3733-
IsCXX && Std &&
3734-
(Std->containsValue("c++2a") || Std->containsValue("gnu++2a") ||
3735-
Std->containsValue("c++20") || Std->containsValue("gnu++20") ||
3736-
Std->containsValue("c++2b") || Std->containsValue("gnu++2b") ||
3737-
Std->containsValue("c++23") || Std->containsValue("gnu++23") ||
3738-
Std->containsValue("c++2c") || Std->containsValue("gnu++2c") ||
3739-
Std->containsValue("c++26") || Std->containsValue("gnu++26") ||
3740-
Std->containsValue("c++latest") || Std->containsValue("gnu++latest"));
3730+
bool HaveStdCXXModules = IsCXX && HaveStd20;
37413731
bool HaveModules = HaveStdCXXModules;
37423732

37433733
// -fmodules enables the use of precompiled modules (off by default).
@@ -6840,14 +6830,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
68406830
(!IsWindowsMSVC || IsMSVC2015Compatible)))
68416831
CmdArgs.push_back("-fno-threadsafe-statics");
68426832

6843-
// -fno-delayed-template-parsing is default, except when targeting MSVC.
6844-
// Many old Windows SDK versions require this to parse.
6845-
// FIXME: MSVC introduced /Zc:twoPhase- to disable this behavior in their
6846-
// compiler. We should be able to disable this by default at some point.
6847-
if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
6848-
options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
6849-
CmdArgs.push_back("-fdelayed-template-parsing");
6850-
68516833
// -fgnu-keywords default varies depending on language; only pass if
68526834
// specified.
68536835
Args.AddLastArg(CmdArgs, options::OPT_fgnu_keywords,
@@ -6868,8 +6850,38 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
68686850

68696851
Args.AddLastArg(CmdArgs, options::OPT_finline_max_stacksize_EQ);
68706852

6853+
// FIXME: Find a better way to determine whether we are in C++20.
6854+
bool HaveCxx20 =
6855+
Std &&
6856+
(Std->containsValue("c++2a") || Std->containsValue("gnu++2a") ||
6857+
Std->containsValue("c++20") || Std->containsValue("gnu++20") ||
6858+
Std->containsValue("c++2b") || Std->containsValue("gnu++2b") ||
6859+
Std->containsValue("c++23") || Std->containsValue("gnu++23") ||
6860+
Std->containsValue("c++2c") || Std->containsValue("gnu++2c") ||
6861+
Std->containsValue("c++26") || Std->containsValue("gnu++26") ||
6862+
Std->containsValue("c++latest") || Std->containsValue("gnu++latest"));
68716863
bool HaveModules =
6872-
RenderModulesOptions(C, D, Args, Input, Output, Std, CmdArgs);
6864+
RenderModulesOptions(C, D, Args, Input, Output, HaveCxx20, CmdArgs);
6865+
6866+
// -fdelayed-template-parsing is default when targeting MSVC.
6867+
// Many old Windows SDK versions require this to parse.
6868+
//
6869+
// According to
6870+
// https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-170,
6871+
// MSVC actually defaults to -fno-delayed-template-parsing (/Zc:twoPhase-
6872+
// with MSVC CLI) if using C++20. So we match the behavior with MSVC here to
6873+
// not enable -fdelayed-template-parsing by default after C++20.
6874+
//
6875+
// FIXME: Given -fdelayed-template-parsing is a source of bugs, we should be
6876+
// able to disable this by default at some point.
6877+
if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
6878+
options::OPT_fno_delayed_template_parsing,
6879+
IsWindowsMSVC && !HaveCxx20)) {
6880+
if (HaveCxx20)
6881+
D.Diag(clang::diag::warn_drv_delayed_template_parsing_after_cxx20);
6882+
6883+
CmdArgs.push_back("-fdelayed-template-parsing");
6884+
}
68736885

68746886
if (Args.hasFlag(options::OPT_fpch_validate_input_files_content,
68756887
options::OPT_fno_pch_validate_input_files_content, false))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=PRE-CXX20
2+
// RUN: %clang_cl -std:c++20 -### -- %s 2>&1 | FileCheck %s
3+
// RUN: %clang_cl -std:c++20 -### -fdelayed-template-parsing -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-EXPLICIT
4+
5+
// PRE-CXX20: -fdelayed-template-parsing
6+
7+
// CHECK-NOT: -fdelayed-template-parsing
8+
9+
// CHECK-EXPLICIT: warning: -fdelayed-template-parsing is deprecated after C++20
10+
// CHECK-EXPLICIT: -fdelayed-template-parsing

0 commit comments

Comments
 (0)