Age | Commit message (Collapse) | Author | Files | Lines |
|
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
|
|
This patch updates the pmulhw/pmulhuw builtins to support constant
expression handling - extending the VectorExprEvaluator::VisitCallExpr
handling code that handles elementwise integer binop builtins.
Hopefully this can be used as reference patch to show how to add future
target specific constexpr handling with minimal code impact.
I've also enabled pmullw constexpr handling (which are tagged on
#152490) as they all use very similar tests.
I've also had to tweak the MMX -> SSE2 wrapper as undefs are not
permitted in constexpr shuffle masks
Fixes #152524
|
|
When casting a 0 to a pointer type, the IsNullPtr flag was always set to
false, leading to weird results like a pointer with value 0 that isn't a
null pointer.
This caused
```c++
struct B { const int *p;};
template<B> void f() {}
template void f<B{nullptr}>();
template void f<B{fold(reinterpret_cast<int*>(0))}>();
```
to be valid code, since nullptr and (int*)0 aren't equal. This seems
weird and GCC doesn't behave like this.
|
|
(#150829)
HandleMemberPointerAccess considered whether the lvalue path in a member
pointer access matched the bases of the containing class of the member,
but neglected to check the same for the containing class of the member
itself, thereby ignoring access attempts to members in direct sibling
classes.
Fixes #150705.
Fixes #150709.
|
|
|
|
(#151466)
This was one case where we didn't call `FastEvaluateAsRValue` before
going through `EvaluateAsRValue`.
Also replace the `EvalResult` parameter with an `APValue` one, since
`FastEvaluateAsRVaule` only needs that.
Small gains:
https://llvm-compile-time-tracker.com/compare.php?from=112af8e62e734938547d50eeb7b416c8dd666f45&to=b2ea804b9e22b7f37eb1b07b01c0a8057275fe4a&stat=instructions:u
|
|
The Loc param to these functions was weird and not always set in error
cases. It wasn't reliable to use.
This was almost entirely unused inside of clang and the one call site
that used the returned source location doesn't make a difference in
practice.
|
|
This has been explicitly forbidden since C++11, but somehow the edge
case of converting a function pointer to void* using a cast like
`(void*)f` wasn't handled.
Fixes #150340 .
|
|
Like in other places, ignore the reference type of the base. (It might
make sense to refactor this at some point.)
Fixes #150015.
|
|
Fixes #138475
|
|
In #143667, we made constant evaluation fail on `*null_ptr`, as this is
UB. However, `&(*(foo*)0)` seems to be a common pattern, which made
#143667 too disruptive.
So instead of failing the evaluation, we note the UB, which let clang
recovers when checking for constant initialization.
Fixes #149500
|
|
(#149462)
…nevaluated
Fake a function call to the given function and evaluate the given
expression as if it was part of that function call.
Fixes #149383
|
|
(#149227)
071765749a70b22fb62f2efc07a3f242ff5b4c52 improved constexpr-unknown
diagnostics, but potential constant expression checking broke in the
process: we produce diagnostics in more cases. Suppress the diagnostics
as appropriate.
This fix affects -Winvalid-constexpr and the enable_if attribute. (The
-Winvalid-constexpr diagnostic isn't really important right now, but it
will become important if we allow constexpr-unknown with pre-C++23
standards.)
Fixes #149041. Fixes #149188.
|
|
Per [decl.ref],
> Because a null pointer value or a pointer past the end of an object
does not point to an object, a reference in a well-defined program
cannot refer to such things.
Note this does not fixes the new bytecode interpreter.
Fixes #48665
|
|
A constexpr-unknown reference can be equal to an arbitrary value, except
values allocated during constant evaluation. Fix the handling.
The standard is unclear exactly which pointer comparisons count as
"unknown" in this context; for example, in some cases we could use
alignment to prove two constexpr-unknown references are not equal. I
decided to ignore all the cases involving variables not allocated during
constant evaluation.
While looking at this, I also spotted that there might be issues with
lifetimes, but I didn't try to address it.
|
|
|
|
implementation. (#147973)
Closes #147891.
|
|
with std::numeric_limits (#147623)
This PR addresses instances of compiler warning C4146 that can be
replaced with std::numeric_limits. Specifically, these are cases where a
literal such as '-1ULL' was used to assign a value to a uint64_t
variable. The intent is much cleaner if we use the appropriate
std::numeric_limits value<Type>::max() for these cases.
Addresses #147439
|
|
127bf44385424891eb04cff8e52d3f157fc2cb7c implemented most of the
infrastructure for capturing structured bindings in lambdas, but missed
one piece: constant evaluation of such lambdas. Refactor the code to
handle this case.
Fixes #145956.
|
|
Previously we would defer evaluation of CLEs until LValue to RValue
conversions, which would result in creating values within wrong scope
and triggering use-after-frees.
This patch instead eagerly evaluates CLEs, within the scope requiring
them. This requires storing an extra pointer for CLE expressions with
static storage.
Fixes https://github.com/llvm/llvm-project/issues/137165
|
|
APValue::ConstexprUnknown() constructs a broken LValue that doesn't have
an lvalue path, which confuses later error handling. It turns out we
don't actually use the result of createConstexprUnknownAPValues for
anything, so just stop using it. Just construct the LValue directly when
we need it.
Make findCompleteObject emit errors more aggressively; allowing it to
succeed for constexpr-unknown objects leads to weird states where it
succeeds, but doesn't return a well-formed object.
Delete the check for constexpr-unknown in dynamic_cast handling: it's
not necessary, and breaks with the other changes in this patch.
These changes allow us to produce proper diagnostics when something
fails to be evaluated, instead of just printing a generic top-level
error without any notes.
|
|
(#145447)
This reverts commit 329ae86 and adds an early exit for EvaluateInPlace when the expression's type is null.
|
|
(#145207)
|
|
This removes the delayed typo correction functionality from Clang
(regular typo correction still remains) due to fragility of the
solution.
An RFC was posted here:
https://discourse.llvm.org/t/rfc-removing-support-for-delayed-typo-correction/86631
and while that RFC was asking for folks to consider stepping up to be
maintainers, and we did have a few new contributors show some interest,
experiments show that it's likely worth it to remove this functionality
entirely and focus efforts on improving regular typo correction.
This removal fixes ~20 open issues (quite possibly more), improves
compile time performance by roughly .3-.4%
(https://llvm-compile-time-tracker.com/?config=Overview&stat=instructions%3Au&remote=AaronBallman&sortBy=date),
and does not appear to regress diagnostic behavior in a way we wouldn't
find acceptable.
Fixes #142457
Fixes #139913
Fixes #138850
Fixes #137867
Fixes #137860
Fixes #107840
Fixes #93308
Fixes #69470
Fixes #59391
Fixes #58172
Fixes #46215
Fixes #45915
Fixes #45891
Fixes #44490
Fixes #36703
Fixes #32903
Fixes #23312
Fixes #69874
|
|
Use declaresSameEntity when evaluating constexpr to avoid resetting
computed union value due to using different instances of the merged
field decl.
|
|
In 8de51375f12d91675a18d17f262276e65f43fbe0 and related patches, we
added some code to avoid triggering -Wenum-constexpr-conversion in some
cases. This isn't necessary anymore because -Wenum-constexpr-conversion
doesn't exist anymore. And the checks are subtly wrong: they exclude
cases where we actually do need to check the conversion. This patch gets
rid of the unnecessary checks.
|
|
loop during constant evaluation (#140278)
Within the condition statement of the for block, the destructor doesn't
get called when evaluating compile time constants.
Resolves #139818
|
|
parameter (#142964)
Fixes #142835
|
|
(#142498)
If we see a parameter of reference type that isn't part of the frame,
don't try to evaluate its default argument. Just treat it as a
constexpr-unknown value.
Fixes #141114. Fixes #141858.
|
|
|
|
This implements the design proposed by [Representing SpirvType in
Clang's Type System](https://github.com/llvm/wg-hlsl/pull/181). It
creates `HLSLInlineSpirvType` as a new `Type` subclass, and
`__hlsl_spirv_type` as a new builtin type template to create such a
type.
This new type is lowered to the `spirv.Type` target extension type, as
described in [Target Extension Types for Inline SPIR-V and Decorated
Types](https://github.com/llvm/wg-hlsl/blob/main/proposals/0017-inline-spirv-and-decorated-types.md).
|
|
It's potentially costly, so only do it once.
|
|
Usually, in constant evaluation, references which are local to the
evaluation have to be initialized before they're accessed. However,
there's one funny special case: the initializer of a reference can refer
to itself. This generally ends up being undefined behavior if it's used
in an evaluated context, but it isn't otherwise forbidden.
In constant evaluation, this splits into two cases: global variables,
and local variables in constexpr functions. This patch handles both of
those cases. (Local variables tends to trip other errors in most cases,
but if you try hard enough, you can get an accepts-invalid.)
Fixes #131330 .
|
|
Since P2280R4 Unknown references and pointers was implemented,
HandleLValueBase now has to deal with referneces:
D.MostDerivedType->getAsCXXRecordDecl()
will return a nullptr if D.MostDerivedType is a ReferenceType. The fix
is to use getNonReferenceType() to obtain the Pointee Type if we have a
reference.
Fixes: https://github.com/llvm/llvm-project/issues/139452
|
|
The passed indices have to be constant integers anyway, which we verify
before creating the ShuffleVectorExpr. Use the value we create there and
save the indices using a ConstantExpr instead. This way, we don't have
to evaluate the args every time we call getShuffleMaskIdx().
|
|
Take this piece of code:
```cpp
#include <cassert>
consteval int square(int x) {
int result = x * x;
assert(result == 42);
return result;
}
void test() {
auto val = square(2);
}
```
The assertion will fail, and `clang++` will output
(https://godbolt.org/z/hjz3KbTTv):
```cpp
<source>:10:14: error: call to consteval function 'square' is not a constant expression
10 | auto val = square(2);
| ^
<source>:5:3: note: non-constexpr function '__assert_fail' cannot be used in a constant expression
5 | assert(result == 42);
| ^
/usr/include/assert.h:95:9: note: expanded from macro 'assert'
95 | : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))
| ^
<source>:10:14: note: in call to 'square(2)'
10 | auto val = square(2);
| ^~~~~~~~~
/usr/include/assert.h:69:13: note: declared here
69 | extern void __assert_fail (const char *__assertion, const char *__file,
| ^
1 error generated.
Compiler returned: 1
```
This is confusing because it implies that the issue was using an
assertion in a constant-evaluted context, and not that the assertion
failed (`assert()` is OK in constant evaluation). This PR changes the
error message to:
```cpp
test.cpp:10:14: error: call to consteval function 'square' is not a constant expression
10 | auto val = square(2);
| ^
test.cpp:5:3: note: assertion failed in consteval context: 'result == 42'
5 | assert(result == 42);
| ^
/nix/store/lw21wr626v5sdcaxxkv2k4zf1121hfc9-glibc-2.40-36-dev/include/assert.h:102:9: note: expanded from macro 'assert'
102 | : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \
| ^
test.cpp:10:14: note: in call to 'square(2)'
10 | auto val = square(2);
| ^~~~~~~~~
1 error generated.```
|
|
This reverts commit d35ad58859c97521edab7b2eddfa9fe6838b9a5e.
This breaks the clang build:
https://lab.llvm.org/buildbot/#/builders/132/builds/1033
/home/buildbot-worker/bbroot/clang-riscv-rva23-evl-vec-2stage/stage2/lib/Target/RISCV/RISCVGenGlobalISel.inc:1512:44: note: cannot allocate array; evaluated array bound 2431270 exceeds the limit (1048576); use '-fconstexpr-steps' to increase this limit
|
|
Fixes #138653
|
|
Fixes https://github.com/llvm/llvm-project/issues/138824
|
|
(#138461)
This was always using the ast walker.
|
|
(#138247)
The order of operation was slightly incorrect, as we were checking for
incomplete types *before* handling reference types.
Fixes #129397
---------
Co-authored-by: Erich Keane <ekeane@nvidia.com>
|
|
Handle the case where the base expression is a pointer to a vector type.
rdar://149223362
|
|
Relands #137078 after updating clang/test/AST/ByteCode/cxx20.cpp to
account for diagnostic outputs that differ between Linux and macOS.
|
|
Reverts llvm/llvm-project#137078
|
|
When `ArePotentiallyOverlappingStringLiterals`, added in
https://github.com/llvm/llvm-project/pull/109208, compares string
literals it drops the front of the string with the greatest offset from
its base pointer. The number of characters dropped is equal to the
difference between the two strings' offsets from their base pointers.
This would trigger an assert when the resulting offset is past the end
of the object. Not only are one-past-the-end pointers legal constructs,
the compiler should not crash even when faced with illegal constructs.
rdar://149865910
|
|
|
|
The attached test case was missing the note.
|
|
This is a basic implementation of P2719: "Type-aware allocation and
deallocation functions" described at http://wg21.link/P2719
The proposal includes some more details but the basic change in
functionality is the addition of support for an additional implicit
parameter in operators `new` and `delete` to act as a type tag. Tag is
of type `std::type_identity<T>` where T is the concrete type being
allocated. So for example, a custom type specific allocator for `int`
say can be provided by the declaration of
void *operator new(std::type_identity<int>, size_t, std::align_val_t);
void operator delete(std::type_identity<int>, void*, size_t, std::align_val_t);
However this becomes more powerful by specifying templated declarations,
for example
template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t);
template <typename T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t););
Where the operators being resolved will be the concrete type being
operated over (NB. A completely unconstrained global definition as above
is not recommended as it triggers many problems similar to a general
override of the global operators).
These type aware operators can be declared as either free functions or
in class, and can be specified with or without the other implicit
parameters, with overload resolution performed according to the existing
standard parameter prioritisation, only with type parameterised
operators having higher precedence than non-type aware operators. The
only exception is destroying_delete which for reasons discussed in the
paper we do not support type-aware variants by default.
|
|
C2y adds the `_Countof` operator which returns the number of elements in
an array. As with `sizeof`, `_Countof` either accepts a parenthesized
type name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
This is being exposed as an extension in earlier C language modes, but
not in C++. C++ already has `std::extent` and `std::size` to cover these
needs, so the operator doesn't seem to get the user enough benefit to
warrant carrying this as an extension.
Fixes #102836
|
|
Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.
Fixes #131432
|