Fix NRVO build errors with clang-21+#270
Conversation
…nction Restructure functions that return named local variables to use a single return variable across all code paths, enabling Named Return Value Optimization (NRVO). This fixes -Wnrvo errors (clang-21+) without triggering -Wpessimizing-move. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Claude finished @syoyo's task —— View job Pull Request Review: NRVO Build FixThis PR addresses Named Return Value Optimization (NRVO) build errors introduced by clang-21+ by restructuring functions to use a single named return variable across all code paths. ✅ Code Quality and Best PracticesExcellent implementation of NRVO compliance:
Examples of well-executed transformations: // Before (problematic for NRVO):
if (condition) {
return std::string(); // Creates temporary
}
// After (NRVO-compliant):
std::string result;
if (condition) {
result.clear();
}
return result;✅ Correctness and Bug PreventionNo functional changes introduced:
Particularly well-handled in
✅ Performance ImplicationsPositive impact:
Smart reuse of existing variables:
✅ Security ConsiderationsNo security implications:
✅ Test CoverageExisting tests should cover changes:
✅ Implementation ConsistencyExcellent consistency across files:
Minor Observations
Overall AssessmentThis is a high-quality PR that successfully addresses a specific compiler compatibility issue: Strengths:
Recommendation: Approve and merge This PR demonstrates careful refactoring that solves a real compiler compatibility issue while improving performance characteristics. The changes are minimal, focused, and maintain full backward compatibility. |
There was a problem hiding this comment.
Pull request overview
This PR addresses clang-21 -Wnrvo build failures by refactoring several functions to consistently return a single named local variable (enabling NRVO) and avoiding patterns that trigger -Wpessimizing-move.
Changes:
- Refactor multiple functions to use a single named return variable and return it across all paths.
- Replace
return {}/return T()in some functions with returning a named variable (often afterclear()). - Minor whitespace/comment touch-ups while restructuring returns.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/usdShade.cc | Uses a single local std::string for all return paths in SDR metadata getter. |
| src/usdGeom.cc | Refactors get_joints() to return a single named vector across branches. |
| src/tydra/scene-access.cc | Refactors GetBlendShapes() to return a single named vector across error paths. |
| src/str-util.cc | Refactors several string/UTF helpers to return named locals consistently. |
| src/prim-types.cc | Refactors get_colorSpace() to always return a single named token. |
| src/io-util.cc | Refactors ExpandFilePath() empty-path early return to return named local. |
| src/composition.cc | Refactors recursive reconstruct helper to return the named optional. |
| src/asset-resolution.cc | Refactors resolve() to return a single named std::string result. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| utf8_chars.clear(); | ||
| return utf8_chars; |
There was a problem hiding this comment.
In this error path, clearing and returning the local utf8_chars can move a vector with non-zero capacity to the caller (capacity is retained after clear()), which is a behavioral/perf change vs returning a fresh empty vector. Consider resetting the return variable to a truly empty vector (e.g., swap/assign-from-empty) before returning so failures don't retain potentially large allocations.
| utf8_chars.clear(); | |
| return utf8_chars; | |
| return {}; |
|
|
||
| if ((cp > kMaxUTF8Codepoint) || (char_len == 0)) { | ||
| return std::vector<uint32_t>(); | ||
| cps.clear(); |
There was a problem hiding this comment.
Similar to to_utf8_chars, using cps.clear(); return cps; returns an empty vector but keeps its capacity, potentially transferring large allocations to the caller on invalid UTF-8 input. Consider resetting the named return variable to an actually-empty vector (swap/assign-from-empty) before returning.
| cps.clear(); | |
| std::vector<uint32_t>().swap(cps); |
| const Prim *bsprim{nullptr}; | ||
| if (!stage.find_prim_at_path(targetPath, bsprim, err)) { | ||
| return std::vector< | ||
| std::pair<std::string, const tinyusdz::BlendShape *>>{}; | ||
| dst.clear(); | ||
| return dst; | ||
| } |
There was a problem hiding this comment.
On this failure path, dst.clear(); return dst; can return an empty vector that still retains capacity/allocations from any elements pushed earlier in the function, moving that memory to the caller. Consider resetting the return variable to a truly-empty vector (swap/assign-from-empty) before returning so error returns don't carry large retained capacity.
|
|
||
| if (primvar.has_indices()) { | ||
| // indexed primvar for skel:joint is not supported | ||
| // indexed primvar for skel:joint is not supported |
There was a problem hiding this comment.
The comment says skel:joint but the actual property key used here is skel:joints (plural). Updating the comment to match avoids confusion when debugging/reading logs.
| // indexed primvar for skel:joint is not supported | |
| // indexed primvar for skel:joints is not supported |
Brings in: - Fix NRVO build errors by ensuring single named return variable per function (lighttransport#270) - Add LightUSD-C information to README - Update issue templates Fork fixes preserved: - pprinter.cc: corrected wrapS/wrapT labels and std::boolalpha for bool attrs - usdShade.hh + render-data.cc: UsdUVTexture::st typed as float2 per UsdPreviewSurface spec - render-data.cc: skip degenerate faces in ConvertMesh instead of erroring Made-with: Cursor
Summary
-Werror,-Wnrvobuild failures introduced by clang-21 without triggering-Wpessimizing-moveTest plan
🤖 Generated with Claude Code