Just like everywhere else, we can't just abort compilation because
a function is invalid. We need to emit the Call op and let later
interpretation handle the failure.
This fixes a long standing FIXME comment.
We used to emit dummy pointers for unknown declarations in certain
cases in C, but this is also necessary in C++.
I'm limiting this to static local variables for now.
First, we need to register local constant variables in C, so we get the
same diagnostic behavior as the current interpeter.
Second, when returning an LValue (as a Pointer), which we eventually
convert to an RValue, we need to do the conversion immediately when
saving the Pointer in the EvaluationResult. Otherwise, we will possibly
deallocate the data before doing the conversion (which will look at the
Block*).
For variadic member functions, the way we calculated the instance
pointer and RVO pointer offsts on the stack was incorrect, due
to Func->getArgSize() not returning the full size of all the
passed arguments. When calling variadic functions, we need
to pass the size of the passed (variadic) arguments to the Call*
ops, so they can use that information to properly check the
instance pointer, etc.
This patch adds a bit of code duplication in Interp.h, which I
will get rid of in later cleanup NFC patches.
See the comment I added. When initializing a complex value from a
DeclRefExpr, we need to manually copy both array elements.
This adds some unfortunate code duplication that I'm still pondering
on how to get rid of best.
This is similar to c1ad363e6eba308fa94c47374ee98b3c79693a35, but with
the additional twist that initializing an existing value from a
`MemberExpr` was not working correctly.
Some time ago, I did a similar patch for local variables.
Initializing global variables can fail as well:
```c++
constexpr int a = 1/0;
static_assert(a == 0);
```
... would succeed in the new interpreter, because we never saved the
fact that `a` has not been successfully initialized.
Add an `EvaluationResult` class. This contains the result either as a
`Pointer` or as a `APValue`.
This way, we can inspect the result of the evaluation and diagnose
problems with it (e.g. uninitialized fields in global initializers or
pointers pointing to things they shouldn't point to).
This fixes a long-standing FIXME item.
Unfortunately it changes the diagnostic output of the tests added in
`cxx23.cpp`, but they were wrong before and are wrong after, so no big
deal.
We reach visitExpr() when evaluating standalone expressions. However,
the RetValue() code path was unused before, because we never reach it,
even with structs or arrays.
RetValue expects a pointer on the stack it can take apart to return an
APValue, so provide it with one.
Differential Revision: https://reviews.llvm.org/D150661