tryEvaluateString was returning an std::optional, but the other try* API
was not. Update tryEvaluateObjectSize and tryEvaluateStrLen to return an
std::optional<uint64_t>.
This is like https://github.com/llvm/llvm-project/pull/179033, which
broke a few builders for reasons I still don't really understand. I ran
the other clang tests and this version fixes a few of the introduced
regressions.
This still regresses `CodeGen/pass-object-size.c`, but that's a
pre-existing issue.
Patch is of coursed based on #179033 by @mariusdr.
Fixes#138474
Use new bytecode intepreter in `Expr::tryEvaluateObjectSize`. Reuses the
already existing implementation for `__builtin_object_size` in of the
intepreter.
---------
Co-authored-by: Timm Baeder <tbaeder@redhat.com>
The fast path for string literals fails to consider the offset of the
pointer into an array of chars, this change simply adds the required
checks and bounds corrections prior to calling strnlen.
Fixes#173175
In this PR I'm changing the way we provide the missing functions like
strnlen() on z/OS from the separate header file to a wrapper around the
system headers that declare these functions. This will be less
intrusive.
---------
Co-authored-by: Zibi Sarbinowski <zibi@ca.ibm.com>
If the type of the ParmVarDecl and the parameter type from the
FunctionProtoType don't match, we're in for trouble. Just reject those
functions.
Fixes#163568
On z/OS `strnlen()` is not available by default so we use the wrapper
header `zOSSupport.h` to make it visible. This will fix the following
error:
```
clang/lib/AST/ByteCode/Context.cpp:250:16: error: use of undeclared identifier 'strnlen'
250 | Result = strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), N);
| ^~~~~~~
1 error generated.
```
So the static invoker's Function still points to the static invoker
instead of the call operator of the lambda record. This is important for
a later commit.
Remove support for saving a `Pointer` in the `EvaluationResult` since
that was unused. Add `stealAPValue()` which moves the `APValue` out of
the `EvaluationResult` to avoid a copy at the end of the evaluation.
This has been a long-standing problem, but we didn't use to call the
destructors of items on the stack unless we explicitly `pop()` or
`discard()` them.
When interpretation was interrupted midway-through (because something
failed), we left `Pointer`s on the stack. Since all `Block`s track what
`Pointer`s point to them (via a doubly-linked list in the `Pointer`),
that meant we potentially leave deallocated pointers in that list. We
used to work around this by removing the `Pointer` from the list before
deallocating the block.
However, we now want to track pointers to global blocks as well, which
poses a problem since the blocks are never deallocated and thus those
pointers are always left dangling.
I've tried a few different approaches to fixing this but in the end I
just gave up on the idea of never knowing what items are in the stack.
We already have an `ItemTypes` vector that we use for debugging
assertions. This patch simply enables this vector unconditionally and
uses it in the abort case to properly `discard()` all elements from the
stack. That's a little sad IMO but I don't know of another way of
solving this problem.
As expected, this is a slight hit to compile times:
https://llvm-compile-time-tracker.com/compare.php?from=574d0a92060bf4808776b7a0239ffe91a092b15d&to=0317105f559093cfb909bfb01857a6b837991940&stat=instructions:u
Sometimes we don't need the return value of a classsify() call, we only
need to know if we can map the given Expr/Type to a primitive type. Add
canClassify() for that.
This is a major change on how we represent nested name qualifications in
the AST.
* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.
This patch offers a great performance benefit.
It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.
This has great results on compile-time-tracker as well:

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.
It has some other miscelaneous drive-by fixes.
About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.
There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.
How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.
The rest and bulk of the changes are mostly consequences of the changes
in API.
PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.
Fixes#136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
As a way of writing atIndex(I).deref<T>(), which creates an intermediate
Pointer, which in turn adds (and removes) that pointer from the pointer
list of the Block. This way we can avoid that.
Rename isConstexpr to isValid, the former was always a bad name. Save a
constexpr bit in Function so we don't have to access the decl in
CheckCallable.
Try to do as few checks as possible. Check for builtin types only once,
then look at the BuiltinType Kind. For integers, we cache the int and
long size, since those are used a lot and the ASTContext::getIntWidth()
call is costly.
The Pointer class already has the capability to be a function pointer,
but we still classifed function pointers as PT_FnPtr/FunctionPointer.
This means when converting from a Pointer to a FunctionPointer, we lost
the information of what the original Pointer pointed to.
Create the Function* handles for all functions we see, but delay the
actual compilation until we really call the function. This speeds up
compile times with the new interpreter a bit.
This is unneeded in almost all circumstances. We only return an APValue
back to clang when the evaluation is finished, and that is always done
by an EvalEmitter - which has its own implementation of the Ret
instructions.
The global scope we create when evaluating expressions might free some
of the dynamic memory allocations, so we can't check for memory leaks
before destroying it.
I started out by adding a new pointer type for blocks, and I was fully
prepared to compile their AST to bytecode and later call them.
... then I found out that the current interpreter doesn't support
calling blocks at all. So we reuse `Function` to support sources other
than `FunctionDecl`s and classify `BlockPointerType` as `PT_FnPtr`.
This happens for enum types with bool parent types. isBooleanType()
returns false for them however.
The previous version did the same thing by re-classifying the enum
integer type, but that breaks with forward-declared enums.