From 85a76d40678b85dadb547ae79cc92817c2401d2a Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 14 Mar 2026 22:17:25 +0100 Subject: [PATCH 1/7] mitigated `bugprone-assignment-in-selection-statement` clang-tidy warning fixed `readability-redundant-parentheses` clang-tidy warnings mitigated `misc-explicit-constructor` clang-tidy warnings disabled `-Wlifetime-safety-*` Clang warnings for now mitigated `misc-const-correctness` clang-tidy warnings .clang-tidy: disabled `bugprone-std-exception-baseclass` for now .clang-tidy: disabled `bugprone-signed-bitwise` for now mitigated `bugprone-unhandled-code-paths` clang-tidy warnings .clang-tidy: disabled `readability-trailing-comma` clang-tidy check .clang-tidy: removed disabling of `hicpp-*` checks as they no longer exist clang-tidy.yml: updated to Clang 23 --- .clang-tidy | 4 +++- .github/workflows/clang-tidy.yml | 10 +++++----- CMakeLists.txt | 5 +++++ main.cpp | 3 ++- simplecpp.cpp | 29 +++++++++++++++-------------- simplecpp.h | 2 ++ test.cpp | 22 +++++++++++----------- 7 files changed, 43 insertions(+), 32 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index e0b384bf..a35732c0 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -10,7 +10,6 @@ Checks: > -cppcoreguidelines-*, -fuchsia-*, -google-*, - -hicpp-*, -linuxkernel-*, -llvm-*, -llvmlibc-*, @@ -21,6 +20,8 @@ Checks: > -bugprone-branch-clone, -bugprone-easily-swappable-parameters, -bugprone-narrowing-conversions, + -bugprone-signed-bitwise, + -bugprone-std-exception-baseclass, -bugprone-switch-missing-default-case, -bugprone-throwing-static-initialization, -bugprone-unchecked-string-to-number-conversion, @@ -42,6 +43,7 @@ Checks: > -readability-isolate-declaration, -readability-magic-numbers, -readability-redundant-inline-specifier, + -readability-trailing-comma, -readability-use-concise-preprocessor-directives, -readability-uppercase-literal-suffix, -performance-avoid-endl, diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 333672d7..932a0d72 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -33,19 +33,19 @@ jobs: run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 22 - sudo apt-get install clang-tidy-22 + sudo ./llvm.sh 23 + sudo apt-get install clang-tidy-23 - name: Verify clang-tidy configuration run: | - clang-tidy-22 --verify-config + clang-tidy-23 --verify-config - name: Prepare CMake run: | cmake -S . -B cmake.output -Werror=dev --warn-uninitialized -DCMAKE_CXX_STANDARD=23 -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_EXPORT_COMPILE_COMMANDS=ON env: - CXX: clang-22 + CXX: clang-23 - name: Clang-Tidy run: | - run-clang-tidy-22 -q -j $(nproc) -enable-check-profile -p=cmake.output + run-clang-tidy-23 -q -j $(nproc) -enable-check-profile -p=cmake.output diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a90efae..837b07b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options_safe(-Wno-thread-safety-negative) add_compile_options_safe(-Wno-thread-safety-beta) + # TODO: enable + add_compile_options_safe(-Wno-lifetime-safety-intra-tu-suggestions) + add_compile_options_safe(-Wno-lifetime-safety-intra-tu-constructor-suggestions) + add_compile_options_safe(-Wno-lifetime-safety-cross-tu-constructor-suggestions) + # TODO: fix these? add_compile_options(-Wno-padded) add_compile_options(-Wno-sign-conversion) diff --git a/main.cpp b/main.cpp index 06afcfbb..5bd9e9f3 100644 --- a/main.cpp +++ b/main.cpp @@ -26,7 +26,7 @@ static bool isDir(const std::string& path) return (file_stat.st_mode & S_IFMT) == S_IFDIR; } -int main(int argc, char **argv) +int main(int argc, char *argv[]) { bool error = false; const char *filename = nullptr; @@ -49,6 +49,7 @@ int main(int argc, char **argv) if (*arg == '-') { bool found = false; const char c = arg[1]; + // NOLINTNEXTLINE(bugprone-unhandled-code-paths) switch (c) { case 'D': { // define symbol found = true; diff --git a/simplecpp.cpp b/simplecpp.cpp index 748ea6a9..65e3535f 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -153,12 +153,12 @@ static bool endsWith(const std::string &s, const std::string &e) return (s.size() >= e.size()) && std::equal(e.rbegin(), e.rend(), s.rbegin()); } -static bool sameline(const simplecpp::Token *tok1, const simplecpp::Token *tok2) +static bool sameline(const simplecpp::Token * const tok1, const simplecpp::Token * const tok2) { return tok1 && tok2 && tok1->location.sameline(tok2->location); } -static bool isAlternativeBinaryOp(const simplecpp::Token *tok, const std::string &alt) +static bool isAlternativeBinaryOp(const simplecpp::Token * const tok, const std::string &alt) { return (tok->name && tok->str() == alt && @@ -168,7 +168,7 @@ static bool isAlternativeBinaryOp(const simplecpp::Token *tok, const std::string (tok->next->number || tok->next->name || tok->next->op == '(')); } -static bool isAlternativeUnaryOp(const simplecpp::Token *tok, const std::string &alt) +static bool isAlternativeUnaryOp(const simplecpp::Token * const tok, const std::string &alt) { return ((tok->name && tok->str() == alt) && (!tok->previous || tok->previous->op == '(') && @@ -622,7 +622,7 @@ static std::string escapeString(const std::string &str) return ostr.str(); } -static void portabilityBackslash(simplecpp::OutputList *outputList, const simplecpp::Location &location) +static void portabilityBackslash(simplecpp::OutputList * const outputList, const simplecpp::Location &location) { if (!outputList) return; @@ -799,7 +799,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, if (ch == '\\') { TokenString tmp; char tmp_ch = ch; - while ((stream.good()) && (tmp_ch == '\\' || tmp_ch == ' ' || tmp_ch == '\t')) { + while (stream.good() && (tmp_ch == '\\' || tmp_ch == ' ' || tmp_ch == '\t')) { tmp += tmp_ch; tmp_ch = stream.readChar(); } @@ -999,7 +999,7 @@ void simplecpp::TokenList::constFold() } } -static bool isFloatSuffix(const simplecpp::Token *tok) +static bool isFloatSuffix(const simplecpp::Token * const tok) { if (!tok || tok->str().size() != 1U) return false; @@ -1010,7 +1010,7 @@ static bool isFloatSuffix(const simplecpp::Token *tok) static const std::string AND("and"); static const std::string BITAND("bitand"); static const std::string BITOR("bitor"); -static bool isAlternativeAndBitandBitor(const simplecpp::Token* tok) +static bool isAlternativeAndBitandBitor(const simplecpp::Token * const tok) { return isAlternativeBinaryOp(tok, AND) || isAlternativeBinaryOp(tok, BITAND) || isAlternativeBinaryOp(tok, BITOR); } @@ -1699,7 +1699,7 @@ namespace simplecpp { }; struct invalidDirectiveAsMacroParameter : public Error { - invalidDirectiveAsMacroParameter(const Location &loc) + explicit invalidDirectiveAsMacroParameter(const Location &loc) : Error(loc, "it is invalid to use a preprocessor directive as macro parameter") {} }; @@ -2296,7 +2296,7 @@ namespace simplecpp { * @return token after B */ const Token *expandHashHash(TokenList &output, const Location &loc, const Token *tok, const MacroMap ¯os, const std::set &expandedmacros, const std::vector ¶metertokens, bool expandResult=true) const { - Token *A = output.back(); + Token * const A = output.back(); if (!A) throw invalidHashHash(tok->location, name(), "Missing first argument"); if (!sameline(tok, tok->next) || !sameline(tok, tok->next->next)) @@ -3258,7 +3258,7 @@ static bool getFileId(const std::string &path, FileID &id) #endif } -simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, FileDataCache cache) +simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList * const outputList, FileDataCache cache) { #ifdef SIMPLECPP_WINDOWS if (dui.clearIncludeCache) @@ -3341,7 +3341,7 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, return cache; } -static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token *&tok1, simplecpp::MacroMap ¯os, std::vector &files, simplecpp::OutputList *outputList) +static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token *&tok1, simplecpp::MacroMap ¯os, std::vector &files, simplecpp::OutputList * const outputList) { const simplecpp::Token * const tok = tok1; const simplecpp::MacroMap::const_iterator it = tok->name ? macros.find(tok->str()) : macros.end(); @@ -3391,21 +3391,21 @@ static void getLocaltime(struct tm <ime) #endif } -static std::string getDateDefine(const struct tm *timep) +static std::string getDateDefine(const struct tm * const timep) { char buf[] = "??? ?? ????"; strftime(buf, sizeof(buf), "%b %d %Y", timep); return std::string("\"").append(buf).append("\""); } -static std::string getTimeDefine(const struct tm *timep) +static std::string getTimeDefine(const struct tm * const timep) { char buf[] = "??:??:??"; strftime(buf, sizeof(buf), "%H:%M:%S", timep); return std::string("\"").append(buf).append("\""); } -void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, simplecpp::FileDataCache &cache, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) +void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, simplecpp::FileDataCache &cache, const simplecpp::DUI &dui, simplecpp::OutputList * const outputList, std::list * const macroUsage, std::list * const ifCond) { #ifdef SIMPLECPP_WINDOWS if (dui.clearIncludeCache) @@ -3783,6 +3783,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL std::string header; if (systemheader) { + // NOLINTNEXTLINE(bugprone-assignment-in-selection-statement) while ((tok = tok->next) && tok->op != '>') header += tok->str(); if (tok && tok->op == '>') diff --git a/simplecpp.h b/simplecpp.h index ee2eb100..d8fc12cd 100644 --- a/simplecpp.h +++ b/simplecpp.h @@ -75,6 +75,7 @@ namespace simplecpp { struct View { // cppcheck-suppress noExplicitConstructor + // NOLINTNEXTLINE(misc-explicit-constructor) View(const char* data) : mData(data) , mSize(strlen(data)) @@ -88,6 +89,7 @@ namespace simplecpp { {} // cppcheck-suppress noExplicitConstructor + // NOLINTNEXTLINE(misc-explicit-constructor) View(const std::string& str) : mData(str.data()) , mSize(str.size()) diff --git a/test.cpp b/test.cpp index 3a858929..952fe722 100644 --- a/test.cpp +++ b/test.cpp @@ -86,7 +86,7 @@ static void assertThrowFailed(int line) std::cerr << "exception not thrown" << std::endl; } -static void testcase(const std::string &name, void (*f)(), int argc, char * const *argv) +static void testcase(const std::string &name, void (*const f)(), int argc, char *argv[]) { if (argc == 1) { f(); @@ -101,7 +101,7 @@ static void testcase(const std::string &name, void (*f)(), int argc, char * cons #define TEST_CASE(F) (testcase(#F, F, argc, argv)) -static simplecpp::TokenList makeTokenList(const char code[], std::size_t size, std::vector &filenames, const std::string &filename=std::string(), simplecpp::OutputList *outputList=nullptr) +static simplecpp::TokenList makeTokenList(const char code[], std::size_t size, std::vector &filenames, const std::string &filename=std::string(), simplecpp::OutputList * const outputList=nullptr) { switch (USE_INPUT) { case Input::Stringstream: { @@ -115,24 +115,24 @@ static simplecpp::TokenList makeTokenList(const char code[], std::size_t size, s return simplecpp::TokenList{filenames}; // unreachable - needed for GCC and Visual Studio } -static simplecpp::TokenList makeTokenList(const char code[], std::vector &filenames, const std::string &filename=std::string(), simplecpp::OutputList *outputList=nullptr) +static simplecpp::TokenList makeTokenList(const char code[], std::vector &filenames, const std::string &filename=std::string(), simplecpp::OutputList * const outputList=nullptr) { return makeTokenList(code, strlen(code), filenames, filename, outputList); } -static std::string readfile(const char code[], simplecpp::OutputList *outputList=nullptr) +static std::string readfile(const char code[], simplecpp::OutputList * const outputList=nullptr) { std::vector files; return makeTokenList(code,files,std::string(),outputList).stringify(); } -static std::string readfile(const char code[], std::size_t size, simplecpp::OutputList *outputList=nullptr) +static std::string readfile(const char code[], std::size_t size, simplecpp::OutputList * const outputList=nullptr) { std::vector files; return makeTokenList(code,size,files,std::string(),outputList).stringify(); } -static std::string preprocess(const char code[], const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage = nullptr, std::list *ifCond = nullptr, const std::string &file = std::string()) +static std::string preprocess(const char code[], const simplecpp::DUI &dui, simplecpp::OutputList * const outputList, std::list * const macroUsage = nullptr, std::list * const ifCond = nullptr, const std::string &file = std::string()) { std::vector files; simplecpp::FileDataCache cache; @@ -160,17 +160,17 @@ static std::string preprocess(const char code[], const simplecpp::DUI &dui) return preprocess(code, dui, nullptr); } -static std::string preprocess(const char code[], simplecpp::OutputList *outputList) +static std::string preprocess(const char code[], simplecpp::OutputList * const outputList) { return preprocess(code, simplecpp::DUI(), outputList); } -static std::string preprocess(const char code[], std::list *ifCond) +static std::string preprocess(const char code[], std::list * const ifCond) { return preprocess(code, simplecpp::DUI(), nullptr, nullptr, ifCond); } -static std::string preprocess(const char code[], std::list *macroUsage) +static std::string preprocess(const char code[], std::list * const macroUsage) { return preprocess(code, simplecpp::DUI(), nullptr, macroUsage); } @@ -3960,7 +3960,7 @@ static void leak() } } -static void runTests(int argc, char **argv, Input input) +static void runTests(int argc, char *argv[], Input input) { USE_INPUT = input; @@ -4257,7 +4257,7 @@ static void runTests(int argc, char **argv, Input input) TEST_CASE(leak); } -int main(int argc, char **argv) +int main(int argc, char *argv[]) { runTests(argc, argv, Input::Stringstream); runTests(argc, argv, Input::CharBuffer); From a4defa8086c857efdc60b933fdf88e3d0c0d3122 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 11 Jul 2026 12:11:28 +0200 Subject: [PATCH 2/7] added `SIMPLECPP_LIFETIMEBOUND` --- simplecpp.cpp | 10 ++++++++++ simplecpp.h | 12 ++++++++++++ test.cpp | 10 ++++++++++ 3 files changed, 32 insertions(+) diff --git a/simplecpp.cpp b/simplecpp.cpp index 65e3535f..3054eb14 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -60,6 +60,16 @@ # include #endif +#if defined(__has_cpp_attribute) +# if __has_cpp_attribute (clang::lifetimebound) +# define SIMPLECPP_LIFETIMEBOUND [[clang::lifetimebound]] +# else +# define SIMPLECPP_LIFETIMEBOUND +# endif +#else +# define SIMPLECPP_LIFETIMEBOUND +#endif + static bool isHex(const std::string &s) { return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0); diff --git a/simplecpp.h b/simplecpp.h index d8fc12cd..0cfd324b 100644 --- a/simplecpp.h +++ b/simplecpp.h @@ -42,6 +42,16 @@ # define SIMPLECPP_LIB #endif +#if defined(__has_cpp_attribute) +# if __has_cpp_attribute (clang::lifetimebound) +# define SIMPLECPP_LIFETIMEBOUND [[clang::lifetimebound]] +# else +# define SIMPLECPP_LIFETIMEBOUND +# endif +#else +# define SIMPLECPP_LIFETIMEBOUND +#endif + #if defined(_MSC_VER) # pragma warning(push) // suppress warnings about "conversion from 'type1' to 'type2', possible loss of data" @@ -602,6 +612,8 @@ namespace simplecpp { # pragma warning(pop) #endif +#undef SIMPLECPP_LIFETIMEBOUND + #undef SIMPLECPP_LIB #endif diff --git a/test.cpp b/test.cpp index 952fe722..3d3f1702 100644 --- a/test.cpp +++ b/test.cpp @@ -22,6 +22,16 @@ #error "SIMPLECPP_TEST_SOURCE_DIR is not defined." #endif +#if defined(__has_cpp_attribute) +# if __has_cpp_attribute (clang::lifetimebound) +# define SIMPLECPP_LIFETIMEBOUND [[clang::lifetimebound]] +# else +# define SIMPLECPP_LIFETIMEBOUND +# endif +#else +# define SIMPLECPP_LIFETIMEBOUND +#endif + #define STRINGIZE_(x) #x #define STRINGIZE(x) STRINGIZE_(x) From 50f5ae6de9598a975a108ddb68d65e762ea0c502 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 11 Jul 2026 12:12:58 +0200 Subject: [PATCH 3/7] fixed `-Wlifetime-safety-intra-tu-suggestions` Clang warnings --- CMakeLists.txt | 8 ++++++-- simplecpp.cpp | 6 +++--- simplecpp.h | 14 +++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 837b07b4..f3ea188a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,8 +73,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options_safe(-Wno-thread-safety-negative) add_compile_options_safe(-Wno-thread-safety-beta) - # TODO: enable - add_compile_options_safe(-Wno-lifetime-safety-intra-tu-suggestions) + # we do not add the annotation until C++20 + # the warnings were introduced with Clang 23 + if(CMAKE_CXX_STANDARD LESS 20) + add_compile_options_safe(-Wno-lifetime-safety-intra-tu-suggestions) + endif() add_compile_options_safe(-Wno-lifetime-safety-intra-tu-constructor-suggestions) add_compile_options_safe(-Wno-lifetime-safety-cross-tu-constructor-suggestions) @@ -88,6 +91,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # we are not interested in these set_source_files_properties(test.cpp PROPERTIES COMPILE_FLAGS "-Wno-multichar -Wno-four-char-constants") + # TODO: check for proper AppleClang version if (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 14 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14) # TODO: verify this regression still exists in clang-15 if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") diff --git a/simplecpp.cpp b/simplecpp.cpp index 3054eb14..597146f2 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -1689,7 +1689,7 @@ namespace simplecpp { } /** how has this macro been used so far */ - const std::list &usage() const { + const std::list &usage() const SIMPLECPP_LIFETIMEBOUND { return usageList; } @@ -1884,7 +1884,7 @@ namespace simplecpp { const Token *appendTokens(TokenList &tokens, const Location &rawloc, - const Token * const lpar, + const Token * const lpar SIMPLECPP_LIFETIMEBOUND, const MacroMap ¯os, const std::set &expandedmacros, const std::vector ¶metertokens) const { @@ -3011,7 +3011,7 @@ static long long evaluate(simplecpp::TokenList &expr, const simplecpp::DUI &dui, return expr.cfront() && expr.cfront() == expr.cback() && expr.cfront()->number ? stringToLL(expr.cfront()->str()) : 0LL; } -static const simplecpp::Token *gotoNextLine(const simplecpp::Token *tok) +static const simplecpp::Token *gotoNextLine(const simplecpp::Token *tok SIMPLECPP_LIFETIMEBOUND) { const unsigned int line = tok->location.line; const unsigned int file = tok->location.fileIndex; diff --git a/simplecpp.h b/simplecpp.h index 0cfd324b..03949faa 100644 --- a/simplecpp.h +++ b/simplecpp.h @@ -172,7 +172,7 @@ namespace simplecpp { Token &operator=(const Token &tok) = delete; - const TokenString& str() const { + const TokenString& str() const SIMPLECPP_LIFETIMEBOUND { return string; } void setstr(const std::string &s) { @@ -493,22 +493,22 @@ namespace simplecpp { size_type size() const { return mData.size(); } - iterator begin() { + iterator begin() SIMPLECPP_LIFETIMEBOUND { return mData.begin(); } - iterator end() { + iterator end() SIMPLECPP_LIFETIMEBOUND { return mData.end(); } - const_iterator begin() const { + const_iterator begin() const SIMPLECPP_LIFETIMEBOUND { return mData.begin(); } - const_iterator end() const { + const_iterator end() const SIMPLECPP_LIFETIMEBOUND { return mData.end(); } - const_iterator cbegin() const { + const_iterator cbegin() const SIMPLECPP_LIFETIMEBOUND { return mData.cbegin(); } - const_iterator cend() const { + const_iterator cend() const SIMPLECPP_LIFETIMEBOUND { return mData.cend(); } From 08765750899b4102f6391d4810ed521aa3463da2 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 11 Jul 2026 12:30:28 +0200 Subject: [PATCH 4/7] .clang-tidy: disabled `modernize-use-auto` for now test.cpp: fixed `misc-include-cleaner` clang-tidy warning .clang-tidy: disabled some warnings only fixable when targeting newer C++ standards make it possibly to actually override the C++ standard in CMake --- .clang-tidy | 5 +++++ CMakeLists.txt | 6 +++++- test.cpp | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index a35732c0..d829b813 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -32,10 +32,15 @@ Checks: > -modernize-avoid-c-arrays, -modernize-loop-convert, -modernize-pass-by-value, + -modernize-use-auto, + -modernize-use-designated-initializers, -modernize-use-nodiscard, + -modernize-use-ranges, + -modernize-use-starts-ends-with, -modernize-use-trailing-return-type, -readability-avoid-nested-conditional-operator, -readability-braces-around-statements, + -readability-container-contains, -readability-function-cognitive-complexity, -readability-function-size, -readability-implicit-bool-conversion, diff --git a/CMakeLists.txt b/CMakeLists.txt index f3ea188a..c5c502a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,13 @@ cmake_minimum_required (VERSION 3.10) project (simplecpp LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to use") set(CMAKE_CXX_STANDARD_REQUIRED ON) +if(CMAKE_CXX_STANDARD LESS 11) + message(FATAL_ERROR "C++ standard was set to ${CMAKE_CXX_STANDARD} but 11 is required as a minimum") +endif() + include(CheckCXXCompilerFlag) if (WIN32) diff --git a/test.cpp b/test.cpp index 3d3f1702..a88163a2 100644 --- a/test.cpp +++ b/test.cpp @@ -18,6 +18,10 @@ #include #include +#ifdef __cpp_lib_string_view +#include +#endif + #ifndef SIMPLECPP_TEST_SOURCE_DIR #error "SIMPLECPP_TEST_SOURCE_DIR is not defined." #endif From 52c57d81b9e5dea35186c42b041f84451bede885 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 11 Jul 2026 15:49:48 +0200 Subject: [PATCH 5/7] fixed `-Wlifetime-safety-intra-tu-constructor-suggestions` Clang warnings --- CMakeLists.txt | 2 +- simplecpp.cpp | 10 +++++----- simplecpp.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5c502a7..ebb8d1c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # the warnings were introduced with Clang 23 if(CMAKE_CXX_STANDARD LESS 20) add_compile_options_safe(-Wno-lifetime-safety-intra-tu-suggestions) + add_compile_options_safe(-Wno-lifetime-safety-intra-tu-constructor-suggestions) endif() - add_compile_options_safe(-Wno-lifetime-safety-intra-tu-constructor-suggestions) add_compile_options_safe(-Wno-lifetime-safety-cross-tu-constructor-suggestions) # TODO: fix these? diff --git a/simplecpp.cpp b/simplecpp.cpp index 597146f2..9d4dad89 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -368,7 +368,7 @@ namespace { class StdIStream : public simplecpp::TokenList::Stream { public: // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members - explicit StdIStream(std::istream &istr) + explicit StdIStream(std::istream &istr SIMPLECPP_LIFETIMEBOUND) : istr(istr) { assert(istr.good()); init(); @@ -394,7 +394,7 @@ namespace { class StdCharBufStream : public simplecpp::TokenList::Stream { public: // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members - StdCharBufStream(const unsigned char* str, std::size_t size) + StdCharBufStream(const unsigned char* str SIMPLECPP_LIFETIMEBOUND, std::size_t size) : str(str) , size(size) { @@ -1508,12 +1508,12 @@ namespace simplecpp { class Macro { public: - explicit Macro(std::vector &f) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), variadicOpt(false), valueDefinedInCode_(false) {} + explicit Macro(std::vector &f SIMPLECPP_LIFETIMEBOUND) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), variadicOpt(false), valueDefinedInCode_(false) {} /** * @throws std::runtime_error thrown on bad macro syntax */ - Macro(const Token *tok, std::vector &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(true) { + Macro(const Token *tok, std::vector &f SIMPLECPP_LIFETIMEBOUND) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(true) { if (sameline(tok->previousSkipComments(), tok)) throw std::runtime_error("bad macro syntax"); if (tok->op != '#') @@ -1532,7 +1532,7 @@ namespace simplecpp { /** * @throws std::runtime_error thrown on bad macro syntax */ - Macro(const std::string &name, const std::string &value, std::vector &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(false) { + Macro(const std::string &name, const std::string &value, std::vector &f SIMPLECPP_LIFETIMEBOUND) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(false) { const std::string def(name + ' ' + value); StdCharBufStream stream(reinterpret_cast(def.data()), def.size()); tokenListDefine.readfile(stream); diff --git a/simplecpp.h b/simplecpp.h index 03949faa..0f832b06 100644 --- a/simplecpp.h +++ b/simplecpp.h @@ -86,7 +86,7 @@ namespace simplecpp { { // cppcheck-suppress noExplicitConstructor // NOLINTNEXTLINE(misc-explicit-constructor) - View(const char* data) + View(const char* data SIMPLECPP_LIFETIMEBOUND) : mData(data) , mSize(strlen(data)) {} @@ -100,7 +100,7 @@ namespace simplecpp { // cppcheck-suppress noExplicitConstructor // NOLINTNEXTLINE(misc-explicit-constructor) - View(const std::string& str) + View(const std::string& str ) : mData(str.data()) , mSize(str.size()) {} From 2dd5a05ae30d340cb43461350c714d614ca12a50 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 11 Jul 2026 15:57:35 +0200 Subject: [PATCH 6/7] fixed `-Wlifetime-safety-cross-tu-constructor-suggestions` Clang warnings --- CMakeLists.txt | 2 +- simplecpp.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebb8d1c1..d31b2989 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,8 +82,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_STANDARD LESS 20) add_compile_options_safe(-Wno-lifetime-safety-intra-tu-suggestions) add_compile_options_safe(-Wno-lifetime-safety-intra-tu-constructor-suggestions) + add_compile_options_safe(-Wno-lifetime-safety-cross-tu-constructor-suggestions) endif() - add_compile_options_safe(-Wno-lifetime-safety-cross-tu-constructor-suggestions) # TODO: fix these? add_compile_options(-Wno-padded) diff --git a/simplecpp.h b/simplecpp.h index 0f832b06..2b19faaf 100644 --- a/simplecpp.h +++ b/simplecpp.h @@ -269,9 +269,9 @@ namespace simplecpp { public: class Stream; - explicit TokenList(std::vector &filenames); + explicit TokenList(std::vector &filenames SIMPLECPP_LIFETIMEBOUND); /** generates a token list from the given std::istream parameter */ - TokenList(std::istream &istr, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr); + TokenList(std::istream &istr, std::vector &filenames SIMPLECPP_LIFETIMEBOUND, const std::string &filename=std::string(), OutputList *outputList = nullptr); /** generates a token list from the given buffer */ template TokenList(const char (&data)[size], std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) @@ -309,7 +309,7 @@ namespace simplecpp { #endif // __cpp_lib_span /** generates a token list from the given filename parameter */ - TokenList(const std::string &filename, std::vector &filenames, OutputList *outputList = nullptr); + TokenList(const std::string &filename, std::vector &filenames SIMPLECPP_LIFETIMEBOUND, OutputList *outputList = nullptr); TokenList(const TokenList &other); TokenList(TokenList &&other); ~TokenList(); @@ -389,7 +389,7 @@ namespace simplecpp { const std::string& file(const Location& loc) const; private: - TokenList(const unsigned char* data, std::size_t size, std::vector &filenames, const std::string &filename, OutputList *outputList, int /*unused*/); + TokenList(const unsigned char* data, std::size_t size, std::vector &filenames SIMPLECPP_LIFETIMEBOUND, const std::string &filename, OutputList *outputList, int /*unused*/); void combineOperators(); From 8f65217ae55a044045321724adf98cbc9bc473b4 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 11 Jul 2026 16:08:27 +0200 Subject: [PATCH 7/7] test.cpp fixed `-Wlifetime-safety-intra-tu-suggestions` Clang warnings --- test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.cpp b/test.cpp index a88163a2..3a19a6db 100644 --- a/test.cpp +++ b/test.cpp @@ -115,7 +115,7 @@ static void testcase(const std::string &name, void (*const f)(), int argc, char #define TEST_CASE(F) (testcase(#F, F, argc, argv)) -static simplecpp::TokenList makeTokenList(const char code[], std::size_t size, std::vector &filenames, const std::string &filename=std::string(), simplecpp::OutputList * const outputList=nullptr) +static simplecpp::TokenList makeTokenList(const char code[], std::size_t size, std::vector &filenames SIMPLECPP_LIFETIMEBOUND, const std::string &filename=std::string(), simplecpp::OutputList * const outputList=nullptr) { switch (USE_INPUT) { case Input::Stringstream: { @@ -129,7 +129,7 @@ static simplecpp::TokenList makeTokenList(const char code[], std::size_t size, s return simplecpp::TokenList{filenames}; // unreachable - needed for GCC and Visual Studio } -static simplecpp::TokenList makeTokenList(const char code[], std::vector &filenames, const std::string &filename=std::string(), simplecpp::OutputList * const outputList=nullptr) +static simplecpp::TokenList makeTokenList(const char code[], std::vector &filenames SIMPLECPP_LIFETIMEBOUND, const std::string &filename=std::string(), simplecpp::OutputList * const outputList=nullptr) { return makeTokenList(code, strlen(code), filenames, filename, outputList); }