Skip to content

#11681 - Enable -Wshadow-field and investigate actual bugs it finds#11684

Draft
jmarrec wants to merge 38 commits into
developfrom
Wshadow-field
Draft

#11681 - Enable -Wshadow-field and investigate actual bugs it finds#11684
jmarrec wants to merge 38 commits into
developfrom
Wshadow-field

Conversation

@jmarrec

@jmarrec jmarrec commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Pull request overview

Description of the purpose of this PR

Enable -Wshadow-field on clang and fixup the warnings. Found a few fixable bugs.

Found another one that will warrant another issue in HeatPumpAirToWater, for now I restored the behavior to the current so I wouldn't produce diff, but it seems that there are more than a few issues.

Pull Request Author

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies
  • If adding/removing any output files (e.g., eplustbl.*)
    • Update ..\scripts\Epl-run.bat
    • Update ..\scripts\RunEPlus.bat
    • Update ..\src\EPLaunch\ MainModule.bas, epl-ui.frm, and epl.vbp (VersionComments)
    • Update ...github\workflows\energyplus.py

Reviewer

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

jmarrec added 30 commits July 9, 2026 09:42
```bash
run-clang-tidy     -checks='-*,modernize-use-override'     -p=/Users/julien/Software/Others/EnergyPlus-build-release-clang     -header-filter='src/EnergyPlus/.*'     -fix     -j "$(sysctl -n hw.ncpu)"     'src/EnergyPlus/.*\.cc$'

run-clang-tidy     -checks='-*,modernize-use-override'     -p=/Users/julien/Software/Others/EnergyPlus-build-release-clang     -header-filter='tst/EnergyPlus/.*'     -fix     -j "$(sysctl -n hw.ncpu)"     'tst/EnergyPlus/.*\.cc$'
```
…rts (objexx, kiva, libtk205)

Preparatory step for declaring per-target third_party dependencies
instead of leaking every third_party include dir globally via
project_options.

- New header-only INTERFACE targets: cli11 (CLI11.hpp moved to third_party/CLI/CLI/CLI11.hpp to match the <CLI/CLI11.hpp> include
  spelling) and valijson.
- objexx now exports its own include dir instead of relying on the global include.
- libkiva: point at our shared third_party/eigen (vendor/eigen is stripped from our vendored kiva) and export kiva/src for E+'s <libkiva/...> include spelling.
- libtk205: link btwxt instead of the removed vendor/btwxt copy.
- Document the kiva and libtk205 patches in third_party/PATCHES.md.
Removes the top-level project_options SYSTEM INTERFACE include dirs that exposed every third_party library to every target regardless of
whether it was actually used. Each target now links only the third_party libraries it needs directly, PUBLIC if used in its own
public headers and PRIVATE if only in .cc/.cpp.

- energyplusparser, energypluslib, energyplusapi, energyplus, and ConvertInputFormat now link cli11/objexx/valijson explicitly instead
  of relying on the global include path.
- generate_embeddable_epJSON_schema links nlohmann_json directly.
- airflownetworklib gains objexx (PUBLIC) and re2/Windows-CalcEngine
  (PRIVATE), and I moved btwxt to PRIVATE since it's not part of the headers
     - I don't think this should be a separate lib (see #7123): its sources and headers depend on EnergyPlus/ headers and objects throughout (circular with energypluslib, resolved only at final link). It should be folded into energypluslib which would delete most of these links
- Dropped the now-dead SAM_SKIP_*/SAMAPI_EXPORT/BUILD_PENUMBRA_TESTING block in the top-level CMakeLists.txt: third_party/CMakeLists.txt already sets these correctly before its own add_subdirectory calls,  so the top-level copies ran too late to have any effect.

add_subdirectory(third_party SYSTEM) (CMake >= 3.25) still makes any remaining third_party INTERFACE includes -isystem for consumers
automatically, so no explicit SYSTEM keyword is needed at the call sites added here.
…IR}) here (same pattern as objexx), so energypluslib gets the vendored header via its existing PUBLIC sqlite link

