https://github.com/Fznamznon created https://github.com/llvm/llvm-project/pull/77753
Per https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2448r2.html function/constructor/destructor can be marked `constexpr` even though it never produces a constant expression. Non-literal types as return types and parameter types of functions marked `constexpr` are also allowed. Since this is not a DR, the diagnostic messages are still preserved for C++ standards older than C++23. >From 699f47bba02012523e1862f9b15ce9de1d7511b5 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Wed, 18 Oct 2023 02:47:33 -0700 Subject: [PATCH] [Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions Per https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2448r2.html function/constructor/destructor can be marked `constexpr` even though it never produces a constant expression. Non-literal types as return types and parameter types of functions marked `constexpr` are also allowed. Since this is not a DR, the diagnostic messages are still preserved for C++ standards older than C++23. --- clang/docs/ReleaseNotes.rst | 2 + .../clang/Basic/DiagnosticSemaKinds.td | 42 +++-- clang/lib/Sema/SemaDeclCXX.cpp | 54 +++++-- clang/test/AST/Interp/cxx23.cpp | 24 +-- clang/test/AST/Interp/literals.cpp | 2 +- clang/test/AST/Interp/shifts.cpp | 8 +- clang/test/CXX/basic/basic.types/p10.cpp | 26 +-- .../dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp | 8 +- .../dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp | 4 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 27 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 20 +-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp | 6 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp | 2 +- .../dcl.fct.def/dcl.fct.def.default/p2.cpp | 6 +- clang/test/CXX/drs/dr13xx.cpp | 22 +-- clang/test/CXX/drs/dr14xx.cpp | 6 +- clang/test/CXX/drs/dr16xx.cpp | 12 +- clang/test/CXX/drs/dr6xx.cpp | 24 +-- clang/test/CXX/expr/expr.const/p2-0x.cpp | 2 +- clang/test/CXX/expr/expr.const/p5-26.cpp | 4 +- clang/test/CXX/special/class.copy/p13-0x.cpp | 2 +- clang/test/PCH/cxx11-constexpr.cpp | 2 +- clang/test/SemaCXX/builtin_vectorelements.cpp | 2 +- .../SemaCXX/constant-expression-cxx11.cpp | 29 ++-- .../SemaCXX/constant-expression-cxx14.cpp | 33 ++-- .../SemaCXX/constant-expression-cxx2b.cpp | 18 ++- .../constexpr-function-recovery-crash.cpp | 4 +- .../test/SemaCXX/cxx1z-constexpr-lambdas.cpp | 4 +- .../test/SemaCXX/cxx23-invalid-constexpr.cpp | 152 ++++++++++++++++++ clang/test/SemaCXX/cxx2a-consteval.cpp | 4 +- .../SemaCXX/deduced-return-type-cxx14.cpp | 8 +- clang/test/SemaCXX/ms-constexpr-invalid.cpp | 6 +- clang/test/SemaCXX/ms-constexpr.cpp | 2 +- clang/test/SemaCXX/sizeless-1.cpp | 2 +- .../addrspace-constructors.clcpp | 2 +- clang/www/cxx_status.html | 9 +- 36 files changed, 378 insertions(+), 202 deletions(-) create mode 100644 clang/test/SemaCXX/cxx23-invalid-constexpr.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a18d36a16b1a9c..23342a6a7256d8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -165,6 +165,8 @@ C++23 Feature Support - Added a separate warning to warn the use of attributes on lambdas as a C++23 extension in previous language versions: ``-Wc++23-lambda-attributes``. +- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_. + C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a79892e40030a..67409374f26dfa 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2765,10 +2765,14 @@ def err_constexpr_tag : Error< "cannot be marked %sub{select_constexpr_spec_kind}1">; def err_constexpr_dtor : Error< "destructor cannot be declared %sub{select_constexpr_spec_kind}0">; -def err_constexpr_dtor_subobject : Error< - "destructor cannot be declared %sub{select_constexpr_spec_kind}0 because " +def ext_constexpr_dtor_subobject : ExtWarn< + "destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because " "%select{data member %2|base class %3}1 does not have a " - "constexpr destructor">; + "constexpr destructor">, InGroup<CXX23>, DefaultError; +def warn_cxx23_compat_constexpr_dtor_subobject : ExtWarn< + "%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because " + "%select{data member %2|base class %3}1 does not have a " + "constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore; def note_constexpr_dtor_subobject : Note< "%select{data member %1|base class %2}0 declared here">; def err_constexpr_wrong_decl_kind : Error< @@ -2800,11 +2804,14 @@ def note_non_literal_incomplete : Note< def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 " "with virtual base %plural{1:class|:classes}1 is not a literal type">; def note_constexpr_virtual_base_here : Note<"virtual base class declared here">; -def err_constexpr_non_literal_return : Error< - "%select{constexpr|consteval}0 function's return type %1 is not a literal type">; -def err_constexpr_non_literal_param : Error< - "%select{constexpr|consteval}2 %select{function|constructor}1's %ordinal0 parameter type %3 is " - "not a literal type">; +def ext_constexpr_non_literal_return : ExtWarn< + "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">, InGroup<CXX23>, DefaultError; +def warn_cxx23_compat_constexpr_non_literal_return : Warning< + "%select{constexpr|consteval}0 function with non-literal return type %1 is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore; +def ext_constexpr_non_literal_param : ExtWarn< + "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">, InGroup<CXX23>, DefaultError; +def warn_cxx23_compat_constexpr_non_literal_param : Warning< + "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is not compatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore; def err_constexpr_body_invalid_stmt : Error< "statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">; def ext_constexpr_body_invalid_stmt : ExtWarn< @@ -2865,8 +2872,11 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning< "is incompatible with C++ standards before C++20">, InGroup<CXXPre20Compat>, DefaultIgnore; def ext_constexpr_function_never_constant_expr : ExtWarn< - "%select{constexpr|consteval}1 %select{function|constructor}0 never produces a " - "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError; + "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a " + "constant expression is a C++23 extension">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError; +def warn_cxx23_compat_constexpr_function_never_constant_expr : Warning< + "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a " + "constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore; def err_attr_cond_never_constant_expr : Error< "%0 attribute expression never produces a constant expression">; def err_diagnose_if_invalid_diagnostic_type : Error< @@ -9539,14 +9549,14 @@ def err_defaulted_special_member_copy_const_param : Error< def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; -def err_incorrect_defaulted_constexpr : Error< - "defaulted definition of %sub{select_special_member_kind}0 " - "is not constexpr">; +def ext_incorrect_defaulted_constexpr : ExtWarn< + "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 " + "but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError; +def warn_cxx23_compat_incorrect_defaulted_constexpr : Warning< + "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 " + "but never produces a constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore; def err_incorrect_defaulted_constexpr_with_vb: Error< "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">; -def err_incorrect_defaulted_consteval : Error< - "defaulted declaration of %sub{select_special_member_kind}0 " - "cannot be consteval because implicit definition is not constexpr">; def warn_defaulted_method_deleted : Warning< "explicitly defaulted %sub{select_special_member_kind}0 is implicitly " "deleted">, InGroup<DefaultedFunctionDeleted>; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 36e53c684ac4dc..aa49dc73e157bf 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1722,12 +1722,19 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, return true; if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject) + SemaRef.Diag(DD->getLocation(), + SemaRef.getLangOpts().CPlusPlus23 + ? diag::warn_cxx23_compat_constexpr_dtor_subobject + : diag::ext_constexpr_dtor_subobject) << static_cast<int>(DD->getConstexprKind()) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; } + + if (SemaRef.getLangOpts().CPlusPlus23) + return true; + return false; }; @@ -1754,11 +1761,17 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); assert(PD && "null in a parameter list"); SourceLocation ParamLoc = PD->getLocation(); - if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i, - diag::err_constexpr_non_literal_param, ArgIndex + 1, - PD->getSourceRange(), isa<CXXConstructorDecl>(FD), - FD->isConsteval())) + if (CheckLiteralType( + SemaRef, Kind, ParamLoc, *i, + SemaRef.getLangOpts().CPlusPlus23 + ? diag::warn_cxx23_compat_constexpr_non_literal_param + : diag::ext_constexpr_non_literal_param, + ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD), + FD->isConsteval())) { + if (SemaRef.getLangOpts().CPlusPlus23) + return true; return false; + } } return true; } @@ -1767,10 +1780,16 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, /// true. If not, produce a suitable diagnostic and return false. static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD, Sema::CheckConstexprKind Kind) { - if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(), - diag::err_constexpr_non_literal_return, - FD->isConsteval())) + if (CheckLiteralType( + SemaRef, Kind, FD->getLocation(), FD->getReturnType(), + SemaRef.getLangOpts().CPlusPlus23 + ? diag::warn_cxx23_compat_constexpr_non_literal_return + : diag::ext_constexpr_non_literal_return, + FD->isConsteval())) { + if (SemaRef.getLangOpts().CPlusPlus23) + return true; return false; + } return true; } @@ -2458,8 +2477,11 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, SmallVector<PartialDiagnosticAt, 8> Diags; if (Kind == Sema::CheckConstexprKind::Diagnose && !Expr::isPotentialConstantExpr(Dcl, Diags)) { - SemaRef.Diag(Dcl->getLocation(), - diag::ext_constexpr_function_never_constant_expr) + SemaRef.Diag( + Dcl->getLocation(), + SemaRef.getLangOpts().CPlusPlus23 + ? diag::warn_cxx23_compat_constexpr_function_never_constant_expr + : diag::ext_constexpr_function_never_constant_expr) << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval() << Dcl->getNameInfo().getSourceRange(); for (size_t I = 0, N = Diags.size(); I != N; ++I) @@ -7852,13 +7874,15 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); } else { - Diag(MD->getBeginLoc(), MD->isConsteval() - ? diag::err_incorrect_defaulted_consteval - : diag::err_incorrect_defaulted_constexpr) - << CSM; + Diag(MD->getBeginLoc(), + getLangOpts().CPlusPlus23 + ? diag::warn_cxx23_compat_incorrect_defaulted_constexpr + : diag::ext_incorrect_defaulted_constexpr) + << CSM << MD->isConsteval(); } // FIXME: Explain why the special member can't be constexpr. - HadError = true; + if (!getLangOpts().CPlusPlus23) + HadError = true; } if (First) { diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp index bd1cf186d519c5..6ef7df9662e6a4 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/Interp/cxx23.cpp @@ -6,57 +6,45 @@ /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics. -constexpr int f(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // ref23-error {{constexpr function never produces a constant expression}} +constexpr int f(int n) { // ref20-error {{constexpr function that never produces a constant expression}} static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \ // ref20-warning {{is a C++23 extension}} \ - // ref23-note {{control flows through the definition of a static variable}} \ // expected20-warning {{is a C++23 extension}} return m; } -constexpr int g(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // ref23-error {{constexpr function never produces a constant expression}} +constexpr int g(int n) { // ref20-error {{constexpr function that never produces a constant expression}} thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ - // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} return m; } -constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // ref23-error {{constexpr function never produces a constant expression}} +constexpr int c_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}} static _Thread_local int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ - // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} return m; } -constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // ref23-error {{constexpr function never produces a constant expression}} +constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}} static __thread int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ - // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} return m; } -constexpr int h(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // ref23-error {{constexpr function never produces a constant expression}} +constexpr int h(int n) { // ref20-error {{constexpr function that never produces a constant expression}} static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \ // ref20-warning {{is a C++23 extension}} \ - // ref23-note {{control flows through the definition of a static variable}} \ // expected20-warning {{is a C++23 extension}} return &m - &m; } -constexpr int i(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // ref23-error {{constexpr function never produces a constant expression}} +constexpr int i(int n) { // ref20-error {{constexpr function that never produces a constant expression}} thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ - // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} return &m - &m; } diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 61825bc11438f6..ab09280e883fba 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -275,7 +275,7 @@ namespace SizeOf { #if __cplusplus >= 202002L /// FIXME: The following code should be accepted. - consteval int foo(int n) { // ref-error {{consteval function never produces a constant expression}} + consteval int foo(int n) { // ref-error {{consteval function that never produces a constant expression}} return sizeof(int[n]); // ref-note 3{{not valid in a constant expression}} } constinit int var = foo(5); // ref-error {{not a constant expression}} \ diff --git a/clang/test/AST/Interp/shifts.cpp b/clang/test/AST/Interp/shifts.cpp index cf71e7145c2742..f8fa1b5d095da0 100644 --- a/clang/test/AST/Interp/shifts.cpp +++ b/clang/test/AST/Interp/shifts.cpp @@ -7,10 +7,10 @@ namespace shifts { - constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \ - // ref-cxx17-error {{constexpr function never produces a constant expression}} \ - // expected-error {{constexpr function never produces a constant expression}} \ - // cxx17-error {{constexpr function never produces a constant expression}} \ + constexpr void test() { // ref-error {{constexpr function that never produces a constant expression}} \ + // ref-cxx17-error {{constexpr function that never produces a constant expression}} \ + // expected-error {{constexpr function that never produces a constant expression}} \ + // cxx17-error {{constexpr function that never produces a constant expression}} \ char c; // cxx17-warning {{uninitialized variable}} \ // ref-cxx17-warning {{uninitialized variable}} diff --git a/clang/test/CXX/basic/basic.types/p10.cpp b/clang/test/CXX/basic/basic.types/p10.cpp index a543f248e53711..19e099d5077de7 100644 --- a/clang/test/CXX/basic/basic.types/p10.cpp +++ b/clang/test/CXX/basic/basic.types/p10.cpp @@ -8,7 +8,7 @@ struct NonLiteral { NonLiteral(); }; // [C++1y] - void constexpr void f() {} #ifndef CXX1Y -// expected-error@-2 {{'void' is not a literal type}} +// expected-error@-2 {{constexpr function with non-literal return type 'void' is a C++23 extension}} #endif // - a scalar type @@ -40,12 +40,12 @@ constexpr ClassTemp<int> classtemplate2[] = {}; struct UserProvDtor { ~UserProvDtor(); // expected-note {{has a user-provided destructor}} }; -constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}} +constexpr int f(UserProvDtor) { return 0; } // expected-error {{non-literal parameter type 'UserProvDtor'}} struct NonTrivDtor { constexpr NonTrivDtor(); virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}} }; -constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}} +constexpr int f(NonTrivDtor) { return 0; } // expected-error {{non-literal parameter type 'NonTrivDtor'}} struct NonTrivDtorBase { ~NonTrivDtorBase(); }; @@ -53,7 +53,7 @@ template<typename T> struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} constexpr DerivedFromNonTrivDtor(); }; -constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} +constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is a C++23 extension}} struct TrivDtor { constexpr TrivDtor(); }; @@ -77,11 +77,11 @@ struct CtorTemplate { struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr CopyCtorOnly(CopyCtorOnly&); }; -constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}} +constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'CopyCtorOnly'}} struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} constexpr MoveCtorOnly(MoveCtorOnly&&); }; -constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}} +constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'MoveCtorOnly'}} template<typename T> struct CtorArg { constexpr CtorArg(T); @@ -97,7 +97,7 @@ struct Derived : HasVBase { template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} constexpr DerivedFromVBase(); }; -constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} +constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromVBase<HasVBase>' is a C++23 extension}} template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {} constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}} @@ -105,12 +105,12 @@ constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{co struct NonLitMember { S s; // expected-note {{has data member 's' of non-literal type 'S'}} }; -constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} +constexpr int f(NonLitMember) {} // expected-error {{1st non-literal parameter type 'NonLitMember' is a C++23 extension}} struct NonLitBase : S { // expected-note {{base class 'S' of non-literal type}} constexpr NonLitBase(); }; -constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}} +constexpr int f(NonLitBase) { return 0; } // expected-error {{non-literal parameter type 'NonLitBase'}} struct LitMemBase : Agg { Agg agg; }; @@ -120,7 +120,7 @@ struct MemberType { constexpr MemberType(); }; constexpr int f(MemberType<int>) { return 0; } -constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}} +constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{non-literal parameter type}} // - an array of literal type [C++1y] other than an array of runtime bound struct ArrGood { @@ -134,7 +134,7 @@ constexpr int f(ArrGood) { return 0; } struct ArrBad { S s[3]; // expected-note {{data member 's' of non-literal type 'S[3]'}} }; -constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}} +constexpr int f(ArrBad) { return 0; } // expected-error {{1st non-literal parameter type 'ArrBad'}} constexpr int arb(int n) { // expected-note {{declared here}} int a[n]; // expected-error {{variable of non-literal type 'int[n]' cannot be defined in a constexpr function}} \ @@ -159,7 +159,7 @@ namespace inherited_ctor { D(int); using C::C; }; - constexpr int f(D) { return 0; } // expected-error {{not a literal type}} + constexpr int f(D) { return 0; } // expected-error {{non-literal parameter type}} // This one is a bit odd: F inherits E's default constructor, which is // constexpr. Because F has a constructor of its own, it doesn't declare a @@ -178,7 +178,7 @@ namespace inherited_ctor { struct H : G { // expected-note {{because}} using G::G; }; - constexpr int f(H) { return 0; } // expected-error {{not a literal type}} + constexpr int f(H) { return 0; } // expected-error {{non-literal parameter type}} struct J; struct I { constexpr I(const J&); }; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp index 7ad2e582a81268..1a3da8bdc252ac 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp @@ -58,12 +58,12 @@ namespace subobject { struct A { ~A(); }; - struct B : A { // expected-note {{here}} - constexpr ~B() {} // expected-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}} + struct B : A { // cxx2a-note {{here}} + constexpr ~B() {} // cxx2a-error {{destructor cannot be declared constexpr before C++23 because base class 'A' does not have a constexpr destructor}} }; struct C { - A a; // expected-note {{here}} - constexpr ~C() {} // expected-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}} + A a; // cxx2a-note {{here}} + constexpr ~C() {} // cxx2a-error {{destructor cannot be declared constexpr before C++23 because data member 'a' does not have a constexpr destructor}} }; struct D : A { A a; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp index c07502c0555b50..e8c71b44edd620 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp @@ -14,7 +14,7 @@ constexpr int i(int n) { return m; } -constexpr int g() { // expected-error {{constexpr function never produces a constant expression}} +constexpr int g() { // expected-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} goto test; // expected-note {{subexpression not valid in a constant expression}} \ // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} test: @@ -29,7 +29,7 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}} NonLiteral() {} }; -constexpr void non_literal() { // expected-error {{constexpr function never produces a constant expression}} +constexpr void non_literal() { // expected-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} NonLiteral n; // expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} \ // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}} } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 6214ff8006d67f..d57c098faff6dd 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,beforecxx14,beforecxx20,beforecxx23 -std=c++11 %s -// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23 -std=c++14 %s -// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23 -std=c++20 %s +// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23,cxx14_20 -std=c++14 %s +// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23,cxx14_20 -std=c++20 %s // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20 -std=c++23 %s namespace N { @@ -11,7 +11,7 @@ namespace M { typedef double D; } -struct NonLiteral { // expected-note 2{{no constexpr constructors}} +struct NonLiteral { // beforecxx23-note 2{{no constexpr constructors}} NonLiteral() {} NonLiteral(int) {} }; @@ -41,18 +41,17 @@ struct T : SS, NonLiteral { virtual constexpr int OutOfLineVirtual() const; // beforecxx20-error {{virtual function cannot be constexpr}} // - its return type shall be a literal type; - // Once we support P2448R2 constexpr functions will be allowd to return non-literal types - // The destructor will also be allowed - constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} - constexpr void VoidReturn() const { return; } // beforecxx14-error {{constexpr function's return type 'void' is not a literal type}} + // With support for P2448R2 constexpr functions are allowed to return non-literal types in C++23. + constexpr NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-error {{constexpr function with non-literal return type 'NonLiteral' is a C++23 extension}} + constexpr void VoidReturn() const { return; } // beforecxx14-error {{constexpr function with non-literal return type 'void' is a C++23 extension}} constexpr ~T(); // beforecxx20-error {{destructor cannot be declared constexpr}} typedef NonLiteral F() const; constexpr F NonLiteralReturn2; // ok until definition // - each of its parameter types shall be a literal type; - // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types - constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + // With support for P2448R2 constexpr functions are allowed to have parameters of non-literal types in C++23. + constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}} typedef int G(NonLiteral) const; constexpr G NonLiteralParam2; // ok until definition @@ -66,7 +65,7 @@ struct T : SS, NonLiteral { // constexpr since they can't be const. constexpr T &operator=(const T &) = default; // beforecxx14-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} \ // beforecxx14-warning {{C++14}} \ - // aftercxx14-error{{defaulted definition of copy assignment operator is not constexpr}} + // cxx14_20-error{{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression}} }; constexpr int T::OutOfLineVirtual() const { return 0; } @@ -229,9 +228,9 @@ namespace DR1364 { return k; // ok, even though lvalue-to-rvalue conversion of a function // parameter is not allowed in a constant expression. } - int kGlobal; // expected-note {{here}} - constexpr int f() { // expected-error {{constexpr function never produces a constant expression}} - return kGlobal; // expected-note {{read of non-const}} + int kGlobal; // beforecxx23-note {{here}} + constexpr int f() { // beforecxx23-error {{constexpr function that never produces a constant expression is a C++23 extension}} + return kGlobal; // beforecxx23-note {{read of non-const}} } } @@ -272,7 +271,7 @@ namespace std_example { int a; // beforecxx20-warning {{uninitialized}} return a; } - constexpr int prev(int x) { // beforecxx14-error {{never produces a constant expression}} + constexpr int prev(int x) { // beforecxx14-error {{constexpr function that never produces a constant expression is a C++23 extension}} return --x; // beforecxx14-note {{subexpression}} } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index f1f677ebfcd341..71c8d09d3041d4 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -24,8 +24,8 @@ struct Literal { // shall be a literal type. struct S { constexpr S(int, N::C) {} - constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} - constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor with 2nd non-literal parameter type 'NonLiteral' is a C++23 extension}} + constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor with 2nd non-literal parameter type 'NonLiteral' is a C++23 extension}} // In addition, either its function-body shall be = delete or = default constexpr S() = default; @@ -242,15 +242,15 @@ constexpr int f(enable_shared_from_this<int>); // - every constructor involved in initializing non-static data members and base // class sub-objects shall be a constexpr constructor. -// This will no longer be the case once we support P2448R2 +// This is the case before C++23. struct ConstexprBaseMemberCtors : Literal { Literal l; constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok - constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}} + constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} Literal(0), // expected-note {{non-constexpr constructor}} l() {} - constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}} + constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} l(0) // expected-note {{non-constexpr constructor}} {} }; @@ -272,7 +272,7 @@ struct X { union XU1 { int a; constexpr XU1() = default; }; #ifndef CXX2A -// expected-error@-2{{not constexpr}} +// expected-error@-2{{marked constexpr but never produces a constant expression}} #endif union XU2 { int a = 1; constexpr XU2() = default; }; @@ -282,7 +282,7 @@ struct XU3 { }; constexpr XU3() = default; #ifndef CXX2A - // expected-error@-2{{not constexpr}} + // expected-error@-2{{marked constexpr but never produces a constant expression}} #endif }; struct XU4 { @@ -306,7 +306,7 @@ static_assert(XU4().a == 1, ""); int kGlobal; // expected-note {{here}} struct Z { constexpr Z(int a) : n(a) {} - constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} + constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} expected-note {{read of non-const}} int n; }; @@ -333,7 +333,7 @@ namespace CtorLookup { constexpr B(B&); }; constexpr B::B(const B&) = default; - constexpr B::B(B&) = default; // expected-error {{not constexpr}} + constexpr B::B(B&) = default; // expected-error {{marked constexpr but never produces a constant expression}} struct C { A a; @@ -342,7 +342,7 @@ namespace CtorLookup { constexpr C(C&); }; constexpr C::C(const C&) = default; - constexpr C::C(C&) = default; // expected-error {{not constexpr}} + constexpr C::C(C&) = default; // expected-error {{marked constexpr but never produces a constant expression}} } namespace PR14503 { diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp index 18b2c6b1d6d15b..7c06e5a9f928ad 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp @@ -30,7 +30,7 @@ static_assert(g4() == 5, ""); constexpr int f(bool b) { return b ? throw 0 : 0; } // ok -constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}} +constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function that never produces a constant expression is a C++23 extension}} expected-note {{subexpression}} struct B { constexpr B(int x) : i(0) { } @@ -40,14 +40,14 @@ struct B { int global; // expected-note {{declared here}} struct D : B { - constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} + constexpr D() : B(global) { } // expected-error {{constexpr constructor that never produces a constant expression}} expected-note {{read of non-const}} }; } namespace PotentialConstant { -constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}} +constexpr int Comma(int n) { return // expected-error {{constexpr function that never produces a constant expression}} (void)(n * 2), throw 0, // expected-note {{subexpression}} 0; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp index 00ef78426289fa..850420ca8ae1c0 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -64,5 +64,5 @@ namespace TemplateVBase { constexpr T3() {} }; constexpr T3<Literal> g3() { return {}; } // ok - constexpr T3<VirtBase> g4() { return {}; } // expected-error {{not a literal type}} + constexpr T3<VirtBase> g4() { return {}; } // expected-error {{non-literal return type}} } diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp index 5b525fc91aba1c..9c9034c7f908ba 100644 --- a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp +++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -3,7 +3,7 @@ // An explicitly-defaulted function may be declared constexpr only if it would // have been implicitly declared as constexpr. struct S1 { - constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}} + constexpr S1() = default; // expected-error {{marked constexpr but never produces a constant expression}} constexpr S1(const S1&) = default; constexpr S1(S1&&) = default; constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}} @@ -18,8 +18,8 @@ struct NoCopyMove { }; struct S2 { constexpr S2() = default; - constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}} - constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}} + constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is a C++23 extension}} + constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor that marked constexpr but never produces a constant expression}} NoCopyMove ncm; }; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index 359c04b3e0f3d4..be656c4468eaeb 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors @@ -410,11 +410,11 @@ namespace dr1358 { // dr1358: 3.1 struct B : Virt { int member; constexpr B(NonLit u) : member(u) {} - // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} - // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-error@-1 {{constexpr constructor with 1st non-literal parameter type 'NonLit' is a C++23 extension}} + // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr NonLit f(NonLit u) const { return NonLit(); } - // since-cxx11-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} - // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-error@-1 {{constexpr function with non-literal return type 'NonLit' is a C++23 extension}} + // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} }; #endif } @@ -423,13 +423,13 @@ namespace dr1359 { // dr1359: 3.5 #if __cplusplus >= 201103L union A { constexpr A() = default; }; union B { constexpr B() = default; int a; }; // #dr1359-B - // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}} union C { constexpr C() = default; int a, b; }; // #dr1359-C - // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr}} struct X { constexpr X() = default; union {}; }; // since-cxx11-error@-1 {{declaration does not declare anything}} struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y - // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr}} constexpr A a = A(); constexpr B b = B(); diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index d262f6f9dcab79..4bce1de0ab5149 100644 --- a/clang/test/CXX/drs/dr14xx.cpp +++ b/clang/test/CXX/drs/dr14xx.cpp @@ -153,16 +153,16 @@ namespace dr1460 { // dr1460: 3.5 namespace Defaulted { union A { constexpr A() = default; }; union B { int n; constexpr B() = default; }; - // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}} union C { int n = 0; constexpr C() = default; }; struct D { union {}; constexpr D() = default; }; // expected-error@-1 {{declaration does not declare anything}} struct E { union { int n; }; constexpr E() = default; }; - // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}} struct F { union { int n = 0; }; constexpr F() = default; }; struct G { union { int n = 0; }; union { int m; }; constexpr G() = default; }; - // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}} struct H { union { int n = 0; diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 3f074c4d57354a..1cf7bb840507ff 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors @@ -349,8 +349,8 @@ namespace dr1684 { // dr1684: 3.6 }; constexpr int f(NonLiteral &) { return 0; } constexpr int f(NonLiteral) { return 0; } - // since-cxx11-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} - // since-cxx11-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-error@-1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}} + // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} #endif } diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp index 78604d480aa1ca..17e32dcc51ac98 100644 --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-17,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking namespace dr600 { // dr600: 2.8 @@ -584,8 +584,8 @@ namespace dr647 { // dr647: 3.1 struct C { constexpr C(NonLiteral); constexpr C(NonLiteral, int) {} - // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}} - // since-cxx11-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-error@-1 {{constexpr constructor with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}} + // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr C() try {} catch (...) {} // cxx11-17-error@-1 {{function try block in constexpr constructor is a C++20 extension}} // cxx11-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} @@ -609,15 +609,15 @@ namespace dr647 { // dr647: 3.1 d(0) {} constexpr E(int) - // since-cxx11-error@-1 {{constexpr constructor never produces a constant expression}} - // since-cxx11-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}} - // since-cxx11-note@#dr647-D-float-ctor {{declared here}} + // cxx11-20-error@-1 {{constexpr constructor that never produces a constant expression}} + // cxx11-20-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}} + // cxx11-20-note@#dr647-D-float-ctor {{declared here}} : n(0), d(0.0f) {} // #dr647-int-d constexpr E(float f) - // since-cxx11-error@-1 {{never produces a constant expression}} - // since-cxx11-note@#dr647-float-d {{non-constexpr constructor}} - // since-cxx11-note@#dr647-D-float-ctor {{declared here}} + // cxx11-20-error@-1 {{never produces a constant expression}} + // cxx11-20-note@#dr647-float-d {{non-constexpr constructor}} + // cxx11-20-note@#dr647-D-float-ctor {{declared here}} : n(get()), d(D(0) + f) {} // #dr647-float-d }; diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index e3cd057baba75f..868dacd4415a39 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -302,7 +302,7 @@ constexpr float negpi = -pi; // expect no error on unary operator #if __cplusplus >= 201703L namespace CompoundAssignment { -constexpr int rem() { // expected-error {{constexpr function never produces a constant expression}} +constexpr int rem() { // expected-error {{constexpr function that never produces a constant expression}} int x = ~__INT_MAX__; return x%=-1; // cxx20-note {{value 2147483648 is outside the range of representable values of type 'int'}} } diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp index de2afa71b42669..3624b1e5a3e3df 100644 --- a/clang/test/CXX/expr/expr.const/p5-26.cpp +++ b/clang/test/CXX/expr/expr.const/p5-26.cpp @@ -5,11 +5,11 @@ struct S {}; struct T : S {} t; -consteval void test() { // cxx23-error{{consteval function never produces a constant expression}} +consteval void test() { void* a = &t; const void* b = &t; volatile void* c = &t; - (void)static_cast<T*>(a); //cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}} + (void)static_cast<T*>(a); (void)static_cast<const T*>(a); (void)static_cast<volatile T*>(a); diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp index 16c8a4029cbac6..2f6173be74a2ae 100644 --- a/clang/test/CXX/special/class.copy/p13-0x.cpp +++ b/clang/test/CXX/special/class.copy/p13-0x.cpp @@ -125,7 +125,7 @@ namespace Mutable { mutable A a; }; struct C { - constexpr C(const C &) = default; // expected-error {{not constexpr}} + constexpr C(const C &) = default; // expected-error {{marked constexpr but never produces a constant expression}} A a; }; } diff --git a/clang/test/PCH/cxx11-constexpr.cpp b/clang/test/PCH/cxx11-constexpr.cpp index b315b477dbf1c6..22cc53e9152cd6 100644 --- a/clang/test/PCH/cxx11-constexpr.cpp +++ b/clang/test/PCH/cxx11-constexpr.cpp @@ -33,7 +33,7 @@ constexpr T plus_seven(T other) { #else static_assert(D(4).k == 9, ""); -constexpr int f(C c) { return 0; } // expected-error {{not a literal type}} +constexpr int f(C c) { return 0; } // expected-error {{non-literal parameter type}} // expected-note@16 {{not an aggregate and has no constexpr constructors}} constexpr B b; // expected-error {{constant expression}} expected-note {{non-constexpr}} // expected-note@12 {{here}} diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp index 59ff09ac72e42d..e83d931ee4026f 100644 --- a/clang/test/SemaCXX/builtin_vectorelements.cpp +++ b/clang/test/SemaCXX/builtin_vectorelements.cpp @@ -41,7 +41,7 @@ void test_builtin_vectorelements() { #if defined(__ARM_FEATURE_SVE) #include <arm_sve.h> -consteval int consteval_elements() { // expected-error {{consteval function never produces a constant expression}} +consteval int consteval_elements() { // expected-error {{consteval function that never produces a constant expression}} return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 9e2ae07cbe4c9c..a29659301dfd66 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1273,8 +1273,8 @@ namespace PR11595 { struct B { B(); A& x; }; static_assert(B().x == 3, ""); // expected-error {{constant expression}} expected-note {{non-literal type 'B' cannot be used in a constant expression}} - constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}} - return B().x == k; // expected-note {{non-literal type 'B' cannot be used in a constant expression}} + constexpr bool f(int k) { // cxx11_20-error {{constexpr function that never produces a constant expression}} + return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used in a constant expression}} } } @@ -1326,8 +1326,8 @@ namespace ExternConstexpr { constexpr int g() { return q; } // expected-note {{outside its lifetime}} constexpr int q = g(); // expected-error {{constant expression}} expected-note {{in call}} - extern int r; // expected-note {{here}} - constexpr int h() { return r; } // expected-error {{never produces a constant}} expected-note {{read of non-const}} + extern int r; // cxx11_20-note {{here}} + constexpr int h() { return r; } // cxx11_20-error {{never produces a constant}} cxx11_20-note {{read of non-const}} struct S { int n; }; extern const S s; @@ -1767,7 +1767,7 @@ namespace TLS { } namespace Void { - constexpr void f() { return; } // cxx11-error{{constexpr function's return type 'void' is not a literal type}} + constexpr void f() { return; } // cxx11-error{{constexpr function with non-literal return type 'void' is a C++23 extension}} void assert_failed(const char *msg, const char *file, int line); // expected-note {{declared here}} #define ASSERT(expr) ((expr) ? static_cast<void>(0) : assert_failed(#expr, __FILE__, __LINE__)) @@ -1906,9 +1906,9 @@ namespace StmtExpr { }); } static_assert(g(123) == 15129, ""); - constexpr int h() { // expected-error {{never produces a constant}} + constexpr int h() { // cxx11_20-error {{never produces a constant}} return ({ // expected-warning {{extension}} - return 0; // expected-note {{not supported}} + return 0; // cxx11_20-note {{not supported}} 1; }); } @@ -2093,8 +2093,8 @@ namespace ZeroSizeTypes { // expected-note@-2 {{subtraction of pointers to type 'int[0]' of zero size}} int arr[5][0]; - constexpr int f() { // expected-error {{never produces a constant expression}} - return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int[0]' of zero size}} + constexpr int f() { // cxx11_20-error {{never produces a constant expression}} + return &arr[3] - &arr[0]; // cxx11_20-note {{subtraction of pointers to type 'int[0]' of zero size}} } } @@ -2118,8 +2118,8 @@ namespace NeverConstantTwoWays { // If we see something non-constant but foldable followed by something // non-constant and not foldable, we want the first diagnostic, not the // second. - constexpr int f(int n) { // expected-error {{never produces a constant expression}} - return (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}} + constexpr int f(int n) { // cxx11_20-error {{never produces a constant expression}} + return (int *)(long)&n == &n ? // cxx11_20-note {{reinterpret_cast}} 1 / 0 : // expected-warning {{division by zero}} 0; } @@ -2316,10 +2316,11 @@ namespace InheritedCtor { namespace PR28366 { namespace ns1 { -void f(char c) { //expected-note2{{declared here}} +void f(char c) { //expected-note{{declared here}} + //cxx11_20-note@-1{{declared here}} struct X { - static constexpr char f() { //expected-error{{never produces a constant expression}} - return c; //expected-error{{reference to local}} expected-note{{function parameter}} + static constexpr char f() { // cxx11_20-error {{never produces a constant expression}} + return c; //expected-error{{reference to local}} cxx11_20-note{{function parameter}} } }; int I = X::f(); diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index 273d7ff3a208e2..c829bcc1fc94d4 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -44,13 +44,13 @@ constexpr int g(int k) { return 3 * k3 + 5 * k2 + n * k - 20; } static_assert(g(2) == 42, ""); -constexpr int h(int n) { // expected-error {{constexpr function never produces a constant expression}} - static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ +constexpr int h(int n) { // cxx14_20-error {{constexpr function that never produces a constant expression}} + static const int m = n; // cxx14_20-note {{control flows through the definition of a static variable}} \ // cxx14_20-warning {{definition of a static variable in a constexpr function is a C++23 extension}} return m; } -constexpr int i(int n) { // expected-error {{constexpr function never produces a constant expression}} - thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ +constexpr int i(int n) { // cxx14_20-error {{constexpr function that never produces a constant expression}} + thread_local const int m = n; // cxx14_20-note {{control flows through the definition of a thread_local variable}} \ // cxx14_20-warning {{definition of a thread_local variable in a constexpr function is a C++23 extension}} return m; } @@ -68,6 +68,7 @@ constexpr int j(int k) { } } } // expected-note 2{{control reached end of constexpr function}} + // cxx23-warning@-1 {{does not return a value in all control paths}} static_assert(j(0) == -3, ""); static_assert(j(1) == 5, ""); static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}} @@ -104,10 +105,10 @@ static_assert(l(false) == 5, ""); static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}} // Potential constant expression checking is still applied where possible. -constexpr int htonl(int x) { // expected-error {{never produces a constant expression}} +constexpr int htonl(int x) { // cxx14_20-error {{never produces a constant expression}} typedef unsigned char uchar; uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) }; - return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} + return *reinterpret_cast<int*>(arr); // cxx14_20-note {{reinterpret_cast is not allowed in a constant expression}} } constexpr int maybe_htonl(bool isBigEndian, int x) { @@ -183,7 +184,7 @@ namespace string_assign { static_assert(!test1(100), ""); static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}} - constexpr void f() { // expected-error{{constexpr function never produces a constant expression}} expected-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} + constexpr void f() { // cxx14_20-error{{constexpr function that never produces a constant expression}} cxx14_20-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} char foo[10] = { "z" }; // expected-note {{here}} foo[10] = 'x'; // expected-warning {{past the end}} } @@ -207,14 +208,14 @@ namespace array_resize { namespace potential_const_expr { constexpr void set(int &n) { n = 1; } constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error - constexpr int div_zero_2() { // expected-error {{never produces a constant expression}} + constexpr int div_zero_2() { // cxx14_20-error {{never produces a constant expression}} int z = 0; - return 100 / (set(z), 0); // expected-note {{division by zero}} + return 100 / (set(z), 0); // cxx14_20-note {{division by zero}} } - int n; // expected-note {{declared here}} - constexpr int ref() { // expected-error {{never produces a constant expression}} + int n; // cxx14_20-note {{declared here}} + constexpr int ref() { // cxx14_20-error {{never produces a constant expression}} int &r = n; - return r; // expected-note {{read of non-const variable 'n'}} + return r; // cxx14_20-note {{read of non-const variable 'n'}} } } @@ -846,8 +847,8 @@ namespace StmtExpr { static_assert(g() == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} // FIXME: We should handle the void statement expression case. - constexpr int h() { // expected-error {{never produces a constant}} - ({ if (true) {} }); // expected-note {{not supported}} + constexpr int h() { // cxx14_20-error {{never produces a constant}} + ({ if (true) {} }); // cxx14_20-note {{not supported}} return 0; } } @@ -1043,9 +1044,9 @@ static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral cons constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}} } -constexpr void PR28739(int n) { // expected-error {{never produces a constant}} +constexpr void PR28739(int n) { // cxx14_20-error {{never produces a constant}} int *p = &n; // expected-note {{array 'p' declared here}} - p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}} + p += (__int128)(unsigned long)-1; // cxx14_20-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}} // expected-warning@-1 {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 32-bit (4-byte) elements (max possible 4611686018427387904 elements)}} } diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp index 2ee1d48d1cd697..e92a64d830881f 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp @@ -10,35 +10,41 @@ struct Constexpr{}; #if __cplusplus > 202002L -constexpr int f(int n) { // expected-error {{constexpr function never produces a constant expression}} +constexpr int f(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \ + // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int g(int n) { // expected-error {{constexpr function never produces a constant expression}} +constexpr int g(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \ + // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int c_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}} +constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \ + // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} static _Thread_local int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int gnu_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}} +constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \ + // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} static __thread int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int h(int n) { // expected-error {{constexpr function never produces a constant expression}} +constexpr int h(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \ + // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return &m - &m; } -constexpr int i(int n) { // expected-error {{constexpr function never produces a constant expression}} +constexpr int i(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \ + // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} return &m - &m; diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp index 90ee7892b2fc2e..dd0b911fc516b2 100644 --- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp +++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp @@ -34,13 +34,13 @@ constexpr int test4() { return 0; } -constexpr int test5() { // expected-error {{constexpr function never produce}} +constexpr int test5() { // expected-error {{constexpr function that never produce}} for (;; a++); // expected-error {{use of undeclared identifier}} \ expected-note {{constexpr evaluation hit maximum step limit; possible infinite loop?}} return 1; } -constexpr int test6() { // expected-error {{constexpr function never produce}} +constexpr int test6() { // expected-error {{constexpr function that never produce}} int n = 0; switch (n) { for (;; a++) { // expected-error {{use of undeclared identifier}} diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp index 6a1f48bf7958fd..46c24cc3e5d0b7 100644 --- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -6,7 +6,7 @@ namespace test_lambda_is_literal { #ifdef CPP14_AND_EARLIER -//expected-error@+4{{not a literal type}} +//expected-error@+4{{non-literal parameter type}} //expected-note@+2{{lambda closure types are non-literal types before C++17}} #endif auto L = [] { }; @@ -19,7 +19,7 @@ namespace test_constexpr_checking { namespace ns1 { struct NonLit { ~NonLit(); }; //expected-note{{not literal}} - auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}} + auto L = [](NonLit NL) constexpr { }; //expected-error{{non-literal parameter type}} } // end ns1 namespace ns2 { diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp new file mode 100644 index 00000000000000..69562ebfeaf736 --- /dev/null +++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wpre-c++23-compat %s + +// This test covers modifications made by P2448R2 in C++23 mode. + +// Check that there is no error when a constexpr function that never produces a +// constant expression, but still an error if such function is called from +// constexpr context. +constexpr int F(int N) { + // expected-warning@-1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} + double D = 2.0 / 0.0; // expected-note 2{{division by zero}} + return 1; +} + +// No warning here since the function can produce a constant expression. +constexpr int F0(int N) { + if (N == 0) + double d2 = 2.0 / 0.0; // expected-note {{division by zero}} + return 1; +} + +template <typename T> +constexpr int FT(T N) { + double D = 2.0 / 0.0; // expected-note {{division by zero}} + return 1; +} + +class NonLiteral { +// expected-note@-1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} +public: + NonLiteral() {} // expected-note 2{{declared here}} + ~NonLiteral() {} +}; + +constexpr NonLiteral F1() { +// expected-warning@-1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}} +// expected-warning@-2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} + return NonLiteral{}; +// expected-note@-1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}} +} + +constexpr int F2(NonLiteral N) { + // expected-warning@-1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}} + return 8; +} + +class Derived : public NonLiteral { // expected-note {{declared here}} + constexpr ~Derived() {}; + // expected-warning@-1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}} + +}; + +class Derived1 : public NonLiteral { + constexpr Derived1() : NonLiteral () {} + // expected-warning@-1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}} +}; + + +struct X { // expected-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + X(); // expected-note 3{{declared here}} + X(const X&); // expected-note 2{{declared here}} + X(X&&); + X& operator=(X&); + X& operator=(X&& other); + bool operator==(X const&) const; // expected-note 2{{non-constexpr comparison function declared here}} +}; + +template <typename T> +struct Wrapper { + constexpr Wrapper() = default; + constexpr Wrapper(Wrapper const&) = default; + constexpr Wrapper(T const& t) : t(t) { } + constexpr Wrapper(Wrapper &&) = default; + constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} + constexpr bool operator==(Wrapper const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}} +private: + T t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}} +}; + +struct WrapperNonT { + constexpr WrapperNonT() = default; // expected-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-1 {{declared here}} + constexpr WrapperNonT(WrapperNonT const&) = default; // expected-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + constexpr WrapperNonT(X const& t) : t(t) { } // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr WrapperNonT(WrapperNonT &&) = default; // expected-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + constexpr WrapperNonT& operator=(WrapperNonT &) = default; // expected-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // expected-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} + // expected-warning@-1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-2 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr bool operator==(WrapperNonT const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}} +private: + X t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}} +}; + +struct NonDefaultMembers { + constexpr NonDefaultMembers() {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + // expected-note@-2 {{non-literal type 'X' cannot be used in a constant expression}} + constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;} + constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;} + constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;} + X t; +}; + +static int Glob = 0; // expected-note {{declared here}} +class C1 { +public: + constexpr C1() : D(Glob) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // expected-note@-1 {{read of non-const variable 'Glob' is not allowed in a constant expression}} +private: + int D; +}; + +void test() { + + constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}} + // expected-note@-1 {{in call}} + F(3); + constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}} + // expected-note@-1 {{in call}} + F0(0); + constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}} + F1(); + NonLiteral L; + constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}} + // expected-note@-1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}} + + constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}} + // expected-note@-1 {{in call}} + F2(L); + + Wrapper<X> x; // expected-note {{requested here}} + WrapperNonT x1; + NonDefaultMembers x2; + + // TODO produces note with an invalid source location + // static_assert((Wrapper<X>(), true)); + + static_assert((WrapperNonT(), true)); // expected-error{{expression is not an integral constant expression}}\ + // expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}} + static_assert((NonDefaultMembers(), true)); // expected-error{{expression is not an integral constant expression}} \ + // expected-note {{in call to}} + constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \ + // expected-note{{non-literal}} + +} diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index d8482ec53f0ed4..0a3eb29675844b 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -54,7 +54,7 @@ struct C { struct D { C c; - consteval D() = default; // expected-error {{cannot be consteval}} + consteval D() = default; // expected-error {{marked consteval but never produces a constant expression}} consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}} }; @@ -884,7 +884,7 @@ void func() { S<Baz, 3> s7; } -consteval int aConstevalFunction() { // expected-error {{consteval function never produces a constant expression}} +consteval int aConstevalFunction() { // expected-error {{consteval function that never produces a constant expression}} // Defaulted default constructors are implicitly consteval. S<Bar, 1> s1; diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index eac9c587869f55..90856b59e999cd 100644 --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23,cxx20 %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23,cxx20 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING @@ -299,8 +299,8 @@ namespace Constexpr { constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y<int>().f()'}} } struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}} - // cxx20_23-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}} - constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}} + // cxx20-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}} + constexpr auto f2(int n) { return nl; } // cxx14_20-error {{with non-literal return type 'struct NonLiteral' is a C++23 extension}} } // It's not really clear whether these are valid, but this matches g++. diff --git a/clang/test/SemaCXX/ms-constexpr-invalid.cpp b/clang/test/SemaCXX/ms-constexpr-invalid.cpp index e5bec0c7119b02..94a4d62515ee87 100644 --- a/clang/test/SemaCXX/ms-constexpr-invalid.cpp +++ b/clang/test/SemaCXX/ms-constexpr-invalid.cpp @@ -5,7 +5,7 @@ void runtime() {} // expected-note {{declared here}} -[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function never produces a constant expression}} \ +[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function that 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 {{attribute 'msvc::constexpr' cannot be applied to the constexpr function 'f1'}} #if __cplusplus >= 202202L @@ -31,13 +31,13 @@ static_assert(f5()); // expected-error {{static assertion expression is not an i int f6(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f6(x / 2) : 0; } // expected-note {{declared here}} \ // expected-note {{declared here}} -constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function never produces a constant expression}} \ +constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function that never produces a constant expression}} \ // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} \ // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} static_assert(f7()); // expected-error {{static assertion expression is not an integral constant expression}} \ // expected-note {{in call to 'f7()'}} -constexpr bool f8() { // expected-error {{constexpr function never produces a constant expression}} +constexpr bool f8() { // expected-error {{constexpr function that never produces a constant expression}} [[msvc::constexpr]] f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} \ // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \ // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} diff --git a/clang/test/SemaCXX/ms-constexpr.cpp b/clang/test/SemaCXX/ms-constexpr.cpp index 79f71a34cb7d84..6bf2dec91250c9 100644 --- a/clang/test/SemaCXX/ms-constexpr.cpp +++ b/clang/test/SemaCXX/ms-constexpr.cpp @@ -29,7 +29,7 @@ static_assert(test_get_msconstexpr_true()); struct S2 { [[msvc::constexpr]] S2() {} [[msvc::constexpr]] bool value() { return true; } - static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function never produces a constant expression}} \ + static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function that never produces a constant expression}} \ // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} \ // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} }; diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp index 368a3eeb6955bd..1300f9960ca751 100644 --- a/clang/test/SemaCXX/sizeless-1.cpp +++ b/clang/test/SemaCXX/sizeless-1.cpp @@ -303,7 +303,7 @@ struct constructible_from_sizeless { void with_default(svint8_t = svint8_t()); #if __cplusplus >= 201103L -constexpr int ce_taking_int8(svint8_t) { return 1; } // expected-error {{constexpr function's 1st parameter type 'svint8_t' (aka '__SVInt8_t') is not a literal type}} +constexpr int ce_taking_int8(svint8_t) { return 1; } // expected-error {{constexpr function with 1st non-literal parameter type 'svint8_t' (aka '__SVInt8_t') is a C++23 extension}} #endif #if __cplusplus < 201703L diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp index 1b97484767b1a5..23102b8ab88725 100644 --- a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp +++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp @@ -54,5 +54,5 @@ struct Z { struct W { int w; - constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}} + constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}} }; diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 197726f3aa3eee..0bec14c62765b7 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -356,14 +356,7 @@ <h2 id="cxx23">C++23 implementation status</h2> <tr> <td>Relaxing some constexpr restrictions</td> <td><a href="https://wg21.link/P2448R2">P2448R2</a></td> - <td class="partial" align="center"> - <details><summary>Clang 17 (Partial)</summary> - We do not support outside of defaulted special memeber functions the change that constexpr functions no - longer have to be constexpr compatible but rather support a less restricted requirements for constexpr - functions. Which include allowing non-literal types as return values and parameters, allow calling of - non-constexpr functions and constructors. - </details></td> - </td> + <td class="full" align="center">Clang 18</td> </tr> <tr> <td>Using unknown pointers and references in constant expressions</td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits