diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | cmake/warnings.cmake | 82 | ||||
-rw-r--r-- | include/fud_assert.hpp | 2 | ||||
-rw-r--r-- | include/fud_c_file.hpp | 2 | ||||
-rw-r--r-- | include/fud_memory.hpp | 6 | ||||
-rw-r--r-- | include/fud_utf8.hpp | 11 | ||||
-rw-r--r-- | include/libfud.hpp | 9 | ||||
-rw-r--r-- | source/fud_directory.cpp | 16 | ||||
-rw-r--r-- | source/fud_sqlite.cpp | 16 | ||||
-rw-r--r-- | source/fud_string.cpp | 6 | ||||
-rw-r--r-- | source/fud_utf8.cpp | 12 | ||||
-rwxr-xr-x | tools/coverage.sh | 5 | ||||
-rwxr-xr-x | tools/create-pyenv.sh | 9 | ||||
-rwxr-xr-x | tools/run-cppcheck.sh | 46 |
14 files changed, 165 insertions, 60 deletions
@@ -9,4 +9,5 @@ cppcheck.json test/fuzztest dist/ .semgrepignore -.#*
\ No newline at end of file +.#* +fudenv/ diff --git a/cmake/warnings.cmake b/cmake/warnings.cmake index 03d7a32..cd3cdf9 100644 --- a/cmake/warnings.cmake +++ b/cmake/warnings.cmake @@ -1,65 +1,93 @@ set(FUD_WARNINGS + # baseline -Werror - -Wstack-usage=2048 - -Wno-long-long - -Wno-error=long-long - -Wno-error=inline - -Wno-error=mismatched-tags -Wall - -Weffc++ + -Wextra -pedantic - -Wsizeof-pointer-memaccess -pedantic-errors - -Wextra + -Wstack-usage=2048 # GCC specific + -Wvla # variable modified types don't play nice in C++ + # types + -Wlong-long + -Wlong-long + -Winline + # memory / data / array / string + -Wsizeof-pointer-memaccess -Wpacked - -Wshadow - -Wvla - -Wnull-dereference -Wuninitialized -Wstack-protector -Warray-bounds -Woverlength-strings -Wwrite-strings - -Wcast-qual -Wcast-align - -Wdisabled-optimization + -Wchar-subscripts + -Wpointer-arith + -Wstrict-aliasing + -Wstrict-aliasing=2 + -Wstrict-null-sentinel + # classes / initialization + -Weffc++ + -Wmismatched-tags -Wmissing-field-initializers - -Wimport -Winit-self - -Wchar-subscripts - -Wcomment - -Wconversion - -Wfloat-equal + -Wctor-dtor-privacy + -Wnon-virtual-dtor + -Wsuggest-final-types + -Wsuggest-final-methods + -Wsuggest-override + # format -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wmissing-format-attribute + -Wformat-overflow + -Wformat-security + -Wformat-signedness + # floats and signedness + -Wfloat-equal + -Wsign-compare + -Wsign-conversion + -Wdouble-promotion + # semantics / style + -Wshadow + -Wnull-dereference + -Wimplicit-fallthrough=5 + -Wduplicated-branches + -Wduplicated-cond + -Wcast-qual + -Wcomment + -Wconversion -Wmissing-braces -Winvalid-pch -Wmissing-include-dirs - -Wmissing-noreturn -Wparentheses - -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point - -Wsign-compare - -Wstrict-aliasing - -Wstrict-aliasing=2 - -Wswitch - -Wswitch-default - -Wswitch-enum -Wtrigraphs -Wunknown-pragmas - -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable + -Wswitch + -Wswitch-default + -Wswitch-enum + # this plays badly with clangd + # -Wzero-as-null-pointer-constant + -Wlogical-op + -Wuseless-cast + -Wextra-semi + -Wredundant-decls + -Wmisleading-indentation + # optmizations + -Wdisabled-optimization + -Wmissing-noreturn -Wvariadic-macros -Wvolatile-register-var + -Wunreachable-code ) diff --git a/include/fud_assert.hpp b/include/fud_assert.hpp index 5b63703..fd861ea 100644 --- a/include/fud_assert.hpp +++ b/include/fud_assert.hpp @@ -24,7 +24,7 @@ void assertFail(const char* assertion, const char* file, unsigned int line, cons __attribute__((__noreturn__)); #define fudAssert(expr) \ - (static_cast<bool>(expr) ? static_cast<void>(0) : assertFail(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__)) + ((expr) ? static_cast<void>(0) : assertFail(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__)) } // namespace fud diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp index 3b7d821..0908841 100644 --- a/include/fud_c_file.hpp +++ b/include/fud_c_file.hpp @@ -151,7 +151,7 @@ class CFile { FILE* file() { - auto& self = static_cast<Derived&>(*this); + const auto& self = static_cast<const Derived&>(*this); return self.m_file; } diff --git a/include/fud_memory.hpp b/include/fud_memory.hpp index 41393bd..62ff81a 100644 --- a/include/fud_memory.hpp +++ b/include/fud_memory.hpp @@ -77,7 +77,7 @@ void copyMem(T& destination, const U& source) for (size_t idx = 0; idx < Count; ++idx) { // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) - reinterpret_cast<uint8_t*>(&destination)[idx] = reinterpret_cast<const uint8_t*>(&source)[idx]; + reinterpret_cast<char*>(&destination)[idx] = reinterpret_cast<const char*>(&source)[idx]; // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) } } @@ -115,11 +115,13 @@ int compareMem(const T& lhs, U&& rhs) static_assert(Count <= sizeof(T)); static_assert(Count <= sizeof(U)); + U uRhs{std::forward<U>(rhs)}; + int difference = 0; for (size_t idx = 0; idx < Count; ++idx) { // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) difference = reinterpret_cast<const uint8_t*>(&lhs)[idx] - - reinterpret_cast<const uint8_t*>(&std::forward<U>(rhs))[idx]; + reinterpret_cast<const uint8_t*>(&uRhs)[idx]; // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) if (difference != 0) { break; diff --git a/include/fud_utf8.hpp b/include/fud_utf8.hpp index 99766d4..5b84a3a 100644 --- a/include/fud_utf8.hpp +++ b/include/fud_utf8.hpp @@ -19,7 +19,6 @@ #define FUD_UTF8_HPP #include "fud_array.hpp" -#include "fud_memory.hpp" #include "fud_status.hpp" #include "fud_unique_array.hpp" @@ -62,7 +61,7 @@ constexpr bool validUtf8MB(utf8 code) noexcept struct Ascii { Array<utf8, 1> characters; - constexpr Ascii() noexcept = default; + constexpr Ascii() noexcept = default; // cppcheck-suppress uninitMemberVar constexpr explicit Ascii(utf8 chr) noexcept : characters{{chr}} { @@ -252,10 +251,10 @@ struct FudUtf8 { static constexpr Ascii invalidAsciiCode{Ascii{0xFF}}; static FudUtf8 fromString(const String& fudString, size_t index) noexcept; - static FudUtf8 fromStringView(StringView&& fudView, size_t index) noexcept; - static FudUtf8 fromStringView(const StringView& fudView, size_t index) noexcept; + static FudUtf8 fromStringView(StringView&& view, size_t index) noexcept; + static FudUtf8 fromStringView(const StringView& view, size_t index) noexcept; - static constexpr FudUtf8 makeUtf8(Array<utf8, 4>& data) + static constexpr FudUtf8 makeUtf8(const Array<utf8, 4>& data) { FudUtf8 unicode{}; if (Ascii::valid(data[0])) { @@ -367,10 +366,10 @@ struct FudUtf8 { [[nodiscard]] constexpr int64_t hash() const noexcept { - using fud::Utf8Type; using fud::Utf82Byte; using fud::Utf83Byte; using fud::Utf84Byte; + using fud::Utf8Type; if (!valid()) { return -1; diff --git a/include/libfud.hpp b/include/libfud.hpp index 1e6df5d..271d55b 100644 --- a/include/libfud.hpp +++ b/include/libfud.hpp @@ -27,6 +27,15 @@ namespace fud { /** \brief Fear, unknown, doubt. Call at your own peril. */ void fud(); +/** + * \brief Get an environmental variable if it exists. + * + * \param[in] name The name of the variable to look up. + * + * \retstmt The value of the string bound to the variable if it exists. + * \retcode FudStatus::NullPointer if name is a null pointer. + * \retcode FudStatus::NotFound if no binding for the variable exists. + */ Result<String, FudStatus> getEnv(const char* name); template<typename T> diff --git a/source/fud_directory.cpp b/source/fud_directory.cpp index 6851158..5772c95 100644 --- a/source/fud_directory.cpp +++ b/source/fud_directory.cpp @@ -137,15 +137,15 @@ Result<DirectoryEntry, FudStatus> Directory::info() return RetType::error(m_status); } - Stat statBuffer{}; - auto status = fstat(m_dirFd, &statBuffer); - if (status == -1) { + Stat sBuffer{}; + auto fStatus = fstat(m_dirFd, &sBuffer); + if (fStatus == -1) { m_errorCode = errno; m_status = FudStatus::Failure; return RetType::error(m_status); } - auto retValue = DirectoryEntry::fromStat(m_name, statBuffer); + auto retValue = DirectoryEntry::fromStat(m_name, sBuffer); if (retValue.isOkay()) { m_errorCode = 0; @@ -187,17 +187,17 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry() m_errorCode = 0; - Stat statBuffer{}; + Stat sBuffer{}; auto flags = 0; - auto status = fstatat(m_dirFd, entryNameCString, &statBuffer, flags); - if (status == -1) { + auto fStatus = fstatat(m_dirFd, entryNameCString, &sBuffer, flags); + if (fStatus == -1) { m_errorCode = errno; m_status = FudStatus::Failure; return RetType::error(m_status); } auto entryName = String{entryNameCString}; - auto retValue = DirectoryEntry::fromStat(entryName, statBuffer); + auto retValue = DirectoryEntry::fromStat(entryName, sBuffer); if (retValue.isOkay()) { m_errorCode = 0; diff --git a/source/fud_sqlite.cpp b/source/fud_sqlite.cpp index f573f1c..e07523d 100644 --- a/source/fud_sqlite.cpp +++ b/source/fud_sqlite.cpp @@ -58,6 +58,8 @@ SqliteDb& SqliteDb::operator=(SqliteDb&& rhs) m_nameValid = rhs.m_nameValid; m_dbHandle = rhs.m_dbHandle; m_errorCode = rhs.m_errorCode; + m_mode = rhs.m_mode; + m_extraFlags = rhs.m_extraFlags; rhs.m_nameValid = false; rhs.m_dbHandle = nullptr; @@ -94,9 +96,9 @@ FudStatus SqliteDb::exec( } char* errorMsgPtr = nullptr; - char** errorMsgPtrAddress = &errorMsgPtr; - if (errorMessage == nullptr) { - errorMsgPtrAddress = nullptr; + char** errorMsgPtrAddress = nullptr; + if (errorMessage != nullptr) { + errorMsgPtrAddress = &errorMsgPtr; } m_errorCode = sqlite3_exec( @@ -106,6 +108,10 @@ FudStatus SqliteDb::exec( context, errorMsgPtrAddress); + if (errorMessage != nullptr) { + *errorMessage = String{errorMsgPtr}; + } + return m_errorCode == SQLITE_OK ? FudStatus::Success : FudStatus::Failure; } @@ -126,10 +132,10 @@ int SqliteDb::open() return sqlite3_open_v2(m_name.c_str(), &m_dbHandle, static_cast<int>(m_mode) | m_extraFlags, nullptr); } -Result<SqliteStatement, FudStatus> SqliteDb::prepare(const String& dql) +Result<SqliteStatement, FudStatus> SqliteDb::prepare(const String& sql) { using RetType = Result<SqliteStatement, FudStatus>; - SqliteStatement preparedStatement{*this, dql}; + SqliteStatement preparedStatement{*this, sql}; if (!preparedStatement.valid() || preparedStatement.status() != FudStatus::Success) { m_errorCode = preparedStatement.errorCode(); diff --git a/source/fud_string.cpp b/source/fud_string.cpp index 10352ad..4cffb60 100644 --- a/source/fud_string.cpp +++ b/source/fud_string.cpp @@ -357,12 +357,12 @@ FudStatus String::append(StringView source) return FudStatus::Aliased; } - const auto newLength = length() + source.length(); + const size_t newLength = length() + source.length(); if (newLength < length()) { return FudStatus::OperationInvalid; } - const auto newSize = newLength + 1; - if (newSize < newLength) { + const size_t newSize = newLength + 1; // cppcheck-suppress knownConditionTrueFalse + if (newSize < newLength) { // cppcheck-suppress knownConditionTrueFalse return FudStatus::OperationInvalid; } if (newSize >= m_capacity) { diff --git a/source/fud_utf8.cpp b/source/fud_utf8.cpp index 1c23581..50b5d31 100644 --- a/source/fud_utf8.cpp +++ b/source/fud_utf8.cpp @@ -41,32 +41,32 @@ FudUtf8 FudUtf8::fromStringView(const StringView& view, size_t index) noexcept FudUtf8 FudUtf8::fromStringView(StringView&& view, size_t index) noexcept { auto len = view.length(); - const auto* data = view.data(); - if (data == nullptr) { + const auto* vData = view.data(); + if (vData == nullptr) { return invalidAscii(); } - FudUtf8 localChar{Ascii{data[index]}}; + FudUtf8 localChar{Ascii{vData[index]}}; if (localChar.valid()) { return localChar; } if (index + 1 < len) { - localChar.m_variant = Utf82Byte{data[index], data[index + 1]}; + localChar.m_variant = Utf82Byte{vData[index], vData[index + 1]}; } if (localChar.valid()) { return localChar; } if (index + 2 < len) { - localChar.m_variant = Utf83Byte{data[index], data[index + 1], data[index + 2]}; + localChar.m_variant = Utf83Byte{vData[index], vData[index + 1], vData[index + 2]}; } if (localChar.valid()) { return localChar; } if (index + 3 < len) { - localChar.m_variant = Utf84Byte{data[index], data[index + 1], data[index + 2], data[index + 3]}; + localChar.m_variant = Utf84Byte{vData[index], vData[index + 1], vData[index + 2], vData[index + 3]}; } if (localChar.valid()) { return localChar; diff --git a/tools/coverage.sh b/tools/coverage.sh new file mode 100755 index 0000000..5caa6f0 --- /dev/null +++ b/tools/coverage.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +ctest --test-dir build/test -j8 +mkdir -p build/html +gcovr --exclude-throw-branches --exclude build/_deps/ --exclude test -r source . --html-details build/html/gcovr_report.html diff --git a/tools/create-pyenv.sh b/tools/create-pyenv.sh new file mode 100755 index 0000000..64b1fbf --- /dev/null +++ b/tools/create-pyenv.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +PROJ_ROOT=$(git rev-parse --show-toplevel) +cd $PROJ_ROOT + +python3 -m venv fudenv +. fudenv/bin/activate +pip install cppcheck-codequality +deactivate diff --git a/tools/run-cppcheck.sh b/tools/run-cppcheck.sh new file mode 100755 index 0000000..1f8ee7d --- /dev/null +++ b/tools/run-cppcheck.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# libfud +# Copyright 2024 Dominick Allen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PROJ_ROOT=$(git rev-parse --show-toplevel) +cd $PROJ_ROOT + +COMPILE_COMMANDS='build/compile_commands.json' + +cppcheck \ + --verbose \ + --inline-suppr \ + --checkers-report=build/cppcheck-checkers-report.log \ + --suppress=useStlAlgorithm \ + --suppress=missingIncludeSystem \ + --suppress=functionStatic \ + --suppress=functionConst \ + --suppress=unusedFunction \ + --enable=all \ + --inconclusive \ + --max-ctu-depth=8 \ + --check-level=exhaustive \ + -i build/ \ + --cppcheck-build-dir=build/ \ + --project="$COMPILE_COMMANDS" \ + --verbose \ + --error-exitcode=2 \ + --xml 2> build/err.xml + +cppcheck-htmlreport --file=build/err.xml --report-dir=build/cppcheck_report --source-dir="$PROJ_ROOT" +. fudenv/bin/activate +python3 -m cppcheck_codequality --input-file=build/err.xml --base-dir=$PROJ_ROOT --output-file=build/cppcheck.json +deactivate |