https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92449
>From 0e73c984a4215207b2842f60ac4dcaeb63230407 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Thu, 16 May 2024 15:47:04 -0400 Subject: [PATCH 1/2] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 --- clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++++++++++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8a7af678b33d3..051814643ed88 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10290,15 +10290,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { - CXXMethodDecl *OldMD = - dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast<CXXMethodDecl>(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa<CXXConstructorDecl, CXXDestructorDecl>(NewMD)) { + auto *OldMD = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 788e93b56bb38..9e890204c78bd 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template<typename T> constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template <typename T> T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g<int>' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 0000000000000..2a57489083695 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template<typename T> + void f0(); + + template<> + constexpr void f0<short>(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + template<typename T> + void f1() const; // since-cxx14-note 2{{candidate template ignored: could not match 'void () const' against 'void ()'}} + + template<> + constexpr void f1<short>(); // since-cxx14-error {{no function template matches function template specialization 'f1'}} + // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} +}; + +template<> +constexpr void A::f0<long>(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +constexpr void A::f1<long>(); // since-cxx14-error {{no function template matches function template specialization 'f1'}} + // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +// FIXME: It's unclear whether [temp.expl.spec]p12 is intended to apply to +// members of a class template explicitly specialized for an implicitly +// instantiated specialization of that template. +template<typename T> +struct B { + void g0(); // since-cxx14-note {{previous declaration is here}} + // cxx11-note@-1 {{member declaration does not match because it is not const qualified}} + + void g1() const; // since-cxx14-note {{member declaration does not match because it is const qualified}} + // cxx11-note@-1 {{previous declaration is here}} + + template<typename U> + void h0(); // since-cxx14-note {{previous declaration is here}} + + template<typename U> + void h1() const; // cxx11-note {{previous declaration is here}} +}; + +template<> +constexpr void B<short>::g0(); // since-cxx14-error {{constexpr declaration of 'g0' follows non-constexpr declaration}} + // cxx11-error@-1 {{out-of-line declaration of 'g0' does not match any declaration in 'B<short>'}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +constexpr void B<short>::g1(); // since-cxx14-error {{out-of-line declaration of 'g1' does not match any declaration in 'B<short>'}} + // cxx11-error@-1 {{constexpr declaration of 'g1' follows non-constexpr declaration}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +template<typename U> +constexpr void B<long>::h0(); // since-cxx14-error {{constexpr declaration of 'h0' follows non-constexpr declaration}} + // cxx11-error@-1 {{out-of-line declaration of 'h0' does not match any declaration in 'B<long>'}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +template<typename U> +constexpr void B<long>::h1(); // since-cxx14-error {{out-of-line declaration of 'h1' does not match any declaration in 'B<long>'}} + // cxx11-error@-1 {{constexpr declaration of 'h1' follows non-constexpr declaration}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + >From 95e1182719047c4bb8db370583c7ea6553197c09 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Thu, 16 May 2024 16:20:39 -0400 Subject: [PATCH 2/2] [FOLD] add release note --- clang/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a89e10524aa1f..56a74004995ed 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -744,6 +744,8 @@ Bug Fixes to C++ Support explicit object argument member functions. Fixes (#GH92188). - Fix a C++11 crash when a non-const non-static member function is defined out-of-line with the ``constexpr`` specifier. Fixes (#GH61004). +- Clang no longer treats ``constexpr`` class scope function template specializations of non-static data members + as implicitly ``const`` in language standards after C++11. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits