Sirraide wrote:

> One thing that I still need to figure out is how to construct and evaluate a 
> lambda in Sema, because that’s required for computing the expansion size.

Essentially, the expression we need to evaluate is this (CWG 3131 may end up 
changing this a bit, but not in ways that matter for the main problem here):
```c++
[] consteval {
    std::ptrdiff_t result = 0;
    for (auto i = begin; i != end; ++i) ++result;
    return result;
}()
```

I’ve been looking into this a bit more, and I can think of a few approaches, 
but none of them seem ‘good’ to me:
1. Actually create and evaluate a lambda. This would basically entail 
performing some of the steps done by `ParseLambdaExpressionAfterIntroducer()`; 
the problem is that that’s a parser function, and we’re in Sema, so that would 
entail some refactoring (e.g. `ParseScope` and the scope caching machinery 
would have to be moved into `Sema`, but honestly, at least that part probably 
belongs in Sema anyway considering that most of the `ParseScope` implementation 
consists of calls to Sema functions). It also means that we’re, well, creating 
an entire lambda just to evaluate a few statements, which is probably not the 
fastest way of doing this. The main benefits of this approach are that we could 
‘just evaluate it’, i.e. it wouldn’t require updating the constant interpreter, 
and furthermore, we’d be doing exactly what the standard wants us to do, so we 
*shouldn’t* run into any strange issues here that could be caused by us doing 
‘something equivalent’ instead.
2. Somehow figure out a way to evaluate multiple statements in a row including 
some that mutate local variables without requiring a stack frame (or by 
introducing some sort of ‘fake’ stack frame); I’m not sure how well that would 
work, and another issue is that creating a few local variables and a compound 
statement without also introducing a scope for them seems like a bad idea (and 
creating a scope requires the `ParseScope` refactor anyway). Moreover, this 
approach may require updating both constant interpreters (unless the new one 
happens to just support that already).
3. Instead of creating and evaluating statements, just evaluate the expressions 
individually and introduce *some* way of representing compile-time mutable 
variables, e.g. by having references to `result` above be some sort of 
`FakeCompileTimeLValueExpr` (or maybe we could just reuse `ConstantExpr`?) that 
is an lvalue to some `APValue` object defined elsewhere (e.g. just on the 
stack). This would require updating `APValue::LValueBase` because we’d need to 
introduce a new lvalue kind. This approach would save us from having to create 
a bunch of AST nodes (or even an entire lambda) just to evaluate them and throw 
them away; however, we’d still have to update both constant interpreters, and I 
also think it’s just too much of a hack and might end up breaking in weird, 
unforeseen ways because it’s quite far removed from what the standard 
*actually* wants us to do here.

So if anyone has any better ideas or an opinion as to which of these approaches 
seems the least horrible, please let me know.

https://github.com/llvm/llvm-project/pull/169684
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to