RIscRIpt created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a subscriber: jdoerfert.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D148926
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticASTKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/ExprConstant.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaStmtAttr.cpp
clang/test/AST/msvc-attrs-invalid.cpp
clang/test/AST/msvc-attrs.cpp
clang/test/AST/msvc-constexpr-new.cpp
clang/test/Misc/pragma-attribute-supported-attributes-list.test
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -83,6 +83,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)
Index: clang/test/AST/msvc-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-constexpr-new.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// CHECK: used operator new
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}}
+[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+// CHECK: used constexpr construct_at
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}}
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}}
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}}
+constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); }
+
+constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; }
+
+static_assert(check_construct_at());
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// [[msvc::constexpr]] tests
+
+// MSConstexprDocs (1)
+// CHECK: used f1 'bool ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}}
+[[msvc::constexpr]] bool f1() { return true; }
+
+// MSConstexprDocs (2)
+// CHECK: used constexpr f2 'bool ()'
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}}
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}}
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}}
+constexpr bool f2() { [[msvc::constexpr]] return f1(); }
+
+static_assert(f2());
+
+constexpr bool f3() { [[msvc::constexpr]] return f1() || f1() && f1(); }
+static_assert(f3());
+
+[[msvc::constexpr]] int f4(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f4(x / 2) : 0; }
+constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; }
+static_assert(f5());
+
+[[msvc::constexpr]] int f6(int x)
+{
+switch (x)
+{
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return f4(-x);
+ else return x;
+}
+}
+
+constexpr bool f7() { [[msvc::constexpr]] return f6(f6(42) - 1337 + f6(-32) - 5 + (f6(1) ? f6(0) : f6(2))) == f6(0); }
+static_assert(f7());
Index: clang/test/AST/msvc-attrs-invalid.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs-invalid.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -verify %s
+
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::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 {{[[msvc::constexpr]] cannot be applied to a constexpr function 'f1'}}
+[[msvc::constexpr]] consteval void f2() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a consteval function 'f2'}}
+
+// Check invalid code mixed with valid code
+
+[[msvc::constexpr]] bool undefined();
+
+[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{[[msvc::constexpr]] function 'f4' is used not in '[[msvc::constexpr]] return' statement}}
+constexpr bool f5() {