diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 0ffe74dab..d98161488 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -141,7 +141,9 @@ public: Value * * elems; ListBuilder(EvalState & state, size_t size); - ListBuilder(ListBuilder && x) + // NOTE: Can be noexcept because we are just copying integral values and + // raw pointers. + ListBuilder(ListBuilder && x) noexcept : size(x.size) , inlineElems{x.inlineElems[0], x.inlineElems[1]} , elems(size <= 2 ? inlineElems : x.elems) diff --git a/src/libstore/remote-store-connection.hh b/src/libstore/remote-store-connection.hh index 513bd6838..f8549d0b2 100644 --- a/src/libstore/remote-store-connection.hh +++ b/src/libstore/remote-store-connection.hh @@ -40,7 +40,7 @@ struct RemoteStore::ConnectionHandle : handle(std::move(handle)) { } - ConnectionHandle(ConnectionHandle && h) + ConnectionHandle(ConnectionHandle && h) noexcept : handle(std::move(h.handle)) { } diff --git a/src/libstore/sqlite.hh b/src/libstore/sqlite.hh index 003e4d101..037380b71 100644 --- a/src/libstore/sqlite.hh +++ b/src/libstore/sqlite.hh @@ -42,7 +42,8 @@ struct SQLite SQLite(const Path & path, SQLiteOpenMode mode = SQLiteOpenMode::Normal); SQLite(const SQLite & from) = delete; SQLite& operator = (const SQLite & from) = delete; - SQLite& operator = (SQLite && from) { db = from.db; from.db = 0; return *this; } + // NOTE: This is noexcept since we are only copying and assigning raw pointers. + SQLite& operator = (SQLite && from) noexcept { db = from.db; from.db = 0; return *this; } ~SQLite(); operator sqlite3 * () { return db; } diff --git a/src/libutil/callback.hh b/src/libutil/callback.hh index 3710d1239..26c386d80 100644 --- a/src/libutil/callback.hh +++ b/src/libutil/callback.hh @@ -21,7 +21,9 @@ public: Callback(std::function)> fun) : fun(fun) { } - Callback(Callback && callback) : fun(std::move(callback.fun)) + // NOTE: std::function is noexcept move-constructible since C++20. + Callback(Callback && callback) noexcept(std::is_nothrow_move_constructible_v) + : fun(std::move(callback.fun)) { auto prev = callback.done.test_and_set(); if (prev) done.test_and_set(); diff --git a/src/libutil/file-descriptor.cc b/src/libutil/file-descriptor.cc index 3d8d70fdb..542c33f3b 100644 --- a/src/libutil/file-descriptor.cc +++ b/src/libutil/file-descriptor.cc @@ -45,8 +45,9 @@ AutoCloseFD::AutoCloseFD() : fd{INVALID_DESCRIPTOR} {} AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {} - -AutoCloseFD::AutoCloseFD(AutoCloseFD && that) : fd{that.fd} +// NOTE: This can be noexcept since we are just copying a value and resetting +// the file descriptor in the rhs. +AutoCloseFD::AutoCloseFD(AutoCloseFD && that) noexcept : fd{that.fd} { that.fd = INVALID_DESCRIPTOR; } diff --git a/src/libutil/file-descriptor.hh b/src/libutil/file-descriptor.hh index bc8602e5c..fde362999 100644 --- a/src/libutil/file-descriptor.hh +++ b/src/libutil/file-descriptor.hh @@ -155,7 +155,7 @@ public: AutoCloseFD(); AutoCloseFD(Descriptor fd); AutoCloseFD(const AutoCloseFD & fd) = delete; - AutoCloseFD(AutoCloseFD&& fd); + AutoCloseFD(AutoCloseFD&& fd) noexcept; ~AutoCloseFD(); AutoCloseFD& operator =(const AutoCloseFD & fd) = delete; AutoCloseFD& operator =(AutoCloseFD&& fd); diff --git a/src/libutil/finally.hh b/src/libutil/finally.hh index bda4227e6..2b25010a1 100644 --- a/src/libutil/finally.hh +++ b/src/libutil/finally.hh @@ -20,7 +20,11 @@ public: // Copying Finallys is definitely not a good idea and will cause them to be // called twice. Finally(Finally &other) = delete; - Finally(Finally &&other) : fun(std::move(other.fun)) { + // NOTE: Move constructor can be nothrow if the callable type is itself nothrow + // move-constructible. + Finally(Finally && other) noexcept(std::is_nothrow_move_constructible_v) + : fun(std::move(other.fun)) + { other.movedFrom = true; } ~Finally() noexcept(false) diff --git a/src/libutil/pool.hh b/src/libutil/pool.hh index 6247b6125..b2ceb7143 100644 --- a/src/libutil/pool.hh +++ b/src/libutil/pool.hh @@ -109,7 +109,15 @@ public: Handle(Pool & pool, std::shared_ptr r) : pool(pool), r(r) { } public: - Handle(Handle && h) : pool(h.pool), r(h.r) { h.r.reset(); } + // NOTE: Copying std::shared_ptr and calling a .reset() on it is always noexcept. + Handle(Handle && h) noexcept + : pool(h.pool) + , r(h.r) + { + static_assert(noexcept(h.r.reset())); + static_assert(noexcept(std::shared_ptr(h.r))); + h.r.reset(); + } Handle(const Handle & l) = delete;