Dedicated meeting for C++26 reflection

During the Clang WG meeting yesterday an idea was surfaced to have a dedicated regular meeting to discuss C++26 reflection in Clang. This would be a perfect place to discuss ongoing upstreaming efforts, news coming from WG21, and future directions of reflection implementation in Clang.

I invite interested parties to fill their availability here: C++ Reflection in Clang - Crab Fit. I estimate this to be an open one hour meeting every two weeks, but details are subject to change based on feedback in this thread.

CC @AaronBallman @nhat @katzdm @cor3ntin @erichkeane @shafik

7 Likes

Thank you for getting the ball rolling on this! I think this is such a large feature with so many questions, it makes a lot of sense to have a meeting at least every two weeks to help ensure that reviewers and patch authors are on the same page, make progress more quickly on points than we can do in a PR, etc.

2 Likes

Thank you for starting the conversation. I think it is unavoidable that we will need a dedicated meeting for this, considering how much time it takes up in existing meetings, it could easily dominate a prevent us from getting to other stuff. The first PR is still ongoing it would likely benefit from having a forum to discuss upstreaming issues.

I think since we are already filing new core issues, it would be in our interest to get on the same page wrt those new issues and hopefully come to core with a well thought out position on how to resolve them

At Tesla, our usage of GitHub - Neargye/magic_enum: Static reflection for enums (to string, from string, iteration) for modern C++, work with any enum type without any macro or boilerplate code is amounting to roughly a 15% compile time overhead for our AutoPilot codebase. If I can help out in code reviews, this feature seems like it might be able to help us reduce our compile times a bit.

1 Like

It seems that there is a slot on Friday when everyone is available.

I expect some participants to be out this week because of Thanksgiving, so I propose to meet next Friday, December 5th, at 17:00 UTC (9 AM PST, 12 PM EST).
Calendar link: Reflection in Clang
Meeting link: https://meet.google.com/ihm-kcmg-duy
Agenda and notes: Reflection in Clang Meetings - Google Docs

(This is my first time setting up a meeting in Google Meet, so let me know if something is wrong)

4 Likes

I was told that calendar invite link above did not work for some people. Now our meeting appears at calendar@llvm.org. Hopefully this works better.

Reminder: the meeting starts in one hour.

1 Like

As discussed on Dec 5th, we’re going to have a recurring meeting every 2 weeks starting Jan 9th, at the same time slot of 17:00 UTC (9 AM PST, 12 PM EST) for one hour.

Calendar link: Reflection Sync-Up (also present at calendar@llvm.org)

Meeting Agenda - December 5th, 2025

