clang error on exception specification from C++20 on
Asked Answered
R

1

7

This code compiles on gcc and msvc but not with clang from C++20 on:

#include <type_traits>

class IBase {
   protected:
    IBase() noexcept = default;

   public:
    virtual ~IBase() noexcept = default;
};

class Derived : public IBase {
   public:
    virtual ~Derived() noexcept(
        std::is_nothrow_destructible<IBase>::value) override = default;
};

LIVE

Up to C++17 included, gcc, msvc and clang compile this code but from C++20, clang rejects it with error: exception specification is not available until end of class definition.

Is it a clang bug or, on the contrary, a change in exception specification in C++20? How can I fix this code?


[EDIT] Based on the comments, here is a "more minimal reproducible example":

class IBase {
   public:
    virtual ~IBase() noexcept = default;
};

class Derived : public IBase {
   public:
    ~Derived() noexcept(true) override = default;
};

LIVE

Notice that the inheritance and both = defaultseem necessary to trigger the error.

Redfin answered 21/9, 2024 at 16:27 Comment(10)
A more minimal MRE : virtual ~Derived() noexcept(true) override = default; gives the same error might simplify analysis. (I don't know what's going on yet either)Typeface
And you can drop virtual in the derived class to make it even more minimal :-) Interesting question.Natalia
This seems to pass if you don't =default the ~IBase(). Also ~Derived() noexcept = default; (instead of ~Derived() noexcept(true) = default;) passes regardless of ~IBase being defaulted. This smells like an error in clang.Attica
My guess would be that it has something to do with the overload resolution necessary to select a destructor among the prospective destructors since C++20 coupled with the issue that an expression in the exception specification can't be parsed until after the class is complete (which causes still unresolved issues similar to this). Also relevant may be that the compiler is required to check the validity of the exception specification for overriding functions on their declaration, because they must not be looser than the specification of the function they override. But I don't see why exactly.Displacement
mmm, can one change the except specification on an override? good question.Detonator
@Detonator timsong-cpp.github.io/cppwp/n4861/except.spec#4. But my first snippet seems to explicitly enforce this rule.Redfin
Besides, the issue does not appear on a non-special function: godbolt.org/z/b15EorohaRedfin
Workaround for Clang "exception specification is not available until end of class definition" bugYearning
@Yearning I had dismissed this post on purpose as it was quite old. Yet thanks for your workaround in answer.Redfin
@Redfin Also the code there(in that post) works now in clang. You're welcome.Yearning
Y
1

How can I fix this code?

Although I don't know if this is a clang bug or not but I do know a workaround if you really want to =default the dtor.

In particular, you can =default outside the Derived class as shown below.

class Derived : public IBase {
   public:
    ~Derived() noexcept(true) ;
};
//default outside the class
Derived::~Derived() noexcept(true)= default;
int main() {
} 

Working demo

Yearning answered 23/9, 2024 at 14:31 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.