-
Notifications
You must be signed in to change notification settings - Fork 15k
Description
| Bugzilla Link | 39889 |
| Version | trunk |
| OS | All |
Extended Description
I've been trying to find a way to tell Clang that a std::unique_ptr's pointer cannot be null, so the emitted destructor code does not contain an unnecessary check. GCC's optimizer seems to be able to figure this out. MSVC's optimizer misses this opportunity.
https://godbolt.org/z/rywaj3 has my code and the compilers I've used. I will also include the code at the end of the bug. In this example, the code generated for Handle::~Handle(), which contains an inlined unique_ptr::~unique_ptr(), should not contain a test/je sequence. The check contradicts the assumption that the unique_ptr is not null.
I tried expressing the assumption using the GCC-style _builtin_unreachable() as well as Clang's builtin_assume(). I tried to be more or less explicit in the predicate -- tried ptr, ptr.get(), ptr.get() != nullptr. I tried -O2, -O3 and -Ofast.
Here is the code in the godbolt link above. The code can be simplified by inlining the ASSUME(x) macro. I am submitting the current form so developers can easily compare output across Clang, GCC and MSVC.
#include
#include
#if defined(clang)
// #define ASSUME(x) __builtin_assume(static_cast(x))
#define ASSUME(x) if(!static_cast(x)) __builtin_unreachable()
#elif defined(GNUC)
#define ASSUME(x) if(!static_cast(x)) __builtin_unreachable()
#elif defined(_MSC_VER)
#define ASSUME(x) __assume(static_cast(x))
#else
#error "No ASSUME definition"
#endif
struct Resource {
~Resource() noexcept;
};
class HandleBase {
public:
HandleBase() noexcept = default;
virtual ~HandleBase();
};
class Handle : public HandleBase {
const std::unique_ptr ptr_;
public:
Handle();
~Handle() override;
};
Handle::Handle() : ptr_(std::make_unique()) {}
Handle::~Handle() {
ASSUME(ptr_.get() != nullptr);
}