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

Reply via email to