[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

Richard Dzenis via cfe-commits cfe-commits at lists.llvm.org
Sat Nov 4 17:11:36 PDT 2023


================
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+[[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: Add support for [[msvc::constexpr]] constructor
----------------
RIscRIpt wrote:

Note: this is a long-term TODO, which is quite difficult to implement with reasonably small changes.

Please let me know, how you typically deal with such cases.

---

Redacted comment from https://reviews.llvm.org/D134475#4288759:

Regarding on absolute matching MSVC implementation, I am not sure we will be able to achieve it with reasonable changes. I am skeptical, because I discovered the following test case: (which you see in the code).

It's a valid code for MSVC; nothing special https://godbolt.org/z/znnaonEhM
However supporting this code seems to be difficult in Clang:

`S2` fails checks of "literal type" in this callstack:
1. [clang::CXXRecordDecl::isLiteral](https://github.com/llvm/llvm-project/blob/d27897ade53ab6f983e442f24880260eed26238a/clang/include/clang/AST/DeclCXX.h#L1425-L1451)
2. [clang::Type::isLiteralType](https://github.com/llvm/llvm-project/blob/d27897ade53ab6f983e442f24880260eed26238a/clang/lib/AST/Type.cpp#L2795)
3. [CheckLiteralType](https://github.com/llvm/llvm-project/blob/d27897ade53ab6f983e442f24880260eed26238a/clang/lib/AST/ExprConstant.cpp#L2392-L2397)

We have information about `CanEvalMSConstexpr` only in `CheckLiteralType`. So, currently, I don't see how we can reasonably check whether `S2` is a valid literal type in context of `[[msvc::constexpr]]`. Two obvious ugly solutions are:
1. Copy all checks from `clang::CXXRecordDecl::isLiteral` to `CheckLiteralType` - two places shall be maintained.
2. Propagate `CanEvalMSConstexpr` down to `clang::CXXRecordDecl::isLiteral`. We could add bool args for both `clang::CXXRecordDecl::isLiteral` and `clang::Type::isLiteralType`. But I don't think it's reasonable for supporting rare vendor-specific attribute. Or is it?

I'll try to dive into this problem again, when I start addressing another round of review comments.

https://github.com/llvm/llvm-project/pull/71300


More information about the cfe-commits mailing list