From 94bb252c16b486f56a9852b9c82080702b697b4d Mon Sep 17 00:00:00 2001 From: Bee Klimt Date: Mon, 26 Oct 2026 11:00:30 -0700 Subject: [PATCH 1/4] chore: Disable bugprone-unchecked-optional-access and guard fragile optionals --- .clang-tidy | 11 +++++++++++ .github/workflows/cpp-linter.yml | 4 ++-- .../src/data_sources/fdv2/streaming_synchronizer.cpp | 7 +++++-- .../src/data_sources/polling_data_source.cpp | 11 +++++++++-- .../src/data_systems/fdv2/fdv2_polling_impl.cpp | 7 +++++-- .../src/data_systems/fdv2/streaming_synchronizer.cpp | 7 +++++-- libs/server-sdk/src/evaluation/rules.cpp | 10 +++++++--- 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 154cb4e32..17ba14bff 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,15 @@ --- +Checks: > + boost-*, + bugprone-*, + -bugprone-unchecked-optional-access, + performance-*, + readability-*, + portability-*, + modernize-*, + -modernize-use-trailing-return-type, + clang-analyzer-*, + cppcoreguidelines-* CheckOptions: - { key: readability-identifier-length.IgnoredParameterNames, value: 'i|j|k|c|os|it' } - { key: readability-identifier-length.IgnoredVariableNames, value: 'ec|id|it' } diff --git a/.github/workflows/cpp-linter.yml b/.github/workflows/cpp-linter.yml index 62ccd9e34..f36af69a6 100644 --- a/.github/workflows/cpp-linter.yml +++ b/.github/workflows/cpp-linter.yml @@ -38,8 +38,8 @@ jobs: style: file # The file extensions to run the action against. This comma-separated string defaults to 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx'. # extensions: # optional, default is c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx - # A string of regex-like patterns specifying what checks clang-tidy will use. This defaults to 'boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*'. See also clang-tidy docs for more info. - tidy-checks: boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,-modernize-use-trailing-return-type,clang-analyzer-*,cppcoreguidelines-* + # A blank string makes clang-tidy use only the checks in .clang-tidy files. + tidy-checks: '' # The relative path to the repository root directory. The default value '.' is relative to the runner's GITHUB_WORKSPACE environment variable. # repo-root: # optional, default is . # The desired version of the clang tools to use. Accepted options are strings which can be 15, 14, 13, 12, 11, 10, 9, or 8. Defaults to 12. diff --git a/libs/client-sdk/src/data_sources/fdv2/streaming_synchronizer.cpp b/libs/client-sdk/src/data_sources/fdv2/streaming_synchronizer.cpp index 2f52877b3..689440100 100644 --- a/libs/client-sdk/src/data_sources/fdv2/streaming_synchronizer.cpp +++ b/libs/client-sdk/src/data_sources/fdv2/streaming_synchronizer.cpp @@ -309,11 +309,14 @@ void FDv2StreamingSynchronizer::State::OnEvent(sse::Event const& event) { } else if constexpr (std::is_same_v) { if (r.kind == FDv2ProtocolHandler::Error::Kind::kServerError) { - auto const& id = r.server_error.value().id; + std::string id; + if (r.server_error) { + id = r.server_error->id.value_or(""); + } std::string msg = "An issue was encountered receiving updates for " "payload '" + - id.value_or("") + "' with reason: '" + r.message + + id + "' with reason: '" + r.message + "'. Automatic retry will occur."; LD_LOG(logger_, LogLevel::kInfo) << kIdentity << ": " << msg; diff --git a/libs/client-sdk/src/data_sources/polling_data_source.cpp b/libs/client-sdk/src/data_sources/polling_data_source.cpp index 4e50f612b..e6cd4bf21 100644 --- a/libs/client-sdk/src/data_sources/polling_data_source.cpp +++ b/libs/client-sdk/src/data_sources/polling_data_source.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include #include #include @@ -148,7 +148,14 @@ void PollingDataSource::HandlePollResult(network::HttpResult res) { << "Polling for feature flag updates failed: " << (res.ErrorMessage() ? *res.ErrorMessage() : "unknown error"); } else if (res.Status() == 200) { - data_source_handler_.HandleMessage("put", res.Body().value()); + if (res.Body()) { + data_source_handler_.HandleMessage("put", *res.Body()); + } else { + status_manager_.SetState( + DataSourceStatus::DataSourceState::kInterrupted, + DataSourceStatus::ErrorInfo::ErrorKind::kUnknown, + "Polling response contained no body"); + } } else if (res.Status() == 304) { // This should be handled ahead of here, but if we get a 304, // and it didn't have an etag, we still don't want to try to diff --git a/libs/server-sdk/src/data_systems/fdv2/fdv2_polling_impl.cpp b/libs/server-sdk/src/data_systems/fdv2/fdv2_polling_impl.cpp index 0b668851b..c57b82e6e 100644 --- a/libs/server-sdk/src/data_systems/fdv2/fdv2_polling_impl.cpp +++ b/libs/server-sdk/src/data_systems/fdv2/fdv2_polling_impl.cpp @@ -138,11 +138,14 @@ static FDv2SourceResult ParseFDv2PollEvents( } if (auto* error = std::get_if(&result)) { if (error->kind == FDv2ProtocolHandler::Error::Kind::kServerError) { - auto const& id = error->server_error.value().id; + std::string id; + if (error->server_error) { + id = error->server_error->id.value_or(""); + } std::string msg = "An issue was encountered receiving updates for " "payload '" + - id.value_or("") + "' with reason: '" + error->message + + id + "' with reason: '" + error->message + "'. Automatic retry will occur."; return FDv2SourceResult{FDv2SourceResult::Interrupted{ MakeError(ErrorKind::kErrorResponse, 0, std::move(msg))}}; diff --git a/libs/server-sdk/src/data_systems/fdv2/streaming_synchronizer.cpp b/libs/server-sdk/src/data_systems/fdv2/streaming_synchronizer.cpp index 0f09ef5cf..a8a6c4d00 100644 --- a/libs/server-sdk/src/data_systems/fdv2/streaming_synchronizer.cpp +++ b/libs/server-sdk/src/data_systems/fdv2/streaming_synchronizer.cpp @@ -272,11 +272,14 @@ void FDv2StreamingSynchronizer::State::OnEvent(sse::Event const& event) { } else if constexpr (std::is_same_v) { if (r.kind == FDv2ProtocolHandler::Error::Kind::kServerError) { - auto const& id = r.server_error.value().id; + std::string id; + if (r.server_error) { + id = r.server_error->id.value_or(""); + } std::string msg = "An issue was encountered receiving updates for " "payload '" + - id.value_or("") + "' with reason: '" + r.message + + id + "' with reason: '" + r.message + "'. Automatic retry will occur."; LD_LOG(logger_, LogLevel::kInfo) << kIdentity << ": " << msg; diff --git a/libs/server-sdk/src/evaluation/rules.cpp b/libs/server-sdk/src/evaluation/rules.cpp index 8e37259e9..5a5350242 100644 --- a/libs/server-sdk/src/evaluation/rules.cpp +++ b/libs/server-sdk/src/evaluation/rules.cpp @@ -4,6 +4,7 @@ #include "../data_components/big_segments/big_segment_store_wrapper.hpp" +#include #include #include #include @@ -30,8 +31,9 @@ enum EvaluationReason::BigSegmentsStatus ToBigSegmentsStatus( return EvaluationReason::BigSegmentsStatus::kHealthy; } -std::string MakeBigSegmentRef(Segment const& segment) { - return segment.key + ".g" + std::to_string(*segment.generation); +std::string MakeBigSegmentRef(std::string const& key, + std::uint64_t generation) { + return key + ".g" + std::to_string(generation); } // Evaluates membership in an unbounded (Big) segment. Returns true/false for a @@ -46,6 +48,7 @@ std::optional MatchBigSegment(Segment const& segment, EvaluationReason::BigSegmentsStatus::kNotConfigured); return false; } + std::uint64_t const generation = *segment.generation; // An absent or empty unboundedContextKind defaults to "user". ContextKind const kind = (segment.unboundedContextKind && @@ -81,7 +84,8 @@ std::optional MatchBigSegment(Segment const& segment, membership = stack.FindMembership(key); } - return membership->CheckMembership(MakeBigSegmentRef(segment)); + return membership->CheckMembership( + MakeBigSegmentRef(segment.key, generation)); } } // namespace From 15b3183fc0b36f0eabbb1b246656e415ea28eaaf Mon Sep 17 00:00:00 2001 From: Bee Klimt Date: Mon, 26 Oct 2026 11:37:34 -0700 Subject: [PATCH 2/4] chore: Disable the clang-tidy magic number checks --- .clang-tidy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 17ba14bff..4b2d1a09f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,7 +9,9 @@ Checks: > modernize-*, -modernize-use-trailing-return-type, clang-analyzer-*, - cppcoreguidelines-* + cppcoreguidelines-*, + -cppcoreguidelines-avoid-magic-numbers, + -readability-magic-numbers CheckOptions: - { key: readability-identifier-length.IgnoredParameterNames, value: 'i|j|k|c|os|it' } - { key: readability-identifier-length.IgnoredVariableNames, value: 'ec|id|it' } From db90aea5ef0edb93ba4d9a2bb736fed54dab19c8 Mon Sep 17 00:00:00 2001 From: Bee Klimt Date: Mon, 26 Oct 2026 11:45:14 -0700 Subject: [PATCH 3/4] chore: Disable readability-identifier-length --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-tidy b/.clang-tidy index 4b2d1a09f..b0563517a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -5,6 +5,7 @@ Checks: > -bugprone-unchecked-optional-access, performance-*, readability-*, + -readability-identifier-length, portability-*, modernize-*, -modernize-use-trailing-return-type, From a7b4fb18ce4eae25a9938bdd693de95aca7329b7 Mon Sep 17 00:00:00 2001 From: Bee Klimt Date: Mon, 26 Oct 2026 11:50:26 -0700 Subject: [PATCH 4/4] chore: Sort the clang-tidy check list --- .clang-tidy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index b0563517a..82b75971a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -2,16 +2,16 @@ Checks: > boost-*, bugprone-*, - -bugprone-unchecked-optional-access, - performance-*, - readability-*, - -readability-identifier-length, - portability-*, - modernize-*, - -modernize-use-trailing-return-type, clang-analyzer-*, cppcoreguidelines-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -bugprone-unchecked-optional-access, -cppcoreguidelines-avoid-magic-numbers, + -modernize-use-trailing-return-type, + -readability-identifier-length, -readability-magic-numbers CheckOptions: - { key: readability-identifier-length.IgnoredParameterNames, value: 'i|j|k|c|os|it' }