[clang][P2996] Make parameter-name queries independent of instantiation state - #324
Merged
zebullax merged 1 commit intoJul 28, 2026
Conversation
…on state The P3096 consistency walk in getParameterName runs over the function's redeclaration chain and reports no identifier when redeclarations disagree. For an instantiated member, however, instantiating the out-of-line definition REPLACES the parameters on the same FunctionDecl -- no redeclaration is added -- so the walk saw exactly one name: whichever redeclaration happened to be instantiated last. The same query on the same entity then answered differently depending on instantiation state, and two translation units reflecting the same entity could disagree (field shape: Eigen declares DenseBase::setConstant(const Scalar& value) and defines it with 'val'; identifier_of flipped between the two depending on whether binding lambdas had odr-used the member). Walk the template instantiation pattern's declaration chain instead, which carries the in-class declaration and the out-of-line definition regardless of instantiation state. Skipped when the pattern contains a parameter pack (its parameter list does not line up index-for-index with the instantiation's; pack-substituted parameters are already filtered earlier). An inconsistently-named parameter now deterministically has no identifier; consistently-named parameters keep their name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
19 tasks
zebullax
self-requested a review
June 16, 2026 02:26
zebullax
requested changes
Jun 16, 2026
zebullax
left a comment
There was a problem hiding this comment.
The fix goes in the right direction, but it skips the pattern walk altogether when the function has a parameter pack anywhere, regardless of whether the parameter being queried is itself pack-derived.
template <class T> struct P {
template <class... Args> void h(int value, Args... rest);
};
template <class T> template <class... Args>
void P<T>::h(int val, Args... rest) {}
template void P<int>::h<float>(int, float);
// The non-pack parameter "value"/"val" is inconsistently named,
// but has_identifier still returns true (reports "val"):
static_assert(!has_identifier(parameters_of(^^P<int>::h<float>)[0])); // FAILSThe pack guard (none_of(...isParameterPack())) should probably be narrowed.
|
@Cfretz244 per above |
|
To make progress, i ll merge the above (incomplete) then push a delta. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #322.
The P3096 consistency walk in
getParameterName(report no identifier when redeclarations disagree on a parameter name) ran over the function's redeclaration chain — but for an instantiated member, instantiating the out-of-line definition REPLACES the parameters on the sameFunctionDeclwithout adding a redeclaration, so the walk saw exactly one name: whichever redeclaration happened to be instantiated last. The same query on the same entity answered differently depending on instantiation state, and two TUs reflecting the same entity could disagree (field shape: Eigen'sDenseBase::setConstant, declared withvalue, defined withval).Fix: walk the template instantiation pattern's declaration chain, which carries the in-class declaration and the out-of-line definition regardless of instantiation state. Skipped when the pattern contains a parameter pack (its parameter list does not line up index-for-index with the instantiation's; pack-substituted parameters were already filtered earlier in the function). An inconsistently-named parameter now deterministically has no identifier; consistently-named parameters keep their name.
Adds
libcxx/test/std/experimental/reflection/param-name-consistency-instantiation.pass.cpp: the pre-fix flip trigger (explicit instantiation of the definition before the query) plus a consistently-named control.Validated on a Release+assertions AArch64/macOS build of this branch: the repro flips answers at the base commit and is deterministic with the fix;
clang/test/Reflectionparity with base; found and exercised by differential surface-comparison of two independently generated Python binding modules over Eigen.