When: December 5th, 17:00 UTC (9 AM PST, 12 PM EST)

  • Initial introductions as needed
    • Aaron Ballman
      • Clang maintainer from Intel
      • Interested from design perspective
      • Planning to help with code reviews, but not direct implementation efforts
    • Nhat Ngyuen
      • From Bloomberg
      • Working on upstream implementation
    • Ambrose
      • Mostly frontend stuff, more review than implementation
      • but working on expansion statements too
    • Shafik Yagmour
      • A Clang frontend maintainer from Intel
      • Member of CWG
      • Active on reviews
    • Corentin Jabot
      • From Bloomberg
      • Don’t plan to work much on reflection
      • Will try to work on exposing Sema to constant evaluation
      • Is going to have opinions
    • Michael Levine
      • From compiler group in Bloomberg
      • Project manager
      • Engage in more projects and help people
    • Valentyn Yukhumenko
      • From bloomberg
      • Contributor to open source projects
      • Beginner-level contributor to LLVM and GCC
    • Vlad Serebrennikov
      • Maintainer in Clang, used to contract for Bloomberg, have been interested in Reflection for a long while
      • Helping coordinate between Reflection authors and other clang maintainers
      • Plan to do code reviews, mainly on the test side
      • Corentin is picking up my PR on exposing Sema to constant evaluation
    • Vassil Vassilev
      • Princeton University, researcher
      • Built clang-based tools around reflection
    • Alicja Texler
      • From Bloomberg compilers working group
      • Still learning, hoping to get involved with implementation work
    • Hubert Tong
      • From IBM compiler group
      • In C++ standards committee for a decade
      • Hoping to do code review
      • Needs buy-in from management to have time
      • Interested in alignment between implementations and the wording
    • Aurelien Cassagnes
      • Bloomberg engineer
      • Interested in annotations
      • Japanese timezone
  • Meeting cadence for the next year
    • Aaron: holiday season, not a good idea to meet in december once again
    • Aaron: is every two weeks works?
    • Aaron: Jan 9th next meeting?
    • Hubert: I’m available. Today we have CWG, 9th would be the same situation
    • Shafik: this might be a feature. Can discuss Core issues right before CWG telecons
    • Aaron: I’m typically good at ending meetings on time
    • Hubert: I’m fine to have it before Core
    • Aaron: next meeting Jan 9th, same time, every two weeks
  • Start discussing the high-level plan for how to surface reflection
    • to Clang users
    • to downstream consumers of clang as a library
    • Aaron: feature is expansive, need to plan ahead even though prototype implementation is available. Experimental feature, don’t want to surface as a feature in older language modes or C until more deployment experience. Do we want to put it under a flag? Flag to control FTM? Cc1 flag?
    • Corentin: I like the idea of only cc1 flag, because it will take a while to make reflection useful and usable. Cc1 should be fairly limited in what it hides. Opposed to setting FTM before the feature is ready. Should not expose in older language modes for now.
    • Aaron: reflection is different for older language modes, because they have different language rules (asking questions about implementation details).
    • Corentin: we’re in agreement. We should not backport features that are not ready
    • Aaron: need distinction between reflection and metaprogramming. Reflection is well-known, but metaprogramming is terrifying. WG21 might not understand the ramifications themselves
    • Vassil: generally it’s a good idea to split the const part for tools, the const parts are thread safe in ways that the generative parts are not
    • Vlad: there are so many things that change during the translation; parameters can change names, get default arguments, namespaces can be reopened, etc. We also have substitute() which makes us instantiate templates during constant evaluation. So it might be more challenging to find the subset of reflection that is clear. Core is making more expressions value-dependent than before, so even basic stuff is changing.
    • Corentin: 1) it’s going to take us a long time to implementa reflection (>6 months). We should postpone define_aggregate. From the user perspective, if they need to pass a flag to get define_aggregate, this is user-hostile, because it’s a core feature. When we get to it, we should accept that define_aggregate is there to stay.
    • Aaron: I agree on delaying generative bits. I think the biggest use case is enum_to_string and type traits. Generative bits are a different kind of feature which needs a flag. Invalidates assumptions of library authors, because users can change stuff. Not sure what the way is, but the use of generative bits should break the build.
    • Vassil: I think that makes sense. Vlad mentioned that things change during translation, but I meant something different. I’m concerned with changes to AST.
    • Aaron: interesting thing to think about is that we currently rely on some things running in debugger. I don’t want expression evaluator to change AST.
    • Corentin: it won’t work and can’t work.
    • Aaron: if you evaluate rvalue it gives you a value you can expect.
    • Corentin:
    • Vassil: what Aaron means is that you can run expression in debugger, and debugger parses them. Modules are reflections for us. We should be cognizant of this perspective
    • Corentin: AST is finished, you can’t change it
    • Vlad: lldb generates an AST and runs it
    • Vassil: the metaquestion is that clang is different from gcc, because there is an ecosystem of tools around clang, and we’re discussing how to make reflection work for them. Tools will have access to Sema, and will be changing their ASTs. if you debug clang within lldb, and you dump, then there are a bunch of effects happening on the state of clang. We need “no module load” modes to prevent that
    • Ambrose: I see Sema usage in lldb
    • Aaron: Vassil and I are on the same page, but different from Corentin. When I’m debugging clang, I don’t want dump to change anything.
    • Corentin: why would that happen?
    • Aaron: because we already do this with modules
    • Corenin: they are happening at different times.
    • Shafik: you can debug while you’re compiling
    • Aaron: run expression evaluator before TU is complete
    • Corentin: there are specific points where define_aggregate is called
    • Aaron: we don’t want clang-tidy to redo effects of consteval blocks.
    • Corentin: I think we’re in agreement. AST you have in the tool is not changing
    • Vassil: this might be true from language perspective, but not from implementation perspective
    • Corentin: I think we don’t agree on how clang works or should work
    • Aaron: any of our internal APIs can be called by any tool at any point in time, and in the past we’ve made assumptions that did not alway hold
    • Hubert: I’m in agreement with you about internal APIs. scenario: someone is using internal API to evaluate a constant expression in a consteval block. Not sure if we can protect ourselves from this evaluation.
    • Aaron: this is what I’m worried about. What if they create an AST node and evaluate it
    • Vassil: I’ve seen this problem in libraries. They do hooks into clang to assert if declarations happen in wrong contexts. We’d need to significantly change AST to detect if someone is changing it from outside. It will help modules, too.
    • Aaron: Corentin mentioned that our tools don’t have access to Sema, but we need to think about downstream tools as well
    • Corentin: reflection can’t do arbitrary mutation at arbitrary points, we might be able to protect just those points
    • Vlad: indirect changes to AST: inject a default argument, and let the program to observe it later
    • Vassil: one of the reasons tools want to use clang is to instantiate templates. Not wise to think that tools are not using Sema.
    • Corentin: if we assume that, then it’s the same if you call instantiate()
    • Aaron: we wanted to turn off generative bits.
    • Corentin: it can do very specific things
    • Aaron: can it declare arbitrary functions?
    • Corentin: no
    • Hubert: currently evaluation request from a tool is harmless, but with generative bits it may be not.
    • Aaron: good way to put it
    • Vassil: code will behave differently depending on what tools does
    • Hubert: we need to find subset of things that are not going to have effect on subsequent translation
    • Vlad: even harmless queries like names of function parameters can impact the values the metafunctions produce
    • Hubert: declarations hidden from reflection
  • Start discussing the high-level plan for how to upstream existing reflection fork into Clang
    • Timelines of when people are available, including reviewers
    • Corentin: I plan to work over the holidays. For Clang 22, I think we want everything hidden behind a cc1 flag, and do generative bits later. Are we agreed?
    • The room loves the idea
    • Corentin: we can start landing PRs in the next few weeks?
    • Aaron: sure, subject to usual review rules

Request from Nick: post the meeting minutes as something other than a google doc

Meeting Agenda - January 9th, 2026

  • Nhat
    • Nhat: waiting for reviews on the PR
  • Corentin is taking over “Sema in constant evaluator” PR as 173537 (second attempt)
    • Background: some of the generative parts of reflection, as well as things like substitute(), etc require the ability to invoke Sema during constant evaluation
    • Vlad started a PR with a few approaches to try to see how it works. Corentin needs the functionality for something.
    • Corentin: two different concerns. We have needs to access Sema during constant expression evaluation, even outside of reflection. We have some issues already filed on this. But then we need the same functionality for expansion statements as well as reflection.
    • Not trying to answer the question for reflection with this PR.
    • We need a way to tell when constant evaluation can or cannot modify the AST, that’s currently handled by consteval blocks.
    • In some cases, we evaluate a constexpr function before it’s defined and at that point we need to define it.
    • Hubert: that was discussed on the CWG reflectors in Dec. We want to extend the evaluation points for reflection & access context to constant evaluation in general. A lot of it comes down to “usable in constant expressions”. For the variable side, that’s the concept in the wording. That’s depending on the point of the start of the evaluation. But we use the term various times in the standard without specifying the context. The wording is completely wrong because the context is required. Dan and Hubert have been trying to fix that wording on the reflector.
    • Corentin: I’m trying to match GCC rather than the wording in the standard. libstdc++ doesn’t work unless we fix some of these bugs.
    • Hubert: could try to take a look at the wording for mismatches so we can work with the committee to repair it. The committee might still say “no” because the wording is moving towards a principled design.
    • Corentin: we want to instantiate a function in a consteval context unless it is not a trial evaluation. You don’t want side effects just because you’re trying something. That’s why I’m following GCC’s behavior, the standard doesn’t seem to say anything about this.
    • Vlad: there might be a similar case when we handle most vexing parse where we try to parse initializers and instantiate stuff there and back off when we find that doesn’t work. I’ll dig up an example.
    • Corentin: when doing constant evaluation, if you call a function that’s not been instantiated, you do not want to instantiate it at that point if it’s a trial evaluation.
    • Hubert: the wording says you do not do it in the constant evaluator at all. It’s not a property of the evaluation. It’s a property of whether it’s manifestly constant evaluated. At which point that may cause an instantiation. You can do the instantiation ahead of time and not avoid the instantiation.
    • Corentin: the issue we ran into is that it’s very hard to do ahead of time.
    • Hubert: but we’re parsing? After you parse, you know what context you’re in, so now you know that all the names within the expression that you have to care about
    • Corentin: trying to avoid walking multiple times
    • Hubert: but that’s basically what the standard requires
    • Corentin: this is a long-standing issue with uninstantiated functions
    • Vlad: relevant examples: Clang reports an undefined function that has been defined ¡ Issue #73232 ¡ llvm/llvm-project ¡ GitHub
    • Hubert: because we have issues with instantiations as well as lookup context for names, so I’m concerned about trying to do this in the constant evaluator. That moves us away from the model in the standard. I’m fairly certain the committee is not going to be able to review any wording tying instantiation behavior based on the evaluation.
    • Corentin: the standard already says “when needed”
    • Hubert: yes, but “when needed” is based on context. If you have a false path during constant evaluation, it’s not supposed to make a different.
    • Corentin: I don’t think that’s what implementations are doing in practice. Any time you have a constexpr function calling another, you need the instantiation.
    • Hubert: okay, that’s not a constant evaluated context.
    • Corentin: so the standard saying “when needed” is not sufficiently clear.
    • Hubert: the standard has two ways of causing the instantiation. ODR-use and needed for constant evaluation. In the case of the function body, that’s an ODR use. So I guess it’s a question of the order of instantiation that you’re trying to do. Are you trying to say there’s a circular dependency if you try to instantiate before?
    • Corentin: yes, see the link to Clang reports an undefined function that has been defined ¡ Issue #73232 ¡ llvm/llvm-project ¡ GitHub that showcases.
    • Shafik: any example in particular?
    • Corentin: all of them are isomorphic. In all the cases you call a constexpr function which is later defined.
    • Hubert: what’s the simplest one to look at as an example?
    • Corentin: Clang reports an undefined function that has been defined ¡ Issue #73232 ¡ llvm/llvm-project ¡ GitHub
    • Hubert: that’s an ODR use in the definition, but you cannot do the instantiation at that point.
    • Corentin: Clang is going to try to instantiate that function at the end of the TU unless we do something. But then we use it before the end of the TU.
    • Hubert: and it is defined at the point where you do the constant evaluation. I think if you didn’t defer instantiation until codegen, and instead tracked that you need the instantiation when you see it. That might be a road of madness leading to circular dependency where there’s no good order.
    • Corentin: yes
    • Hubert: the standard wording may not be great; it doesn’t talk about timing of instantiations. The direction we’re trying to move to, at the point you do the call to f() is the point where we care if g() is instantiated or not. g() is needed for constant evaluation and it will be instantiated, but the standard never says when. So the case where you need to instantiate is the case the standard doesn’t say much about.
    • Vlad: the idea to instantiate at the end of template definition is what Richard suggested and Corentin implemented (in the comments on the issue). It had to be reverted. The next example in the thread shows the kind of code that doesn’t work, such as things like specializations.
    • Hubert: at some point you have to say that’s not going to work.
    • Corentin: but code relies on this (existing GCC behavior); I don’t want to break Qt
    • Hubert: needs to be discussed in the committee for sure. It’s not like this is the first time where patches had to be made to other projects.
    • Vlad: I think Richard is convinced that code should work (comment), but that ship might have sailed. So far Clang seems to be the only implementation upholding the model Hubert described.
    • Hubert: not surprising, a lot of this constexpr wording was driven by Richard (and Jens).
    • Corentin: if we did not have reflection, it might be worth it to not mix constant evaluation and sema. But with reflection, we have to do that anyway.
    • Hubert: I’ve already pointed out to the committee these issues around reflection and point of instantiation. If you start going down the reflection path, then when you do the instantiation, you’re going to drag a point of instantiation with you. In the reflection world, that’s what happens. If you move in the direction you’re suggesting, you’re going to have issues figuring out what your point of instantiation is for name lookup, ADL, etc. The additional aspect that is very surprising is that we end up seeing block scope declarations in the point of instantiation now, that never happened before.
    • Vlad: is unique_ptr in scope for your PR?
    • Corentin: no, going to come after. Clang has issues when trying to instantiate a constexpr function too late and too early.
    • Shafik: it sounds like what we’re saying is that Clang is strictly following the wording but recent changes in the standard are pulling us in a different direction. Is that right?
    • Hubert: Clang currently does something close to the wording, but won’t cover the first case in Corentin’s issue. What the standard says about that case is not very clear but it leans towards saying it should work. So the attempt at making it work in a manner consistent with what the standard might do exposed the further issue with ordering.
    • Corentin: yes, and I suspect there are many variations of ordering issues.
    • Shafik: so we have too much real world code doing it this way but it will significantly break our users.
    • Corentin: like scenarios where unique_ptr doesn’t work for people.
    • Vlad: worth mentioning it’s not going to break people; unique_ptr issue is only for C++23 because that’s when unique_ptr started having a constexpr destructor. We have the data that not many of our users are on C++23 or newer.
    • Corentin: unfortunately, there’s a difference between what Standard says and was users do
    • Aaron: is Qt broken in just C++23 and newer?
    • Corentin: no, since C++11
    • Corentin: https://godbolt.org/z/Wz5oMzdnP
    • Hubert & Aaron: doing it during evaluation is weird code
    • Aaron: comma operator convinces me that this is weird code (joke)
    • Corentin: are we going to be the only implementation which doesn’t instantiate during constant evaluation?
    • Aaron: the only implementation that follows the standard? That happened before
    • Corentin: I’m not sure whether I should be talking to other implementations or with the committee
    • Hubert: CWG is coming up, we can talk there
    • Aaron: we should talk more to the committee
    • Corentin: agreed
    • Aaron: reflection is experimental all over the place and should not influence our decision here
    • Hubert: even queries require implicit instantiations
    • Aaron: I see this being generative in the same way as define_aggregate
    • Corentin: then the entirety of the reflection is generative
    • Aaron: why can’t we instantiate upon parsing?
    • Corentin: if you do a query that requires class completion, it requires definitions
    • Hubert: even substitute doesn’t cause instantiation
    • Vlad: what meta::info points to?
    • Hubert: instantiation of declaration, not definition. But (I guess there may be cases where) declaration can require other instantiations
    • Vlad: it’s not news that we need to instantiate stuff other than via define_aggregate. members_of requires instantiation. No reflection queries are immune to this
    • Corentin: there is a case of expansion statements, which also need instantiations
    • Ambrose: I don’t remember that we need to instantiate during constant evaluation
    • Ambrose: do you mean creating a lambda out of this air? That happens in Sema
    • Corentin: oh, did I invent something?
    • Ambrose: I can’t think of anything
    • Corentin: Maybe I misunderstood something
    • Ambrose: maybe I didn’t do a good job explaining. We need to evaluate the loop to get a number out of it.
    • Hubert: Aaron, can you give me link to the minutes. We need to discuss whether Google Meet is the best place to have this meeting
    • Aaron: Nick asked to post minutes elsewhere, we didn’t do that
    • Action item for Vlad to post minutes to Discourse
    • Hubert: Google Meet works the worst for me. Can we use anything else?
    • Aaron: happy to use anything else
    • Vlad: Discord doesn’t work for you
    • Aaron: I’ll make it work
    • Alicja: Google Meet works so much better than Zoom for me
    • Ambrose: I prefer google meet
    • Shafik: …
    • Aaron: sounds like folks prefer meet. Hubert, if meet is untenable, let us know
    • Aaron: I like you all too much to suggest Teams
    • Hubert: I’m glad to hear that
    • Aaron: next meeting will be held in Google Meet on 23rd
1 Like

Today’s meeting has just started at https://meet.google.com/ihm-kcmg-duy

Sorry, multiple people make the same mistake of joining an hour earlier. We’ll continuing during the scheduled time.

Meeting Agenda - January 23rd, 2026

  • Nhat’s progress
    • Nhat: Erich approved the PR, Aaron and Corentin left some comments. Continue to work on this after this meeting
  • (added after the meeting) Aurelien (contributor from BB) is waiting for next iteration of review for “C++ Annotation” PR – https://github.com/llvm/llvm-project/pull/166287
  • Hubert: follow-up on discussion about new point of instantiation at the end of template definition
    • CWG2497 might be the right vehicle for WG21 discussion on this
    • Also see Clang reports an undefined function that has been defined ¡ Issue #73232 ¡ llvm/llvm-project ¡ GitHub
    • Hubert: Jens did not point be to this core issue (2794). Telecons don’t have enough quorum to discuss this, so waiting for in-person meeting. A paper might be needed
    • Shafik: agreed, this will need a significant effort to get right
    • Dan: Daveed mentioned that they instantiate during evaluation, and that MSVC does something similar
    • Hubert will email Jens to ask him to discuss 2497 CCing Corentin
    • Hubert: (speaking about 2497) there is a fine line understanding that g is used in a manifestly-constant evaluation, so that there’s a dependency on the definition of f()
    • Dan: we need to do dynamic path instantiation for reflection
    • Hubert: we need an example, and see what other implementations do
    • Dan: the problem is that it can be arbitrarily nested in function calls
    • Hubert: there has to be a structure that describe the dependencies
    • Hubert: then we’d need to know whether side effects of define aggregate was observed
    • Dan: define_aggregate can’t define arbitrary structs. You have the same issue with friend injection
    • Hubert: I have an idea what two models look like, but I have hard time coming up with examples to show what differences are
    • Dan: define_aggregate makes it observable whether you instantiated something
    • Dan: if we’re going after instantiation during evaluation model, at least we can try to specify precisely when instantiations are produced. This is made harder by immediately-escalated expressions. Tentative evaluations make it harder, too. Instantiations would persists even after failed trial evaluations
    • Hubert: if we’re going to codify all the stuff out of constant-evaluation, we could also codify odr-uses
    • Hubert: there are two cases for instantiation to happen: when you referenced it: you need to for constant evaluation, and needed for codegen. We can codify the latter, too
    • Hubert: g() is code-gened, it references f, so it has to be instantiated
    • Dan: f already has a point of instantiation at the end of the TU. We can try to say that if the primary template is not reachable from namespace
    • Hubert: you might not be able to parse if the end of the TU is the only point of instantiation
    • Dan: it’s possible to contrive a program that is IFNDR but it’s not possible to translate the program the bad way
    • Hubert: this is why I said there are two cases for odr-use
    • Hubert: IFNDR supports AST-based implementations
    • Dan: sure there’s a well-formed program that contains a template. At least one.
    • Dan: so it was a bridge too far to discard points of instantiation at the end of the TU. we need to see what other implementations are doing
    • Hubert: that is our homework. Then we’ll have enough material to come to Jens and describe what the options are
  • Which synthesized points are included in the evaluation context?
    • Compiler Explorer
    • Dan: program points historically describes state of the compiler, despite being a spatial property. Define_aggregate breaks that, because state of the compiler changes during evaluation. So we introduced evaluation context which includes program points and synthesized points which describes what is observable for translation: both lexical and injected declarations. It works like this: synthesized point is included in the evaluation context, and that point brings corresponding injected declaration into consideration.
    • Shafik: how does this affect instantiation?
    • Dan: evaluation and instantiation interleaved in two ways: evaluation can cause instantiation, and template specialization can have manifestly-constant evaluated expressions.
    • Dan: members_of can cause implicit instantiations.
    • Dan: Compiler Explorer
    • Dan: consteval block is immediately-invoked lambda which is allowed to produce injected declarations
    • Dan: after line 15 evaluation context contains synthesized points corresponding to the definition of S
    • Dan: Compiler Explorer
    • Dan: now we have nested constant expression
    • Dan: sizeof(T) needs synthesized point from define_aggregate
    • Dan: getting synthesized points into instantiation context makes line 10 work
    • Dan: Compiler Explorer
    • Dan: now on line 8 we have new evaluation context, which again needs the synthesized point.
    • Dan: wording for 73232 can definitely be improved, how and where side-effects happen
    • Vlad: not for the lack of trying — we did try to specify how evaluations and instantiations, but it didn’t bear fruit
    • Dan: it was particularly hard around point of instantiation
    • Dan: synthesized point model is weird, but seems coherent so far
    • Vlad: Compiler Explorer
    • Dan: yes, I want to specify that instantiation context is immutable
    • Dan: the issues here is that line 5 has an initializer
    • Dan: is_complete_type has been phrased in terms of evaluation context of the expression under evaluation
    • Dan: but there’s no distinction between runtime and compile-time evaluation in the abstract machine. There’s only one evaluation
    • Dan: the wording asks b on line 5 to be different depending on whether line 11 has executed.
    • Shafik: we need examples that show how the code executes
    • Dan: the question is whether initializer on line 5 has to be cached
    • Dan: in standardese cached is whether initializer is evaluated with the same evaluation context
    • Dan: I’m arguing that caching is what we want. Compilers are already has to verify whether an initializer is constant, and we don’t want them to throw out the result
    • Dan: to fix this I want to tweak the definition of evaluation context
    • Vlad: you can take 20 words and make sentences out of them
    • Dan: b on line 5 is different variable every time
    • Dan: Compiler Explorer
    • Dan: I think we want to mandate Clang behavior
    • Vlad: but clang re-evaluates
    • Dan: then I want you guys to change
    • Dan: Compiler Explorer
    • Dan: you cache statics, which makes some sense
    • ===========================
    • Dan: Compiler Explorer
    • Dan: a pair of incomplete classes S and T
    • Dan: they will be completed in the course of execution consteval block
    • Dan: we have function f, which has variable b with automatic storage duration. It observes completeness of S. the observation influences the width of a bitfield in T
    • Dan: in the course of doing P2996 there was an unjustified assumptions that constant evaluations are self-contained
    • Dan: evaluation context is codifying translation state that will be observed by metafunctions
    • Dan: initializer of b is manifestly constant-evaluated
    • Dan: when we were considering expressions under evaluation in consteval block, we’re passing through initialization of b, which is now supposed to observe the side-effects of line 11.
    • Dan: there is divergence between Clang and GCC, but only for automatic storage duration
    • Dan: b is a new variable every time f is evaluated
    • Dan: formally b is initialized every time f is called
    • Dan: but initializer of b is evaluated for validation purposes, and then we throw away the result
    • Dan: the idea is to specify caching in the wording
    • Hubert: we’ll take it as a core issue
    • Hubert: the expression under evaluation is the smallest one is the model we have
    • Dan: I want implementation feedback on how possible it is to mandate caching
    • Hubert: with respect to the state of constant evaluator, can we create a separate context?
    • Dan: re-entracy is handled quite good. Everything is kept in EvalInfo
    • Hubert: it needs something like this anyway
    • Hubert: the problem you talk about might exist in the rules about starting the lifetime
    • Hubert: it’s a question whether something is core constant expression. You anchor it to the smallest one.
    • Dan: I want to say that initializer context of initializer of b is evaluated in the same context irrespective of how it was reached
    • Hubert: makes sense
    • Hubert: caching is not the question. The question is whether you can create new evaluation context
    • Dan: in clang you wouldn’t re-enter the evaluation context, you return cached APValue
    • Hubert: …
    • Hubert: in terms of how to approach this in the committee, for the sake of transparency, this might be considered an oversight. Example might complicate things. We might process this without looking at code
    • Shafik: context is always important, so we should be explicit more often
    • Hubert: the issue with making every constexpr static is that you have the pure value problem again. We need objects
    • Dan: evaluation of a metafunction is a function of expression itself and of the evaluation context. For other things it’s just the expression itself. If we say that for manifestly contant-evaluations evaluation context is fixed, then it removes the parametrization for them.
    • Hubert: I’m happy with this
  • CWG3150: Incomplete consteval-only class types (discussion)
    • Dan: Consteval-only types are compounded from meta::info
    • Dan: References and pointers can also be consteval-only
    • Dan: You can have a pointer to incomplete type that becomes consteval-only later:
    • Dan: idea is to make this property dependent on a program point
    • Vlad: like completeness of a type
    • Dan: the initial idea was to prevent meta::info from being emitted
    • Dan: do we really need to disallow emitting meta::info?
    • Hubert: we need to understand the mechanics. Maybe we can check consteval-onlyness on the usage
    • Dan: you can ODR-use B
    • Hubert: but meta::info is something you can’t talk about still
    • Hubert: the really interesting thing is entanglement between consteval-only and immediate escalation and all that
    • Dan: why so?
    • Hubert: you could have a different interpretation whether something is immediate-escalating, depending on where you are evaluating your expression
    • Dan: it would. You have to evaluate immediate invocation after parsing to see whether it’s constant
    • Hubert: but can you have a case when you don’t know if it was an immediate expression
    • Dan: definition of immediate expression will have to be rewritten
    • Hubert: the model will need to change on how we identify the boundaries of constant evaluation
    • Hubert: I don’t know how we deal with something at parse time is immediate or not
    • Dan: I think it’s a matter of type of an expression after you parse it
    • Dan: if you know that something is consteval-only, it’s not changing
    • Dan: we’d run into trouble specifying the second half of [baisc.types.general]/12. It doesn’t make sense to talk about object w.r.t. a point. We’d need to better account for temporaries

Is the next instance of this meeting Friday Feb 20 at 9am pacific?

Yes, 17:00 UTC should be 9 AM Pacific on 20th.

Meeting Agenda - February 6th, 2026

  • Nhat’s progress
    • PR about reflection operator parsing got merged
    • Going to focus on remaining items for reflect-expression next
    • Hubert: my concern is that we’re doing parsing, and then I’m not sure what we’re generating out of it. We need meta::info, even as an opaque type, to do meaningful testing.
    • Nhat: agree. Implementing meta::info might be the next step
    • Dan: there’re developments on consteval-only types that might influence this
    • Hubert: now compiler doesn’t enforce some restrictions around consteval-only types
    • Dan: you mean trunk?
    • Hubert: yes
    • Hubert: it would alleviate my concerns if we run tests through the other compiler (Dan’t fork)
    • Shafik: Hubert, do you have a suggestion or this is a general concern?
    • Hubert: I think we want to have an informal policy that tests should be tested against Dan’s fork
    • Vlad: makes sense to me. How is it going to work? Locally? Godbolt?
    • Hubert: godbolt links in the review, I guess
    • Shafik: makes sense to me
    • Dan: happy to review any tests
    • Vlad: Dan, is your fork separate from Bloomberg’s?
    • Dan: Bloomberg’s fork is dated, but the best we have
    • Hubert: Dan, do you have an opinion on whether we should ignore EDG? It’s not up-to-date
    • Dan: I agree that we should ignore it
    • Hubert: going back to parsing. Not having meta::info made tests less useful, with weird limitations. There’s still a scoping issue. Going breadth-first leaves us with a lot of danger in the future. Can we go depth-first?
    • Hubert: limit parsing, but take it forward, create meta::info, maybe even down to splices.
    • Dan: I’ve always thought of splicing, expressions, and metafunctions as separate branches of P2996. There’s a separate question of how we’re going to implement it upstream. Tablegen? You might be right that meta::info is the right approach. Maybe omitting consteval-only semantics, since it’s still in flux. What do you think, Hubert?
    • Hubert: makes sense
    • Dan: or implement the tracking of consteval-only, but not the semantic restrictions
    • Hubert: maybe we want to avoid the consteval-only question for now
    • Hubert: if we have meta::info, we can have metafunctions. Let’s try to get one query in
    • Vlad: what about instantiation problem that we want to discuss in Core?
    • Dan: we can implement scaffolding, then implement metafunctions that do not implicitly instantiate
    • Hubert: the ship has sailed on whether you need to instantiate during constant evaluation
    • Dan: agreed
    • Hubert: in which instances do synthesized point appear, going back to the issue of point of instantiation
    • Dan: we could have a call to members_of, which needs an implicit instantiation. The question is that compilers like yours what to constant-fold everything. We want to specify that point of instantiation is right after the expression. But then we have tentative evaluations
    • Hubert: the are treated as manifestly constant-evaluated
    • Dan: but we can’t treat them this way
    • Hubert: I don’t agree
    • Dan: if we were to pursue this, which I think we should, while you determining
    • Hubert: it’s time travel, but not time travel
    • Dan: it’s about evaluations you hit before you give up
    • Hubert: yes, but I was trying to explain what it was not
    • Hubert: compile is a process during which we have evaluations, but the standard doesn’t describe it this way: it will state facts, like whether something is a core constant expression. It’s something that compiler determines after following a process. If side effects happened, this is bad. WE’re trying to say that there’s a portion of evaluation that is going to happen anyway. The other prong of the discussion is where the point of instantiation is. We’re trying to tie to where the evaluation emanates.
    • Shafik: it almost feels like we need a design paper
    • Dan: probably
    • Shafil: every time we discuss this, I feel like I’m diving into a cold water. This needs to be laid down on a paper.
    • Hubert: sometimes we’re writing papers to resolve core issue, not always going through evolution
    • Shafik: sure
    • Hubert: I thought you want a trade-off review
    • Shafik: no, trade-off within core
    • Dan: I’d already written it if I had time
    • Shafik: Hubert, are we going to discuss this in core?
    • Hubert: it is one of those places where you need a paper before discussion in core can happen
    • Dan: I won’t have time to put a paper before Croydon. I have ideas which someone else can put into a paper. This is one of the places where we can strengthen the specification
    • Shafik: what is it blocking? Or we can go forward assuming it’s going to be resolved in a particular way
    • Hubert: it’s safe to assume that our ideas to resolve this will be accepted, because it feels natural to me. Dan, when one of the metafunctions get to a point where it needs instantiation, we stop?
    • Dan: yes, we do it in many places
    • Hubert: compilers arelady separately establish the idea where the point of instantiation comes from. Dan, you have a wording, but we don’t have a Core issue that Jens can open
    • Hubert: in the end, I think this issue is to reflect in the wording what the implementation reality is. Fixing the wording gives us a better idea how things work, but it doesn’t block us
    • Dan: status quo is not worse than the rest of the template wording
    • Shafik: sure, makes sense
    • Hubert: I think we haven’t confirmed how we’re going to proceed. We discussed a lot of things, now need to decide. Does Nhat understand how to do meta::info.
    • Nhat: we’re doing meta::Info, but without consteval-only
    • Hubert: we don’t need to do anything on codegen for meta::info
    • Nhat: works for me, I’ll follow-up when I start working
  • Dan: “Constification fails to apply to splice-expressions”
    • Dan: I was reading about contracts and ran into this. Constification says that if you name outside variables, they are const. Reflection and contracts went in parallel through the committee. If you designate a variable through a splice, constification doesn’t happen. Compilers should be able to diagnose the example. We need to integrate splicing into constificatin wording
    • Vlad: not a fan of constification, so this might be a feature, but still worth bringing up for consistency.
    • Dan: me neither
    • Hubert: makes sense to me
    • Aaron: is this applicable when the variable is not named directly?
    • Dan: yes
    • Vlad: constification would apply to the result of splice-expreesion, irrespecituve of what’s within
    • Aaron: makes sense, thank you
  • Dan: pointers to consteval-only types
    • Dan: let’s open CWG3150
    • Dan: I hate this issues
    • Dan: we look at consteval-only as being a global property of a type, but from a given point you don’t know whether a type is consteval. Especially fun if you go cross-TU. My current thinking is that GCC does a good thing. They don’t care and don’t emit anything that is consteavl-only. You get a linker error.
    • Hubert:
    • Dan: my goal is to never force an implementation to emit meta::info. Maybe it’s fine to emit composite types with it, as long as you don’t need to emit info itself. Something like function with info* parameter.
    • Hubert: so this is why you’re saying IFNDR
    • Hubert: this direction leads to question of what is the value of having consteval-only types in the specification.
    • Corentin: if nothing in your type is odr-used, it won’t be emitted anyway
    • Hubert: one of the more recent core issues opened was that there is a way to make compiler emit it, which caused Clang ICE
    • Dan: I think that crux motivation to have consteval-only types was that by prevening emitting info you ‘re more strict on zero-cost nature of reflection.
    • Hubert: this pointer concern doens’t hold. You have a ponter to meta::Info. If it’s null, you’re good.
    • Dan: if pointer type is not consteval-only, why can’t you use it
    • Hubert: hmm, you might be right
    • Corentin: we’re forcing frontend to do a lot of work to prevent emitting an integer that is meaningless. I don’t think we need to do anything
    • Dan: if you can have infos at runtime, people would try to have hashsets of them at runtime
    • Dan: I wouldn’t underestimate reflection being zero-cost
    • Hubert: we made this mistake with inline variables
    • Hubert: but with info it’s IFNDR, so you’re just allowing it to be zero-cost
    • Dan: standard can’t guarantee zero-cost