Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3026,7 +3026,7 @@ def warn_cxx17_compat_constexpr_virtual : Warning<
"virtual constexpr functions are incompatible with "
"C++ standards before C++20">, InGroup<CXXPre20Compat>, 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<
Expand Down
13 changes: 6 additions & 7 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CXXMethodDecl>(NewFD);
if (MD && MD->isInstance()) {
if ((!getLangOpts().CPlusPlus26 && isa<CXXConstructorDecl>(NewFD)) ||
((getLangOpts().CPlusPlus20 && !getLangOpts().CPlusPlus26) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to check for C++20? I think some other function will diagnose that destructor can't be constexpr.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have explicit constexpr destructor before C++20 and so this would be a spurious diagnostic.

isa<CXXDestructorDecl>(NewFD))) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(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<CXXConstructorDecl>(NewFD)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
<< isa<CXXConstructorDecl>(NewFD)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
for (const auto &I : RD->vbases())
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here)
<< I.getSourceRange();
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
};
}

Expand Down
10 changes: 8 additions & 2 deletions clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down