Wasn't getting the build erorr on this Linux machine because I have sqlite3-dev installed...
nlohmann_json used to export the whole third_party/ root as an include path, silently supplying <BCVTB/...>, <FMI/...>, <fast_float/...> and <milo/...> wherever it was linked. Nesting its headers under third_party/nlohmann/nlohmann/ (like the earlier CLI11 move) and scoping its export to just that directory turns those hidden dependencies into real link errors instead of accidents.

- doj/alphanum.hpp moved under third_party/nlohmann/doj/ since it's only used by our patched json.hpp.
- New fast_float and milo INTERFACE targets, each nested one level to match their include spelling, linked PRIVATE onto energyplusparser and energypluslib (fast_float PUBLIC in energyplus_lib because it's in StringUtilities.hh). cli11/valijson given the same SYSTEM treatment as upstream libraries (e.g. googletest) use on their own targets.
- epfmiimport, bcvtb, and epexpat now export their own include dir PUBLIC instead of relying on directory-scoped include_directories() calls; Expat reordered ahead of BCVTB so bcvtb can link it.
- DElight: dropped the DElight/ prefix from its one external include site instead of nesting ~80 files; DElight now exports its own directory PUBLIC.
- Fixed the EP_CXX_PCH_HEADERS path for json.hpp to match its new location
… advanced option ENABLE_WARNINGS_IN_THIRD_PARTY

third_party was doing link_libraries and add_compile_options global calls, which leaks everywhere downstream
We use target_link_libraries specifically now.

third_party/CMakeLists.txt used to apply project_options and project_fp_options to every subsequently-added target via directory-scoped
link_libraries() calls. Because that's the plain (default-PUBLIC) form, it silently propagated project_options' interface requirements -- most
importantly the ${PROJECT_SOURCE_DIR}/src include dir and -Werror -- to anything that happened to link a third-party target, whether or not that
consumer asked for it.

Each third-party target now links project_options and project_fp_options explicitly and PRIVATE, tracked in a new all_third_party_targets list so the warning-suppression loop below doesn't need to be updated by hand every time a target is added.

Add an advanced ENABLE_WARNINGS_IN_THIRD_PARTY option (default OFF):
- OFF (default): every third-party target links turn_off_warnings (-w),   fully silencing the compiler for vendored code, same as before.
- ON: most third-party targets link project_warnings plus a new  warnings_as_not_error target (-Wno-error / /WX-) so the extra diagnostics
  surface without turning -Werror on vendored code into hard build failures.  This is useful for sanity once in a while

Fix ssc/ssc/CMakeLists.txt's own target_link_libraries calls to use the PUBLIC keyword form (matching upstream) instead of the plain signature -- CMake forbids mixing plain and keyword signatures for the same target, and this file already needed one or the other once third_party/CMakeLists.txt started using keywords.

Also normalize third_party/FMUParser/CMakeLists.txt to lowercase commands and the keyword target_link_libraries signature, since parser needed the
same signature fix.
…ject_warnings currently as it won't build with it

[ 97%][154/158] Building CXX object src/EnergyPlus/AirflowNetwork/CMakeFiles/airflownetworklib.dir/src/Elements.cpp.o
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Elements.cpp:448:49: warning: unused parameter 'state' [-Wunused-parameter]
  448 |     int SurfaceCrack::calculate(EnergyPlusData &state,
      |                                                 ^
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Elements.cpp:787:42: warning: unused parameter 'i' [-Wunused-parameter]
  787 |                                int const i,                              // Linkage number
      |                                          ^
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Elements.cpp:1074:37: warning: unused parameter 'i' [-Wunused-parameter]
 1074 |                           int const i,                              // Linkage number
      |                                     ^
3 warnings generated.
[ 98%][155/158] Building CXX object src/EnergyPlus/AirflowNetwork/CMakeFiles/airflownetworklib.dir/src/Solver.cpp.o
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Solver.cpp:147:45: warning: field 'm_state' will be initialized after field 'properties' [-Wreorder-ctor]
  147 |     Solver::Solver(EnergyPlusData &state) : m_state(state), properties(state)
      |                                             ^~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~
      |                                             properties(state) m_state(state)
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Solver.cpp:10742:17: warning: unused variable 'j' [-Wunused-variable]
 10742 |             int j = AirflowNetworkLinkageData(i).NodeNums[0];
       |                 ^
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Solver.cpp:10743:17: warning: unused variable 'k' [-Wunused-variable]
 10743 |             int k = AirflowNetworkLinkageData(i).NodeNums[1];
       |                 ^
/home/julien/Software/Others/EnergyPlus2/src/EnergyPlus/AirflowNetwork/src/Solver.cpp:13393:78: warning: unused parameter 'state' [-Wunused-parameter]
 13393 |     bool OccupantVentilationControlProp::closing_probability(EnergyPlusData &state,
       |                                                                              ^
4 warnings generated.
[100%][158/158] Linking CXX static library Products/libairflownetworklib.a
```
[ 40%][2/5] Building CXX object src\EnergyPlus\AirflowNetwork\CMakeFiles\airflownetworklib.dir\src\Elements.cpp.obj
cl : Command line warning D9025 : overriding '/WX' with '/WX-'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(113): warning C4458: declaration of 'A1' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Elements.hpp(1001): note: see declaration of 'EnergyPlus::AirflowNetwork::Duct::A1'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(125): warning C4458: declaration of 'g' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Elements.hpp(1000): note: see declaration of 'EnergyPlus::AirflowNetwork::Duct::g'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(262): warning C4458: declaration of 'A1' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Elements.hpp(1001): note: see declaration of 'EnergyPlus::AirflowNetwork::Duct::A1'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(274): warning C4458: declaration of 'g' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Elements.hpp(1000): note: see declaration of 'EnergyPlus::AirflowNetwork::Duct::g'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(722): warning C4458: declaration of 'AirLoopNum' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Elements.hpp(1096): note: see declaration of 'EnergyPlus::AirflowNetwork::ConstantVolumeFan::AirLoopNum'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(1847): warning C4458: declaration of 'OpenFactor' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Elements.hpp(536): note: see declaration of 'EnergyPlus::AirflowNetwork::SimpleOpening::OpenFactor'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(1521) : warning C4701: potentially uninitialized local variable 'WFact' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(1522) : warning C4701: potentially uninitialized local variable 'HFact' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(1523) : warning C4701: potentially uninitialized local variable 'Cfact' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(1638) : warning C4701: potentially uninitialized local variable 'Lextra' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Elements.cpp(1707) : warning C4701: potentially uninitialized local variable 'Axishght' used
[ 60%][3/5] Building CXX object src\EnergyPlus\AirflowNetwork\CMakeFiles\airflownetworklib.dir\src\Solver.cpp.obj
cl : Command line warning D9025 : overriding '/WX' with '/WX-'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(4699): warning C4458: declaration of 'compnum' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(418): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::compnum'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(4837): warning C4458: declaration of 'compnum' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(418): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::compnum'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(4965): warning C4458: declaration of 'compnum' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(418): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::compnum'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14334): warning C4458: declaration of 'AU' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(454): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::AU'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14335): warning C4458: declaration of 'AD' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(453): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::AD'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14337): warning C4458: declaration of 'IK' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(452): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::IK'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14485): warning C4458: declaration of 'AU' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(454): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::AU'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14486): warning C4458: declaration of 'AD' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(453): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::AD'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14489): warning C4458: declaration of 'IK' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(452): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::IK'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14593): warning C4458: declaration of 'IK' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(452): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::IK'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14594): warning C4458: declaration of 'AU' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(454): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::AU'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(14595): warning C4458: declaration of 'AD' hides class member
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\include\AirflowNetwork/Solver.hpp(453): note: see declaration of 'EnergyPlus::AirflowNetwork::Solver::AD'
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(9119) : warning C4701: potentially uninitialized local variable 'RepOnOffFanRunTimeFraction' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(6715) : warning C4701: potentially uninitialized local variable 'PressureSet' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12027) : warning C4701: potentially uninitialized local variable 'X1' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12027) : warning C4701: potentially uninitialized local variable 'Y1' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12019) : warning C4701: potentially uninitialized local variable 'ZoneAng1' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12027) : warning C4701: potentially uninitialized local variable 'X2' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12027) : warning C4701: potentially uninitialized local variable 'Y2' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12019) : warning C4701: potentially uninitialized local variable 'ZoneAng2' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12838) : warning C4701: potentially uninitialized local variable 'Velocity' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(12964) : warning C4701: potentially uninitialized local variable 'Velocity' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(13086) : warning C4701: potentially uninitialized local variable 'Velocity' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(1465) : warning C4701: potentially uninitialized local variable 'inletNode' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(1466) : warning C4701: potentially uninitialized local variable 'outletNode' used
C:\src\EnergyPlus\src\EnergyPlus\AirflowNetwork\src\Solver.cpp(2237) : warning C4701: potentially uninitialized local variable 'NumAPL' used
[ 80%][4/5] Linking CXX static library Products\airflownetworklib.lib
```
… getting ffp-contract from third_party...

22
  1702: [ RUN      ] EnergyPlusFixture.OutputReportTabular_GatherHeatEmissionReport
  1702: /Users/runner/work/EnergyPlus/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:3773: Failure
  1702: Expected equality of these values:
  1702:   2 * condenserReject * Constant::convertJtoGJ + coilReject * Constant::convertJtoGJ
  1702:     Which is: 0.00010831
  1702:   state->dataHeatBal->BuildingPreDefRep.emiHVACReject
  1702:     Which is: 0.00010831
  1/1 Test #1702: EnergyPlusFixture.OutputReportTabular_GatherHeatEmissionReport ...***Exception: SegFault  0.07 sec
I didn't get that C4127 on MSVC 2026 but CI reported it

And exclude a warning that is thrown anyways regardles off /W0 in shared (ssc)
/Users/julien/Software/Others/EnergyPlus/third_party/btwxt/include/btwxt/logging.h:33:52: error: parameter 'message' shadows member inherited from type 'CourierrException' [-Werror,-Wshadow-field]
   33 |         explicit BtwxtException(const std::string &message, Courierr::Courierr &logger)
      |                                                    ^
/Users/julien/Software/Others/EnergyPlus/third_party/btwxt/vendor/courierr/include/courierr/courierr.h:66:17: note: declared here
   66 |     std::string message;
      |                 ^
In file included from /Users/julien/Software/Others/EnergyPlus/src/EnergyPlus/api/state.cc:49:
In file included from /Users/julien/Software/Others/EnergyPlus/src/EnergyPlus/Data/CommonIncludes.hh:266:
In file included from /Users/julien/Software/Others/EnergyPlus/src/EnergyPlus/SolarShading.hh:61:
In file included from /Users/julien/Software/Others/EnergyPlus/third_party/penumbra/include/penumbra/penumbra.h:16:
/Users/julien/Software/Others/EnergyPlus/third_party/penumbra/include/penumbra/logging.h:40:49: error: parameter 'message' shadows member inherited from type 'CourierrException' [-Werror,-Wshadow-field]
   40 |   explicit PenumbraException(const std::string &message, Courierr::Courierr &logger)
      |                                                 ^
/Users/julien/Software/Others/EnergyPlus/third_party/btwxt/vendor/courierr/include/courierr/courierr.h:66:17: note: declared here
   66 |     std::string message;
51ba69
Removed `BaseThermalPropertySet Properties;` from `BaseCell`, and instead gave each of its three derived structs its own appropriately-typed `Properties` member directly:
- `RadialCellInformation` → `BaseThermalPropertySet Properties;` (new, explicit)
- `CartesianCell` → `BaseThermalPropertySet Properties;` (new, explicit)
- `FluidCellInformation` → kept its existing `ExtendedFluidProperties Properties;` (unchanged)

**Why:** `FluidCellInformation` was redeclaring `Properties` with the wider `ExtendedFluidProperties` type (adds `Viscosity`/`Prandtl`) to shadow the inherited `BaseThermalPropertySet Properties` from `BaseCell` — needed so that bulk-assignments like `cell.PipeCellData.Fluid.Properties = thisCircuit->CurFluidPropertySet;` copy the full extended struct instead of object-slicing it. This triggered a `-Wshadow-field` warning, and — since C++ field-hiding isn't virtual dispatch — meant every `FluidCellInformation` instance carried a second, entirely dead `BaseThermalPropertySet` subobject inherited from `BaseCell` that was never read or written.

Since `BaseCell` itself is never instantiated or referenced directly (only used as a base for these three structs), moving `Properties` down into each derived struct removes the shadowing entirely and eliminates the wasted subobject, with no behavior change — `RadialCellInformation` and `CartesianCell` still get the same `BaseThermalPropertySet Properties` they had before, just declared locally instead of inherited.
So there’s a ZoneHVAC:Baseboard:RadiantConvective:Steam and a ZoneHVAC:Baseboard:RadiantConvective:Steam:Design objects

The C++ `SteamBaseboardParams` instance has an `int` index to find the `SteamBaseboardDesignData`...

But the `SteamBaseboardDesignData` inherits from `SteamBaseboardParams`, so it carries EVERY field from SteamBaseboardParams, so about 656 bytes for no reason!

It shouldn't inherit at all!
jmarrec added 8 commits July 10, 2026 16:27
… inheriting

Here HWBaseboardParams::HeatingCapMethod/ScaledHeatingCapacity are genuinely used as per-instance cached copies (set once from the design object, read every   timestep), so those stayed untouched
Removed four pure-duplicate member redeclarations that shadowed identical inherited fields for no reason — same name, same type, same default, no divergent usage found anywhere in the `.cc`:

- `EIRPlantLoopHeatPump::oneTimeInitFlag` (line 209) — exact duplicate of `PlantComponent::oneTimeInitFlag` (`bool`, default `true`). Deleted; `this->oneTimeInitFlag` now resolves to the inherited one, same behavior.
- `EIRFuelFiredHeatPump::flowMode` — exact duplicate of `EIRPlantLoopHeatPump::flowMode` (`DataPlant::FlowMode`, default `Invalid`). Deleted.
- `EIRFuelFiredHeatPump::capModFTErrorIndex`, `eirModFTErrorIndex`, `eirModFPLRErrorIndex` — exact duplicates of the same-named `int` error-index members on `EIRPlantLoopHeatPump` (all default `0`). Deleted.

In all four cases the derived class had no custom constructor initializing these differently, and every usage site accessed them polymorphically through `this->` — so removing the redeclaration doesn't change behavior, just stops the derived object from carrying (and the compiler from having to reason about) two separately-named-but-identical copies of the same state.
…en it goes to an array for HeatPumpAirToWater

The base class xxxFuncYYYCurveIndex still exists but it's left untouched at int = 0, so trying to access curves(int) with it will throw when NDEBUG not defined, and having three unused ints beats creating a new derived class...
…in there

Fix regression in HeatPumpAirToWater sizing from companionHeatPumpCoil rename

The Wshadow-field fix in 4f15f0b removed HeatPumpAirToWater's own `companionHeatPumpCoil` shadow member and had its pairUpCompanionCoils() assign into the base EIRPlantLoopHeatPump::companionHeatPumpCoil instead.
That member is also read by EIRPlantLoopHeatPump::sizeLoadSide() (and other base sizing methods), whose companion-based sizing branch was written for, and only type-checks against, the plain PlantLoopHeatPump:EIR
Heating/Cooling pair (DataPlant::PlantEquipmentType::HeatPumpEIRHeating/Cooling) -- it was never adapted for HeatPumpAirToWater.
Before the rename, this branch was structurally unreachable for AWHP objects (the base member always stayed null for them); after the rename it started firing, changing autosized "Rated Water Volume Flow Rate in Heating Mode" for PlantLoopHeatPump_EIR_AirSource_and_AWHP.eio from 0.005 to 0.018 m3/s.

Fixing it: Restore a separate, non-shadowing member (companionAWHPCoil) used only by  `HeatPumpAirToWater::pairUpCompanionCoils()`/`calcOpMode()`, leaving the base member's null-for-AWHP behavior intact, matching pre-fix sizing results.

Needs further investigation (separate, pre-existing issue, not caused by this branch).

`HeatPumpAirToWater::sizeLoadSide()` is not virtual, and its only would-be caller (EIRPlantLoopHeatPump::onInitLoopEquip) invokes `this->sizeLoadSide(state)` from within the base class's own scope, so that call always statically resolves to `EIRPlantLoopHeatPump::sizeLoadSide`,
never the derived override.
Confirmed no production or test code calls `sizeLoadSide()` through a HeatPumpAirToWater*-typed pointer either, so `HeatPumpAirToWater::sizeLoadSide()` (and its referenceCapacityOneUnit
recompute) is effictively dead code today. Left a TODO comment at the definition;

This likely needs a real fix (e.g. making sizeLoadSide virtual, or overriding onInitLoopEquip in HeatPumpAirToWater) but that's a behavior (and diff-producing) change out of scope for this PR.
@jmarrec jmarrec self-assigned this Jul 10, 2026
@jmarrec jmarrec added Defect Includes code to repair a defect in EnergyPlus Developer Issue Related to cmake, packaging, installers, or developer tooling (CI, etc) labels Jul 10, 2026
Comment thread cmake/CompilerFlags.cmake
target_compile_options(project_options INTERFACE $<$<CONFIG:RelWithDebInfo>:-UNDEBUG>)
target_compile_options(project_fp_options INTERFACE -ffp-contract=off) # Disable fused-floating point operations (default is fast)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
target_compile_options(project_warnings INTERFACE -Wshadow-field) # Equivalent to MSVC's C4458 (declaration of 'identifier' hides class member); narrower than -Wshadow

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

New flag on clang. Like I said, -Wshadow is way too noisy

};

struct SteamBaseboardDesignData : SteamBaseboardParams
struct SteamBaseboardDesignData

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Wshadow revealed a big inheritance mistake in SteamBaseboardRadiator

So there’s a ZoneHVAC:Baseboard:RadiantConvective:Steam and a ZoneHVAC:Baseboard:RadiantConvective:Steam:Design objects

The C++ SteamBaseboardParams instance has an int index to find the SteamBaseboardDesignData...

But the SteamBaseboardDesignData inherits from SteamBaseboardParams, so it carries EVERY field from SteamBaseboardParams, so about 656 bytes for no reason!

It shouldn't inherit at all!

};

struct HWBaseboardDesignData : HWBaseboardParams
struct HWBaseboardDesignData

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same issue as the Steam counterpart


// logic flags
bool oneTimeInitFlag = true;
bool oneTimeInitFlagPLHP = true;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

oneTimeInitFlag is defined in PlantComponent, which is inherits, but we need that flag here as it's used to call SetupOutputVariables

Comment on lines +494 to +496
std::array<int, maxNumSpeeds + 1> capFuncTempCurveIndices = {};
std::array<int, maxNumSpeeds + 1> powerRatioFuncTempCurveIndices = {};
std::array<int, maxNumSpeeds + 1> powerRatioFuncPLRCurveIndices = {};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

EIRPlantLoopHeatPump defines int indices

struct HeatPumpAirToWater : public EIRPlantLoopHeatPump would redefine it: it shadows with a different type. Not great.

Ideally we add a different Base but this was too much change for not so much gains, so I just defined a different one.

Comment on lines +462 to +468
// Deliberately NOT named companionHeatPumpCoil: the base class's own EIRPlantLoopHeatPump::companionHeatPumpCoil
// must stay null for HeatPumpAirToWater objects, because EIRPlantLoopHeatPump::sizeLoadSide() (and other base
// sizing methods) branch on it being non-null to size off a companion coil using logic that was written for,
// and only checks for, the plain PlantLoopHeatPump:EIR:Heating/Cooling pair (DataPlant::PlantEquipmentType::
// HeatPumpEIRHeating/Cooling), not HeatPumpAirToWater. This member is used instead by
// HeatPumpAirToWater::pairUpCompanionCoils() and HeatPumpAirToWater::calcOpMode().
HeatPumpAirToWater *companionAWHPCoil = nullptr;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is a hard bug. Here I'm voluntarily restoring the behavior to avoid a diff.

But there's a problem in there.

Needs further investigation (separate, pre-existing issue, not caused by this branch).

HeatPumpAirToWater::sizeLoadSide() is not virtual, and its only would-be caller (EIRPlantLoopHeatPump::onInitLoopEquip) invokes this->sizeLoadSide(state) from within the base class's own scope, so that call always statically resolves to EIRPlantLoopHeatPump::sizeLoadSide,
never the derived override.
Confirmed no production or test code calls sizeLoadSide() through a HeatPumpAirToWater*-typed pointer either, so HeatPumpAirToWater::sizeLoadSide() (and its referenceCapacityOneUnit
recompute) is effictively dead code today. Left a TODO comment at the definition;

This likely needs a real fix (e.g. making sizeLoadSide virtual, or overriding onInitLoopEquip in HeatPumpAirToWater) but that's a behavior (and diff-producing) change out of scope for this PR.

@jmarrec jmarrec Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +2840 to 2848
// TODO: sizeLoadSide() is not virtual, and the only production call site (EIRPlantLoopHeatPump::onInitLoopEquip,
// via `this->sizeLoadSide(state);`) is compiled in the base class's own scope, so it always statically resolves to
// EIRPlantLoopHeatPump::sizeLoadSide. This override is therefore unreachable dead code today; the
// referenceCapacityOneUnit recompute below never runs. Pre-existing issue, unrelated to the Wshadow-field cleanup.
void HeatPumpAirToWater::sizeLoadSide(EnergyPlusData &state)
{
EIRPlantLoopHeatPump::sizeLoadSide(state);
this->referenceCapacityOneUnit = this->referenceCapacity / this->heatPumpMultiplier;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This code is effectively dead currently, which I suppose isn't the intent given this function does post-calculations...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

if (this->companionHeatPumpCoil != nullptr) {

In EIRPlantLoopHeatPump::sizeLoadSide, the companionHeatingCoil was ALWAYS nullptr for HeatPumpAirToWater (and it is still, but it's more explicit now).

HeatPumpAirToWater would initialize its own shadowing copy of companionHeatPumpCoil and leave the base one unitialized.

And it's the Base method that's called so in there companionHeatPumpCoil is definitely the Base's, not the Derived

I have a not so MCVE at https://compiler-explorer.com/z/3vYjEj1oY that shows it, and a more MCVE (less complete) at https://gcc.godbolt.org/z/YrMY9P3q8

Real64 Temperature_PrevIteration = 0.0; // C
Real64 Temperature_PrevTimeStep = 0.0; // C
Real64 Beta = 0.0; // K/W
BaseThermalPropertySet Properties;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed BaseThermalPropertySet Properties; from BaseCell, and instead gave each of its three derived structs its own appropriately-typed Properties member directly:

  • RadialCellInformationBaseThermalPropertySet Properties; (new, explicit)
  • CartesianCellBaseThermalPropertySet Properties; (new, explicit)
  • FluidCellInformation → kept its existing ExtendedFluidProperties Properties; (unchanged)

Why: FluidCellInformation was redeclaring Properties with the wider ExtendedFluidProperties type (adds Viscosity/Prandtl) to shadow the inherited BaseThermalPropertySet Properties from BaseCell — needed so that bulk-assignments like cell.PipeCellData.Fluid.Properties = thisCircuit->CurFluidPropertySet; copy the full extended struct instead of object-slicing it. This triggered a -Wshadow-field warning, and — since C++ field-hiding isn't virtual dispatch — meant every FluidCellInformation instance carried a second, entirely dead BaseThermalPropertySet subobject inherited from BaseCell that was never read or written.

Since BaseCell itself is never instantiated or referenced directly (only used as a base for these three structs), moving Properties down into each derived struct removes the shadowing entirely and eliminates the wasted subobject, with no behavior change — RadialCellInformation and CartesianCell still get the same BaseThermalPropertySet Properties they had before, just declared locally instead of inherited

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Defect Includes code to repair a defect in EnergyPlus Developer Issue Related to cmake, packaging, installers, or developer tooling (CI, etc)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable Wshadow-field and investigate actual bugs it finds

2 participants