diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4f62a679b8b21..e851667336c5e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -477,6 +477,7 @@ Bug Fixes to C++ Support - Fix for clang incorrectly rejecting the default construction of a union with nontrivial member when another member has an initializer. (#GH81774) - Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753) +- Fix bug where we were diagnosing all constexpr member functions if the class had a virtual bases. (#GH97266) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 12fd7b08683e1..a3eee8d9a9104 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3026,7 +3026,7 @@ def warn_cxx17_compat_constexpr_virtual : Warning< "virtual constexpr functions are incompatible with " "C++ standards before C++20">, InGroup, DefaultIgnore; def err_constexpr_virtual_base : Error< - "constexpr %select{member function|constructor}0 not allowed in " + "constexpr %select{destructor|constructor}0 not allowed in " "%select{struct|interface|class}1 with virtual base " "%plural{1:class|:classes}2">; def note_non_literal_incomplete : Note< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d41ab126c426f..b9db48df424f1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1918,23 +1918,22 @@ static bool CheckConstexprMissingReturn(Sema &SemaRef, const FunctionDecl *Dcl); bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, CheckConstexprKind Kind) { - const CXXMethodDecl *MD = dyn_cast(NewFD); - if (MD && MD->isInstance()) { + if ((!getLangOpts().CPlusPlus26 && isa(NewFD)) || + ((getLangOpts().CPlusPlus20 && !getLangOpts().CPlusPlus26) && + isa(NewFD))) { + const CXXMethodDecl *MD = cast(NewFD); // C++11 [dcl.constexpr]p4: // The definition of a constexpr constructor shall satisfy the following // constraints: // - the class shall not have any virtual base classes; - // - // FIXME: This only applies to constructors and destructors, not arbitrary - // member functions. const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { if (Kind == CheckConstexprKind::CheckValid) return false; Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) - << isa(NewFD) - << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); + << isa(NewFD) + << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here) << I.getSourceRange(); 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 48bc8fb426bcb..a3d9d1181fef1 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 @@ -6,7 +6,7 @@ namespace vbase { struct A {}; struct B : virtual A { // expected-note {{virtual}} - constexpr ~B() {} // expected-error {{constexpr member function not allowed in struct with virtual base class}} + constexpr ~B() {} // expected-error {{constexpr destructor not allowed in struct with virtual base class}} }; } 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 51990ee4341d2..5a06d686b4c0f 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 @@ -84,10 +84,16 @@ struct T3 { struct U { constexpr U SelfReturn() const; constexpr int SelfParam(U) const; + constexpr ~U(); // beforecxx20-error {{destructor cannot be declared constexpr}} }; -struct V : virtual U { // expected-note {{here}} - constexpr int F() const { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}} +struct V : virtual U { // expected-note {{here}} //aftercxx20-note {{here}} + constexpr V() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} + constexpr ~V() {} // aftercxx20-error {{constexpr destructor not allowed in struct with virtual base class}} + // beforecxx20-error@-1 {{destructor cannot be declared constexpr}} + // beforecxx14-error@-2 {{constexpr function's return type 'void' is not a literal type}} + // ^ FIXME this is just a bad diagnostic + constexpr int f() const { return 0; } }; // or a compound-statememt that contains only [CXX11]