Pārlūkot izejas kodu

Strict compile warnings and related fixes

Kajetan Johannes Hammerle 1 gadu atpakaļ
vecāks
revīzija
c291161c03

+ 2 - 2
data/Array.h

@@ -2,11 +2,11 @@
 #define ARRAY_H
 
 #include "utils/StringBuffer.h"
-#include <initializer_list>
 
 template<typename T, int N>
 class Array final {
-    T data[N];
+    static_assert(N > 0, "Array size must be positive");
+    T data[static_cast<unsigned int>(N)];
 
 public:
     Array() = default;

+ 7 - 1
data/ArrayList.h

@@ -8,7 +8,13 @@
 
 template<typename T, int N>
 class ArrayList final {
-    alignas(T) char data[sizeof(T) * N];
+    static_assert(N > 0, "ArrayList size must be positive");
+
+    struct alignas(T) Aligned {
+        char data[sizeof(T)];
+    };
+
+    Aligned data[static_cast<unsigned int>(N)];
     int length;
 
 public:

+ 7 - 7
data/BitArray.cpp

@@ -1,4 +1,5 @@
 #include "data/BitArray.h"
+
 #include "math/Math.h"
 
 static int roundUpDivide(int a, int b) {
@@ -34,8 +35,7 @@ static void setBits(int* data, int index, int bits, int value) {
     data[dataIndexA] |= (value << shifts);
     if(dataIndexA != dataIndexB) {
         int leftBits = bits - (INT_BITS - shifts);
-        int mask = (1 << leftBits) - 1;
-        data[dataIndexB] &= ~mask;
+        data[dataIndexB] &= ~((1 << leftBits) - 1);
         data[dataIndexB] |= (value >> (INT_BITS - shifts));
     }
 }
@@ -50,12 +50,12 @@ BitArray::BitArray() : length(0), bits(0), data(nullptr) {
 static int* allocate(int length, int bits) {
     int l = getArrayLength(length, bits);
     int* a = new int[l];
-    memset(a, 0, l * sizeof(int));
+    memset(a, 0, static_cast<size_t>(l) * sizeof(int));
     return a;
 }
 
-BitArray::BitArray(int length, int bits)
-    : length(length), bits(bits), data(nullptr) {
+BitArray::BitArray(int length_, int bits_)
+    : length(length_), bits(bits_), data(nullptr) {
     if(length > 0 && bits > 0) {
         data = allocate(length, bits);
     }
@@ -101,7 +101,7 @@ int BitArray::getInternalByteSize() const {
     if(bits <= 0 || length <= 0) {
         return 0;
     }
-    return getArrayLength(length, bits) * sizeof(int);
+    return getArrayLength(length, bits) * static_cast<int>(sizeof(int));
 }
 
 int BitArray::select(int index) const {
@@ -111,7 +111,7 @@ int BitArray::select(int index) const {
     int found = 0;
     int end = getArrayLength(length, bits);
     for(int i = 0; i < end; i++) {
-        int ones = __builtin_popcount(data[i]);
+        int ones = __builtin_popcount(static_cast<unsigned int>(data[i]));
         found += ones;
         if(found >= index) {
             found -= ones;

+ 2 - 2
data/Components.h

@@ -25,8 +25,8 @@ public:
         int index;
 
     public:
-        EntityIterator(C& components, int index)
-            : components(components), index(index) {
+        EntityIterator(C& components_, int index_)
+            : components(components_), index(index_) {
         }
 
         EntityIterator& operator++() {

+ 10 - 10
data/HashMap.h

@@ -22,8 +22,8 @@ struct HashMap final {
 
     private:
         template<typename... Args>
-        Node(const K& key, Args&&... args)
-            : key(key), value(std::forward<Args>(args)...) {
+        Node(const K& key_, Args&&... args)
+            : key(key_), value(std::forward<Args>(args)...) {
         }
     };
     using Nodes = List<List<Node>>;
@@ -35,8 +35,8 @@ struct HashMap final {
         int indexB;
 
     public:
-        Iterator(N& nodes, int indexA, int indexB)
-            : nodes(nodes), indexA(indexA), indexB(indexB) {
+        Iterator(N& nodes_, int indexA_, int indexB_)
+            : nodes(nodes_), indexA(indexA_), indexB(indexB_) {
             skip();
         }
 
@@ -131,7 +131,7 @@ public:
         Hash h = hash(key);
         V* v = searchList(key, h);
         if(v == nullptr) {
-            nodes[h].add(key, std::forward<Args>(args)...);
+            nodes[static_cast<int>(h)].add(key, std::forward<Args>(args)...);
             elements++;
             return false;
         }
@@ -144,7 +144,7 @@ public:
         Hash h = hash(key);
         V* v = searchList(key, h);
         if(v == nullptr) {
-            nodes[h].add(key, std::forward<VA>(value));
+            nodes[static_cast<int>(h)].add(key, std::forward<VA>(value));
             elements++;
         } else {
             *v = std::forward<VA>(value);
@@ -153,7 +153,7 @@ public:
     }
 
     bool remove(const K& key) {
-        List<Node>& list = nodes[hash(key)];
+        List<Node>& list = nodes[static_cast<int>(hash(key))];
         for(int i = 0; i < list.getLength(); i++) {
             if(list[i].key == key) {
                 list.removeBySwap(i);
@@ -238,7 +238,7 @@ public:
 private:
     template<typename H>
     Hash hash(const H& key) const {
-        return fullHash(key) & (nodes.getLength() - 1);
+        return fullHash(key) & (static_cast<Hash>(nodes.getLength()) - 1u);
     }
 
     template<typename H>
@@ -249,7 +249,7 @@ private:
     Hash fullHash(int key) const {
         static_assert(sizeof(key) == sizeof(Hash),
                       "unwanted loose of precision in hash");
-        return key;
+        return static_cast<Hash>(key);
     }
 
     Hash fullHash(unsigned int key) const {
@@ -272,7 +272,7 @@ private:
     }
 
     const V* searchList(const K& key, Hash h) const {
-        for(const Node& n : nodes[h]) {
+        for(const Node& n : nodes[static_cast<int>(h)]) {
             if(n.key == key) {
                 return &n.value;
             }

+ 8 - 1
data/List.h

@@ -167,8 +167,15 @@ public:
     }
 
 private:
+    struct alignas(T) Aligned {
+        char data[sizeof(T)];
+    };
+
     static T* allocate(int n) {
-        return reinterpret_cast<T*>(new char[sizeof(T) * n]);
+        if(n < 0) {
+            n = 0;
+        }
+        return reinterpret_cast<T*>(new Aligned[static_cast<size_t>(n)]);
     }
 
     void swap(List& other) {

+ 4 - 0
io/ImageReader.cpp

@@ -1,4 +1,8 @@
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#pragma GCC diagnostic ignored "-Wpadded"
 #include "libs/lodepng/lodepng.h"
+#pragma GCC diagnostic pop
 
 #include "io/ImageReader.h"
 #include "utils/Cleaner.h"

+ 1 - 1
math/Box.cpp

@@ -1,6 +1,6 @@
 #include "math/Box.h"
 
-Box::Box(const Vector3& min, const Vector3& max) : min(min), max(max) {
+Box::Box(const Vector3& min_, const Vector3& max_) : min(min_), max(max_) {
 }
 
 Box::Box(const Vector3& size) {

+ 6 - 6
math/Frustum.cpp

@@ -1,13 +1,13 @@
 #include "math/Frustum.h"
 
-Frustum::Frustum(float fieldOfView, float nearClip, float farClip)
-    : fieldOfView(fieldOfView), nearClip(nearClip), farClip(farClip) {
+Frustum::Frustum(float fieldOfView_, float nearClip_, float farClip_)
+    : fieldOfView(fieldOfView_), nearClip(nearClip_), farClip(farClip_) {
 }
 
 const Matrix& Frustum::updateProjection(const IntVector2& size) {
-    float tan = tanf(fieldOfView * (0.5f * M_PI / 180.0f));
+    float tan = tanf(fieldOfView * (0.5f * static_cast<float>(M_PI) / 180.0f));
     float q = 1.0f / tan;
-    float aspect = static_cast<float>(size[0]) / size[1];
+    float aspect = static_cast<float>(size[0]) / static_cast<float>(size[1]);
     float diff = 1.0f / (nearClip - farClip);
 
     projection.set(0, Vector4(q / aspect, 0.0f, 0.0f, 0.0f));
@@ -21,8 +21,8 @@ const Matrix& Frustum::updateProjection(const IntVector2& size) {
 void Frustum::updatePlanes(const Vector3& pos, const Vector3& right,
                            const Vector3& up, const Vector3& front,
                            const IntVector2& size) {
-    float tan = tanf(fieldOfView * (0.5f * M_PI / 180.0f));
-    float aspect = static_cast<float>(size[0]) / size[1];
+    float tan = tanf(fieldOfView * (0.5f * static_cast<float>(M_PI) / 180.0f));
+    float aspect = static_cast<float>(size[0]) / static_cast<float>(size[1]);
 
     float halfNearHeight = tan * nearClip;
     float halfNearWidth = halfNearHeight * aspect;

+ 2 - 1
math/Matrix.cpp

@@ -1,4 +1,5 @@
 #include "math/Matrix.h"
+
 #include "math/Math.h"
 
 Matrix::Matrix() {
@@ -91,7 +92,7 @@ Matrix& Matrix::translateTo(const Vector3& v) {
 }
 
 Matrix& Matrix::rotate(float degrees, int a, int b) {
-    degrees *= (M_PI / 180.0f);
+    degrees *= (static_cast<float>(M_PI) / 180.0f);
     float sin = 0.0f;
     float cos = 0.0f;
     sincosf(degrees, &sin, &cos);

+ 1 - 1
math/Quaternion.cpp

@@ -6,7 +6,7 @@ Quaternion::Quaternion() : w(1.0f) {
 Quaternion::Quaternion(const Vector3& axis, float angle) : xyz(axis) {
     xyz.normalize();
     float factor = 0.0f;
-    sincosf(angle * (M_PI / 360.0f), &factor, &w);
+    sincosf(angle * (static_cast<float>(M_PI) / 360.0f), &factor, &w);
     xyz *= factor;
 }
 

+ 3 - 2
math/Vector.cpp

@@ -4,11 +4,12 @@ template<>
 Vector3& Vector3::setAngles(float lengthAngle, float widthAngle) {
     float sWidth = 0.0f;
     float cWidth = 0.0f;
-    sincosf(widthAngle * (M_PI / 180.0f), &sWidth, &cWidth);
+    sincosf(widthAngle * (static_cast<float>(M_PI) / 180.0f), &sWidth, &cWidth);
 
     float sLength = 0.0f;
     float cLength = 0.0f;
-    sincosf(lengthAngle * (M_PI / 180.0f), &sLength, &cLength);
+    sincosf(lengthAngle * (static_cast<float>(M_PI) / 180.0f), &sLength,
+            &cLength);
 
     return *this = Vector3(cWidth * cLength, sWidth, -sLength * cWidth);
 }

+ 9 - 8
math/Vector.h

@@ -6,7 +6,8 @@
 
 template<int N, typename T>
 class Vector final {
-    T values[N];
+    static_assert(N > 0, "Vector size must be positive");
+    T values[static_cast<unsigned int>(N)];
 
 public:
     Vector() {
@@ -15,8 +16,8 @@ public:
         }
     }
 
-    template<typename... Args>
-    Vector(T a, Args&&... args) {
+    template<typename OT, typename... Args>
+    Vector(OT a, Args&&... args) {
         init<0>(a, args...);
     }
 
@@ -26,9 +27,9 @@ private:
         static_assert(I == N, "vector parameters do not match its size");
     }
 
-    template<int I, typename... Args>
-    void init(T a, Args&&... args) {
-        values[I] = a;
+    template<int I, typename OT, typename... Args>
+    void init(OT a, Args&&... args) {
+        values[I] = static_cast<T>(a);
         init<I + 1>(args...);
     }
 
@@ -154,7 +155,7 @@ public:
     Vector<N, int> toInt() const {
         Vector<N, int> cast;
         for(int i = 0; i < N; i++) {
-            cast[i] = values[i];
+            cast[i] = static_cast<int>(values[i]);
         }
         return cast;
     }
@@ -162,7 +163,7 @@ public:
     Vector<N, float> toFloat() const {
         Vector<N, float> cast;
         for(int i = 0; i < N; i++) {
-            cast[i] = values[i];
+            cast[i] = static_cast<float>(values[i]);
         }
         return cast;
     }

+ 24 - 7
meson.build

@@ -1,4 +1,4 @@
-project('gamingcore', 'cpp', default_options : ['default_library=static'])
+project('gamingcore', 'cpp', default_options : ['default_library=static', 'cpp_std=c++17'])
 
 src = [
     'io/ImageReader.cpp',
@@ -25,7 +25,6 @@ src = [
     'utils/Error.cpp',
     'utils/Logger.cpp',
     'utils/Random.cpp',
-    'libs/lodepng/lodepng.cpp',
 ]
 
 src_tests = [
@@ -62,7 +61,22 @@ src_tests = [
 ]
 
 compiler = meson.get_compiler('cpp')
-args = compiler.get_supported_arguments(['-Wall', '-Wextra', '-pedantic', '-Werror'])
+args = compiler.get_supported_arguments([
+    '-Wcast-align=strict', '-pedantic', '-Wmissing-declarations', '-Wdate-time', 
+    '-Winit-self', '-Woverlength-strings', '-Wsign-promo', '-Wnon-virtual-dtor', 
+    '-Wconversion', '-Woverloaded-virtual', '-Wdeprecated-enum-enum-conversion', 
+    '-Wdisabled-optimization', '-Winvalid-imported-macros', '-Wduplicated-cond', 
+    '-Wdeprecated-enum-float-conversion', '-Wduplicated-branches', '-Wformat=2', 
+    '-Wmissing-braces', '-Wsuggest-override', '-Wcast-qual', '-Wbidi-chars=any', 
+    '-Wzero-as-null-pointer-constant', '-pedantic-errors', '-Wnull-dereference', 
+    '-Wformat-signedness', '-Wfloat-equal', '-Wvolatile', '-Wctor-dtor-privacy', 
+    '-Winfinite-recursion', '-Wshift-overflow=2', '-Wmultichar', '-Walloc-zero', 
+    '-Wcomma-subscript', '-Wold-style-cast', '-Wwrite-strings', '-Wswitch-enum', 
+    '-Wredundant-decls', '-Werror', '-Wsign-conversion', '-Walloca', '-Wshadow',
+    '-Winvalid-pch', '-Wdeprecated-copy-dtor', '-Wundef', '-Wdouble-promotion',
+    '-Warith-conversion', '-Wextra', '-Wtrivial-auto-var-init', '-Wlogical-op', 
+    '-Wall', '-Wenum-conversion',
+])
 
 cmake = import('cmake')
 glfw_proj = cmake.subproject('glfw')
@@ -83,16 +97,19 @@ dl_dep = compiler.find_library('dl', required: false)
 
 gamingcore_include = [include_directories('.'), glfw_includes, glew_includes]
 
+lodepng = static_library('lodepng', sources: 'libs/lodepng/lodepng.cpp')
+lodepng_dep = declare_dependency(link_with: lodepng)
+
 gamingcore = static_library('gamingcore', 
     sources: src,
-    include_directories : gamingcore_include,
-    dependencies : [thread_dep, glfw_dep, glew_dep, gl_dep, ws2_32_dep, winmm_dep, glu_dep, dl_dep, glu_dep],
+    include_directories: gamingcore_include,
+    dependencies: [thread_dep, glfw_dep, glew_dep, gl_dep, ws2_32_dep, winmm_dep, glu_dep, dl_dep, glu_dep, lodepng_dep],
     cpp_args: args)
 gamingcore_dep = declare_dependency(
-    include_directories : gamingcore_include,
+    include_directories: gamingcore_include,
     link_with: gamingcore)
 
 executable('tests', 
     sources: src_tests,
-    dependencies : gamingcore_dep,
+    dependencies: gamingcore_dep,
     cpp_args: args + ['-DLOG_LEVEL=4'])

+ 8 - 7
network/Client.cpp

@@ -1,6 +1,5 @@
-#include "libs/enet/include/enet.h"
-
 #include "network/Client.h"
+
 #include "network/ENet.h"
 
 static_assert(sizeof(enet_uint16) == sizeof(Client::Port),
@@ -80,10 +79,11 @@ void Client::send(OutPacket& p, PacketSendMode mode) {
     if(client != nullptr && connection != nullptr && connectTicks < 0) {
         constexpr enet_uint32 flags[] = {ENET_PACKET_FLAG_RELIABLE, 0,
                                          ENET_PACKET_FLAG_UNSEQUENCED};
-        int index = static_cast<int>(mode);
-        enet_peer_send(
-            connection, index,
-            enet_packet_create(p.buffer, p.buffer.getLength(), flags[index]));
+        enet_uint8 index = static_cast<enet_uint8>(mode);
+        enet_peer_send(connection, index,
+                       enet_packet_create(
+                           p.buffer, static_cast<size_t>(p.buffer.getLength()),
+                           flags[index]));
     }
 }
 
@@ -106,7 +106,8 @@ void Client::tick() {
                 break;
             case ENET_EVENT_TYPE_NONE: return;
             case ENET_EVENT_TYPE_RECEIVE:
-                InPacket in(e.packet->data, e.packet->dataLength);
+                InPacket in(e.packet->data,
+                            static_cast<int>(e.packet->dataLength));
                 onPacket(in);
                 enet_packet_destroy(e.packet);
                 break;

+ 0 - 2
network/ENet.cpp

@@ -1,6 +1,4 @@
 #define ENET_IMPLEMENTATION
-#include "libs/enet/include/enet.h"
-
 #include "network/ENet.h"
 
 static int enetCounter = 0;

+ 4 - 0
network/ENet.h

@@ -6,4 +6,8 @@ namespace ENet {
     void remove();
 }
 
+// all code after this is not checked
+#pragma GCC system_header
+#include <libs/enet/include/enet.h>
+
 #endif

+ 23 - 17
network/Packet.cpp

@@ -1,19 +1,19 @@
-#include "libs/enet/include/enet.h"
-
 #include "network/Packet.h"
 
+#include "network/ENet.h"
+
 static_assert(sizeof(float) == sizeof(uint32),
               "sizeof(float) != sizeof(uint32)");
 
-InPacket::InPacket(const void* data, int size)
-    : data(static_cast<const char*>(data)), size(size), index(0) {
+InPacket::InPacket(const void* data_, int size_)
+    : data(static_cast<const char*>(data_)), size(size_), index(0) {
 }
 
 bool InPacket::read(void* buffer, int length) {
-    if(index + length > size) {
+    if(index + length > size || length <= 0) {
         return true;
     }
-    memcpy(buffer, data + index, length);
+    memcpy(buffer, data + index, static_cast<unsigned int>(length));
     index += length;
     return false;
 }
@@ -38,15 +38,19 @@ bool InPacket::read(uint32& u) {
     return false;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wduplicated-branches"
+// the branches are actually different but the hardware does not care
+
 bool InPacket::read(int8& s) {
     uint8 u;
     if(read(u)) {
         return true;
     }
     if(u < 128) {
-        s = static_cast<int8>(u) - 128;
+        s = static_cast<int8>(static_cast<int>(u) - static_cast<int>(128));
     } else {
-        s = u - 128;
+        s = static_cast<int8>(static_cast<unsigned int>(u) - 128u);
     }
     return false;
 }
@@ -57,9 +61,9 @@ bool InPacket::read(int16& s) {
         return true;
     }
     if(u < 32768) {
-        s = static_cast<int16>(u) - 32768;
+        s = static_cast<int16>(static_cast<int16>(u) - 32768);
     } else {
-        s = u - 32768;
+        s = static_cast<int16>(static_cast<unsigned int>(u) - 32768u);
     }
     return false;
 }
@@ -70,13 +74,15 @@ bool InPacket::read(int32& s) {
         return true;
     }
     if(u < 2147483648) {
-        s = static_cast<int32>(u) - 2147483648;
+        s = static_cast<int32>(static_cast<int32>(u) - 2147483648);
     } else {
-        s = u - 2147483648;
+        s = static_cast<int32>(u - 2147483648u);
     }
     return false;
 }
 
+#pragma GCC diagnostic pop
+
 bool InPacket::read(float& f) {
     uint32 u;
     if(read(u)) {
@@ -108,21 +114,21 @@ OutPacket& OutPacket::writeU32(uint32 u) {
 
 OutPacket& OutPacket::writeS8(int8 s) {
     if(s < 0) {
-        return writeU8(s + 128);
+        return writeU8(static_cast<uint8>(s + 128));
     }
-    return writeU8(static_cast<uint8>(s) + 128u);
+    return writeU8(static_cast<uint8>(static_cast<unsigned int>(s) + 128u));
 }
 
 OutPacket& OutPacket::writeS16(int16 s) {
     if(s < 0) {
-        return writeU16(s + 32768);
+        return writeU16(static_cast<uint16>(s + 32768));
     }
-    return writeU16(static_cast<uint16>(s) + 32768u);
+    return writeU16(static_cast<uint16>(static_cast<unsigned int>(s) + 32768u));
 }
 
 OutPacket& OutPacket::writeS32(int32 s) {
     if(s < 0) {
-        return writeU32(s + 2147483648);
+        return writeU32(static_cast<uint32>(s + 2147483648));
     }
     return writeU32(static_cast<uint32>(s) + 2147483648u);
 }

+ 3 - 3
network/Packet.h

@@ -70,9 +70,9 @@ struct OutPacket {
 
     template<int N>
     OutPacket& writeString(const StringBuffer<N>& s) {
-        uint16 end = s.getLength() > 65535 ? 65535 : s.getLength();
-        writeU16(end);
-        for(unsigned int i = 0; i < end; i++) {
+        int end = s.getLength() > 65535 ? 65535 : s.getLength();
+        writeU16(static_cast<uint16>(end));
+        for(int i = 0; i < end; i++) {
             writeS8(s[i]);
         }
         return *this;

+ 15 - 10
network/Server.cpp

@@ -1,8 +1,7 @@
-#include "libs/enet/include/enet.h"
+#include "network/Server.h"
 
 #include "data/HashMap.h"
 #include "network/ENet.h"
-#include "network/Server.h"
 #include "utils/Logger.h"
 
 static_assert(sizeof(enet_uint16) == sizeof(Server::Port),
@@ -16,7 +15,9 @@ static Server::OnDisconnect onDisconnect = [](Server::Client) {};
 static Server::OnPacket onPacket = [](Server::Client, InPacket&) {};
 
 Error Server::start(Port port, int maxClients) {
-    if(server != nullptr) {
+    if(maxClients <= 0) {
+        return {"invalid max client amount"};
+    } else if(server != nullptr) {
         return {"already started"};
     } else if(ENet::add()) {
         return {"cannot initialize enet"};
@@ -27,7 +28,8 @@ Error Server::start(Port port, int maxClients) {
     address.host = ENET_HOST_ANY;
     address.port = port;
 
-    server = enet_host_create(&address, maxClients, 3, 0, 0);
+    server = enet_host_create(&address, static_cast<unsigned int>(maxClients),
+                              3, 0, 0);
     if(server == nullptr) {
         ENet::remove();
         return {"cannot create enet server host"};
@@ -47,13 +49,13 @@ void Server::stop() {
     ENet::remove();
 }
 
-void writeId(ENetPeer* peer, Server::Client id) {
+static void writeId(ENetPeer* peer, Server::Client id) {
     static_assert(sizeof(peer->data) >= sizeof(id),
                   "private data not big enough for id");
     memcpy(&(peer->data), &id, sizeof(id));
 }
 
-Server::Client getId(ENetPeer* peer) {
+static Server::Client getId(ENetPeer* peer) {
     Server::Client id = -1;
     memcpy(&id, &(peer->data), sizeof(id));
     return id;
@@ -75,7 +77,7 @@ static void handlePacket(ENetEvent& e) {
         return;
     }
     Server::Client id = getId(e.peer);
-    InPacket in(e.packet->data, e.packet->dataLength);
+    InPacket in(e.packet->data, static_cast<int>(e.packet->dataLength));
     onPacket(id, in);
 }
 
@@ -113,13 +115,15 @@ void Server::tick() {
 static ENetPacket* fromBuffer(const Buffer& buffer, int index) {
     constexpr enet_uint32 flags[] = {ENET_PACKET_FLAG_RELIABLE, 0,
                                      ENET_PACKET_FLAG_UNSEQUENCED};
-    return enet_packet_create(buffer, buffer.getLength(), flags[index]);
+    return enet_packet_create(
+        buffer, static_cast<unsigned int>(buffer.getLength()), flags[index]);
 }
 
 void Server::send(const OutPacket& p, PacketSendMode mode) {
     if(server != nullptr) {
         int index = static_cast<int>(mode);
-        enet_host_broadcast(server, index, fromBuffer(p.buffer, index));
+        enet_host_broadcast(server, static_cast<enet_uint8>(index),
+                            fromBuffer(p.buffer, index));
     }
 }
 
@@ -131,7 +135,8 @@ void Server::send(Server::Client client, const OutPacket& p,
     ENetPeer** peer = clients.search(client);
     if(peer != nullptr) {
         int index = static_cast<int>(mode);
-        enet_peer_send(*peer, index, fromBuffer(p.buffer, index));
+        enet_peer_send(*peer, static_cast<enet_uint8>(index),
+                       fromBuffer(p.buffer, index));
     }
 }
 

+ 1 - 1
rendering/Framebuffer.h

@@ -27,7 +27,7 @@ public:
     template<typename... Args>
     Error init(const IntVector2& size, Args&&... args) {
         const int n = sizeof...(args);
-        Texture::Format init[n] = {args...};
+        Texture::Format init[static_cast<unsigned int>(n)] = {args...};
         static_assert(N == n,
                       "framebuffer size and amount of arguments do not match");
         for(int i = 0; i < N; i++) {

+ 14 - 11
rendering/GL.cpp

@@ -1,8 +1,9 @@
-#include "GL/glew.h"
+#include "rendering/GL.h"
+
 #include <type_traits>
 
+#include "GL/glew.h"
 #include "data/Array.h"
-#include "rendering/GL.h"
 #include "utils/Logger.h"
 
 static_assert(std::is_same<GL::Shader, GLuint>::value,
@@ -37,8 +38,8 @@ GL::BufferUsage GL::STATIC_DRAW = GL_STATIC_DRAW;
 GL::BufferUsage GL::STREAM_DRAW = GL_STREAM_DRAW;
 GL::BufferUsage GL::DYNAMIC_DRAW = GL_DYNAMIC_DRAW;
 
-GL::Attribute::Attribute(int count, int size, int type, bool normalized)
-    : count(count), size(size), type(type), normalized(normalized) {
+GL::Attribute::Attribute(int count_, int size_, int type_, bool normalized_)
+    : count(count_), size(size_), type(type_), normalized(normalized_) {
 }
 
 GL::Attribute GL::Attribute::newFloat(int count) {
@@ -61,8 +62,8 @@ int GL::Attribute::getSize() const {
     return count * size;
 }
 
-GL::TextureFormat::TextureFormat(int internalformat, int format, int type)
-    : internalformat(internalformat), format(format), type(type) {
+GL::TextureFormat::TextureFormat(int internalformat_, int format_, int type_)
+    : internalformat(internalformat_), format(format_), type(type_) {
 }
 
 GL::TextureFormat GL::TextureFormat::color8(int channels) {
@@ -165,9 +166,10 @@ void GL::setViewport(int width, int height) {
 
 void GL::vertexAttribPointer(int index, const Attribute& a, int stride,
                              int offset) {
-    glVertexAttribPointer(index, a.count, a.type, a.normalized, stride,
+    glVertexAttribPointer(static_cast<GLuint>(index), a.count,
+                          static_cast<GLenum>(a.type), a.normalized, stride,
                           static_cast<char*>(0) + offset);
-    glEnableVertexAttribArray(index);
+    glEnableVertexAttribArray(static_cast<GLuint>(index));
 }
 
 GL::Program GL::createProgram() {
@@ -260,7 +262,8 @@ void GL::set4Float(Program p, const char* name, const float* data) {
 void GL::texImage2D(const TextureFormat& tf, int width, int height,
                     const void* data, int level) {
     glTexImage2D(GL_TEXTURE_2D, level, tf.internalformat, width, height, 0,
-                 tf.format, tf.type, data);
+                 static_cast<GLenum>(tf.format), static_cast<GLenum>(tf.type),
+                 data);
 }
 
 GL::Texture GL::genTexture() {
@@ -312,7 +315,7 @@ void GL::bindTexture2D(Texture t) {
 }
 
 void GL::activeTexture(int index) {
-    glActiveTexture(GL_TEXTURE0 + index);
+    glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + index));
 }
 
 void GL::generateMipmap2D(int maxLevels) {
@@ -343,7 +346,7 @@ void GL::framebufferDepthTexture2D(Texture t) {
 }
 
 GL::ColorAttachment GL::framebufferColorTexture2D(Texture t, int index) {
-    GLenum c = GL_COLOR_ATTACHMENT0 + index;
+    GLenum c = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index);
     glFramebufferTexture2D(GL_FRAMEBUFFER, c, GL_TEXTURE_2D, t, 0);
     return c;
 }

+ 0 - 1
rendering/GL.h

@@ -101,7 +101,6 @@ namespace GL {
     void setMipMapLinearFilter2D();
     void setClampWrap2D();
     void setRepeatWrap2D();
-    void setMipMapLinearFilter2D();
     void bindTexture2D(Texture t);
     void activeTexture(int index);
     void generateMipmap2D(int maxLevels);

+ 5 - 4
rendering/Shader.cpp

@@ -1,6 +1,7 @@
+#include "rendering/Shader.h"
+
 #include <fstream>
 
-#include "rendering/Shader.h"
 #include "utils/Logger.h"
 
 Shader::Shader() : shaders(0), program(0) {
@@ -14,7 +15,7 @@ Shader::~Shader() {
 }
 
 static bool endsWith(const char* path, int length, const char* ending) {
-    int endingLength = strlen(ending);
+    int endingLength = static_cast<int>(strlen(ending));
     if(length < endingLength) {
         return false;
     }
@@ -22,7 +23,7 @@ static bool endsWith(const char* path, int length, const char* ending) {
 }
 
 GL::ShaderType Shader::getShaderType(const char* path) const {
-    int length = strlen(path);
+    int length = static_cast<int>(strlen(path));
     if(endsWith(path, length, ".vs")) {
         return GL::VERTEX_SHADER;
     } else if(endsWith(path, length, ".fs")) {
@@ -58,7 +59,7 @@ Error Shader::readFile(List<char>& code, const char* path) const {
         if(c == EOF) {
             break;
         }
-        code.add(c);
+        code.add(static_cast<char>(c));
     }
     code.add('\0');
     return {};

+ 1 - 1
rendering/Shader.h

@@ -23,7 +23,7 @@ public:
     template<typename... Args>
     Error compile(Args&&... args) {
         const int size = sizeof...(args);
-        const char* paths[size] = {args...};
+        const char* paths[static_cast<unsigned int>(size)] = {args...};
         static_assert(size <= MAX_SHADERS, "too much shaders paths given");
 
         for(int i = 0; i < size; i++) {

+ 12 - 10
rendering/Texture.cpp

@@ -1,8 +1,9 @@
 #include "rendering/Texture.h"
+
 #include "io/ImageReader.h"
 
-Texture::Format::Format(const GL::TextureFormat& tf, bool linear, bool depth)
-    : format(tf), linear(linear), depth(depth) {
+Texture::Format::Format(const GL::TextureFormat& tf, bool linear_, bool depth_)
+    : format(tf), linear(linear_), depth(depth_) {
 }
 
 Texture::Format Texture::Format::color8(int channels, bool linear) {
@@ -36,12 +37,12 @@ Texture::~Texture() {
     GL::deleteTexture(texture);
 }
 
-void Texture::init(const Format& format, int maxMipMaps) {
+void Texture::init(const Format& format_, int maxMipMaps_) {
     if(texture != 0) {
         return;
     }
-    Texture::format = format;
-    Texture::maxMipMaps = maxMipMaps;
+    format = format_;
+    maxMipMaps = maxMipMaps_;
     texture = GL::genTexture();
     setNearestFilter();
     setRepeatWrap();
@@ -92,24 +93,25 @@ void Texture::bindTo(int index) const {
     bind();
 }
 
-Error Texture::load(const char* path, int maxMipMaps) {
+Error Texture::load(const char* path, int maxMipMaps_) {
     ImageReader::Image image;
     Error error = ImageReader::load(image, path);
     if(error.has()) {
         return error;
     }
     if(image.channels < 1 || image.channels > 4) {
-        Error error = {"'"};
+        error = {"'"};
         error.message.append(path)
             .append("' has unsupported number of channels: ")
             .append(image.channels);
         return error;
     } else if(image.bitdepth != 8) {
-        Error error = {"bit depth of '"};
+        error = {"bit depth of '"};
         error.message.append(path).append("' is not 8");
         return error;
     }
-    init(Format::color8(image.channels), maxMipMaps);
-    setData(image.width, image.height, image.data);
+    init(Format::color8(static_cast<int>(image.channels)), maxMipMaps_);
+    setData(static_cast<int>(image.width), static_cast<int>(image.height),
+            image.data);
     return {};
 }

+ 5 - 4
rendering/VertexBuffer.cpp

@@ -58,8 +58,9 @@ void VertexBuffer::init(const Attributes& attributes) {
     attributes.set();
 }
 
-void VertexBuffer::setData(int size, const void* data, GL::BufferUsage usage) {
-    VertexBuffer::size = size;
+void VertexBuffer::setData(int dataSize, const void* data,
+                           GL::BufferUsage usage) {
+    size = dataSize;
     bindBuffer();
     GL::bufferData(size, data, usage);
 }
@@ -68,9 +69,9 @@ void VertexBuffer::setData(const Buffer& buffer, GL::BufferUsage usage) {
     setData(buffer.getLength(), buffer, usage);
 }
 
-void VertexBuffer::updateData(int offset, int size, const void* data) {
+void VertexBuffer::updateData(int offset, int dataSize, const void* data) {
     bindBuffer();
-    GL::bufferSubData(offset, size, data);
+    GL::bufferSubData(offset, dataSize, data);
 }
 
 void VertexBuffer::draw(int vertices, int offset) {

+ 10 - 10
rendering/Window.cpp

@@ -1,11 +1,11 @@
+#include "rendering/Window.h"
+
 #include <utility>
 
 #include "GL/glew.h"
 #include "GLFW/glfw3.h"
-
 #include "data/Array.h"
 #include "data/HashMap.h"
-#include "rendering/Window.h"
 
 static GLFWwindow* window = nullptr;
 static Clock fps;
@@ -28,8 +28,8 @@ struct Button final {
     int controllerDown;
     bool released;
 
-    Button(const Window::Controls::ButtonName& name)
-        : name(name), key(0), downTime(0), upEvents(0), downEvents(0),
+    Button(const Window::Controls::ButtonName& name_)
+        : name(name_), key(0), downTime(0), upEvents(0), downEvents(0),
           controllerUp(0), controllerDown(0), released(false) {
     }
 
@@ -60,10 +60,10 @@ static Vector2 mousePosition;
 static int activeController = -1;
 static GLFWgamepadstate lastControllerState;
 
-Window::Options::Options(int majorVersion, int minorVersion,
-                         const IntVector2& size, bool es, const char* name)
-    : majorVersion(majorVersion), minorVersion(minorVersion), size(size),
-      fullscreen(false), es(es), vsync(true), name(name) {
+Window::Options::Options(int majorVersion_, int minorVersion_,
+                         const IntVector2& size_, bool es_, const char* name_)
+    : majorVersion(majorVersion_), minorVersion(minorVersion_), size(size_),
+      fullscreen(false), es(es_), vsync(true), name(name_) {
 }
 
 static void onButton(HashMap<int, Window::Controls::ButtonId>& map, int key,
@@ -148,7 +148,7 @@ static void onMouse(GLFWwindow*, int button, int action, int mods) {
 }
 
 static void onMouseMove(GLFWwindow*, double x, double y) {
-    mousePosition = Vector2(x, y);
+    mousePosition = Vector<2, double>(x, y).toFloat();
 }
 
 Error Window::open(const Options& o) {
@@ -333,7 +333,7 @@ static uint32 read(int& index, const char* s) {
     if(s[index] == '\0') {
         return '\0';
     }
-    return s[index++];
+    return static_cast<uint32>(s[index++]);
 }
 
 static uint32 readUnicode(int& index, const char* s) {

+ 1 - 1
rendering/Window.h

@@ -57,7 +57,7 @@ namespace Window {
                 T();
                 postTick();
             }
-            R(static_cast<float>(lag) / nanosPerTick);
+            R(static_cast<float>(lag) / static_cast<float>(nanosPerTick));
             endFrame();
         }
     }

+ 2 - 1
tests/HashMapTests.cpp

@@ -1,4 +1,5 @@
 #include "tests/HashMapTests.h"
+
 #include "data/HashMap.h"
 #include "tests/Test.h"
 #include "utils/StringBuffer.h"
@@ -77,7 +78,7 @@ struct A {
     int a;
     int b;
 
-    A(int a, int b) : a(a), b(b) {
+    A(int a_, int b_) : a(a_), b(b_) {
     }
 
     bool operator==(const A& other) const {

+ 3 - 2
tests/NetworkTests.cpp

@@ -1,11 +1,12 @@
+#include "tests/NetworkTests.h"
+
 #include <iostream>
 
 #include "network/Client.h"
 #include "network/Server.h"
-#include "tests/NetworkTests.h"
 #include "tests/Test.h"
 
-bool checkError(Test& test, const Error e, const char* msg) {
+static bool checkError(Test& test, const Error e, const char* msg) {
     if(e.has()) {
         test.checkFalse(true, msg);
         std::cout << "Error: " << e.message << "\n";

+ 11 - 6
tests/RandomTests.cpp

@@ -1,4 +1,5 @@
 #include "tests/RandomTests.h"
+
 #include "data/Array.h"
 #include "tests/Test.h"
 #include "utils/Random.h"
@@ -7,7 +8,7 @@ static void testAverage(Test& test) {
     Random r(553);
     float sum = 0;
     for(int i = 0; i < 1000000; i++) {
-        sum += r.next(2, 10);
+        sum += static_cast<float>(r.next(2, 10));
     }
     sum /= 1000000.0f;
     test.checkFloat(6.0f, sum, 0.01f, "average");
@@ -19,7 +20,8 @@ static void testCoin(Test& test) {
     for(int i = 0; i < 1000000; i++) {
         c[r.next() & 1]++;
     }
-    test.checkFloat(0.0f, (c[0] - c[1]) / 1000000.0f, 0.001f, "coin");
+    test.checkFloat(0.0f, static_cast<float>(c[0] - c[1]) / 1000000.0f, 0.001f,
+                    "coin");
 }
 
 static void testDistribution(Test& test) {
@@ -31,7 +33,8 @@ static void testDistribution(Test& test) {
     test.checkEqual(0, c[0], "distribution does not underflow");
     test.checkEqual(0, c[c.getLength() - 1], "distribution does not overflow");
     for(int i = 1; i < c.getLength() - 1; i++) {
-        test.checkFloat(0.01f, c[i] / 1000000.0f, 0.001f, "distribution");
+        test.checkFloat(0.01f, static_cast<float>(c[i]) / 1000000.0f, 0.001f,
+                        "distribution");
     }
 }
 
@@ -51,20 +54,22 @@ static void testFloatCoin(Test& test) {
     for(int i = 0; i < 1000000; i++) {
         c[r.nextFloat() < 0.5f]++;
     }
-    test.checkFloat(0.0f, (c[0] - c[1]) / 1000000.0f, 0.001f, "float coin");
+    test.checkFloat(0.0f, static_cast<float>(c[0] - c[1]) / 1000000.0f, 0.001f,
+                    "float coin");
 }
 
 static void testFloatDistribution(Test& test) {
     Random r(553);
     Array<int, 102> c(0);
     for(int i = 0; i < 1000000; i++) {
-        c[r.nextFloat(1.0f, c.getLength() - 1)]++;
+        c[static_cast<int>(r.nextFloat(1.0f, c.getLength() - 1))]++;
     }
     test.checkEqual(0, c[0], "float distribution does not underflow");
     test.checkEqual(0, c[c.getLength() - 1],
                     "float distribution does not overflow");
     for(int i = 1; i < c.getLength() - 1; i++) {
-        test.checkFloat(0.01f, c[i] / 1000000.0f, 0.001f, "float distribution");
+        test.checkFloat(0.01f, static_cast<float>(c[i]) / 1000000.0f, 0.001f,
+                        "float distribution");
     }
 }
 

+ 1 - 1
tests/Test.cpp

@@ -1,6 +1,6 @@
 #include "Test.h"
 
-Test::Test(const char* name) : tests(0), successTests(0), name(name) {
+Test::Test(const char* name_) : tests(0), successTests(0), name(name_) {
 }
 
 void Test::finalize() {

+ 4 - 0
tests/Test.h

@@ -37,6 +37,10 @@ public:
         }
     }
 
+    void checkEqual(float wanted, float actual, const char* text) {
+        checkFloat(wanted, actual, 0.0000001f, text);
+    }
+
     void checkFloat(float wanted, float actual, float error, const char* text);
     void checkTrue(bool actual, const char* text);
     void checkFalse(bool actual, const char* text);

+ 2 - 1
tests/VectorTests.cpp

@@ -1,4 +1,5 @@
 #include "tests/VectorTests.h"
+
 #include "math/Vector.h"
 #include "tests/Test.h"
 #include "utils/StringBuffer.h"
@@ -10,7 +11,7 @@ static void compareVectors(Test& test, const Vector<N, T>& wanted,
                            const Vector<N, T>& actual, const char* text) {
     for(int i = 0; i < N; i++) {
         test.checkFloat(
-            wanted[i], actual[i], eps,
+            static_cast<float>(wanted[i]), static_cast<float>(actual[i]), eps,
             StringBuffer<50>(text).append(" (").append(i).append(")"));
     }
 }

+ 9 - 8
utils/Buffer.cpp

@@ -1,18 +1,18 @@
+#include "utils/Buffer.h"
+
 #include <cstdlib>
 #include <cstring>
 #include <utility>
 
-#include "utils/Buffer.h"
-
 Buffer::Buffer(int initialSize)
-    : length(0), capacity(initialSize),
-      buffer(static_cast<char*>(malloc(initialSize))) {
+    : length(0), capacity(initialSize <= 0 ? 1 : initialSize),
+      buffer(static_cast<char*>(malloc(static_cast<unsigned int>(capacity)))) {
 }
 
 Buffer::Buffer(const Buffer& other)
     : length(other.length), capacity(other.capacity),
-      buffer(static_cast<char*>(malloc(capacity))) {
-    memcpy(buffer, other.buffer, length);
+      buffer(static_cast<char*>(malloc(static_cast<unsigned int>(capacity)))) {
+    memcpy(buffer, other.buffer, static_cast<unsigned int>(length));
 }
 
 Buffer::Buffer(Buffer&& other) : length(0), capacity(0), buffer(nullptr) {
@@ -31,9 +31,10 @@ Buffer& Buffer::operator=(Buffer other) {
 Buffer& Buffer::add(const void* data, int size) {
     while(length + size > capacity) {
         capacity *= 2;
-        buffer = static_cast<char*>(realloc(buffer, capacity));
+        buffer = static_cast<char*>(
+            realloc(buffer, static_cast<unsigned int>(capacity)));
     }
-    memcpy(buffer + length, data, size);
+    memcpy(buffer + length, data, static_cast<unsigned int>(size));
     length += size;
     return *this;
 }

+ 19 - 0
utils/Check.h

@@ -0,0 +1,19 @@
+#ifndef CHECK_H
+#define CHECK_H
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 202300L
+#define check_return [[nodiscard]]
+#elif defined(__GNUC__)
+#define check_return __attribute__((warn_unused_result))
+#else
+#error "please add a 'check_return' option"
+#endif
+
+#if defined(__GNUC__)
+#define check_format(format_index, arg_start_index)                            \
+    __attribute__((format(printf, format_index, arg_start_index)))
+#else
+#error "please add a 'check_format' option"
+#endif
+
+#endif

+ 3 - 3
utils/Clock.cpp

@@ -1,8 +1,8 @@
+#include "utils/Clock.h"
+
 #include <chrono>
 #include <thread>
 
-#include "utils/Clock.h"
-
 Clock::Clock() : index(0), last(getNanos()), sum(0), time(0) {
 }
 
@@ -17,7 +17,7 @@ Clock::Nanos Clock::update() {
 }
 
 float Clock::getUpdatesPerSecond() const {
-    return (LENGTH * 1000000000.0f) / sum;
+    return (LENGTH * 1000000000.0f) / static_cast<float>(sum);
 }
 
 Clock::Nanos Clock::getNanos() const {

+ 4 - 4
utils/Color.h

@@ -5,9 +5,9 @@ typedef unsigned char ColorChannel;
 
 template<int N>
 class Color {
-    static_assert(N <= 4, "a color can have at most 4 channels");
+    static_assert(N >= 1 && N <= 4, "a color has 1 to 4 channels");
 
-    ColorChannel data[N];
+    ColorChannel data[static_cast<unsigned int>(N)];
 
 public:
     Color() = default;
@@ -15,12 +15,12 @@ public:
     template<typename... Args>
     Color(ColorChannel a, Args&&... args) {
         const int size = sizeof...(args) + 1;
-        int init[size] = {a, args...};
+        int init[static_cast<unsigned int>(size)] = {a, args...};
         static_assert(
             N == size,
             "color size and amount of channel arguments do not match");
         for(int i = 0; i < N; i++) {
-            data[i] = init[i];
+            data[i] = static_cast<ColorChannel>(init[i]);
         }
     }
 

+ 4 - 4
utils/Logger.h

@@ -8,7 +8,7 @@ namespace Logger {
     extern Level level;
 }
 
-#if LOG_LEVEL >= 1
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 1
 #define LOG_ERROR(text)                                                        \
     if(Logger::level >= Logger::Level::L_ERROR) {                              \
         std::cout << "\33[1;31m[ERROR] " << (text) << "\33[39;49m\n";          \
@@ -17,7 +17,7 @@ namespace Logger {
 #define LOG_ERROR(text)
 #endif
 
-#if LOG_LEVEL >= 2
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 2
 #define LOG_WARNING(text)                                                      \
     if(Logger::level >= Logger::Level::L_WARNING) {                            \
         std::cout << "\33[1;33m[WARNING] " << (text) << "\33[39;49m\n";        \
@@ -26,7 +26,7 @@ namespace Logger {
 #define LOG_WARNING(text)
 #endif
 
-#if LOG_LEVEL >= 3
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 3
 #define LOG_INFO(text)                                                         \
     if(Logger::level >= Logger::Level::L_INFO) {                               \
         std::cout << "\33[1;37m[INFO] " << (text) << "\33[39;49m\n";           \
@@ -35,7 +35,7 @@ namespace Logger {
 #define LOG_INFO(text)
 #endif
 
-#if LOG_LEVEL >= 4
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 4
 #define LOG_DEBUG(text)                                                        \
     if(Logger::level >= Logger::Level::L_DEBUG) {                              \
         std::cout << "\33[1;32m[DEBUG] " << (text) << "\33[39;49m\n";          \

+ 5 - 4
utils/Random.cpp

@@ -1,7 +1,7 @@
-#include <chrono>
-
 #include "utils/Random.h"
 
+#include <chrono>
+
 Random::Random(Seed seed) : index(0) {
     for(int i = 0; i < N; i++) {
         data[i] = seed;
@@ -10,7 +10,8 @@ Random::Random(Seed seed) : index(0) {
 }
 
 Random::Random()
-    : Random(std::chrono::steady_clock::now().time_since_epoch().count()) {
+    : Random(static_cast<Seed>(
+          std::chrono::steady_clock::now().time_since_epoch().count())) {
 }
 
 void Random::update() {
@@ -42,7 +43,7 @@ int Random::next(int min, int inclusiveMax) {
 float Random::nextFloat() {
     static constexpr int bits = sizeof(int) * 6;
     static constexpr int mask = (1 << bits) - 1;
-    return (next() & mask) * (1.0f / (1.0f + mask));
+    return static_cast<float>(next() & mask) * (1.0f / (1.0f + mask));
 }
 
 float Random::nextFloat(float min, float exclusiveMax) {

+ 19 - 11
utils/StringBuffer.h

@@ -1,9 +1,11 @@
 #ifndef STRINGBUFFER_H
 #define STRINGBUFFER_H
 
+#include <cstdarg>
 #include <cstring>
 #include <iostream>
 
+#include "utils/Check.h"
 #include "utils/Types.h"
 
 // ignore buffer overflow warnings with snprintf
@@ -14,7 +16,8 @@ template<int N>
 class StringBuffer final {
     int length;
     Hash hash;
-    char data[N];
+    static_assert(N > 0, "StringBuffer must have a positive size");
+    char data[static_cast<unsigned int>(N)];
 
     void addToHash(char c) {
         hash = static_cast<Hash>(2120251889) * hash + static_cast<Hash>(c);
@@ -93,10 +96,15 @@ public:
         return appendString<const unsigned char*>(str);
     }
 
-    template<typename T>
-    StringBuffer& append(const char* format, const T& t) {
+    check_format(2, 3) StringBuffer& appendFormat(const char* format, ...) {
         int left = N - length;
-        int written = snprintf(data + length, left, format, t);
+
+        va_list args;
+        va_start(args, format);
+        int written = vsnprintf(data + length, static_cast<unsigned int>(left),
+                                format, args);
+        va_end(args);
+
         int oldLength = length;
         if(written < left) {
             length += written;
@@ -108,23 +116,23 @@ public:
     }
 
     StringBuffer& append(signed short s) {
-        return append("%hd", s);
+        return appendFormat("%hd", s);
     }
 
     StringBuffer& append(unsigned short s) {
-        return append("%hu", s);
+        return appendFormat("%hu", s);
     }
 
     StringBuffer& append(signed int i) {
-        return append("%d", i);
+        return appendFormat("%d", i);
     }
 
     StringBuffer& append(unsigned int i) {
-        return append("%u", i);
+        return appendFormat("%u", i);
     }
 
     StringBuffer& append(float f) {
-        return append("%.2f", f);
+        return appendFormat("%.2f", static_cast<double>(f));
     }
 
     StringBuffer& append(bool b) {
@@ -188,8 +196,8 @@ private:
     template<typename T>
     StringBuffer& appendString(T str) {
         for(int i = 0; length < N - 1 && str[i] != '\0'; length++, i++) {
-            data[length] = str[i];
-            addToHash(str[i]);
+            data[length] = static_cast<char>(str[i]);
+            addToHash(static_cast<char>(str[i]));
         }
         data[length] = '\0';
         return *this;

+ 2 - 2
utils/TypedBuffer.h

@@ -8,7 +8,7 @@ class TypedBuffer {
     Buffer data;
 
 public:
-    TypedBuffer(int n) : data(sizeof(T) * n) {
+    TypedBuffer(int n) : data(static_cast<int>(sizeof(T)) * n) {
     }
 
     TypedBuffer& add(const T& t) {
@@ -17,7 +17,7 @@ public:
     }
 
     int getLength() const {
-        return data.getLength() / sizeof(T);
+        return data.getLength() / static_cast<int>(sizeof(T));
     }
 
     int getByteLength() const {

+ 1 - 1
utils/UniquePointer.h

@@ -6,7 +6,7 @@ class UniquePointer {
     T* t;
 
 public:
-    UniquePointer(T* t) : t(t) {
+    UniquePointer(T* t_) : t(t_) {
     }
 
     UniquePointer() : UniquePointer(nullptr) {