Using the original register_component name (just moved to protected)
produces identical compiled output to the baseline, avoiding the
symbol name length overhead from renaming.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Rename the non-template to register_component_impl_ and add
a protected template register_component_ that wraps it. This
preserves the compiler optimization behavior (isra clones)
while keeping the method inaccessible to external components.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Without the template wrapper, the compiler inlines the 24-byte
function at each of ~92 call sites in setup(), growing setup()
by ~284 bytes. Force a function call instead.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Arduino.h on ESP8266 already declares void setup(void), so our
forward declaration triggers readability-redundant-declaration.
Co-Authored-By: J. Nick Koston <nick@koston.org>
The cpp test framework renames setup() to original_setup() and
replaces setup() with the gtest runner, so we need to friend both.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Instead of runtime null, duplicate, and capacity checks in
register_component_, make the method unreachable from outside
codegen by removing the public template wrapper and granting
friend access to the codegen-generated ::setup() function.
Since ESPHOME_COMPONENT_COUNT is set to exactly
len(CORE.component_ids) at codegen time, the StaticVector is
always correctly sized and the runtime capacity check cannot
trigger from codegen. External components that bypassed codegen
to call App.register_component() directly will now get a
compile error, forcing them to properly declare their components
in their config schema.
Co-Authored-By: J. Nick Koston <nick@koston.org>
Fix clang-tidy bugprone-unchecked-optional-access in speed fan,
speaker media player, and sprinkler components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Store optional results in local variables before checking
and dereferencing to satisfy bugprone-unchecked-optional-access.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move set_component_state_ from component.cpp to the header as
an inline method so it can be reused wherever Component state
needs to be updated. Replace the manual bit manipulation in
Application::enable_pending_loops_ with a call to the helper.
Co-Authored-By: J. Nick Koston <nick@koston.org>
get_state() requires callers to check has_state() first.
This is a documented precondition, not an unchecked access.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The custom optional implementation (from optional-bare, 2017) predates
C++17. All ESPHome platforms now compile with gnu++20, making
std::optional available everywhere.
The custom implementation had several issues:
- No emplace() support
- Always default-constructs value_ (wasteful for non-trivial types)
- reset() only flips a bool without destroying the value
- No move semantics
- Requires T to be default constructible
Replace with using aliases (using std::optional, using std::nullopt,
etc.) so all existing code using esphome::optional continues to work.
Also fix ~30 unsafe .value() calls across climate IR components that
relied on the custom optional's behavior of returning a
default-constructed value when empty. With std::optional, accessing
an empty optional is UB. These are replaced with value_or() using
appropriate defaults (CLIMATE_FAN_AUTO, CLIMATE_PRESET_NONE).
The sen6x test YAML used identical sensor IDs (pm_1_0, pm_2_5,
pm_4_0, pm_10_0) as sen5x, causing ID redefinition errors when
both components are tested together in grouped builds. Prefix
the sen6x IDs with sen6x_ to make them unique.
Make set_mode(const char*, size_t) the real implementation using
ESPHOME_strncasecmp_P with length checks, instead of ignoring len
and delegating to the null-terminated overload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Avoid implicit StringRef->std::string conversion when the protobuf
message fields are already StringRef. Use the (const char*, size_t)
overloads directly.