llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/177388.diff 10 Files Affected: - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+15-2) - (modified) clang/lib/AST/ByteCode/Function.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Interp.cpp (+10-4) - (modified) clang/lib/AST/ByteCode/Interp.h (+12) - (modified) clang/lib/AST/ByteCode/InterpFrame.h (+3) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+3) - (modified) clang/test/AST/ms-constexpr-new.cpp (+1) - (modified) clang/test/SemaCXX/ms-constexpr-invalid.cpp (+3) - (modified) clang/test/SemaCXX/ms-constexpr-new.cpp (+4) - (modified) clang/test/SemaCXX/ms-constexpr.cpp (+1) ``````````diff diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index bbc0f5058e6f9..30e90ed00611b 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -6180,6 +6180,14 @@ bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) { template <class Emitter> bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) { + const Stmt *SubStmt = S->getSubStmt(); + + bool IsMSVCConstexprAttr = isa<ReturnStmt>(SubStmt) && + hasSpecificAttr<MSConstexprAttr>(S->getAttrs()); + + if (IsMSVCConstexprAttr && !this->emitPushMSVCCE(S)) + return false; + if (this->Ctx.getLangOpts().CXXAssumptions && !this->Ctx.getLangOpts().MSVCCompat) { for (const Attr *A : S->getAttrs()) { @@ -6187,7 +6195,7 @@ bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) { if (!AA) continue; - assert(isa<NullStmt>(S->getSubStmt())); + assert(isa<NullStmt>(SubStmt)); const Expr *Assumption = AA->getAssumption(); if (Assumption->isValueDependent()) @@ -6206,7 +6214,12 @@ bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) { } // Ignore other attributes. - return this->visitStmt(S->getSubStmt()); + if (!this->visitStmt(SubStmt)) + return false; + + if (IsMSVCConstexprAttr) + return this->emitPopMSVCCE(S); + return true; } template <class Emitter> diff --git a/clang/lib/AST/ByteCode/Function.cpp b/clang/lib/AST/ByteCode/Function.cpp index a513be56ac0f8..4c7872b19dcdf 100644 --- a/clang/lib/AST/ByteCode/Function.cpp +++ b/clang/lib/AST/ByteCode/Function.cpp @@ -28,7 +28,7 @@ Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize, if (const auto *F = dyn_cast<const FunctionDecl *>(Source)) { Variadic = F->isVariadic(); Immediate = F->isImmediateFunction(); - Constexpr = F->isConstexpr() || F->hasAttr<MSConstexprAttr>(); + Constexpr = F->isConstexpr(); if (const auto *CD = dyn_cast<CXXConstructorDecl>(F)) { Virtual = CD->isVirtual(); Kind = FunctionKind::Ctor; diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 4a98de1e75ecc..b61ff1dfd1691 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1042,7 +1042,9 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { if (S.checkingPotentialConstantExpression() && S.Current->getDepth() != 0) return false; - if (F->isValid() && F->hasBody() && F->isConstexpr()) + if (F->isValid() && F->hasBody() && + (F->isConstexpr() || (S.Current->MSVCConstexprAllowed && + F->getDecl()->hasAttr<MSConstexprAttr>()))) return true; const FunctionDecl *DiagDecl = F->getDecl(); @@ -1551,7 +1553,8 @@ bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD) { const Stmt *Body = FD->getBody(Definition); if (Definition && Body && - (Definition->isConstexpr() || Definition->hasAttr<MSConstexprAttr>())) + (Definition->isConstexpr() || (S.Current->MSVCConstexprAllowed && + Definition->hasAttr<MSConstexprAttr>()))) return true; return diagnoseCallableDecl(S, OpPC, FD); @@ -2062,9 +2065,12 @@ bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) { const FunctionDecl *OperatorNew = NewExpr->getOperatorNew(); if (NewExpr->getNumPlacementArgs() > 0) { - // This is allowed pre-C++26, but only an std function. - if (S.getLangOpts().CPlusPlus26 || S.Current->isStdFunction()) + // This is allowed pre-C++26, but only an std function or if + // [[msvc::constexpr]] was used. + if (S.getLangOpts().CPlusPlus26 || S.Current->isStdFunction() || + (S.Current->MSVCConstexprAllowed)) return true; + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement) << /*C++26 feature*/ 1 << E->getSourceRange(); } else if ( diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 2d8cccb8095a4..0865d1824c311 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3290,6 +3290,18 @@ inline bool PopCC(InterpState &S, CodePtr OpPC) { return true; } +inline bool PushMSVCCE(InterpState &S, CodePtr OpPC) { + // This is a per-frame property. + ++S.Current->MSVCConstexprAllowed; + return true; +} + +inline bool PopMSVCCE(InterpState &S, CodePtr OpPC) { + // This is a per-frame property. + --S.Current->MSVCConstexprAllowed; + return true; +} + /// Do nothing and just abort execution. inline bool Error(InterpState &S, CodePtr OpPC) { return false; } diff --git a/clang/lib/AST/ByteCode/InterpFrame.h b/clang/lib/AST/ByteCode/InterpFrame.h index e150e9279a6ef..61c1065e5848a 100644 --- a/clang/lib/AST/ByteCode/InterpFrame.h +++ b/clang/lib/AST/ByteCode/InterpFrame.h @@ -192,6 +192,9 @@ class InterpFrame final : public Frame { const size_t FrameOffset; /// Mapping from arg offsets to their argument blocks. llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params; + +public: + unsigned MSVCConstexprAllowed = 0; }; } // namespace interp diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 6e768793fcfcf..a3b0275ebd2ea 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -925,3 +925,6 @@ def CheckDestruction : Opcode; def PushCC : Opcode { let Args = [ArgBool]; } def PopCC : Opcode; + +def PushMSVCCE : Opcode; +def PopMSVCCE : Opcode; diff --git a/clang/test/AST/ms-constexpr-new.cpp b/clang/test/AST/ms-constexpr-new.cpp index 4b534cf020764..f39b2594189cf 100644 --- a/clang/test/AST/ms-constexpr-new.cpp +++ b/clang/test/AST/ms-constexpr-new.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump %s -fexperimental-new-constant-interpreter | FileCheck %s // CHECK: used operator new // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} <col:17, col:23> diff --git a/clang/test/SemaCXX/ms-constexpr-invalid.cpp b/clang/test/SemaCXX/ms-constexpr-invalid.cpp index 89102c6fb954f..5405d3dc77aef 100644 --- a/clang/test/SemaCXX/ms-constexpr-invalid.cpp +++ b/clang/test/SemaCXX/ms-constexpr-invalid.cpp @@ -1,5 +1,8 @@ // 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 +// +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s -fexperimental-new-constant-interpreter // Check explicitly invalid code diff --git a/clang/test/SemaCXX/ms-constexpr-new.cpp b/clang/test/SemaCXX/ms-constexpr-new.cpp index 08794565f91df..a311b90bda730 100644 --- a/clang/test/SemaCXX/ms-constexpr-new.cpp +++ b/clang/test/SemaCXX/ms-constexpr-new.cpp @@ -1,5 +1,9 @@ // 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 + +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s -fexperimental-new-constant-interpreter + // supported-no-diagnostics [[nodiscard]] diff --git a/clang/test/SemaCXX/ms-constexpr.cpp b/clang/test/SemaCXX/ms-constexpr.cpp index 79f71a34cb7d8..9beaf3d5a7d8c 100644 --- a/clang/test/SemaCXX/ms-constexpr.cpp +++ b/clang/test/SemaCXX/ms-constexpr.cpp @@ -1,4 +1,5 @@ // 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++20 -verify %s -fexperimental-new-constant-interpreter [[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; } `````````` </details> https://github.com/llvm/llvm-project/pull/177388 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
