Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
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 = dyn_cast<CXXMethodDecl>(NewFD);
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels like you are trying to partially implement https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3533r2.html as a drive-by?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That is not really my intent but leaving it enabled for C++26 is also not correct. I can leave it enabled for C++26 but it is such a trivial addition it seems silly not to. If the objections are strong I can take out the C++26 check.

// 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