https://github.com/RIscRIpt updated https://github.com/llvm/llvm-project/pull/71300
>From 3be36c6100801195f8f1f5167bdaa289bc8cb175 Mon Sep 17 00:00:00 2001 From: Richard Dzenis <dze...@richard.lv> Date: Thu, 20 Jul 2023 00:18:50 +0300 Subject: [PATCH 1/4] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute Differential Revision: https://reviews.llvm.org/D134475 --- clang/include/clang/Basic/Attr.td | 8 +++ clang/include/clang/Basic/AttrDocs.td | 15 ++++++ .../clang/Basic/DiagnosticSemaKinds.td | 2 + clang/include/clang/Basic/LangOptions.h | 1 + clang/lib/AST/ExprConstant.cpp | 34 +++++++++--- clang/lib/Basic/Targets/OSTargets.cpp | 3 ++ clang/lib/Sema/SemaDecl.cpp | 4 +- clang/lib/Sema/SemaDeclAttr.cpp | 25 +++++++++ clang/lib/Sema/SemaStmtAttr.cpp | 12 +++++ clang/test/AST/ms-constexpr.cpp | 28 ++++++++++ ...a-attribute-supported-attributes-list.test | 1 + clang/test/SemaCXX/ms-constexpr-invalid.cpp | 52 +++++++++++++++++++ clang/test/SemaCXX/ms-constexpr-new.cpp | 16 ++++++ clang/test/SemaCXX/ms-constexpr.cpp | 37 +++++++++++++ 14 files changed, 231 insertions(+), 7 deletions(-) create mode 100644 clang/test/AST/ms-constexpr.cpp create mode 100644 clang/test/SemaCXX/ms-constexpr-invalid.cpp create mode 100644 clang/test/SemaCXX/ms-constexpr-new.cpp create mode 100644 clang/test/SemaCXX/ms-constexpr.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 121ed203829cec..b0a8ef10c500a7 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3646,6 +3646,14 @@ def : MutualExclusions<[Owner, Pointer]>; // Microsoft-related attributes +def MSConstexpr : InheritableAttr { + let LangOpts = [MicrosoftExt]; + let Spellings = [CXX11<"msvc", "constexpr">]; + let Subjects = SubjectList<[Function, ReturnStmt], ErrorDiag, + "functions and return statements">; + let Documentation = [MSConstexprDocs]; +} + def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { let Spellings = [Declspec<"novtable">]; let Subjects = SubjectList<[CXXRecord]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 88f7c65e6e847b..9dc6a909f07d09 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3657,6 +3657,21 @@ an error: }]; } +def MSConstexprDocs : Documentation { + let Category = DocCatStmt; + let Content = [{ +The ``[[msvc::constexpr]]`` attribute can be applied only to a function +definition or a ``return`` statement. It does not impact function declarations. +A ``[[msvc::constexpr]]`` function cannot be ``constexpr`` or ``consteval``. +A ``[[msvc::constexpr]]`` function is treated as if it were a ``constexpr`` function +if it is evaluated in a constant context of ``[[msvc::constexpr]] return`` statement. +Otherwise, it is treated as a regular function. + +Semantics of this attribute is enabled only under MSVC compatibility +(``-fms-compatibility-version``) 19.33 and later. + }]; +} + def MSNoVTableDocs : Documentation { let Category = DocCatDecl; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ea08fa84d022cd..28d95ca9b13893 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2884,6 +2884,8 @@ def warn_cxx11_compat_constexpr_body_multiple_return : Warning< InGroup<CXXPre14Compat>, DefaultIgnore; def note_constexpr_body_previous_return : Note< "previous return statement is here">; +def err_ms_constexpr_cannot_be_applied : Error< + "attribute 'msvc::constexpr' cannot be applied to the %select{constexpr|consteval|virtual}0 function %1">; // C++20 function try blocks in constexpr def ext_constexpr_function_try_block_cxx20 : ExtWarn< diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 2d167dd2bdf128..c4979b9a38c0cf 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -152,6 +152,7 @@ class LangOptions : public LangOptionsBase { MSVC2019 = 1920, MSVC2019_5 = 1925, MSVC2019_8 = 1928, + MSVC2022_3 = 1933, }; enum SYCLMajorVersion { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 986302e1fd225f..90cc0b84f0439c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -641,6 +641,10 @@ namespace { return false; } + /// Whether we're in a context where [[msvc::constexpr]] evaluation is + /// permitted. See MSConstexprDocs for description of permitted contexts. + bool CanEvalMSConstexpr = false; + private: APValue &createLocal(APValue::LValueBase Base, const void *Key, QualType T, ScopeKind Scope); @@ -674,6 +678,19 @@ namespace { private: llvm::TimeTraceScope TimeScope; }; + + /// RAII object used to change the current ability of + /// [[msvc::constexpr]] evaulation. + struct MSConstexprContextRAII { + CallStackFrame &Frame; + bool OldValue; + explicit MSConstexprContextRAII(CallStackFrame &Frame, bool Value) + : Frame(Frame), OldValue(Frame.CanEvalMSConstexpr) { + Frame.CanEvalMSConstexpr = Value; + } + + ~MSConstexprContextRAII() { Frame.CanEvalMSConstexpr = OldValue; } + }; } static bool HandleDestruction(EvalInfo &Info, const Expr *E, @@ -5546,11 +5563,14 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::LabelStmtClass: return EvaluateStmt(Result, Info, cast<LabelStmt>(S)->getSubStmt(), Case); - case Stmt::AttributedStmtClass: - // As a general principle, C++11 attributes can be ignored without - // any semantic impact. - return EvaluateStmt(Result, Info, cast<AttributedStmt>(S)->getSubStmt(), - Case); + case Stmt::AttributedStmtClass: { + const auto *AS = cast<AttributedStmt>(S); + const auto *SS = AS->getSubStmt(); + MSConstexprContextRAII msConstexprContext( + *Info.CurrentCall, hasSpecificAttr<MSConstexprAttr>(AS->getAttrs()) && + isa<ReturnStmt>(SS)); + return EvaluateStmt(Result, Info, SS, Case); + } case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: @@ -5621,7 +5641,9 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, } // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && Body) + if (Definition && Body && + (Definition->isConstexpr() || Info.CurrentCall->CanEvalMSConstexpr && + Definition->hasAttr<MSConstexprAttr>())) return true; if (Info.getLangOpts().CPlusPlus11) { diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp index 627bc912fa2310..899aefa6173acf 100644 --- a/clang/lib/Basic/Targets/OSTargets.cpp +++ b/clang/lib/Basic/Targets/OSTargets.cpp @@ -224,6 +224,9 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { else if (Opts.CPlusPlus14) Builder.defineMacro("_MSVC_LANG", "201402L"); } + + if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2022_3)) + Builder.defineMacro("_MSVC_CONSTEXPR_ATTRIBUTE"); } if (Opts.MicrosoftExt) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e3c122de39dfe6..150c2fb4931d1b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16221,7 +16221,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, ActivePolicy = &WP; } - if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && + if (!IsInstantiation && FD && + (FD->isConstexpr() || FD->hasAttr<MSConstexprAttr>()) && + !FD->isInvalidDecl() && !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose)) FD->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a345978bb8701c..59e456fd9f7298 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7372,6 +7372,28 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL)); } +static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2022_3)) { + S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL << AL.getRange(); + return; + } + auto *FD = cast<FunctionDecl>(D); + if (FD->isConstexprSpecified() || FD->isConsteval()) { + S.Diag(AL.getLoc(), diag::err_ms_constexpr_cannot_be_applied) + << FD->isConsteval() << FD; + return; + } + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { + if (!S.getLangOpts().CPlusPlus20 && MD->isVirtual()) { + S.Diag(AL.getLoc(), diag::err_ms_constexpr_cannot_be_applied) + << /*virtual*/ 2 << MD; + return; + } + } + D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL)); +} + static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector<StringRef, 4> Tags; for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { @@ -9477,6 +9499,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_Thread: handleDeclspecThreadAttr(S, D, AL); break; + case ParsedAttr::AT_MSConstexpr: + handleMSConstexprAttr(S, D, AL); + break; // HLSL attributes: case ParsedAttr::AT_HLSLNumThreads: diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index eae1eaa2f9563d..725d8efe3828d6 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -397,6 +397,16 @@ static void CheckForDuplicateCodeAlignAttrs(Sema &S, } } +static Attr *handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + if (!S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2022_3)) { + S.Diag(A.getLoc(), diag::warn_unknown_attribute_ignored) + << A << A.getRange(); + return nullptr; + } + return ::new (S.Context) MSConstexprAttr(S.Context, A); +} + #define WANT_STMT_MERGE_LOGIC #include "clang/Sema/AttrParsedAttrImpl.inc" #undef WANT_STMT_MERGE_LOGIC @@ -600,6 +610,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, return handleUnlikely(S, St, A, Range); case ParsedAttr::AT_CodeAlign: return handleCodeAlignAttr(S, St, A); + case ParsedAttr::AT_MSConstexpr: + return handleMSConstexprAttr(S, St, A, Range); default: // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a // declaration attribute is not written on a statement, but this code is diff --git a/clang/test/AST/ms-constexpr.cpp b/clang/test/AST/ms-constexpr.cpp new file mode 100644 index 00000000000000..e85af8494f3344 --- /dev/null +++ b/clang/test/AST/ms-constexpr.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump -verify %s | FileCheck %s +// expected-no-diagnostics + +// CHECK: used f1 'bool ()' +// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} <col:3, col:9> +[[msvc::constexpr]] bool f1() { return true; } + +// CHECK: used constexpr f2 'bool ()' +// CHECK-NEXT: CompoundStmt 0x{{[0-9a-f]+}} <col:21, col:56> +// CHECK-NEXT: AttributedStmt 0x{{[0-9a-f]+}} <col:23, col:53> +// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} <col:25, col:31> +// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} <col:43, col:53> +constexpr bool f2() { [[msvc::constexpr]] return f1(); } +static_assert(f2()); + +struct S1 { + // CHECK: used vm 'bool ()' virtual + // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} <col:7, col:13> + [[msvc::constexpr]] virtual bool vm() { return true; } + + // CHECK: used constexpr cm 'bool ()' + // CHECK-NEXT: CompoundStmt 0x{{[0-9a-f]+}} <col:25, col:60> + // CHECK-NEXT: AttributedStmt 0x{{[0-9a-f]+}} <col:27, col:57> + // CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} <col:29, col:35> + // CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} <col:47, col:57> + constexpr bool cm() { [[msvc::constexpr]] return vm(); } +}; +static_assert(S1{}.cm()); diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 707fc8875089f7..bdfda430eea86c 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -90,6 +90,7 @@ // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global) // CHECK-NEXT: Lockable (SubjectMatchRule_record) // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block) +// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function) // CHECK-NEXT: MSStruct (SubjectMatchRule_record) // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: MicroMips (SubjectMatchRule_function) diff --git a/clang/test/SemaCXX/ms-constexpr-invalid.cpp b/clang/test/SemaCXX/ms-constexpr-invalid.cpp new file mode 100644 index 00000000000000..e5bec0c7119b02 --- /dev/null +++ b/clang/test/SemaCXX/ms-constexpr-invalid.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s + +// Check explicitly invalid code + +void runtime() {} // expected-note {{declared here}} + +[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function never produces a constant expression}} \ + // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}} +[[msvc::constexpr]] constexpr void f1() {} // expected-error {{attribute 'msvc::constexpr' cannot be applied to the constexpr function 'f1'}} +#if __cplusplus >= 202202L +[[msvc::constexpr]] consteval void f2() {} // expected-error {{attribute 'msvc::constexpr' cannot be applied to the consteval function 'f1'}} +#endif + +struct B1 {}; +struct D1 : virtual B1 { // expected-note {{virtual base class declared here}} + [[msvc::constexpr]] D1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} +}; + +struct [[msvc::constexpr]] S2{}; // expected-error {{'constexpr' attribute only applies to functions and return statements}} + +// Check invalid code mixed with valid code + +[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \ + // expected-note {{declared here}} \ + // expected-note {{declared here}} \ + // expected-note {{declared here}} +constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; } // expected-note {{in call to 'f4(32)'}} +static_assert(f5()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f5()'}} + +int f6(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f6(x / 2) : 0; } // expected-note {{declared here}} \ + // expected-note {{declared here}} +constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function never produces a constant expression}} \ + // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} \ + // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} +static_assert(f7()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f7()'}} + +constexpr bool f8() { // expected-error {{constexpr function never produces a constant expression}} + [[msvc::constexpr]] f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} \ + // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \ + // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} + [[msvc::constexpr]] int i5 = f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} + return i5 == 5; +} +static_assert(f8()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f8()'}} + +#if __cplusplus == 201702L +struct S1 { [[msvc::constexpr]] virtual bool vm() const { return true; } }; // expected-error {{attribute 'msvc::constexpr' ignored, it only applies to function definitions and return statements}} +#endif diff --git a/clang/test/SemaCXX/ms-constexpr-new.cpp b/clang/test/SemaCXX/ms-constexpr-new.cpp new file mode 100644 index 00000000000000..05ee5c5b4e154a --- /dev/null +++ b/clang/test/SemaCXX/ms-constexpr-new.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s +// supported-no-diagnostics + +[[nodiscard]] +[[msvc::constexpr]] // unsupported-warning {{unknown attribute 'constexpr' ignored}} +inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; } + +namespace std { + constexpr int* construct_at(int* p, int v) { + [[msvc::constexpr]] return ::new (p) int(v); // unsupported-warning {{unknown attribute 'constexpr' ignored}} + } +} + +constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; } +static_assert(check_construct_at()); diff --git a/clang/test/SemaCXX/ms-constexpr.cpp b/clang/test/SemaCXX/ms-constexpr.cpp new file mode 100644 index 00000000000000..79f71a34cb7d84 --- /dev/null +++ b/clang/test/SemaCXX/ms-constexpr.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s + +[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + log2(x / 2) : 0; } +constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; } +static_assert(test_log2()); + +[[msvc::constexpr]] int get_value(int x) +{ + switch (x) + { + case 42: return 1337; + default: + if (x < 0) [[msvc::constexpr]] return log2(-x); + else return x; + } +} + +constexpr bool test_complex_expr() { + [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0); +} +static_assert(test_complex_expr()); + +constexpr bool get_constexpr_true() { return true; } +[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); } +constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return get_msconstexpr_true(); } +static_assert(test_get_msconstexpr_true()); + +// TODO (#72149): Add support for [[msvc::constexpr]] constructor; this code is valid for MSVC. +struct S2 { + [[msvc::constexpr]] S2() {} + [[msvc::constexpr]] bool value() { return true; } + static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function never produces a constant expression}} \ + // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} \ + // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} +}; +static_assert(S2::check()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'check()'}} >From 8d62660446ed4ae64eeaa99373425cb0878d9b81 Mon Sep 17 00:00:00 2001 From: Richard Dzenis <dze...@richard.lv> Date: Thu, 20 Jul 2023 00:39:46 +0300 Subject: [PATCH 2/4] [clang-cl] Bump default -fms-compatibility-version to 19.33 --- clang/docs/ReleaseNotes.rst | 1 + clang/docs/UsersManual.rst | 4 ++-- clang/lib/Driver/ToolChains/MSVC.cpp | 4 ++-- clang/test/Driver/cl-options.c | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5c044658197139..d1510add7d8d1c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -235,6 +235,7 @@ Non-comprehensive list of changes in this release except that it returns the size of a type ignoring tail padding. * ``__builtin_classify_type()`` now classifies ``_BitInt`` values as the return value ``18`` and vector types as return value ``19``, to match GCC 14's behavior. +* Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this release adds the attribute as well. * Added ``#pragma clang fp reciprocal``. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 9d64195ee338e2..f1b344ef5109b5 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -3359,8 +3359,8 @@ default for Windows targets. For compatibility with existing code that compiles with MSVC, clang defines the ``_MSC_VER`` and ``_MSC_FULL_VER`` macros. When on Windows, these default to -either the same value as the currently installed version of cl.exe, or ``1920`` -and ``192000000`` (respectively). The ``-fms-compatibility-version=`` flag +either the same value as the currently installed version of cl.exe, or ``1933`` +and ``193300000`` (respectively). The ``-fms-compatibility-version=`` flag overrides these values. It accepts a dotted version tuple, such as 19.00.23506. Changing the MSVC compatibility version makes clang behave more like that version of MSVC. For example, ``-fms-compatibility-version=19`` will enable diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 8a4a174c90ea85..6d925555b7bb4b 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -787,11 +787,11 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, if (MSVT.empty() && Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, IsWindowsMSVC)) { - // -fms-compatibility-version=19.20 is default, aka 2019, 16.x + // -fms-compatibility-version=19.33 is default, aka 2022, 17.3 // NOTE: when changing this value, also update // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst // accordingly. - MSVT = VersionTuple(19, 20); + MSVT = VersionTuple(19, 33); } return MSVT; } diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 6d929b19e7e2ef..81d1b907eced18 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -747,7 +747,7 @@ // Validate that the default triple is used when run an empty tools dir is specified // RUN: %clang_cl -vctoolsdir "" -### -- %s 2>&1 | FileCheck %s --check-prefix VCTOOLSDIR -// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.20.0" +// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.33.0" // Validate that built-in include paths are based on the supplied path // RUN: %clang_cl --target=aarch64-pc-windows-msvc -vctoolsdir "/fake" -winsdkdir "/foo" -winsdkversion 10.0.12345.0 -### -- %s 2>&1 | FileCheck %s --check-prefix FAKEDIR @@ -787,7 +787,7 @@ // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC %s // ARM64EC-NOT: /arm64EC has been overridden by specified target -// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.20.0" +// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.33.0" // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s // ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored >From fda6092fd67f3b425879b414f8c04cb65a88f848 Mon Sep 17 00:00:00 2001 From: Richard Dzenis <dze...@richard.lv> Date: Fri, 8 Dec 2023 21:32:23 +0200 Subject: [PATCH 3/4] fixup! [clang-cl] Bump default -fms-compatibility-version to 19.33 --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d1510add7d8d1c..ce51db51681dab 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -235,6 +235,7 @@ Non-comprehensive list of changes in this release except that it returns the size of a type ignoring tail padding. * ``__builtin_classify_type()`` now classifies ``_BitInt`` values as the return value ``18`` and vector types as return value ``19``, to match GCC 14's behavior. +* The default value of `_MSC_VER` was raised from 1920 to 1933. * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this release adds the attribute as well. * Added ``#pragma clang fp reciprocal``. >From 616895e832622d26b234d2ced1ff716418f153b4 Mon Sep 17 00:00:00 2001 From: Richard Dzenis <dze...@richard.lv> Date: Fri, 8 Dec 2023 21:33:18 +0200 Subject: [PATCH 4/4] fixup! [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute --- clang/include/clang/Basic/AttrDocs.td | 4 ++-- clang/lib/AST/ExprConstant.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 9dc6a909f07d09..1a98196834cefc 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3664,10 +3664,10 @@ The ``[[msvc::constexpr]]`` attribute can be applied only to a function definition or a ``return`` statement. It does not impact function declarations. A ``[[msvc::constexpr]]`` function cannot be ``constexpr`` or ``consteval``. A ``[[msvc::constexpr]]`` function is treated as if it were a ``constexpr`` function -if it is evaluated in a constant context of ``[[msvc::constexpr]] return`` statement. +when it is evaluated in a constant context of ``[[msvc::constexpr]] return`` statement. Otherwise, it is treated as a regular function. -Semantics of this attribute is enabled only under MSVC compatibility +Semantics of this attribute are enabled only under MSVC compatibility (``-fms-compatibility-version``) 19.33 and later. }]; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 90cc0b84f0439c..9bef70770a5449 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5566,7 +5566,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::AttributedStmtClass: { const auto *AS = cast<AttributedStmt>(S); const auto *SS = AS->getSubStmt(); - MSConstexprContextRAII msConstexprContext( + MSConstexprContextRAII ConstexprContext( *Info.CurrentCall, hasSpecificAttr<MSConstexprAttr>(AS->getAttrs()) && isa<ReturnStmt>(SS)); return EvaluateStmt(Result, Info, SS, Case); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits