From 699f47bba02012523e1862f9b15ce9de1d7511b5 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 18 Oct 2023 02:47:33 -0700 Subject: [PATCH 01/13] [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 a18d36a16b1a9..23342a6a7256d 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 `_. + C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a79892e40030..67409374f26df 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, 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, 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, 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, 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, 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, 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, DefaultIgnore; def ext_constexpr_function_never_constant_expr : ExtWarn< - "%select{constexpr|consteval}1 %select{function|constructor}0 never produces a " - "constant expression">, InGroup>, DefaultError; + "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a " + "constant expression is a C++23 extension">, InGroup>, 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, 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, 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, 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; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 36e53c684ac4d..aa49dc73e157b 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(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(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(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 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(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 bd1cf186d519c..6ef7df9662e6a 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 61825bc11438f..ab09280e883fb 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 cf71e7145c274..f8fa1b5d095da 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 a543f248e5371..19e099d5077de 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 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 struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} constexpr DerivedFromNonTrivDtor(); }; -constexpr int f(DerivedFromNonTrivDtor) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor' is not a literal type}} +constexpr int f(DerivedFromNonTrivDtor) { return 0; } // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromNonTrivDtor' 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 struct CtorArg { constexpr CtorArg(T); @@ -97,7 +97,7 @@ struct Derived : HasVBase { template struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} constexpr DerivedFromVBase(); }; -constexpr int f(DerivedFromVBase) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase' is not a literal type}} +constexpr int f(DerivedFromVBase) {} // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromVBase' is a C++23 extension}} template constexpr DerivedFromVBase::DerivedFromVBase() : T() {} constexpr int nVBase = (DerivedFromVBase(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase' with virtual base class in a constant expression}} @@ -105,12 +105,12 @@ constexpr int nVBase = (DerivedFromVBase(), 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) { return 0; } -constexpr int f(MemberType) { return 0; } // expected-error {{not a literal type}} +constexpr int f(MemberType) { 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 7ad2e582a8126..1a3da8bdc252a 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 c07502c0555b5..e8c71b44edd62 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 6214ff8006d67..d57c098faff6d 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 f1f677ebfcd34..71c8d09d3041d 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); // - 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 18b2c6b1d6d15..7c06e5a9f928a 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 00ef78426289f..850420ca8ae1c 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 g3() { return {}; } // ok - constexpr T3 g4() { return {}; } // expected-error {{not a literal type}} + constexpr T3 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 5b525fc91aba1..9c9034c7f908b 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 359c04b3e0f3d..be656c4468eae 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 d262f6f9dcab7..4bce1de0ab514 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 3f074c4d57354..1cf7bb840507f 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 78604d480aa1c..17e32dcc51ac9 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 e3cd057baba75..868dacd4415a3 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 de2afa71b4266..3624b1e5a3e3d 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(a); //cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}} + (void)static_cast(a); (void)static_cast(a); (void)static_cast(a); diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp index 16c8a4029cbac..2f6173be74a2a 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 b315b477dbf1c..22cc53e9152cd 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 59ff09ac72e42..e83d931ee4026 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 -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 9e2ae07cbe4c9..a29659301dfd6 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(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 273d7ff3a208e..c829bcc1fc94d 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(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} + return *reinterpret_cast(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 2ee1d48d1cd69..e92a64d830881 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 90ee7892b2fc2..dd0b911fc516b 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 6a1f48bf7958f..46c24cc3e5d0b 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 0000000000000..69562ebfeaf73 --- /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 +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 +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; // expected-note {{requested here}} + WrapperNonT x1; + NonDefaultMembers x2; + + // TODO produces note with an invalid source location + // static_assert((Wrapper(), 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 d8482ec53f0ed..0a3eb29675844 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 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 s1; diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index eac9c587869f5..90856b59e999c 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().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y().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 e5bec0c7119b0..94a4d62515ee8 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 79f71a34cb7d8..6bf2dec91250c 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 368a3eeb6955b..1300f9960ca75 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 1b97484767b1a..23102b8ab8872 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 197726f3aa3ee..0bec14c62765b 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -356,14 +356,7 @@

C++23 implementation status

Relaxing some constexpr restrictions P2448R2 - -
Clang 17 (Partial) - 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. -
- + Clang 18 Using unknown pointers and references in constant expressions From 8527b69506cc08bf45d20ad86e891b4b5b3663ea Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 17 Jan 2024 03:59:28 -0800 Subject: [PATCH 02/13] Make sure feature is actually backported --- clang/docs/LanguageExtensions.rst | 1 + clang/docs/ReleaseNotes.rst | 3 +- clang/lib/Sema/SemaDeclCXX.cpp | 3 +- clang/test/CXX/drs/dr13xx.cpp | 9 -- .../test/SemaCXX/cxx23-invalid-constexpr.cpp | 116 ++++++++++-------- 5 files changed, 69 insertions(+), 63 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index c1420079f7511..eb83faebfebba 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1486,6 +1486,7 @@ Conditional ``explicit`` __cpp_conditional_explicit C++20 ``if consteval`` __cpp_if_consteval C++23 C++20 ``static operator()`` __cpp_static_call_operator C++23 C++03 Attributes on Lambda-Expressions C++23 C++11 +Relaxing some constexpr restrictions __cpp_constexpr C++23 C++11 -------------------------------------- -------------------------------- ------------- ------------- Designated initializers (N494) C99 C89 Array & element qualification (N2607) C23 C89 diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 23342a6a7256d..ba005ccbc471e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -165,7 +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 `_. +- Implemented `P2448R2: Relaxing some constexpr restrictions `_ + as a conforming extension. C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index aa49dc73e157b..f4affcd262b23 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7873,6 +7873,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, << CSM; for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); + HadError = true; } else { Diag(MD->getBeginLoc(), getLangOpts().CPlusPlus23 @@ -7881,8 +7882,6 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, << CSM << MD->isConsteval(); } // FIXME: Explain why the special member can't be constexpr. - if (!getLangOpts().CPlusPlus23) - HadError = true; } if (First) { diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index be656c4468eae..f025eff3a48c2 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -433,18 +433,9 @@ namespace dr1359 { // dr1359: 3.5 constexpr A a = A(); constexpr B b = B(); - // cxx11-17-error@-1 {{no matching constructor for initialization of 'B'}} - // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr C c = C(); - // cxx11-17-error@-1 {{no matching constructor for initialization of 'C'}} - // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr X x = X(); constexpr Y y = Y(); - // cxx11-17-error@-1 {{no matching constructor for initialization of 'Y'}} - // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} #endif } diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp index 69562ebfeaf73..355495689ccd8 100644 --- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp +++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp @@ -1,13 +1,18 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wpre-c++23-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++20 -Wno-c++23-extensions -Wno-invalid-constexpr %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++17 -Wno-c++23-extensions -Wno-invalid-constexpr %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++14 -Wno-c++23-extensions -Wno-invalid-constexpr %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20,cxx11 -std=c++11 -Wno-c++14-extensions -Wno-c++23-extensions -Wno-invalid-constexpr -Wno-constexpr-not-const %s -// This test covers modifications made by P2448R2 in C++23 mode. +// This test covers modifications made by P2448R2. // 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}} + // cxx23-warning@-1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} + double D = 2.0 / 0.0; // cxx23-note {{division by zero}} \ + // expected-note {{division by zero}} return 1; } @@ -25,44 +30,44 @@ constexpr int FT(T N) { } 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}} +// cxx23-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() {} // cxx23-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}} +// cxx23-warning@-1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}} +// cxx23-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}} +// cxx23-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}} + // cxx23-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 Derived : public NonLiteral { // cxx23-note {{declared here}} + constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}} + // cxx23-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}} + // cxx23-warning@-1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-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}} +struct X { // cxx23-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + X(); // cxx23-note 3{{declared here}} + X(const X&); // cxx23-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}} + X& operator=(X&); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}} + X& operator=(X&& other); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}} + bool operator==(X const&) const; // cxx23-note 2{{non-constexpr comparison function declared here}} }; template @@ -71,48 +76,56 @@ struct Wrapper { 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}} + constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} + constexpr bool operator==(Wrapper const&) const = default; // cxx23-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}} + // precxx20-warning@-1 2{{defaulted comparison operators are a C++20 extension}} private: - T t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}} + T t; // cxx23-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}} + constexpr WrapperNonT() = default; // cxx23-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}} + constexpr WrapperNonT(WrapperNonT const&) = default; // cxx23-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) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr WrapperNonT(WrapperNonT &&) = default; // cxx23-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; // cxx23-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx11-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} + constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx23-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx11-error@-1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} + constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} + // cxx23-warning@-1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-note@-2 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr bool operator==(WrapperNonT const&) const = default; // cxx23-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}} + // precxx20-warning@-1 {{defaulted comparison operators are a C++20 extension}} private: - X t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}} + X t; // cxx23-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}} + constexpr NonDefaultMembers() {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-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(NonDefaultMembers const&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;} + // cxx11-error@-1 {{no viable overloaded '='}} + // cxx11-error@-2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}} constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;} + // cxx11-error@-1 {{no viable overloaded '='}} + // cxx11-error@-2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}} constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;} X t; }; -static int Glob = 0; // expected-note {{declared here}} +static int Glob = 0; // cxx23-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}} + constexpr C1() : D(Glob) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} + // cxx23-note@-1 {{read of non-const variable 'Glob' is not allowed in a constant expression}} private: int D; }; @@ -125,26 +138,27 @@ void test() { 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'}} + constexpr auto C = F1(); // cxx23-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 D = F2(L); // cxx23-error {{constexpr variable 'D' must be initialized by a constant expression}} + // cxx23-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; // expected-note {{requested here}} + Wrapper x; // cxx23-note {{requested here}} + // precxx20-note@-1 {{requested here}} WrapperNonT x1; NonDefaultMembers x2; // TODO produces note with an invalid source location // static_assert((Wrapper(), true)); - static_assert((WrapperNonT(), true)); // expected-error{{expression is not an integral constant expression}}\ + 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}} \ + 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}} From 8ca1f210d51c584783948c2d0ea708ba7bf8796e Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 17 Jan 2024 04:14:27 -0800 Subject: [PATCH 03/13] Minor changes applied --- clang/lib/Sema/SemaDeclCXX.cpp | 20 +++++--------------- clang/test/CXX/drs/dr13xx.cpp | 4 ++-- clang/test/CXX/drs/dr16xx.cpp | 2 +- clang/test/CXX/drs/dr6xx.cpp | 2 +- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index f4affcd262b23..a9c1bcf5db726 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1731,11 +1731,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; } - - if (SemaRef.getLangOpts().CPlusPlus23) - return true; - - return false; + return !!SemaRef.getLangOpts().CPlusPlus23; }; const CXXRecordDecl *RD = DD->getParent(); @@ -1767,11 +1763,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, ? diag::warn_cxx23_compat_constexpr_non_literal_param : diag::ext_constexpr_non_literal_param, ArgIndex + 1, PD->getSourceRange(), isa(FD), - FD->isConsteval())) { - if (SemaRef.getLangOpts().CPlusPlus23) - return true; - return false; - } + FD->isConsteval())) + return SemaRef.getLangOpts().CPlusPlus23; } return true; } @@ -1785,11 +1778,8 @@ static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD, 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; - } + FD->isConsteval())) + return SemaRef.getLangOpts().CPlusPlus23; return true; } diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index f025eff3a48c2..f2457194e8d44 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -411,10 +411,10 @@ namespace dr1358 { // dr1358: 3.1 int member; constexpr B(NonLit u) : member(u) {} // 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}} + // 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(); } // 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}} + // 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 } diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 1cf7bb840507f..c00e1f483c123 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -350,7 +350,7 @@ namespace dr1684 { // dr1684: 3.6 constexpr int f(NonLiteral &) { return 0; } constexpr int f(NonLiteral) { return 0; } // 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}} + // 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 17e32dcc51ac9..7d4ab70a32adb 100644 --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -585,7 +585,7 @@ namespace dr647 { // dr647: 3.1 constexpr C(NonLiteral); constexpr C(NonLiteral, int) {} // 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}} + // 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}} From b365e48a36550d68dda83515b790e3beaf6d7893 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 17 Jan 2024 04:21:12 -0800 Subject: [PATCH 04/13] Clang 18 is unreleased --- clang/www/cxx_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 0bec14c62765b..b60d032985476 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -356,7 +356,7 @@

C++23 implementation status

Relaxing some constexpr restrictions P2448R2 - Clang 18 + Clang 18 Using unknown pointers and references in constant expressions From 1a35417ff41c818bc721fa0aaa944d2eca708849 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 17 Jan 2024 04:55:43 -0800 Subject: [PATCH 05/13] Make format happy --- clang/lib/Sema/SemaDeclCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6fadca805b35a..5adc825c03f06 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7871,7 +7871,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, : diag::ext_incorrect_defaulted_constexpr) << CSM << MD->isConsteval(); } - // FIXME: Explain why the special member can't be constexpr. + // FIXME: Explain why the special member can't be constexpr. } if (First) { From 0a0253fb66a74503b5f91962accdc0c7cdbe7a9a Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Thu, 18 Jan 2024 06:35:08 -0800 Subject: [PATCH 06/13] Fix diagnostic concern --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index af92472bf9e6a..0be20d4636964 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2769,7 +2769,7 @@ 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">, InGroup, DefaultError; -def warn_cxx23_compat_constexpr_dtor_subobject : ExtWarn< +def warn_cxx23_compat_constexpr_dtor_subobject : Warning< "%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, DefaultIgnore; From 28a3fcd825a1c761c7c62774431997c6b9a57293 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Tue, 23 Jan 2024 08:51:13 -0800 Subject: [PATCH 07/13] Make defaulted special members actually constexpr --- .../clang/Basic/DiagnosticSemaKinds.td | 3 - clang/lib/AST/DeclCXX.cpp | 11 ++-- clang/lib/Sema/SemaDeclCXX.cpp | 61 ++++++++++--------- clang/test/CXX/drs/dr15xx.cpp | 21 ++++--- clang/test/CXX/drs/dr16xx.cpp | 8 +-- .../SemaCXX/constant-expression-cxx11.cpp | 11 ++-- .../test/SemaCXX/cxx23-invalid-constexpr.cpp | 22 +++---- 7 files changed, 70 insertions(+), 67 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0be20d4636964..a0e203a9bccd6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9565,9 +9565,6 @@ def err_defaulted_copy_assign_not_ref : Error< 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, 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, 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 warn_defaulted_method_deleted : Warning< diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 117e802dae2d9..1da9fa4bbb4eb 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -400,10 +400,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // C++11 [class.ctor]p6: // If that user-written default constructor would satisfy the - // requirements of a constexpr constructor, the implicitly-defined + // requirements of a constexpr constructor/function(C++23), the implicitly-defined // default constructor is constexpr. if (!BaseClassDecl->hasConstexprDefaultConstructor()) - data().DefaultedDefaultConstructorIsConstexpr = false; + data().DefaultedDefaultConstructorIsConstexpr = + C.getLangOpts().CPlusPlus23; // C++1z [class.copy]p8: // The implicitly-declared copy constructor for a class X will have @@ -548,7 +549,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // -- for every subobject of class type or (possibly multi-dimensional) // array thereof, that class type shall have a constexpr destructor if (!Subobj->hasConstexprDestructor()) - data().DefaultedDestructorIsConstexpr = false; + data().DefaultedDestructorIsConstexpr = + getASTContext().getLangOpts().CPlusPlus23; // C++20 [temp.param]p7: // A structural type is [...] a literal class type [for which] the types @@ -1297,7 +1299,8 @@ void CXXRecordDecl::addedMember(Decl *D) { !FieldRec->hasConstexprDefaultConstructor() && !isUnion()) // The standard requires any in-class initializer to be a constant // expression. We consider this to be a defect. - data().DefaultedDefaultConstructorIsConstexpr = false; + data().DefaultedDefaultConstructorIsConstexpr = + Context.getLangOpts().CPlusPlus23; // C++11 [class.copy]p8: // The implicitly-declared copy constructor for a class X will have diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 14712ae34cae4..85cf291519c0e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1873,8 +1873,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, if (auto *Dtor = dyn_cast(NewFD)) { // A destructor can be constexpr only if the defaulted destructor could be; // we don't need to check the members and bases if we already know they all - // have constexpr destructors. - if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) { + // have constexpr destructors. (removed in C++23) + if (!getLangOpts().CPlusPlus23 && + !Dtor->getParent()->defaultedDestructorIsConstexpr()) { if (Kind == CheckConstexprKind::CheckValid) return false; if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind)) @@ -7535,21 +7536,23 @@ static bool defaultedSpecialMemberIsConstexpr( // C++1y [class.copy]p26: // -- [the class] is a literal type, and - if (!Ctor && !ClassDecl->isLiteral()) + if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23) return false; // -- every constructor involved in initializing [...] base class // sub-objects shall be a constexpr constructor; // -- the assignment operator selected to copy/move each direct base // class is a constexpr function, and - for (const auto &B : ClassDecl->bases()) { - const RecordType *BaseType = B.getType()->getAs(); - if (!BaseType) - continue; - CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); - if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, - InheritedCtor, Inherited)) - return false; + if (!S.getLangOpts().CPlusPlus23) { + for (const auto &B : ClassDecl->bases()) { + const RecordType *BaseType = B.getType()->getAs(); + if (!BaseType) + continue; + CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, + InheritedCtor, Inherited)) + return false; + } } // -- every constructor involved in initializing non-static data members @@ -7559,20 +7562,22 @@ static bool defaultedSpecialMemberIsConstexpr( // -- for each non-static data member of X that is of class type (or array // thereof), the assignment operator selected to copy/move that member is // a constexpr function - for (const auto *F : ClassDecl->fields()) { - if (F->isInvalidDecl()) - continue; - if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) - continue; - QualType BaseType = S.Context.getBaseElementType(F->getType()); - if (const RecordType *RecordTy = BaseType->getAs()) { - CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); - if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, - BaseType.getCVRQualifiers(), - ConstArg && !F->isMutable())) + if (!S.getLangOpts().CPlusPlus23) { + for (const auto *F : ClassDecl->fields()) { + if (F->isInvalidDecl()) + continue; + if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) + continue; + QualType BaseType = S.Context.getBaseElementType(F->getType()); + if (const RecordType *RecordTy = BaseType->getAs()) { + CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); + if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, + BaseType.getCVRQualifiers(), + ConstArg && !F->isMutable())) + return false; + } else if (CSM == Sema::CXXDefaultConstructor) { return false; - } else if (CSM == Sema::CXXDefaultConstructor) { - return false; + } } } @@ -7864,10 +7869,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); HadError = true; } else { - Diag(MD->getBeginLoc(), - getLangOpts().CPlusPlus23 - ? diag::warn_cxx23_compat_incorrect_defaulted_constexpr - : diag::ext_incorrect_defaulted_constexpr) + Diag(MD->getBeginLoc(), diag::ext_incorrect_defaulted_constexpr) << CSM << MD->isConsteval(); } // FIXME: Explain why the special member can't be constexpr. @@ -9121,7 +9123,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // declaration, it is implicitly considered to be constexpr. // FIXME: Only applying this to the first declaration seems problematic, as // simple reorderings can affect the meaning of the program. - if (First && !FD->isConstexpr() && Info.Constexpr) + if ((First && !FD->isConstexpr() && Info.Constexpr) || + getLangOpts().CPlusPlus23) FD->setConstexprKind(ConstexprSpecKind::Constexpr); // C++2a [except.spec]p3: diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 3d4050a5713f9..c79e1b9fdafe0 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr1512 { // dr1512: 4 void f(char *p) { @@ -368,7 +368,7 @@ namespace dr1573 { // dr1573: 3.9 B b(1, 'x', 4.0, "hello"); // ok // inherited constructor is effectively constexpr if the user-written constructor would be - struct C { C(); constexpr C(int) {} }; + struct C { C(); constexpr C(int) {} }; // #dr1573-C struct D : C { using C::C; }; constexpr D d = D(0); // ok struct E : C { using C::C; A a; }; // #dr1573-E @@ -381,8 +381,11 @@ namespace dr1573 { // dr1573: 3.9 struct F : C { using C::C; C c; }; // #dr1573-F constexpr F f = F(0); // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}} - // since-cxx11-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} - // since-cxx11-note@#dr1573-F {{declared here}} + // cxx11-20-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} + // since-cxx23-note@-3 {{in implicit initialization for inherited constructor of 'F'}} + // since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}} + // cxx11-20-note@#dr1573-F {{declared here}} + // since-cxx23-note@#dr1573-C {{declared here}} // inherited constructor is effectively deleted if the user-written constructor would be struct G { G(int); }; diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 3f4f75df5b25d..1dfe092d7b288 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -3,8 +3,8 @@ // 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 +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,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-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) @@ -255,12 +255,12 @@ namespace dr1658 { // dr1658: 5 struct A { A(A&); }; struct B : virtual A { virtual void f() = 0; }; struct C : virtual A { virtual void f(); }; - struct D : A { virtual void f() = 0; }; + struct D : A { virtual void f() = 0; }; // since-cxx23-note {{previous declaration is here}} struct X { friend B::B(const B&) throw(); friend C::C(C&); - friend D::D(D&); + friend D::D(D&); // since-cxx23-error {{non-constexpr declaration of 'D' follows constexpr declaration}} }; } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index a29659301dfd6..43e9434dee455 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1678,7 +1678,7 @@ namespace ImplicitConstexpr { struct R { constexpr R() noexcept; constexpr R(const R&) noexcept; constexpr R(R&&) noexcept; ~R() noexcept; }; struct S { R r; }; // expected-note 3{{here}} struct T { T(const T&) noexcept; T(T &&) noexcept; ~T() noexcept; }; - struct U { T t; }; // expected-note 3{{here}} + struct U { T t; }; // cxx11_20-note 3{{here}} static_assert(!__is_literal_type(Q), ""); static_assert(!__is_literal_type(R), ""); static_assert(!__is_literal_type(S), ""); @@ -1691,9 +1691,9 @@ namespace ImplicitConstexpr { friend S::S() noexcept; // expected-error {{follows constexpr}} friend S::S(S&&) noexcept; // expected-error {{follows constexpr}} friend S::S(const S&) noexcept; // expected-error {{follows constexpr}} - friend constexpr U::U() noexcept; // expected-error {{follows non-constexpr}} - friend constexpr U::U(U&&) noexcept; // expected-error {{follows non-constexpr}} - friend constexpr U::U(const U&) noexcept; // expected-error {{follows non-constexpr}} + friend constexpr U::U() noexcept; // cxx11_20-error {{follows non-constexpr}} + friend constexpr U::U(U&&) noexcept; // cxx11_20-error {{follows non-constexpr}} + friend constexpr U::U(const U&) noexcept; // cxx11_20-error {{follows non-constexpr}} }; } @@ -2277,7 +2277,8 @@ namespace InheritedCtor { struct A { constexpr A(int) {} }; struct B : A { int n; using A::A; }; // expected-note {{here}} - constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}} + constexpr B b(0); // expected-error {{constant expression}} cxx11_20-note {{derived class}}\ + // cxx23-note {{not initialized}} struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}} constexpr C c(0); diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp index 355495689ccd8..da22d11a5dcbf 100644 --- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp +++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp @@ -48,10 +48,8 @@ constexpr int F2(NonLiteral N) { return 8; } -class Derived : public NonLiteral { // cxx23-note {{declared here}} +class Derived : public NonLiteral { constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}} - // cxx23-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 { @@ -84,15 +82,14 @@ struct Wrapper { }; struct WrapperNonT { - constexpr WrapperNonT() = default; // cxx23-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; // cxx23-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() = default; + constexpr WrapperNonT(WrapperNonT const&) = default; constexpr WrapperNonT(X const& t) : t(t) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} - constexpr WrapperNonT(WrapperNonT &&) = default; // cxx23-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; // cxx23-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(WrapperNonT &&) = default; + constexpr WrapperNonT& operator=(WrapperNonT &) = default; // cxx11-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} - constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx23-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 WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx11-error@-1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} // cxx23-warning@-1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} @@ -153,11 +150,10 @@ void test() { WrapperNonT x1; NonDefaultMembers x2; - // TODO produces note with an invalid source location + // TODO these produce notes with an invalid source location. // static_assert((Wrapper(), 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((WrapperNonT(), true),""); + 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}} \ From 26fdf352330e173543a973a38882dbd59332c9d9 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 24 Jan 2024 01:02:22 -0800 Subject: [PATCH 08/13] Fix test after merge --- clang/test/SemaCXX/deduced-return-type-cxx14.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index 8aa6f6bb05f3a..367dfc85e229d 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,since-cxx20,since-cxx14,cxx20_23,cxx23 %s // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING From 96a8f7f2f37b22cd63102b1134cceccc2cc9a734 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 24 Jan 2024 08:39:02 -0800 Subject: [PATCH 09/13] Format --- clang/lib/AST/DeclCXX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1da9fa4bbb4eb..63acd10d34b9e 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -400,8 +400,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // C++11 [class.ctor]p6: // If that user-written default constructor would satisfy the - // requirements of a constexpr constructor/function(C++23), the implicitly-defined - // default constructor is constexpr. + // requirements of a constexpr constructor/function(C++23), the + // implicitly-defined default constructor is constexpr. if (!BaseClassDecl->hasConstexprDefaultConstructor()) data().DefaultedDefaultConstructorIsConstexpr = C.getLangOpts().CPlusPlus23; From 1ed37bf0d0c060d390b81f77bf31eba5cc6dc685 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Tue, 5 Mar 2024 05:45:05 -0800 Subject: [PATCH 10/13] Fix test --- clang/test/AST/Interp/cxx17.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/AST/Interp/cxx17.cpp b/clang/test/AST/Interp/cxx17.cpp index 5e38d1a588700..b063a9e71828c 100644 --- a/clang/test/AST/Interp/cxx17.cpp +++ b/clang/test/AST/Interp/cxx17.cpp @@ -83,7 +83,7 @@ static_assert(b() == 11); /// The diagnostics between the two interpreters used to be different here. struct S { int a; }; -constexpr S getS() { // both-error {{constexpr function never produces a constant expression}} +constexpr S getS() { // both-error {{constexpr function that never produces a constant expression}} (void)(1/0); // both-note 2{{division by zero}} \ // both-warning {{division by zero}} return S{12}; From 5b8e47672c8ddbbcbfcfacb245c4db16aab273ba Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Tue, 5 Mar 2024 07:11:30 -0800 Subject: [PATCH 11/13] Roll back to C++23 only implementation --- clang/docs/LanguageExtensions.rst | 1 - clang/docs/ReleaseNotes.rst | 3 +- .../clang/Basic/DiagnosticSemaKinds.td | 26 +++++++-------- clang/lib/Sema/SemaDeclCXX.cpp | 21 ++++++------ .../test/SemaCXX/cxx23-invalid-constexpr.cpp | 32 ++++++++++++++++--- 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 898c2cb4bb721..bcd69198eafdb 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1487,7 +1487,6 @@ Conditional ``explicit`` __cpp_conditional_explicit C++20 ``if consteval`` __cpp_if_consteval C++23 C++20 ``static operator()`` __cpp_static_call_operator C++23 C++03 Attributes on Lambda-Expressions C++23 C++11 -Relaxing some constexpr restrictions __cpp_constexpr C++23 C++11 -------------------------------------- -------------------------------- ------------- ------------- Designated initializers (N494) C99 C89 Array & element qualification (N2607) C23 C89 diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 28b9159c91127..58348eaa8a4cb 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -92,8 +92,7 @@ C++23 Feature Support - Implemented `P2718R0: Lifetime extension in range-based for loops `_. Also materialize temporary object which is a prvalue in discarded-value expression. -- Implemented `P2448R2: Relaxing some constexpr restrictions `_ - as a conforming extension. +- Implemented `P2448R2: Relaxing some constexpr restrictions `_. C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c50d0d7aae961..8cd89df2b4f7d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2773,11 +2773,11 @@ 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 ext_constexpr_dtor_subobject : ExtWarn< +def err_constexpr_dtor_subobject : Error< "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">, InGroup, DefaultError; -def warn_cxx23_compat_constexpr_dtor_subobject : Warning< + "constexpr destructor">; +def warn_cxx20_compat_constexpr_dtor_subobject : Warning< "%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, DefaultIgnore; @@ -2812,13 +2812,13 @@ 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 ext_constexpr_non_literal_return : ExtWarn< - "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">, InGroup, DefaultError; -def warn_cxx23_compat_constexpr_non_literal_return : Warning< +def err_constexpr_non_literal_return : Error< + "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">; +def warn_cxx20_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, 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, DefaultError; -def warn_cxx23_compat_constexpr_non_literal_param : Warning< +def err_constexpr_non_literal_param : Error< + "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">; +def warn_cxx20_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, DefaultIgnore; def err_constexpr_body_invalid_stmt : Error< "statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">; @@ -2882,7 +2882,7 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning< def ext_constexpr_function_never_constant_expr : ExtWarn< "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a " "constant expression is a C++23 extension">, InGroup>, DefaultError; -def warn_cxx23_compat_constexpr_function_never_constant_expr : Warning< +def warn_cxx20_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, DefaultIgnore; def err_attr_cond_never_constant_expr : Error< @@ -9600,9 +9600,9 @@ 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 ext_incorrect_defaulted_constexpr : ExtWarn< +def err_incorrect_defaulted_constexpr : Error< "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, DefaultError; + "but never produces a constant expression is a C++23 extension">; 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 warn_defaulted_method_deleted : Warning< @@ -9722,7 +9722,7 @@ def ext_defaulted_comparison_constexpr_mismatch : Extension< "%select{|for which the corresponding implicit 'operator==' }0 " "invokes a non-constexpr comparison function is a C++23 extension">, InGroup>; -def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning< +def warn_cxx20_compat_defaulted_comparison_constexpr_mismatch : Warning< "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" "three-way comparison operator}0 that is " "declared %select{constexpr|consteval}2 but" diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ae953085a21b4..78c94bce1f3d6 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1724,8 +1724,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.Diag(DD->getLocation(), SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx23_compat_constexpr_dtor_subobject - : diag::ext_constexpr_dtor_subobject) + ? diag::warn_cxx20_compat_constexpr_dtor_subobject + : diag::err_constexpr_dtor_subobject) << static_cast(DD->getConstexprKind()) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject) @@ -1760,8 +1760,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, if (CheckLiteralType( SemaRef, Kind, ParamLoc, *i, SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx23_compat_constexpr_non_literal_param - : diag::ext_constexpr_non_literal_param, + ? diag::warn_cxx20_compat_constexpr_non_literal_param + : diag::err_constexpr_non_literal_param, ArgIndex + 1, PD->getSourceRange(), isa(FD), FD->isConsteval())) return SemaRef.getLangOpts().CPlusPlus23; @@ -1776,8 +1776,8 @@ static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD, 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, + ? diag::warn_cxx20_compat_constexpr_non_literal_return + : diag::err_constexpr_non_literal_return, FD->isConsteval())) return SemaRef.getLangOpts().CPlusPlus23; return true; @@ -2471,7 +2471,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, SemaRef.Diag( Dcl->getLocation(), SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx23_compat_constexpr_function_never_constant_expr + ? diag::warn_cxx20_compat_constexpr_function_never_constant_expr : diag::ext_constexpr_function_never_constant_expr) << isa(Dcl) << Dcl->isConsteval() << Dcl->getNameInfo().getSourceRange(); @@ -7881,7 +7881,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); HadError = true; } else { - Diag(MD->getBeginLoc(), diag::ext_incorrect_defaulted_constexpr) + Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM << MD->isConsteval(); } // FIXME: Explain why the special member can't be constexpr. @@ -9121,7 +9121,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, !Info.Constexpr) { Diag(FD->getBeginLoc(), getLangOpts().CPlusPlus23 - ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch + ? diag::warn_cxx20_compat_defaulted_comparison_constexpr_mismatch : diag::ext_defaulted_comparison_constexpr_mismatch) << FD->isImplicit() << (int)DCK << FD->isConsteval(); DefaultedComparisonAnalyzer(*this, RD, FD, DCK, @@ -9135,8 +9135,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // declaration, it is implicitly considered to be constexpr. // FIXME: Only applying this to the first declaration seems problematic, as // simple reorderings can affect the meaning of the program. - if ((First && !FD->isConstexpr() && Info.Constexpr) || - getLangOpts().CPlusPlus23) + if (First && !FD->isConstexpr() && Info.Constexpr) FD->setConstexprKind(ConstexprSpecKind::Constexpr); // C++2a [except.spec]p3: diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp index da22d11a5dcbf..61d87def3718b 100644 --- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp +++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp @@ -1,8 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s -// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++20 -Wno-c++23-extensions -Wno-invalid-constexpr %s -// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++17 -Wno-c++23-extensions -Wno-invalid-constexpr %s -// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++14 -Wno-c++23-extensions -Wno-invalid-constexpr %s -// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20,cxx11 -std=c++11 -Wno-c++14-extensions -Wno-c++23-extensions -Wno-invalid-constexpr -Wno-constexpr-not-const %s // This test covers modifications made by P2448R2. @@ -158,5 +154,33 @@ void test() { // expected-note {{in call to}} constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \ // expected-note{{non-literal}} +} + +struct A { + A (); + ~A(); +}; + +template +struct opt +{ + union { + char c; + T data; + }; + + constexpr opt() {} + constexpr ~opt() { + if (engaged) + data.~T(); + } + + bool engaged = false; +}; + +consteval void foo() { + opt a; } + +void bar() { foo(); } From 03a990186c67808ded9380614211f7e643f0f45d Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 6 Mar 2024 07:15:19 -0800 Subject: [PATCH 12/13] Remove extension warnings and mentioning --- .../clang/Basic/DiagnosticSemaKinds.td | 45 +++------ clang/lib/Sema/SemaDeclCXX.cpp | 72 +++++++-------- clang/test/AST/Interp/cxx17.cpp | 2 +- clang/test/AST/Interp/cxx23.cpp | 20 ++-- clang/test/AST/Interp/literals.cpp | 2 +- clang/test/AST/Interp/shifts.cpp | 8 +- clang/test/CXX/basic/basic.types/p10.cpp | 26 +++--- .../class.compare.default/p3.cpp | 40 ++++---- .../class.compare.default/p4.cpp | 20 ++-- .../dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp | 4 +- .../dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp | 10 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 17 ++-- .../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 | 19 +++- clang/test/CXX/drs/dr14xx.cpp | 6 +- clang/test/CXX/drs/dr16xx.cpp | 2 +- clang/test/CXX/drs/dr6xx.cpp | 4 +- clang/test/CXX/expr/expr.const/p2-0x.cpp | 2 +- clang/test/CXX/special/class.copy/p13-0x.cpp | 2 +- clang/test/PCH/cxx11-constexpr.cpp | 2 +- .../SemaCXX/constant-expression-cxx11.cpp | 4 +- .../SemaCXX/constant-expression-cxx14.cpp | 6 +- .../SemaCXX/constant-expression-cxx2b.cpp | 30 +++--- .../constexpr-function-recovery-crash.cpp | 4 +- .../test/SemaCXX/cxx1z-constexpr-lambdas.cpp | 4 +- .../test/SemaCXX/cxx23-invalid-constexpr.cpp | 91 +++++++------------ clang/test/SemaCXX/cxx2a-consteval.cpp | 4 +- .../SemaCXX/deduced-return-type-cxx14.cpp | 2 +- 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 | 2 +- 36 files changed, 225 insertions(+), 271 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8cd89df2b4f7d..5fdfad2c5ae72 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2774,13 +2774,9 @@ def err_constexpr_tag : Error< 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 before C++23 because " + "destructor cannot be declared %sub{select_constexpr_spec_kind}0 because " "%select{data member %2|base class %3}1 does not have a " "constexpr destructor">; -def warn_cxx20_compat_constexpr_dtor_subobject : Warning< - "%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, DefaultIgnore; def note_constexpr_dtor_subobject : Note< "%select{data member %1|base class %2}0 declared here">; def err_constexpr_wrong_decl_kind : Error< @@ -2813,13 +2809,10 @@ 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 with non-literal return type %1 is a C++23 extension">; -def warn_cxx20_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, DefaultIgnore; + "%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 with %ordinal0 non-literal parameter type %3 is a C++23 extension">; -def warn_cxx20_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, DefaultIgnore; + "%select{constexpr|consteval}2 %select{function|constructor}1's %ordinal0 parameter type %3 is " + "not a literal type">; 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< @@ -2880,11 +2873,8 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning< "is incompatible with C++ standards before C++20">, InGroup, DefaultIgnore; def ext_constexpr_function_never_constant_expr : ExtWarn< - "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a " - "constant expression is a C++23 extension">, InGroup>, DefaultError; -def warn_cxx20_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, DefaultIgnore; + "%select{constexpr|consteval}1 %select{function|constructor}0 never produces a " + "constant expression">, InGroup>, DefaultError; def err_attr_cond_never_constant_expr : Error< "%0 attribute expression never produces a constant expression">; def err_diagnose_if_invalid_diagnostic_type : Error< @@ -9601,8 +9591,8 @@ 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 that marked %select{constexpr|consteval}1 " - "but never produces a constant expression is a C++23 extension">; + "defaulted definition of %sub{select_special_member_kind}0 cannot be marked %select{constexpr|consteval}1 " + "before C++23">; 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 warn_defaulted_method_deleted : Warning< @@ -9715,21 +9705,12 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note< "%select{|member|base class}0 %1 declared here">; def note_defaulted_comparison_cannot_deduce_callee : Note< "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">; -def ext_defaulted_comparison_constexpr_mismatch : Extension< - "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" - "three-way comparison operator}0 that is " - "declared %select{constexpr|consteval}2 but" - "%select{|for which the corresponding implicit 'operator==' }0 " - "invokes a non-constexpr comparison function is a C++23 extension">, - InGroup>; -def warn_cxx20_compat_defaulted_comparison_constexpr_mismatch : Warning< +def err_defaulted_comparison_constexpr_mismatch : Error< "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" - "three-way comparison operator}0 that is " - "declared %select{constexpr|consteval}2 but" - "%select{|for which the corresponding implicit 'operator==' }0 " - "invokes a non-constexpr comparison function is incompatible with C++ " - "standards before C++23">, - InGroup, DefaultIgnore; + "three-way comparison operator}0 cannot be " + "declared %select{constexpr|consteval}2 because " + "%select{it|for which the corresponding implicit 'operator==' }0 " + "invokes a non-constexpr comparison function ">; def note_defaulted_comparison_not_constexpr : Note< "non-constexpr comparison function would be used to compare " "%select{|member %1|base class %1}0">; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 78c94bce1f3d6..51794f1b4ecce 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1715,6 +1715,8 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind, static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, const CXXDestructorDecl *DD, Sema::CheckConstexprKind Kind) { + assert(!SemaRef.getLangOpts().CPlusPlus23 && + "this check is obsolete for C++23"); auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) { const CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); @@ -1722,16 +1724,13 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, return true; if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag(DD->getLocation(), - SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx20_compat_constexpr_dtor_subobject - : diag::err_constexpr_dtor_subobject) + SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject) << static_cast(DD->getConstexprKind()) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; } - return !!SemaRef.getLangOpts().CPlusPlus23; + return false; }; const CXXRecordDecl *RD = DD->getParent(); @@ -1749,6 +1748,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, Sema::CheckConstexprKind Kind) { + assert(!SemaRef.getLangOpts().CPlusPlus23 && + "this check is obsolete for C++23"); unsigned ArgIndex = 0; const auto *FT = FD->getType()->castAs(); for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(), @@ -1757,14 +1758,11 @@ 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, - SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx20_compat_constexpr_non_literal_param - : diag::err_constexpr_non_literal_param, - ArgIndex + 1, PD->getSourceRange(), isa(FD), - FD->isConsteval())) - return SemaRef.getLangOpts().CPlusPlus23; + if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i, + diag::err_constexpr_non_literal_param, ArgIndex + 1, + PD->getSourceRange(), isa(FD), + FD->isConsteval())) + return false; } return true; } @@ -1773,13 +1771,12 @@ 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(), - SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx20_compat_constexpr_non_literal_return - : diag::err_constexpr_non_literal_return, - FD->isConsteval())) - return SemaRef.getLangOpts().CPlusPlus23; + assert(!SemaRef.getLangOpts().CPlusPlus23 && + "this check is obsolete for C++23"); + if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(), + diag::err_constexpr_non_literal_return, + FD->isConsteval())) + return false; return true; } @@ -1865,8 +1862,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, } } - // - its return type shall be a literal type; - if (!CheckConstexprReturnType(*this, NewFD, Kind)) + // - its return type shall be a literal type; (removed in C++23) + if (!getLangOpts().CPlusPlus23 && + !CheckConstexprReturnType(*this, NewFD, Kind)) return false; } @@ -1883,8 +1881,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, } } - // - each of its parameter types shall be a literal type; - if (!CheckConstexprParameterTypes(*this, NewFD, Kind)) + // - each of its parameter types shall be a literal type; (removed in C++23) + if (!getLangOpts().CPlusPlus23 && + !CheckConstexprParameterTypes(*this, NewFD, Kind)) return false; Stmt *Body = NewFD->getBody(); @@ -2467,12 +2466,10 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, // function", so is not checked in CheckValid mode. SmallVector Diags; if (Kind == Sema::CheckConstexprKind::Diagnose && - !Expr::isPotentialConstantExpr(Dcl, Diags)) { - SemaRef.Diag( - Dcl->getLocation(), - SemaRef.getLangOpts().CPlusPlus23 - ? diag::warn_cxx20_compat_constexpr_function_never_constant_expr - : diag::ext_constexpr_function_never_constant_expr) + !Expr::isPotentialConstantExpr(Dcl, Diags) && + !SemaRef.getLangOpts().CPlusPlus23) { + SemaRef.Diag(Dcl->getLocation(), + diag::ext_constexpr_function_never_constant_expr) << isa(Dcl) << Dcl->isConsteval() << Dcl->getNameInfo().getSourceRange(); for (size_t I = 0, N = Diags.size(); I != N; ++I) @@ -7875,16 +7872,17 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { if (!MD->isConsteval() && RD->getNumVBases()) { - Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb) + Diag(MD->getBeginLoc(), + diag::err_incorrect_defaulted_constexpr_with_vb) << CSM; for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); - HadError = true; } else { Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM << MD->isConsteval(); } - // FIXME: Explain why the special member can't be constexpr. + HadError = true; + // FIXME: Explain why the special member can't be constexpr. } if (First) { @@ -9116,13 +9114,11 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // - if the function is a constructor or destructor, its class does not // have any virtual base classes. if (FD->isConstexpr()) { - if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) && + if (!getLangOpts().CPlusPlus23 && + CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) && CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) && !Info.Constexpr) { - Diag(FD->getBeginLoc(), - getLangOpts().CPlusPlus23 - ? diag::warn_cxx20_compat_defaulted_comparison_constexpr_mismatch - : diag::ext_defaulted_comparison_constexpr_mismatch) + Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch) << FD->isImplicit() << (int)DCK << FD->isConsteval(); DefaultedComparisonAnalyzer(*this, RD, FD, DCK, DefaultedComparisonAnalyzer::ExplainConstexpr) diff --git a/clang/test/AST/Interp/cxx17.cpp b/clang/test/AST/Interp/cxx17.cpp index b063a9e71828c..5e38d1a588700 100644 --- a/clang/test/AST/Interp/cxx17.cpp +++ b/clang/test/AST/Interp/cxx17.cpp @@ -83,7 +83,7 @@ static_assert(b() == 11); /// The diagnostics between the two interpreters used to be different here. struct S { int a; }; -constexpr S getS() { // both-error {{constexpr function that never produces a constant expression}} +constexpr S getS() { // both-error {{constexpr function never produces a constant expression}} (void)(1/0); // both-note 2{{division by zero}} \ // both-warning {{division by zero}} return S{12}; diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp index c109d35090a7f..127b58915127c 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/Interp/cxx23.cpp @@ -5,8 +5,8 @@ /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics. -constexpr int f(int n) { // ref20-error {{constexpr function that never produces a constant expression}} \ - // expected20-error {{constexpr function that never produces a constant expression}} +constexpr int f(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function 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}} \ // expected20-warning {{is a C++23 extension}} \ @@ -14,8 +14,8 @@ constexpr int f(int n) { // ref20-error {{constexpr function that never produce return m; // expected20-note {{initializer of 'm' is not a constant expression}} } -constexpr int g(int n) { // ref20-error {{constexpr function that never produces a constant expression}} \ - // expected20-error {{constexpr function that never produces a constant expression}} +constexpr int g(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function 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}} \ // expected20-warning {{is a C++23 extension}} \ @@ -24,8 +24,8 @@ constexpr int g(int n) { // ref20-error {{constexpr function that never p } -constexpr int c_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}} \ - // expected20-error {{constexpr function that never produces a constant expression}} +constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function 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}} \ // expected20-warning {{is a C++23 extension}} \ @@ -34,8 +34,8 @@ constexpr int c_thread_local(int n) { // ref20-error {{constexpr function that n } -constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}} \ - // expected20-error {{constexpr function that never produces a constant expression}} +constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function 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}} \ // expected20-warning {{is a C++23 extension}} \ @@ -43,14 +43,14 @@ constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function that return m; // expected20-note {{read of non-const variable}} } -constexpr int h(int n) { // ref20-error {{constexpr function that never produces a constant expression}} +constexpr int h(int n) { // ref20-error {{constexpr function 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}} \ // expected20-warning {{is a C++23 extension}} return &m - &m; } -constexpr int i(int n) { // ref20-error {{constexpr function that never produces a constant expression}} +constexpr int i(int n) { // ref20-error {{constexpr function 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}} \ // expected20-warning {{is a C++23 extension}} diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 86f8f80258494..d86609108ca44 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -272,7 +272,7 @@ namespace SizeOf { #if __cplusplus >= 202002L /// FIXME: The following code should be accepted. - consteval int foo(int n) { // ref-error {{consteval function that never produces a constant expression}} + consteval int foo(int n) { // ref-error {{consteval function 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 134e1b6291046..76047d0f752d5 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 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}} \ + 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}} \ 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 19e099d5077de..a543f248e5371 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 {{constexpr function with non-literal return type 'void' is a C++23 extension}} +// expected-error@-2 {{'void' is not a literal type}} #endif // - a scalar type @@ -40,12 +40,12 @@ constexpr ClassTemp classtemplate2[] = {}; struct UserProvDtor { ~UserProvDtor(); // expected-note {{has a user-provided destructor}} }; -constexpr int f(UserProvDtor) { return 0; } // expected-error {{non-literal parameter type 'UserProvDtor'}} +constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}} 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 {{non-literal parameter type 'NonTrivDtor'}} +constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}} struct NonTrivDtorBase { ~NonTrivDtorBase(); }; @@ -53,7 +53,7 @@ template struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} constexpr DerivedFromNonTrivDtor(); }; -constexpr int f(DerivedFromNonTrivDtor) { return 0; } // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromNonTrivDtor' is a C++23 extension}} +constexpr int f(DerivedFromNonTrivDtor) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor' is not a literal type}} 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 {{non-literal parameter type 'CopyCtorOnly'}} +constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}} struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} constexpr MoveCtorOnly(MoveCtorOnly&&); }; -constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'MoveCtorOnly'}} +constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}} template struct CtorArg { constexpr CtorArg(T); @@ -97,7 +97,7 @@ struct Derived : HasVBase { template struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} constexpr DerivedFromVBase(); }; -constexpr int f(DerivedFromVBase) {} // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromVBase' is a C++23 extension}} +constexpr int f(DerivedFromVBase) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase' is not a literal type}} template constexpr DerivedFromVBase::DerivedFromVBase() : T() {} constexpr int nVBase = (DerivedFromVBase(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase' with virtual base class in a constant expression}} @@ -105,12 +105,12 @@ constexpr int nVBase = (DerivedFromVBase(), 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 non-literal parameter type 'NonLitMember' is a C++23 extension}} +constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} struct NonLitBase : S { // expected-note {{base class 'S' of non-literal type}} constexpr NonLitBase(); }; -constexpr int f(NonLitBase) { return 0; } // expected-error {{non-literal parameter type 'NonLitBase'}} +constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}} struct LitMemBase : Agg { Agg agg; }; @@ -120,7 +120,7 @@ struct MemberType { constexpr MemberType(); }; constexpr int f(MemberType) { return 0; } -constexpr int f(MemberType) { return 0; } // expected-error {{non-literal parameter type}} +constexpr int f(MemberType) { return 0; } // expected-error {{not a literal 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 non-literal parameter type 'ArrBad'}} +constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}} 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 {{non-literal parameter type}} + constexpr int f(D) { return 0; } // expected-error {{not a literal 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 {{non-literal parameter type}} + constexpr int f(H) { return 0; } // expected-error {{not a literal type}} struct J; struct I { constexpr I(const J&); }; diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp index 166bd97e2731c..c73eb0dee9951 100644 --- a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp +++ b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp @@ -1,8 +1,8 @@ // This test is for the [class.compare.default]p3 added by P2002R0 -// Also covers modifications made by P2448R2 and extension warnings +// Also covers modifications made by P2448R2 -// RUN: %clang_cc1 -std=c++2a -verify %s -// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s +// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s +// RUN: %clang_cc1 -std=c++23 -verify=expected %s namespace std { struct strong_ordering { @@ -82,10 +82,12 @@ struct TestB { }; struct C { - friend bool operator==(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}} + friend bool operator==(const C&, const C&); // expected-note {{previous}} \ + // cxx2a-note 2{{declared here}} friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}} - friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}} + friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} \ + // cxx2a-note 2{{declared here}} friend bool operator<(const C&, const C&) = default; // expected-note {{previous}} friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}} friend bool operator>(const C&, const C&) = default; // expected-note {{previous}} @@ -129,23 +131,23 @@ struct TestD { struct E { A a; - C c; // extension-note 2{{non-constexpr comparison function would be used to compare member 'c'}} + C c; // cxx2a-note 2{{non-constexpr comparison function would be used to compare member 'c'}} A b; - friend constexpr bool operator==(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend constexpr bool operator==(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}} friend constexpr bool operator!=(const E&, const E&) = default; - friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}} friend constexpr bool operator<(const E&, const E&) = default; friend constexpr bool operator<=(const E&, const E&) = default; friend constexpr bool operator>(const E&, const E&) = default; friend constexpr bool operator>=(const E&, const E&) = default; }; -struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would be used to compare base class 'C'}} - friend constexpr bool operator==(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} +struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be used to compare base class 'C'}} + friend constexpr bool operator==(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}} friend constexpr bool operator!=(const E2&, const E2&) = default; - friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}} friend constexpr bool operator<(const E2&, const E2&) = default; friend constexpr bool operator<=(const E2&, const E2&) = default; friend constexpr bool operator>(const E2&, const E2&) = default; @@ -153,14 +155,14 @@ struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would }; struct F { - friend bool operator==(const F&, const F&); // extension-note {{non-constexpr comparison function declared here}} - friend constexpr bool operator!=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} - - friend std::strong_ordering operator<=>(const F&, const F&); // extension-note 4{{non-constexpr comparison function declared here}} - friend constexpr bool operator<(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} - friend constexpr bool operator<=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} - friend constexpr bool operator>(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} - friend constexpr bool operator>=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend bool operator==(const F&, const F&); // cxx2a-note {{declared here}} + friend constexpr bool operator!=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} + + friend std::strong_ordering operator<=>(const F&, const F&); // cxx2a-note 4{{non-constexpr comparison function declared here}} + friend constexpr bool operator<(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend constexpr bool operator<=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend constexpr bool operator>(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend constexpr bool operator>=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} }; // No implicit 'constexpr' if it's not the first declaration. diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp index 02cdd7f85aebf..534c3b34d8832 100644 --- a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp +++ b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s -// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s +// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s +// RUN: %clang_cc1 -std=c++23 -verify=expected %s // This test is for [class.compare.default]p3 as modified and renumbered to p4 // by P2002R0. -// Also covers modifications made by P2448R2 and extension warnings +// Also covers modifications made by P2448R2 namespace std { struct strong_ordering { @@ -78,13 +78,13 @@ void use_g(G g) { } struct H { - bool operator==(const H&) const; // extension-note {{non-constexpr comparison function declared here}} + bool operator==(const H&) const; // cxx2a-note {{non-constexpr comparison function declared here}} constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; } }; struct I { - H h; // extension-note {{non-constexpr comparison function would be used to compare member 'h'}} - constexpr std::strong_ordering operator<=>(const I&) const = default; // extension-warning {{implicit 'operator==' invokes a non-constexpr comparison function is a C++23 extension}} + H h; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'h'}} + constexpr std::strong_ordering operator<=>(const I&) const = default; // cxx2a-error {{cannot be declared constexpr}} }; struct J { @@ -148,16 +148,16 @@ namespace NoInjectionIfOperatorEqualsDeclared { namespace GH61238 { template struct my_struct { - A value; // extension-note {{non-constexpr comparison function would be used to compare member 'value'}} + A value; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'value'}} - constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // cxx2a-error {{cannot be declared constexpr}} }; struct non_constexpr_type { - friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // extension-note {{non-constexpr comparison function declared here}} + friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // cxx2a-note {{non-constexpr comparison function declared here}} return false; } }; -my_struct obj; // extension-note {{in instantiation of template class 'GH61238::my_struct' requested here}} +my_struct obj; // cxx2a-note {{in instantiation of template class 'GH61238::my_struct' requested here}} } 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 1a3da8bdc252a..48bc8fb426bcb 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 @@ -59,11 +59,11 @@ namespace subobject { ~A(); }; 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}} + constexpr ~B() {} // cxx2a-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}} }; struct C { 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}} + constexpr ~C() {} // cxx2a-error {{destructor cannot be declared constexpr 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 e8c71b44edd62..8cb37ae6d1cde 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,9 +14,8 @@ constexpr int i(int n) { return m; } -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}} +constexpr int g() { + goto test; // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} test: return 0; } @@ -29,9 +28,8 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}} NonLiteral() {} }; -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}} +constexpr void non_literal() { + NonLiteral n; // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}} } constexpr void non_literal2(bool b) { 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 d57c098faff6d..4416c82522649 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 @@ -41,17 +41,18 @@ struct T : SS, NonLiteral { virtual constexpr int OutOfLineVirtual() const; // beforecxx20-error {{virtual function cannot be constexpr}} // - its return type shall be 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}} + // 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 {}; } // beforecxx23-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}} 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; - // 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}} + // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types + constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} typedef int G(NonLiteral) const; constexpr G NonLiteralParam2; // ok until definition @@ -65,7 +66,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}} \ - // cxx14_20-error{{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression}} + // cxx14_20-error{{defaulted definition of copy assignment operator cannot be marked constexpr}} }; constexpr int T::OutOfLineVirtual() const { return 0; } @@ -229,7 +230,7 @@ namespace DR1364 { // parameter is not allowed in a constant expression. } int kGlobal; // beforecxx23-note {{here}} - constexpr int f() { // beforecxx23-error {{constexpr function that never produces a constant expression is a C++23 extension}} + constexpr int f() { // beforecxx23-error {{constexpr function never produces a constant expression}} return kGlobal; // beforecxx23-note {{read of non-const}} } } @@ -271,7 +272,7 @@ namespace std_example { int a; // beforecxx20-warning {{uninitialized}} return a; } - constexpr int prev(int x) { // beforecxx14-error {{constexpr function that never produces a constant expression is a C++23 extension}} + constexpr int prev(int x) { // beforecxx14-error {{never produces a constant expression}} 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 71c8d09d3041d..92698ec1c7387 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 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}} + 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}} // 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); // - every constructor involved in initializing non-static data members and base // class sub-objects shall be a constexpr constructor. -// This is the case before C++23. +// This will no longer be the case once we support P2448R2 struct ConstexprBaseMemberCtors : Literal { Literal l; constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok - constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} + constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}} Literal(0), // expected-note {{non-constexpr constructor}} l() {} - constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} + constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}} 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{{marked constexpr but never produces a constant expression}} +// expected-error@-2{{cannot be marked constexpr}} #endif union XU2 { int a = 1; constexpr XU2() = default; }; @@ -282,7 +282,7 @@ struct XU3 { }; constexpr XU3() = default; #ifndef CXX2A - // expected-error@-2{{marked constexpr but never produces a constant expression}} + // expected-error@-2{{cannot be marked constexpr}} #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 that never produces a constant expression is a C++23 extension}} expected-note {{read of non-const}} + constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} 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 {{marked constexpr but never produces a constant expression}} + constexpr B::B(B&) = default; // expected-error {{cannot be marked constexpr}} 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 {{marked constexpr but never produces a constant expression}} + constexpr C::C(C&) = default; // expected-error {{cannot be marked constexpr}} } 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 7c06e5a9f928a..18b2c6b1d6d15 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 that never produces a constant expression is a C++23 extension}} expected-note {{subexpression}} +constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} 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 that never produces a constant expression}} expected-note {{read of non-const}} + constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} }; } namespace PotentialConstant { -constexpr int Comma(int n) { return // expected-error {{constexpr function that never produces a constant expression}} +constexpr int Comma(int n) { return // expected-error {{constexpr function 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 850420ca8ae1c..00ef78426289f 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 g3() { return {}; } // ok - constexpr T3 g4() { return {}; } // expected-error {{non-literal return type}} + constexpr T3 g4() { return {}; } // expected-error {{not a literal 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 9c9034c7f908b..849594307390f 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 {{marked constexpr but never produces a constant expression}} + constexpr S1() = default; // expected-error {{defaulted definition of default constructor cannot be marked constexpr}} 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 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}} + constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor cannot be marked constexpr}} + constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor cannot be marked}} NoCopyMove ncm; }; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index b9f23c1f934fd..d8e3b5d87bd14 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -485,10 +485,10 @@ namespace dr1358 { // dr1358: 3.1 struct B : Virt { int member; constexpr B(NonLit u) : member(u) {} - // cxx11-20-error@-1 {{constexpr constructor with 1st non-literal parameter type 'NonLit' is a C++23 extension}} + // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} // 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(); } - // cxx11-20-error@-1 {{constexpr function with non-literal return type 'NonLit' is a C++23 extension}} + // cxx11-20-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} // 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 @@ -498,19 +498,28 @@ 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 that marked constexpr but never produces a constant expression is a C++23 extension}} + // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr before C++23}} union C { constexpr C() = default; int a, b; }; // #dr1359-C - // cxx11-17-error@-1 {{defaulted definition of default constructor that marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be 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 that marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} constexpr A a = A(); constexpr B b = B(); + // cxx11-17-error@-1 {{no matching constructor for initialization of 'B'}} + // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr C c = C(); + // cxx11-17-error@-1 {{no matching constructor for initialization of 'C'}} + // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr X x = X(); constexpr Y y = Y(); + // cxx11-17-error@-1 {{no matching constructor for initialization of 'Y'}} + // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} #endif } diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index 873431b433291..ed6dda731fd51 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 that marked constexpr but never produces a constant expression is a C++23 extension}} + // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} 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 that marked constexpr but never produces a constant expression is a C++23 extension}} + // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} 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 that marked constexpr but never produces a constant expression is a C++23 extension}} + // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} struct H { union { int n = 0; diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index d51f0d9828f12..766c90d3bc7bd 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -350,7 +350,7 @@ namespace dr1684 { // dr1684: 3.6 }; constexpr int f(NonLiteral &) { return 0; } constexpr int f(NonLiteral) { return 0; } - // cxx11-20-error@-1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}} + // cxx11-20-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} // 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 e62803e56885b..190e05784f32b 100644 --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -584,7 +584,7 @@ namespace dr647 { // dr647: 3.1 struct C { constexpr C(NonLiteral); constexpr C(NonLiteral, int) {} - // cxx11-20-error@-1 {{constexpr constructor with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}} + // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}} // 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}} @@ -609,7 +609,7 @@ namespace dr647 { // dr647: 3.1 d(0) {} constexpr E(int) - // cxx11-20-error@-1 {{constexpr constructor that never produces a constant expression}} + // cxx11-20-error@-1 {{constexpr constructor 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), diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index 868dacd4415a3..e3cd057baba75 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 that never produces a constant expression}} +constexpr int rem() { // expected-error {{constexpr function 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/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp index 2f6173be74a2a..013d5b5658238 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 {{marked constexpr but never produces a constant expression}} + constexpr C(const C &) = default; // expected-error {{cannot be marked constexpr}} A a; }; } diff --git a/clang/test/PCH/cxx11-constexpr.cpp b/clang/test/PCH/cxx11-constexpr.cpp index 22cc53e9152cd..b315b477dbf1c 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 {{non-literal parameter type}} +constexpr int f(C c) { return 0; } // expected-error {{not a literal 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/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 43e9434dee455..efb391ba0922d 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1273,7 +1273,7 @@ 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) { // cxx11_20-error {{constexpr function that never produces a constant expression}} + constexpr bool f(int k) { // cxx11_20-error {{constexpr function never produces a constant expression}} return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used in a constant expression}} } } @@ -1767,7 +1767,7 @@ namespace TLS { } namespace Void { - constexpr void f() { return; } // cxx11-error{{constexpr function with non-literal return type 'void' is a C++23 extension}} + constexpr void f() { return; } // cxx11-error{{constexpr function's return type 'void' is not a literal type}} void assert_failed(const char *msg, const char *file, int line); // expected-note {{declared here}} #define ASSERT(expr) ((expr) ? static_cast(0) : assert_failed(#expr, __FILE__, __LINE__)) diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index c829bcc1fc94d..80a7a2dd31531 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -44,12 +44,12 @@ constexpr int g(int k) { return 3 * k3 + 5 * k2 + n * k - 20; } static_assert(g(2) == 42, ""); -constexpr int h(int n) { // cxx14_20-error {{constexpr function that never produces a constant expression}} +constexpr int h(int n) { // cxx14_20-error {{constexpr function 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) { // cxx14_20-error {{constexpr function that never produces a constant expression}} +constexpr int i(int n) { // cxx14_20-error {{constexpr function 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; @@ -184,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() { // 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}} + constexpr void f() { // cxx14_20-error{{constexpr function 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}} } diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp index e92a64d830881..2519839b7ac57 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp @@ -10,42 +10,36 @@ struct Constexpr{}; #if __cplusplus > 202002L -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}} \ +constexpr int f(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} + static const int m = n; // cxx2a-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) { // 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}} \ +constexpr int g(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} + thread_local const int m = n; // cxx2a-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) { // 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}} \ +constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} + static _Thread_local int m = 0; // cxx2a-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) { // 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}} \ +constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} + static __thread int m = 0; // cxx2a-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) { // 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}} \ +constexpr int h(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} + static const int m = n; // cxx2a-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) { // 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}} \ +constexpr int i(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} + thread_local const int m = n; // cxx2a-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 dd0b911fc516b..90ee7892b2fc2 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 that never produce}} +constexpr int test5() { // expected-error {{constexpr function 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 that never produce}} +constexpr int test6() { // expected-error {{constexpr function 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 46c24cc3e5d0b..6a1f48bf7958f 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{{non-literal parameter type}} +//expected-error@+4{{not a literal 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{{non-literal parameter type}} + auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}} } // end ns1 namespace ns2 { diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp index 61d87def3718b..4dc16c59d8058 100644 --- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp +++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp @@ -1,18 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s // This test covers modifications made by P2448R2. // 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) { - // cxx23-warning@-1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} - double D = 2.0 / 0.0; // cxx23-note {{division by zero}} \ - // expected-note {{division by zero}} +constexpr int F(int N) { + double D = 2.0 / 0.0; // expected-note {{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}} @@ -25,43 +22,36 @@ constexpr int FT(T N) { return 1; } -class NonLiteral { -// cxx23-note@-1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} +class NonLiteral { // expected-note {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}} public: - NonLiteral() {} // cxx23-note 2{{declared here}} + NonLiteral() {} ~NonLiteral() {} }; constexpr NonLiteral F1() { -// cxx23-warning@-1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}} -// cxx23-warning@-2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} return NonLiteral{}; -// cxx23-note@-1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}} } constexpr int F2(NonLiteral N) { - // cxx23-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 { - constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}} + constexpr ~Derived() {}; }; class Derived1 : public NonLiteral { constexpr Derived1() : NonLiteral () {} - // cxx23-warning@-1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-note@-2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}} }; -struct X { // cxx23-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} - X(); // cxx23-note 3{{declared here}} - X(const X&); // cxx23-note 2{{declared here}} +struct X { + X(); + X(const X&); X(X&&); - X& operator=(X&); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}} - X& operator=(X&& other); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}} - bool operator==(X const&) const; // cxx23-note 2{{non-constexpr comparison function declared here}} + X& operator=(X&); + X& operator=(X&& other); + bool operator==(X const&) const; }; template @@ -70,55 +60,39 @@ struct Wrapper { constexpr Wrapper(Wrapper const&) = default; constexpr Wrapper(T const& t) : t(t) { } constexpr Wrapper(Wrapper &&) = default; - constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} - constexpr bool operator==(Wrapper const&) const = default; // cxx23-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}} - // precxx20-warning@-1 2{{defaulted comparison operators are a C++20 extension}} -private: - T t; // cxx23-note {{non-constexpr comparison function would be used to compare member 't'}} + constexpr X get() const { return t; } + constexpr bool operator==(Wrapper const&) const = default; + private: + T t; }; struct WrapperNonT { constexpr WrapperNonT() = default; constexpr WrapperNonT(WrapperNonT const&) = default; - constexpr WrapperNonT(X const& t) : t(t) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr WrapperNonT(X const& t) : t(t) { } constexpr WrapperNonT(WrapperNonT &&) = default; constexpr WrapperNonT& operator=(WrapperNonT &) = default; - // cxx11-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; - // cxx11-error@-1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} - constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}} - // cxx23-warning@-1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-note@-2 {{non-constexpr constructor 'X' cannot be used in a constant expression}} - constexpr bool operator==(WrapperNonT const&) const = default; // cxx23-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}} - // precxx20-warning@-1 {{defaulted comparison operators are a C++20 extension}} -private: - X t; // cxx23-note {{non-constexpr comparison function would be used to compare member 't'}} + constexpr X get() const { return t; } + constexpr bool operator==(WrapperNonT const&) const = default; + private: + X t; }; struct NonDefaultMembers { - constexpr NonDefaultMembers() {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-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&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} - constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-note@-1 {{non-constexpr constructor 'X' cannot be used in a constant expression}} + constexpr NonDefaultMembers() {}; // expected-note {{non-literal type 'X' cannot be used in a constant expression}} + constexpr NonDefaultMembers(NonDefaultMembers const&) {}; + constexpr NonDefaultMembers(NonDefaultMembers &&) {}; constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;} - // cxx11-error@-1 {{no viable overloaded '='}} - // cxx11-error@-2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}} constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;} - // cxx11-error@-1 {{no viable overloaded '='}} - // cxx11-error@-2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}} constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;} X t; }; -static int Glob = 0; // cxx23-note {{declared here}} +int Glob = 0; class C1 { public: - constexpr C1() : D(Glob) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}} - // cxx23-note@-1 {{read of non-const variable 'Glob' is not allowed in a constant expression}} + constexpr C1() : D(Glob) {}; private: int D; }; @@ -131,27 +105,26 @@ void test() { 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(); // cxx23-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}} + constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}} F1(); NonLiteral L; - constexpr auto D = F2(L); // cxx23-error {{constexpr variable 'D' must be initialized by a constant expression}} - // cxx23-note@-1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}} + 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; // cxx23-note {{requested here}} - // precxx20-note@-1 {{requested here}} + Wrapper x; WrapperNonT x1; NonDefaultMembers x2; // TODO these produce notes with an invalid source location. // static_assert((Wrapper(), true)); - // static_assert((WrapperNonT(), true),""); + // static_assert((WrapperNonT(), true),""); static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \ - // expected-note {{in call to}} + // 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 0a3eb29675844..192621225a543 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 {{marked consteval but never produces a constant expression}} + consteval D() = default; // expected-error {{cannot be marked consteval}} consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}} }; @@ -884,7 +884,7 @@ void func() { S s7; } -consteval int aConstevalFunction() { // expected-error {{consteval function that never produces a constant expression}} +consteval int aConstevalFunction() { // expected-error {{consteval function never produces a constant expression}} // Defaulted default constructors are implicitly consteval. S s1; diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index be75be199c684..431d77ca785b8 100644 --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -300,7 +300,7 @@ namespace Constexpr { } struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}} // 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}} + constexpr auto f2(int n) { return nl; } // cxx14_20-error {{constexpr function's return type 'struct NonLiteral' is not a literal type}} } // 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 94a4d62515ee8..e5bec0c7119b0 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 that never produces a constant expression}} \ +[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function never produces a constant expression}} \ // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}} [[msvc::constexpr]] constexpr void f1() {} // expected-error {{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 that never produces a constant expression}} \ +constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function 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 that never produces a constant expression}} +constexpr bool f8() { // expected-error {{constexpr function 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 6bf2dec91250c..79f71a34cb7d8 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 that never produces a constant expression}} \ + static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function 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 1300f9960ca75..368a3eeb6955b 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 with 1st non-literal parameter type 'svint8_t' (aka '__SVInt8_t') is a C++23 extension}} +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}} #endif #if __cplusplus < 201703L diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp index 23102b8ab8872..067a404c489aa 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 that marked constexpr but never produces a constant expression is a C++23 extension}} + constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor cannot be marked constexpr}} }; diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 0d2ad2ec4bc4e..7d1470c02369e 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -356,7 +356,7 @@

C++23 implementation status

Relaxing some constexpr restrictions
P2448R2 - Clang 18 + Clang 19 Using unknown pointers and references in constant expressions From f4cf3e1154aef1486ec1bc05588b1cb813f1e0f6 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 6 Mar 2024 10:09:38 -0800 Subject: [PATCH 13/13] Fix format and test --- clang/lib/Sema/SemaDeclCXX.cpp | 4 ++-- clang/test/SemaCXX/builtin_vectorelements.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 51794f1b4ecce..e258a4f7c8941 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7881,8 +7881,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM << MD->isConsteval(); } - HadError = true; - // FIXME: Explain why the special member can't be constexpr. + HadError = true; + // FIXME: Explain why the special member can't be constexpr. } if (First) { diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp index e83d931ee4026..59ff09ac72e42 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 -consteval int consteval_elements() { // expected-error {{consteval function that never produces a constant expression}} +consteval int consteval_elements() { // expected-error {{consteval function 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}} }