Skip to content

[clang][reflection] Keep namespace member walks clear of out-of-line class-member definitions - #306

Open
Cfretz244 wants to merge 1 commit into
bloomberg:p2996from
Cfretz244:reflect-namespace-members-out-of-line-defs
Open

[clang][reflection] Keep namespace member walks clear of out-of-line class-member definitions#306
Cfretz244 wants to merge 1 commit into
bloomberg:p2996from
Cfretz244:reflect-namespace-members-out-of-line-defs

Conversation

@Cfretz244

Copy link
Copy Markdown

Fixes #303.

Two complementary changes to the namespace member walk in ExprConstantMeta.cpp:

  • isReflectableDecl: reject any decl whose semantic DeclContext is a CXXRecordDecl while its lexical context differs. An out-of-line definition of a class member is a pure redeclaration — the entity is enumerable through its class, never through the namespace it is lexically written in — and its redeclaration filter used to pass it (the definition is the first declaration in its own lexical context), yielding (for class templates) a dependent definition PATTERN whose reflection breaks downstream metafunctions (isa<> used on a null pointer in display/mangling).
  • findIterableMember: when stepping FROM such a decl (the cross-block hop lands on *decls_begin() of a re-opened block unchecked), use its LEXICAL context as the iteration context, so the walk continues through the namespace block instead of departing into the class's getPrevMultDCDeclInSemaContext chain and silently dropping every remaining member. Decls whose semantic context is a NAMESPACE (the legitimate getLastMultDCSemaDecl multi-context chain, e.g. void ns::f() {} defined at TU scope) are deliberately not rewritten.

The regression test covers: interleaved out-of-line defs in a single block, re-opened blocks beginning with template and non-template out-of-line definitions, full member recovery across all blocks, no definition leaking in as a member, and no duplicate enumeration through the class's own walk.

Validation (Release+assertions, AArch64/macOS): minimized repro flips from one bogus member to the three real ones; against real Eigen 5.0.1 headers, a members_of(^^Eigen) lift goes from crashing (or silently yielding 69 of 125 members) to clean; clang/test/Reflection 15/16, identical to pristine base.

…definitions; add regression test

A re-opened namespace block beginning with an out-of-line member definition
(lexically in the namespace, semantically in the class -- Eigen's header
layout) derailed members_of: the definition pattern was yielded as a
namespace member (its reflection breaks downstream metafunctions for
dependent signatures), and stepping from it followed the class's
multi-decl-context chain, silently dropping every remaining member.
isReflectableDecl now rejects such definitions (the entity is enumerable
through its class), and findIterableMember steps through their LEXICAL
context. Decls whose semantic context is a namespace (the legitimate
getLastMultDCSemaDecl chain) are untouched.
@Cfretz244 Cfretz244 changed the title clang: keep namespace member walks clear of out-of-line class-member definitions [clang][reflection] Keep namespace member walks clear of out-of-line class-member definitions Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant