diff --git a/NEWS b/NEWS
index 2e86cc75e..e1a0a770a 100644
--- a/NEWS
+++ b/NEWS
@@ -9,9 +9,12 @@ ver 0.21 (not yet released)
 * output
   - alsa: non-blocking mode
 
-ver 0.20.7 (not yet released)
+ver 0.20.7 (2017/05/15)
 * database
   - simple: fix false positive directory loop detection with NFS
+* enforce a reasonable minimum audio_buffer_size setting
+* cap buffer_before_play at 80% to prevent deadlock
+* fix random crashes when compiled with clang
 
 ver 0.20.6 (2017/03/10)
 * input
diff --git a/README.md b/README.md
index c80ccbf2f..ea588710d 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ For basic installation instructions
 - [Manual](http://www.musicpd.org/doc/user/)
 - [Forum](http://forum.musicpd.org/)
 - [IRC](irc://chat.freenode.net/#mpd)
-- [Bug tracker](http://bugs.musicpd.org/)
+- [Bug tracker](https://github.com/MusicPlayerDaemon/MPD/issues/)
 
 # Developers
 
diff --git a/doc/developer.xml b/doc/developer.xml
index d0a3f301a..ee94c2d55 100644
--- a/doc/developer.xml
+++ b/doc/developer.xml
@@ -97,20 +97,20 @@ Foo(const char *abc, int xyz)
 
     <para>
       MPD sources are managed in a git repository on <ulink
-      url="http://git.musicpd.org/">git.musicpd.org</ulink>.
+      url="https://github.com/MusicPlayerDaemon/">GitHub</ulink>.
     </para>
 
     <para>
       Always write your code against the latest git:
     </para>
 
-    <programlisting>git clone git://git.musicpd.org/master/mpd.git</programlisting>
+    <programlisting>git clone git://github.com/MusicPlayerDaemon/MPD</programlisting>
 
     <para>
       If you already have a clone, update it:
     </para>
 
-    <programlisting>git pull --rebase git://git.musicpd.org/master/mpd.git master</programlisting>
+    <programlisting>git pull --rebase git://github.com/MusicPlayerDaemon/MPD master</programlisting>
 
     <para>
       You can do without "--rebase", but we recommend that you rebase
@@ -188,17 +188,7 @@ Foo(const char *abc, int xyz)
     </para>
 
     <para>
-      <command>git pull</command> requests are preferred.  Regular
-      contributors can get <ulink
-      url="http://git.musicpd.org/account-policy.html">an account on
-      git.musicpd.org</ulink>, but any public git repository will do.
-    </para>
-
-    <para>
-      There is <ulink url="https://github.com/MaxKellermann/MPD">a
-      mirror of the <application>MPD</application> git repository on
-      GitHub</ulink>, and you can use that as well to submit pull
-      requests.
+      <command>git pull</command> requests are preferred.
     </para>
   </chapter>
 
diff --git a/doc/mpd.1 b/doc/mpd.1
index 5bc613fd4..5d2634570 100644
--- a/doc/mpd.1
+++ b/doc/mpd.1
@@ -48,7 +48,7 @@ mpd.conf(5), mpc(1)
 .SH BUGS
 If you find a bug, please report it at
 .br
-<\fBhttp://bugs.musicpd.org/bug_report_page.php\fP>.
+<\fBhttps://github.com/MusicPlayerDaemon/MPD/issues/\fP>.
 .SH AUTHORS
 Max Kellermann <max.kellermann@gmail.com>
 
diff --git a/doc/user.xml b/doc/user.xml
index 97152394d..9a93123f3 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -1857,7 +1857,7 @@ buffer_size: 16384</programlisting>
       <para>
         If you believe you found a bug in
         <application>MPD</application>, report it on <ulink
-        url="https://bugs.musicpd.org/my_view_page.php">the bug
+        url="https://github.com/MusicPlayerDaemon/MPD/issues/">the bug
         tracker</ulink>.
       </para>
 
diff --git a/src/AudioFormat.cxx b/src/AudioFormat.cxx
index 9a9f8ab5e..f317d8abe 100644
--- a/src/AudioFormat.cxx
+++ b/src/AudioFormat.cxx
@@ -24,7 +24,7 @@
 #include <stdio.h>
 
 void
-AudioFormat::ApplyMask(AudioFormat mask)
+AudioFormat::ApplyMask(AudioFormat mask) noexcept
 {
 	assert(IsValid());
 	assert(mask.IsMaskValid());
@@ -42,7 +42,7 @@ AudioFormat::ApplyMask(AudioFormat mask)
 }
 
 StringBuffer<24>
-ToString(const AudioFormat af)
+ToString(const AudioFormat af) noexcept
 {
 	StringBuffer<24> buffer;
 
diff --git a/src/AudioFormat.hxx b/src/AudioFormat.hxx
index e48d2c8cf..04c682b54 100644
--- a/src/AudioFormat.hxx
+++ b/src/AudioFormat.hxx
@@ -124,7 +124,7 @@ struct AudioFormat {
 		return !(*this == other);
 	}
 
-	void ApplyMask(AudioFormat mask);
+	void ApplyMask(AudioFormat mask) noexcept;
 
 	gcc_pure
 	AudioFormat WithMask(AudioFormat mask) const {
@@ -223,6 +223,6 @@ AudioFormat::GetTimeToSize() const
  */
 gcc_const
 StringBuffer<24>
-ToString(AudioFormat af);
+ToString(AudioFormat af) noexcept;
 
 #endif
diff --git a/src/AudioParser.hxx b/src/AudioParser.hxx
index 6923dbad5..36c36740a 100644
--- a/src/AudioParser.hxx
+++ b/src/AudioParser.hxx
@@ -25,8 +25,6 @@
 #ifndef MPD_AUDIO_PARSER_HXX
 #define MPD_AUDIO_PARSER_HXX
 
-#include "Compiler.h"
-
 struct AudioFormat;
 
 /**
@@ -38,7 +36,6 @@ struct AudioFormat;
  * @param src the input string
  * @param mask if true, then "*" is allowed for any number of items
  */
-gcc_pure
 AudioFormat
 ParseAudioFormat(const char *src, bool mask);
 
diff --git a/src/DetachedSong.cxx b/src/DetachedSong.cxx
index 6ed08cd14..8c5ff5371 100644
--- a/src/DetachedSong.cxx
+++ b/src/DetachedSong.cxx
@@ -45,19 +45,19 @@ DetachedSong::operator LightSong() const
 }
 
 bool
-DetachedSong::IsRemote() const
+DetachedSong::IsRemote() const noexcept
 {
 	return uri_has_scheme(GetRealURI());
 }
 
 bool
-DetachedSong::IsAbsoluteFile() const
+DetachedSong::IsAbsoluteFile() const noexcept
 {
 	return PathTraitsUTF8::IsAbsolute(GetRealURI());
 }
 
 bool
-DetachedSong::IsInDatabase() const
+DetachedSong::IsInDatabase() const noexcept
 {
 	/* here, we use GetURI() and not GetRealURI() because
 	   GetRealURI() is never relative */
@@ -67,7 +67,7 @@ DetachedSong::IsInDatabase() const
 }
 
 SignedSongTime
-DetachedSong::GetDuration() const
+DetachedSong::GetDuration() const noexcept
 {
 	SongTime a = start_time, b = end_time;
 	if (!b.IsPositive()) {
diff --git a/src/DetachedSong.hxx b/src/DetachedSong.hxx
index fc8d7c4e6..c05ca82dd 100644
--- a/src/DetachedSong.hxx
+++ b/src/DetachedSong.hxx
@@ -111,7 +111,7 @@ public:
 	explicit operator LightSong() const;
 
 	gcc_pure
-	const char *GetURI() const {
+	const char *GetURI() const noexcept {
 		return uri.c_str();
 	}
 
@@ -125,7 +125,7 @@ public:
 	 * displayed URI?
 	 */
 	gcc_pure
-	bool HasRealURI() const {
+	bool HasRealURI() const noexcept {
 		return !real_uri.empty();
 	}
 
@@ -134,7 +134,7 @@ public:
 	 * GetURI().
 	 */
 	gcc_pure
-	const char *GetRealURI() const {
+	const char *GetRealURI() const noexcept {
 		return (HasRealURI() ? real_uri : uri).c_str();
 	}
 
@@ -148,19 +148,19 @@ public:
 	 * song.
 	 */
 	gcc_pure
-	bool IsSame(const DetachedSong &other) const {
+	bool IsSame(const DetachedSong &other) const noexcept {
 		return uri == other.uri &&
 			start_time == other.start_time &&
 			end_time == other.end_time;
 	}
 
 	gcc_pure gcc_nonnull_all
-	bool IsURI(const char *other_uri) const {
+	bool IsURI(const char *other_uri) const noexcept {
 		return uri == other_uri;
 	}
 
 	gcc_pure
-	bool IsRemote() const;
+	bool IsRemote() const noexcept;
 
 	gcc_pure
 	bool IsFile() const {
@@ -168,10 +168,10 @@ public:
 	}
 
 	gcc_pure
-	bool IsAbsoluteFile() const;
+	bool IsAbsoluteFile() const noexcept;
 
 	gcc_pure
-	bool IsInDatabase() const;
+	bool IsInDatabase() const noexcept;
 
 	const Tag &GetTag() const {
 		return tag;
@@ -226,7 +226,7 @@ public:
 	}
 
 	gcc_pure
-	SignedSongTime GetDuration() const;
+	SignedSongTime GetDuration() const noexcept;
 
 	/**
 	 * Update the #tag and #mtime.
diff --git a/src/IdleFlags.cxx b/src/IdleFlags.cxx
index 731b2075e..14ab6e51a 100644
--- a/src/IdleFlags.cxx
+++ b/src/IdleFlags.cxx
@@ -47,13 +47,13 @@ static const char *const idle_names[] = {
 };
 
 const char*const*
-idle_get_names(void)
+idle_get_names() noexcept
 {
         return idle_names;
 }
 
 unsigned
-idle_parse_name(const char *name)
+idle_parse_name(const char *name) noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
diff --git a/src/IdleFlags.hxx b/src/IdleFlags.hxx
index e6a221477..ab253f092 100644
--- a/src/IdleFlags.hxx
+++ b/src/IdleFlags.hxx
@@ -73,8 +73,9 @@ static constexpr unsigned IDLE_PARTITION = 0x2000;
 /**
  * Get idle names
  */
+gcc_const
 const char*const*
-idle_get_names();
+idle_get_names() noexcept;
 
 /**
  * Parse an idle name and return its mask.  Returns 0 if the given
@@ -82,6 +83,6 @@ idle_get_names();
  */
 gcc_nonnull_all gcc_pure
 unsigned
-idle_parse_name(const char *name);
+idle_parse_name(const char *name) noexcept;
 
 #endif
diff --git a/src/Instance.hxx b/src/Instance.hxx
index dfc3a79e9..04cb0a1e1 100644
--- a/src/Instance.hxx
+++ b/src/Instance.hxx
@@ -128,7 +128,6 @@ struct Instance final
 	 * DatabaseError if this MPD configuration has no database (no
 	 * music_directory was configured).
 	 */
-	gcc_pure
 	const Database &GetDatabaseOrThrow() const;
 #endif
 
diff --git a/src/Main.cxx b/src/Main.cxx
index be6d0ea7f..7a5e8cc62 100644
--- a/src/Main.cxx
+++ b/src/Main.cxx
@@ -116,7 +116,13 @@
 
 #include <limits.h>
 
-static constexpr unsigned DEFAULT_BUFFER_SIZE = 4096;
+static constexpr size_t KILOBYTE = 1024;
+static constexpr size_t MEGABYTE = 1024 * KILOBYTE;
+
+static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE;
+static constexpr size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32,
+						   64 * KILOBYTE);
+
 static constexpr unsigned DEFAULT_BUFFER_BEFORE_PLAY = 10;
 
 #ifdef ANDROID
@@ -129,7 +135,6 @@ struct Config {
 	ReplayGainConfig replay_gain;
 };
 
-gcc_const
 static Config
 LoadConfig()
 {
@@ -306,12 +311,17 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
 			FormatFatalError("buffer size \"%s\" is not a "
 					 "positive integer, line %i",
 					 param->value.c_str(), param->line);
-		buffer_size = tmp;
+		buffer_size = tmp * KILOBYTE;
+
+		if (buffer_size < MIN_BUFFER_SIZE) {
+			FormatWarning(config_domain, "buffer size %lu is too small, using %lu bytes instead",
+				      (unsigned long)buffer_size,
+				      (unsigned long)MIN_BUFFER_SIZE);
+			buffer_size = MIN_BUFFER_SIZE;
+		}
 	} else
 		buffer_size = DEFAULT_BUFFER_SIZE;
 
-	buffer_size *= 1024;
-
 	const unsigned buffered_chunks = buffer_size / CHUNK_SIZE;
 
 	if (buffered_chunks >= 1 << 15)
@@ -329,6 +339,19 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
 					 "than 100 percent, line %i",
 					 param->value.c_str(), param->line);
 		}
+
+		if (perc > 80) {
+			/* this upper limit should avoid deadlocks
+			   which can occur because the DecoderThread
+			   cannot ever fill the music buffer to
+			   exactly 100%; a few chunks always need to
+			   be available to generate silence in
+			   Player::SendSilence() */
+			FormatError(config_domain,
+				    "buffer_before_play is too large (%f%%), capping at 80%%; please fix your configuration",
+				    perc);
+			perc = 80;
+		}
 	} else
 		perc = DEFAULT_BUFFER_BEFORE_PLAY;
 
diff --git a/src/Mapper.cxx b/src/Mapper.cxx
index 5df4a962e..959e6836e 100644
--- a/src/Mapper.cxx
+++ b/src/Mapper.cxx
@@ -59,14 +59,14 @@ mapper_init(AllocatedPath &&_playlist_dir)
 }
 
 void
-mapper_finish()
+mapper_finish() noexcept
 {
 }
 
 #ifdef ENABLE_DATABASE
 
 AllocatedPath
-map_uri_fs(const char *uri)
+map_uri_fs(const char *uri) noexcept
 {
 	assert(uri != nullptr);
 	assert(*uri != '/');
@@ -86,7 +86,7 @@ map_uri_fs(const char *uri)
 }
 
 std::string
-map_fs_to_utf8(Path path_fs)
+map_fs_to_utf8(Path path_fs) noexcept
 {
 	if (path_fs.IsAbsolute()) {
 		if (instance->storage == nullptr)
@@ -109,13 +109,13 @@ map_fs_to_utf8(Path path_fs)
 #endif
 
 const AllocatedPath &
-map_spl_path()
+map_spl_path() noexcept
 {
 	return playlist_dir_fs;
 }
 
 AllocatedPath
-map_spl_utf8_to_fs(const char *name)
+map_spl_utf8_to_fs(const char *name) noexcept
 {
 	if (playlist_dir_fs.IsNull())
 		return AllocatedPath::Null();
diff --git a/src/Mapper.hxx b/src/Mapper.hxx
index befab774e..55731a6d8 100644
--- a/src/Mapper.hxx
+++ b/src/Mapper.hxx
@@ -37,7 +37,7 @@ void
 mapper_init(AllocatedPath &&playlist_dir);
 
 void
-mapper_finish();
+mapper_finish() noexcept;
 
 #ifdef ENABLE_DATABASE
 
@@ -48,7 +48,7 @@ mapper_finish();
  */
 gcc_pure
 AllocatedPath
-map_uri_fs(const char *uri);
+map_uri_fs(const char *uri) noexcept;
 
 /**
  * Maps a file system path (relative to the music directory or
@@ -60,7 +60,7 @@ map_uri_fs(const char *uri);
  */
 gcc_pure
 std::string
-map_fs_to_utf8(Path path_fs);
+map_fs_to_utf8(Path path_fs) noexcept;
 
 #endif
 
@@ -69,7 +69,7 @@ map_fs_to_utf8(Path path_fs);
  */
 gcc_const
 const AllocatedPath &
-map_spl_path();
+map_spl_path() noexcept;
 
 /**
  * Maps a playlist name (without the ".m3u" suffix) to a file system
@@ -79,6 +79,6 @@ map_spl_path();
  */
 gcc_pure
 AllocatedPath
-map_spl_utf8_to_fs(const char *name);
+map_spl_utf8_to_fs(const char *name) noexcept;
 
 #endif
diff --git a/src/MusicBuffer.cxx b/src/MusicBuffer.cxx
index defd0d2fc..2d08f42f1 100644
--- a/src/MusicBuffer.cxx
+++ b/src/MusicBuffer.cxx
@@ -23,19 +23,19 @@
 
 #include <assert.h>
 
-MusicBuffer::MusicBuffer(unsigned num_chunks)
+MusicBuffer::MusicBuffer(unsigned num_chunks) noexcept
 	:buffer(num_chunks) {
 }
 
 MusicChunk *
-MusicBuffer::Allocate()
+MusicBuffer::Allocate() noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 	return buffer.Allocate();
 }
 
 void
-MusicBuffer::Return(MusicChunk *chunk)
+MusicBuffer::Return(MusicChunk *chunk) noexcept
 {
 	assert(chunk != nullptr);
 
diff --git a/src/MusicBuffer.hxx b/src/MusicBuffer.hxx
index 108e2522c..1c51839e2 100644
--- a/src/MusicBuffer.hxx
+++ b/src/MusicBuffer.hxx
@@ -41,7 +41,7 @@ public:
 	 * @param num_chunks the number of #MusicChunk reserved in
 	 * this buffer
 	 */
-	MusicBuffer(unsigned num_chunks);
+	MusicBuffer(unsigned num_chunks) noexcept;
 
 #ifndef NDEBUG
 	/**
@@ -71,13 +71,13 @@ public:
 	 * @return an empty chunk or nullptr if there are no chunks
 	 * available
 	 */
-	MusicChunk *Allocate();
+	MusicChunk *Allocate() noexcept;
 
 	/**
 	 * Returns a chunk to the buffer.  It can be reused by
 	 * Allocate() then.
 	 */
-	void Return(MusicChunk *chunk);
+	void Return(MusicChunk *chunk) noexcept;
 };
 
 #endif
diff --git a/src/MusicChunk.cxx b/src/MusicChunk.cxx
index 55a9f98b1..581974ae4 100644
--- a/src/MusicChunk.cxx
+++ b/src/MusicChunk.cxx
@@ -31,7 +31,7 @@ MusicChunk::~MusicChunk()
 
 #ifndef NDEBUG
 bool
-MusicChunk::CheckFormat(const AudioFormat other_format) const
+MusicChunk::CheckFormat(const AudioFormat other_format) const noexcept
 {
 	assert(other_format.IsValid());
 
@@ -41,7 +41,7 @@ MusicChunk::CheckFormat(const AudioFormat other_format) const
 
 WritableBuffer<void>
 MusicChunk::Write(const AudioFormat af,
-		  SongTime data_time, uint16_t _bit_rate)
+		  SongTime data_time, uint16_t _bit_rate) noexcept
 {
 	assert(CheckFormat(af));
 	assert(length == 0 || audio_format.IsValid());
@@ -64,7 +64,7 @@ MusicChunk::Write(const AudioFormat af,
 }
 
 bool
-MusicChunk::Expand(const AudioFormat af, size_t _length)
+MusicChunk::Expand(const AudioFormat af, size_t _length) noexcept
 {
 	const size_t frame_size = af.GetFrameSize();
 
diff --git a/src/MusicChunk.hxx b/src/MusicChunk.hxx
index d572152cd..c5be179a9 100644
--- a/src/MusicChunk.hxx
+++ b/src/MusicChunk.hxx
@@ -111,7 +111,7 @@ struct MusicChunk {
 	 * specified audio_format.
 	 */
 	gcc_pure
-	bool CheckFormat(AudioFormat audio_format) const;
+	bool CheckFormat(AudioFormat audio_format) const noexcept;
 #endif
 
 	/**
@@ -127,7 +127,7 @@ struct MusicChunk {
 	 */
 	WritableBuffer<void> Write(AudioFormat af,
 				   SongTime data_time,
-				   uint16_t bit_rate);
+				   uint16_t bit_rate) noexcept;
 
 	/**
 	 * Increases the length of the chunk after the caller has written to
@@ -138,7 +138,7 @@ struct MusicChunk {
 	 * @param length the number of bytes which were appended
 	 * @return true if the chunk is full
 	 */
-	bool Expand(AudioFormat af, size_t length);
+	bool Expand(AudioFormat af, size_t length) noexcept;
 };
 
 #endif
diff --git a/src/MusicPipe.cxx b/src/MusicPipe.cxx
index c6128ce74..c82faa648 100644
--- a/src/MusicPipe.cxx
+++ b/src/MusicPipe.cxx
@@ -25,7 +25,7 @@
 #ifndef NDEBUG
 
 bool
-MusicPipe::Contains(const MusicChunk *chunk) const
+MusicPipe::Contains(const MusicChunk *chunk) const noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 
diff --git a/src/MusicPipe.hxx b/src/MusicPipe.hxx
index 65890580c..e9bebed6e 100644
--- a/src/MusicPipe.hxx
+++ b/src/MusicPipe.hxx
@@ -86,7 +86,7 @@ public:
 	 * Checks if the specified chunk is enqueued in the music pipe.
 	 */
 	gcc_pure
-	bool Contains(const MusicChunk *chunk) const;
+	bool Contains(const MusicChunk *chunk) const noexcept;
 #endif
 
 	/**
diff --git a/src/Partition.hxx b/src/Partition.hxx
index 4b571ee06..68b69aa0b 100644
--- a/src/Partition.hxx
+++ b/src/Partition.hxx
@@ -205,7 +205,6 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
 	 */
 	const Database *GetDatabase() const;
 
-	gcc_pure
 	const Database &GetDatabaseOrThrow() const;
 
 	/**
diff --git a/src/Permission.cxx b/src/Permission.cxx
index 39b33bf1d..e955c4ca5 100644
--- a/src/Permission.cxx
+++ b/src/Permission.cxx
@@ -49,7 +49,6 @@ static std::map<std::string, unsigned> permission_passwords;
 
 static unsigned permission_default;
 
-gcc_pure
 static unsigned
 ParsePermission(const char *p)
 {
diff --git a/src/ReplayGainInfo.cxx b/src/ReplayGainInfo.cxx
index 1f9f863ce..c7742d056 100644
--- a/src/ReplayGainInfo.cxx
+++ b/src/ReplayGainInfo.cxx
@@ -24,7 +24,7 @@
 #include <math.h>
 
 float
-ReplayGainTuple::CalculateScale(const ReplayGainConfig &config) const
+ReplayGainTuple::CalculateScale(const ReplayGainConfig &config) const noexcept
 {
 	float scale;
 
diff --git a/src/ReplayGainInfo.hxx b/src/ReplayGainInfo.hxx
index 413e2fb1d..4cdbbc0c6 100644
--- a/src/ReplayGainInfo.hxx
+++ b/src/ReplayGainInfo.hxx
@@ -40,23 +40,23 @@ struct ReplayGainTuple {
 	}
 
 	gcc_pure
-	float CalculateScale(const ReplayGainConfig &config) const;
+	float CalculateScale(const ReplayGainConfig &config) const noexcept;
 };
 
 struct ReplayGainInfo {
 	ReplayGainTuple track, album;
 
-	constexpr bool IsDefined() const {
+	constexpr bool IsDefined() const noexcept {
 		return track.IsDefined() || album.IsDefined();
 	}
 
-	const ReplayGainTuple &Get(ReplayGainMode mode) const {
+	const ReplayGainTuple &Get(ReplayGainMode mode) const noexcept {
 		return mode == ReplayGainMode::ALBUM
 			? (album.IsDefined() ? album : track)
 			: (track.IsDefined() ? track : album);
 	}
 
-	void Clear() {
+	void Clear() noexcept {
 		track.Clear();
 		album.Clear();
 	}
diff --git a/src/ReplayGainMode.cxx b/src/ReplayGainMode.cxx
index 0db40cc40..ddcec0450 100644
--- a/src/ReplayGainMode.cxx
+++ b/src/ReplayGainMode.cxx
@@ -25,7 +25,7 @@
 #include <string.h>
 
 const char *
-ToString(ReplayGainMode mode)
+ToString(ReplayGainMode mode) noexcept
 {
 	switch (mode) {
 	case ReplayGainMode::AUTO:
diff --git a/src/ReplayGainMode.hxx b/src/ReplayGainMode.hxx
index 37cbb2ab7..885151704 100644
--- a/src/ReplayGainMode.hxx
+++ b/src/ReplayGainMode.hxx
@@ -36,13 +36,12 @@ enum class ReplayGainMode : uint8_t {
  */
 gcc_pure
 const char *
-ToString(ReplayGainMode mode);
+ToString(ReplayGainMode mode) noexcept;
 
 /**
  * Parse a string to a #ReplayGainMode.  Throws std::runtime_error on
  * error.
  */
-gcc_pure
 ReplayGainMode
 FromString(const char *s);
 
diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx
index 61acefb85..ecda29617 100644
--- a/src/SongFilter.cxx
+++ b/src/SongFilter.cxx
@@ -39,7 +39,7 @@
 #define LOCATE_TAG_ANY_KEY      "any"
 
 unsigned
-locate_parse_type(const char *str)
+locate_parse_type(const char *str) noexcept
 {
 	if (StringEqualsCaseASCII(str, LOCATE_TAG_FILE_KEY) ||
 	    StringEqualsCaseASCII(str, LOCATE_TAG_FILE_KEY_OLD))
@@ -57,7 +57,6 @@ locate_parse_type(const char *str)
 	return tag_name_parse_i(str);
 }
 
-gcc_pure
 static AllocatedString<>
 ImportString(const char *p, bool fold_case)
 {
@@ -78,7 +77,7 @@ SongFilter::Item::Item(unsigned _tag, time_t _time)
 }
 
 bool
-SongFilter::Item::StringMatch(const char *s) const
+SongFilter::Item::StringMatch(const char *s) const noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
@@ -97,14 +96,14 @@ SongFilter::Item::StringMatch(const char *s) const
 }
 
 bool
-SongFilter::Item::Match(const TagItem &item) const
+SongFilter::Item::Match(const TagItem &item) const noexcept
 {
 	return (tag == LOCATE_TAG_ANY_TYPE || (unsigned)item.type == tag) &&
 		StringMatch(item.value);
 }
 
 bool
-SongFilter::Item::Match(const Tag &_tag) const
+SongFilter::Item::Match(const Tag &_tag) const noexcept
 {
 	bool visited_types[TAG_NUM_OF_ITEM_TYPES];
 	std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
@@ -140,7 +139,7 @@ SongFilter::Item::Match(const Tag &_tag) const
 }
 
 bool
-SongFilter::Item::Match(const DetachedSong &song) const
+SongFilter::Item::Match(const DetachedSong &song) const noexcept
 {
 	if (tag == LOCATE_TAG_BASE_TYPE)
 		return uri_is_child_or_same(value.c_str(), song.GetURI());
@@ -155,7 +154,7 @@ SongFilter::Item::Match(const DetachedSong &song) const
 }
 
 bool
-SongFilter::Item::Match(const LightSong &song) const
+SongFilter::Item::Match(const LightSong &song) const noexcept
 {
 	if (tag == LOCATE_TAG_BASE_TYPE) {
 		const auto uri = song.GetURI();
@@ -185,7 +184,7 @@ SongFilter::~SongFilter()
 
 gcc_pure
 static time_t
-ParseTimeStamp(const char *s)
+ParseTimeStamp(const char *s) noexcept
 {
 	assert(s != nullptr);
 
@@ -246,7 +245,7 @@ SongFilter::Parse(ConstBuffer<const char *> args, bool fold_case)
 }
 
 bool
-SongFilter::Match(const DetachedSong &song) const
+SongFilter::Match(const DetachedSong &song) const noexcept
 {
 	for (const auto &i : items)
 		if (!i.Match(song))
@@ -256,7 +255,7 @@ SongFilter::Match(const DetachedSong &song) const
 }
 
 bool
-SongFilter::Match(const LightSong &song) const
+SongFilter::Match(const LightSong &song) const noexcept
 {
 	for (const auto &i : items)
 		if (!i.Match(song))
@@ -266,7 +265,7 @@ SongFilter::Match(const LightSong &song) const
 }
 
 bool
-SongFilter::HasOtherThanBase() const
+SongFilter::HasOtherThanBase() const noexcept
 {
 	for (const auto &i : items)
 		if (i.GetTag() != LOCATE_TAG_BASE_TYPE)
@@ -276,7 +275,7 @@ SongFilter::HasOtherThanBase() const
 }
 
 const char *
-SongFilter::GetBase() const
+SongFilter::GetBase() const noexcept
 {
 	for (const auto &i : items)
 		if (i.GetTag() == LOCATE_TAG_BASE_TYPE)
diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx
index e8ffa7075..a0bb25d41 100644
--- a/src/SongFilter.hxx
+++ b/src/SongFilter.hxx
@@ -80,19 +80,19 @@ public:
 		}
 
 		gcc_pure gcc_nonnull(2)
-		bool StringMatch(const char *s) const;
+		bool StringMatch(const char *s) const noexcept;
 
 		gcc_pure
-		bool Match(const TagItem &tag_item) const;
+		bool Match(const TagItem &tag_item) const noexcept;
 
 		gcc_pure
-		bool Match(const Tag &tag) const;
+		bool Match(const Tag &tag) const noexcept;
 
 		gcc_pure
-		bool Match(const DetachedSong &song) const;
+		bool Match(const DetachedSong &song) const noexcept;
 
 		gcc_pure
-		bool Match(const LightSong &song) const;
+		bool Match(const LightSong &song) const noexcept;
 	};
 
 private:
@@ -112,20 +112,20 @@ public:
 	bool Parse(ConstBuffer<const char *> args, bool fold_case=false);
 
 	gcc_pure
-	bool Match(const Tag &tag) const;
+	bool Match(const Tag &tag) const noexcept;
 
 	gcc_pure
-	bool Match(const DetachedSong &song) const;
+	bool Match(const DetachedSong &song) const noexcept;
 
 	gcc_pure
-	bool Match(const LightSong &song) const;
+	bool Match(const LightSong &song) const noexcept;
 
-	const std::list<Item> &GetItems() const {
+	const std::list<Item> &GetItems() const noexcept {
 		return items;
 	}
 
 	gcc_pure
-	bool IsEmpty() const {
+	bool IsEmpty() const noexcept {
 		return items.empty();
 	}
 
@@ -133,7 +133,7 @@ public:
 	 * Is there at least one item with "fold case" enabled?
 	 */
 	gcc_pure
-	bool HasFoldCase() const {
+	bool HasFoldCase() const noexcept {
 		for (const auto &i : items)
 			if (i.GetFoldCase())
 				return true;
@@ -145,14 +145,14 @@ public:
 	 * Does this filter contain constraints other than "base"?
 	 */
 	gcc_pure
-	bool HasOtherThanBase() const;
+	bool HasOtherThanBase() const noexcept;
 
 	/**
 	 * Returns the "base" specification (if there is one) or
 	 * nullptr.
 	 */
 	gcc_pure
-	const char *GetBase() const;
+	const char *GetBase() const noexcept;
 };
 
 /**
@@ -160,6 +160,6 @@ public:
  */
 gcc_pure
 unsigned
-locate_parse_type(const char *str);
+locate_parse_type(const char *str) noexcept;
 
 #endif
diff --git a/src/StateFile.cxx b/src/StateFile.cxx
index 6be355431..fc858b332 100644
--- a/src/StateFile.cxx
+++ b/src/StateFile.cxx
@@ -50,7 +50,7 @@ StateFile::StateFile(AllocatedPath &&_path,
 }
 
 void
-StateFile::RememberVersions()
+StateFile::RememberVersions() noexcept
 {
 	prev_volume_version = sw_volume_state_get_hash();
 	prev_output_version = audio_output_state_get_version();
@@ -59,7 +59,7 @@ StateFile::RememberVersions()
 }
 
 bool
-StateFile::IsModified() const
+StateFile::IsModified() const noexcept
 {
 	return prev_volume_version != sw_volume_state_get_hash() ||
 		prev_output_version != audio_output_state_get_version() ||
diff --git a/src/StateFile.hxx b/src/StateFile.hxx
index c4ceb2abb..342a20c22 100644
--- a/src/StateFile.hxx
+++ b/src/StateFile.hxx
@@ -67,14 +67,14 @@ private:
 	/**
 	 * Save the current state versions for use with IsModified().
 	 */
-	void RememberVersions();
+	void RememberVersions() noexcept;
 
 	/**
 	 * Check if MPD's state was modified since the last
 	 * RememberVersions() call.
 	 */
 	gcc_pure
-	bool IsModified() const;
+	bool IsModified() const noexcept;
 
 	/* virtual methods from TimeoutMonitor */
 	void OnTimeout() override;
diff --git a/src/TagStream.cxx b/src/TagStream.cxx
index 27263f140..436904dc8 100644
--- a/src/TagStream.cxx
+++ b/src/TagStream.cxx
@@ -40,7 +40,7 @@
 gcc_pure
 static bool
 CheckDecoderPlugin(const DecoderPlugin &plugin,
-		   const char *suffix, const char *mime)
+		   const char *suffix, const char *mime) noexcept
 {
 	return (mime != nullptr && plugin.SupportsMimeType(mime)) ||
 		(suffix != nullptr && plugin.SupportsSuffix(suffix));
diff --git a/src/archive/ArchiveLookup.cxx b/src/archive/ArchiveLookup.cxx
index 07b73e147..f84d97f23 100644
--- a/src/archive/ArchiveLookup.cxx
+++ b/src/archive/ArchiveLookup.cxx
@@ -28,7 +28,7 @@
 
 gcc_pure
 static char *
-FindSlash(char *p, size_t i)
+FindSlash(char *p, size_t i) noexcept
 {
 	for (; i > 0; --i)
 		if (p[i] == '/')
@@ -39,7 +39,7 @@ FindSlash(char *p, size_t i)
 
 gcc_pure
 static const char *
-FindSuffix(const char *p, const char *i)
+FindSuffix(const char *p, const char *i) noexcept
 {
 	for (; i > p; --i) {
 		if (*i == '.')
diff --git a/src/archive/plugins/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx
index ee22290c2..3dc0b51c3 100644
--- a/src/archive/plugins/Bzip2ArchivePlugin.cxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx
@@ -93,7 +93,7 @@ public:
 	~Bzip2InputStream();
 
 	/* virtual methods from InputStream */
-	bool IsEOF() override;
+	bool IsEOF() noexcept override;
 	size_t Read(void *ptr, size_t size) override;
 
 private:
@@ -205,7 +205,7 @@ Bzip2InputStream::Read(void *ptr, size_t length)
 }
 
 bool
-Bzip2InputStream::IsEOF()
+Bzip2InputStream::IsEOF() noexcept
 {
 	return eof;
 }
diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx
index 7139da32d..9e4c4f16a 100644
--- a/src/archive/plugins/Iso9660ArchivePlugin.cxx
+++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx
@@ -162,7 +162,7 @@ public:
 	}
 
 	/* virtual methods from InputStream */
-	bool IsEOF() override;
+	bool IsEOF() noexcept override;
 	size_t Read(void *ptr, size_t size) override;
 };
 
@@ -213,7 +213,7 @@ Iso9660InputStream::Read(void *ptr, size_t read_size)
 }
 
 bool
-Iso9660InputStream::IsEOF()
+Iso9660InputStream::IsEOF() noexcept
 {
 	return offset == size;
 }
diff --git a/src/archive/plugins/ZzipArchivePlugin.cxx b/src/archive/plugins/ZzipArchivePlugin.cxx
index f9b2b3010..5ba087f48 100644
--- a/src/archive/plugins/ZzipArchivePlugin.cxx
+++ b/src/archive/plugins/ZzipArchivePlugin.cxx
@@ -116,7 +116,7 @@ struct ZzipInputStream final : public InputStream {
 	}
 
 	/* virtual methods from InputStream */
-	bool IsEOF() override;
+	bool IsEOF() noexcept override;
 	size_t Read(void *ptr, size_t size) override;
 	void Seek(offset_type offset) override;
 };
@@ -147,7 +147,7 @@ ZzipInputStream::Read(void *ptr, size_t read_size)
 }
 
 bool
-ZzipInputStream::IsEOF()
+ZzipInputStream::IsEOF() noexcept
 {
 	return offset_type(zzip_tell(file)) == size;
 }
diff --git a/src/client/Client.cxx b/src/client/Client.cxx
index 3819c6584..922e901ab 100644
--- a/src/client/Client.cxx
+++ b/src/client/Client.cxx
@@ -46,7 +46,7 @@ Client::GetPlayerControl()
 #ifdef ENABLE_DATABASE
 
 const Database *
-Client::GetDatabase() const
+Client::GetDatabase() const noexcept
 {
 	return partition->instance.GetDatabase();
 }
@@ -58,7 +58,7 @@ Client::GetDatabaseOrThrow() const
 }
 
 const Storage *
-Client::GetStorage() const
+Client::GetStorage() const noexcept
 {
 	return partition->instance.storage;
 }
diff --git a/src/client/Client.hxx b/src/client/Client.hxx
index 67cd1cfe0..762eccd18 100644
--- a/src/client/Client.hxx
+++ b/src/client/Client.hxx
@@ -166,7 +166,7 @@ public:
 	};
 
 	gcc_pure
-	bool IsSubscribed(const char *channel_name) const {
+	bool IsSubscribed(const char *channel_name) const noexcept {
 		return subscriptions.find(channel_name) != subscriptions.end();
 	}
 
@@ -211,16 +211,15 @@ public:
 	 * Wrapper for Instance::GetDatabase().
 	 */
 	gcc_pure
-	const Database *GetDatabase() const;
+	const Database *GetDatabase() const noexcept;
 
 	/**
 	 * Wrapper for Instance::GetDatabaseOrThrow().
 	 */
-	gcc_pure
 	const Database &GetDatabaseOrThrow() const;
 
 	gcc_pure
-	const Storage *GetStorage() const;
+	const Storage *GetStorage() const noexcept;
 
 private:
 	/* virtual methods from class BufferedSocket */
diff --git a/src/client/ClientMessage.cxx b/src/client/ClientMessage.cxx
index 145f706dd..da45fe643 100644
--- a/src/client/ClientMessage.cxx
+++ b/src/client/ClientMessage.cxx
@@ -23,14 +23,14 @@
 
 gcc_const
 static bool
-valid_channel_char(const char ch)
+valid_channel_char(const char ch) noexcept
 {
 	return IsAlphaNumericASCII(ch) ||
 		ch == '_' || ch == '-' || ch == '.' || ch == ':';
 }
 
 bool
-client_message_valid_channel_name(const char *name)
+client_message_valid_channel_name(const char *name) noexcept
 {
 	do {
 		if (!valid_channel_char(*name))
diff --git a/src/client/ClientMessage.hxx b/src/client/ClientMessage.hxx
index aef914dd7..b665cd65e 100644
--- a/src/client/ClientMessage.hxx
+++ b/src/client/ClientMessage.hxx
@@ -53,6 +53,6 @@ public:
 
 gcc_pure
 bool
-client_message_valid_channel_name(const char *name);
+client_message_valid_channel_name(const char *name) noexcept;
 
 #endif
diff --git a/src/command/CommandError.cxx b/src/command/CommandError.cxx
index c52eb86ca..8f5badb4d 100644
--- a/src/command/CommandError.cxx
+++ b/src/command/CommandError.cxx
@@ -54,7 +54,7 @@
 
 gcc_const
 static enum ack
-ToAck(PlaylistResult result)
+ToAck(PlaylistResult result) noexcept
 {
 	switch (result) {
 	case PlaylistResult::SUCCESS:
@@ -90,7 +90,7 @@ ToAck(PlaylistResult result)
 #ifdef ENABLE_DATABASE
 gcc_const
 static enum ack
-ToAck(DatabaseErrorCode code)
+ToAck(DatabaseErrorCode code) noexcept
 {
 	switch (code) {
 	case DatabaseErrorCode::DISABLED:
@@ -107,7 +107,7 @@ ToAck(DatabaseErrorCode code)
 
 gcc_pure
 static enum ack
-ToAck(std::exception_ptr ep)
+ToAck(std::exception_ptr ep) noexcept
 {
 	try {
 		std::rethrow_exception(ep);
diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx
index 898761de1..b7e4bbbbf 100644
--- a/src/command/FileCommands.cxx
+++ b/src/command/FileCommands.cxx
@@ -44,7 +44,7 @@
 
 gcc_pure
 static bool
-SkipNameFS(PathTraitsFS::const_pointer_type name_fs)
+SkipNameFS(PathTraitsFS::const_pointer_type name_fs) noexcept
 {
 	return name_fs[0] == '.' &&
 		(name_fs[1] == 0 ||
@@ -53,7 +53,7 @@ SkipNameFS(PathTraitsFS::const_pointer_type name_fs)
 
 gcc_pure
 static bool
-skip_path(Path name_fs)
+skip_path(Path name_fs) noexcept
 {
 	return name_fs.HasNewline();
 }
@@ -107,7 +107,7 @@ handle_listfiles_local(Response &r, Path path_fs)
 
 gcc_pure
 static bool
-IsValidName(const char *p)
+IsValidName(const char *p) noexcept
 {
 	if (!IsAlphaASCII(*p))
 		return false;
@@ -123,7 +123,7 @@ IsValidName(const char *p)
 
 gcc_pure
 static bool
-IsValidValue(const char *p)
+IsValidValue(const char *p) noexcept
 {
 	while (*p) {
 		const char ch = *p++;
diff --git a/src/command/NeighborCommands.cxx b/src/command/NeighborCommands.cxx
index 5601f1f2f..5e73cba08 100644
--- a/src/command/NeighborCommands.cxx
+++ b/src/command/NeighborCommands.cxx
@@ -29,7 +29,7 @@
 #include <string>
 
 bool
-neighbor_commands_available(const Instance &instance)
+neighbor_commands_available(const Instance &instance) noexcept
 {
 	return instance.neighbors != nullptr;
 }
diff --git a/src/command/NeighborCommands.hxx b/src/command/NeighborCommands.hxx
index fa021f313..9c383c599 100644
--- a/src/command/NeighborCommands.hxx
+++ b/src/command/NeighborCommands.hxx
@@ -30,7 +30,7 @@ class Response;
 
 gcc_pure
 bool
-neighbor_commands_available(const Instance &instance);
+neighbor_commands_available(const Instance &instance) noexcept;
 
 CommandResult
 handle_listneighbors(Client &client, Request request, Response &response);
diff --git a/src/command/PlaylistCommands.cxx b/src/command/PlaylistCommands.cxx
index 9aaa053c3..a8a9d8c57 100644
--- a/src/command/PlaylistCommands.cxx
+++ b/src/command/PlaylistCommands.cxx
@@ -39,7 +39,7 @@
 #include "util/ConstBuffer.hxx"
 
 bool
-playlist_commands_available()
+playlist_commands_available() noexcept
 {
 	return !map_spl_path().IsNull();
 }
diff --git a/src/command/PlaylistCommands.hxx b/src/command/PlaylistCommands.hxx
index ef72cce61..9a787a7d2 100644
--- a/src/command/PlaylistCommands.hxx
+++ b/src/command/PlaylistCommands.hxx
@@ -29,7 +29,7 @@ class Response;
 
 gcc_const
 bool
-playlist_commands_available();
+playlist_commands_available() noexcept;
 
 CommandResult
 handle_save(Client &client, Request request, Response &response);
diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx
index 5ea53fd67..d144c0a63 100644
--- a/src/command/StorageCommands.cxx
+++ b/src/command/StorageCommands.cxx
@@ -45,7 +45,7 @@
 
 gcc_pure
 static bool
-skip_path(const char *name_utf8)
+skip_path(const char *name_utf8) noexcept
 {
 	return strchr(name_utf8, '\n') != nullptr;
 }
diff --git a/src/config/Block.cxx b/src/config/Block.cxx
index b3da7ed88..723e5f6f0 100644
--- a/src/config/Block.cxx
+++ b/src/config/Block.cxx
@@ -68,7 +68,7 @@ ConfigBlock::~ConfigBlock()
 }
 
 const BlockParam *
-ConfigBlock::GetBlockParam(const char *name) const
+ConfigBlock::GetBlockParam(const char *name) const noexcept
 {
 	for (const auto &i : block_params) {
 		if (i.name == name) {
@@ -81,7 +81,8 @@ ConfigBlock::GetBlockParam(const char *name) const
 }
 
 const char *
-ConfigBlock::GetBlockValue(const char *name, const char *default_value) const
+ConfigBlock::GetBlockValue(const char *name,
+			   const char *default_value) const noexcept
 {
 	const BlockParam *bp = GetBlockParam(name);
 	if (bp == nullptr)
@@ -128,7 +129,6 @@ ConfigBlock::GetBlockValue(const char *name, unsigned default_value) const
 	return bp->GetUnsignedValue();
 }
 
-gcc_pure
 bool
 ConfigBlock::GetBlockValue(const char *name, bool default_value) const
 {
diff --git a/src/config/Block.hxx b/src/config/Block.hxx
index 96399e59f..edfa5a7d2 100644
--- a/src/config/Block.hxx
+++ b/src/config/Block.hxx
@@ -44,13 +44,10 @@ struct BlockParam {
 	BlockParam(const char *_name, const char *_value, int _line=-1)
 		:name(_name), value(_value), line(_line), used(false) {}
 
-	gcc_pure
 	int GetIntValue() const;
 
-	gcc_pure
 	unsigned GetUnsignedValue() const;
 
-	gcc_pure
 	bool GetBoolValue() const;
 };
 
@@ -101,11 +98,11 @@ struct ConfigBlock {
 	}
 
 	gcc_nonnull_all gcc_pure
-	const BlockParam *GetBlockParam(const char *_name) const;
+	const BlockParam *GetBlockParam(const char *_name) const noexcept;
 
 	gcc_pure
 	const char *GetBlockValue(const char *name,
-				  const char *default_value=nullptr) const;
+				  const char *default_value=nullptr) const noexcept;
 
 	/**
 	 * Same as config_get_path(), but looks up the setting in the
@@ -116,13 +113,10 @@ struct ConfigBlock {
 	AllocatedPath GetPath(const char *name,
 			      const char *default_value=nullptr) const;
 
-	gcc_pure
 	int GetBlockValue(const char *name, int default_value) const;
 
-	gcc_pure
 	unsigned GetBlockValue(const char *name, unsigned default_value) const;
 
-	gcc_pure
 	bool GetBlockValue(const char *name, bool default_value) const;
 };
 
diff --git a/src/config/ConfigGlobal.cxx b/src/config/ConfigGlobal.cxx
index ebb04039c..8425a2e6e 100644
--- a/src/config/ConfigGlobal.cxx
+++ b/src/config/ConfigGlobal.cxx
@@ -75,7 +75,7 @@ void config_global_check(void)
 }
 
 const ConfigParam *
-config_get_param(ConfigOption option)
+config_get_param(ConfigOption option) noexcept
 {
 	auto *param = config_data.params[unsigned(option)];
 	if (param != nullptr)
@@ -84,7 +84,7 @@ config_get_param(ConfigOption option)
 }
 
 const ConfigBlock *
-config_get_block(ConfigBlockOption option)
+config_get_block(ConfigBlockOption option) noexcept
 {
 	ConfigBlock *block = config_data.blocks[unsigned(option)];
 	if (block != nullptr)
@@ -110,7 +110,7 @@ config_find_block(ConfigBlockOption option, const char *key, const char *value)
 }
 
 const char *
-config_get_string(ConfigOption option, const char *default_value)
+config_get_string(ConfigOption option, const char *default_value) noexcept
 {
 	const auto *param = config_get_param(option);
 
diff --git a/src/config/ConfigGlobal.hxx b/src/config/ConfigGlobal.hxx
index 735649eae..89a4b7cad 100644
--- a/src/config/ConfigGlobal.hxx
+++ b/src/config/ConfigGlobal.hxx
@@ -48,11 +48,11 @@ ReadConfigFile(Path path);
 
 gcc_pure
 const ConfigParam *
-config_get_param(enum ConfigOption option);
+config_get_param(enum ConfigOption option) noexcept;
 
 gcc_pure
 const ConfigBlock *
-config_get_block(enum ConfigBlockOption option);
+config_get_block(enum ConfigBlockOption option) noexcept;
 
 /**
  * Find a block with a matching attribute.
@@ -61,20 +61,12 @@ config_get_block(enum ConfigBlockOption option);
  * @param key the attribute name
  * @param value the expected attribute value
  */
-gcc_pure
 const ConfigBlock *
 config_find_block(ConfigBlockOption option, const char *key, const char *value);
 
-/* Note on gcc_pure: Some of the functions declared pure are not
-   really pure in strict sense.  They have side effect such that they
-   validate parameter's value and signal an error if it's invalid.
-   However, if the argument was already validated or we don't care
-   about the argument at all, this may be ignored so in the end, we
-   should be fine with calling those functions pure.  */
-
-gcc_pure
 const char *
-config_get_string(enum ConfigOption option, const char *default_value=nullptr);
+config_get_string(enum ConfigOption option,
+		  const char *default_value=nullptr) noexcept;
 
 /**
  * Returns an optional configuration variable which contains an
@@ -86,11 +78,9 @@ config_get_string(enum ConfigOption option, const char *default_value=nullptr);
 AllocatedPath
 config_get_path(enum ConfigOption option);
 
-gcc_pure
 unsigned
 config_get_unsigned(enum ConfigOption option, unsigned default_value);
 
-gcc_pure
 static inline std::chrono::steady_clock::duration
 config_get_unsigned(ConfigOption option,
 		    std::chrono::steady_clock::duration default_value)
@@ -100,11 +90,9 @@ config_get_unsigned(ConfigOption option,
 	return std::chrono::steady_clock::duration(u);
 }
 
-gcc_pure
 unsigned
 config_get_positive(enum ConfigOption option, unsigned default_value);
 
-gcc_pure
 static inline std::chrono::steady_clock::duration
 config_get_positive(ConfigOption option,
 		    std::chrono::steady_clock::duration default_value)
@@ -114,7 +102,6 @@ config_get_positive(ConfigOption option,
 	return std::chrono::steady_clock::duration(u);
 }
 
-gcc_pure
 bool config_get_bool(enum ConfigOption option, bool default_value);
 
 #endif
diff --git a/src/config/ConfigOption.hxx b/src/config/ConfigOption.hxx
index efbf613d5..b29bf526b 100644
--- a/src/config/ConfigOption.hxx
+++ b/src/config/ConfigOption.hxx
@@ -102,13 +102,13 @@ enum class ConfigBlockOption {
  */
 gcc_pure
 enum ConfigOption
-ParseConfigOptionName(const char *name);
+ParseConfigOptionName(const char *name) noexcept;
 
 /**
  * @return #ConfigOption::MAX if not found
  */
 gcc_pure
 enum ConfigBlockOption
-ParseConfigBlockOptionName(const char *name);
+ParseConfigBlockOptionName(const char *name) noexcept;
 
 #endif
diff --git a/src/config/ConfigTemplates.cxx b/src/config/ConfigTemplates.cxx
index 54ceb5e04..683e30ccd 100644
--- a/src/config/ConfigTemplates.cxx
+++ b/src/config/ConfigTemplates.cxx
@@ -101,7 +101,7 @@ static_assert(n_config_block_templates == unsigned(ConfigBlockOption::MAX),
 gcc_pure
 static inline unsigned
 ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
-			const char *name)
+			const char *name) noexcept
 {
 	unsigned i = 0;
 	for (; i < count; ++i)
@@ -112,7 +112,7 @@ ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
 }
 
 ConfigOption
-ParseConfigOptionName(const char *name)
+ParseConfigOptionName(const char *name) noexcept
 {
 	return ConfigOption(ParseConfigTemplateName(config_param_templates,
 						    n_config_param_templates,
@@ -120,7 +120,7 @@ ParseConfigOptionName(const char *name)
 }
 
 ConfigBlockOption
-ParseConfigBlockOptionName(const char *name)
+ParseConfigBlockOptionName(const char *name) noexcept
 {
 	return ConfigBlockOption(ParseConfigTemplateName(config_block_templates,
 							 n_config_block_templates,
diff --git a/src/config/Param.hxx b/src/config/Param.hxx
index e0a4b9a19..50c514a19 100644
--- a/src/config/Param.hxx
+++ b/src/config/Param.hxx
@@ -71,7 +71,6 @@ struct ConfigParam {
 	 *
 	 * Throws #std::runtime_error on error.
 	 */
-	gcc_pure
 	AllocatedPath GetPath() const;
 };
 
diff --git a/src/db/DatabaseLock.hxx b/src/db/DatabaseLock.hxx
index cf551b7ac..4bcb17bc0 100644
--- a/src/db/DatabaseLock.hxx
+++ b/src/db/DatabaseLock.hxx
@@ -45,7 +45,7 @@ extern ThreadId db_mutex_holder;
  */
 gcc_pure
 static inline bool
-holding_db_lock(void)
+holding_db_lock() noexcept
 {
 	return db_mutex_holder.IsInside();
 }
diff --git a/src/db/DatabaseSong.hxx b/src/db/DatabaseSong.hxx
index 316d628b1..1265dbcec 100644
--- a/src/db/DatabaseSong.hxx
+++ b/src/db/DatabaseSong.hxx
@@ -31,7 +31,6 @@ class DetachedSong;
  * "Detach" the #Song object, i.e. convert it to a #DetachedSong
  * instance.
  */
-gcc_pure
 DetachedSong
 DatabaseDetachSong(const Storage *storage, const LightSong &song);
 
diff --git a/src/db/LightSong.cxx b/src/db/LightSong.cxx
index 5f78f101d..98e8a1001 100644
--- a/src/db/LightSong.cxx
+++ b/src/db/LightSong.cxx
@@ -21,7 +21,7 @@
 #include "tag/Tag.hxx"
 
 SignedSongTime
-LightSong::GetDuration() const
+LightSong::GetDuration() const noexcept
 {
 	SongTime a = start_time, b = end_time;
 	if (!b.IsPositive()) {
diff --git a/src/db/LightSong.hxx b/src/db/LightSong.hxx
index 737992703..599acba54 100644
--- a/src/db/LightSong.hxx
+++ b/src/db/LightSong.hxx
@@ -76,7 +76,7 @@ struct LightSong {
 	SongTime end_time;
 
 	gcc_pure
-	std::string GetURI() const {
+	std::string GetURI() const noexcept {
 		if (directory == nullptr)
 			return std::string(uri);
 
@@ -87,7 +87,7 @@ struct LightSong {
 	}
 
 	gcc_pure
-	SignedSongTime GetDuration() const;
+	SignedSongTime GetDuration() const noexcept;
 };
 
 #endif
diff --git a/src/db/PlaylistVector.cxx b/src/db/PlaylistVector.cxx
index 08a294cfb..26269b88b 100644
--- a/src/db/PlaylistVector.cxx
+++ b/src/db/PlaylistVector.cxx
@@ -26,7 +26,7 @@
 #include <assert.h>
 
 PlaylistVector::iterator
-PlaylistVector::find(const char *name)
+PlaylistVector::find(const char *name) noexcept
 {
 	assert(holding_db_lock());
 	assert(name != nullptr);
diff --git a/src/db/PlaylistVector.hxx b/src/db/PlaylistVector.hxx
index 20e943a59..5a7f9f973 100644
--- a/src/db/PlaylistVector.hxx
+++ b/src/db/PlaylistVector.hxx
@@ -31,7 +31,7 @@ protected:
 	 * Caller must lock the #db_mutex.
 	 */
 	gcc_pure
-	iterator find(const char *name);
+	iterator find(const char *name) noexcept;
 
 public:
 	using std::list<PlaylistInfo>::empty;
diff --git a/src/db/Registry.cxx b/src/db/Registry.cxx
index 27e3dd69d..71598c777 100644
--- a/src/db/Registry.cxx
+++ b/src/db/Registry.cxx
@@ -38,7 +38,7 @@ const DatabasePlugin *const database_plugins[] = {
 };
 
 const DatabasePlugin *
-GetDatabasePluginByName(const char *name)
+GetDatabasePluginByName(const char *name) noexcept
 {
 	for (auto i = database_plugins; *i != nullptr; ++i)
 		if (strcmp((*i)->name, name) == 0)
diff --git a/src/db/Registry.hxx b/src/db/Registry.hxx
index 1fca03dcc..71f107c42 100644
--- a/src/db/Registry.hxx
+++ b/src/db/Registry.hxx
@@ -32,6 +32,6 @@ extern const DatabasePlugin *const database_plugins[];
 
 gcc_pure
 const DatabasePlugin *
-GetDatabasePluginByName(const char *name);
+GetDatabasePluginByName(const char *name) noexcept;
 
 #endif
diff --git a/src/db/Selection.cxx b/src/db/Selection.cxx
index b15a3a587..bab9c9de8 100644
--- a/src/db/Selection.cxx
+++ b/src/db/Selection.cxx
@@ -34,19 +34,19 @@ DatabaseSelection::DatabaseSelection(const char *_uri, bool _recursive,
 }
 
 bool
-DatabaseSelection::IsEmpty() const
+DatabaseSelection::IsEmpty() const noexcept
 {
 	return uri.empty() && (filter == nullptr || filter->IsEmpty());
 }
 
 bool
-DatabaseSelection::HasOtherThanBase() const
+DatabaseSelection::HasOtherThanBase() const noexcept
 {
 	return filter != nullptr && filter->HasOtherThanBase();
 }
 
 bool
-DatabaseSelection::Match(const LightSong &song) const
+DatabaseSelection::Match(const LightSong &song) const noexcept
 {
 	return filter == nullptr || filter->Match(song);
 }
diff --git a/src/db/Selection.hxx b/src/db/Selection.hxx
index 1ace52c8d..633f858c5 100644
--- a/src/db/Selection.hxx
+++ b/src/db/Selection.hxx
@@ -45,16 +45,16 @@ struct DatabaseSelection {
 			  const SongFilter *_filter=nullptr);
 
 	gcc_pure
-	bool IsEmpty() const;
+	bool IsEmpty() const noexcept;
 
 	/**
 	 * Does this selection contain constraints other than "base"?
 	 */
 	gcc_pure
-	bool HasOtherThanBase() const;
+	bool HasOtherThanBase() const noexcept;
 
 	gcc_pure
-	bool Match(const LightSong &song) const;
+	bool Match(const LightSong &song) const noexcept;
 };
 
 #endif
diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx
index 985fce35a..9c086d93e 100644
--- a/src/db/plugins/ProxyDatabasePlugin.cxx
+++ b/src/db/plugins/ProxyDatabasePlugin.cxx
@@ -220,7 +220,7 @@ ProxySong::ProxySong(const mpd_song *song)
 
 gcc_const
 static enum mpd_tag_type
-Convert(TagType tag_type)
+Convert(TagType tag_type) noexcept
 {
 	for (auto i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
 		if (i->d == tag_type)
@@ -578,7 +578,7 @@ Visit(struct mpd_connection *connection,
 
 gcc_pure
 static bool
-Match(const SongFilter *filter, const LightSong &song)
+Match(const SongFilter *filter, const LightSong &song) noexcept
 {
 	return filter == nullptr || filter->Match(song);
 }
@@ -721,7 +721,7 @@ SearchSongs(struct mpd_connection *connection,
  */
 gcc_pure
 static bool
-ServerSupportsSearchBase(const struct mpd_connection *connection)
+ServerSupportsSearchBase(const struct mpd_connection *connection) noexcept
 {
 #if LIBMPDCLIENT_CHECK_VERSION(2,9,0)
 	return mpd_connection_cmp_server_version(connection, 0, 18, 0) >= 0;
diff --git a/src/db/plugins/simple/Directory.cxx b/src/db/plugins/simple/Directory.cxx
index afd1da96c..7d1ca5afa 100644
--- a/src/db/plugins/simple/Directory.cxx
+++ b/src/db/plugins/simple/Directory.cxx
@@ -62,7 +62,7 @@ Directory::Delete()
 }
 
 const char *
-Directory::GetName() const
+Directory::GetName() const noexcept
 {
 	assert(!IsRoot());
 
@@ -86,7 +86,7 @@ Directory::CreateChild(const char *name_utf8)
 }
 
 const Directory *
-Directory::FindChild(const char *name) const
+Directory::FindChild(const char *name) const noexcept
 {
 	assert(holding_db_lock());
 
@@ -98,7 +98,7 @@ Directory::FindChild(const char *name) const
 }
 
 void
-Directory::PruneEmpty()
+Directory::PruneEmpty() noexcept
 {
 	assert(holding_db_lock());
 
@@ -115,7 +115,7 @@ Directory::PruneEmpty()
 }
 
 Directory::LookupResult
-Directory::LookupDirectory(const char *uri)
+Directory::LookupDirectory(const char *uri) noexcept
 {
 	assert(holding_db_lock());
 	assert(uri != nullptr);
@@ -170,7 +170,7 @@ Directory::AddSong(Song *song)
 }
 
 void
-Directory::RemoveSong(Song *song)
+Directory::RemoveSong(Song *song) noexcept
 {
 	assert(holding_db_lock());
 	assert(song != nullptr);
@@ -180,7 +180,7 @@ Directory::RemoveSong(Song *song)
 }
 
 const Song *
-Directory::FindSong(const char *name_utf8) const
+Directory::FindSong(const char *name_utf8) const noexcept
 {
 	assert(holding_db_lock());
 	assert(name_utf8 != nullptr);
@@ -197,13 +197,13 @@ Directory::FindSong(const char *name_utf8) const
 
 gcc_pure
 static bool
-directory_cmp(const Directory &a, const Directory &b)
+directory_cmp(const Directory &a, const Directory &b) noexcept
 {
 	return IcuCollate(a.path.c_str(), b.path.c_str()) < 0;
 }
 
 void
-Directory::Sort()
+Directory::Sort() noexcept
 {
 	assert(holding_db_lock());
 
@@ -258,7 +258,7 @@ Directory::Walk(bool recursive, const SongFilter *filter,
 }
 
 LightDirectory
-Directory::Export() const
+Directory::Export() const noexcept
 {
 	return LightDirectory(GetPath(), mtime);
 }
diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx
index 980ac7615..9a5092631 100644
--- a/src/db/plugins/simple/Directory.hxx
+++ b/src/db/plugins/simple/Directory.hxx
@@ -134,10 +134,10 @@ public:
 	 * Caller must lock the #db_mutex.
 	 */
 	gcc_pure
-	const Directory *FindChild(const char *name) const;
+	const Directory *FindChild(const char *name) const noexcept;
 
 	gcc_pure
-	Directory *FindChild(const char *name) {
+	Directory *FindChild(const char *name) noexcept {
 		const Directory *cthis = this;
 		return const_cast<Directory *>(cthis->FindChild(name));
 	}
@@ -177,10 +177,10 @@ public:
 	 * @return the Directory, or nullptr if none was found
 	 */
 	gcc_pure
-	LookupResult LookupDirectory(const char *uri);
+	LookupResult LookupDirectory(const char *uri) noexcept;
 
 	gcc_pure
-	bool IsEmpty() const {
+	bool IsEmpty() const noexcept {
 		return children.empty() &&
 			songs.empty() &&
 			playlists.empty();
@@ -195,13 +195,13 @@ public:
 	 * Returns the base name of the directory.
 	 */
 	gcc_pure
-	const char *GetName() const;
+	const char *GetName() const noexcept;
 
 	/**
 	 * Is this the root directory of the music database?
 	 */
 	gcc_pure
-	bool IsRoot() const {
+	bool IsRoot() const noexcept {
 		return parent == nullptr;
 	}
 
@@ -229,10 +229,10 @@ public:
 	 * Caller must lock the #db_mutex.
 	 */
 	gcc_pure
-	const Song *FindSong(const char *name_utf8) const;
+	const Song *FindSong(const char *name_utf8) const noexcept;
 
 	gcc_pure
-	Song *FindSong(const char *name_utf8) {
+	Song *FindSong(const char *name_utf8) noexcept {
 		const Directory *cthis = this;
 		return const_cast<Song *>(cthis->FindSong(name_utf8));
 	}
@@ -248,19 +248,19 @@ public:
 	 * invalidates the song object, because the "parent" attribute becomes
 	 * stale), but does not free it.
 	 */
-	void RemoveSong(Song *song);
+	void RemoveSong(Song *song) noexcept;
 
 	/**
 	 * Caller must lock the #db_mutex.
 	 */
-	void PruneEmpty();
+	void PruneEmpty() noexcept;
 
 	/**
 	 * Sort all directory entries recursively.
 	 *
 	 * Caller must lock the #db_mutex.
 	 */
-	void Sort();
+	void Sort() noexcept;
 
 	/**
 	 * Caller must lock #db_mutex.
@@ -270,7 +270,7 @@ public:
 		  VisitPlaylist visit_playlist) const;
 
 	gcc_pure
-	LightDirectory Export() const;
+	LightDirectory Export() const noexcept;
 };
 
 #endif
diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx
index 8272985e7..e1f83bf5b 100644
--- a/src/db/plugins/simple/DirectorySave.cxx
+++ b/src/db/plugins/simple/DirectorySave.cxx
@@ -40,7 +40,7 @@
 
 gcc_const
 static const char *
-DeviceToTypeString(unsigned device)
+DeviceToTypeString(unsigned device) noexcept
 {
 	switch (device) {
 	case DEVICE_INARCHIVE:
@@ -56,7 +56,7 @@ DeviceToTypeString(unsigned device)
 
 gcc_pure
 static unsigned
-ParseTypeString(const char *type)
+ParseTypeString(const char *type) noexcept
 {
 	if (strcmp(type, "archive") == 0)
 		return DEVICE_INARCHIVE;
diff --git a/src/db/plugins/simple/Song.cxx b/src/db/plugins/simple/Song.cxx
index 45c8c67fe..54a9c95ff 100644
--- a/src/db/plugins/simple/Song.cxx
+++ b/src/db/plugins/simple/Song.cxx
@@ -77,7 +77,7 @@ Song::Free()
 }
 
 std::string
-Song::GetURI() const
+Song::GetURI() const noexcept
 {
 	assert(*uri);
 
@@ -96,7 +96,7 @@ Song::GetURI() const
 }
 
 LightSong
-Song::Export() const
+Song::Export() const noexcept
 {
 	LightSong dest;
 	dest.directory = parent->IsRoot()
diff --git a/src/db/plugins/simple/Song.hxx b/src/db/plugins/simple/Song.hxx
index 85f9f2867..2fa952a35 100644
--- a/src/db/plugins/simple/Song.hxx
+++ b/src/db/plugins/simple/Song.hxx
@@ -123,10 +123,10 @@ struct Song {
 	 * location within the music directory.
 	 */
 	gcc_pure
-	std::string GetURI() const;
+	std::string GetURI() const noexcept;
 
 	gcc_pure
-	LightSong Export() const;
+	LightSong Export() const noexcept;
 };
 
 typedef boost::intrusive::list<Song,
diff --git a/src/db/plugins/simple/SongSort.cxx b/src/db/plugins/simple/SongSort.cxx
index e383f44ab..57fe9430b 100644
--- a/src/db/plugins/simple/SongSort.cxx
+++ b/src/db/plugins/simple/SongSort.cxx
@@ -26,7 +26,7 @@
 #include <stdlib.h>
 
 static int
-compare_utf8_string(const char *a, const char *b)
+compare_utf8_string(const char *a, const char *b) noexcept
 {
 	if (a == nullptr)
 		return b == nullptr ? 0 : -1;
@@ -42,8 +42,7 @@ compare_utf8_string(const char *a, const char *b)
  * nullptr.
  */
 static int
-compare_string_tag_item(const Tag &a, const Tag &b,
-			TagType type)
+compare_string_tag_item(const Tag &a, const Tag &b, TagType type) noexcept
 {
 	return compare_utf8_string(a.GetValue(type),
 				   b.GetValue(type));
@@ -54,7 +53,7 @@ compare_string_tag_item(const Tag &a, const Tag &b,
  * (e.g. disc or track number).  Either one may be nullptr.
  */
 static int
-compare_number_string(const char *a, const char *b)
+compare_number_string(const char *a, const char *b) noexcept
 {
 	long ai = a == nullptr ? 0 : strtol(a, nullptr, 10);
 	long bi = b == nullptr ? 0 : strtol(b, nullptr, 10);
@@ -69,7 +68,7 @@ compare_number_string(const char *a, const char *b)
 }
 
 static int
-compare_tag_item(const Tag &a, const Tag &b, TagType type)
+compare_tag_item(const Tag &a, const Tag &b, TagType type) noexcept
 {
 	return compare_number_string(a.GetValue(type),
 				     b.GetValue(type));
@@ -78,7 +77,7 @@ compare_tag_item(const Tag &a, const Tag &b, TagType type)
 /* Only used for sorting/searchin a songvec, not general purpose compares */
 gcc_pure
 static bool
-song_cmp(const Song &a, const Song &b)
+song_cmp(const Song &a, const Song &b) noexcept
 {
 	int ret;
 
@@ -102,7 +101,7 @@ song_cmp(const Song &a, const Song &b)
 }
 
 void
-song_list_sort(SongList &songs)
+song_list_sort(SongList &songs) noexcept
 {
 	songs.sort(song_cmp);
 }
diff --git a/src/db/plugins/simple/SongSort.hxx b/src/db/plugins/simple/SongSort.hxx
index 23acb7506..e1c1ae1fa 100644
--- a/src/db/plugins/simple/SongSort.hxx
+++ b/src/db/plugins/simple/SongSort.hxx
@@ -23,6 +23,6 @@
 #include "Song.hxx"
 
 void
-song_list_sort(SongList &songs);
+song_list_sort(SongList &songs) noexcept;
 
 #endif
diff --git a/src/db/plugins/upnp/Directory.cxx b/src/db/plugins/upnp/Directory.cxx
index 806f49c1a..d82cdcbae 100644
--- a/src/db/plugins/upnp/Directory.cxx
+++ b/src/db/plugins/upnp/Directory.cxx
@@ -39,7 +39,7 @@ UPnPDirContent::~UPnPDirContent()
 
 gcc_pure
 static UPnPDirObject::ItemClass
-ParseItemClass(StringView name)
+ParseItemClass(StringView name) noexcept
 {
 	if (name.EqualsLiteral("object.item.audioItem.musicTrack"))
 		return UPnPDirObject::ItemClass::MUSIC;
@@ -51,7 +51,7 @@ ParseItemClass(StringView name)
 
 gcc_pure
 static SignedSongTime
-ParseDuration(const char *duration)
+ParseDuration(const char *duration) noexcept
 {
 	char *endptr;
 
@@ -81,7 +81,7 @@ ParseDuration(const char *duration)
  */
 gcc_pure
 static std::string &&
-TitleToPathSegment(std::string &&s)
+TitleToPathSegment(std::string &&s) noexcept
 {
 	std::replace(s.begin(), s.end(), '/', '_');
 	return std::move(s);
diff --git a/src/db/plugins/upnp/Directory.hxx b/src/db/plugins/upnp/Directory.hxx
index f8427d513..23d01039c 100644
--- a/src/db/plugins/upnp/Directory.hxx
+++ b/src/db/plugins/upnp/Directory.hxx
@@ -40,7 +40,7 @@ public:
 	~UPnPDirContent();
 
 	gcc_pure
-	UPnPDirObject *FindObject(const char *name) {
+	UPnPDirObject *FindObject(const char *name) noexcept {
 		for (auto &o : objects)
 			if (o.name == name)
 				return &o;
diff --git a/src/db/update/InotifyQueue.cxx b/src/db/update/InotifyQueue.cxx
index e097dda0b..d83d26612 100644
--- a/src/db/update/InotifyQueue.cxx
+++ b/src/db/update/InotifyQueue.cxx
@@ -56,7 +56,7 @@ InotifyQueue::OnTimeout()
 
 gcc_pure
 static bool
-path_in(const char *path, const char *possible_parent)
+path_in(const char *path, const char *possible_parent) noexcept
 {
 	if (StringIsEmpty(path))
 		return true;
diff --git a/src/db/update/InotifyUpdate.cxx b/src/db/update/InotifyUpdate.cxx
index 245a7bcb9..562315fa3 100644
--- a/src/db/update/InotifyUpdate.cxx
+++ b/src/db/update/InotifyUpdate.cxx
@@ -62,10 +62,10 @@ struct WatchDirectory {
 	WatchDirectory &operator=(const WatchDirectory &) = delete;
 
 	gcc_pure
-	unsigned GetDepth() const;
+	unsigned GetDepth() const noexcept;
 
 	gcc_pure
-	AllocatedPath GetUriFS() const;
+	AllocatedPath GetUriFS() const noexcept;
 };
 
 static InotifySource *inotify_source;
@@ -132,7 +132,7 @@ remove_watch_directory(WatchDirectory *directory)
 }
 
 AllocatedPath
-WatchDirectory::GetUriFS() const
+WatchDirectory::GetUriFS() const noexcept
 {
 	if (parent == nullptr)
 		return AllocatedPath::Null();
@@ -225,7 +225,7 @@ recursive_watch_subdirectories(WatchDirectory *directory,
 
 gcc_pure
 unsigned
-WatchDirectory::GetDepth() const
+WatchDirectory::GetDepth() const noexcept
 {
 	const WatchDirectory *d = this;
 	unsigned depth = 0;
@@ -331,7 +331,7 @@ mpd_inotify_init(EventLoop &loop, Storage &storage, UpdateService &update,
 }
 
 void
-mpd_inotify_finish(void)
+mpd_inotify_finish(void) noexcept
 {
 	if (inotify_source == nullptr)
 		return;
diff --git a/src/db/update/InotifyUpdate.hxx b/src/db/update/InotifyUpdate.hxx
index 8bef9016d..a58a38dcd 100644
--- a/src/db/update/InotifyUpdate.hxx
+++ b/src/db/update/InotifyUpdate.hxx
@@ -32,6 +32,6 @@ mpd_inotify_init(EventLoop &loop, Storage &storage, UpdateService &update,
 		 unsigned max_depth);
 
 void
-mpd_inotify_finish();
+mpd_inotify_finish() noexcept;
 
 #endif
diff --git a/src/db/update/UpdateIO.cxx b/src/db/update/UpdateIO.cxx
index 617a4f2f7..9680c06a0 100644
--- a/src/db/update/UpdateIO.cxx
+++ b/src/db/update/UpdateIO.cxx
@@ -32,7 +32,7 @@
 #include <errno.h>
 
 bool
-GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info)
+GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info) noexcept
 try {
 	info = storage.GetInfo(uri_utf8, true);
 	return true;
@@ -42,7 +42,7 @@ try {
 }
 
 bool
-GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info)
+GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info) noexcept
 try {
 	info = reader.GetInfo(true);
 	return true;
@@ -52,7 +52,7 @@ try {
 }
 
 bool
-DirectoryExists(Storage &storage, const Directory &directory)
+DirectoryExists(Storage &storage, const Directory &directory) noexcept
 {
 	StorageFileInfo info;
 
@@ -79,7 +79,7 @@ GetDirectoryChildInfo(Storage &storage, const Directory &directory,
 
 bool
 directory_child_is_regular(Storage &storage, const Directory &directory,
-			   const char *name_utf8)
+			   const char *name_utf8) noexcept
 try {
 	return GetDirectoryChildInfo(storage, directory, name_utf8)
 		.IsRegular();
@@ -89,7 +89,7 @@ try {
 
 bool
 directory_child_access(Storage &storage, const Directory &directory,
-		       const char *name, int mode)
+		       const char *name, int mode) noexcept
 {
 #ifdef WIN32
 	/* CheckAccess() is useless on WIN32 */
diff --git a/src/db/update/UpdateIO.hxx b/src/db/update/UpdateIO.hxx
index bf5e87c67..b9f43105a 100644
--- a/src/db/update/UpdateIO.hxx
+++ b/src/db/update/UpdateIO.hxx
@@ -33,23 +33,23 @@ class StorageDirectoryReader;
  * returning them.
  */
 bool
-GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info);
+GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info) noexcept;
 
 /**
  * Wrapper for LocalDirectoryReader::GetInfo() that logs errors
  * instead of returning them.
  */
 bool
-GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info);
+GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info) noexcept;
 
 gcc_pure
 bool
-DirectoryExists(Storage &storage, const Directory &directory);
+DirectoryExists(Storage &storage, const Directory &directory) noexcept;
 
 gcc_pure
 bool
 directory_child_is_regular(Storage &storage, const Directory &directory,
-			   const char *name_utf8);
+			   const char *name_utf8) noexcept;
 
 /**
  * Checks if the given permissions on the mapped file are given.
@@ -57,6 +57,6 @@ directory_child_is_regular(Storage &storage, const Directory &directory,
 gcc_pure
 bool
 directory_child_access(Storage &storage, const Directory &directory,
-		       const char *name, int mode);
+		       const char *name, int mode) noexcept;
 
 #endif
diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx
index fc3497b3a..03612d1cc 100644
--- a/src/db/update/Walk.cxx
+++ b/src/db/update/Walk.cxx
@@ -248,7 +248,7 @@ try {
 /* we don't look at "." / ".." nor files with newlines in their name */
 gcc_pure
 static bool
-skip_path(const char *name_utf8)
+skip_path(const char *name_utf8) noexcept
 {
 	return strchr(name_utf8, '\n') != nullptr;
 }
@@ -256,7 +256,7 @@ skip_path(const char *name_utf8)
 gcc_pure
 bool
 UpdateWalk::SkipSymlink(const Directory *directory,
-			const char *utf8_name) const
+			const char *utf8_name) const noexcept
 {
 #ifndef WIN32
 	const auto path_fs = storage.MapChildFS(directory->GetPath(),
diff --git a/src/db/update/Walk.hxx b/src/db/update/Walk.hxx
index e32b906d0..7d7a03db5 100644
--- a/src/db/update/Walk.hxx
+++ b/src/db/update/Walk.hxx
@@ -78,7 +78,7 @@ public:
 private:
 	gcc_pure
 	bool SkipSymlink(const Directory *directory,
-			 const char *utf8_name) const;
+			 const char *utf8_name) const noexcept;
 
 	void RemoveExcludedFromDirectory(Directory &directory,
 					 const ExcludeList &exclude_list);
diff --git a/src/decoder/Bridge.cxx b/src/decoder/Bridge.cxx
index 201e6a1aa..c24c80768 100644
--- a/src/decoder/Bridge.cxx
+++ b/src/decoder/Bridge.cxx
@@ -54,7 +54,7 @@ DecoderBridge::~DecoderBridge()
 }
 
 bool
-DecoderBridge::CheckCancelRead() const
+DecoderBridge::CheckCancelRead() const noexcept
 {
 	if (error)
 		/* this translates to DecoderCommand::STOP */
@@ -78,7 +78,7 @@ DecoderBridge::CheckCancelRead() const
  * one.
  */
 static DecoderCommand
-need_chunks(DecoderControl &dc)
+need_chunks(DecoderControl &dc) noexcept
 {
 	if (dc.command == DecoderCommand::NONE)
 		dc.Wait();
@@ -87,14 +87,14 @@ need_chunks(DecoderControl &dc)
 }
 
 static DecoderCommand
-LockNeedChunks(DecoderControl &dc)
+LockNeedChunks(DecoderControl &dc) noexcept
 {
 	const std::lock_guard<Mutex> protect(dc.mutex);
 	return need_chunks(dc);
 }
 
 MusicChunk *
-DecoderBridge::GetChunk()
+DecoderBridge::GetChunk() noexcept
 {
 	DecoderCommand cmd;
 
@@ -177,7 +177,7 @@ DecoderBridge::PrepareInitialSeek()
 }
 
 DecoderCommand
-DecoderBridge::GetVirtualCommand()
+DecoderBridge::GetVirtualCommand() noexcept
 {
 	if (error)
 		/* an error has occurred: stop the decoder plugin */
@@ -192,7 +192,7 @@ DecoderBridge::GetVirtualCommand()
 }
 
 DecoderCommand
-DecoderBridge::LockGetVirtualCommand()
+DecoderBridge::LockGetVirtualCommand() noexcept
 {
 	const std::lock_guard<Mutex> protect(dc.mutex);
 	return GetVirtualCommand();
diff --git a/src/decoder/Bridge.hxx b/src/decoder/Bridge.hxx
index 977f56083..8573d6a7f 100644
--- a/src/decoder/Bridge.hxx
+++ b/src/decoder/Bridge.hxx
@@ -114,7 +114,7 @@ public:
 	 * Caller must lock the #DecoderControl object.
 	 */
 	gcc_pure
-	bool CheckCancelRead() const;
+	bool CheckCancelRead() const noexcept;
 
 	/**
 	 * Returns the current chunk the decoder writes to, or allocates a new
@@ -122,7 +122,7 @@ public:
 	 *
 	 * @return the chunk, or NULL if we have received a decoder command
 	 */
-	MusicChunk *GetChunk();
+	MusicChunk *GetChunk() noexcept;
 
 	/**
 	 * Flushes the current chunk.
@@ -161,8 +161,8 @@ private:
 	 * "virtual" synthesized command, e.g. to seek to the
 	 * beginning of the CUE track.
 	 */
-	DecoderCommand GetVirtualCommand();
-	DecoderCommand LockGetVirtualCommand();
+	DecoderCommand GetVirtualCommand() noexcept;
+	DecoderCommand LockGetVirtualCommand() noexcept;
 
 	/**
 	 * Sends a #Tag as-is to the #MusicPipe.  Flushes the current
diff --git a/src/decoder/DecoderControl.cxx b/src/decoder/DecoderControl.cxx
index ca724fe36..bd0c87837 100644
--- a/src/decoder/DecoderControl.cxx
+++ b/src/decoder/DecoderControl.cxx
@@ -75,7 +75,7 @@ DecoderControl::SetReady(const AudioFormat audio_format,
 }
 
 bool
-DecoderControl::IsCurrentSong(const DetachedSong &_song) const
+DecoderControl::IsCurrentSong(const DetachedSong &_song) const noexcept
 {
 	switch (state) {
 	case DecoderState::STOP:
diff --git a/src/decoder/DecoderControl.hxx b/src/decoder/DecoderControl.hxx
index 90d10d960..926f74343 100644
--- a/src/decoder/DecoderControl.hxx
+++ b/src/decoder/DecoderControl.hxx
@@ -305,10 +305,10 @@ struct DecoderControl {
 	 * Caller must lock the object.
 	 */
 	gcc_pure
-	bool IsCurrentSong(const DetachedSong &_song) const;
+	bool IsCurrentSong(const DetachedSong &_song) const noexcept;
 
 	gcc_pure
-	bool LockIsCurrentSong(const DetachedSong &_song) const {
+	bool LockIsCurrentSong(const DetachedSong &_song) const noexcept {
 		const std::lock_guard<Mutex> protect(mutex);
 		return IsCurrentSong(_song);
 	}
diff --git a/src/decoder/DecoderList.cxx b/src/decoder/DecoderList.cxx
index 4f420db05..58c0f0973 100644
--- a/src/decoder/DecoderList.cxx
+++ b/src/decoder/DecoderList.cxx
@@ -118,7 +118,7 @@ static constexpr unsigned num_decoder_plugins =
 bool decoder_plugins_enabled[num_decoder_plugins];
 
 const struct DecoderPlugin *
-decoder_plugin_from_name(const char *name)
+decoder_plugin_from_name(const char *name) noexcept
 {
 	return decoder_plugins_find([=](const DecoderPlugin &plugin){
 			return strcmp(plugin.name, name) == 0;
@@ -154,7 +154,7 @@ void decoder_plugin_deinit_all(void)
 }
 
 bool
-decoder_plugins_supports_suffix(const char *suffix)
+decoder_plugins_supports_suffix(const char *suffix) noexcept
 {
 	return decoder_plugins_try([suffix](const DecoderPlugin &plugin){
 			return plugin.SupportsSuffix(suffix);
diff --git a/src/decoder/DecoderList.hxx b/src/decoder/DecoderList.hxx
index 6dce02338..2eb9aa231 100644
--- a/src/decoder/DecoderList.hxx
+++ b/src/decoder/DecoderList.hxx
@@ -31,7 +31,7 @@ extern bool decoder_plugins_enabled[];
 
 gcc_pure
 const struct DecoderPlugin *
-decoder_plugin_from_name(const char *name);
+decoder_plugin_from_name(const char *name) noexcept;
 
 /* this is where we "load" all the "plugins" ;-) */
 void
@@ -86,6 +86,6 @@ decoder_plugins_for_each_enabled(F f)
  */
 gcc_pure gcc_nonnull_all
 bool
-decoder_plugins_supports_suffix(const char *suffix);
+decoder_plugins_supports_suffix(const char *suffix) noexcept;
 
 #endif
diff --git a/src/decoder/DecoderPlugin.cxx b/src/decoder/DecoderPlugin.cxx
index 1372e2504..0c2a3bbe9 100644
--- a/src/decoder/DecoderPlugin.cxx
+++ b/src/decoder/DecoderPlugin.cxx
@@ -24,7 +24,7 @@
 #include <assert.h>
 
 bool
-DecoderPlugin::SupportsSuffix(const char *suffix) const
+DecoderPlugin::SupportsSuffix(const char *suffix) const noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
@@ -36,7 +36,7 @@ DecoderPlugin::SupportsSuffix(const char *suffix) const
 }
 
 bool
-DecoderPlugin::SupportsMimeType(const char *mime_type) const
+DecoderPlugin::SupportsMimeType(const char *mime_type) const noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
diff --git a/src/decoder/DecoderPlugin.hxx b/src/decoder/DecoderPlugin.hxx
index 2d2631c24..5c7c81c8e 100644
--- a/src/decoder/DecoderPlugin.hxx
+++ b/src/decoder/DecoderPlugin.hxx
@@ -168,13 +168,13 @@ struct DecoderPlugin {
 	 * Does the plugin announce the specified file name suffix?
 	 */
 	gcc_pure gcc_nonnull_all
-	bool SupportsSuffix(const char *suffix) const;
+	bool SupportsSuffix(const char *suffix) const noexcept;
 
 	/**
 	 * Does the plugin announce the specified MIME type?
 	 */
 	gcc_pure gcc_nonnull_all
-	bool SupportsMimeType(const char *mime_type) const;
+	bool SupportsMimeType(const char *mime_type) const noexcept;
 };
 
 #endif
diff --git a/src/decoder/DecoderThread.cxx b/src/decoder/DecoderThread.cxx
index 1e45a6a68..e362e19e0 100644
--- a/src/decoder/DecoderThread.cxx
+++ b/src/decoder/DecoderThread.cxx
@@ -170,7 +170,8 @@ decoder_file_decode(const DecoderPlugin &plugin,
 
 gcc_pure
 static bool
-decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is)
+decoder_check_plugin_mime(const DecoderPlugin &plugin,
+			  const InputStream &is) noexcept
 {
 	assert(plugin.stream_decode != nullptr);
 
@@ -181,7 +182,8 @@ decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is)
 
 gcc_pure
 static bool
-decoder_check_plugin_suffix(const DecoderPlugin &plugin, const char *suffix)
+decoder_check_plugin_suffix(const DecoderPlugin &plugin,
+			    const char *suffix) noexcept
 {
 	assert(plugin.stream_decode != nullptr);
 
@@ -191,7 +193,7 @@ decoder_check_plugin_suffix(const DecoderPlugin &plugin, const char *suffix)
 gcc_pure
 static bool
 decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
-		     const char *suffix)
+		     const char *suffix) noexcept
 {
 	return plugin.stream_decode != nullptr &&
 		(decoder_check_plugin_mime(plugin, is) ||
diff --git a/src/decoder/plugins/AudiofileDecoderPlugin.cxx b/src/decoder/plugins/AudiofileDecoderPlugin.cxx
index c01426f71..cf0d26bc6 100644
--- a/src/decoder/plugins/AudiofileDecoderPlugin.cxx
+++ b/src/decoder/plugins/AudiofileDecoderPlugin.cxx
@@ -66,7 +66,7 @@ struct AudioFileInputStream {
 
 gcc_pure
 static SongTime
-audiofile_get_duration(AFfilehandle fh)
+audiofile_get_duration(AFfilehandle fh) noexcept
 {
 	return SongTime::FromScale<uint64_t>(afGetFrameCount(fh, AF_DEFAULT_TRACK),
 					     afGetRate(fh, AF_DEFAULT_TRACK));
@@ -239,7 +239,7 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
 
 gcc_pure
 static SignedSongTime
-audiofile_get_duration(InputStream &is)
+audiofile_get_duration(InputStream &is) noexcept
 {
 	if (!is.IsSeekable() || !is.KnownSize())
 		return SignedSongTime::Negative();
diff --git a/src/decoder/plugins/DsdLib.cxx b/src/decoder/plugins/DsdLib.cxx
index 9fd19dfa8..c1c026e87 100644
--- a/src/decoder/plugins/DsdLib.cxx
+++ b/src/decoder/plugins/DsdLib.cxx
@@ -39,7 +39,7 @@
 #include <stdlib.h>
 
 bool
-DsdId::Equals(const char *s) const
+DsdId::Equals(const char *s) const noexcept
 {
 	assert(s != nullptr);
 	assert(strlen(s) == sizeof(value));
@@ -95,7 +95,7 @@ dsdlib_skip(DecoderClient *client, InputStream &is,
 }
 
 bool
-dsdlib_valid_freq(uint32_t samplefreq)
+dsdlib_valid_freq(uint32_t samplefreq) noexcept
 {
 	switch (samplefreq) {
 	case 2822400: /* DSD64, 64xFs, Fs = 44.100kHz */
diff --git a/src/decoder/plugins/DsdLib.hxx b/src/decoder/plugins/DsdLib.hxx
index 311afb6e2..c1a059c55 100644
--- a/src/decoder/plugins/DsdLib.hxx
+++ b/src/decoder/plugins/DsdLib.hxx
@@ -34,7 +34,7 @@ struct DsdId {
 	char value[4];
 
 	gcc_pure
-	bool Equals(const char *s) const;
+	bool Equals(const char *s) const noexcept;
 };
 
 class DsdUint64 {
@@ -72,7 +72,7 @@ dsdlib_skip(DecoderClient *client, InputStream &is,
  **/
 gcc_const
 bool
-dsdlib_valid_freq(uint32_t samplefreq);
+dsdlib_valid_freq(uint32_t samplefreq) noexcept;
 
 /**
  * Add tags from ID3 tag. All tags commonly found in the ID3 tags of
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
index e5787bf09..1380bf94b 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
@@ -112,14 +112,14 @@ ffmpeg_finish()
 
 gcc_pure
 static const AVCodecParameters &
-GetCodecParameters(const AVStream &stream)
+GetCodecParameters(const AVStream &stream) noexcept
 {
 	return *stream.codecpar;
 }
 
 gcc_pure
 static AVSampleFormat
-GetSampleFormat(const AVCodecParameters &codec_params)
+GetSampleFormat(const AVCodecParameters &codec_params) noexcept
 {
 	return AVSampleFormat(codec_params.format);
 }
@@ -128,14 +128,14 @@ GetSampleFormat(const AVCodecParameters &codec_params)
 
 gcc_pure
 static const AVCodecContext &
-GetCodecParameters(const AVStream &stream)
+GetCodecParameters(const AVStream &stream) noexcept
 {
 	return *stream.codec;
 }
 
 gcc_pure
 static AVSampleFormat
-GetSampleFormat(const AVCodecContext &codec_context)
+GetSampleFormat(const AVCodecContext &codec_context) noexcept
 {
 	return codec_context.sample_fmt;
 }
@@ -144,14 +144,14 @@ GetSampleFormat(const AVCodecContext &codec_context)
 
 gcc_pure
 static bool
-IsAudio(const AVStream &stream)
+IsAudio(const AVStream &stream) noexcept
 {
 	return GetCodecParameters(stream).codec_type == AVMEDIA_TYPE_AUDIO;
 }
 
 gcc_pure
 static int
-ffmpeg_find_audio_stream(const AVFormatContext &format_context)
+ffmpeg_find_audio_stream(const AVFormatContext &format_context) noexcept
 {
 	for (unsigned i = 0; i < format_context.nb_streams; ++i)
 		if (IsAudio(*format_context.streams[i]))
@@ -220,7 +220,7 @@ copy_interleave_frame(const AVCodecContext &codec_context,
  */
 gcc_pure
 static int64_t
-StreamRelativePts(const AVPacket &packet, const AVStream &stream)
+StreamRelativePts(const AVPacket &packet, const AVStream &stream) noexcept
 {
 	auto pts = packet.pts;
 	if (pts < 0 || pts == int64_t(AV_NOPTS_VALUE))
@@ -237,7 +237,7 @@ StreamRelativePts(const AVPacket &packet, const AVStream &stream)
 gcc_pure
 static uint64_t
 PtsToPcmFrame(uint64_t pts, const AVStream &stream,
-	      const AVCodecContext &codec_context)
+	      const AVCodecContext &codec_context) noexcept
 {
 	return av_rescale_q(pts, stream.time_base, codec_context.time_base);
 }
@@ -437,7 +437,7 @@ ffmpeg_send_packet(DecoderClient &client, InputStream &is,
 
 gcc_const
 static SampleFormat
-ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
+ffmpeg_sample_format(enum AVSampleFormat sample_fmt) noexcept
 {
 	switch (sample_fmt) {
 	case AV_SAMPLE_FMT_S16:
diff --git a/src/decoder/plugins/FlacMetadata.cxx b/src/decoder/plugins/FlacMetadata.cxx
index afecd06f7..da246e335 100644
--- a/src/decoder/plugins/FlacMetadata.cxx
+++ b/src/decoder/plugins/FlacMetadata.cxx
@@ -67,7 +67,7 @@ flac_parse_mixramp(const FLAC__StreamMetadata_VorbisComment &vc)
  */
 static const char *
 flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
-		   const char *name)
+		   const char *name) noexcept
 {
 	return vorbis_comment_value((const char *)entry->entry, name);
 }
@@ -126,7 +126,7 @@ flac_scan_comments(const FLAC__StreamMetadata_VorbisComment *comment,
 
 gcc_pure
 static inline SongTime
-flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
+flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) noexcept
 {
 	assert(stream_info->sample_rate > 0);
 
diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx
index 2058dfde0..5a9379488 100644
--- a/src/decoder/plugins/GmeDecoderPlugin.cxx
+++ b/src/decoder/plugins/GmeDecoderPlugin.cxx
@@ -74,7 +74,7 @@ gme_plugin_init(gcc_unused const ConfigBlock &block)
 
 gcc_pure
 static unsigned
-ParseSubtuneName(const char *base)
+ParseSubtuneName(const char *base) noexcept
 {
 	if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
 		return 0;
diff --git a/src/decoder/plugins/MadDecoderPlugin.cxx b/src/decoder/plugins/MadDecoderPlugin.cxx
index 184d5b327..f0b707a02 100644
--- a/src/decoder/plugins/MadDecoderPlugin.cxx
+++ b/src/decoder/plugins/MadDecoderPlugin.cxx
@@ -71,7 +71,7 @@ static bool gapless_playback;
 
 gcc_const
 static SongTime
-ToSongTime(mad_timer_t t)
+ToSongTime(mad_timer_t t) noexcept
 {
 	return SongTime::FromMS(mad_timer_count(t, MAD_UNITS_MILLISECONDS));
 }
@@ -155,10 +155,10 @@ struct MadDecoder {
 	enum mp3_action DecodeNextFrame();
 
 	gcc_pure
-	offset_type ThisFrameOffset() const;
+	offset_type ThisFrameOffset() const noexcept;
 
 	gcc_pure
-	offset_type RestIncludingThisFrame() const;
+	offset_type RestIncludingThisFrame() const noexcept;
 
 	/**
 	 * Attempt to calulcate the length of the song from filesize
@@ -177,7 +177,7 @@ struct MadDecoder {
 	}
 
 	gcc_pure
-	long TimeToFrame(SongTime t) const;
+	long TimeToFrame(SongTime t) const noexcept;
 
 	void UpdateTimerNextFrame();
 
@@ -291,7 +291,7 @@ parse_id3_replay_gain_info(ReplayGainInfo &rgi,
 #ifdef ENABLE_ID3TAG
 gcc_pure
 static MixRampInfo
-parse_id3_mixramp(struct id3_tag *tag)
+parse_id3_mixramp(struct id3_tag *tag) noexcept
 {
 	MixRampInfo result;
 
@@ -710,7 +710,7 @@ mp3_frame_duration(const struct mad_frame *frame)
 }
 
 inline offset_type
-MadDecoder::ThisFrameOffset() const
+MadDecoder::ThisFrameOffset() const noexcept
 {
 	auto offset = input_stream.GetOffset();
 
@@ -723,7 +723,7 @@ MadDecoder::ThisFrameOffset() const
 }
 
 inline offset_type
-MadDecoder::RestIncludingThisFrame() const
+MadDecoder::RestIncludingThisFrame() const noexcept
 {
 	return input_stream.GetSize() - ThisFrameOffset();
 }
@@ -846,7 +846,7 @@ mad_decoder_total_file_time(InputStream &is)
 }
 
 long
-MadDecoder::TimeToFrame(SongTime t) const
+MadDecoder::TimeToFrame(SongTime t) const noexcept
 {
 	unsigned long i;
 
diff --git a/src/decoder/plugins/OpusTags.cxx b/src/decoder/plugins/OpusTags.cxx
index 2ecc816a4..dc1bab674 100644
--- a/src/decoder/plugins/OpusTags.cxx
+++ b/src/decoder/plugins/OpusTags.cxx
@@ -31,7 +31,7 @@
 
 gcc_pure
 static TagType
-ParseOpusTagName(const char *name)
+ParseOpusTagName(const char *name) noexcept
 {
 	TagType type = tag_name_parse_i(name);
 	if (type != TAG_NUM_OF_ITEM_TYPES)
diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx
index 8fc2a01d1..a217f2b00 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.cxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx
@@ -116,7 +116,7 @@ struct SidplayContainerPath {
 
 gcc_pure
 static unsigned
-ParseSubtuneName(const char *base)
+ParseSubtuneName(const char *base) noexcept
 {
 	if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
 		return 0;
@@ -390,7 +390,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
 
 gcc_pure
 static const char *
-GetInfoString(const SidTuneInfo &info, unsigned i)
+GetInfoString(const SidTuneInfo &info, unsigned i) noexcept
 {
 #ifdef HAVE_SIDPLAYFP
 	return info.numberOfInfoStrings() > i
diff --git a/src/decoder/plugins/SndfileDecoderPlugin.cxx b/src/decoder/plugins/SndfileDecoderPlugin.cxx
index 297dbe8a6..2f49c7f28 100644
--- a/src/decoder/plugins/SndfileDecoderPlugin.cxx
+++ b/src/decoder/plugins/SndfileDecoderPlugin.cxx
@@ -148,7 +148,7 @@ sndfile_duration(const SF_INFO &info)
 
 gcc_pure
 static SampleFormat
-sndfile_sample_format(const SF_INFO &info)
+sndfile_sample_format(const SF_INFO &info) noexcept
 {
 	switch (info.format & SF_FORMAT_SUBMASK) {
 	case SF_FORMAT_PCM_S8:
diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx
index a97306203..63615ec3d 100644
--- a/src/decoder/plugins/WavpackDecoderPlugin.cxx
+++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx
@@ -101,7 +101,7 @@ WavpackOpenInput(WavpackStreamReader *reader, void *wv_id, void *wvc_id,
 
 gcc_pure
 static SignedSongTime
-GetDuration(WavpackContext *wpc)
+GetDuration(WavpackContext *wpc) noexcept
 {
 #ifdef OPEN_DSD_AS_PCM
 	/* libWavPack 5 */
diff --git a/src/event/ServerSocket.cxx b/src/event/ServerSocket.cxx
index 6b36ed815..556648cc4 100644
--- a/src/event/ServerSocket.cxx
+++ b/src/event/ServerSocket.cxx
@@ -103,16 +103,16 @@ public:
 	using SocketMonitor::Close;
 
 	gcc_pure
-	std::string ToString() const {
+	std::string ToString() const noexcept {
 		return ::ToString(address);
 	}
 
-	void SetFD(int _fd) {
+	void SetFD(int _fd) noexcept {
 		SocketMonitor::Open(_fd);
 		SocketMonitor::ScheduleRead();
 	}
 
-	void Accept();
+	void Accept() noexcept;
 
 private:
 	virtual bool OnSocketReady(unsigned flags) override;
@@ -146,7 +146,7 @@ get_remote_uid(int fd)
 }
 
 inline void
-OneServerSocket::Accept()
+OneServerSocket::Accept() noexcept
 {
 	StaticSocketAddress peer_address;
 	size_t peer_address_length = sizeof(peer_address);
@@ -343,7 +343,7 @@ ServerSocket::AddPortIPv6(unsigned port)
  */
 gcc_pure
 static bool
-SupportsIPv6()
+SupportsIPv6() noexcept
 {
 	int fd = socket(AF_INET6, SOCK_STREAM, 0);
 	if (fd < 0)
diff --git a/src/filter/FilterRegistry.cxx b/src/filter/FilterRegistry.cxx
index 3a319da59..ffbbb9c3d 100644
--- a/src/filter/FilterRegistry.cxx
+++ b/src/filter/FilterRegistry.cxx
@@ -32,7 +32,7 @@ static const FilterPlugin *const filter_plugins[] = {
 };
 
 const FilterPlugin *
-filter_plugin_by_name(const char *name)
+filter_plugin_by_name(const char *name) noexcept
 {
 	for (unsigned i = 0; filter_plugins[i] != nullptr; ++i)
 		if (strcmp(filter_plugins[i]->name, name) == 0)
diff --git a/src/filter/FilterRegistry.hxx b/src/filter/FilterRegistry.hxx
index 20d3662d3..e014ed322 100644
--- a/src/filter/FilterRegistry.hxx
+++ b/src/filter/FilterRegistry.hxx
@@ -39,6 +39,6 @@ extern const FilterPlugin volume_filter_plugin;
 
 gcc_pure
 const FilterPlugin *
-filter_plugin_by_name(const char *name);
+filter_plugin_by_name(const char *name) noexcept;
 
 #endif
diff --git a/src/fs/AllocatedPath.cxx b/src/fs/AllocatedPath.cxx
index 0a1c26b42..fd5e54bf4 100644
--- a/src/fs/AllocatedPath.cxx
+++ b/src/fs/AllocatedPath.cxx
@@ -29,7 +29,7 @@
 AllocatedPath::~AllocatedPath() {}
 
 AllocatedPath
-AllocatedPath::FromUTF8(const char *path_utf8)
+AllocatedPath::FromUTF8(const char *path_utf8) noexcept
 {
 #if defined(HAVE_FS_CHARSET) || defined(WIN32)
 	try {
@@ -53,13 +53,13 @@ AllocatedPath::FromUTF8Throw(const char *path_utf8)
 }
 
 AllocatedPath
-AllocatedPath::GetDirectoryName() const
+AllocatedPath::GetDirectoryName() const noexcept
 {
 	return FromFS(PathTraitsFS::GetParent(c_str()));
 }
 
 std::string
-AllocatedPath::ToUTF8() const
+AllocatedPath::ToUTF8() const noexcept
 {
 	try {
 		return ::PathToUTF8(c_str());
@@ -69,7 +69,7 @@ AllocatedPath::ToUTF8() const
 }
 
 void
-AllocatedPath::ChopSeparators()
+AllocatedPath::ChopSeparators() noexcept
 {
 	size_t l = length();
 	const auto *p = data();
diff --git a/src/fs/AllocatedPath.hxx b/src/fs/AllocatedPath.hxx
index cb5192542..513453ffd 100644
--- a/src/fs/AllocatedPath.hxx
+++ b/src/fs/AllocatedPath.hxx
@@ -153,13 +153,13 @@ public:
 	 * Returns return a "nulled" instance on error.
 	 */
 	gcc_pure gcc_nonnull_all
-	static AllocatedPath FromUTF8(const char *path_utf8);
+	static AllocatedPath FromUTF8(const char *path_utf8) noexcept;
 
 	/**
 	 * Convert a UTF-8 C string to an #AllocatedPath instance.
 	 * Throws a std::runtime_error on error.
 	 */
-	gcc_pure gcc_nonnull_all
+	gcc_nonnull_all
 	static AllocatedPath FromUTF8Throw(const char *path_utf8);
 
 	/**
@@ -244,14 +244,14 @@ public:
 	 * (#IsNull returns true).
 	 */
 	gcc_pure
-	std::string ToUTF8() const;
+	std::string ToUTF8() const noexcept;
 
 	/**
 	 * Gets directory name of this path.
 	 * Returns a "nulled" instance on error.
 	 */
 	gcc_pure
-	AllocatedPath GetDirectoryName() const;
+	AllocatedPath GetDirectoryName() const noexcept;
 
 	/**
 	 * Determine the relative part of the given path to this
@@ -260,17 +260,17 @@ public:
 	 * nullptr on mismatch.
 	 */
 	gcc_pure
-	const_pointer_type Relative(Path other_fs) const {
+	const_pointer_type Relative(Path other_fs) const noexcept {
 		return PathTraitsFS::Relative(c_str(), other_fs.c_str());
 	}
 
 	/**
 	 * Chop trailing directory separators.
 	 */
-	void ChopSeparators();
+	void ChopSeparators() noexcept;
 
 	gcc_pure
-	bool IsAbsolute() const {
+	bool IsAbsolute() const noexcept {
 		return PathTraitsFS::IsAbsolute(c_str());
 	}
 };
diff --git a/src/fs/Charset.cxx b/src/fs/Charset.cxx
index 333c4afac..1b84063fa 100644
--- a/src/fs/Charset.cxx
+++ b/src/fs/Charset.cxx
@@ -57,7 +57,7 @@ SetFSCharset(const char *charset)
 #endif
 
 void
-DeinitFSCharset()
+DeinitFSCharset() noexcept
 {
 #ifdef HAVE_ICU_CONVERTER
 	delete fs_converter;
@@ -66,7 +66,7 @@ DeinitFSCharset()
 }
 
 const char *
-GetFSCharset()
+GetFSCharset() noexcept
 {
 #ifdef HAVE_FS_CHARSET
 	return fs_charset.empty() ? "UTF-8" : fs_charset.c_str();
diff --git a/src/fs/Charset.hxx b/src/fs/Charset.hxx
index 8f20cb565..7f7097b95 100644
--- a/src/fs/Charset.hxx
+++ b/src/fs/Charset.hxx
@@ -33,7 +33,7 @@
  */
 gcc_const
 const char *
-GetFSCharset();
+GetFSCharset() noexcept;
 
 /**
  * Throws std::runtime_error on error.
@@ -42,14 +42,14 @@ void
 SetFSCharset(const char *charset);
 
 void
-DeinitFSCharset();
+DeinitFSCharset() noexcept;
 
 /**
  * Convert the path to UTF-8.
  *
  * Throws std::runtime_error on error.
  */
-gcc_pure gcc_nonnull_all
+gcc_nonnull_all
 PathTraitsUTF8::string
 PathToUTF8(PathTraitsFS::const_pointer_type path_fs);
 
@@ -58,7 +58,7 @@ PathToUTF8(PathTraitsFS::const_pointer_type path_fs);
  *
  * Throws std::runtime_error on error.
  */
-gcc_pure gcc_nonnull_all
+gcc_nonnull_all
 PathTraitsFS::string
 PathFromUTF8(PathTraitsUTF8::const_pointer_type path_utf8);
 
diff --git a/src/fs/Path.cxx b/src/fs/Path.cxx
index d8eadfcec..b8745915f 100644
--- a/src/fs/Path.cxx
+++ b/src/fs/Path.cxx
@@ -24,7 +24,7 @@
 #include <stdexcept>
 
 std::string
-Path::ToUTF8() const
+Path::ToUTF8() const noexcept
 {
 	try {
 		return ::PathToUTF8(c_str());
@@ -34,7 +34,7 @@ Path::ToUTF8() const
 }
 
 Path::const_pointer_type
-Path::GetSuffix() const
+Path::GetSuffix() const noexcept
 {
 	const auto base = GetBase().c_str();
 	const auto *dot = StringFindLast(base, '.');
diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx
index ea2a6bb7c..5053162ef 100644
--- a/src/fs/Path.hxx
+++ b/src/fs/Path.hxx
@@ -123,7 +123,7 @@ public:
 	 * transfer newline characters).
 	 */
 	gcc_pure
-	bool HasNewline() const {
+	bool HasNewline() const noexcept {
 		return PathTraitsFS::Find(c_str(), '\n') != nullptr;
 	}
 
@@ -133,14 +133,14 @@ public:
 	 * (#IsNull returns true).
 	 */
 	gcc_pure
-	std::string ToUTF8() const;
+	std::string ToUTF8() const noexcept;
 
 	/**
 	 * Determine the "base" file name.
 	 * The return value points inside this object.
 	 */
 	gcc_pure
-	Path GetBase() const {
+	Path GetBase() const noexcept {
 		return FromFS(PathTraitsFS::GetBase(c_str()));
 	}
 
@@ -149,7 +149,7 @@ public:
 	 * Returns a "nulled" instance on error.
 	 */
 	gcc_pure
-	AllocatedPath GetDirectoryName() const;
+	AllocatedPath GetDirectoryName() const noexcept;
 
 	/**
 	 * Determine the relative part of the given path to this
@@ -158,17 +158,17 @@ public:
 	 * nullptr on mismatch.
 	 */
 	gcc_pure
-	const_pointer_type Relative(Path other_fs) const {
+	const_pointer_type Relative(Path other_fs) const noexcept {
 		return PathTraitsFS::Relative(c_str(), other_fs.c_str());
 	}
 
 	gcc_pure
-	bool IsAbsolute() const {
+	bool IsAbsolute() const noexcept {
 		return PathTraitsFS::IsAbsolute(c_str());
 	}
 
 	gcc_pure
-	const_pointer_type GetSuffix() const;
+	const_pointer_type GetSuffix() const noexcept;
 };
 
 #endif
diff --git a/src/fs/Path2.cxx b/src/fs/Path2.cxx
index ac2fb5a31..44410f9a2 100644
--- a/src/fs/Path2.cxx
+++ b/src/fs/Path2.cxx
@@ -22,7 +22,7 @@
 #include "AllocatedPath.hxx"
 
 AllocatedPath
-Path::GetDirectoryName() const
+Path::GetDirectoryName() const noexcept
 {
 	return AllocatedPath::FromFS(PathTraitsFS::GetParent(c_str()));
 }
diff --git a/src/fs/StandardDirectory.cxx b/src/fs/StandardDirectory.cxx
index 583962b12..1ea92cf2c 100644
--- a/src/fs/StandardDirectory.cxx
+++ b/src/fs/StandardDirectory.cxx
@@ -202,7 +202,8 @@ ParseConfigLine(char *line, const char *dir_name, AllocatedPath &result_dir)
 	return true;
 }
 
-static AllocatedPath GetUserDir(const char *name)
+static AllocatedPath
+GetUserDir(const char *name) noexcept
 try {
 	auto result = AllocatedPath::Null();
 	auto config_dir = GetUserConfigDir();
@@ -222,7 +223,8 @@ try {
 
 #endif
 
-AllocatedPath GetUserConfigDir()
+AllocatedPath
+GetUserConfigDir() noexcept
 {
 #if defined(WIN32)
 	return GetStandardDir(CSIDL_LOCAL_APPDATA);
@@ -246,7 +248,8 @@ AllocatedPath GetUserConfigDir()
 #endif
 }
 
-AllocatedPath GetUserMusicDir()
+AllocatedPath
+GetUserMusicDir() noexcept
 {
 #if defined(WIN32)
 	return GetStandardDir(CSIDL_MYMUSIC);	
@@ -259,7 +262,8 @@ AllocatedPath GetUserMusicDir()
 #endif
 }
 
-AllocatedPath GetUserCacheDir()
+AllocatedPath
+GetUserCacheDir() noexcept
 {
 #ifdef USE_XDG
 	// Check for $XDG_CACHE_HOME
@@ -285,12 +289,14 @@ AllocatedPath GetUserCacheDir()
 
 #ifdef WIN32
 
-AllocatedPath GetSystemConfigDir()
+AllocatedPath
+GetSystemConfigDir() noexcept
 {
 	return GetStandardDir(CSIDL_COMMON_APPDATA);
 }
 
-AllocatedPath GetAppBaseDir()
+AllocatedPath
+GetAppBaseDir() noexcept
 {
 	std::array<PathTraitsFS::value_type, MAX_PATH> app;
 	auto ret = GetModuleFileName(nullptr, app.data(), app.size());
@@ -309,7 +315,8 @@ AllocatedPath GetAppBaseDir()
 
 #else
 
-AllocatedPath GetHomeDir()
+AllocatedPath
+GetHomeDir() noexcept
 {
 #ifndef ANDROID
 	auto home = getenv("HOME");
@@ -322,7 +329,8 @@ AllocatedPath GetHomeDir()
 	return AllocatedPath::Null();
 }
 
-AllocatedPath GetHomeDir(const char *user_name)
+AllocatedPath
+GetHomeDir(const char *user_name) noexcept
 {
 #ifdef ANDROID
 	(void)user_name;
diff --git a/src/fs/StandardDirectory.hxx b/src/fs/StandardDirectory.hxx
index 26d6fe4e8..13d324c92 100644
--- a/src/fs/StandardDirectory.hxx
+++ b/src/fs/StandardDirectory.hxx
@@ -26,45 +26,51 @@
 /**
  * Obtains configuration directory for the current user.
  */
-AllocatedPath GetUserConfigDir();
+AllocatedPath
+GetUserConfigDir() noexcept;
 
 /**
  * Obtains music directory for the current user.
  */
-AllocatedPath GetUserMusicDir();
+AllocatedPath
+GetUserMusicDir() noexcept;
 
 /**
  * Obtains cache directory for the current user.
  */
 gcc_pure
 AllocatedPath
-GetUserCacheDir();
+GetUserCacheDir() noexcept;
 
 #ifdef WIN32
 
 /**
  * Obtains system configuration directory.
  */
-AllocatedPath GetSystemConfigDir();
+AllocatedPath
+GetSystemConfigDir() noexcept;
 
 /**
  * Obtains application application base directory.
  * Application base directory is a directory that contains 'bin' folder
  * for current executable.
  */
-AllocatedPath GetAppBaseDir();
+AllocatedPath
+GetAppBaseDir() noexcept;
 
 #else
 
 /**
  * Obtains home directory for the current user.
  */
-AllocatedPath GetHomeDir();
+AllocatedPath
+GetHomeDir() noexcept;
 
 /**
  * Obtains home directory for the specified user.
  */
-AllocatedPath GetHomeDir(const char *user_name);
+AllocatedPath
+GetHomeDir(const char *user_name) noexcept;
 
 #endif
 
diff --git a/src/fs/Traits.cxx b/src/fs/Traits.cxx
index 45a2ffacf..9f2bbac02 100644
--- a/src/fs/Traits.cxx
+++ b/src/fs/Traits.cxx
@@ -121,50 +121,51 @@ RelativePathImpl(typename Traits::const_pointer_type base,
 
 PathTraitsFS::string
 PathTraitsFS::Build(const_pointer_type a, size_t a_size,
-		    const_pointer_type b, size_t b_size)
+		    const_pointer_type b, size_t b_size) noexcept
 {
 	return BuildPathImpl<PathTraitsFS>(a, a_size, b, b_size);
 }
 
 PathTraitsFS::const_pointer_type
-PathTraitsFS::GetBase(PathTraitsFS::const_pointer_type p)
+PathTraitsFS::GetBase(PathTraitsFS::const_pointer_type p) noexcept
 {
 	return GetBasePathImpl<PathTraitsFS>(p);
 }
 
 PathTraitsFS::string
-PathTraitsFS::GetParent(PathTraitsFS::const_pointer_type p)
+PathTraitsFS::GetParent(PathTraitsFS::const_pointer_type p) noexcept
 {
 	return GetParentPathImpl<PathTraitsFS>(p);
 }
 
 PathTraitsFS::const_pointer_type
-PathTraitsFS::Relative(const_pointer_type base, const_pointer_type other)
+PathTraitsFS::Relative(const_pointer_type base, const_pointer_type other) noexcept
 {
 	return RelativePathImpl<PathTraitsFS>(base, other);
 }
 
 PathTraitsUTF8::string
 PathTraitsUTF8::Build(const_pointer_type a, size_t a_size,
-		      const_pointer_type b, size_t b_size)
+		      const_pointer_type b, size_t b_size) noexcept
 {
 	return BuildPathImpl<PathTraitsUTF8>(a, a_size, b, b_size);
 }
 
 PathTraitsUTF8::const_pointer_type
-PathTraitsUTF8::GetBase(const_pointer_type p)
+PathTraitsUTF8::GetBase(const_pointer_type p) noexcept
 {
 	return GetBasePathImpl<PathTraitsUTF8>(p);
 }
 
 PathTraitsUTF8::string
-PathTraitsUTF8::GetParent(const_pointer_type p)
+PathTraitsUTF8::GetParent(const_pointer_type p) noexcept
 {
 	return GetParentPathImpl<PathTraitsUTF8>(p);
 }
 
 PathTraitsUTF8::const_pointer_type
-PathTraitsUTF8::Relative(const_pointer_type base, const_pointer_type other)
+PathTraitsUTF8::Relative(const_pointer_type base,
+			 const_pointer_type other) noexcept
 {
 	return RelativePathImpl<PathTraitsUTF8>(base, other);
 }
diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx
index 388c41195..699ab73e8 100644
--- a/src/fs/Traits.hxx
+++ b/src/fs/Traits.hxx
@@ -124,7 +124,7 @@ struct PathTraitsFS {
 	 * The return value points inside the given string.
 	 */
 	gcc_pure gcc_nonnull_all
-	static const_pointer_type GetBase(const_pointer_type p);
+	static const_pointer_type GetBase(const_pointer_type p) noexcept;
 
 	/**
 	 * Determine the "parent" file name of the given native path.
@@ -132,7 +132,7 @@ struct PathTraitsFS {
 	 * separator in the given input string.
 	 */
 	gcc_pure gcc_nonnull_all
-	static string GetParent(const_pointer_type p);
+	static string GetParent(const_pointer_type p) noexcept;
 
 	/**
 	 * Determine the relative part of the given path to this
@@ -142,7 +142,7 @@ struct PathTraitsFS {
 	 */
 	gcc_pure gcc_nonnull_all
 	static const_pointer_type Relative(const_pointer_type base,
-					   const_pointer_type other);
+					   const_pointer_type other) noexcept;
 
 	/**
 	 * Constructs the path from the given components.
@@ -152,10 +152,10 @@ struct PathTraitsFS {
 	 */
 	gcc_pure gcc_nonnull_all
 	static string Build(const_pointer_type a, size_t a_size,
-			    const_pointer_type b, size_t b_size);
+			    const_pointer_type b, size_t b_size) noexcept;
 
 	gcc_pure gcc_nonnull_all
-	static string Build(const_pointer_type a, const_pointer_type b) {
+	static string Build(const_pointer_type a, const_pointer_type b) noexcept {
 		return Build(a, GetLength(a), b, GetLength(b));
 	}
 };
@@ -224,7 +224,7 @@ struct PathTraitsUTF8 {
 	 * The return value points inside the given string.
 	 */
 	gcc_pure gcc_nonnull_all
-	static const_pointer_type GetBase(const_pointer_type p);
+	static const_pointer_type GetBase(const_pointer_type p) noexcept;
 
 	/**
 	 * Determine the "parent" file name of the given UTF-8 path.
@@ -232,7 +232,7 @@ struct PathTraitsUTF8 {
 	 * separator in the given input string.
 	 */
 	gcc_pure gcc_nonnull_all
-	static string GetParent(const_pointer_type p);
+	static string GetParent(const_pointer_type p) noexcept;
 
 	/**
 	 * Determine the relative part of the given path to this
@@ -242,7 +242,7 @@ struct PathTraitsUTF8 {
 	 */
 	gcc_pure gcc_nonnull_all
 	static const_pointer_type Relative(const_pointer_type base,
-					   const_pointer_type other);
+					   const_pointer_type other) noexcept;
 
 	/**
 	 * Constructs the path from the given components.
@@ -252,7 +252,7 @@ struct PathTraitsUTF8 {
 	 */
 	gcc_pure gcc_nonnull_all
 	static string Build(const_pointer_type a, size_t a_size,
-			    const_pointer_type b, size_t b_size);
+			    const_pointer_type b, size_t b_size) noexcept;
 
 	gcc_pure gcc_nonnull_all
 	static string Build(const_pointer_type a, const_pointer_type b) {
diff --git a/src/fs/io/AutoGunzipReader.cxx b/src/fs/io/AutoGunzipReader.cxx
index c4a4dab61..bfbab240f 100644
--- a/src/fs/io/AutoGunzipReader.cxx
+++ b/src/fs/io/AutoGunzipReader.cxx
@@ -28,7 +28,7 @@ AutoGunzipReader::~AutoGunzipReader()
 
 gcc_pure
 static bool
-IsGzip(const uint8_t data[4])
+IsGzip(const uint8_t data[4]) noexcept
 {
 	return data[0] == 0x1f && data[1] == 0x8b && data[2] == 0x08 &&
 		(data[3] & 0xe0) == 0;
diff --git a/src/fs/io/BufferedReader.hxx b/src/fs/io/BufferedReader.hxx
index 6495b71ef..0e1b4a5b7 100644
--- a/src/fs/io/BufferedReader.hxx
+++ b/src/fs/io/BufferedReader.hxx
@@ -65,7 +65,6 @@ public:
 	 * it).  Throws std::runtime_error if not enough data is
 	 * available.
 	 */
-	gcc_pure
 	void *ReadFull(size_t size);
 
 	void Consume(size_t n) {
diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index 6675cb431..b72bee643 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
@@ -78,7 +78,7 @@ FileOutputStream::OpenAppend(bool create)
 }
 
 uint64_t
-FileOutputStream::Tell() const
+FileOutputStream::Tell() const noexcept
 {
 	LONG high = 0;
 	DWORD low = SetFilePointer(handle, 0, &high, FILE_CURRENT);
@@ -184,7 +184,7 @@ FileOutputStream::OpenAppend(bool create)
 }
 
 uint64_t
-FileOutputStream::Tell() const
+FileOutputStream::Tell() const noexcept
 {
 	return fd.Tell();
 }
diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx
index 8b1b30bd7..0d195909c 100644
--- a/src/fs/io/FileOutputStream.hxx
+++ b/src/fs/io/FileOutputStream.hxx
@@ -101,7 +101,7 @@ public:
 	}
 
 	gcc_pure
-	uint64_t Tell() const;
+	uint64_t Tell() const noexcept;
 
 	/* virtual methods from class OutputStream */
 	void Write(const void *data, size_t size) override;
diff --git a/src/fs/io/FileReader.hxx b/src/fs/io/FileReader.hxx
index 27a5e451b..7dc122217 100644
--- a/src/fs/io/FileReader.hxx
+++ b/src/fs/io/FileReader.hxx
@@ -86,11 +86,10 @@ public:
 
 	void Close();
 
-	gcc_pure
 	FileInfo GetFileInfo() const;
 
 	gcc_pure
-	uint64_t GetSize() const {
+	uint64_t GetSize() const noexcept {
 #ifdef WIN32
 		LARGE_INTEGER size;
 		return GetFileSizeEx(handle, &size)
@@ -102,7 +101,7 @@ public:
 	}
 
 	gcc_pure
-	uint64_t GetPosition() const {
+	uint64_t GetPosition() const noexcept {
 #ifdef WIN32
 		LARGE_INTEGER zero;
 		zero.QuadPart = 0;
diff --git a/src/input/AsyncInputStream.cxx b/src/input/AsyncInputStream.cxx
index 9e749884f..daf63faf1 100644
--- a/src/input/AsyncInputStream.cxx
+++ b/src/input/AsyncInputStream.cxx
@@ -89,7 +89,7 @@ AsyncInputStream::Check()
 }
 
 bool
-AsyncInputStream::IsEOF()
+AsyncInputStream::IsEOF() noexcept
 {
 	return (KnownSize() && offset >= size) ||
 		(!open && buffer.IsEmpty());
@@ -164,7 +164,7 @@ AsyncInputStream::ReadTag()
 }
 
 bool
-AsyncInputStream::IsAvailable()
+AsyncInputStream::IsAvailable() noexcept
 {
 	return postponed_exception ||
 		IsEOF() ||
diff --git a/src/input/AsyncInputStream.hxx b/src/input/AsyncInputStream.hxx
index ade1ea622..29fea5406 100644
--- a/src/input/AsyncInputStream.hxx
+++ b/src/input/AsyncInputStream.hxx
@@ -86,10 +86,10 @@ public:
 
 	/* virtual methods from InputStream */
 	void Check() final;
-	bool IsEOF() final;
+	bool IsEOF() noexcept final;
 	void Seek(offset_type new_offset) final;
 	Tag *ReadTag() final;
-	bool IsAvailable() final;
+	bool IsAvailable() noexcept final;
 	size_t Read(void *ptr, size_t read_size) final;
 
 protected:
diff --git a/src/input/InputStream.cxx b/src/input/InputStream.cxx
index 592c6ebe1..d17a95f1e 100644
--- a/src/input/InputStream.cxx
+++ b/src/input/InputStream.cxx
@@ -75,14 +75,14 @@ InputStream::LockWaitReady()
  */
 gcc_pure
 static bool
-ExpensiveSeeking(const char *uri)
+ExpensiveSeeking(const char *uri) noexcept
 {
 	return StringStartsWith(uri, "http://") ||
 		StringStartsWith(uri, "https://");
 }
 
 bool
-InputStream::CheapSeeking() const
+InputStream::CheapSeeking() const noexcept
 {
 	return IsSeekable() && !ExpensiveSeeking(uri.c_str());
 }
@@ -121,7 +121,7 @@ InputStream::LockReadTag()
 }
 
 bool
-InputStream::IsAvailable()
+InputStream::IsAvailable() noexcept
 {
 	return true;
 }
@@ -169,7 +169,7 @@ InputStream::LockReadFull(void *ptr, size_t _size)
 }
 
 bool
-InputStream::LockIsEOF()
+InputStream::LockIsEOF() noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 	return IsEOF();
diff --git a/src/input/InputStream.hxx b/src/input/InputStream.hxx
index 095b498fc..86f19f094 100644
--- a/src/input/InputStream.hxx
+++ b/src/input/InputStream.hxx
@@ -261,7 +261,7 @@ public:
 	 * Determines whether seeking is cheap.  This is true for local files.
 	 */
 	gcc_pure
-	bool CheapSeeking() const;
+	bool CheapSeeking() const noexcept;
 
 	/**
 	 * Seeks to the specified position in the stream.  This will most
@@ -308,14 +308,14 @@ public:
 	 * The caller must lock the mutex.
 	 */
 	gcc_pure
-	virtual bool IsEOF() = 0;
+	virtual bool IsEOF() noexcept = 0;
 
 	/**
 	 * Wrapper for IsEOF() which locks and unlocks the mutex; the
 	 * caller must not be holding it already.
 	 */
 	gcc_pure
-	bool LockIsEOF();
+	bool LockIsEOF() noexcept;
 
 	/**
 	 * Reads the tag from the stream.
@@ -343,7 +343,7 @@ public:
 	 * The caller must lock the mutex.
 	 */
 	gcc_pure
-	virtual bool IsAvailable();
+	virtual bool IsAvailable() noexcept;
 
 	/**
 	 * Reads data from the stream into the caller-supplied buffer.
diff --git a/src/input/ProxyInputStream.cxx b/src/input/ProxyInputStream.cxx
index 481edd547..c8e66fecf 100644
--- a/src/input/ProxyInputStream.cxx
+++ b/src/input/ProxyInputStream.cxx
@@ -70,7 +70,7 @@ ProxyInputStream::Seek(offset_type new_offset)
 }
 
 bool
-ProxyInputStream::IsEOF()
+ProxyInputStream::IsEOF() noexcept
 {
 	return input.IsEOF();
 }
@@ -82,7 +82,7 @@ ProxyInputStream::ReadTag()
 }
 
 bool
-ProxyInputStream::IsAvailable()
+ProxyInputStream::IsAvailable() noexcept
 {
 	return input.IsAvailable();
 }
diff --git a/src/input/ProxyInputStream.hxx b/src/input/ProxyInputStream.hxx
index 27257b169..bce35c224 100644
--- a/src/input/ProxyInputStream.hxx
+++ b/src/input/ProxyInputStream.hxx
@@ -46,9 +46,9 @@ public:
 	void Check() override;
 	void Update() override;
 	void Seek(offset_type new_offset) override;
-	bool IsEOF() override;
+	bool IsEOF() noexcept override;
 	Tag *ReadTag() override;
-	bool IsAvailable() override;
+	bool IsAvailable() noexcept override;
 	size_t Read(void *ptr, size_t read_size) override;
 
 protected:
diff --git a/src/input/ThreadInputStream.cxx b/src/input/ThreadInputStream.cxx
index fa9343e53..88251a70a 100644
--- a/src/input/ThreadInputStream.cxx
+++ b/src/input/ThreadInputStream.cxx
@@ -117,7 +117,7 @@ ThreadInputStream::Check()
 }
 
 bool
-ThreadInputStream::IsAvailable()
+ThreadInputStream::IsAvailable() noexcept
 {
 	assert(!thread.IsInside());
 
@@ -151,7 +151,7 @@ ThreadInputStream::Read(void *ptr, size_t read_size)
 }
 
 bool
-ThreadInputStream::IsEOF()
+ThreadInputStream::IsEOF() noexcept
 {
 	assert(!thread.IsInside());
 
diff --git a/src/input/ThreadInputStream.hxx b/src/input/ThreadInputStream.hxx
index 1cd5196d0..046e0821c 100644
--- a/src/input/ThreadInputStream.hxx
+++ b/src/input/ThreadInputStream.hxx
@@ -85,8 +85,8 @@ public:
 
 	/* virtual methods from InputStream */
 	void Check() override final;
-	bool IsEOF() override final;
-	bool IsAvailable() override final;
+	bool IsEOF() noexcept final;
+	bool IsAvailable() noexcept final;
 	size_t Read(void *ptr, size_t size) override final;
 
 protected:
diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx
index 081f4151c..011ba6751 100644
--- a/src/input/plugins/CdioParanoiaInputPlugin.cxx
+++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx
@@ -96,7 +96,7 @@ class CdioParanoiaInputStream final : public InputStream {
 	}
 
 	/* virtual methods from InputStream */
-	bool IsEOF() override;
+	bool IsEOF() noexcept override;
 	size_t Read(void *ptr, size_t size) override;
 	void Seek(offset_type offset) override;
 };
@@ -340,7 +340,7 @@ CdioParanoiaInputStream::Read(void *ptr, size_t length)
 }
 
 bool
-CdioParanoiaInputStream::IsEOF()
+CdioParanoiaInputStream::IsEOF() noexcept
 {
 	return lsn_from + lsn_relofs > lsn_to;
 }
diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx
index 861128e2a..f2611c094 100644
--- a/src/input/plugins/FfmpegInputPlugin.cxx
+++ b/src/input/plugins/FfmpegInputPlugin.cxx
@@ -59,7 +59,7 @@ struct FfmpegInputStream final : public InputStream {
 	}
 
 	/* virtual methods from InputStream */
-	bool IsEOF() override;
+	bool IsEOF() noexcept override;
 	size_t Read(void *ptr, size_t size) override;
 	void Seek(offset_type offset) override;
 };
@@ -118,7 +118,7 @@ FfmpegInputStream::Read(void *ptr, size_t read_size)
 }
 
 bool
-FfmpegInputStream::IsEOF()
+FfmpegInputStream::IsEOF() noexcept
 {
 	return eof;
 }
diff --git a/src/input/plugins/FileInputPlugin.cxx b/src/input/plugins/FileInputPlugin.cxx
index 0642b7233..fc51715ad 100644
--- a/src/input/plugins/FileInputPlugin.cxx
+++ b/src/input/plugins/FileInputPlugin.cxx
@@ -45,7 +45,7 @@ public:
 
 	/* virtual methods from InputStream */
 
-	bool IsEOF() override {
+	bool IsEOF() noexcept override {
 		return GetOffset() >= GetSize();
 	}
 
diff --git a/src/input/plugins/RewindInputPlugin.cxx b/src/input/plugins/RewindInputPlugin.cxx
index 5a4f91d9b..7ece4ad50 100644
--- a/src/input/plugins/RewindInputPlugin.cxx
+++ b/src/input/plugins/RewindInputPlugin.cxx
@@ -59,7 +59,7 @@ public:
 			ProxyInputStream::Update();
 	}
 
-	bool IsEOF() override {
+	bool IsEOF() noexcept override {
 		return !ReadingFromBuffer() && ProxyInputStream::IsEOF();
 	}
 
diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx
index 278b4f417..4b3026e40 100644
--- a/src/input/plugins/SmbclientInputPlugin.cxx
+++ b/src/input/plugins/SmbclientInputPlugin.cxx
@@ -55,7 +55,7 @@ public:
 
 	/* virtual methods from InputStream */
 
-	bool IsEOF() override {
+	bool IsEOF() noexcept override {
 		return offset >= size;
 	}
 
diff --git a/src/lib/curl/Request.cxx b/src/lib/curl/Request.cxx
index 14d626b34..d8301cbba 100644
--- a/src/lib/curl/Request.cxx
+++ b/src/lib/curl/Request.cxx
@@ -170,7 +170,7 @@ CurlRequest::Done(CURLcode result)
 
 gcc_pure
 static bool
-IsResponseBoundaryHeader(StringView s)
+IsResponseBoundaryHeader(StringView s) noexcept
 {
 	return s.size > 5 && (memcmp(s.data, "HTTP/", 5) == 0 ||
 			      /* the proprietary "ICY 200 OK" is
diff --git a/src/lib/curl/Version.cxx b/src/lib/curl/Version.cxx
index 94a248b61..2a00d669b 100644
--- a/src/lib/curl/Version.cxx
+++ b/src/lib/curl/Version.cxx
@@ -32,7 +32,7 @@
 #include <curl/curl.h>
 
 bool
-IsCurlOlderThan(unsigned version_num)
+IsCurlOlderThan(unsigned version_num) noexcept
 {
 	const auto *const info = curl_version_info(CURLVERSION_FIRST);
 	return info == nullptr || info->version_num < version_num;
diff --git a/src/lib/curl/Version.hxx b/src/lib/curl/Version.hxx
index 21b5164e5..c854a0d58 100644
--- a/src/lib/curl/Version.hxx
+++ b/src/lib/curl/Version.hxx
@@ -34,6 +34,6 @@
 
 gcc_const
 bool
-IsCurlOlderThan(unsigned version_num);
+IsCurlOlderThan(unsigned version_num) noexcept;
 
 #endif
diff --git a/src/lib/expat/ExpatParser.cxx b/src/lib/expat/ExpatParser.cxx
index 75e4291a3..28e68e11a 100644
--- a/src/lib/expat/ExpatParser.cxx
+++ b/src/lib/expat/ExpatParser.cxx
@@ -32,7 +32,7 @@ ExpatParser::Parse(const char *data, size_t length, bool is_final)
 
 const char *
 ExpatParser::GetAttribute(const XML_Char **atts,
-			  const char *name)
+			  const char *name) noexcept
 {
 	for (unsigned i = 0; atts[i] != nullptr; i += 2)
 		if (strcmp(atts[i], name) == 0)
@@ -43,7 +43,7 @@ ExpatParser::GetAttribute(const XML_Char **atts,
 
 const char *
 ExpatParser::GetAttributeCase(const XML_Char **atts,
-			      const char *name)
+			      const char *name) noexcept
 {
 	for (unsigned i = 0; atts[i] != nullptr; i += 2)
 		if (StringEqualsCaseASCII(atts[i], name))
diff --git a/src/lib/expat/ExpatParser.hxx b/src/lib/expat/ExpatParser.hxx
index 1215b8bc4..99feb03fa 100644
--- a/src/lib/expat/ExpatParser.hxx
+++ b/src/lib/expat/ExpatParser.hxx
@@ -64,11 +64,11 @@ public:
 	ExpatParser &operator=(const ExpatParser &) = delete;
 
 	void SetElementHandler(XML_StartElementHandler start,
-			       XML_EndElementHandler end) {
+			       XML_EndElementHandler end) noexcept {
 		XML_SetElementHandler(parser, start, end);
 	}
 
-	void SetCharacterDataHandler(XML_CharacterDataHandler charhndl) {
+	void SetCharacterDataHandler(XML_CharacterDataHandler charhndl) noexcept {
 		XML_SetCharacterDataHandler(parser, charhndl);
 	}
 
@@ -78,11 +78,11 @@ public:
 
 	gcc_pure
 	static const char *GetAttribute(const XML_Char **atts,
-					const char *name);
+					const char *name) noexcept;
 
 	gcc_pure
 	static const char *GetAttributeCase(const XML_Char **atts,
-					    const char *name);
+					    const char *name) noexcept;
 };
 
 /**
@@ -114,13 +114,13 @@ public:
 
 	gcc_pure
 	static const char *GetAttribute(const XML_Char **atts,
-					const char *name) {
+					const char *name) noexcept {
 		return ExpatParser::GetAttribute(atts, name);
 	}
 
 	gcc_pure
 	static const char *GetAttributeCase(const XML_Char **atts,
-					    const char *name) {
+					    const char *name) noexcept {
 		return ExpatParser::GetAttributeCase(atts, name);
 	}
 
diff --git a/src/lib/ffmpeg/LogCallback.cxx b/src/lib/ffmpeg/LogCallback.cxx
index ee0389947..c682da63d 100644
--- a/src/lib/ffmpeg/LogCallback.cxx
+++ b/src/lib/ffmpeg/LogCallback.cxx
@@ -34,7 +34,7 @@ extern "C" {
 
 gcc_const
 static LogLevel
-FfmpegImportLogLevel(int level)
+FfmpegImportLogLevel(int level) noexcept
 {
 	if (level <= AV_LOG_FATAL)
 		return LogLevel::ERROR;
diff --git a/src/lib/ffmpeg/Time.hxx b/src/lib/ffmpeg/Time.hxx
index 39805b85f..71f7edd22 100644
--- a/src/lib/ffmpeg/Time.hxx
+++ b/src/lib/ffmpeg/Time.hxx
@@ -41,7 +41,7 @@ extern "C" {
  */
 gcc_const
 static inline double
-FfmpegTimeToDouble(int64_t t, const AVRational time_base)
+FfmpegTimeToDouble(int64_t t, const AVRational time_base) noexcept
 {
 	assert(t != (int64_t)AV_NOPTS_VALUE);
 
@@ -64,7 +64,7 @@ RatioToAVRational()
  */
 gcc_const
 static inline SongTime
-FromFfmpegTime(int64_t t, const AVRational time_base)
+FromFfmpegTime(int64_t t, const AVRational time_base) noexcept
 {
 	assert(t != (int64_t)AV_NOPTS_VALUE);
 
@@ -77,7 +77,7 @@ FromFfmpegTime(int64_t t, const AVRational time_base)
  */
 gcc_const
 static inline SignedSongTime
-FromFfmpegTimeChecked(int64_t t, const AVRational time_base)
+FromFfmpegTimeChecked(int64_t t, const AVRational time_base) noexcept
 {
 	return t != (int64_t)AV_NOPTS_VALUE
 		? SignedSongTime(FromFfmpegTime(t, time_base))
@@ -89,7 +89,7 @@ FromFfmpegTimeChecked(int64_t t, const AVRational time_base)
  */
 gcc_const
 static inline int64_t
-ToFfmpegTime(SongTime t, const AVRational time_base)
+ToFfmpegTime(SongTime t, const AVRational time_base) noexcept
 {
 	return av_rescale_q(t.count(),
 			    RatioToAVRational<SongTime::period>(),
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx
index 10452cc26..abb4b709c 100644
--- a/src/lib/icu/Collate.cxx
+++ b/src/lib/icu/Collate.cxx
@@ -65,7 +65,7 @@ IcuCollateInit()
 }
 
 void
-IcuCollateFinish()
+IcuCollateFinish() noexcept
 {
 	assert(collator != nullptr);
 
@@ -76,7 +76,7 @@ IcuCollateFinish()
 
 gcc_pure
 int
-IcuCollate(const char *a, const char *b)
+IcuCollate(const char *a, const char *b) noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Collate.hxx
index f96f32423..d6cfcb764 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/lib/icu/Collate.hxx
@@ -32,13 +32,13 @@ void
 IcuCollateInit();
 
 void
-IcuCollateFinish();
+IcuCollateFinish() noexcept;
 
 gcc_pure gcc_nonnull_all
 int
-IcuCollate(const char *a, const char *b);
+IcuCollate(const char *a, const char *b) noexcept;
 
-gcc_pure gcc_nonnull_all
+gcc_nonnull_all
 AllocatedString<char>
 IcuCaseFold(const char *src);
 
diff --git a/src/lib/icu/Converter.hxx b/src/lib/icu/Converter.hxx
index 80eec20c0..7ce545cf6 100644
--- a/src/lib/icu/Converter.hxx
+++ b/src/lib/icu/Converter.hxx
@@ -81,7 +81,7 @@ public:
 	 *
 	 * Throws std::runtime_error on error.
 	 */
-	gcc_pure gcc_nonnull_all
+	gcc_nonnull_all
 	AllocatedString<char> ToUTF8(const char *s) const;
 
 	/**
@@ -89,7 +89,7 @@ public:
 	 *
 	 * Throws std::runtime_error on error.
 	 */
-	gcc_pure gcc_nonnull_all
+	gcc_nonnull_all
 	AllocatedString<char> FromUTF8(const char *s) const;
 };
 
diff --git a/src/lib/nfs/Base.cxx b/src/lib/nfs/Base.cxx
index 0a9f4335c..5e67cb5f4 100644
--- a/src/lib/nfs/Base.cxx
+++ b/src/lib/nfs/Base.cxx
@@ -46,7 +46,7 @@ nfs_set_base(const char *server, const char *export_name)
 }
 
 const char *
-nfs_check_base(const char *server, const char *path)
+nfs_check_base(const char *server, const char *path) noexcept
 {
 	assert(server != nullptr);
 	assert(path != nullptr);
diff --git a/src/lib/nfs/Base.hxx b/src/lib/nfs/Base.hxx
index 2ca15929d..78d25da72 100644
--- a/src/lib/nfs/Base.hxx
+++ b/src/lib/nfs/Base.hxx
@@ -41,6 +41,6 @@ nfs_set_base(const char *server, const char *export_name);
  */
 gcc_pure
 const char *
-nfs_check_base(const char *server, const char *path);
+nfs_check_base(const char *server, const char *path) noexcept;
 
 #endif
diff --git a/src/lib/nfs/Cancellable.hxx b/src/lib/nfs/Cancellable.hxx
index 7c2ccd71a..89635bec7 100644
--- a/src/lib/nfs/Cancellable.hxx
+++ b/src/lib/nfs/Cancellable.hxx
@@ -91,29 +91,29 @@ private:
 	};
 
 	gcc_pure
-	iterator Find(reference_type p) {
+	iterator Find(reference_type p) noexcept {
 		return std::find_if(list.begin(), list.end(), MatchPointer(p));
 	}
 
 	gcc_pure
-	const_iterator Find(const_reference_type p) const {
+	const_iterator Find(const_reference_type p) const noexcept {
 		return std::find_if(list.begin(), list.end(), MatchPointer(p));
 	}
 
 	gcc_pure
-	iterator Find(CT &c) {
+	iterator Find(CT &c) noexcept {
 		return list.iterator_to(c);
 	}
 
 	gcc_pure
-	const_iterator Find(const CT &c) const {
+	const_iterator Find(const CT &c) const noexcept {
 		return list.iterator_to(c);
 	}
 
 public:
 #ifndef NDEBUG
 	gcc_pure
-	bool IsEmpty() const {
+	bool IsEmpty() const noexcept {
 		for (const auto &c : list)
 			if (!c.IsCancelled())
 				return false;
@@ -123,7 +123,7 @@ public:
 #endif
 
 	gcc_pure
-	bool Contains(const_reference_type p) const {
+	bool Contains(const_reference_type p) const noexcept {
 		return Find(p) != list.end();
 	}
 
@@ -151,7 +151,7 @@ public:
 		i->Cancel();
 	}
 
-	CT &Get(reference_type p) {
+	CT &Get(reference_type p) noexcept {
 		auto i = Find(p);
 		assert(i != list.end());
 
diff --git a/src/lib/nfs/Connection.hxx b/src/lib/nfs/Connection.hxx
index ec858e177..a752535e0 100644
--- a/src/lib/nfs/Connection.hxx
+++ b/src/lib/nfs/Connection.hxx
@@ -135,7 +135,7 @@ class NfsConnection : SocketMonitor, TimeoutMonitor, DeferredMonitor {
 public:
 	gcc_nonnull_all
 	NfsConnection(EventLoop &_loop,
-		      const char *_server, const char *_export_name)
+		      const char *_server, const char *_export_name) noexcept
 		:SocketMonitor(_loop), TimeoutMonitor(_loop),
 		 DeferredMonitor(_loop),
 		 server(_server), export_name(_export_name),
diff --git a/src/lib/nfs/Glue.cxx b/src/lib/nfs/Glue.cxx
index adea9d7b1..be8c5a135 100644
--- a/src/lib/nfs/Glue.cxx
+++ b/src/lib/nfs/Glue.cxx
@@ -57,7 +57,7 @@ nfs_get_event_loop()
 }
 
 NfsConnection &
-nfs_get_connection(const char *server, const char *export_name)
+nfs_get_connection(const char *server, const char *export_name) noexcept
 {
 	assert(in_use > 0);
 
diff --git a/src/lib/nfs/Glue.hxx b/src/lib/nfs/Glue.hxx
index 3606a908d..66c154ddd 100644
--- a/src/lib/nfs/Glue.hxx
+++ b/src/lib/nfs/Glue.hxx
@@ -41,6 +41,6 @@ nfs_get_event_loop();
 
 gcc_pure
 NfsConnection &
-nfs_get_connection(const char *server, const char *export_name);
+nfs_get_connection(const char *server, const char *export_name) noexcept;
 
 #endif
diff --git a/src/lib/nfs/Manager.cxx b/src/lib/nfs/Manager.cxx
index d9385782b..89999e44f 100644
--- a/src/lib/nfs/Manager.cxx
+++ b/src/lib/nfs/Manager.cxx
@@ -38,7 +38,7 @@ NfsManager::ManagedConnection::OnNfsConnectionError(std::exception_ptr &&e)
 
 inline bool
 NfsManager::Compare::operator()(const LookupKey a,
-				const ManagedConnection &b) const
+				const ManagedConnection &b) const noexcept
 {
 	int result = strcmp(a.server, b.GetServer());
 	if (result != 0)
@@ -50,7 +50,7 @@ NfsManager::Compare::operator()(const LookupKey a,
 
 inline bool
 NfsManager::Compare::operator()(const ManagedConnection &a,
-				const LookupKey b) const
+				const LookupKey b) const noexcept
 {
 	int result = strcmp(a.GetServer(), b.server);
 	if (result != 0)
@@ -62,7 +62,7 @@ NfsManager::Compare::operator()(const ManagedConnection &a,
 
 inline bool
 NfsManager::Compare::operator()(const ManagedConnection &a,
-				const ManagedConnection &b) const
+				const ManagedConnection &b) const noexcept
 {
 	int result = strcmp(a.GetServer(), b.GetServer());
 	if (result != 0)
@@ -82,7 +82,7 @@ NfsManager::~NfsManager()
 }
 
 NfsConnection &
-NfsManager::GetConnection(const char *server, const char *export_name)
+NfsManager::GetConnection(const char *server, const char *export_name) noexcept
 {
 	assert(server != nullptr);
 	assert(export_name != nullptr);
diff --git a/src/lib/nfs/Manager.hxx b/src/lib/nfs/Manager.hxx
index f922ca17a..cc001e2f8 100644
--- a/src/lib/nfs/Manager.hxx
+++ b/src/lib/nfs/Manager.hxx
@@ -59,15 +59,15 @@ class NfsManager final : IdleMonitor {
 	struct Compare {
 		gcc_pure
 		bool operator()(const LookupKey a,
-				const ManagedConnection &b) const;
+				const ManagedConnection &b) const noexcept;
 
 		gcc_pure
 		bool operator()(const ManagedConnection &a,
-				const LookupKey b) const;
+				const LookupKey b) const noexcept;
 
 		gcc_pure
 		bool operator()(const ManagedConnection &a,
-				const ManagedConnection &b) const;
+				const ManagedConnection &b) const noexcept;
 	};
 
 	/**
@@ -101,7 +101,7 @@ public:
 
 	gcc_pure
 	NfsConnection &GetConnection(const char *server,
-				     const char *export_name);
+				     const char *export_name) noexcept;
 
 private:
 	void ScheduleDelete(ManagedConnection &c) {
diff --git a/src/lib/upnp/Discovery.cxx b/src/lib/upnp/Discovery.cxx
index 024658683..121c01c57 100644
--- a/src/lib/upnp/Discovery.cxx
+++ b/src/lib/upnp/Discovery.cxx
@@ -36,7 +36,7 @@ static constexpr char ContentDirectorySType[] = "urn:schemas-upnp-org:service:Co
 // version 1
 gcc_pure
 static bool
-isCDService(const char *st)
+isCDService(const char *st) noexcept
 {
 	constexpr size_t sz = sizeof(ContentDirectorySType) - 3;
 	return memcmp(ContentDirectorySType, st, sz) == 0;
@@ -47,7 +47,7 @@ static constexpr char MediaServerDType[] = "urn:schemas-upnp-org:device:MediaSer
 
 gcc_pure
 static bool
-isMSDevice(const char *st)
+isMSDevice(const char *st) noexcept
 {
 	constexpr size_t sz = sizeof(MediaServerDType) - 3;
 	return memcmp(MediaServerDType, st, sz) == 0;
diff --git a/src/lib/upnp/Util.cxx b/src/lib/upnp/Util.cxx
index 61c11719d..b6cd4189e 100644
--- a/src/lib/upnp/Util.cxx
+++ b/src/lib/upnp/Util.cxx
@@ -23,7 +23,7 @@
 
 /** Get rid of white space at both ends */
 void
-trimstring(std::string &s, const char *ws)
+trimstring(std::string &s, const char *ws) noexcept
 {
 	auto pos = s.find_first_not_of(ws);
 	if (pos == std::string::npos) {
@@ -38,14 +38,14 @@ trimstring(std::string &s, const char *ws)
 }
 
 static void
-path_catslash(std::string &s)
+path_catslash(std::string &s) noexcept
 {
 	if (s.empty() || s.back() != '/')
 		s += '/';
 }
 
 std::string
-path_getfather(const std::string &s)
+path_getfather(const std::string &s) noexcept
 {
 	std::string father = s;
 
@@ -71,7 +71,7 @@ path_getfather(const std::string &s)
 
 std::list<std::string>
 stringToTokens(const std::string &str,
-	       const char delim)
+	       const char delim) noexcept
 {
 	std::list<std::string> tokens;
 
@@ -105,7 +105,7 @@ stringToTokens(const std::string &str,
 
 template <class T>
 bool
-csvToStrings(const char *s, T &tokens)
+csvToStrings(const char *s, T &tokens) noexcept
 {
 	assert(tokens.empty());
 
@@ -132,4 +132,4 @@ csvToStrings(const char *s, T &tokens)
 	}
 }
 
-template bool csvToStrings<std::list<std::string>>(const char *, std::list<std::string> &);
+template bool csvToStrings<std::list<std::string>>(const char *, std::list<std::string> &) noexcept;
diff --git a/src/lib/upnp/Util.hxx b/src/lib/upnp/Util.hxx
index b935611ec..5ff2710a6 100644
--- a/src/lib/upnp/Util.hxx
+++ b/src/lib/upnp/Util.hxx
@@ -26,17 +26,17 @@
 #include <list>
 
 void
-trimstring(std::string &s, const char *ws = " \t\n");
+trimstring(std::string &s, const char *ws = " \t\n") noexcept;
 
 std::string
-path_getfather(const std::string &s);
+path_getfather(const std::string &s) noexcept;
 
 gcc_pure
 std::list<std::string>
-stringToTokens(const std::string &str, char delim);
+stringToTokens(const std::string &str, char delim) noexcept;
 
 template <class T>
 bool
-csvToStrings(const char *s, T &tokens);
+csvToStrings(const char *s, T &tokens) noexcept;
 
 #endif /* _UPNPP_H_X_INCLUDED_ */
diff --git a/src/ls.cxx b/src/ls.cxx
index 2ba735b4d..72754dd7f 100644
--- a/src/ls.cxx
+++ b/src/ls.cxx
@@ -89,7 +89,8 @@ print_supported_uri_schemes(Response &r)
 	}
 }
 
-bool uri_supported_scheme(const char *uri)
+bool
+uri_supported_scheme(const char *uri) noexcept
 {
 	const char *const*urlPrefixes = remoteUrlPrefixes;
 
diff --git a/src/ls.hxx b/src/ls.hxx
index d4c1d296b..b8c8f249a 100644
--- a/src/ls.hxx
+++ b/src/ls.hxx
@@ -32,7 +32,8 @@ class Response;
  * uri_has_scheme() first.
  */
 gcc_pure
-bool uri_supported_scheme(const char *url);
+bool
+uri_supported_scheme(const char *url) noexcept;
 
 /**
  * Send a list of supported URI schemes to the client.  This is the
diff --git a/src/mixer/MixerAll.cxx b/src/mixer/MixerAll.cxx
index cb50c3418..ddccbcd80 100644
--- a/src/mixer/MixerAll.cxx
+++ b/src/mixer/MixerAll.cxx
@@ -30,8 +30,9 @@
 
 #include <assert.h>
 
+gcc_pure
 static int
-output_mixer_get_volume(const AudioOutputControl &ao)
+output_mixer_get_volume(const AudioOutputControl &ao) noexcept
 {
 	if (!ao.IsEnabled())
 		return -1;
@@ -51,7 +52,7 @@ output_mixer_get_volume(const AudioOutputControl &ao)
 }
 
 int
-MultipleOutputs::GetVolume() const
+MultipleOutputs::GetVolume() const noexcept
 {
 	unsigned ok = 0;
 	int total = 0;
@@ -71,7 +72,7 @@ MultipleOutputs::GetVolume() const
 }
 
 static bool
-output_mixer_set_volume(AudioOutputControl &ao, unsigned volume)
+output_mixer_set_volume(AudioOutputControl &ao, unsigned volume) noexcept
 {
 	assert(volume <= 100);
 
@@ -94,7 +95,7 @@ output_mixer_set_volume(AudioOutputControl &ao, unsigned volume)
 }
 
 bool
-MultipleOutputs::SetVolume(unsigned volume)
+MultipleOutputs::SetVolume(unsigned volume) noexcept
 {
 	assert(volume <= 100);
 
@@ -107,7 +108,7 @@ MultipleOutputs::SetVolume(unsigned volume)
 }
 
 static int
-output_mixer_get_software_volume(const AudioOutputControl &ao)
+output_mixer_get_software_volume(const AudioOutputControl &ao) noexcept
 {
 	if (!ao.IsEnabled())
 		return -1;
@@ -120,7 +121,7 @@ output_mixer_get_software_volume(const AudioOutputControl &ao)
 }
 
 int
-MultipleOutputs::GetSoftwareVolume() const
+MultipleOutputs::GetSoftwareVolume() const noexcept
 {
 	unsigned ok = 0;
 	int total = 0;
@@ -140,7 +141,7 @@ MultipleOutputs::GetSoftwareVolume() const
 }
 
 void
-MultipleOutputs::SetSoftwareVolume(unsigned volume)
+MultipleOutputs::SetSoftwareVolume(unsigned volume) noexcept
 {
 	assert(volume <= PCM_VOLUME_1);
 
diff --git a/src/mixer/MixerType.cxx b/src/mixer/MixerType.cxx
index cfc0edab9..e792123df 100644
--- a/src/mixer/MixerType.cxx
+++ b/src/mixer/MixerType.cxx
@@ -24,7 +24,7 @@
 #include <string.h>
 
 MixerType
-mixer_type_parse(const char *input)
+mixer_type_parse(const char *input) noexcept
 {
 	assert(input != NULL);
 
diff --git a/src/mixer/MixerType.hxx b/src/mixer/MixerType.hxx
index 0c5b55031..6c6d4cb47 100644
--- a/src/mixer/MixerType.hxx
+++ b/src/mixer/MixerType.hxx
@@ -20,6 +20,8 @@
 #ifndef MPD_MIXER_TYPE_HXX
 #define MPD_MIXER_TYPE_HXX
 
+#include "Compiler.h"
+
 enum class MixerType {
 	/** parser error */
 	UNKNOWN,
@@ -44,7 +46,8 @@ enum class MixerType {
  * a #MixerType value; #MixerType::UNKNOWN means #input could not be
  * parsed
  */
+gcc_pure
 MixerType
-mixer_type_parse(const char *input);
+mixer_type_parse(const char *input) noexcept;
 
 #endif
diff --git a/src/mixer/Volume.cxx b/src/mixer/Volume.cxx
index 365136240..c85dc8b8f 100644
--- a/src/mixer/Volume.cxx
+++ b/src/mixer/Volume.cxx
@@ -42,14 +42,14 @@ static int last_hardware_volume = -1;
 static PeriodClock hardware_volume_clock;
 
 void
-InvalidateHardwareVolume()
+InvalidateHardwareVolume() noexcept
 {
 	/* flush the hardware volume cache */
 	last_hardware_volume = -1;
 }
 
 int
-volume_level_get(const MultipleOutputs &outputs)
+volume_level_get(const MultipleOutputs &outputs) noexcept
 {
 	if (last_hardware_volume >= 0 &&
 	    !hardware_volume_clock.CheckUpdate(std::chrono::seconds(1)))
@@ -118,7 +118,7 @@ save_sw_volume_state(BufferedOutputStream &os)
 }
 
 unsigned
-sw_volume_state_get_hash(void)
+sw_volume_state_get_hash() noexcept
 {
 	return volume_software_set;
 }
diff --git a/src/mixer/Volume.hxx b/src/mixer/Volume.hxx
index c74786469..5ca467d77 100644
--- a/src/mixer/Volume.hxx
+++ b/src/mixer/Volume.hxx
@@ -26,11 +26,11 @@ class MultipleOutputs;
 class BufferedOutputStream;
 
 void
-InvalidateHardwareVolume();
+InvalidateHardwareVolume() noexcept;
 
 gcc_pure
 int
-volume_level_get(const MultipleOutputs &outputs);
+volume_level_get(const MultipleOutputs &outputs) noexcept;
 
 bool
 volume_level_change(MultipleOutputs &outputs, unsigned volume);
@@ -49,6 +49,6 @@ save_sw_volume_state(BufferedOutputStream &os);
  */
 gcc_pure
 unsigned
-sw_volume_state_get_hash();
+sw_volume_state_get_hash() noexcept;
 
 #endif
diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx
index cf2dc2055..a62d5a587 100644
--- a/src/mixer/plugins/AlsaMixerPlugin.cxx
+++ b/src/mixer/plugins/AlsaMixerPlugin.cxx
@@ -191,7 +191,8 @@ AlsaMixer::~AlsaMixer()
 
 gcc_pure
 static snd_mixer_elem_t *
-alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx)
+alsa_mixer_lookup_elem(snd_mixer_t *handle,
+		       const char *name, unsigned idx) noexcept
 {
 	for (snd_mixer_elem_t *elem = snd_mixer_first_elem(handle);
 	     elem != nullptr; elem = snd_mixer_elem_next(elem)) {
diff --git a/src/mixer/plugins/SoftwareMixerPlugin.cxx b/src/mixer/plugins/SoftwareMixerPlugin.cxx
index 69491390d..14c35e7f1 100644
--- a/src/mixer/plugins/SoftwareMixerPlugin.cxx
+++ b/src/mixer/plugins/SoftwareMixerPlugin.cxx
@@ -71,7 +71,7 @@ software_mixer_init(gcc_unused EventLoop &event_loop,
 
 gcc_const
 static unsigned
-PercentVolumeToSoftwareVolume(unsigned volume)
+PercentVolumeToSoftwareVolume(unsigned volume) noexcept
 {
 	assert(volume <= 100);
 
diff --git a/src/neighbor/Glue.cxx b/src/neighbor/Glue.cxx
index f82abe899..f82e47fb8 100644
--- a/src/neighbor/Glue.cxx
+++ b/src/neighbor/Glue.cxx
@@ -93,7 +93,7 @@ NeighborGlue::Close()
 }
 
 NeighborGlue::List
-NeighborGlue::GetList() const
+NeighborGlue::GetList() const noexcept
 {
 	List result;
 
diff --git a/src/neighbor/Glue.hxx b/src/neighbor/Glue.hxx
index 68e219910..a0d749a3b 100644
--- a/src/neighbor/Glue.hxx
+++ b/src/neighbor/Glue.hxx
@@ -71,7 +71,7 @@ public:
 	 * plugins.
 	 */
 	gcc_pure
-	List GetList() const;
+	List GetList() const noexcept;
 };
 
 #endif
diff --git a/src/neighbor/Registry.cxx b/src/neighbor/Registry.cxx
index ea1c50cd6..fad045f27 100644
--- a/src/neighbor/Registry.cxx
+++ b/src/neighbor/Registry.cxx
@@ -36,7 +36,7 @@ const NeighborPlugin *const neighbor_plugins[] = {
 };
 
 const NeighborPlugin *
-GetNeighborPluginByName(const char *name)
+GetNeighborPluginByName(const char *name) noexcept
 {
 	for (auto i = neighbor_plugins; *i != nullptr; ++i)
 		if (strcmp((*i)->name, name) == 0)
diff --git a/src/neighbor/Registry.hxx b/src/neighbor/Registry.hxx
index f18c41d74..5e9ddfb62 100644
--- a/src/neighbor/Registry.hxx
+++ b/src/neighbor/Registry.hxx
@@ -32,6 +32,6 @@ extern const NeighborPlugin *const neighbor_plugins[];
 
 gcc_pure
 const NeighborPlugin *
-GetNeighborPluginByName(const char *name);
+GetNeighborPluginByName(const char *name) noexcept;
 
 #endif
diff --git a/src/neighbor/plugins/SmbclientNeighborPlugin.cxx b/src/neighbor/plugins/SmbclientNeighborPlugin.cxx
index 3b7a8b069..19f20b219 100644
--- a/src/neighbor/plugins/SmbclientNeighborPlugin.cxx
+++ b/src/neighbor/plugins/SmbclientNeighborPlugin.cxx
@@ -169,7 +169,7 @@ ReadServers(NeighborExplorer::List &list, const char *uri)
 
 gcc_pure
 static NeighborExplorer::List
-DetectServers()
+DetectServers() noexcept
 {
 	NeighborExplorer::List list;
 	const std::lock_guard<Mutex> protect(smbclient_mutex);
@@ -181,7 +181,7 @@ gcc_pure
 static NeighborExplorer::List::const_iterator
 FindBeforeServerByURI(NeighborExplorer::List::const_iterator prev,
 		      NeighborExplorer::List::const_iterator end,
-		      const std::string &uri)
+		      const std::string &uri) noexcept
 {
 	for (auto i = std::next(prev); i != end; prev = i, i = std::next(prev))
 		if (i->uri == uri)
diff --git a/src/net/AllocatedSocketAddress.cxx b/src/net/AllocatedSocketAddress.cxx
index d109eac8d..92781a29b 100644
--- a/src/net/AllocatedSocketAddress.cxx
+++ b/src/net/AllocatedSocketAddress.cxx
@@ -50,7 +50,7 @@ AllocatedSocketAddress::operator=(SocketAddress src)
 }
 
 void
-AllocatedSocketAddress::SetSize(size_type new_size)
+AllocatedSocketAddress::SetSize(size_type new_size) noexcept
 {
 	if (size == new_size)
 		return;
@@ -63,7 +63,7 @@ AllocatedSocketAddress::SetSize(size_type new_size)
 #ifdef HAVE_UN
 
 void
-AllocatedSocketAddress::SetLocal(const char *path)
+AllocatedSocketAddress::SetLocal(const char *path) noexcept
 {
 	const bool is_abstract = *path == '@';
 
diff --git a/src/net/AllocatedSocketAddress.hxx b/src/net/AllocatedSocketAddress.hxx
index af015a387..15aafd7d1 100644
--- a/src/net/AllocatedSocketAddress.hxx
+++ b/src/net/AllocatedSocketAddress.hxx
@@ -140,11 +140,11 @@ public:
 	 * begins with a '@', then the rest specifies an "abstract" local
 	 * address.
 	 */
-	void SetLocal(const char *path);
+	void SetLocal(const char *path) noexcept;
 #endif
 
 private:
-	void SetSize(size_type new_size);
+	void SetSize(size_type new_size) noexcept;
 };
 
 #endif
diff --git a/src/net/SocketAddress.cxx b/src/net/SocketAddress.cxx
index 10609269c..3bbb3ac1f 100644
--- a/src/net/SocketAddress.cxx
+++ b/src/net/SocketAddress.cxx
@@ -32,7 +32,7 @@
 #include <string.h>
 
 bool
-SocketAddress::operator==(SocketAddress other) const
+SocketAddress::operator==(SocketAddress other) const noexcept
 {
 	return size == other.size && memcmp(address, other.address, size) == 0;
 }
diff --git a/src/net/SocketAddress.hxx b/src/net/SocketAddress.hxx
index 31d513609..5db6d55f9 100644
--- a/src/net/SocketAddress.hxx
+++ b/src/net/SocketAddress.hxx
@@ -93,9 +93,9 @@ public:
 	}
 
 	gcc_pure
-	bool operator==(const SocketAddress other) const;
+	bool operator==(const SocketAddress other) const noexcept;
 
-	bool operator!=(const SocketAddress other) const {
+	bool operator!=(const SocketAddress other) const noexcept {
 		return !(*this == other);
 	}
 };
diff --git a/src/net/SocketError.cxx b/src/net/SocketError.cxx
index e670a3d47..082dec187 100644
--- a/src/net/SocketError.cxx
+++ b/src/net/SocketError.cxx
@@ -25,7 +25,7 @@
 
 #ifdef WIN32
 
-SocketErrorMessage::SocketErrorMessage(socket_error_t code)
+SocketErrorMessage::SocketErrorMessage(socket_error_t code) noexcept
 {
 #ifdef _UNICODE
 	wchar_t buffer[ARRAY_SIZE(msg)];
@@ -56,7 +56,7 @@ SocketErrorMessage::SocketErrorMessage(socket_error_t code)
 
 #else
 
-SocketErrorMessage::SocketErrorMessage(socket_error_t code)
+SocketErrorMessage::SocketErrorMessage(socket_error_t code) noexcept
 	:msg(strerror(code)) {}
 
 #endif
diff --git a/src/net/SocketError.hxx b/src/net/SocketError.hxx
index a86ceb86c..6e3a7799c 100644
--- a/src/net/SocketError.hxx
+++ b/src/net/SocketError.hxx
@@ -33,7 +33,7 @@ typedef int socket_error_t;
 
 gcc_pure
 static inline socket_error_t
-GetSocketError()
+GetSocketError() noexcept
 {
 #ifdef WIN32
 	return WSAGetLastError();
@@ -44,7 +44,7 @@ GetSocketError()
 
 gcc_const
 static inline bool
-IsSocketErrorAgain(socket_error_t code)
+IsSocketErrorAgain(socket_error_t code) noexcept
 {
 #ifdef WIN32
 	return code == WSAEINPROGRESS;
@@ -55,7 +55,7 @@ IsSocketErrorAgain(socket_error_t code)
 
 gcc_const
 static inline bool
-IsSocketErrorInterruped(socket_error_t code)
+IsSocketErrorInterruped(socket_error_t code) noexcept
 {
 #ifdef WIN32
 	return code == WSAEINTR;
@@ -66,7 +66,7 @@ IsSocketErrorInterruped(socket_error_t code)
 
 gcc_const
 static inline bool
-IsSocketErrorClosed(socket_error_t code)
+IsSocketErrorClosed(socket_error_t code) noexcept
 {
 #ifdef WIN32
 	return code == WSAECONNRESET;
@@ -88,11 +88,7 @@ class SocketErrorMessage {
 #endif
 
 public:
-#ifdef WIN32
-	explicit SocketErrorMessage(socket_error_t code=GetSocketError());
-#else
-	explicit SocketErrorMessage(socket_error_t code=GetSocketError());
-#endif
+	explicit SocketErrorMessage(socket_error_t code=GetSocketError()) noexcept;
 
 	operator const char *() const {
 		return msg;
@@ -101,7 +97,7 @@ public:
 
 gcc_const
 static inline std::system_error
-MakeSocketError(socket_error_t code, const char *msg)
+MakeSocketError(socket_error_t code, const char *msg) noexcept
 {
 #ifdef WIN32
 	return MakeLastError(code, msg);
@@ -112,7 +108,7 @@ MakeSocketError(socket_error_t code, const char *msg)
 
 gcc_pure
 static inline std::system_error
-MakeSocketError(const char *msg)
+MakeSocketError(const char *msg) noexcept
 {
 	return MakeSocketError(GetSocketError(), msg);
 }
diff --git a/src/net/StaticSocketAddress.cxx b/src/net/StaticSocketAddress.cxx
index 70237fd48..35a8cd804 100644
--- a/src/net/StaticSocketAddress.cxx
+++ b/src/net/StaticSocketAddress.cxx
@@ -35,7 +35,7 @@
 #include <string.h>
 
 StaticSocketAddress &
-StaticSocketAddress::operator=(SocketAddress other)
+StaticSocketAddress::operator=(SocketAddress other) noexcept
 {
 	size = std::min(other.GetSize(), GetCapacity());
 	memcpy(&address, other.GetAddress(), size);
diff --git a/src/net/StaticSocketAddress.hxx b/src/net/StaticSocketAddress.hxx
index 620b74e1d..d2da90d2f 100644
--- a/src/net/StaticSocketAddress.hxx
+++ b/src/net/StaticSocketAddress.hxx
@@ -49,7 +49,7 @@ private:
 public:
 	StaticSocketAddress() = default;
 
-	StaticSocketAddress &operator=(SocketAddress other);
+	StaticSocketAddress &operator=(SocketAddress other) noexcept;
 
 	operator SocketAddress() const {
 		return SocketAddress(reinterpret_cast<const struct sockaddr *>(&address),
diff --git a/src/net/ToString.cxx b/src/net/ToString.cxx
index 7df2cb07a..f185a5e2e 100644
--- a/src/net/ToString.cxx
+++ b/src/net/ToString.cxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2015 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright (C) 2011-2017 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -53,7 +53,7 @@
 #ifdef HAVE_UN
 
 static std::string
-LocalAddressToString(const struct sockaddr_un &s_un, size_t size)
+LocalAddressToString(const struct sockaddr_un &s_un, size_t size) noexcept
 {
 	const size_t prefix_size = (size_t)
 		((struct sockaddr_un *)nullptr)->sun_path;
@@ -83,7 +83,7 @@ LocalAddressToString(const struct sockaddr_un &s_un, size_t size)
 
 gcc_pure
 static bool
-IsV4Mapped(SocketAddress address)
+IsV4Mapped(SocketAddress address) noexcept
 {
 	if (address.GetFamily() != AF_INET6)
 		return false;
@@ -96,7 +96,7 @@ IsV4Mapped(SocketAddress address)
  * Convert "::ffff:127.0.0.1" to "127.0.0.1".
  */
 static SocketAddress
-UnmapV4(SocketAddress src, struct sockaddr_in &buffer)
+UnmapV4(SocketAddress src, struct sockaddr_in &buffer) noexcept
 {
 	assert(IsV4Mapped(src));
 
@@ -113,7 +113,7 @@ UnmapV4(SocketAddress src, struct sockaddr_in &buffer)
 #endif
 
 std::string
-ToString(SocketAddress address)
+ToString(SocketAddress address) noexcept
 {
 #ifdef HAVE_UN
 	if (address.GetFamily() == AF_UNIX)
diff --git a/src/net/ToString.hxx b/src/net/ToString.hxx
index a221c6c06..4eef8656d 100644
--- a/src/net/ToString.hxx
+++ b/src/net/ToString.hxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2015 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright (C) 2011-2017 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,6 +43,6 @@ class SocketAddress;
  */
 gcc_pure
 std::string
-ToString(SocketAddress address);
+ToString(SocketAddress address) noexcept;
 
 #endif
diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index df28292e6..2f1ad25ad 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -89,7 +89,7 @@ audio_output_detect()
  */
 gcc_pure
 static MixerType
-audio_output_mixer_type(const ConfigBlock &block)
+audio_output_mixer_type(const ConfigBlock &block) noexcept
 {
 	/* read the local "mixer_type" setting */
 	const char *p = block.GetBlockValue("mixer_type");
diff --git a/src/output/Internal.cxx b/src/output/Internal.cxx
index 34d963232..875de1867 100644
--- a/src/output/Internal.cxx
+++ b/src/output/Internal.cxx
@@ -21,7 +21,7 @@
 #include "Internal.hxx"
 
 bool
-AudioOutput::IsChunkConsumed(const MusicChunk &chunk) const
+AudioOutput::IsChunkConsumed(const MusicChunk &chunk) const noexcept
 {
 	if (!open)
 		return true;
diff --git a/src/output/Internal.hxx b/src/output/Internal.hxx
index 45bd25420..8af184acd 100644
--- a/src/output/Internal.hxx
+++ b/src/output/Internal.hxx
@@ -212,10 +212,10 @@ public:
 	 * Caller must lock the mutex.
 	 */
 	gcc_pure
-	bool IsChunkConsumed(const MusicChunk &chunk) const;
+	bool IsChunkConsumed(const MusicChunk &chunk) const noexcept;
 
 	gcc_pure
-	bool LockIsChunkConsumed(const MusicChunk &chunk) {
+	bool LockIsChunkConsumed(const MusicChunk &chunk) noexcept {
 		const std::lock_guard<Mutex> protect(mutex);
 		return IsChunkConsumed(chunk);
 	}
diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index 3781d96dc..65009accb 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -108,7 +108,7 @@ MultipleOutputs::AddNullOutput(EventLoop &event_loop,
 }
 
 AudioOutputControl *
-MultipleOutputs::FindByName(const char *name)
+MultipleOutputs::FindByName(const char *name) noexcept
 {
 	for (auto *i : outputs)
 		if (strcmp(i->GetName(), name) == 0)
@@ -134,7 +134,7 @@ MultipleOutputs::EnableDisable()
 }
 
 bool
-MultipleOutputs::AllFinished() const
+MultipleOutputs::AllFinished() const noexcept
 {
 	for (auto *ao : outputs) {
 		const std::lock_guard<Mutex> protect(ao->mutex);
@@ -146,7 +146,7 @@ MultipleOutputs::AllFinished() const
 }
 
 void
-MultipleOutputs::WaitAll()
+MultipleOutputs::WaitAll() noexcept
 {
 	while (!AllFinished())
 		audio_output_client_notify.Wait();
@@ -257,7 +257,7 @@ MultipleOutputs::Open(const AudioFormat audio_format,
 }
 
 bool
-MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const
+MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const noexcept
 {
 	for (auto *ao : outputs)
 		if (!ao->LockIsChunkConsumed(*chunk))
diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx
index ccadaccbd..3be68981e 100644
--- a/src/output/MultipleOutputs.hxx
+++ b/src/output/MultipleOutputs.hxx
@@ -114,7 +114,7 @@ public:
 	 * Returns nullptr if the name does not exist.
 	 */
 	gcc_pure
-	AudioOutputControl *FindByName(const char *name);
+	AudioOutputControl *FindByName(const char *name) noexcept;
 
 	/**
 	 * Checks the "enabled" flag of all audio outputs, and if one has
@@ -200,7 +200,7 @@ public:
 	 * 0..100).  Returns -1 if no mixer can be queried.
 	 */
 	gcc_pure
-	int GetVolume() const;
+	int GetVolume() const noexcept;
 
 	/**
 	 * Sets the volume on all available mixers.
@@ -208,7 +208,7 @@ public:
 	 * @param volume the volume (range 0..100)
 	 * @return true on success, false on failure
 	 */
-	bool SetVolume(unsigned volume);
+	bool SetVolume(unsigned volume) noexcept;
 
 	/**
 	 * Similar to GetVolume(), but gets the volume only for
@@ -216,7 +216,7 @@ public:
 	 * function fails if no software mixer is configured.
 	 */
 	gcc_pure
-	int GetSoftwareVolume() const;
+	int GetSoftwareVolume() const noexcept;
 
 	/**
 	 * Similar to SetVolume(), but sets the volume only for
@@ -224,7 +224,7 @@ public:
 	 * function cannot fail, because the underlying software
 	 * mixers cannot fail either.
 	 */
-	void SetSoftwareVolume(unsigned volume);
+	void SetSoftwareVolume(unsigned volume) noexcept;
 
 private:
 	/**
@@ -232,9 +232,9 @@ private:
 	 * command.
 	 */
 	gcc_pure
-	bool AllFinished() const;
+	bool AllFinished() const noexcept;
 
-	void WaitAll();
+	void WaitAll() noexcept;
 
 	/**
 	 * Signals all audio outputs which are open.
@@ -252,7 +252,7 @@ private:
 	/**
 	 * Has this chunk been consumed by all audio outputs?
 	 */
-	bool IsChunkConsumed(const MusicChunk *chunk) const;
+	bool IsChunkConsumed(const MusicChunk *chunk) const noexcept;
 
 	/**
 	 * There's only one chunk left in the pipe (#pipe), and all
diff --git a/src/output/OutputPlugin.cxx b/src/output/OutputPlugin.cxx
index edaa50f52..1cecf0b23 100644
--- a/src/output/OutputPlugin.cxx
+++ b/src/output/OutputPlugin.cxx
@@ -64,7 +64,7 @@ ao_plugin_close(AudioOutput &ao)
 }
 
 std::chrono::steady_clock::duration
-ao_plugin_delay(AudioOutput &ao)
+ao_plugin_delay(AudioOutput &ao) noexcept
 {
 	return ao.plugin.delay != nullptr
 		? ao.plugin.delay(&ao)
diff --git a/src/output/OutputPlugin.hxx b/src/output/OutputPlugin.hxx
index 48e0f470e..8a81be663 100644
--- a/src/output/OutputPlugin.hxx
+++ b/src/output/OutputPlugin.hxx
@@ -102,7 +102,7 @@ struct AudioOutputPlugin {
 	 *
 	 * @return the duration to wait
 	 */
-	std::chrono::steady_clock::duration (*delay)(AudioOutput *data);
+	std::chrono::steady_clock::duration (*delay)(AudioOutput *data) noexcept;
 
 	/**
 	 * Display metadata for the next chunk.  Optional method,
@@ -184,7 +184,7 @@ ao_plugin_close(AudioOutput &ao);
 
 gcc_pure
 std::chrono::steady_clock::duration
-ao_plugin_delay(AudioOutput &ao);
+ao_plugin_delay(AudioOutput &ao) noexcept;
 
 void
 ao_plugin_send_tag(AudioOutput &ao, const Tag &tag);
diff --git a/src/output/SharedPipeConsumer.cxx b/src/output/SharedPipeConsumer.cxx
index ea3944fb4..f88e242a5 100644
--- a/src/output/SharedPipeConsumer.cxx
+++ b/src/output/SharedPipeConsumer.cxx
@@ -23,7 +23,7 @@
 #include "MusicPipe.hxx"
 
 const MusicChunk *
-SharedPipeConsumer::Get()
+SharedPipeConsumer::Get() noexcept
 {
 	if (chunk != nullptr) {
 		if (!consumed)
@@ -42,7 +42,7 @@ SharedPipeConsumer::Get()
 }
 
 bool
-SharedPipeConsumer::IsConsumed(const MusicChunk &_chunk) const
+SharedPipeConsumer::IsConsumed(const MusicChunk &_chunk) const noexcept
 {
 	if (chunk == nullptr)
 		return false;
diff --git a/src/output/SharedPipeConsumer.hxx b/src/output/SharedPipeConsumer.hxx
index 84bda4513..4b9efd48f 100644
--- a/src/output/SharedPipeConsumer.hxx
+++ b/src/output/SharedPipeConsumer.hxx
@@ -75,7 +75,7 @@ public:
 		chunk = nullptr;
 	}
 
-	const MusicChunk *Get();
+	const MusicChunk *Get() noexcept;
 
 	void Consume(gcc_unused const MusicChunk &_chunk) {
 		assert(chunk != nullptr);
@@ -85,9 +85,9 @@ public:
 	}
 
 	gcc_pure
-	bool IsConsumed(const MusicChunk &_chunk) const;
+	bool IsConsumed(const MusicChunk &_chunk) const noexcept;
 
-	void ClearTail(gcc_unused const MusicChunk &_chunk) {
+	void ClearTail(gcc_unused const MusicChunk &_chunk) noexcept {
 		assert(chunk == &_chunk);
 		assert(consumed);
 		chunk = nullptr;
diff --git a/src/output/Source.cxx b/src/output/Source.cxx
index e5a67f1bd..de11595f5 100644
--- a/src/output/Source.cxx
+++ b/src/output/Source.cxx
@@ -60,7 +60,7 @@ AudioOutputSource::Open(AudioFormat audio_format, const MusicPipe &_pipe,
 }
 
 void
-AudioOutputSource::Close()
+AudioOutputSource::Close() noexcept
 {
 	assert(in_audio_format.IsValid());
 	in_audio_format.Clear();
@@ -71,7 +71,7 @@ AudioOutputSource::Close()
 }
 
 void
-AudioOutputSource::Cancel()
+AudioOutputSource::Cancel() noexcept
 {
 	current_chunk = nullptr;
 	pipe.Cancel();
@@ -114,7 +114,7 @@ try {
 }
 
 void
-AudioOutputSource::CloseFilter()
+AudioOutputSource::CloseFilter() noexcept
 {
 	delete replay_gain_filter_instance;
 	replay_gain_filter_instance = nullptr;
diff --git a/src/output/Source.hxx b/src/output/Source.hxx
index c9bbd45f6..01b44521a 100644
--- a/src/output/Source.hxx
+++ b/src/output/Source.hxx
@@ -138,8 +138,8 @@ public:
 			 PreparedFilter *prepared_other_replay_gain_filter,
 			 PreparedFilter *prepared_filter);
 
-	void Close();
-	void Cancel();
+	void Close() noexcept;
+	void Cancel() noexcept;
 
 	/**
 	 * Ensure that ReadTag() or PeekData() return any input.
@@ -181,13 +181,13 @@ public:
 	 */
 	void ConsumeData(size_t nbytes) noexcept;
 
-	bool IsChunkConsumed(const MusicChunk &chunk) const {
+	bool IsChunkConsumed(const MusicChunk &chunk) const  noexcept {
 		assert(IsOpen());
 
 		return pipe.IsConsumed(chunk);
 	}
 
-	void ClearTailChunk(const MusicChunk &chunk) {
+	void ClearTailChunk(const MusicChunk &chunk) noexcept {
 		pipe.ClearTail(chunk);
 	}
 
@@ -197,7 +197,7 @@ private:
 			PreparedFilter *prepared_other_replay_gain_filter,
 			PreparedFilter *prepared_filter);
 
-	void CloseFilter();
+	void CloseFilter() noexcept;
 
 	ConstBuffer<void> GetChunkData(const MusicChunk &chunk,
 				       Filter *replay_gain_filter,
diff --git a/src/output/Wrapper.hxx b/src/output/Wrapper.hxx
index 7fa2b47ef..2301c9944 100644
--- a/src/output/Wrapper.hxx
+++ b/src/output/Wrapper.hxx
@@ -65,12 +65,11 @@ struct AudioOutputWrapper {
 	}
 
 	gcc_pure
-	static std::chrono::steady_clock::duration Delay(AudioOutput *ao) {
+	static std::chrono::steady_clock::duration Delay(AudioOutput *ao) noexcept {
 		T &t = Cast(*ao);
 		return t.Delay();
 	}
 
-	gcc_pure
 	static void SendTag(AudioOutput *ao, const Tag &tag) {
 		T &t = Cast(*ao);
 		t.SendTag(tag);
@@ -91,7 +90,6 @@ struct AudioOutputWrapper {
 		t.Cancel();
 	}
 
-	gcc_pure
 	static bool Pause(AudioOutput *ao) {
 		T &t = Cast(*ao);
 		return t.Pause();
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index 026429a5e..58071f4d1 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -483,7 +483,7 @@ alsa_test_default_device()
  */
 gcc_const
 static snd_pcm_format_t
-ToAlsaPcmFormat(SampleFormat sample_format)
+ToAlsaPcmFormat(SampleFormat sample_format) noexcept
 {
 	switch (sample_format) {
 	case SampleFormat::UNDEFINED:
@@ -521,7 +521,7 @@ ToAlsaPcmFormat(SampleFormat sample_format)
  * SND_PCM_FORMAT_UNKNOWN if the format cannot be byte-swapped.
  */
 static snd_pcm_format_t
-ByteSwapAlsaPcmFormat(snd_pcm_format_t fmt)
+ByteSwapAlsaPcmFormat(snd_pcm_format_t fmt) noexcept
 {
 	switch (fmt) {
 	case SND_PCM_FORMAT_S16_LE: return SND_PCM_FORMAT_S16_BE;
diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx
index dfa116968..a57fd44b8 100644
--- a/src/output/plugins/FifoOutputPlugin.cxx
+++ b/src/output/plugins/FifoOutputPlugin.cxx
@@ -67,7 +67,7 @@ public:
 	void Open(AudioFormat &audio_format);
 	void Close();
 
-	std::chrono::steady_clock::duration Delay() const;
+	std::chrono::steady_clock::duration Delay() const noexcept;
 	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 };
@@ -206,7 +206,7 @@ FifoOutput::Cancel()
 }
 
 inline std::chrono::steady_clock::duration
-FifoOutput::Delay() const
+FifoOutput::Delay() const noexcept
 {
 	return timer->IsStarted()
 		? timer->GetDelay()
diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx
index 3f08d50a8..8ef88963f 100644
--- a/src/output/plugins/JackOutputPlugin.cxx
+++ b/src/output/plugins/JackOutputPlugin.cxx
@@ -119,7 +119,7 @@ struct JackOutput {
 	 * on all channels.
 	 */
 	gcc_pure
-	jack_nframes_t GetAvailable() const;
+	jack_nframes_t GetAvailable() const noexcept;
 
 	void Process(jack_nframes_t nframes);
 
@@ -128,7 +128,7 @@ struct JackOutput {
 	 */
 	size_t WriteSamples(const float *src, size_t n_frames);
 
-	std::chrono::steady_clock::duration Delay() const {
+	std::chrono::steady_clock::duration Delay() const noexcept {
 		return base.pause && pause && !shutdown
 			? std::chrono::seconds(1)
 			: std::chrono::steady_clock::duration::zero();
@@ -215,7 +215,7 @@ JackOutput::JackOutput(const ConfigBlock &block)
 }
 
 inline jack_nframes_t
-JackOutput::GetAvailable() const
+JackOutput::GetAvailable() const noexcept
 {
 	size_t min = jack_ringbuffer_read_space(ringbuffer[0]);
 
diff --git a/src/output/plugins/NullOutputPlugin.cxx b/src/output/plugins/NullOutputPlugin.cxx
index 64d0eb392..1090f62b5 100644
--- a/src/output/plugins/NullOutputPlugin.cxx
+++ b/src/output/plugins/NullOutputPlugin.cxx
@@ -50,7 +50,7 @@ public:
 			delete timer;
 	}
 
-	std::chrono::steady_clock::duration Delay() const {
+	std::chrono::steady_clock::duration Delay() const noexcept {
 		return sync && timer->IsStarted()
 			? timer->GetDelay()
 			: std::chrono::steady_clock::duration::zero();
diff --git a/src/output/plugins/OpenALOutputPlugin.cxx b/src/output/plugins/OpenALOutputPlugin.cxx
index bf459aaf5..02a8364e3 100644
--- a/src/output/plugins/OpenALOutputPlugin.cxx
+++ b/src/output/plugins/OpenALOutputPlugin.cxx
@@ -59,7 +59,7 @@ class OpenALOutput {
 	void Close();
 
 	gcc_pure
-	std::chrono::steady_clock::duration Delay() const {
+	std::chrono::steady_clock::duration Delay() const noexcept {
 		return filled < NUM_BUFFERS || HasProcessed()
 			? std::chrono::steady_clock::duration::zero()
 			/* we don't know exactly how long we must wait
diff --git a/src/output/plugins/OssOutputPlugin.cxx b/src/output/plugins/OssOutputPlugin.cxx
index 8b7faceb0..60237a537 100644
--- a/src/output/plugins/OssOutputPlugin.cxx
+++ b/src/output/plugins/OssOutputPlugin.cxx
@@ -392,7 +392,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format)
  */
 gcc_const
 static int
-sample_format_to_oss(SampleFormat format)
+sample_format_to_oss(SampleFormat format) noexcept
 {
 	switch (format) {
 	case SampleFormat::UNDEFINED:
@@ -431,7 +431,7 @@ sample_format_to_oss(SampleFormat format)
  */
 gcc_const
 static SampleFormat
-sample_format_from_oss(int format)
+sample_format_from_oss(int format) noexcept
 {
 	switch (format) {
 	case AFMT_S8:
diff --git a/src/output/plugins/PulseOutputPlugin.cxx b/src/output/plugins/PulseOutputPlugin.cxx
index 63a5ecb81..b2fb06d6b 100644
--- a/src/output/plugins/PulseOutputPlugin.cxx
+++ b/src/output/plugins/PulseOutputPlugin.cxx
@@ -90,7 +90,6 @@ public:
 		Signal();
 	}
 
-	gcc_const
 	static bool TestDefaultDevice();
 
 	static PulseOutput *Create(EventLoop &event_loop,
diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx
index 88baacbd4..15bd031f0 100644
--- a/src/output/plugins/RoarOutputPlugin.cxx
+++ b/src/output/plugins/RoarOutputPlugin.cxx
@@ -77,7 +77,7 @@ static constexpr Domain roar_output_domain("roar_output");
 
 gcc_pure
 static int
-GetConfiguredRole(const ConfigBlock &block)
+GetConfiguredRole(const ConfigBlock &block) noexcept
 {
 	const char *role = block.GetBlockValue("role");
 	return role != nullptr
diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx
index 38d0a9825..847ab3b95 100644
--- a/src/output/plugins/ShoutOutputPlugin.cxx
+++ b/src/output/plugins/ShoutOutputPlugin.cxx
@@ -64,7 +64,7 @@ struct ShoutOutput final {
 	void Open(AudioFormat &audio_format);
 	void Close();
 
-	std::chrono::steady_clock::duration Delay() const;
+	std::chrono::steady_clock::duration Delay() const noexcept;
 	void SendTag(const Tag &tag);
 	size_t Play(const void *chunk, size_t size);
 	void Cancel();
@@ -75,7 +75,6 @@ static int shout_init_count;
 
 static constexpr Domain shout_output_domain("shout_output");
 
-gcc_pure
 static const char *
 require_block_string(const ConfigBlock &block, const char *name)
 {
@@ -362,7 +361,7 @@ ShoutOutput::Open(AudioFormat &audio_format)
 }
 
 std::chrono::steady_clock::duration
-ShoutOutput::Delay() const
+ShoutOutput::Delay() const noexcept
 {
 	int delay = shout_delay(shout_conn);
 	if (delay < 0)
diff --git a/src/output/plugins/httpd/HttpdClient.cxx b/src/output/plugins/httpd/HttpdClient.cxx
index 06f94f239..755074790 100644
--- a/src/output/plugins/httpd/HttpdClient.cxx
+++ b/src/output/plugins/httpd/HttpdClient.cxx
@@ -249,7 +249,7 @@ HttpdClient::TryWritePageN(const Page &page, size_t position, ssize_t n)
 }
 
 ssize_t
-HttpdClient::GetBytesTillMetaData() const
+HttpdClient::GetBytesTillMetaData() const noexcept
 {
 	if (metadata_requested &&
 	    current_page->GetSize() - current_position > metaint - metadata_fill)
diff --git a/src/output/plugins/httpd/HttpdClient.hxx b/src/output/plugins/httpd/HttpdClient.hxx
index f9bd7ece1..5ccd2fe26 100644
--- a/src/output/plugins/httpd/HttpdClient.hxx
+++ b/src/output/plugins/httpd/HttpdClient.hxx
@@ -168,7 +168,7 @@ public:
 	bool SendResponse();
 
 	gcc_pure
-	ssize_t GetBytesTillMetaData() const;
+	ssize_t GetBytesTillMetaData() const noexcept;
 
 	ssize_t TryWritePage(const Page &page, size_t position);
 	ssize_t TryWritePageN(const Page &page, size_t position, ssize_t n);
diff --git a/src/output/plugins/httpd/HttpdInternal.hxx b/src/output/plugins/httpd/HttpdInternal.hxx
index 6c0c940d8..9f3e1994e 100644
--- a/src/output/plugins/httpd/HttpdInternal.hxx
+++ b/src/output/plugins/httpd/HttpdInternal.hxx
@@ -228,7 +228,7 @@ public:
 	void SendHeader(HttpdClient &client) const;
 
 	gcc_pure
-	std::chrono::steady_clock::duration Delay() const;
+	std::chrono::steady_clock::duration Delay() const noexcept;
 
 	/**
 	 * Reads data from the encoder (as much as available) and
diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.cxx b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
index e8ed6d97f..31b44dea9 100644
--- a/src/output/plugins/httpd/HttpdOutputPlugin.cxx
+++ b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
@@ -300,7 +300,7 @@ HttpdOutput::SendHeader(HttpdClient &client) const
 }
 
 inline std::chrono::steady_clock::duration
-HttpdOutput::Delay() const
+HttpdOutput::Delay() const noexcept
 {
 	if (!LockHasClients() && base.pause) {
 		/* if there's no client and this output is paused,
diff --git a/src/pcm/ChannelsConverter.cxx b/src/pcm/ChannelsConverter.cxx
index 0d446ffcb..c03c3e7ed 100644
--- a/src/pcm/ChannelsConverter.cxx
+++ b/src/pcm/ChannelsConverter.cxx
@@ -57,7 +57,7 @@ PcmChannelsConverter::Close()
 }
 
 ConstBuffer<void>
-PcmChannelsConverter::Convert(ConstBuffer<void> src)
+PcmChannelsConverter::Convert(ConstBuffer<void> src) noexcept
 {
 	switch (format) {
 	case SampleFormat::UNDEFINED:
diff --git a/src/pcm/ChannelsConverter.hxx b/src/pcm/ChannelsConverter.hxx
index 4cba279af..b14958ea1 100644
--- a/src/pcm/ChannelsConverter.hxx
+++ b/src/pcm/ChannelsConverter.hxx
@@ -75,7 +75,7 @@ public:
 	 * @return the destination buffer
 	 */
 	gcc_pure
-	ConstBuffer<void> Convert(ConstBuffer<void> src);
+	ConstBuffer<void> Convert(ConstBuffer<void> src) noexcept;
 };
 
 #endif
diff --git a/src/pcm/FloatConvert.hxx b/src/pcm/FloatConvert.hxx
index c32d2b32d..8022fd378 100644
--- a/src/pcm/FloatConvert.hxx
+++ b/src/pcm/FloatConvert.hxx
@@ -37,7 +37,7 @@ struct FloatToIntegerSampleConvert {
 	static constexpr SV factor = 1 << (DstTraits::BITS - 1);
 
 	gcc_const
-	static DV Convert(SV src) {
+	static DV Convert(SV src) noexcept {
 		return PcmClamp<F, Traits>(SL(src * factor));
 	}
 };
@@ -56,7 +56,7 @@ struct IntegerToFloatSampleConvert {
 	static constexpr DV factor = 0.5 / (1 << (SrcTraits::BITS - 2));
 
 	gcc_const
-	static DV Convert(SV src) {
+	static DV Convert(SV src) noexcept {
 		return DV(src) * factor;
 	}
 };
diff --git a/src/pcm/FormatConverter.cxx b/src/pcm/FormatConverter.cxx
index 21fe0b16a..89367e71a 100644
--- a/src/pcm/FormatConverter.cxx
+++ b/src/pcm/FormatConverter.cxx
@@ -54,7 +54,7 @@ PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format)
 }
 
 void
-PcmFormatConverter::Close()
+PcmFormatConverter::Close() noexcept
 {
 #ifndef NDEBUG
 	src_format = SampleFormat::UNDEFINED;
@@ -63,7 +63,7 @@ PcmFormatConverter::Close()
 }
 
 ConstBuffer<void>
-PcmFormatConverter::Convert(ConstBuffer<void> src)
+PcmFormatConverter::Convert(ConstBuffer<void> src) noexcept
 {
 	switch (dest_format) {
 	case SampleFormat::UNDEFINED:
diff --git a/src/pcm/FormatConverter.hxx b/src/pcm/FormatConverter.hxx
index e0381bf39..082dd4f1c 100644
--- a/src/pcm/FormatConverter.hxx
+++ b/src/pcm/FormatConverter.hxx
@@ -65,18 +65,16 @@ public:
 	/**
 	 * Closes the object.  After that, you may call Open() again.
 	 */
-	void Close();
+	void Close() noexcept;
 
 	/**
 	 * Convert a block of PCM data.
 	 *
-	 * Throws std::runtime_error on error.
-	 *
 	 * @param src the input buffer
 	 * @return the destination buffer
 	 */
 	gcc_pure
-	ConstBuffer<void> Convert(ConstBuffer<void> src);
+	ConstBuffer<void> Convert(ConstBuffer<void> src) noexcept;
 };
 
 #endif
diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx
index fce50a4f3..1054dba4c 100644
--- a/src/pcm/PcmExport.cxx
+++ b/src/pcm/PcmExport.cxx
@@ -84,7 +84,7 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels,
 }
 
 size_t
-PcmExport::GetFrameSize(const AudioFormat &audio_format) const
+PcmExport::GetFrameSize(const AudioFormat &audio_format) const noexcept
 {
 	if (pack24)
 		/* packed 24 bit samples (3 bytes per sample) */
@@ -109,7 +109,7 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const
 }
 
 unsigned
-PcmExport::Params::CalcOutputSampleRate(unsigned sample_rate) const
+PcmExport::Params::CalcOutputSampleRate(unsigned sample_rate) const noexcept
 {
 #ifdef ENABLE_DSD
 	if (dsd_u16)
@@ -132,7 +132,7 @@ PcmExport::Params::CalcOutputSampleRate(unsigned sample_rate) const
 }
 
 unsigned
-PcmExport::Params::CalcInputSampleRate(unsigned sample_rate) const
+PcmExport::Params::CalcInputSampleRate(unsigned sample_rate) const noexcept
 {
 #ifdef ENABLE_DSD
 	if (dsd_u16)
@@ -209,7 +209,7 @@ PcmExport::Export(ConstBuffer<void> data)
 }
 
 size_t
-PcmExport::CalcSourceSize(size_t size) const
+PcmExport::CalcSourceSize(size_t size) const noexcept
 {
 	if (pack24)
 		/* 32 bit to 24 bit conversion (4 to 3 bytes) */
diff --git a/src/pcm/PcmExport.hxx b/src/pcm/PcmExport.hxx
index 1639520d8..706a1131a 100644
--- a/src/pcm/PcmExport.hxx
+++ b/src/pcm/PcmExport.hxx
@@ -135,13 +135,13 @@ public:
 		 * one output word (32 bits), dividing the sample rate by 4.
 		 */
 		gcc_pure
-		unsigned CalcOutputSampleRate(unsigned input_sample_rate) const;
+		unsigned CalcOutputSampleRate(unsigned input_sample_rate) const noexcept;
 
 		/**
 		 * The inverse of CalcOutputSampleRate().
 		 */
 		gcc_pure
-		unsigned CalcInputSampleRate(unsigned output_sample_rate) const;
+		unsigned CalcInputSampleRate(unsigned output_sample_rate) const noexcept;
 	};
 
 	/**
@@ -167,7 +167,7 @@ public:
 	 * Calculate the size of one output frame.
 	 */
 	gcc_pure
-	size_t GetFrameSize(const AudioFormat &audio_format) const;
+	size_t GetFrameSize(const AudioFormat &audio_format) const noexcept;
 
 	/**
 	 * Export a PCM buffer.
@@ -183,7 +183,7 @@ public:
 	 * pcm_export() source buffer.
 	 */
 	gcc_pure
-	size_t CalcSourceSize(size_t dest_size) const;
+	size_t CalcSourceSize(size_t dest_size) const noexcept;
 };
 
 #endif
diff --git a/src/pcm/PcmFormat.cxx b/src/pcm/PcmFormat.cxx
index 76a639cd4..54608d917 100644
--- a/src/pcm/PcmFormat.cxx
+++ b/src/pcm/PcmFormat.cxx
@@ -161,7 +161,7 @@ pcm_allocate_float_to_16(PcmBuffer &buffer, ConstBuffer<float> src)
 
 ConstBuffer<int16_t>
 pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
-		  SampleFormat src_format, ConstBuffer<void> src)
+		  SampleFormat src_format, ConstBuffer<void> src) noexcept
 {
 	switch (src_format) {
 	case SampleFormat::UNDEFINED:
@@ -229,7 +229,7 @@ pcm_allocate_float_to_24(PcmBuffer &buffer, ConstBuffer<float> src)
 
 ConstBuffer<int32_t>
 pcm_convert_to_24(PcmBuffer &buffer,
-		  SampleFormat src_format, ConstBuffer<void> src)
+		  SampleFormat src_format, ConstBuffer<void> src) noexcept
 {
 	switch (src_format) {
 	case SampleFormat::UNDEFINED:
@@ -297,7 +297,7 @@ pcm_allocate_float_to_32(PcmBuffer &buffer, ConstBuffer<float> src)
 
 ConstBuffer<int32_t>
 pcm_convert_to_32(PcmBuffer &buffer,
-		  SampleFormat src_format, ConstBuffer<void> src)
+		  SampleFormat src_format, ConstBuffer<void> src) noexcept
 {
 	switch (src_format) {
 	case SampleFormat::UNDEFINED:
@@ -365,7 +365,7 @@ pcm_allocate_32_to_float(PcmBuffer &buffer, ConstBuffer<int32_t> src)
 
 ConstBuffer<float>
 pcm_convert_to_float(PcmBuffer &buffer,
-		     SampleFormat src_format, ConstBuffer<void> src)
+		     SampleFormat src_format, ConstBuffer<void> src) noexcept
 {
 	switch (src_format) {
 	case SampleFormat::UNDEFINED:
diff --git a/src/pcm/PcmFormat.hxx b/src/pcm/PcmFormat.hxx
index 9faa1a003..2c33a829a 100644
--- a/src/pcm/PcmFormat.hxx
+++ b/src/pcm/PcmFormat.hxx
@@ -40,7 +40,7 @@ class PcmDither;
 gcc_pure
 ConstBuffer<int16_t>
 pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
-		  SampleFormat src_format, ConstBuffer<void> src);
+		  SampleFormat src_format, ConstBuffer<void> src) noexcept;
 
 /**
  * Converts PCM samples to 24 bit (32 bit alignment).
@@ -52,7 +52,7 @@ pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
 gcc_pure
 ConstBuffer<int32_t>
 pcm_convert_to_24(PcmBuffer &buffer,
-		  SampleFormat src_format, ConstBuffer<void> src);
+		  SampleFormat src_format, ConstBuffer<void> src) noexcept;
 
 /**
  * Converts PCM samples to 32 bit.
@@ -64,7 +64,7 @@ pcm_convert_to_24(PcmBuffer &buffer,
 gcc_pure
 ConstBuffer<int32_t>
 pcm_convert_to_32(PcmBuffer &buffer,
-		  SampleFormat src_format, ConstBuffer<void> src);
+		  SampleFormat src_format, ConstBuffer<void> src) noexcept;
 
 /**
  * Converts PCM samples to 32 bit floating point.
@@ -76,6 +76,6 @@ pcm_convert_to_32(PcmBuffer &buffer,
 gcc_pure
 ConstBuffer<float>
 pcm_convert_to_float(PcmBuffer &buffer,
-		     SampleFormat src_format, ConstBuffer<void> src);
+		     SampleFormat src_format, ConstBuffer<void> src) noexcept;
 
 #endif
diff --git a/src/pcm/PcmUtils.hxx b/src/pcm/PcmUtils.hxx
index 556762748..b3bc058fa 100644
--- a/src/pcm/PcmUtils.hxx
+++ b/src/pcm/PcmUtils.hxx
@@ -36,7 +36,7 @@ template<SampleFormat F> struct SampleTraits;
 template<SampleFormat F, class Traits=SampleTraits<F>>
 gcc_const
 static inline typename Traits::value_type
-PcmClamp(typename Traits::long_type x)
+PcmClamp(typename Traits::long_type x) noexcept
 {
 	typedef typename Traits::value_type T;
 
diff --git a/src/pcm/SampleFormat.cxx b/src/pcm/SampleFormat.cxx
index 5d477115a..20a7c8c4a 100644
--- a/src/pcm/SampleFormat.cxx
+++ b/src/pcm/SampleFormat.cxx
@@ -22,7 +22,7 @@
 #include <assert.h>
 
 const char *
-sample_format_to_string(SampleFormat format)
+sample_format_to_string(SampleFormat format) noexcept
 {
 	switch (format) {
 	case SampleFormat::UNDEFINED:
diff --git a/src/pcm/SampleFormat.hxx b/src/pcm/SampleFormat.hxx
index 9ac2c8dab..febb89ff5 100644
--- a/src/pcm/SampleFormat.hxx
+++ b/src/pcm/SampleFormat.hxx
@@ -124,6 +124,6 @@ sample_format_size(SampleFormat format)
  */
 gcc_pure gcc_malloc
 const char *
-sample_format_to_string(SampleFormat format);
+sample_format_to_string(SampleFormat format) noexcept;
 
 #endif
diff --git a/src/pcm/SoxrResampler.cxx b/src/pcm/SoxrResampler.cxx
index 67d9f9950..621d3f970 100644
--- a/src/pcm/SoxrResampler.cxx
+++ b/src/pcm/SoxrResampler.cxx
@@ -56,7 +56,7 @@ static constexpr struct {
 
 gcc_const
 static const char *
-soxr_quality_name(unsigned long recipe)
+soxr_quality_name(unsigned long recipe) noexcept
 {
 	for (const auto *i = soxr_quality_table;; ++i) {
 		assert(i->name != nullptr);
@@ -68,7 +68,7 @@ soxr_quality_name(unsigned long recipe)
 
 gcc_pure
 static unsigned long
-soxr_parse_quality(const char *quality)
+soxr_parse_quality(const char *quality) noexcept
 {
 	if (quality == nullptr)
 		return SOXR_DEFAULT_RECIPE;
diff --git a/src/pcm/Volume.cxx b/src/pcm/Volume.cxx
index 761fd048d..97356e4d1 100644
--- a/src/pcm/Volume.cxx
+++ b/src/pcm/Volume.cxx
@@ -123,7 +123,7 @@ PcmVolume::Open(SampleFormat _format)
 }
 
 ConstBuffer<void>
-PcmVolume::Apply(ConstBuffer<void> src)
+PcmVolume::Apply(ConstBuffer<void> src) noexcept
 {
 	if (volume == PCM_VOLUME_1)
 		return src;
diff --git a/src/pcm/Volume.hxx b/src/pcm/Volume.hxx
index fde00b0f4..6a1ffde83 100644
--- a/src/pcm/Volume.hxx
+++ b/src/pcm/Volume.hxx
@@ -112,7 +112,7 @@ public:
 	 * Apply the volume level.
 	 */
 	gcc_pure
-	ConstBuffer<void> Apply(ConstBuffer<void> src);
+	ConstBuffer<void> Apply(ConstBuffer<void> src) noexcept;
 };
 
 #endif
diff --git a/src/player/Control.cxx b/src/player/Control.cxx
index d46b7e424..013b57bf5 100644
--- a/src/player/Control.cxx
+++ b/src/player/Control.cxx
@@ -152,7 +152,7 @@ PlayerControl::LockSetBorderPause(bool _border_pause)
 }
 
 player_status
-PlayerControl::LockGetStatus()
+PlayerControl::LockGetStatus() noexcept
 {
 	player_status status;
 
diff --git a/src/player/Control.hxx b/src/player/Control.hxx
index e753e3149..39e24e4f8 100644
--- a/src/player/Control.hxx
+++ b/src/player/Control.hxx
@@ -317,7 +317,7 @@ private:
 	 * To be called from the main thread.  Caller must lock the
 	 * object.
 	 */
-	void SynchronousCommand(PlayerCommand cmd) {
+	void SynchronousCommand(PlayerCommand cmd) noexcept {
 		assert(command == PlayerCommand::NONE);
 
 		command = cmd;
@@ -332,7 +332,7 @@ private:
 	 * To be called from the main thread.  This method locks the
 	 * object.
 	 */
-	void LockSynchronousCommand(PlayerCommand cmd) {
+	void LockSynchronousCommand(PlayerCommand cmd) noexcept {
 		const std::lock_guard<Mutex> protect(mutex);
 		SynchronousCommand(cmd);
 	}
@@ -383,7 +383,7 @@ public:
 	void Kill();
 
 	gcc_pure
-	player_status LockGetStatus();
+	player_status LockGetStatus() noexcept;
 
 	PlayerState GetState() const {
 		return state;
diff --git a/src/player/CrossFade.cxx b/src/player/CrossFade.cxx
index 872fd3ab0..3db5932c0 100644
--- a/src/player/CrossFade.cxx
+++ b/src/player/CrossFade.cxx
@@ -32,7 +32,7 @@ static constexpr Domain cross_fade_domain("cross_fade");
 
 gcc_pure
 static float
-mixramp_interpolate(const char *ramp_list, float required_db)
+mixramp_interpolate(const char *ramp_list, float required_db) noexcept
 {
 	float last_db = 0, last_secs = 0;
 	bool have_last = false;
@@ -91,7 +91,7 @@ CrossFadeSettings::Calculate(SignedSongTime total_time,
 			     const char *mixramp_start, const char *mixramp_prev_end,
 			     const AudioFormat af,
 			     const AudioFormat old_format,
-			     unsigned max_chunks) const
+			     unsigned max_chunks) const noexcept
 {
 	unsigned int chunks = 0;
 	float chunks_f;
diff --git a/src/player/CrossFade.hxx b/src/player/CrossFade.hxx
index a1949c9f1..9241006d8 100644
--- a/src/player/CrossFade.hxx
+++ b/src/player/CrossFade.hxx
@@ -66,7 +66,7 @@ struct CrossFadeSettings {
 			   const char *mixramp_start,
 			   const char *mixramp_prev_end,
 			   AudioFormat af, AudioFormat old_format,
-			   unsigned max_chunks) const;
+			   unsigned max_chunks) const noexcept;
 };
 
 #endif
diff --git a/src/playlist/cue/CueParser.cxx b/src/playlist/cue/CueParser.cxx
index 7695c67fc..2b4c80383 100644
--- a/src/playlist/cue/CueParser.cxx
+++ b/src/playlist/cue/CueParser.cxx
@@ -107,7 +107,7 @@ cue_parse_rem(char *p, TagBuilder &tag)
 }
 
 TagBuilder *
-CueParser::GetCurrentTag()
+CueParser::GetCurrentTag() noexcept
 {
 	if (state == HEADER)
 		return &header_tag;
@@ -139,7 +139,7 @@ cue_parse_position(const char *p)
 }
 
 void
-CueParser::Commit()
+CueParser::Commit() noexcept
 {
 	/* the caller of this library must call cue_parser_get() often
 	   enough */
@@ -158,7 +158,7 @@ CueParser::Commit()
 }
 
 void
-CueParser::Feed2(char *p)
+CueParser::Feed2(char *p) noexcept
 {
 	assert(!end);
 	assert(p != nullptr);
@@ -260,7 +260,7 @@ CueParser::Feed2(char *p)
 }
 
 void
-CueParser::Feed(const char *line)
+CueParser::Feed(const char *line) noexcept
 {
 	assert(!end);
 	assert(line != nullptr);
@@ -271,7 +271,7 @@ CueParser::Feed(const char *line)
 }
 
 void
-CueParser::Finish()
+CueParser::Finish() noexcept
 {
 	if (end)
 		/* has already been called, ignore */
@@ -282,7 +282,7 @@ CueParser::Finish()
 }
 
 std::unique_ptr<DetachedSong>
-CueParser::Get()
+CueParser::Get() noexcept
 {
 	if (finished == nullptr && end) {
 		/* cue_parser_finish() has been called already:
diff --git a/src/playlist/cue/CueParser.hxx b/src/playlist/cue/CueParser.hxx
index 687a594bc..be89a543e 100644
--- a/src/playlist/cue/CueParser.hxx
+++ b/src/playlist/cue/CueParser.hxx
@@ -98,14 +98,14 @@ public:
 	 * Feed a text line from the CUE file into the parser.  Call
 	 * Get() after this to see if a song has been finished.
 	 */
-	void Feed(const char *line);
+	void Feed(const char *line) noexcept;
 
 	/**
 	 * Tell the parser that the end of the file has been reached.  Call
 	 * Get() after this to see if a song has been finished.
 	 * This procedure must be done twice!
 	 */
-	void Finish();
+	void Finish() noexcept;
 
 	/**
 	 * Check if a song was finished by the last Feed() or Finish()
@@ -114,20 +114,20 @@ public:
 	 * @return a song object that must be freed by the caller, or NULL if
 	 * no song was finished at this time
 	 */
-	std::unique_ptr<DetachedSong> Get();
+	std::unique_ptr<DetachedSong> Get() noexcept;
 
 private:
 	gcc_pure
-	TagBuilder *GetCurrentTag();
+	TagBuilder *GetCurrentTag() noexcept;
 
 	/**
 	 * Commit the current song.  It will be moved to "previous",
 	 * so the next song may soon edit its end time (using the next
 	 * song's start time).
 	 */
-	void Commit();
+	void Commit() noexcept;
 
-	void Feed2(char *p);
+	void Feed2(char *p) noexcept;
 };
 
 #endif
diff --git a/src/protocol/ArgParser.hxx b/src/protocol/ArgParser.hxx
index 135f9e74b..8a23f25a8 100644
--- a/src/protocol/ArgParser.hxx
+++ b/src/protocol/ArgParser.hxx
@@ -21,7 +21,6 @@
 #define MPD_PROTOCOL_ARGPARSER_HXX
 
 #include "check.h"
-#include "Compiler.h"
 
 #include <limits>
 
@@ -30,15 +29,12 @@
 class SongTime;
 class SignedSongTime;
 
-gcc_pure
 uint32_t
 ParseCommandArgU32(const char *s);
 
-gcc_pure
 int
 ParseCommandArgInt(const char *s, int min_value, int max_value);
 
-gcc_pure
 int
 ParseCommandArgInt(const char *s);
 
@@ -55,31 +51,24 @@ struct RangeArg {
 	}
 };
 
-gcc_pure
 RangeArg
 ParseCommandArgRange(const char *s);
 
-gcc_pure
 unsigned
 ParseCommandArgUnsigned(const char *s, unsigned max_value);
 
-gcc_pure
 unsigned
 ParseCommandArgUnsigned(const char *s);
 
-gcc_pure
 bool
 ParseCommandArgBool(const char *s);
 
-gcc_pure
 float
 ParseCommandArgFloat(const char *s);
 
-gcc_pure
 SongTime
 ParseCommandArgSongTime(const char *s);
 
-gcc_pure
 SignedSongTime
 ParseCommandArgSignedSongTime(const char *s);
 
diff --git a/src/queue/Playlist.cxx b/src/queue/Playlist.cxx
index 2249dc8f3..667e3457f 100644
--- a/src/queue/Playlist.cxx
+++ b/src/queue/Playlist.cxx
@@ -92,7 +92,7 @@ playlist::QueuedSongStarted(PlayerControl &pc)
 }
 
 const DetachedSong *
-playlist::GetQueuedSong() const
+playlist::GetQueuedSong() const noexcept
 {
 	return playing && queued >= 0
 		? &queue.GetOrder(queued)
@@ -323,7 +323,7 @@ playlist::SetRandom(PlayerControl &pc, bool status)
 }
 
 int
-playlist::GetCurrentPosition() const
+playlist::GetCurrentPosition() const noexcept
 {
 	return current >= 0
 		? queue.OrderToPosition(current)
@@ -331,7 +331,7 @@ playlist::GetCurrentPosition() const
 }
 
 int
-playlist::GetNextPosition() const
+playlist::GetNextPosition() const noexcept
 {
 	if (current < 0)
 		return -1;
diff --git a/src/queue/Playlist.hxx b/src/queue/Playlist.hxx
index f66b1f2e7..32489e354 100644
--- a/src/queue/Playlist.hxx
+++ b/src/queue/Playlist.hxx
@@ -113,17 +113,17 @@ struct playlist {
 	}
 
 	gcc_pure
-	int GetCurrentPosition() const;
+	int GetCurrentPosition() const noexcept;
 
 	gcc_pure
-	int GetNextPosition() const;
+	int GetNextPosition() const noexcept;
 
 	/**
 	 * Returns the song object which is currently queued.  Returns
 	 * none if there is none (yet?) or if MPD isn't playing.
 	 */
 	gcc_pure
-	const DetachedSong *GetQueuedSong() const;
+	const DetachedSong *GetQueuedSong() const noexcept;
 
 	/**
 	 * This is the "PLAYLIST" event handler.  It is invoked by the
diff --git a/src/queue/Queue.cxx b/src/queue/Queue.cxx
index 6f6a9c8f7..d248f306b 100644
--- a/src/queue/Queue.cxx
+++ b/src/queue/Queue.cxx
@@ -43,7 +43,7 @@ Queue::~Queue()
 }
 
 int
-Queue::GetNextOrder(unsigned _order) const
+Queue::GetNextOrder(unsigned _order) const noexcept
 {
 	assert(_order < length);
 
@@ -60,7 +60,7 @@ Queue::GetNextOrder(unsigned _order) const
 }
 
 void
-Queue::IncrementVersion()
+Queue::IncrementVersion() noexcept
 {
 	static unsigned long max = ((uint32_t) 1 << 31) - 1;
 
@@ -75,7 +75,7 @@ Queue::IncrementVersion()
 }
 
 void
-Queue::ModifyAtOrder(unsigned _order)
+Queue::ModifyAtOrder(unsigned _order) noexcept
 {
 	assert(_order < length);
 
@@ -103,7 +103,7 @@ Queue::Append(DetachedSong &&song, uint8_t priority)
 }
 
 void
-Queue::SwapPositions(unsigned position1, unsigned position2)
+Queue::SwapPositions(unsigned position1, unsigned position2) noexcept
 {
 	unsigned id1 = items[position1].id;
 	unsigned id2 = items[position2].id;
@@ -118,7 +118,7 @@ Queue::SwapPositions(unsigned position1, unsigned position2)
 }
 
 void
-Queue::MovePostion(unsigned from, unsigned to)
+Queue::MovePostion(unsigned from, unsigned to) noexcept
 {
 	const Item tmp = items[from];
 
@@ -154,7 +154,7 @@ Queue::MovePostion(unsigned from, unsigned to)
 }
 
 void
-Queue::MoveRange(unsigned start, unsigned end, unsigned to)
+Queue::MoveRange(unsigned start, unsigned end, unsigned to) noexcept
 {
 	Item tmp[end - start];
 	// Copy the original block [start,end-1]
@@ -196,7 +196,7 @@ Queue::MoveRange(unsigned start, unsigned end, unsigned to)
 }
 
 void
-Queue::MoveOrder(unsigned from_order, unsigned to_order)
+Queue::MoveOrder(unsigned from_order, unsigned to_order) noexcept
 {
 	assert(from_order < length);
 	assert(to_order <= length);
@@ -215,7 +215,7 @@ Queue::MoveOrder(unsigned from_order, unsigned to_order)
 }
 
 void
-Queue::DeletePosition(unsigned position)
+Queue::DeletePosition(unsigned position) noexcept
 {
 	assert(position < length);
 
@@ -248,7 +248,7 @@ Queue::DeletePosition(unsigned position)
 }
 
 void
-Queue::Clear()
+Queue::Clear() noexcept
 {
 	for (unsigned i = 0; i < length; i++) {
 		Item *item = &items[i];
@@ -262,7 +262,8 @@ Queue::Clear()
 }
 
 static void
-queue_sort_order_by_priority(Queue *queue, unsigned start, unsigned end)
+queue_sort_order_by_priority(Queue *queue,
+			     unsigned start, unsigned end) noexcept
 {
 	assert(queue != nullptr);
 	assert(queue->random);
@@ -370,7 +371,7 @@ Queue::ShuffleRange(unsigned start, unsigned end)
 
 unsigned
 Queue::FindPriorityOrder(unsigned start_order, uint8_t priority,
-			 unsigned exclude_order) const
+			 unsigned exclude_order) const noexcept
 {
 	assert(random);
 	assert(start_order <= length);
@@ -386,7 +387,7 @@ Queue::FindPriorityOrder(unsigned start_order, uint8_t priority,
 }
 
 unsigned
-Queue::CountSamePriority(unsigned start_order, uint8_t priority) const
+Queue::CountSamePriority(unsigned start_order, uint8_t priority) const noexcept
 {
 	assert(random);
 	assert(start_order <= length);
diff --git a/src/queue/Queue.hxx b/src/queue/Queue.hxx
index 7ca29bfca..805c2f4de 100644
--- a/src/queue/Queue.hxx
+++ b/src/queue/Queue.hxx
@@ -232,13 +232,13 @@ struct Queue {
 	 * @return the next order number, or -1 to stop playback
 	 */
 	gcc_pure
-	int GetNextOrder(unsigned order) const;
+	int GetNextOrder(unsigned order) const noexcept;
 
 	/**
 	 * Increments the queue's version number.  This handles integer
 	 * overflow well.
 	 */
-	void IncrementVersion();
+	void IncrementVersion() noexcept;
 
 	/**
 	 * Marks the specified song as "modified".  Call
@@ -256,7 +256,7 @@ struct Queue {
 	 * IncrementVersion() after all modifications have been made.
 	 * number.
 	 */
-	void ModifyAtOrder(unsigned order);
+	void ModifyAtOrder(unsigned order) noexcept;
 
 	/**
 	 * Appends a song to the queue and returns its position.  Prior to
@@ -273,7 +273,7 @@ struct Queue {
 	/**
 	 * Swaps two songs, addressed by their position.
 	 */
-	void SwapPositions(unsigned position1, unsigned position2);
+	void SwapPositions(unsigned position1, unsigned position2) noexcept;
 
 	/**
 	 * Swaps two songs, addressed by their order number.
@@ -285,27 +285,27 @@ struct Queue {
 	/**
 	 * Moves a song to a new position in the "order" list.
 	 */
-	void MoveOrder(unsigned from_order, unsigned to_order);
+	void MoveOrder(unsigned from_order, unsigned to_order) noexcept;
 
 	/**
 	 * Moves a song to a new position.
 	 */
-	void MovePostion(unsigned from, unsigned to);
+	void MovePostion(unsigned from, unsigned to) noexcept;
 
 	/**
 	 * Moves a range of songs to a new position.
 	 */
-	void MoveRange(unsigned start, unsigned end, unsigned to);
+	void MoveRange(unsigned start, unsigned end, unsigned to) noexcept;
 
 	/**
 	 * Removes a song from the playlist.
 	 */
-	void DeletePosition(unsigned position);
+	void DeletePosition(unsigned position) noexcept;
 
 	/**
 	 * Removes all songs from the playlist.
 	 */
-	void Clear();
+	void Clear() noexcept;
 
 	/**
 	 * Initializes the "order" array, and restores "normal" order.
@@ -369,11 +369,11 @@ private:
 	 */
 	gcc_pure
 	unsigned FindPriorityOrder(unsigned start_order, uint8_t priority,
-				   unsigned exclude_order) const;
+				   unsigned exclude_order) const noexcept;
 
 	gcc_pure
 	unsigned CountSamePriority(unsigned start_order,
-				   uint8_t priority) const;
+				   uint8_t priority) const noexcept;
 };
 
 #endif
diff --git a/src/sticker/SongSticker.hxx b/src/sticker/SongSticker.hxx
index f52175e97..ea78d4e47 100644
--- a/src/sticker/SongSticker.hxx
+++ b/src/sticker/SongSticker.hxx
@@ -21,7 +21,6 @@
 #define MPD_SONG_STICKER_HXX
 
 #include "Match.hxx"
-#include "Compiler.h"
 
 #include <string>
 
@@ -34,7 +33,6 @@ class Database;
  *
  * Throws #SqliteError on error.
  */
-gcc_pure
 std::string
 sticker_song_get_value(const LightSong &song, const char *name);
 
diff --git a/src/sticker/StickerDatabase.cxx b/src/sticker/StickerDatabase.cxx
index b8ec42ead..d51b6bf96 100644
--- a/src/sticker/StickerDatabase.cxx
+++ b/src/sticker/StickerDatabase.cxx
@@ -151,7 +151,7 @@ sticker_global_finish()
 }
 
 bool
-sticker_enabled()
+sticker_enabled() noexcept
 {
 	return sticker_db != nullptr;
 }
@@ -328,7 +328,7 @@ sticker_free(Sticker *sticker)
 }
 
 const char *
-sticker_get_value(const Sticker &sticker, const char *name)
+sticker_get_value(const Sticker &sticker, const char *name) noexcept
 {
 	auto i = sticker.table.find(name);
 	if (i == sticker.table.end())
diff --git a/src/sticker/StickerDatabase.hxx b/src/sticker/StickerDatabase.hxx
index ec929af11..e533fbfbe 100644
--- a/src/sticker/StickerDatabase.hxx
+++ b/src/sticker/StickerDatabase.hxx
@@ -69,7 +69,7 @@ sticker_global_finish();
  */
 gcc_const
 bool
-sticker_enabled();
+sticker_enabled() noexcept;
 
 /**
  * Returns one value from an object's sticker record.  Returns an
@@ -125,7 +125,7 @@ sticker_free(Sticker *sticker);
  */
 gcc_pure
 const char *
-sticker_get_value(const Sticker &sticker, const char *name);
+sticker_get_value(const Sticker &sticker, const char *name) noexcept;
 
 /**
  * Iterates over all sticker items in a sticker.
diff --git a/src/storage/CompositeStorage.cxx b/src/storage/CompositeStorage.cxx
index 660e12f7b..f96a84bc3 100644
--- a/src/storage/CompositeStorage.cxx
+++ b/src/storage/CompositeStorage.cxx
@@ -109,7 +109,7 @@ CompositeStorage::Directory::~Directory()
 }
 
 const CompositeStorage::Directory *
-CompositeStorage::Directory::Find(const char *uri) const
+CompositeStorage::Directory::Find(const char *uri) const noexcept
 {
 	const Directory *directory = this;
 	while (*uri != 0) {
@@ -175,7 +175,7 @@ CompositeStorage::Directory::Unmount(const char *uri)
 
 bool
 CompositeStorage::Directory::MapToRelativeUTF8(std::string &buffer,
-					       const char *uri) const
+					       const char *uri) const noexcept
 {
 	if (storage != nullptr) {
 		const char *result = storage->MapToRelativeUTF8(uri);
@@ -197,7 +197,7 @@ CompositeStorage::Directory::MapToRelativeUTF8(std::string &buffer,
 	return false;
 }
 
-CompositeStorage::CompositeStorage()
+CompositeStorage::CompositeStorage() noexcept
 {
 }
 
@@ -206,7 +206,7 @@ CompositeStorage::~CompositeStorage()
 }
 
 Storage *
-CompositeStorage::GetMount(const char *uri)
+CompositeStorage::GetMount(const char *uri) noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 
@@ -238,7 +238,7 @@ CompositeStorage::Unmount(const char *uri)
 }
 
 CompositeStorage::FindResult
-CompositeStorage::FindStorage(const char *uri) const
+CompositeStorage::FindStorage(const char *uri) const noexcept
 {
 	FindResult result{&root, uri};
 
@@ -311,7 +311,7 @@ CompositeStorage::OpenDirectory(const char *uri)
 }
 
 std::string
-CompositeStorage::MapUTF8(const char *uri) const
+CompositeStorage::MapUTF8(const char *uri) const noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 
@@ -323,7 +323,7 @@ CompositeStorage::MapUTF8(const char *uri) const
 }
 
 AllocatedPath
-CompositeStorage::MapFS(const char *uri) const
+CompositeStorage::MapFS(const char *uri) const noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 
@@ -335,7 +335,7 @@ CompositeStorage::MapFS(const char *uri) const
 }
 
 const char *
-CompositeStorage::MapToRelativeUTF8(const char *uri) const
+CompositeStorage::MapToRelativeUTF8(const char *uri) const noexcept
 {
 	const std::lock_guard<Mutex> protect(mutex);
 
diff --git a/src/storage/CompositeStorage.hxx b/src/storage/CompositeStorage.hxx
index 96909c559..db71fad8f 100644
--- a/src/storage/CompositeStorage.hxx
+++ b/src/storage/CompositeStorage.hxx
@@ -60,7 +60,7 @@ class CompositeStorage final : public Storage {
 		}
 
 		gcc_pure
-		const Directory *Find(const char *uri) const;
+		const Directory *Find(const char *uri) const noexcept;
 
 		Directory &Make(const char *uri);
 
@@ -69,7 +69,7 @@ class CompositeStorage final : public Storage {
 
 		gcc_pure
 		bool MapToRelativeUTF8(std::string &buffer,
-				       const char *uri) const;
+				       const char *uri) const noexcept;
 	};
 
 	struct FindResult {
@@ -89,7 +89,7 @@ class CompositeStorage final : public Storage {
 	mutable std::string relative_buffer;
 
 public:
-	CompositeStorage();
+	CompositeStorage() noexcept;
 	virtual ~CompositeStorage();
 
 	/**
@@ -101,7 +101,7 @@ public:
 	 * value is being used.
 	 */
 	gcc_pure gcc_nonnull_all
-	Storage *GetMount(const char *uri);
+	Storage *GetMount(const char *uri) noexcept;
 
 	/**
 	 * Call the given function for each mounted storage, including
@@ -123,11 +123,11 @@ public:
 
 	StorageDirectoryReader *OpenDirectory(const char *uri) override;
 
-	std::string MapUTF8(const char *uri) const override;
+	std::string MapUTF8(const char *uri) const noexcept override;
 
-	AllocatedPath MapFS(const char *uri) const override;
+	AllocatedPath MapFS(const char *uri) const noexcept override;
 
-	const char *MapToRelativeUTF8(const char *uri) const override;
+	const char *MapToRelativeUTF8(const char *uri) const noexcept override;
 
 private:
 	template<typename T>
@@ -159,7 +159,7 @@ private:
 	 * the URI was used).
 	 */
 	gcc_pure
-	FindResult FindStorage(const char *uri) const;
+	FindResult FindStorage(const char *uri) const noexcept;
 
 	const char *MapToRelativeUTF8(const Directory &directory,
 				      const char *uri) const;
diff --git a/src/storage/Configured.cxx b/src/storage/Configured.cxx
index f0e7598c0..4b2cc1b5c 100644
--- a/src/storage/Configured.cxx
+++ b/src/storage/Configured.cxx
@@ -73,7 +73,7 @@ CreateConfiguredStorage(EventLoop &event_loop)
 }
 
 bool
-IsStorageConfigured()
+IsStorageConfigured() noexcept
 {
 	return config_get_string(ConfigOption::MUSIC_DIR) != nullptr;
 }
diff --git a/src/storage/Configured.hxx b/src/storage/Configured.hxx
index ec813f313..4b630af04 100644
--- a/src/storage/Configured.hxx
+++ b/src/storage/Configured.hxx
@@ -40,6 +40,6 @@ CreateConfiguredStorage(EventLoop &event_loop);
  */
 gcc_const
 bool
-IsStorageConfigured();
+IsStorageConfigured() noexcept;
 
 #endif
diff --git a/src/storage/Registry.cxx b/src/storage/Registry.cxx
index d0104359c..a919bd9da 100644
--- a/src/storage/Registry.cxx
+++ b/src/storage/Registry.cxx
@@ -43,7 +43,7 @@ const StoragePlugin *const storage_plugins[] = {
 };
 
 const StoragePlugin *
-GetStoragePluginByName(const char *name)
+GetStoragePluginByName(const char *name) noexcept
 {
 	for (auto i = storage_plugins; *i != nullptr; ++i) {
 		const StoragePlugin &plugin = **i;
diff --git a/src/storage/Registry.hxx b/src/storage/Registry.hxx
index e0930fd29..998756da7 100644
--- a/src/storage/Registry.hxx
+++ b/src/storage/Registry.hxx
@@ -35,7 +35,7 @@ extern const StoragePlugin *const storage_plugins[];
 
 gcc_nonnull_all gcc_pure
 const StoragePlugin *
-GetStoragePluginByName(const char *name);
+GetStoragePluginByName(const char *name) noexcept;
 
 gcc_nonnull_all gcc_malloc
 Storage *
diff --git a/src/storage/StorageInterface.cxx b/src/storage/StorageInterface.cxx
index a8d1597cf..a0e8ab460 100644
--- a/src/storage/StorageInterface.cxx
+++ b/src/storage/StorageInterface.cxx
@@ -23,14 +23,14 @@
 #include "fs/Traits.hxx"
 
 AllocatedPath
-Storage::MapFS(gcc_unused const char *uri_utf8) const
+Storage::MapFS(gcc_unused const char *uri_utf8) const noexcept
 {
 	return AllocatedPath::Null();
 }
 
 AllocatedPath
 Storage::MapChildFS(const char *uri_utf8,
-		    const char *child_utf8) const
+		    const char *child_utf8) const noexcept
 {
 	const auto uri2 = PathTraitsUTF8::Build(uri_utf8, child_utf8);
 	return MapFS(uri2.c_str());
diff --git a/src/storage/StorageInterface.hxx b/src/storage/StorageInterface.hxx
index 86f21b0ea..57d15ab15 100644
--- a/src/storage/StorageInterface.hxx
+++ b/src/storage/StorageInterface.hxx
@@ -64,7 +64,7 @@ public:
 	 * Map the given relative URI to an absolute URI.
 	 */
 	gcc_pure
-	virtual std::string MapUTF8(const char *uri_utf8) const = 0;
+	virtual std::string MapUTF8(const char *uri_utf8) const noexcept = 0;
 
 	/**
 	 * Map the given relative URI to a local file path.  Returns
@@ -72,11 +72,11 @@ public:
 	 * support local files.
 	 */
 	gcc_pure
-	virtual AllocatedPath MapFS(const char *uri_utf8) const;
+	virtual AllocatedPath MapFS(const char *uri_utf8) const noexcept;
 
 	gcc_pure
 	AllocatedPath MapChildFS(const char *uri_utf8,
-				 const char *child_utf8) const;
+				 const char *child_utf8) const noexcept;
 
 	/**
 	 * Check if the given URI points inside this storage.  If yes,
@@ -84,7 +84,7 @@ public:
 	 * string); if not, returns nullptr.
 	 */
 	gcc_pure
-	virtual const char *MapToRelativeUTF8(const char *uri_utf8) const = 0;
+	virtual const char *MapToRelativeUTF8(const char *uri_utf8) const noexcept = 0;
 };
 
 #endif
diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx
index 24b5709a1..e8291f1bf 100644
--- a/src/storage/plugins/CurlStorage.cxx
+++ b/src/storage/plugins/CurlStorage.cxx
@@ -65,13 +65,13 @@ public:
 
 	StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
 
-	std::string MapUTF8(const char *uri_utf8) const override;
+	std::string MapUTF8(const char *uri_utf8) const noexcept override;
 
-	const char *MapToRelativeUTF8(const char *uri_utf8) const override;
+	const char *MapToRelativeUTF8(const char *uri_utf8) const noexcept override;
 };
 
 std::string
-CurlStorage::MapUTF8(const char *uri_utf8) const
+CurlStorage::MapUTF8(const char *uri_utf8) const noexcept
 {
 	assert(uri_utf8 != nullptr);
 
@@ -84,7 +84,7 @@ CurlStorage::MapUTF8(const char *uri_utf8) const
 }
 
 const char *
-CurlStorage::MapToRelativeUTF8(const char *uri_utf8) const
+CurlStorage::MapToRelativeUTF8(const char *uri_utf8) const noexcept
 {
 	// TODO: escape/unescape?
 
@@ -435,7 +435,7 @@ CurlStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow)
 
 gcc_pure
 static const char *
-UriPathOrSlash(const char *uri)
+UriPathOrSlash(const char *uri) noexcept
 {
 	const char *path = uri_get_path(uri);
 	if (path == nullptr)
diff --git a/src/storage/plugins/LocalStorage.cxx b/src/storage/plugins/LocalStorage.cxx
index 59e0c34f3..816286b1b 100644
--- a/src/storage/plugins/LocalStorage.cxx
+++ b/src/storage/plugins/LocalStorage.cxx
@@ -61,17 +61,16 @@ public:
 
 	StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
 
-	std::string MapUTF8(const char *uri_utf8) const override;
+	std::string MapUTF8(const char *uri_utf8) const noexcept override;
 
-	AllocatedPath MapFS(const char *uri_utf8) const override;
+	AllocatedPath MapFS(const char *uri_utf8) const noexcept override;
 
-	const char *MapToRelativeUTF8(const char *uri_utf8) const override;
+	const char *MapToRelativeUTF8(const char *uri_utf8) const noexcept override;
 
 private:
 	AllocatedPath MapFSOrThrow(const char *uri_utf8) const;
 };
 
-gcc_pure
 static StorageFileInfo
 Stat(Path path, bool follow)
 {
@@ -97,7 +96,7 @@ Stat(Path path, bool follow)
 }
 
 std::string
-LocalStorage::MapUTF8(const char *uri_utf8) const
+LocalStorage::MapUTF8(const char *uri_utf8) const noexcept
 {
 	assert(uri_utf8 != nullptr);
 
@@ -120,7 +119,7 @@ LocalStorage::MapFSOrThrow(const char *uri_utf8) const
 }
 
 AllocatedPath
-LocalStorage::MapFS(const char *uri_utf8) const
+LocalStorage::MapFS(const char *uri_utf8) const noexcept
 {
 	try {
 		return MapFSOrThrow(uri_utf8);
@@ -130,7 +129,7 @@ LocalStorage::MapFS(const char *uri_utf8) const
 }
 
 const char *
-LocalStorage::MapToRelativeUTF8(const char *uri_utf8) const
+LocalStorage::MapToRelativeUTF8(const char *uri_utf8) const noexcept
 {
 	return PathTraitsUTF8::Relative(base_utf8.c_str(), uri_utf8);
 }
@@ -149,7 +148,7 @@ LocalStorage::OpenDirectory(const char *uri_utf8)
 
 gcc_pure
 static bool
-SkipNameFS(PathTraitsFS::const_pointer_type name_fs)
+SkipNameFS(PathTraitsFS::const_pointer_type name_fs) noexcept
 {
 	return name_fs[0] == '.' &&
 		(name_fs[1] == 0 ||
diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx
index fcf083b02..a544e8460 100644
--- a/src/storage/plugins/NfsStorage.cxx
+++ b/src/storage/plugins/NfsStorage.cxx
@@ -87,9 +87,9 @@ public:
 
 	StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
 
-	std::string MapUTF8(const char *uri_utf8) const override;
+	std::string MapUTF8(const char *uri_utf8) const noexcept override;
 
-	const char *MapToRelativeUTF8(const char *uri_utf8) const override;
+	const char *MapToRelativeUTF8(const char *uri_utf8) const noexcept override;
 
 	/* virtual methods from NfsLease */
 	void OnNfsConnectionReady() final {
@@ -223,7 +223,7 @@ UriToNfsPath(const char *_uri_utf8)
 }
 
 std::string
-NfsStorage::MapUTF8(const char *uri_utf8) const
+NfsStorage::MapUTF8(const char *uri_utf8) const noexcept
 {
 	assert(uri_utf8 != nullptr);
 
@@ -234,7 +234,7 @@ NfsStorage::MapUTF8(const char *uri_utf8) const
 }
 
 const char *
-NfsStorage::MapToRelativeUTF8(const char *uri_utf8) const
+NfsStorage::MapToRelativeUTF8(const char *uri_utf8) const noexcept
 {
 	return PathTraitsUTF8::Relative(base.c_str(), uri_utf8);
 }
@@ -291,7 +291,7 @@ NfsStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow)
 
 gcc_pure
 static bool
-SkipNameFS(const char *name)
+SkipNameFS(const char *name) noexcept
 {
 	return name[0] == '.' &&
 		(name[1] == 0 ||
diff --git a/src/storage/plugins/SmbclientStorage.cxx b/src/storage/plugins/SmbclientStorage.cxx
index 4254d6e9f..a87cdd569 100644
--- a/src/storage/plugins/SmbclientStorage.cxx
+++ b/src/storage/plugins/SmbclientStorage.cxx
@@ -69,13 +69,13 @@ public:
 
 	StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
 
-	std::string MapUTF8(const char *uri_utf8) const override;
+	std::string MapUTF8(const char *uri_utf8) const noexcept override;
 
-	const char *MapToRelativeUTF8(const char *uri_utf8) const override;
+	const char *MapToRelativeUTF8(const char *uri_utf8) const noexcept override;
 };
 
 std::string
-SmbclientStorage::MapUTF8(const char *uri_utf8) const
+SmbclientStorage::MapUTF8(const char *uri_utf8) const noexcept
 {
 	assert(uri_utf8 != nullptr);
 
@@ -86,7 +86,7 @@ SmbclientStorage::MapUTF8(const char *uri_utf8) const
 }
 
 const char *
-SmbclientStorage::MapToRelativeUTF8(const char *uri_utf8) const
+SmbclientStorage::MapToRelativeUTF8(const char *uri_utf8) const noexcept
 {
 	return PathTraitsUTF8::Relative(base.c_str(), uri_utf8);
 }
@@ -143,7 +143,7 @@ SmbclientStorage::OpenDirectory(const char *uri_utf8)
 
 gcc_pure
 static bool
-SkipNameFS(const char *name)
+SkipNameFS(const char *name) noexcept
 {
 	return name[0] == '.' &&
 		(name[1] == 0 ||
diff --git a/src/system/Error.hxx b/src/system/Error.hxx
index 32887ec25..4d89e12c8 100644
--- a/src/system/Error.hxx
+++ b/src/system/Error.hxx
@@ -149,7 +149,7 @@ FormatErrno(const char *fmt, Args&&... args)
 
 gcc_pure
 static inline bool
-IsFileNotFound(const std::system_error &e)
+IsFileNotFound(const std::system_error &e) noexcept
 {
 #ifdef WIN32
 	return e.code().category() == std::system_category() &&
@@ -162,7 +162,7 @@ IsFileNotFound(const std::system_error &e)
 
 gcc_pure
 static inline bool
-IsPathNotFound(const std::system_error &e)
+IsPathNotFound(const std::system_error &e) noexcept
 {
 #ifdef WIN32
 	return e.code().category() == std::system_category() &&
@@ -175,7 +175,7 @@ IsPathNotFound(const std::system_error &e)
 
 gcc_pure
 static inline bool
-IsAccessDenied(const std::system_error &e)
+IsAccessDenied(const std::system_error &e) noexcept
 {
 #ifdef WIN32
 	return e.code().category() == std::system_category() &&
diff --git a/src/system/FileDescriptor.cxx b/src/system/FileDescriptor.cxx
index 68bb3c022..e570090c4 100644
--- a/src/system/FileDescriptor.cxx
+++ b/src/system/FileDescriptor.cxx
@@ -58,14 +58,14 @@
 #endif
 
 bool
-FileDescriptor::Open(const char *pathname, int flags, mode_t mode)
+FileDescriptor::Open(const char *pathname, int flags, mode_t mode) noexcept
 {
 	fd = ::open(pathname, flags | O_NOCTTY | O_CLOEXEC, mode);
 	return IsDefined();
 }
 
 bool
-FileDescriptor::OpenReadOnly(const char *pathname)
+FileDescriptor::OpenReadOnly(const char *pathname) noexcept
 {
 	return Open(pathname, O_RDONLY);
 }
@@ -73,13 +73,13 @@ FileDescriptor::OpenReadOnly(const char *pathname)
 #ifndef WIN32
 
 bool
-FileDescriptor::OpenNonBlocking(const char *pathname)
+FileDescriptor::OpenNonBlocking(const char *pathname) noexcept
 {
 	return Open(pathname, O_RDWR | O_NONBLOCK);
 }
 
 bool
-FileDescriptor::CreatePipe(FileDescriptor &r, FileDescriptor &w)
+FileDescriptor::CreatePipe(FileDescriptor &r, FileDescriptor &w) noexcept
 {
 	int fds[2];
 
@@ -99,7 +99,7 @@ FileDescriptor::CreatePipe(FileDescriptor &r, FileDescriptor &w)
 }
 
 void
-FileDescriptor::SetNonBlocking()
+FileDescriptor::SetNonBlocking() noexcept
 {
 	assert(IsDefined());
 
@@ -108,7 +108,7 @@ FileDescriptor::SetNonBlocking()
 }
 
 void
-FileDescriptor::SetBlocking()
+FileDescriptor::SetBlocking() noexcept
 {
 	assert(IsDefined());
 
@@ -121,7 +121,7 @@ FileDescriptor::SetBlocking()
 #ifdef USE_EVENTFD
 
 bool
-FileDescriptor::CreateEventFD(unsigned initval)
+FileDescriptor::CreateEventFD(unsigned initval) noexcept
 {
 	fd = ::eventfd(initval, EFD_NONBLOCK|EFD_CLOEXEC);
 	return fd >= 0;
@@ -132,7 +132,7 @@ FileDescriptor::CreateEventFD(unsigned initval)
 #ifdef USE_SIGNALFD
 
 bool
-FileDescriptor::CreateSignalFD(const sigset_t *mask)
+FileDescriptor::CreateSignalFD(const sigset_t *mask) noexcept
 {
 	int new_fd = ::signalfd(fd, mask, SFD_NONBLOCK|SFD_CLOEXEC);
 	if (new_fd < 0)
@@ -147,7 +147,7 @@ FileDescriptor::CreateSignalFD(const sigset_t *mask)
 #ifdef HAVE_INOTIFY_INIT
 
 bool
-FileDescriptor::CreateInotify()
+FileDescriptor::CreateInotify() noexcept
 {
 #ifdef HAVE_INOTIFY_INIT1
 	int new_fd = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
@@ -168,7 +168,7 @@ FileDescriptor::CreateInotify()
 #endif
 
 bool
-FileDescriptor::Rewind()
+FileDescriptor::Rewind() noexcept
 {
 	assert(IsDefined());
 
@@ -176,7 +176,7 @@ FileDescriptor::Rewind()
 }
 
 off_t
-FileDescriptor::GetSize() const
+FileDescriptor::GetSize() const noexcept
 {
 	struct stat st;
 	return ::fstat(fd, &st) >= 0
@@ -187,7 +187,7 @@ FileDescriptor::GetSize() const
 #ifndef WIN32
 
 int
-FileDescriptor::Poll(short events, int timeout) const
+FileDescriptor::Poll(short events, int timeout) const noexcept
 {
 	assert(IsDefined());
 
@@ -201,13 +201,13 @@ FileDescriptor::Poll(short events, int timeout) const
 }
 
 int
-FileDescriptor::WaitReadable(int timeout) const
+FileDescriptor::WaitReadable(int timeout) const noexcept
 {
 	return Poll(POLLIN, timeout);
 }
 
 int
-FileDescriptor::WaitWritable(int timeout) const
+FileDescriptor::WaitWritable(int timeout) const noexcept
 {
 	return Poll(POLLOUT, timeout);
 }
diff --git a/src/system/FileDescriptor.hxx b/src/system/FileDescriptor.hxx
index 89e2cab20..163418c42 100644
--- a/src/system/FileDescriptor.hxx
+++ b/src/system/FileDescriptor.hxx
@@ -70,11 +70,11 @@ public:
 		return fd;
 	}
 
-	void Set(int _fd) {
+	void Set(int _fd) noexcept {
 		fd = _fd;
 	}
 
-	int Steal() {
+	int Steal() noexcept {
 		assert(IsDefined());
 
 		int _fd = fd;
@@ -82,7 +82,7 @@ public:
 		return _fd;
 	}
 
-	void SetUndefined() {
+	void SetUndefined() noexcept {
 		fd = -1;
 	}
 
@@ -90,42 +90,42 @@ public:
 		return FileDescriptor(-1);
 	}
 
-	bool Open(const char *pathname, int flags, mode_t mode=0666);
-	bool OpenReadOnly(const char *pathname);
+	bool Open(const char *pathname, int flags, mode_t mode=0666) noexcept;
+	bool OpenReadOnly(const char *pathname) noexcept;
 
 #ifndef WIN32
-	bool OpenNonBlocking(const char *pathname);
+	bool OpenNonBlocking(const char *pathname) noexcept;
 
-	static bool CreatePipe(FileDescriptor &r, FileDescriptor &w);
+	static bool CreatePipe(FileDescriptor &r, FileDescriptor &w) noexcept;
 
 	/**
 	 * Enable non-blocking mode on this file descriptor.
 	 */
-	void SetNonBlocking();
+	void SetNonBlocking() noexcept;
 
 	/**
 	 * Enable blocking mode on this file descriptor.
 	 */
-	void SetBlocking();
+	void SetBlocking() noexcept;
 
 	/**
 	 * Duplicate the file descriptor onto the given file descriptor.
 	 */
-	bool Duplicate(int new_fd) const {
+	bool Duplicate(int new_fd) const noexcept {
 		return ::dup2(Get(), new_fd) == 0;
 	}
 #endif
 
 #ifdef USE_EVENTFD
-	bool CreateEventFD(unsigned initval=0);
+	bool CreateEventFD(unsigned initval=0) noexcept;
 #endif
 
 #ifdef USE_SIGNALFD
-	bool CreateSignalFD(const sigset_t *mask);
+	bool CreateSignalFD(const sigset_t *mask) noexcept;
 #endif
 
 #ifdef HAVE_INOTIFY_INIT
-	bool CreateInotify();
+	bool CreateInotify() noexcept;
 #endif
 
 	/**
@@ -133,25 +133,25 @@ public:
 	 * "undefined" object.  After this call, IsDefined() is guaranteed
 	 * to return false, and this object may be reused.
 	 */
-	bool Close() {
+	bool Close() noexcept {
 		return ::close(Steal()) == 0;
 	}
 
 	/**
 	 * Rewind the pointer to the beginning of the file.
 	 */
-	bool Rewind();
+	bool Rewind() noexcept;
 
-	off_t Seek(off_t offset) {
+	off_t Seek(off_t offset) noexcept {
 		return lseek(Get(), offset, SEEK_SET);
 	}
 
-	off_t Skip(off_t offset) {
+	off_t Skip(off_t offset) noexcept {
 		return lseek(Get(), offset, SEEK_CUR);
 	}
 
 	gcc_pure
-	off_t Tell() const {
+	off_t Tell() const noexcept {
 		return lseek(Get(), 0, SEEK_CUR);
 	}
 
@@ -159,21 +159,21 @@ public:
 	 * Returns the size of the file in bytes, or -1 on error.
 	 */
 	gcc_pure
-	off_t GetSize() const;
+	off_t GetSize() const noexcept;
 
-	ssize_t Read(void *buffer, size_t length) {
+	ssize_t Read(void *buffer, size_t length) noexcept {
 		return ::read(fd, buffer, length);
 	}
 
-	ssize_t Write(const void *buffer, size_t length) {
+	ssize_t Write(const void *buffer, size_t length) noexcept {
 		return ::write(fd, buffer, length);
 	}
 
 #ifndef WIN32
-	int Poll(short events, int timeout) const;
+	int Poll(short events, int timeout) const noexcept;
 
-	int WaitReadable(int timeout) const;
-	int WaitWritable(int timeout) const;
+	int WaitReadable(int timeout) const noexcept;
+	int WaitWritable(int timeout) const noexcept;
 #endif
 };
 
diff --git a/src/tag/Builder.cxx b/src/tag/Builder.cxx
index 57f176869..868715a9f 100644
--- a/src/tag/Builder.cxx
+++ b/src/tag/Builder.cxx
@@ -153,7 +153,7 @@ TagBuilder::CommitNew()
 }
 
 bool
-TagBuilder::HasType(TagType type) const
+TagBuilder::HasType(TagType type) const noexcept
 {
 	for (auto i : items)
 		if (i->type == type)
@@ -237,7 +237,7 @@ TagBuilder::AddEmptyItem(TagType type)
 }
 
 void
-TagBuilder::RemoveAll()
+TagBuilder::RemoveAll() noexcept
 {
 	tag_pool_lock.lock();
 	for (auto i : items)
@@ -248,7 +248,7 @@ TagBuilder::RemoveAll()
 }
 
 void
-TagBuilder::RemoveType(TagType type)
+TagBuilder::RemoveType(TagType type) noexcept
 {
 	const auto begin = items.begin(), end = items.end();
 
diff --git a/src/tag/Builder.hxx b/src/tag/Builder.hxx
index b940515c6..31f00c6a8 100644
--- a/src/tag/Builder.hxx
+++ b/src/tag/Builder.hxx
@@ -124,7 +124,7 @@ public:
 	 * the specified type.
 	 */
 	gcc_pure
-	bool HasType(TagType type) const;
+	bool HasType(TagType type) const noexcept;
 
 	/**
 	 * Copy attributes and items from the other object that do not
@@ -161,12 +161,12 @@ public:
 	/**
 	 * Removes all tag items.
 	 */
-	void RemoveAll();
+	void RemoveAll() noexcept;
 
 	/**
 	 * Removes all tag items of the specified type.
 	 */
-	void RemoveType(TagType type);
+	void RemoveType(TagType type) noexcept;
 
 private:
 	gcc_nonnull_all
diff --git a/src/tag/FixString.cxx b/src/tag/FixString.cxx
index b70118dc4..2719b3767 100644
--- a/src/tag/FixString.cxx
+++ b/src/tag/FixString.cxx
@@ -29,7 +29,7 @@
 
 gcc_pure
 static const char *
-FindInvalidUTF8(const char *p, const char *const end)
+FindInvalidUTF8(const char *p, const char *const end) noexcept
 {
 	while (p < end) {
 		const size_t s = SequenceLengthUTF8(*p);
diff --git a/src/tag/Format.cxx b/src/tag/Format.cxx
index 8019d6ef8..4a35a0692 100644
--- a/src/tag/Format.cxx
+++ b/src/tag/Format.cxx
@@ -54,7 +54,7 @@ IsUnsafeChar(char ch)
 
 gcc_pure
 static bool
-HasUnsafeChar(const char *s)
+HasUnsafeChar(const char *s) noexcept
 {
 	for (; *s; ++s)
 		if (IsUnsafeChar(*s))
@@ -64,7 +64,7 @@ HasUnsafeChar(const char *s)
 }
 
 static const char *
-SanitizeString(const char *s, char *buffer, size_t buffer_size)
+SanitizeString(const char *s, char *buffer, size_t buffer_size) noexcept
 {
 	/* skip leading dots to avoid generating "../" sequences */
 	while (*s == '.')
@@ -80,7 +80,7 @@ SanitizeString(const char *s, char *buffer, size_t buffer_size)
 
 gcc_pure gcc_nonnull_all
 static const char *
-TagGetter(const void *object, const char *name)
+TagGetter(const void *object, const char *name) noexcept
 {
 	const auto &_ctx = *(const FormatTagContext *)object;
 	auto &ctx = const_cast<FormatTagContext &>(_ctx);
@@ -127,7 +127,7 @@ TagGetter(const void *object, const char *name)
 }
 
 char *
-FormatTag(const Tag &tag, const char *format)
+FormatTag(const Tag &tag, const char *format) noexcept
 {
 	FormatTagContext ctx(tag);
 	return format_object(format, &ctx, TagGetter);
diff --git a/src/tag/Format.hxx b/src/tag/Format.hxx
index cf211e010..3cda2e4f9 100644
--- a/src/tag/Format.hxx
+++ b/src/tag/Format.hxx
@@ -27,6 +27,6 @@ struct Tag;
 
 gcc_malloc gcc_nonnull_all
 char *
-FormatTag(const Tag &tag, const char *format);
+FormatTag(const Tag &tag, const char *format) noexcept;
 
 #endif
diff --git a/src/tag/Id3Load.cxx b/src/tag/Id3Load.cxx
index 50be9b76b..fe9ba0b0f 100644
--- a/src/tag/Id3Load.cxx
+++ b/src/tag/Id3Load.cxx
@@ -33,7 +33,7 @@ static constexpr size_t ID3V1_SIZE = 128;
 
 gcc_pure
 static inline bool
-tag_is_id3v1(struct id3_tag *tag)
+tag_is_id3v1(struct id3_tag *tag) noexcept
 {
 	return (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1) != 0;
 }
diff --git a/src/tag/Id3Scan.cxx b/src/tag/Id3Scan.cxx
index 495676f33..9330fbff9 100644
--- a/src/tag/Id3Scan.cxx
+++ b/src/tag/Id3Scan.cxx
@@ -61,7 +61,7 @@
 
 gcc_pure
 static id3_utf8_t *
-tag_id3_getstring(const struct id3_frame *frame, unsigned i)
+tag_id3_getstring(const struct id3_frame *frame, unsigned i) noexcept
 {
 	id3_field *field = id3_frame_field(frame, i);
 	if (field == nullptr)
@@ -207,7 +207,7 @@ tag_id3_import_comment(struct id3_tag *tag, const char *id, TagType type,
  */
 gcc_pure
 static TagType
-tag_id3_parse_txxx_name(const char *name)
+tag_id3_parse_txxx_name(const char *name) noexcept
 {
 	static constexpr struct tag_table txxx_tags[] = {
 		{ "ALBUMARTISTSORT", TAG_ALBUM_ARTIST_SORT },
diff --git a/src/tag/ParseName.cxx b/src/tag/ParseName.cxx
index eb78929a4..f9969f7b9 100644
--- a/src/tag/ParseName.cxx
+++ b/src/tag/ParseName.cxx
@@ -25,7 +25,7 @@
 #include <string.h>
 
 TagType
-tag_name_parse(const char *name)
+tag_name_parse(const char *name) noexcept
 {
 	assert(name != nullptr);
 
@@ -40,7 +40,7 @@ tag_name_parse(const char *name)
 }
 
 TagType
-tag_name_parse_i(const char *name)
+tag_name_parse_i(const char *name) noexcept
 {
 	assert(name != nullptr);
 
diff --git a/src/tag/ParseName.hxx b/src/tag/ParseName.hxx
index 80f328e91..541c0858c 100644
--- a/src/tag/ParseName.hxx
+++ b/src/tag/ParseName.hxx
@@ -29,7 +29,7 @@
  */
 gcc_pure
 TagType
-tag_name_parse(const char *name);
+tag_name_parse(const char *name) noexcept;
 
 /**
  * Parse the string, and convert it into a #TagType.  Returns
@@ -39,6 +39,6 @@ tag_name_parse(const char *name);
  */
 gcc_pure
 TagType
-tag_name_parse_i(const char *name);
+tag_name_parse_i(const char *name) noexcept;
 
 #endif
diff --git a/src/tag/Settings.hxx b/src/tag/Settings.hxx
index 77e754c6e..e3d4d3bac 100644
--- a/src/tag/Settings.hxx
+++ b/src/tag/Settings.hxx
@@ -28,14 +28,14 @@ extern TagMask global_tag_mask;
 
 gcc_const
 static inline bool
-IsTagEnabled(TagType tag)
+IsTagEnabled(TagType tag) noexcept
 {
 	return global_tag_mask.Test(tag);
 }
 
 gcc_const
 static inline bool
-IsTagEnabled(unsigned tag)
+IsTagEnabled(unsigned tag) noexcept
 {
 	return IsTagEnabled(TagType(tag));
 }
diff --git a/src/tag/Table.cxx b/src/tag/Table.cxx
index d8ca1798b..60727a497 100644
--- a/src/tag/Table.cxx
+++ b/src/tag/Table.cxx
@@ -28,7 +28,7 @@
  * in the table.
  */
 TagType
-tag_table_lookup(const struct tag_table *table, const char *name)
+tag_table_lookup(const struct tag_table *table, const char *name) noexcept
 {
 	for (; table->name != nullptr; ++table)
 		if (strcmp(name, table->name) == 0)
@@ -43,7 +43,7 @@ tag_table_lookup(const struct tag_table *table, const char *name)
  * in the table.
  */
 TagType
-tag_table_lookup_i(const struct tag_table *table, const char *name)
+tag_table_lookup_i(const struct tag_table *table, const char *name) noexcept
 {
 	for (; table->name != nullptr; ++table)
 		if (StringEqualsCaseASCII(name, table->name))
@@ -53,7 +53,7 @@ tag_table_lookup_i(const struct tag_table *table, const char *name)
 }
 
 const char *
-tag_table_lookup(const tag_table *table, TagType type)
+tag_table_lookup(const tag_table *table, TagType type) noexcept
 {
 	for (; table->name != nullptr; ++table)
 		if (table->type == type)
diff --git a/src/tag/Table.hxx b/src/tag/Table.hxx
index 3bda0f21f..f808a86ba 100644
--- a/src/tag/Table.hxx
+++ b/src/tag/Table.hxx
@@ -36,7 +36,7 @@ struct tag_table {
  */
 gcc_pure
 TagType
-tag_table_lookup(const tag_table *table, const char *name);
+tag_table_lookup(const tag_table *table, const char *name) noexcept;
 
 /**
  * Looks up a string in a tag translation table (case insensitive).
@@ -45,7 +45,7 @@ tag_table_lookup(const tag_table *table, const char *name);
  */
 gcc_pure
 TagType
-tag_table_lookup_i(const tag_table *table, const char *name);
+tag_table_lookup_i(const tag_table *table, const char *name) noexcept;
 
 /**
  * Looks up a #TagType in a tag translation table and returns its
@@ -54,6 +54,6 @@ tag_table_lookup_i(const tag_table *table, const char *name);
  */
 gcc_pure
 const char *
-tag_table_lookup(const tag_table *table, TagType type);
+tag_table_lookup(const tag_table *table, TagType type) noexcept;
 
 #endif
diff --git a/src/tag/Tag.cxx b/src/tag/Tag.cxx
index 6b7faceb9..f11134b7c 100644
--- a/src/tag/Tag.cxx
+++ b/src/tag/Tag.cxx
@@ -80,7 +80,7 @@ Tag::MergeReplace(Tag *base, Tag *add)
 }
 
 const char *
-Tag::GetValue(TagType type) const
+Tag::GetValue(TagType type) const noexcept
 {
 	assert(type < TAG_NUM_OF_ITEM_TYPES);
 
@@ -92,7 +92,7 @@ Tag::GetValue(TagType type) const
 }
 
 bool
-Tag::HasType(TagType type) const
+Tag::HasType(TagType type) const noexcept
 {
 	return GetValue(type) != nullptr;
 }
diff --git a/src/tag/Tag.hxx b/src/tag/Tag.hxx
index 31658b0a5..3821a5c46 100644
--- a/src/tag/Tag.hxx
+++ b/src/tag/Tag.hxx
@@ -133,14 +133,14 @@ struct Tag {
 	 * nullptr if none is present in this tag object.
 	 */
 	gcc_pure
-	const char *GetValue(TagType type) const;
+	const char *GetValue(TagType type) const noexcept;
 
 	/**
 	 * Checks whether the tag contains one or more items with
 	 * the specified type.
 	 */
 	gcc_pure
-	bool HasType(TagType type) const;
+	bool HasType(TagType type) const noexcept;
 
 	/**
 	 * Returns a value for sorting on the specified type, with
diff --git a/src/tag/VorbisComment.cxx b/src/tag/VorbisComment.cxx
index f29cb80ae..c312c9f18 100644
--- a/src/tag/VorbisComment.cxx
+++ b/src/tag/VorbisComment.cxx
@@ -25,7 +25,7 @@
 #include <string.h>
 
 const char *
-vorbis_comment_value(const char *entry, const char *name)
+vorbis_comment_value(const char *entry, const char *name) noexcept
 {
 	assert(entry != nullptr);
 	assert(name != nullptr);
diff --git a/src/tag/VorbisComment.hxx b/src/tag/VorbisComment.hxx
index f8635c8e1..d2ea86338 100644
--- a/src/tag/VorbisComment.hxx
+++ b/src/tag/VorbisComment.hxx
@@ -29,6 +29,6 @@
  */
 gcc_pure
 const char *
-vorbis_comment_value(const char *entry, const char *name);
+vorbis_comment_value(const char *entry, const char *name) noexcept;
 
 #endif
diff --git a/src/thread/Id.hxx b/src/thread/Id.hxx
index 3063d0098..169cb1af8 100644
--- a/src/thread/Id.hxx
+++ b/src/thread/Id.hxx
@@ -71,7 +71,7 @@ public:
 	 * Return the current thread's id .
 	 */
 	gcc_pure
-	static const ThreadId GetCurrent() {
+	static const ThreadId GetCurrent() noexcept {
 #ifdef WIN32
 		return ::GetCurrentThreadId();
 #else
@@ -91,7 +91,7 @@ public:
 	/**
 	 * Check if this thread is the current thread.
 	 */
-	bool IsInside() const {
+	bool IsInside() const noexcept {
 		return *this == GetCurrent();
 	}
 };
diff --git a/src/unix/PidFile.hxx b/src/unix/PidFile.hxx
index dbb94d8ff..0cb476755 100644
--- a/src/unix/PidFile.hxx
+++ b/src/unix/PidFile.hxx
@@ -88,7 +88,7 @@ public:
 
 gcc_pure
 static inline pid_t
-ReadPidFile(Path path)
+ReadPidFile(Path path) noexcept
 {
 	int fd = OpenFile(path, O_RDONLY, 0);
 	if (fd < 0)
diff --git a/src/util/ASCII.hxx b/src/util/ASCII.hxx
index 38cd9b765..6d31d836a 100644
--- a/src/util/ASCII.hxx
+++ b/src/util/ASCII.hxx
@@ -41,7 +41,7 @@
  */
 gcc_pure gcc_nonnull_all
 static inline bool
-StringEqualsCaseASCII(const char *a, const char *b)
+StringEqualsCaseASCII(const char *a, const char *b) noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
@@ -56,7 +56,7 @@ StringEqualsCaseASCII(const char *a, const char *b)
 
 gcc_pure gcc_nonnull_all
 static inline bool
-StringEqualsCaseASCII(const char *a, const char *b, size_t n)
+StringEqualsCaseASCII(const char *a, const char *b, size_t n) noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
diff --git a/src/util/HugeAllocator.cxx b/src/util/HugeAllocator.cxx
index 67fba1c6d..5116a5923 100644
--- a/src/util/HugeAllocator.cxx
+++ b/src/util/HugeAllocator.cxx
@@ -45,7 +45,7 @@
  */
 gcc_const
 static size_t
-AlignToPageSize(size_t size)
+AlignToPageSize(size_t size) noexcept
 {
 	static const long page_size = sysconf(_SC_PAGESIZE);
 	if (page_size <= 0)
diff --git a/src/util/PeakBuffer.cxx b/src/util/PeakBuffer.cxx
index 05d2f9e89..ea7ad94f3 100644
--- a/src/util/PeakBuffer.cxx
+++ b/src/util/PeakBuffer.cxx
@@ -32,14 +32,14 @@ PeakBuffer::~PeakBuffer()
 }
 
 bool
-PeakBuffer::IsEmpty() const
+PeakBuffer::IsEmpty() const noexcept
 {
 	return (normal_buffer == nullptr || normal_buffer->IsEmpty()) &&
 		(peak_buffer == nullptr || peak_buffer->IsEmpty());
 }
 
 WritableBuffer<void>
-PeakBuffer::Read() const
+PeakBuffer::Read() const noexcept
 {
 	if (normal_buffer != nullptr) {
 		const auto p = normal_buffer->Read();
@@ -57,7 +57,7 @@ PeakBuffer::Read() const
 }
 
 void
-PeakBuffer::Consume(size_t length)
+PeakBuffer::Consume(size_t length) noexcept
 {
 	if (normal_buffer != nullptr && !normal_buffer->IsEmpty()) {
 		normal_buffer->Consume(length);
@@ -76,7 +76,8 @@ PeakBuffer::Consume(size_t length)
 }
 
 static size_t
-AppendTo(DynamicFifoBuffer<uint8_t> &buffer, const void *data, size_t length)
+AppendTo(DynamicFifoBuffer<uint8_t> &buffer,
+	 const void *data, size_t length) noexcept
 {
 	assert(data != nullptr);
 	assert(length > 0);
diff --git a/src/util/PeakBuffer.hxx b/src/util/PeakBuffer.hxx
index a508062dc..294cba380 100644
--- a/src/util/PeakBuffer.hxx
+++ b/src/util/PeakBuffer.hxx
@@ -57,12 +57,12 @@ public:
 	PeakBuffer &operator=(const PeakBuffer &) = delete;
 
 	gcc_pure
-	bool IsEmpty() const;
+	bool IsEmpty() const noexcept;
 
 	gcc_pure
-	WritableBuffer<void> Read() const;
+	WritableBuffer<void> Read() const noexcept;
 
-	void Consume(size_t length);
+	void Consume(size_t length) noexcept;
 
 	bool Append(const void *data, size_t length);
 };
diff --git a/src/util/StringAPI.hxx b/src/util/StringAPI.hxx
index d9e89c628..85456fb8f 100644
--- a/src/util/StringAPI.hxx
+++ b/src/util/StringAPI.hxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2015 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright (C) 2010-2017 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -40,70 +40,70 @@
 
 gcc_pure gcc_nonnull_all
 static inline size_t
-StringLength(const char *p)
+StringLength(const char *p) noexcept
 {
 	return strlen(p);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const char *
-StringFind(const char *haystack, const char *needle)
+StringFind(const char *haystack, const char *needle) noexcept
 {
 	return strstr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline char *
-StringFind(char *haystack, char needle, size_t size)
+StringFind(char *haystack, char needle, size_t size) noexcept
 {
 	return (char *)memchr(haystack, needle, size);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const char *
-StringFind(const char *haystack, char needle, size_t size)
+StringFind(const char *haystack, char needle, size_t size) noexcept
 {
 	return (const char *)memchr(haystack, needle, size);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const char *
-StringFind(const char *haystack, char needle)
+StringFind(const char *haystack, char needle) noexcept
 {
 	return strchr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline char *
-StringFind(char *haystack, char needle)
+StringFind(char *haystack, char needle) noexcept
 {
 	return strchr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const char *
-StringFindLast(const char *haystack, char needle)
+StringFindLast(const char *haystack, char needle) noexcept
 {
 	return strrchr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline char *
-StringFindLast(char *haystack, char needle)
+StringFindLast(char *haystack, char needle) noexcept
 {
 	return strrchr(haystack, needle);
 }
 
 gcc_nonnull_all
 static inline void
-UnsafeCopyString(char *dest, const char *src)
+UnsafeCopyString(char *dest, const char *src) noexcept
 {
 	strcpy(dest, src);
 }
 
 gcc_nonnull_all
 static inline char *
-UnsafeCopyStringP(char *dest, const char *src)
+UnsafeCopyStringP(char *dest, const char *src) noexcept
 {
 #if defined(WIN32) || defined(__BIONIC__)
   /* emulate stpcpy() */
@@ -119,7 +119,7 @@ UnsafeCopyStringP(char *dest, const char *src)
  */
 gcc_pure gcc_nonnull_all
 static inline bool
-StringIsEqual(const char *a, const char *b)
+StringIsEqual(const char *a, const char *b) noexcept
 {
 	return strcmp(a, b) == 0;
 }
@@ -129,7 +129,7 @@ StringIsEqual(const char *a, const char *b)
  */
 gcc_pure gcc_nonnull_all
 static inline bool
-StringIsEqual(const char *a, const char *b, size_t length)
+StringIsEqual(const char *a, const char *b, size_t length) noexcept
 {
 	return strncmp(a, b, length) == 0;
 }
diff --git a/src/util/StringCompare.cxx b/src/util/StringCompare.cxx
index 0eb99034d..58ac5a2c1 100644
--- a/src/util/StringCompare.cxx
+++ b/src/util/StringCompare.cxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright (C) 2013-2017 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,7 +30,7 @@
 #include "StringCompare.hxx"
 
 bool
-StringEndsWith(const char *haystack, const char *needle)
+StringEndsWith(const char *haystack, const char *needle) noexcept
 {
 	const size_t haystack_length = strlen(haystack);
 	const size_t needle_length = strlen(needle);
@@ -41,7 +41,7 @@ StringEndsWith(const char *haystack, const char *needle)
 }
 
 const char *
-FindStringSuffix(const char *p, const char *suffix)
+FindStringSuffix(const char *p, const char *suffix) noexcept
 {
 	const size_t p_length = strlen(p);
 	const size_t suffix_length = strlen(suffix);
diff --git a/src/util/StringCompare.hxx b/src/util/StringCompare.hxx
index 39df6c519..b8c69031a 100644
--- a/src/util/StringCompare.hxx
+++ b/src/util/StringCompare.hxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright (C) 2013-2017 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,14 +45,14 @@ StringIsEmpty(const char *string)
 
 gcc_pure gcc_nonnull_all
 static inline bool
-StringStartsWith(const char *haystack, StringView needle)
+StringStartsWith(const char *haystack, StringView needle) noexcept
 {
 	return strncmp(haystack, needle.data, needle.size) == 0;
 }
 
 gcc_pure
 bool
-StringEndsWith(const char *haystack, const char *needle);
+StringEndsWith(const char *haystack, const char *needle) noexcept;
 
 /**
  * Returns the portion of the string after a prefix.  If the string
@@ -61,7 +61,7 @@ StringEndsWith(const char *haystack, const char *needle);
  */
 gcc_pure gcc_nonnull_all
 static inline const char *
-StringAfterPrefix(const char *haystack, StringView needle)
+StringAfterPrefix(const char *haystack, StringView needle) noexcept
 {
 	return StringStartsWith(haystack, needle)
 		? haystack + needle.size
@@ -74,6 +74,6 @@ StringAfterPrefix(const char *haystack, StringView needle)
  */
 gcc_pure
 const char *
-FindStringSuffix(const char *p, const char *suffix);
+FindStringSuffix(const char *p, const char *suffix) noexcept;
 
 #endif
diff --git a/src/util/StringUtil.cxx b/src/util/StringUtil.cxx
index 9f9d16c41..b8851edb6 100644
--- a/src/util/StringUtil.cxx
+++ b/src/util/StringUtil.cxx
@@ -27,7 +27,8 @@
 #include <string.h>
 
 char *
-CopyString(char *gcc_restrict dest, const char *gcc_restrict src, size_t size)
+CopyString(char *gcc_restrict dest, const char *gcc_restrict src,
+	   size_t size) noexcept
 {
 	size_t length = strlen(src);
 	if (length >= size)
@@ -39,7 +40,7 @@ CopyString(char *gcc_restrict dest, const char *gcc_restrict src, size_t size)
 }
 
 const char *
-StripLeft(const char *p)
+StripLeft(const char *p) noexcept
 {
 	while (IsWhitespaceNotNull(*p))
 		++p;
@@ -48,7 +49,7 @@ StripLeft(const char *p)
 }
 
 const char *
-StripLeft(const char *p, const char *end)
+StripLeft(const char *p, const char *end) noexcept
 {
 	while (p < end && IsWhitespaceOrNull(*p))
 		++p;
@@ -57,7 +58,7 @@ StripLeft(const char *p, const char *end)
 }
 
 const char *
-StripRight(const char *p, const char *end)
+StripRight(const char *p, const char *end) noexcept
 {
 	while (end > p && IsWhitespaceOrNull(end[-1]))
 		--end;
@@ -66,7 +67,7 @@ StripRight(const char *p, const char *end)
 }
 
 size_t
-StripRight(const char *p, size_t length)
+StripRight(const char *p, size_t length) noexcept
 {
 	while (length > 0 && IsWhitespaceOrNull(p[length - 1]))
 		--length;
@@ -75,7 +76,7 @@ StripRight(const char *p, size_t length)
 }
 
 void
-StripRight(char *p)
+StripRight(char *p) noexcept
 {
 	size_t old_length = strlen(p);
 	size_t new_length = StripRight(p, old_length);
@@ -83,7 +84,7 @@ StripRight(char *p)
 }
 
 char *
-Strip(char *p)
+Strip(char *p) noexcept
 {
 	p = StripLeft(p);
 	StripRight(p);
@@ -91,7 +92,8 @@ Strip(char *p)
 }
 
 bool
-StringArrayContainsCase(const char *const*haystack, const char *needle)
+StringArrayContainsCase(const char *const*haystack,
+			const char *needle) noexcept
 {
 	assert(haystack != nullptr);
 	assert(needle != nullptr);
@@ -104,7 +106,7 @@ StringArrayContainsCase(const char *const*haystack, const char *needle)
 }
 
 void
-ToUpperASCII(char *dest, const char *src, size_t size)
+ToUpperASCII(char *dest, const char *src, size_t size) noexcept
 {
 	assert(dest != nullptr);
 	assert(src != nullptr);
diff --git a/src/util/StringUtil.hxx b/src/util/StringUtil.hxx
index c2fc5dcbc..0fe131f25 100644
--- a/src/util/StringUtil.hxx
+++ b/src/util/StringUtil.hxx
@@ -34,7 +34,7 @@
  */
 gcc_nonnull_all
 char *
-CopyString(char *dest, const char *src, size_t size);
+CopyString(char *dest, const char *src, size_t size) noexcept;
 
 /**
  * Returns a pointer to the first non-whitespace character in the
@@ -42,32 +42,32 @@ CopyString(char *dest, const char *src, size_t size);
  */
 gcc_pure
 const char *
-StripLeft(const char *p);
+StripLeft(const char *p) noexcept;
 
 gcc_pure
 static inline char *
-StripLeft(char *p)
+StripLeft(char *p) noexcept
 {
 	return const_cast<char *>(StripLeft((const char *)p));
 }
 
 gcc_pure
 const char *
-StripLeft(const char *p, const char *end);
+StripLeft(const char *p, const char *end) noexcept;
 
 /**
  * Determine the string's end as if it was stripped on the right side.
  */
 gcc_pure
 const char *
-StripRight(const char *p, const char *end);
+StripRight(const char *p, const char *end) noexcept;
 
 /**
  * Determine the string's end as if it was stripped on the right side.
  */
 gcc_pure
 static inline char *
-StripRight(char *p, char *end)
+StripRight(char *p, char *end) noexcept
 {
 	return const_cast<char *>(StripRight((const char *)p,
 					     (const char *)end));
@@ -79,20 +79,20 @@ StripRight(char *p, char *end)
  */
 gcc_pure
 size_t
-StripRight(const char *p, size_t length);
+StripRight(const char *p, size_t length) noexcept;
 
 /**
  * Strip trailing whitespace by null-terminating the string.
  */
 void
-StripRight(char *p);
+StripRight(char *p) noexcept;
 
 /**
  * Skip whitespace at the beginning and terminate the string after the
  * last non-whitespace character.
  */
 char *
-Strip(char *p);
+Strip(char *p) noexcept;
 
 /**
  * Checks whether a string array contains the specified string.
@@ -104,7 +104,8 @@ Strip(char *p);
  */
 gcc_pure
 bool
-StringArrayContainsCase(const char *const*haystack, const char *needle);
+StringArrayContainsCase(const char *const*haystack,
+			const char *needle) noexcept;
 
 /**
  * Convert the specified ASCII string (0x00..0x7f) to upper case.
@@ -112,6 +113,6 @@ StringArrayContainsCase(const char *const*haystack, const char *needle);
  * @param size the destination buffer size
  */
 void
-ToUpperASCII(char *dest, const char *src, size_t size);
+ToUpperASCII(char *dest, const char *src, size_t size) noexcept;
 
 #endif
diff --git a/src/util/TimeParser.cxx b/src/util/TimeParser.cxx
index 1a3417928..9ce915c7f 100644
--- a/src/util/TimeParser.cxx
+++ b/src/util/TimeParser.cxx
@@ -28,6 +28,7 @@
  */
 
 #include "TimeParser.hxx"
+#include "Compiler.h"
 
 #include <stdexcept>
 
@@ -41,7 +42,7 @@
  */
 gcc_const
 static time_t
-GetTimeZoneOffset()
+GetTimeZoneOffset() noexcept
 {
 	time_t t = 1234567890;
 	struct tm tm;
diff --git a/src/util/TimeParser.hxx b/src/util/TimeParser.hxx
index 8b539b4a7..97aa0c016 100644
--- a/src/util/TimeParser.hxx
+++ b/src/util/TimeParser.hxx
@@ -30,8 +30,6 @@
 #ifndef TIME_PARSER_HXX
 #define TIME_PARSER_HXX
 
-#include "Compiler.h"
-
 #include <chrono>
 
 /**
@@ -39,7 +37,6 @@
  *
  * Throws std::runtime_error on error.
  */
-gcc_pure
 std::chrono::system_clock::time_point
 ParseTimePoint(const char *s, const char *format);
 
diff --git a/src/util/UTF8.cxx b/src/util/UTF8.cxx
index e0d0a4fd7..21ce6e1a8 100644
--- a/src/util/UTF8.cxx
+++ b/src/util/UTF8.cxx
@@ -124,7 +124,7 @@ MakeContinuation(unsigned char value)
 }
 
 bool
-ValidateUTF8(const char *p)
+ValidateUTF8(const char *p) noexcept
 {
 	for (; *p != 0; ++p) {
 		unsigned char ch = *p;
@@ -167,7 +167,7 @@ ValidateUTF8(const char *p)
 }
 
 size_t
-SequenceLengthUTF8(char ch)
+SequenceLengthUTF8(char ch) noexcept
 {
 	if (IsASCII(ch))
 		return 1;
@@ -196,14 +196,14 @@ SequenceLengthUTF8(char ch)
 template<size_t L>
 struct CheckSequenceUTF8 {
 	gcc_pure
-	bool operator()(const char *p) const {
+	bool operator()(const char *p) const noexcept {
 		return IsContinuation(*p) && CheckSequenceUTF8<L-1>()(p + 1);
 	}
 };
 
 template<>
 struct CheckSequenceUTF8<0u> {
-	constexpr bool operator()(gcc_unused const char *p) const {
+	constexpr bool operator()(gcc_unused const char *p) const noexcept {
 		return true;
 	}
 };
@@ -211,7 +211,7 @@ struct CheckSequenceUTF8<0u> {
 template<size_t L>
 gcc_pure
 static size_t
-InnerSequenceLengthUTF8(const char *p)
+InnerSequenceLengthUTF8(const char *p) noexcept
 {
 	return CheckSequenceUTF8<L>()(p)
 		? L + 1
@@ -219,7 +219,7 @@ InnerSequenceLengthUTF8(const char *p)
 }
 
 size_t
-SequenceLengthUTF8(const char *p)
+SequenceLengthUTF8(const char *p) noexcept
 {
 	const unsigned char ch = *p++;
 
@@ -246,8 +246,9 @@ SequenceLengthUTF8(const char *p)
 		return 0;
 }
 
+gcc_pure
 static const char *
-FindNonASCIIOrZero(const char *p)
+FindNonASCIIOrZero(const char *p) noexcept
 {
   while (*p != 0 && IsASCII(*p))
     ++p;
@@ -256,7 +257,7 @@ FindNonASCIIOrZero(const char *p)
 
 const char *
 Latin1ToUTF8(const char *gcc_restrict src, char *gcc_restrict buffer,
-	     size_t buffer_size)
+	     size_t buffer_size) noexcept
 {
 	const char *p = FindNonASCIIOrZero(src);
 	if (*p == 0)
@@ -294,7 +295,7 @@ Latin1ToUTF8(const char *gcc_restrict src, char *gcc_restrict buffer,
 }
 
 char *
-UnicodeToUTF8(unsigned ch, char *q)
+UnicodeToUTF8(unsigned ch, char *q) noexcept
 {
   if (gcc_likely(ch < 0x80)) {
     *q++ = (char)ch;
@@ -331,7 +332,7 @@ UnicodeToUTF8(unsigned ch, char *q)
 }
 
 size_t
-LengthUTF8(const char *p)
+LengthUTF8(const char *p) noexcept
 {
 	/* this is a very naive implementation: it does not do any
 	   verification, it just counts the bytes that are not a UTF-8
diff --git a/src/util/UTF8.hxx b/src/util/UTF8.hxx
index e829407bb..62decb4f5 100644
--- a/src/util/UTF8.hxx
+++ b/src/util/UTF8.hxx
@@ -40,7 +40,7 @@
  */
 gcc_pure gcc_nonnull_all
 bool
-ValidateUTF8(const char *p);
+ValidateUTF8(const char *p) noexcept;
 
 /**
  * @return the number of the sequence beginning with the given
@@ -48,7 +48,7 @@ ValidateUTF8(const char *p);
  */
 gcc_const
 size_t
-SequenceLengthUTF8(char ch);
+SequenceLengthUTF8(char ch) noexcept;
 
 /**
  * @return the number of the first sequence in the given string, or 0
@@ -56,7 +56,7 @@ SequenceLengthUTF8(char ch);
  */
 gcc_pure
 size_t
-SequenceLengthUTF8(const char *p);
+SequenceLengthUTF8(const char *p) noexcept;
 
 /**
  * Convert the specified string from ISO-8859-1 to UTF-8.
@@ -67,7 +67,7 @@ SequenceLengthUTF8(const char *p);
  */
 gcc_pure  gcc_nonnull_all
 const char *
-Latin1ToUTF8(const char *src, char *buffer, size_t buffer_size);
+Latin1ToUTF8(const char *src, char *buffer, size_t buffer_size) noexcept;
 
 /**
  * Convert the specified Unicode character to UTF-8 and write it to
@@ -77,7 +77,7 @@ Latin1ToUTF8(const char *src, char *buffer, size_t buffer_size);
  */
 gcc_nonnull_all
 char *
-UnicodeToUTF8(unsigned ch, char *buffer);
+UnicodeToUTF8(unsigned ch, char *buffer) noexcept;
 
 /**
  * Returns the number of characters in the string.  This is different
@@ -85,6 +85,6 @@ UnicodeToUTF8(unsigned ch, char *buffer);
  */
 gcc_pure gcc_nonnull_all
 size_t
-LengthUTF8(const char *p);
+LengthUTF8(const char *p) noexcept;
 
 #endif
diff --git a/src/util/UriUtil.cxx b/src/util/UriUtil.cxx
index 74f831513..61b90da29 100644
--- a/src/util/UriUtil.cxx
+++ b/src/util/UriUtil.cxx
@@ -39,7 +39,7 @@ IsValidSchemeChar(char ch)
 
 gcc_pure
 static bool
-IsValidScheme(StringView p)
+IsValidScheme(StringView p) noexcept
 {
 	if (p.IsEmpty() || !IsValidSchemeStart(p.front()))
 		return false;
@@ -57,7 +57,7 @@ IsValidScheme(StringView p)
  */
 gcc_pure
 static const char *
-uri_after_scheme(const char *uri)
+uri_after_scheme(const char *uri) noexcept
 {
 	if (uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
 		return uri + 2;
@@ -70,13 +70,14 @@ uri_after_scheme(const char *uri)
 		: nullptr;
 }
 
-bool uri_has_scheme(const char *uri)
+bool
+uri_has_scheme(const char *uri) noexcept
 {
 	return strstr(uri, "://") != nullptr;
 }
 
 std::string
-uri_get_scheme(const char *uri)
+uri_get_scheme(const char *uri) noexcept
 {
 	const char *end = strstr(uri, "://");
 	if (end == nullptr)
@@ -86,7 +87,7 @@ uri_get_scheme(const char *uri)
 }
 
 const char *
-uri_get_path(const char *uri)
+uri_get_path(const char *uri) noexcept
 {
 	const char *ap = uri_after_scheme(uri);
 	if (ap != nullptr)
@@ -97,7 +98,7 @@ uri_get_path(const char *uri)
 
 /* suffixes should be ascii only characters */
 const char *
-uri_get_suffix(const char *uri)
+uri_get_suffix(const char *uri) noexcept
 {
 	const char *suffix = strrchr(uri, '.');
 	if (suffix == nullptr || suffix == uri ||
@@ -113,7 +114,7 @@ uri_get_suffix(const char *uri)
 }
 
 const char *
-uri_get_suffix(const char *uri, UriSuffixBuffer &buffer)
+uri_get_suffix(const char *uri, UriSuffixBuffer &buffer) noexcept
 {
 	const char *suffix = uri_get_suffix(uri);
 	if (suffix == nullptr)
@@ -130,7 +131,7 @@ uri_get_suffix(const char *uri, UriSuffixBuffer &buffer)
 }
 
 static const char *
-verify_uri_segment(const char *p)
+verify_uri_segment(const char *p) noexcept
 {
 	unsigned dots = 0;
 	while (*p == '.') {
@@ -146,7 +147,7 @@ verify_uri_segment(const char *p)
 }
 
 bool
-uri_safe_local(const char *uri)
+uri_safe_local(const char *uri) noexcept
 {
 	while (true) {
 		uri = verify_uri_segment(uri);
@@ -164,7 +165,7 @@ uri_safe_local(const char *uri)
 
 gcc_pure
 static const char *
-SkipUriScheme(const char *uri)
+SkipUriScheme(const char *uri) noexcept
 {
 	const char *const schemes[] = { "http://", "https://", "ftp://" };
 	for (auto scheme : schemes) {
@@ -177,7 +178,7 @@ SkipUriScheme(const char *uri)
 }
 
 std::string
-uri_remove_auth(const char *uri)
+uri_remove_auth(const char *uri) noexcept
 {
 	const char *auth = SkipUriScheme(uri);
 	if (auth == nullptr)
@@ -201,7 +202,7 @@ uri_remove_auth(const char *uri)
 }
 
 bool
-uri_is_child(const char *parent, const char *child)
+uri_is_child(const char *parent, const char *child) noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
@@ -216,13 +217,13 @@ uri_is_child(const char *parent, const char *child)
 
 
 bool
-uri_is_child_or_same(const char *parent, const char *child)
+uri_is_child_or_same(const char *parent, const char *child) noexcept
 {
 	return strcmp(parent, child) == 0 || uri_is_child(parent, child);
 }
 
 std::string
-uri_apply_base(const std::string &uri, const std::string &base)
+uri_apply_base(const std::string &uri, const std::string &base) noexcept
 {
 	if (uri.front() == '/') {
 		/* absolute path: replace the whole URI path in base */
diff --git a/src/util/UriUtil.hxx b/src/util/UriUtil.hxx
index 3f673ca7b..10ed67cc0 100644
--- a/src/util/UriUtil.hxx
+++ b/src/util/UriUtil.hxx
@@ -29,14 +29,15 @@
  * "scheme://".
  */
 gcc_pure
-bool uri_has_scheme(const char *uri);
+bool
+uri_has_scheme(const char *uri) noexcept;
 
 /**
  * Returns the scheme name of the specified URI, or an empty string.
  */
 gcc_pure
 std::string
-uri_get_scheme(const char *uri);
+uri_get_scheme(const char *uri) noexcept;
 
 /**
  * Returns the URI path (including the query string) or nullptr if the
@@ -44,11 +45,11 @@ uri_get_scheme(const char *uri);
  */
 gcc_pure gcc_nonnull_all
 const char *
-uri_get_path(const char *uri);
+uri_get_path(const char *uri) noexcept;
 
 gcc_pure
 const char *
-uri_get_suffix(const char *uri);
+uri_get_suffix(const char *uri) noexcept;
 
 struct UriSuffixBuffer {
 	char data[8];
@@ -59,7 +60,7 @@ struct UriSuffixBuffer {
  */
 gcc_pure
 const char *
-uri_get_suffix(const char *uri, UriSuffixBuffer &buffer);
+uri_get_suffix(const char *uri, UriSuffixBuffer &buffer) noexcept;
 
 /**
  * Returns true if this is a safe "local" URI:
@@ -71,7 +72,7 @@ uri_get_suffix(const char *uri, UriSuffixBuffer &buffer);
  */
 gcc_pure
 bool
-uri_safe_local(const char *uri);
+uri_safe_local(const char *uri) noexcept;
 
 /**
  * Removes HTTP username and password from the URI.  This may be
@@ -81,7 +82,7 @@ uri_safe_local(const char *uri);
  */
 gcc_pure
 std::string
-uri_remove_auth(const char *uri);
+uri_remove_auth(const char *uri) noexcept;
 
 /**
  * Check whether #child specifies a resource "inside" the directory
@@ -90,11 +91,11 @@ uri_remove_auth(const char *uri);
  */
 gcc_pure gcc_nonnull_all
 bool
-uri_is_child(const char *parent, const char *child);
+uri_is_child(const char *parent, const char *child) noexcept;
 
 gcc_pure gcc_nonnull_all
 bool
-uri_is_child_or_same(const char *parent, const char *child);
+uri_is_child_or_same(const char *parent, const char *child) noexcept;
 
 /**
  * Translate the given URI in the context of #base.  For example,
@@ -102,6 +103,6 @@ uri_is_child_or_same(const char *parent, const char *child);
  */
 gcc_pure
 std::string
-uri_apply_base(const std::string &uri, const std::string &base);
+uri_apply_base(const std::string &uri, const std::string &base) noexcept;
 
 #endif
diff --git a/src/util/WStringAPI.hxx b/src/util/WStringAPI.hxx
index 1feaf78c6..f69aaf6d1 100644
--- a/src/util/WStringAPI.hxx
+++ b/src/util/WStringAPI.hxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2015 Max Kellermann <max.kellermann@gmail.com>
+ * Copyright (C) 2010-2017 Max Kellermann <max.kellermann@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,70 +36,70 @@
 
 gcc_pure gcc_nonnull_all
 static inline size_t
-StringLength(const wchar_t *p)
+StringLength(const wchar_t *p) noexcept
 {
 	return wcslen(p);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const wchar_t *
-StringFind(const wchar_t *haystack, const wchar_t *needle)
+StringFind(const wchar_t *haystack, const wchar_t *needle) noexcept
 {
 	return wcsstr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const wchar_t *
-StringFind(const wchar_t *haystack, wchar_t needle, size_t size)
+StringFind(const wchar_t *haystack, wchar_t needle, size_t size) noexcept
 {
 	return wmemchr(haystack, needle, size);
 }
 
 gcc_pure gcc_nonnull_all
 static inline wchar_t *
-StringFind(wchar_t *haystack, wchar_t needle, size_t size)
+StringFind(wchar_t *haystack, wchar_t needle, size_t size) noexcept
 {
 	return wmemchr(haystack, needle, size);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const wchar_t *
-StringFind(const wchar_t *haystack, wchar_t needle)
+StringFind(const wchar_t *haystack, wchar_t needle) noexcept
 {
 	return wcschr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline wchar_t *
-StringFind(wchar_t *haystack, wchar_t needle)
+StringFind(wchar_t *haystack, wchar_t needle) noexcept
 {
 	return wcschr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline const wchar_t *
-StringFindLast(const wchar_t *haystack, wchar_t needle)
+StringFindLast(const wchar_t *haystack, wchar_t needle) noexcept
 {
 	return wcsrchr(haystack, needle);
 }
 
 gcc_pure gcc_nonnull_all
 static inline wchar_t *
-StringFindLast(wchar_t *haystack, wchar_t needle)
+StringFindLast(wchar_t *haystack, wchar_t needle) noexcept
 {
 	return wcsrchr(haystack, needle);
 }
 
 gcc_nonnull_all
 static inline void
-UnsafeCopyString(wchar_t *dest, const wchar_t *src)
+UnsafeCopyString(wchar_t *dest, const wchar_t *src) noexcept
 {
 	wcscpy(dest, src);
 }
 
 gcc_nonnull_all
 static inline wchar_t *
-UnsafeCopyStringP(wchar_t *dest, const wchar_t *src)
+UnsafeCopyStringP(wchar_t *dest, const wchar_t *src) noexcept
 {
 #if defined(WIN32) || defined(__BIONIC__) || defined(__OpenBSD__) || \
 	defined(__NetBSD__)
@@ -119,7 +119,7 @@ UnsafeCopyStringP(wchar_t *dest, const wchar_t *src)
  */
 gcc_pure gcc_nonnull_all
 static inline bool
-StringIsEqual(const wchar_t *str1, const wchar_t *str2)
+StringIsEqual(const wchar_t *str1, const wchar_t *str2) noexcept
 {
 	return wcscmp(str1, str2) == 0;
 }
@@ -129,7 +129,7 @@ StringIsEqual(const wchar_t *str1, const wchar_t *str2)
  */
 gcc_pure gcc_nonnull_all
 static inline bool
-StringIsEqual(const wchar_t *a, const wchar_t *b, size_t length)
+StringIsEqual(const wchar_t *a, const wchar_t *b, size_t length) noexcept
 {
 	return wcsncmp(a, b, length) == 0;
 }
diff --git a/src/util/WStringCompare.cxx b/src/util/WStringCompare.cxx
index 1ffdb82c3..c030d84ac 100644
--- a/src/util/WStringCompare.cxx
+++ b/src/util/WStringCompare.cxx
@@ -24,14 +24,14 @@
 #include <string.h>
 
 bool
-StringStartsWith(const wchar_t *haystack, const wchar_t *needle)
+StringStartsWith(const wchar_t *haystack, const wchar_t *needle) noexcept
 {
 	const size_t length = StringLength(needle);
 	return StringIsEqual(haystack, needle, length);
 }
 
 bool
-StringEndsWith(const wchar_t *haystack, const wchar_t *needle)
+StringEndsWith(const wchar_t *haystack, const wchar_t *needle) noexcept
 {
 	const size_t haystack_length = StringLength(haystack);
 	const size_t needle_length = StringLength(needle);
@@ -41,7 +41,7 @@ StringEndsWith(const wchar_t *haystack, const wchar_t *needle)
 }
 
 const wchar_t *
-StringAfterPrefix(const wchar_t *string, const wchar_t *prefix)
+StringAfterPrefix(const wchar_t *string, const wchar_t *prefix) noexcept
 {
 #if !CLANG_CHECK_VERSION(3,6)
 	/* disabled on clang due to -Wtautological-pointer-compare */
@@ -56,7 +56,7 @@ StringAfterPrefix(const wchar_t *string, const wchar_t *prefix)
 }
 
 const wchar_t *
-FindStringSuffix(const wchar_t *p, const wchar_t *suffix)
+FindStringSuffix(const wchar_t *p, const wchar_t *suffix) noexcept
 {
 	const size_t p_length = StringLength(p);
 	const size_t suffix_length = StringLength(suffix);
diff --git a/src/util/WStringCompare.hxx b/src/util/WStringCompare.hxx
index ce5d3163d..03bb19794 100644
--- a/src/util/WStringCompare.hxx
+++ b/src/util/WStringCompare.hxx
@@ -42,20 +42,20 @@ StringIsEmpty(const wchar_t *string)
 
 gcc_pure
 bool
-StringStartsWith(const wchar_t *haystack, const wchar_t *needle);
+StringStartsWith(const wchar_t *haystack, const wchar_t *needle) noexcept;
 
 gcc_pure
 bool
-StringEndsWith(const wchar_t *haystack, const wchar_t *needle);
+StringEndsWith(const wchar_t *haystack, const wchar_t *needle) noexcept;
 
 /**
  * Returns the portion of the string after a prefix.  If the string
  * does not begin with the specified prefix, this function returns
  * nullptr.
  */
-gcc_nonnull_all
+gcc_pure gcc_nonnull_all
 const wchar_t *
-StringAfterPrefix(const wchar_t *string, const wchar_t *prefix);
+StringAfterPrefix(const wchar_t *string, const wchar_t *prefix) noexcept;
 
 /**
  * Check if the given string ends with the specified suffix.  If yes,
@@ -63,6 +63,6 @@ StringAfterPrefix(const wchar_t *string, const wchar_t *prefix);
  */
 gcc_pure
 const wchar_t *
-FindStringSuffix(const wchar_t *p, const wchar_t *suffix);
+FindStringSuffix(const wchar_t *p, const wchar_t *suffix) noexcept;
 
 #endif
diff --git a/test/dump_rva2.cxx b/test/dump_rva2.cxx
index 180e21902..f9d916876 100644
--- a/test/dump_rva2.cxx
+++ b/test/dump_rva2.cxx
@@ -40,7 +40,7 @@
 
 const char *
 config_get_string(gcc_unused enum ConfigOption option,
-		  const char *default_value)
+		  const char *default_value) noexcept
 {
 	return default_value;
 }
diff --git a/test/read_mixer.cxx b/test/read_mixer.cxx
index 575894cee..4c7efabe3 100644
--- a/test/read_mixer.cxx
+++ b/test/read_mixer.cxx
@@ -33,7 +33,7 @@
 #include <stdlib.h>
 
 const FilterPlugin *
-filter_plugin_by_name(gcc_unused const char *name)
+filter_plugin_by_name(gcc_unused const char *name) noexcept
 {
 	assert(false);
 	return NULL;
diff --git a/test/run_output.cxx b/test/run_output.cxx
index a4a39b826..ce926714b 100644
--- a/test/run_output.cxx
+++ b/test/run_output.cxx
@@ -54,7 +54,7 @@ public:
 };
 
 const FilterPlugin *
-filter_plugin_by_name(gcc_unused const char *name)
+filter_plugin_by_name(gcc_unused const char *name) noexcept
 {
 	assert(false);
 	return NULL;
diff --git a/test/test_rewind.cxx b/test/test_rewind.cxx
index ef417de34..ac23d598a 100644
--- a/test/test_rewind.cxx
+++ b/test/test_rewind.cxx
@@ -32,7 +32,7 @@ public:
 	}
 
 	/* virtual methods from InputStream */
-	bool IsEOF() override {
+	bool IsEOF() noexcept override {
 		return remaining == 0;
 	}
 
diff --git a/test/test_translate_song.cxx b/test/test_translate_song.cxx
index 3e8ae2111..a8c83fbb2 100644
--- a/test/test_translate_song.cxx
+++ b/test/test_translate_song.cxx
@@ -32,7 +32,7 @@ Log(const Domain &domain, gcc_unused LogLevel level, const char *msg)
 }
 
 bool
-uri_supported_scheme(const char *uri)
+uri_supported_scheme(const char *uri) noexcept
 {
 	return strncmp(uri, "http://", 7) == 0;
 }
@@ -130,13 +130,13 @@ DetachedSong::LoadFile(Path path)
 }
 
 const Database *
-Client::GetDatabase() const
+Client::GetDatabase() const noexcept
 {
 	return reinterpret_cast<const Database *>(this);
 }
 
 const Storage *
-Client::GetStorage() const
+Client::GetStorage() const noexcept
 {
 	return ::storage;
 }