Skip to content

[[msvc::constexpr]] constructors are not supported #72149

@RIscRIpt

Description

@RIscRIpt

[[msvc::constexpr]] support was added in #71300.
However, it was lacking support of [[msvc::constexpr]] constructors,
because I was not sure how to support them with reasonable changes.

Consider the following test case (from clang/test/SemaCXX/ms-constexpr.cpp):

struct S2 {
    [[msvc::constexpr]] S2() {}
    [[msvc::constexpr]] bool value() { return true; }
    static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
};
static_assert(S2::check());

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

S2 fails checks of "literal type" in this callstack:

  1. clang::CXXRecordDecl::isLiteral
  2. clang::Type::isLiteralType
  3. CheckLiteralType

We have information about CanEvalMSConstexpr only in CheckLiteralType. Two obvious ugly solutions were:

  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 found another variant of the implementation: let ASTContext know about CanEvalMSConstexpr, and pass const ASTContext& to clang::CXXRecordDecl::isLiteral.

In long term, if clang ever switches to new constexpr analyzer (-fexperimental-new-constant-interpreter), then (as far as I understand) CanEvalMSConstexpr could be moved from ASTContext to clang::interp::Context. Then clang::CXXRecordDecl::isLiteral could accept this context instead of ASTContext.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions