From 74103ec4c00d8915efb3130f5ecf34d876273497 Mon Sep 17 00:00:00 2001 From: Brian Han Date: Mon, 13 Jul 2026 15:36:43 -0700 Subject: [PATCH 1/5] Enable -Werror for all dane jobs --- .gitlab/build_dane.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.gitlab/build_dane.yml b/.gitlab/build_dane.yml index bb9e41dcba..a660c8b997 100644 --- a/.gitlab/build_dane.yml +++ b/.gitlab/build_dane.yml @@ -37,34 +37,35 @@ #### # PR Build jobs -dane-llvm_19_1_3-werror-debug-src: +dane-llvm_19_1_3-debug-werror-src: variables: COMPILER: "llvm@19.1.3" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" EXTRA_CMAKE_OPTIONS: "-DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane -dane-llvm_19_1_3-release-src: +dane-llvm_19_1_3-release-werror-src: variables: COMPILER: "llvm@19.1.3" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" BUILD_TYPE: "Release" - EXTRA_CMAKE_OPTIONS: "-DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON" + EXTRA_CMAKE_OPTIONS: "-DAXOM_QUEST_ENABLE_EXTRA_REGRESSION_TESTS:BOOL=ON -DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane -dane-gcc_13_3_1-werror-src: +dane-gcc_13_3_1-release-werror-src: variables: COMPILER: "gcc@13.3.1" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" + BUILD_TYPE: "Release" EXTRA_CMAKE_OPTIONS: "-DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane -dane-sanitizers-gcc_13_3_1-src: +dane-sanitizers-gcc_13_3_1-debug-werror-src: variables: COMPILER: "gcc@13.3.1" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" LSAN_OPTIONS: suppressions=${CI_PROJECT_DIR}/suppressions.asan - EXTRA_CMAKE_OPTIONS: "-DAXOM_ENABLE_ASAN=ON -DAXOM_ENABLE_UBSAN=ON" + EXTRA_CMAKE_OPTIONS: "-DAXOM_ENABLE_ASAN=ON -DAXOM_ENABLE_UBSAN=ON -DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane # TODO: turn back on From bce12940b4c8b4de516634160f4da8e4c5580fcb Mon Sep 17 00:00:00 2001 From: Brian Han Date: Tue, 14 Jul 2026 14:53:20 -0700 Subject: [PATCH 2/5] Changes for release -Werror --- src/axom/bump/tests/bump_views.cpp | 37 ++- .../mint/execution/internal/for_all_cells.hpp | 164 +++++++---- .../mint/execution/internal/for_all_faces.hpp | 276 +++++++++++------- src/axom/mint/execution/internal/helpers.hpp | 8 +- src/axom/mint/mesh/Mesh.hpp | 16 +- src/axom/quest/PointInCell.hpp | 25 +- src/axom/quest/detail/MeshTester_detail.hpp | 2 +- .../detail/PointInCellMeshWrapper_mfem.hpp | 17 +- .../quest/examples/quest_bvh_two_pass.cpp | 7 +- src/axom/slam/tests/slam_make_helpers.cpp | 6 +- src/axom/spin/tests/spin_bvh.cpp | 4 +- 11 files changed, 355 insertions(+), 207 deletions(-) diff --git a/src/axom/bump/tests/bump_views.cpp b/src/axom/bump/tests/bump_views.cpp index 491691e866..8c3267745f 100644 --- a/src/axom/bump/tests/bump_views.cpp +++ b/src/axom/bump/tests/bump_views.cpp @@ -790,11 +790,27 @@ struct test_braid2d_mat eq_count += (end == end2) ? 1 : 0; count++; - // Make sure the iterator order is the same as for the values we got from zoneMaterials(). + // Test ArrayView version of zoneMaterials(). + using IndexType = typename MatsetView::IndexType; + using FloatType = typename MatsetView::FloatType; + constexpr int ARRAY_SIZE = 10; + IndexType idStorage[ARRAY_SIZE] = {}; + FloatType vfStorage[ARRAY_SIZE] = {}; + axom::ArrayView idView(idStorage, ARRAY_SIZE); + axom::ArrayView vfView(vfStorage, ARRAY_SIZE); + const auto nmats = deviceViews.matsetView.zoneMaterials(index, idView, vfView); + eq_count += (nmats == ids.size()) ? 1 : 0; + count++; + + // GCC 13 release+werror reports false -Wmaybe-uninitialized diagnostics when we index the + // StaticArray-backed ids/vfs scratch lists directly after zoneMaterials(). Use the + // zero-initialized ArrayView overload as the comparison source so the test still checks + // iterator/value consistency without depending on those backing slots. int i = 0; for(auto it = deviceViews.matsetView.beginZone(index); it != end; it++, i++) { - eq_count += (vfs[i] == it.volume_fraction() && ids[i] == it.material_id()) ? 1 : 0; + eq_count += + (i < nmats && vfView[i] == it.volume_fraction() && idView[i] == it.material_id()) ? 1 : 0; count++; } @@ -812,23 +828,6 @@ struct test_braid2d_mat } } - // Test ArrayView version of zoneMaterials(). - using IndexType = typename MatsetView::IndexType; - using FloatType = typename MatsetView::FloatType; - constexpr int ARRAY_SIZE = 10; - IndexType idStorage[ARRAY_SIZE]; - FloatType vfStorage[ARRAY_SIZE]; - axom::ArrayView idView(idStorage, ARRAY_SIZE); - axom::ArrayView vfView(vfStorage, ARRAY_SIZE); - const auto nmats = deviceViews.matsetView.zoneMaterials(index, idView, vfView); - eq_count += (nmats == ids.size()) ? 1 : 0; - count++; - for(axom::IndexType j = 0; j < nmats; j++) - { - eq_count += (vfs[j] == vfView[j] && ids[j] == idView[j]) ? 1 : 0; - count++; - } - resultsView[index] = (eq_count == count) ? 1 : 0; }); diff --git a/src/axom/mint/execution/internal/for_all_cells.hpp b/src/axom/mint/execution/internal/for_all_cells.hpp index 869d3f118c..4cd7635933 100644 --- a/src/axom/mint/execution/internal/for_all_cells.hpp +++ b/src/axom/mint/execution/internal/for_all_cells.hpp @@ -33,6 +33,11 @@ namespace mint { namespace internal { +constexpr int STRUCTURED_CELL_NODES_1D = 2; +constexpr int STRUCTURED_CELL_NODES_2D = 4; +constexpr int STRUCTURED_CELL_NODES_3D = 8; +constexpr int STRUCTURED_MAX_CELL_NODES = STRUCTURED_CELL_NODES_3D; + //------------------------------------------------------------------------------ template inline void for_all_cells_impl(xargs::index, const Mesh& m, KernelType&& kernel) @@ -122,8 +127,9 @@ inline void for_all_cells_impl(xargs::nodeids, const StructuredMesh& m, KernelTy const IndexType nodeKp = m.nodeKp(); const StackArray& offsets = m.getCellNodeOffsetsArray(); - // Note: gcc@10.3.1 emits a '-Warray-bounds' warning in callers of this function - // about the sizes of nodeIds and coords not matching due to the runtime switch on dimension + // GCC 13 release+werror still instantiates inactive structured-dimension branches in callers of + // xargs::nodeids. Keep the scratch connectivity arrays at the structured 3D maximum so those + // compile-time paths never expose undersized local buffers to fixed-shape 2D/3D kernels. if(dimension == 1) { @@ -131,7 +137,9 @@ inline void for_all_cells_impl(xargs::nodeids, const StructuredMesh& m, KernelTy xargs::index(), m, AXOM_LAMBDA(IndexType cellID) { - IndexType cell_connectivity[2] = {cellID, cellID + 1}; + IndexType cell_connectivity[STRUCTURED_MAX_CELL_NODES] = {0}; + cell_connectivity[0] = cellID; + cell_connectivity[1] = cellID + 1; kernel(cellID, cell_connectivity, 2); }); } @@ -142,7 +150,7 @@ inline void for_all_cells_impl(xargs::nodeids, const StructuredMesh& m, KernelTy m, AXOM_LAMBDA(IndexType cellID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - IndexType cell_connectivity[4]; + IndexType cell_connectivity[STRUCTURED_MAX_CELL_NODES] = {0}; for(int ii = 0; ii < 4; ++ii) { @@ -161,7 +169,7 @@ inline void for_all_cells_impl(xargs::nodeids, const StructuredMesh& m, KernelTy m, AXOM_LAMBDA(IndexType cellID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - IndexType cell_connectivity[8]; + IndexType cell_connectivity[STRUCTURED_MAX_CELL_NODES] = {0}; for(int ii = 0; ii < 8; ++ii) { @@ -421,8 +429,9 @@ inline void for_all_cells_impl(xargs::coords, const UniformMesh& m, KernelType&& const double z0 = origin[2]; const double dz = spacing[2]; - // Note: gcc@10.3.1 emits a '-Warray-bounds' warning in callers of this function - // about the sizes of nodeIds and coords not matching due to the runtime switch on dimension + // GCC 13 release+werror still instantiates inactive structured-dimension branches in callers of + // xargs::coords. Use the structured 3D maximum for zero-initialized scratch buffers so fixed- + // shape 2D/3D kernels do not see undersized local storage when inactive branches are compiled. if(dimension == 1) { @@ -430,8 +439,12 @@ inline void for_all_cells_impl(xargs::coords, const UniformMesh& m, KernelType&& xargs::index(), m, AXOM_LAMBDA(IndexType cellID) { - const IndexType nodeIDs[2] = {cellID, cellID + 1}; - double coords[2] = {x0 + nodeIDs[0] * dx, x0 + nodeIDs[1] * dx}; + IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; + nodeIDs[0] = cellID; + nodeIDs[1] = cellID + 1; + double coords[3 * STRUCTURED_MAX_CELL_NODES] = {0.}; + coords[0] = x0 + nodeIDs[0] * dx; + coords[1] = x0 + nodeIDs[1] * dx; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(cellID, coordsMatrix, nodeIDs); @@ -444,16 +457,21 @@ inline void for_all_cells_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType cellID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - const IndexType nodeIDs[4] = {n0, n0 + 1, n0 + 1 + nodeJp, n0 + nodeJp}; - - double coords[8] = {x0 + i * dx, - y0 + j * dy, - x0 + (i + 1) * dx, - y0 + j * dy, - x0 + (i + 1) * dx, - y0 + (j + 1) * dy, - x0 + i * dx, - y0 + (j + 1) * dy}; + IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeJp; + nodeIDs[3] = n0 + nodeJp; + + double coords[3 * STRUCTURED_MAX_CELL_NODES] = {0.}; + coords[0] = x0 + i * dx; + coords[1] = y0 + j * dy; + coords[2] = x0 + (i + 1) * dx; + coords[3] = y0 + j * dy; + coords[4] = x0 + (i + 1) * dx; + coords[5] = y0 + (j + 1) * dy; + coords[6] = x0 + i * dx; + coords[7] = y0 + (j + 1) * dy; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(cellID, coordsMatrix, nodeIDs); @@ -467,16 +485,17 @@ inline void for_all_cells_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType cellID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[8] = {n0, - n0 + 1, - n0 + 1 + nodeJp, - n0 + nodeJp, - n0 + nodeKp, - n0 + 1 + nodeKp, - n0 + 1 + nodeJp + nodeKp, - n0 + nodeJp + nodeKp}; - - double coords[24] = { + IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeJp; + nodeIDs[3] = n0 + nodeJp; + nodeIDs[4] = n0 + nodeKp; + nodeIDs[5] = n0 + 1 + nodeKp; + nodeIDs[6] = n0 + 1 + nodeJp + nodeKp; + nodeIDs[7] = n0 + nodeJp + nodeKp; + + double coords[3 * STRUCTURED_MAX_CELL_NODES] = { x0 + i * dx, y0 + j * dy, z0 + k * dz, x0 + (i + 1) * dx, y0 + j * dy, z0 + k * dz, x0 + (i + 1) * dx, y0 + (j + 1) * dy, z0 + k * dz, x0 + i * dx, y0 + (j + 1) * dy, z0 + k * dz, @@ -518,8 +537,14 @@ inline void for_all_cells_impl(xargs::coords, const RectilinearMesh& m, KernelTy xargs::index(), m, AXOM_LAMBDA(IndexType cellID) { - const IndexType nodeIDs[2] = {cellID, cellID + 1}; - double coords[2] = {x_vals_view[nodeIDs[0]], x_vals_view[nodeIDs[1]]}; + IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; + nodeIDs[0] = cellID; + nodeIDs[1] = cellID + 1; + // GCC 13 release+werror reports false -Warray-bounds in inactive fixed-2D/3D callers when + // this 1D rectilinear branch uses exact-size buffers. Keep the backing storage max-sized. + double coords[3 * STRUCTURED_MAX_CELL_NODES] = {0.}; + coords[0] = x_vals_view[nodeIDs[0]]; + coords[1] = x_vals_view[nodeIDs[1]]; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(cellID, coordsMatrix, nodeIDs); @@ -541,16 +566,21 @@ inline void for_all_cells_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType cellID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - const IndexType nodeIDs[4] = {n0, n0 + 1, n0 + 1 + nodeJp, n0 + nodeJp}; - - double coords[8] = {x_vals_view[i], - y_vals_view[j], - x_vals_view[i + 1], - y_vals_view[j], - x_vals_view[i + 1], - y_vals_view[j + 1], - x_vals_view[i], - y_vals_view[j + 1]}; + IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeJp; + nodeIDs[3] = n0 + nodeJp; + + double coords[3 * STRUCTURED_MAX_CELL_NODES] = {0.}; + coords[0] = x_vals_view[i]; + coords[1] = y_vals_view[j]; + coords[2] = x_vals_view[i + 1]; + coords[3] = y_vals_view[j]; + coords[4] = x_vals_view[i + 1]; + coords[5] = y_vals_view[j + 1]; + coords[6] = x_vals_view[i]; + coords[7] = y_vals_view[j + 1]; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(cellID, coordsMatrix, nodeIDs); @@ -580,16 +610,17 @@ inline void for_all_cells_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType cellID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[8] = {n0, - n0 + 1, - n0 + 1 + nodeJp, - n0 + nodeJp, - n0 + nodeKp, - n0 + 1 + nodeKp, - n0 + 1 + nodeJp + nodeKp, - n0 + nodeJp + nodeKp}; - - double coords[24] = { + IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeJp; + nodeIDs[3] = n0 + nodeJp; + nodeIDs[4] = n0 + nodeKp; + nodeIDs[5] = n0 + 1 + nodeKp; + nodeIDs[6] = n0 + 1 + nodeJp + nodeKp; + nodeIDs[7] = n0 + nodeJp + nodeKp; + + double coords[3 * STRUCTURED_MAX_CELL_NODES] = { x_vals_view[i], y_vals_view[j], z_vals_view[k], x_vals_view[i + 1], y_vals_view[j], z_vals_view[k], x_vals_view[i + 1], y_vals_view[j + 1], z_vals_view[k], x_vals_view[i], y_vals_view[j + 1], z_vals_view[k], @@ -625,21 +656,24 @@ inline void for_all_cells_impl(xargs::coords, const CurvilinearMesh& m, KernelTy const int dimension = m.getDimension(); if(dimension == 1) { - for_all_coords(for_all_cell_nodes_functor(), - m, - std::forward(kernel)); + for_all_coords( + for_all_cell_nodes_functor(), + m, + std::forward(kernel)); } else if(dimension == 2) { - for_all_coords(for_all_cell_nodes_functor(), - m, - std::forward(kernel)); + for_all_coords( + for_all_cell_nodes_functor(), + m, + std::forward(kernel)); } else { - for_all_coords(for_all_cell_nodes_functor(), - m, - std::forward(kernel)); + for_all_coords( + for_all_cell_nodes_functor(), + m, + std::forward(kernel)); } } @@ -669,7 +703,11 @@ inline void for_all_cells_impl(xargs::coords, const UnstructuredMesh& m, K xargs::nodeids(), m, AXOM_LAMBDA(IndexType cellID, const IndexType* nodeIDs, IndexType AXOM_UNUSED_PARAM(numNodes)) { - double coords[2] = {x_vals_view[nodeIDs[0]], x_vals_view[nodeIDs[1]]}; + // GCC 13 release+werror reports false -Warray-bounds when inactive 2D/3D callers are + // compiled against this 1D unstructured branch. Use a max-sized backing array instead. + double coords[3 * MAX_CELL_NODES] = {0.}; + coords[0] = x_vals_view[nodeIDs[0]]; + coords[1] = x_vals_view[nodeIDs[1]]; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(cellID, coordsMatrix, nodeIDs); @@ -690,7 +728,7 @@ inline void for_all_cells_impl(xargs::coords, const UnstructuredMesh& m, K xargs::nodeids(), m, AXOM_LAMBDA(IndexType cellID, const IndexType* nodeIDs, IndexType numNodes) { - double coords[2 * MAX_CELL_NODES]; + double coords[3 * MAX_CELL_NODES] = {0.}; for(int i = 0; i < numNodes; ++i) { const IndexType nodeID = nodeIDs[i]; @@ -725,7 +763,7 @@ inline void for_all_cells_impl(xargs::coords, const UnstructuredMesh& m, K xargs::nodeids(), m, AXOM_LAMBDA(IndexType cellID, const IndexType* nodeIDs, IndexType numNodes) { - double coords[3 * MAX_CELL_NODES]; + double coords[3 * MAX_CELL_NODES] = {0.}; for(int i = 0; i < numNodes; ++i) { const IndexType nodeID = nodeIDs[i]; diff --git a/src/axom/mint/execution/internal/for_all_faces.hpp b/src/axom/mint/execution/internal/for_all_faces.hpp index c24963e73e..65de619fd2 100644 --- a/src/axom/mint/execution/internal/for_all_faces.hpp +++ b/src/axom/mint/execution/internal/for_all_faces.hpp @@ -30,6 +30,10 @@ namespace mint { namespace internal { +constexpr int STRUCTURED_FACE_NODES_2D = 2; +constexpr int STRUCTURED_FACE_NODES_3D = 4; +constexpr int STRUCTURED_MAX_FACE_NODES = STRUCTURED_FACE_NODES_3D; + namespace helpers { //------------------------------------------------------------------------------ @@ -173,6 +177,9 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy const IndexType* offsets = m.getCellNodeOffsetsArray(); const IndexType cellNodeOffset3 = offsets[3]; + // Keep these scratch arrays at the structured 3D maximum so inactive branches share one + // consistent local buffer shape across 2D and 3D structured traversals. + if(dimension == 2) { const IndexType numIFaces = m.getTotalNumFaces(I_DIRECTION); @@ -181,7 +188,7 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy xargs::ij(), m, AXOM_LAMBDA(IndexType faceID, IndexType AXOM_UNUSED_PARAM(i), IndexType AXOM_UNUSED_PARAM(j)) { - IndexType nodes[2]; + IndexType nodes[STRUCTURED_MAX_FACE_NODES] = {0}; nodes[0] = faceID; nodes[1] = nodes[0] + cellNodeOffset3; kernel(faceID, nodes, 2); @@ -192,7 +199,7 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType AXOM_UNUSED_PARAM(i), IndexType j) { const IndexType shiftedID = faceID - numIFaces; - IndexType nodes[2]; + IndexType nodes[STRUCTURED_MAX_FACE_NODES] = {0}; nodes[0] = shiftedID + j; nodes[1] = nodes[0] + 1; kernel(faceID, nodes, 2); @@ -221,7 +228,7 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy IndexType AXOM_UNUSED_PARAM(i), IndexType AXOM_UNUSED_PARAM(j), IndexType k) { - IndexType nodes[4]; + IndexType nodes[STRUCTURED_MAX_FACE_NODES] = {0}; nodes[0] = faceID + k * INodeResolution; nodes[1] = nodes[0] + cellNodeOffset4; nodes[2] = nodes[0] + cellNodeOffset7; @@ -234,7 +241,7 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType AXOM_UNUSED_PARAM(i), IndexType j, IndexType k) { const IndexType shiftedID = faceID - numIFaces; - IndexType nodes[4]; + IndexType nodes[STRUCTURED_MAX_FACE_NODES] = {0}; nodes[0] = shiftedID + j + k * JNodeResolution; nodes[1] = nodes[0] + 1; nodes[2] = nodes[0] + cellNodeOffset5; @@ -247,7 +254,7 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType AXOM_UNUSED_PARAM(i), IndexType j, IndexType k) { const IndexType shiftedID = faceID - numIJFaces; - IndexType nodes[4]; + IndexType nodes[STRUCTURED_MAX_FACE_NODES] = {0}; nodes[0] = shiftedID + j + k * KFaceNodeStride; nodes[1] = nodes[0] + 1; nodes[2] = nodes[0] + cellNodeOffset2; @@ -541,6 +548,9 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& const double z0 = origin[2]; const double dz = spacing[2]; + // Back each Matrix with the structured 3D maximum so all structured face branches share one + // consistent local buffer layout. + if(dimension == 2) { helpers::for_all_I_faces( @@ -548,9 +558,15 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - const IndexType nodeIDs[2] = {n0, n0 + nodeJp}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + nodeJp; - double coords[4] = {x0 + i * dx, y0 + j * dy, x0 + i * dx, y0 + (j + 1) * dy}; + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x0 + i * dx; + coords[1] = y0 + j * dy; + coords[2] = x0 + i * dx; + coords[3] = y0 + (j + 1) * dy; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -561,9 +577,15 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - const IndexType nodeIDs[2] = {n0, n0 + 1}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; - double coords[4] = {x0 + i * dx, y0 + j * dy, x0 + (i + 1) * dx, y0 + j * dy}; + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x0 + i * dx; + coords[1] = y0 + j * dy; + coords[2] = x0 + (i + 1) * dx; + coords[3] = y0 + j * dy; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -576,20 +598,25 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[4] = {n0, n0 + nodeKp, n0 + nodeJp + nodeKp, n0 + nodeJp}; - - double coords[12] = {x0 + i * dx, - y0 + j * dy, - z0 + k * dz, - x0 + i * dx, - y0 + j * dy, - z0 + (k + 1) * dz, - x0 + i * dx, - y0 + (j + 1) * dy, - z0 + (k + 1) * dz, - x0 + i * dx, - y0 + (j + 1) * dy, - z0 + k * dz}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + nodeKp; + nodeIDs[2] = n0 + nodeJp + nodeKp; + nodeIDs[3] = n0 + nodeJp; + + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x0 + i * dx; + coords[1] = y0 + j * dy; + coords[2] = z0 + k * dz; + coords[3] = x0 + i * dx; + coords[4] = y0 + j * dy; + coords[5] = z0 + (k + 1) * dz; + coords[6] = x0 + i * dx; + coords[7] = y0 + (j + 1) * dy; + coords[8] = z0 + (k + 1) * dz; + coords[9] = x0 + i * dx; + coords[10] = y0 + (j + 1) * dy; + coords[11] = z0 + k * dz; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -600,20 +627,25 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[4] = {n0, n0 + 1, n0 + 1 + nodeKp, n0 + nodeKp}; - - double coords[12] = {x0 + i * dx, - y0 + j * dy, - z0 + k * dz, - x0 + (i + 1) * dx, - y0 + j * dy, - z0 + k * dz, - x0 + (i + 1) * dx, - y0 + j * dy, - z0 + (k + 1) * dz, - x0 + i * dx, - y0 + j * dy, - z0 + (k + 1) * dz}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeKp; + nodeIDs[3] = n0 + nodeKp; + + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x0 + i * dx; + coords[1] = y0 + j * dy; + coords[2] = z0 + k * dz; + coords[3] = x0 + (i + 1) * dx; + coords[4] = y0 + j * dy; + coords[5] = z0 + k * dz; + coords[6] = x0 + (i + 1) * dx; + coords[7] = y0 + j * dy; + coords[8] = z0 + (k + 1) * dz; + coords[9] = x0 + i * dx; + coords[10] = y0 + j * dy; + coords[11] = z0 + (k + 1) * dz; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -624,20 +656,25 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[4] = {n0, n0 + 1, n0 + 1 + nodeJp, n0 + nodeJp}; - - double coords[12] = {x0 + i * dx, - y0 + j * dy, - z0 + k * dz, - x0 + (i + 1) * dx, - y0 + j * dy, - z0 + k * dz, - x0 + (i + 1) * dx, - y0 + (j + 1) * dy, - z0 + k * dz, - x0 + i * dx, - y0 + (j + 1) * dy, - z0 + k * dz}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeJp; + nodeIDs[3] = n0 + nodeJp; + + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x0 + i * dx; + coords[1] = y0 + j * dy; + coords[2] = z0 + k * dz; + coords[3] = x0 + (i + 1) * dx; + coords[4] = y0 + j * dy; + coords[5] = z0 + k * dz; + coords[6] = x0 + (i + 1) * dx; + coords[7] = y0 + (j + 1) * dy; + coords[8] = z0 + k * dz; + coords[9] = x0 + i * dx; + coords[10] = y0 + (j + 1) * dy; + coords[11] = z0 + k * dz; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -681,9 +718,15 @@ inline void for_all_faces_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - const IndexType nodeIDs[2] = {n0, n0 + nodeJp}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + nodeJp; - double coords[4] = {x_vals_view[i], y_vals_view[j], x_vals_view[i], y_vals_view[j + 1]}; + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x_vals_view[i]; + coords[1] = y_vals_view[j]; + coords[2] = x_vals_view[i]; + coords[3] = y_vals_view[j + 1]; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -694,9 +737,15 @@ inline void for_all_faces_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j) { const IndexType n0 = i + j * nodeJp; - const IndexType nodeIDs[2] = {n0, n0 + 1}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; - double coords[4] = {x_vals_view[i], y_vals_view[j], x_vals_view[i + 1], y_vals_view[j]}; + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x_vals_view[i]; + coords[1] = y_vals_view[j]; + coords[2] = x_vals_view[i + 1]; + coords[3] = y_vals_view[j]; numerics::Matrix coordsMatrix(dimension, 2, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -718,20 +767,25 @@ inline void for_all_faces_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[4] = {n0, n0 + nodeKp, n0 + nodeJp + nodeKp, n0 + nodeJp}; - - double coords[12] = {x_vals_view[i], - y_vals_view[j], - z_vals_view[k], - x_vals_view[i], - y_vals_view[j], - z_vals_view[k + 1], - x_vals_view[i], - y_vals_view[j + 1], - z_vals_view[k + 1], - x_vals_view[i], - y_vals_view[j + 1], - z_vals_view[k]}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + nodeKp; + nodeIDs[2] = n0 + nodeJp + nodeKp; + nodeIDs[3] = n0 + nodeJp; + + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x_vals_view[i]; + coords[1] = y_vals_view[j]; + coords[2] = z_vals_view[k]; + coords[3] = x_vals_view[i]; + coords[4] = y_vals_view[j]; + coords[5] = z_vals_view[k + 1]; + coords[6] = x_vals_view[i]; + coords[7] = y_vals_view[j + 1]; + coords[8] = z_vals_view[k + 1]; + coords[9] = x_vals_view[i]; + coords[10] = y_vals_view[j + 1]; + coords[11] = z_vals_view[k]; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -742,20 +796,25 @@ inline void for_all_faces_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[4] = {n0, n0 + 1, n0 + 1 + nodeKp, n0 + nodeKp}; - - double coords[12] = {x_vals_view[i], - y_vals_view[j], - z_vals_view[k], - x_vals_view[i + 1], - y_vals_view[j], - z_vals_view[k], - x_vals_view[i + 1], - y_vals_view[j], - z_vals_view[k + 1], - x_vals_view[i], - y_vals_view[j], - z_vals_view[k + 1]}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeKp; + nodeIDs[3] = n0 + nodeKp; + + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x_vals_view[i]; + coords[1] = y_vals_view[j]; + coords[2] = z_vals_view[k]; + coords[3] = x_vals_view[i + 1]; + coords[4] = y_vals_view[j]; + coords[5] = z_vals_view[k]; + coords[6] = x_vals_view[i + 1]; + coords[7] = y_vals_view[j]; + coords[8] = z_vals_view[k + 1]; + coords[9] = x_vals_view[i]; + coords[10] = y_vals_view[j]; + coords[11] = z_vals_view[k + 1]; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -766,20 +825,25 @@ inline void for_all_faces_impl(xargs::coords, const RectilinearMesh& m, KernelTy m, AXOM_LAMBDA(IndexType faceID, IndexType i, IndexType j, IndexType k) { const IndexType n0 = i + j * nodeJp + k * nodeKp; - const IndexType nodeIDs[4] = {n0, n0 + 1, n0 + 1 + nodeJp, n0 + nodeJp}; - - double coords[12] = {x_vals_view[i], - y_vals_view[j], - z_vals_view[k], - x_vals_view[i + 1], - y_vals_view[j], - z_vals_view[k], - x_vals_view[i + 1], - y_vals_view[j + 1], - z_vals_view[k], - x_vals_view[i], - y_vals_view[j + 1], - z_vals_view[k]}; + IndexType nodeIDs[STRUCTURED_MAX_FACE_NODES] = {0}; + nodeIDs[0] = n0; + nodeIDs[1] = n0 + 1; + nodeIDs[2] = n0 + 1 + nodeJp; + nodeIDs[3] = n0 + nodeJp; + + double coords[3 * STRUCTURED_MAX_FACE_NODES] = {0.}; + coords[0] = x_vals_view[i]; + coords[1] = y_vals_view[j]; + coords[2] = z_vals_view[k]; + coords[3] = x_vals_view[i + 1]; + coords[4] = y_vals_view[j]; + coords[5] = z_vals_view[k]; + coords[6] = x_vals_view[i + 1]; + coords[7] = y_vals_view[j + 1]; + coords[8] = z_vals_view[k]; + coords[9] = x_vals_view[i]; + coords[10] = y_vals_view[j + 1]; + coords[11] = z_vals_view[k]; numerics::Matrix coordsMatrix(dimension, 4, coords, NO_COPY); kernel(faceID, coordsMatrix, nodeIDs); @@ -811,15 +875,17 @@ inline void for_all_faces_impl(xargs::coords, const CurvilinearMesh& m, KernelTy const int dimension = m.getDimension(); if(dimension == 2) { - for_all_coords(for_all_face_nodes_functor(), - m, - std::forward(kernel)); + for_all_coords( + for_all_face_nodes_functor(), + m, + std::forward(kernel)); } else { - for_all_coords(for_all_face_nodes_functor(), - m, - std::forward(kernel)); + for_all_coords( + for_all_face_nodes_functor(), + m, + std::forward(kernel)); } } @@ -856,7 +922,7 @@ inline void for_all_faces_impl(xargs::coords, const UnstructuredMesh& m, K xargs::nodeids(), m, AXOM_LAMBDA(IndexType faceID, const IndexType* nodeIDs, IndexType numNodes) { - double coords[2 * MAX_FACE_NODES]; + double coords[3 * MAX_FACE_NODES] = {0.}; for(int i = 0; i < numNodes; ++i) { const IndexType nodeID = nodeIDs[i]; @@ -883,7 +949,7 @@ inline void for_all_faces_impl(xargs::coords, const UnstructuredMesh& m, K xargs::nodeids(), m, AXOM_LAMBDA(IndexType faceID, const IndexType* nodeIDs, IndexType numNodes) { - double coords[3 * MAX_FACE_NODES]; + double coords[3 * MAX_FACE_NODES] = {0.}; for(int i = 0; i < numNodes; ++i) { const IndexType nodeID = nodeIDs[i]; diff --git a/src/axom/mint/execution/internal/helpers.hpp b/src/axom/mint/execution/internal/helpers.hpp index af65d10b04..20179ca7c0 100644 --- a/src/axom/mint/execution/internal/helpers.hpp +++ b/src/axom/mint/execution/internal/helpers.hpp @@ -40,7 +40,7 @@ namespace internal * */ -template +template inline void for_all_coords(const FOR_ALL_FUNCTOR& for_all_nodes, const MeshType& m, KernelType&& kernel) { SLIC_ERROR_IF(m.getMeshType() == STRUCTURED_UNIFORM_MESH, "Not valid for UniformMesh."); @@ -48,6 +48,7 @@ inline void for_all_coords(const FOR_ALL_FUNCTOR& for_all_nodes, const MeshType& AXOM_STATIC_ASSERT_MSG(NDIM >= 1 && NDIM <= 3, "NDIM must be a valid dimension."); AXOM_STATIC_ASSERT_MSG(NNODES > 0, "NNODES must be greater than zero."); + AXOM_STATIC_ASSERT_MSG(MAX_NODES >= NNODES, "MAX_NODES must cover the active node count."); constexpr bool valid_mesh_type = std::is_base_of::value; AXOM_STATIC_ASSERT(valid_mesh_type); @@ -88,7 +89,10 @@ inline void for_all_coords(const FOR_ALL_FUNCTOR& for_all_nodes, const MeshType& AXOM_UNUSED_VAR(numNodes); assert(numNodes == NNODES); - double localCoords[NDIM * NNODES]; + // GCC 13 release+werror can still instantiate inactive dimension/node-count paths in callers + // of xargs::coords. Back the Matrix with a zero-initialized max-sized buffer so those + // compile-time-only paths never reference storage smaller than the active 2D/3D caller expects. + double localCoords[3 * MAX_NODES] = {0.}; for(int i = 0; i < NNODES; ++i) { const int i_offset = NDIM * i; diff --git a/src/axom/mint/mesh/Mesh.hpp b/src/axom/mint/mesh/Mesh.hpp index edb2cb7e07..be914faa3e 100644 --- a/src/axom/mint/mesh/Mesh.hpp +++ b/src/axom/mint/mesh/Mesh.hpp @@ -857,14 +857,22 @@ inline bool Mesh::hasSidreGroup() const //------------------------------------------------------------------------------ inline const FieldData* Mesh::getFieldData(int association) const { - SLIC_ERROR_IF(association < 0 || association >= NUM_FIELD_ASSOCIATIONS, - "invalid field association [" << association << "]"); - SLIC_ERROR_IF(m_mesh_fields[association] == nullptr, + if(association < 0 || association >= NUM_FIELD_ASSOCIATIONS) + { + SLIC_ERROR("invalid field association [" << association << "]"); + return nullptr; + } + + // GCC 13 release+werror reports -Warray-bounds on m_mesh_fields[association] when the index is + // checked only inside SLIC_ERROR_IF(). Validate the range first, then load the field pointer + // through a local so the later null check cannot be misread as an out-of-bounds access. + const FieldData* field_data = m_mesh_fields[association]; + SLIC_ERROR_IF(field_data == nullptr, "null field data object w/association [" << association << "]"); SLIC_ERROR_IF(m_type == PARTICLE_MESH && association != NODE_CENTERED, "a particle mesh may only store node-centered fields"); - return m_mesh_fields[association]; + return field_data; } //------------------------------------------------------------------------------ diff --git a/src/axom/quest/PointInCell.hpp b/src/axom/quest/PointInCell.hpp index 5023596c7f..65847ff66f 100644 --- a/src/axom/quest/PointInCell.hpp +++ b/src/axom/quest/PointInCell.hpp @@ -189,21 +189,40 @@ class PointInCell { SLIC_ASSERT(pos != nullptr); + const int dim = m_meshWrapper.meshDimension(); IndexType cellIndex = MeshTraits::NO_CELL; + double posBuffer[3] = {0., 0., 0.}; + double isoparBuffer[3] = {0., 0., 0.}; - switch(m_meshWrapper.meshDimension()) + // GCC 13 release+werror can inline the 3D PointFinder path into 2D MFEM call sites and then + // flag the caller's 2-entry point buffers as out-of-bounds. Stage raw coordinates through + // local 3-entry buffers before the dimension switch, then copy back only the active prefix. + for(int i = 0; i < dim; ++i) + { + posBuffer[i] = pos[i]; + } + + switch(dim) { case 2: - cellIndex = m_pointFinder2D->locatePoint(pos, isopar); + cellIndex = m_pointFinder2D->locatePoint(posBuffer, isopar != nullptr ? isoparBuffer : nullptr); break; case 3: - cellIndex = m_pointFinder3D->locatePoint(pos, isopar); + cellIndex = m_pointFinder3D->locatePoint(posBuffer, isopar != nullptr ? isoparBuffer : nullptr); break; default: SLIC_ERROR("Point in Cell query only defined for 2D or 3D meshes."); break; } + if(isopar != nullptr) + { + for(int i = 0; i < dim; ++i) + { + isopar[i] = isoparBuffer[i]; + } + } + return cellIndex; } diff --git a/src/axom/quest/detail/MeshTester_detail.hpp b/src/axom/quest/detail/MeshTester_detail.hpp index bcf7d93284..ca6c2a6578 100644 --- a/src/axom/quest/detail/MeshTester_detail.hpp +++ b/src/axom/quest/detail/MeshTester_detail.hpp @@ -182,7 +182,7 @@ void CandidateFinderBase::initialize() const double* node = coords.getColumn(inode); tri[inode] = PointType {node[mint::X_COORDINATE], node[mint::Y_COORDINATE], node[mint::Z_COORDINATE]}; - } // END for all cells nodes + } // END for all cell nodes v_degenerate[cellIdx] = (tri.degenerate() ? 1 : 0); diff --git a/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp b/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp index 4651f0e8fe..3c8c0c0973 100644 --- a/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp +++ b/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp @@ -290,7 +290,15 @@ class PointInCellMeshWrapper m_mesh->GetElementTransformation(eltIdx, &tr); mfem::IntegrationPoint ip; - ip.Set(isopar, dim); + // GCC 13 release+werror reports false -Warray-bounds diagnostics because MFEM's + // IntegrationPoint::Set/Get touch a 3-entry buffer even for 2D elements. Stage 2D + // isoparametric coordinates through a local 3-vector before copying the active prefix. + double mfemIsopar[3] = {0., 0., 0.}; + for(int i = 0; i < dim; ++i) + { + mfemIsopar[i] = isopar[i]; + } + ip.Set(mfemIsopar, dim); mfem::Vector v(pt, dim); tr.Transform(ip, v); @@ -328,7 +336,12 @@ class PointInCellMeshWrapper // Status codes: {0 -> successful; 1 -> outside elt; 2-> did not converge} int err = invTrans.Transform(ptSpace, ipRef); - ipRef.Get(isopar, dim); + double mfemIsopar[3] = {0., 0., 0.}; + ipRef.Get(mfemIsopar, dim); + for(int i = 0; i < dim; ++i) + { + isopar[i] = mfemIsopar[i]; + } return (err == 0); } diff --git a/src/axom/quest/examples/quest_bvh_two_pass.cpp b/src/axom/quest/examples/quest_bvh_two_pass.cpp index 00e973983c..94a4c2c082 100644 --- a/src/axom/quest/examples/quest_bvh_two_pass.cpp +++ b/src/axom/quest/examples/quest_bvh_two_pass.cpp @@ -121,10 +121,9 @@ void find_collisions_broadphase(const mint::Mesh* mesh, mesh, AXOM_LAMBDA(IndexType cellIdx, axom::numerics::Matrix & coords, const IndexType* nodeIds) { AXOM_UNUSED_VAR(nodeIds); - int numNodes = coords.getNumColumns(); BoxType aabb; - for(IndexType inode = 0; inode < numNodes; ++inode) + for(IndexType inode = 0; inode < 3; ++inode) { const double* node = coords.getColumn(inode); PointType vtx {node[mint::X_COORDINATE], node[mint::Y_COORDINATE], node[mint::Z_COORDINATE]}; @@ -262,9 +261,7 @@ void find_collisions_narrowphase(const mint::Mesh* mesh, AXOM_UNUSED_VAR(nodeIds); TriangleType tri; - int numNodes = coords.getNumColumns(); - SLIC_ASSERT(numNodes == 3); - for(IndexType inode = 0; inode < numNodes; ++inode) + for(IndexType inode = 0; inode < 3; ++inode) { const double* node = coords.getColumn(inode); PointType vtx {node[mint::X_COORDINATE], node[mint::Y_COORDINATE], node[mint::Z_COORDINATE]}; diff --git a/src/axom/slam/tests/slam_make_helpers.cpp b/src/axom/slam/tests/slam_make_helpers.cpp index fd45fe5626..a6e50bb89f 100644 --- a/src/axom/slam/tests/slam_make_helpers.cpp +++ b/src/axom/slam/tests/slam_make_helpers.cpp @@ -261,7 +261,11 @@ TEST(slam_make_helpers, make_constant_relation_rejects_undersized_indices) EXPECT_DEATH_IF_SUPPORTED(slam::make_constant_relation(&fromSet, &toSet, Pos {2}, indices, Pos {4}), ""); #else - SLIC_INFO("Skipped constant-relation size assertion check in release mode."); + // GCC 13 release+werror flags the malformed test buffer as unused because the debug-only + // construction assert compiles out. Build the relation anyway and check isValid() so the + // release path still exercises the undersized-indices failure instead of skipping the test. + auto rel = slam::make_constant_relation(&fromSet, &toSet, Pos {2}, indices, Pos {4}); + EXPECT_FALSE(rel.isValid()); #endif } diff --git a/src/axom/spin/tests/spin_bvh.cpp b/src/axom/spin/tests/spin_bvh.cpp index bb459c9bdf..f6ff6ea5f1 100644 --- a/src/axom/spin/tests/spin_bvh.cpp +++ b/src/axom/spin/tests/spin_bvh.cpp @@ -172,8 +172,8 @@ void generate_aabbs_and_centroids(const mint::Mesh* mesh, PointType coords; for(int dim = 0; dim < NDIMS; ++dim) { - coords[dim] = node[dim]; - sum[dim] += node[dim]; + coords[dim] = static_cast(node[dim]); + sum[dim] += coords[dim]; } range.addPoint(coords); From ab72f1978a398e8a6c7cf80bee04d20e9a4e1a82 Mon Sep 17 00:00:00 2001 From: Brian Han Date: Tue, 14 Jul 2026 15:44:42 -0700 Subject: [PATCH 3/5] Cleanup comments --- src/axom/bump/tests/bump_views.cpp | 6 ++---- src/axom/mint/execution/internal/for_all_cells.hpp | 12 ------------ src/axom/mint/execution/internal/for_all_faces.hpp | 6 ------ src/axom/mint/execution/internal/helpers.hpp | 3 --- src/axom/mint/mesh/Mesh.hpp | 3 --- src/axom/quest/PointInCell.hpp | 5 ++--- .../quest/detail/PointInCellMeshWrapper_mfem.hpp | 5 ++--- src/axom/slam/tests/slam_make_helpers.cpp | 5 ++--- 8 files changed, 8 insertions(+), 37 deletions(-) diff --git a/src/axom/bump/tests/bump_views.cpp b/src/axom/bump/tests/bump_views.cpp index 8c3267745f..2cdcb476cf 100644 --- a/src/axom/bump/tests/bump_views.cpp +++ b/src/axom/bump/tests/bump_views.cpp @@ -802,10 +802,8 @@ struct test_braid2d_mat eq_count += (nmats == ids.size()) ? 1 : 0; count++; - // GCC 13 release+werror reports false -Wmaybe-uninitialized diagnostics when we index the - // StaticArray-backed ids/vfs scratch lists directly after zoneMaterials(). Use the - // zero-initialized ArrayView overload as the comparison source so the test still checks - // iterator/value consistency without depending on those backing slots. + // Compare against the zero-initialized ArrayView results instead of the StaticArray + // backing storage after zoneMaterials() fills the active prefix. int i = 0; for(auto it = deviceViews.matsetView.beginZone(index); it != end; it++, i++) { diff --git a/src/axom/mint/execution/internal/for_all_cells.hpp b/src/axom/mint/execution/internal/for_all_cells.hpp index 4cd7635933..a0d1382169 100644 --- a/src/axom/mint/execution/internal/for_all_cells.hpp +++ b/src/axom/mint/execution/internal/for_all_cells.hpp @@ -127,10 +127,6 @@ inline void for_all_cells_impl(xargs::nodeids, const StructuredMesh& m, KernelTy const IndexType nodeKp = m.nodeKp(); const StackArray& offsets = m.getCellNodeOffsetsArray(); - // GCC 13 release+werror still instantiates inactive structured-dimension branches in callers of - // xargs::nodeids. Keep the scratch connectivity arrays at the structured 3D maximum so those - // compile-time paths never expose undersized local buffers to fixed-shape 2D/3D kernels. - if(dimension == 1) { for_all_cells_impl( @@ -429,10 +425,6 @@ inline void for_all_cells_impl(xargs::coords, const UniformMesh& m, KernelType&& const double z0 = origin[2]; const double dz = spacing[2]; - // GCC 13 release+werror still instantiates inactive structured-dimension branches in callers of - // xargs::coords. Use the structured 3D maximum for zero-initialized scratch buffers so fixed- - // shape 2D/3D kernels do not see undersized local storage when inactive branches are compiled. - if(dimension == 1) { for_all_cells_impl( @@ -540,8 +532,6 @@ inline void for_all_cells_impl(xargs::coords, const RectilinearMesh& m, KernelTy IndexType nodeIDs[STRUCTURED_MAX_CELL_NODES] = {0}; nodeIDs[0] = cellID; nodeIDs[1] = cellID + 1; - // GCC 13 release+werror reports false -Warray-bounds in inactive fixed-2D/3D callers when - // this 1D rectilinear branch uses exact-size buffers. Keep the backing storage max-sized. double coords[3 * STRUCTURED_MAX_CELL_NODES] = {0.}; coords[0] = x_vals_view[nodeIDs[0]]; coords[1] = x_vals_view[nodeIDs[1]]; @@ -703,8 +693,6 @@ inline void for_all_cells_impl(xargs::coords, const UnstructuredMesh& m, K xargs::nodeids(), m, AXOM_LAMBDA(IndexType cellID, const IndexType* nodeIDs, IndexType AXOM_UNUSED_PARAM(numNodes)) { - // GCC 13 release+werror reports false -Warray-bounds when inactive 2D/3D callers are - // compiled against this 1D unstructured branch. Use a max-sized backing array instead. double coords[3 * MAX_CELL_NODES] = {0.}; coords[0] = x_vals_view[nodeIDs[0]]; coords[1] = x_vals_view[nodeIDs[1]]; diff --git a/src/axom/mint/execution/internal/for_all_faces.hpp b/src/axom/mint/execution/internal/for_all_faces.hpp index 65de619fd2..4c77c2e80e 100644 --- a/src/axom/mint/execution/internal/for_all_faces.hpp +++ b/src/axom/mint/execution/internal/for_all_faces.hpp @@ -177,9 +177,6 @@ inline void for_all_faces_impl(xargs::nodeids, const StructuredMesh& m, KernelTy const IndexType* offsets = m.getCellNodeOffsetsArray(); const IndexType cellNodeOffset3 = offsets[3]; - // Keep these scratch arrays at the structured 3D maximum so inactive branches share one - // consistent local buffer shape across 2D and 3D structured traversals. - if(dimension == 2) { const IndexType numIFaces = m.getTotalNumFaces(I_DIRECTION); @@ -548,9 +545,6 @@ inline void for_all_faces_impl(xargs::coords, const UniformMesh& m, KernelType&& const double z0 = origin[2]; const double dz = spacing[2]; - // Back each Matrix with the structured 3D maximum so all structured face branches share one - // consistent local buffer layout. - if(dimension == 2) { helpers::for_all_I_faces( diff --git a/src/axom/mint/execution/internal/helpers.hpp b/src/axom/mint/execution/internal/helpers.hpp index 20179ca7c0..1e2ab9e83f 100644 --- a/src/axom/mint/execution/internal/helpers.hpp +++ b/src/axom/mint/execution/internal/helpers.hpp @@ -89,9 +89,6 @@ inline void for_all_coords(const FOR_ALL_FUNCTOR& for_all_nodes, const MeshType& AXOM_UNUSED_VAR(numNodes); assert(numNodes == NNODES); - // GCC 13 release+werror can still instantiate inactive dimension/node-count paths in callers - // of xargs::coords. Back the Matrix with a zero-initialized max-sized buffer so those - // compile-time-only paths never reference storage smaller than the active 2D/3D caller expects. double localCoords[3 * MAX_NODES] = {0.}; for(int i = 0; i < NNODES; ++i) { diff --git a/src/axom/mint/mesh/Mesh.hpp b/src/axom/mint/mesh/Mesh.hpp index be914faa3e..676a23fbaf 100644 --- a/src/axom/mint/mesh/Mesh.hpp +++ b/src/axom/mint/mesh/Mesh.hpp @@ -863,9 +863,6 @@ inline const FieldData* Mesh::getFieldData(int association) const return nullptr; } - // GCC 13 release+werror reports -Warray-bounds on m_mesh_fields[association] when the index is - // checked only inside SLIC_ERROR_IF(). Validate the range first, then load the field pointer - // through a local so the later null check cannot be misread as an out-of-bounds access. const FieldData* field_data = m_mesh_fields[association]; SLIC_ERROR_IF(field_data == nullptr, "null field data object w/association [" << association << "]"); diff --git a/src/axom/quest/PointInCell.hpp b/src/axom/quest/PointInCell.hpp index 65847ff66f..00a28235ff 100644 --- a/src/axom/quest/PointInCell.hpp +++ b/src/axom/quest/PointInCell.hpp @@ -194,9 +194,8 @@ class PointInCell double posBuffer[3] = {0., 0., 0.}; double isoparBuffer[3] = {0., 0., 0.}; - // GCC 13 release+werror can inline the 3D PointFinder path into 2D MFEM call sites and then - // flag the caller's 2-entry point buffers as out-of-bounds. Stage raw coordinates through - // local 3-entry buffers before the dimension switch, then copy back only the active prefix. + // Stage raw coordinates through local 3-entry buffers before the dimension switch, then + // copy back only the active prefix. for(int i = 0; i < dim; ++i) { posBuffer[i] = pos[i]; diff --git a/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp b/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp index 3c8c0c0973..11ba8de087 100644 --- a/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp +++ b/src/axom/quest/detail/PointInCellMeshWrapper_mfem.hpp @@ -290,9 +290,8 @@ class PointInCellMeshWrapper m_mesh->GetElementTransformation(eltIdx, &tr); mfem::IntegrationPoint ip; - // GCC 13 release+werror reports false -Warray-bounds diagnostics because MFEM's - // IntegrationPoint::Set/Get touch a 3-entry buffer even for 2D elements. Stage 2D - // isoparametric coordinates through a local 3-vector before copying the active prefix. + // MFEM's IntegrationPoint::Set/Get touch a 3-entry buffer even for 2D elements. + // Stage 2D isoparametric coordinates through a local 3-vector before copying the active prefix. double mfemIsopar[3] = {0., 0., 0.}; for(int i = 0; i < dim; ++i) { diff --git a/src/axom/slam/tests/slam_make_helpers.cpp b/src/axom/slam/tests/slam_make_helpers.cpp index a6e50bb89f..2cbfd8d24a 100644 --- a/src/axom/slam/tests/slam_make_helpers.cpp +++ b/src/axom/slam/tests/slam_make_helpers.cpp @@ -261,9 +261,8 @@ TEST(slam_make_helpers, make_constant_relation_rejects_undersized_indices) EXPECT_DEATH_IF_SUPPORTED(slam::make_constant_relation(&fromSet, &toSet, Pos {2}, indices, Pos {4}), ""); #else - // GCC 13 release+werror flags the malformed test buffer as unused because the debug-only - // construction assert compiles out. Build the relation anyway and check isValid() so the - // release path still exercises the undersized-indices failure instead of skipping the test. + // In release builds the construction assert compiles out, so check the invalid relation + // directly to keep exercising the undersized-indices path. auto rel = slam::make_constant_relation(&fromSet, &toSet, Pos {2}, indices, Pos {4}); EXPECT_FALSE(rel.isValid()); #endif From a6773689ae7474d610846ea029e4fc7f83615c25 Mon Sep 17 00:00:00 2001 From: Brian Han Date: Tue, 14 Jul 2026 16:11:01 -0700 Subject: [PATCH 4/5] Reducing changes --- src/axom/mint/execution/internal/helpers.hpp | 2 +- src/axom/quest/detail/MeshTester_detail.hpp | 2 +- src/axom/quest/examples/quest_bvh_two_pass.cpp | 7 +++++-- src/axom/slam/tests/slam_make_helpers.cpp | 8 ++------ src/axom/spin/tests/spin_bvh.cpp | 4 ++-- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/axom/mint/execution/internal/helpers.hpp b/src/axom/mint/execution/internal/helpers.hpp index 1e2ab9e83f..bcd5fbd4a7 100644 --- a/src/axom/mint/execution/internal/helpers.hpp +++ b/src/axom/mint/execution/internal/helpers.hpp @@ -89,7 +89,7 @@ inline void for_all_coords(const FOR_ALL_FUNCTOR& for_all_nodes, const MeshType& AXOM_UNUSED_VAR(numNodes); assert(numNodes == NNODES); - double localCoords[3 * MAX_NODES] = {0.}; + double localCoords[NDIM * MAX_NODES] = {0.}; for(int i = 0; i < NNODES; ++i) { const int i_offset = NDIM * i; diff --git a/src/axom/quest/detail/MeshTester_detail.hpp b/src/axom/quest/detail/MeshTester_detail.hpp index ca6c2a6578..bcf7d93284 100644 --- a/src/axom/quest/detail/MeshTester_detail.hpp +++ b/src/axom/quest/detail/MeshTester_detail.hpp @@ -182,7 +182,7 @@ void CandidateFinderBase::initialize() const double* node = coords.getColumn(inode); tri[inode] = PointType {node[mint::X_COORDINATE], node[mint::Y_COORDINATE], node[mint::Z_COORDINATE]}; - } // END for all cell nodes + } // END for all cells nodes v_degenerate[cellIdx] = (tri.degenerate() ? 1 : 0); diff --git a/src/axom/quest/examples/quest_bvh_two_pass.cpp b/src/axom/quest/examples/quest_bvh_two_pass.cpp index 94a4c2c082..00e973983c 100644 --- a/src/axom/quest/examples/quest_bvh_two_pass.cpp +++ b/src/axom/quest/examples/quest_bvh_two_pass.cpp @@ -121,9 +121,10 @@ void find_collisions_broadphase(const mint::Mesh* mesh, mesh, AXOM_LAMBDA(IndexType cellIdx, axom::numerics::Matrix & coords, const IndexType* nodeIds) { AXOM_UNUSED_VAR(nodeIds); + int numNodes = coords.getNumColumns(); BoxType aabb; - for(IndexType inode = 0; inode < 3; ++inode) + for(IndexType inode = 0; inode < numNodes; ++inode) { const double* node = coords.getColumn(inode); PointType vtx {node[mint::X_COORDINATE], node[mint::Y_COORDINATE], node[mint::Z_COORDINATE]}; @@ -261,7 +262,9 @@ void find_collisions_narrowphase(const mint::Mesh* mesh, AXOM_UNUSED_VAR(nodeIds); TriangleType tri; - for(IndexType inode = 0; inode < 3; ++inode) + int numNodes = coords.getNumColumns(); + SLIC_ASSERT(numNodes == 3); + for(IndexType inode = 0; inode < numNodes; ++inode) { const double* node = coords.getColumn(inode); PointType vtx {node[mint::X_COORDINATE], node[mint::Y_COORDINATE], node[mint::Z_COORDINATE]}; diff --git a/src/axom/slam/tests/slam_make_helpers.cpp b/src/axom/slam/tests/slam_make_helpers.cpp index 2cbfd8d24a..f97efb06a3 100644 --- a/src/axom/slam/tests/slam_make_helpers.cpp +++ b/src/axom/slam/tests/slam_make_helpers.cpp @@ -249,6 +249,7 @@ TEST(slam_make_helpers, make_variable_relation_carray_rejects_short_begins_size) TEST(slam_make_helpers, make_constant_relation_rejects_undersized_indices) { +#ifdef AXOM_DEBUG auto fromSet = slam::make_range_set(3); auto toSet = slam::make_range_set(5); @@ -256,15 +257,10 @@ TEST(slam_make_helpers, make_constant_relation_rejects_undersized_indices) // make_constant_relation asserts the exact size at construction in debug builds // the check compiles out in release builds. Pos indices[4] = {0, 1, 2, 3}; - -#ifdef AXOM_DEBUG EXPECT_DEATH_IF_SUPPORTED(slam::make_constant_relation(&fromSet, &toSet, Pos {2}, indices, Pos {4}), ""); #else - // In release builds the construction assert compiles out, so check the invalid relation - // directly to keep exercising the undersized-indices path. - auto rel = slam::make_constant_relation(&fromSet, &toSet, Pos {2}, indices, Pos {4}); - EXPECT_FALSE(rel.isValid()); + SLIC_INFO("Skipped constant-relation size assertion check in release mode."); #endif } diff --git a/src/axom/spin/tests/spin_bvh.cpp b/src/axom/spin/tests/spin_bvh.cpp index f6ff6ea5f1..bb459c9bdf 100644 --- a/src/axom/spin/tests/spin_bvh.cpp +++ b/src/axom/spin/tests/spin_bvh.cpp @@ -172,8 +172,8 @@ void generate_aabbs_and_centroids(const mint::Mesh* mesh, PointType coords; for(int dim = 0; dim < NDIMS; ++dim) { - coords[dim] = static_cast(node[dim]); - sum[dim] += coords[dim]; + coords[dim] = node[dim]; + sum[dim] += node[dim]; } range.addPoint(coords); From d9e1f3ea1d9d4e76301512c1d66b7b0ca3a8b1e9 Mon Sep 17 00:00:00 2001 From: Brian Han Date: Tue, 21 Jul 2026 09:25:10 -0700 Subject: [PATCH 5/5] Make debug build explicit --- .gitlab/build_dane.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab/build_dane.yml b/.gitlab/build_dane.yml index a660c8b997..d54209640a 100644 --- a/.gitlab/build_dane.yml +++ b/.gitlab/build_dane.yml @@ -41,6 +41,7 @@ dane-llvm_19_1_3-debug-werror-src: variables: COMPILER: "llvm@19.1.3" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" + BUILD_TYPE: "Debug" EXTRA_CMAKE_OPTIONS: "-DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane @@ -64,6 +65,7 @@ dane-sanitizers-gcc_13_3_1-debug-werror-src: variables: COMPILER: "gcc@13.3.1" HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" + BUILD_TYPE: "Debug" LSAN_OPTIONS: suppressions=${CI_PROJECT_DIR}/suppressions.asan EXTRA_CMAKE_OPTIONS: "-DAXOM_ENABLE_ASAN=ON -DAXOM_ENABLE_UBSAN=ON -DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane