Skip to content

Silence a GCC dangling-reference warning in controller parsing - #106

Merged
kahrendt merged 1 commit into
mainfrom
dangling-reference-warning
Aug 12, 2026
Merged

Silence a GCC dangling-reference warning in controller parsing#106
kahrendt merged 1 commit into
mainfrom
dangling-reference-warning

Conversation

@kahrendt

@kahrendt kahrendt commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Bind the supported_commands array to a named local before iterating it
in process_server_state_controller(), so GCC stops emitting
-Wdangling-reference there.

Why

The warning fires on every ESP-IDF build of the component (including via
ESPHome), and is present in released v0.7.1 and on current main:

src/protocol.cpp:554:73: warning: possibly dangling reference to a temporary [-Wdangling-reference]
  554 |              controller_object["supported_commands"].as<JsonArrayConst>()) {
      |                                                                         ^
src/protocol.cpp:554:52: note: 'MemberProxy<JsonObject, RamString>' temporary created here

The range initializer chained .as<JsonArrayConst>() off the
MemberProxy temporary returned by operator[]. Only the final
temporary in such a chain gets lifetime extension in C++20, so the proxy
is destroyed at the end of the full-expression while the loop body is
still running.

It was benign. JsonArrayConst stores only a const ArrayData* and
a const ResourceManager*, both pointing into the JsonDocument's
memory pool, and JsonArrayConstIterator holds an ArrayData::iterator
plus that same resource pointer. Neither the array nor its iterators
retain anything that points into the dead proxy, so the destroyed
temporary was never read. GCC's heuristic cannot see through the proxy
type, though, so this fixes the code rather than suppressing the
diagnostic.

How

-        for (JsonVariantConst command_var :
-             controller_object["supported_commands"].as<JsonArrayConst>()) {
+        JsonArrayConst commands_array =
+            controller_object["supported_commands"].as<JsonArrayConst>();
+        for (JsonVariantConst command_var : commands_array) {

This is also what the rest of the file already does. The five other
array loops (active_roles, artwork channels, visualizer types, and
the roles lists in stream/end and stream/clear) each name a local
first; the loop at line 264 ranges over a function parameter. This was
the only chained range initializer left, so the change makes the file
consistent rather than introducing a new idiom.

No behavior change.

Testing

macOS builds with clang, which does not implement -Wdangling-reference
and so never reproduced this. Verified with Homebrew g++-15 driven at
the host build's exact flags and include set:

  • Warning reproduces verbatim before the change, and is gone after it.
  • Swept every file in src/ and src/host/ with
    -Wall -Wextra -Wdangling-reference -fsyntax-only: no
    dangling-reference warnings remain anywhere.
  • Host clang build rebuilds clean; ctest 123/123 pass.
  • clang-format --dry-run -Werror src/protocol.cpp clean.

GCC emits -Wdangling-reference for the supported_commands range-for in
process_server_state_controller(), and it fires on every ESP-IDF build
of the component:

    warning: possibly dangling reference to a temporary
    note: 'MemberProxy<JsonObject, RamString>' temporary created here

The range initializer chained .as<JsonArrayConst>() off the MemberProxy
temporary returned by operator[]. Only the final temporary gets lifetime
extension, so the proxy dies at the end of the full-expression while the
loop is still running.

It was benign: JsonArrayConst stores a const ArrayData* and a const
ResourceManager*, both pointing into the JsonDocument's memory pool, and
JsonArrayConstIterator holds an ArrayData::iterator plus that same
resource pointer. Nothing reads back through the dead proxy. GCC's
heuristic cannot see that, so bind the array to a named local instead of
suppressing the diagnostic.

This also matches what the file already does everywhere else. The five
other array loops (active_roles, artwork channels, visualizer types, and
both stream roles lists) already name a local first; this was the only
chained range initializer left.

Verified with g++ 15 on the host include set: the warning reproduces
before the change and no -Wdangling-reference remains across src/ or
src/host/ after it. Host clang build and all 123 tests still pass.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a GCC -Wdangling-reference warning in process_server_state_controller() by avoiding a chained temporary in a range-based for loop, aligning this loop with the existing local-binding pattern used elsewhere in src/protocol.cpp.

Changes:

  • Bind controller_object["supported_commands"].as<JsonArrayConst>() to a named local (commands_array) before iterating.
  • Keep parsing behavior unchanged while removing a noisy compiler warning on ESP-IDF/GCC builds.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@kahrendt
kahrendt enabled auto-merge (squash) August 12, 2026 11:28
@kahrendt
kahrendt merged commit 30514d5 into main Aug 12, 2026
6 checks passed
@kahrendt
kahrendt deleted the dangling-reference-warning branch August 12, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants