Revision tags: llvmorg-21-init, llvmorg-19.1.7, llvmorg-19.1.6, llvmorg-19.1.5, llvmorg-19.1.4 |
|
#
46d750be |
| 16-Nov-2024 |
Kazu Hirata <kazu@google.com> |
[Sema] Remove unused includes (NFC) (#116461)
Identified with misc-include-cleaner.
|
Revision tags: llvmorg-19.1.3 |
|
#
4dd55c56 |
| 24-Oct-2024 |
Jay Foad <jay.foad@amd.com> |
[clang] Use {} instead of std::nullopt to initialize empty ArrayRef (#109399)
Follow up to #109133.
|
Revision tags: llvmorg-19.1.2, llvmorg-19.1.1 |
|
#
e1b40dc0 |
| 18-Sep-2024 |
Yuxuan Chen <ych@fb.com> |
[Clang] Propagate elide safe context through [[clang::coro_await_elidable_argument]] (#108474)
|
Revision tags: llvmorg-19.1.0 |
|
#
e17a39bc |
| 09-Sep-2024 |
Yuxuan Chen <ych@fb.com> |
[Clang] C++20 Coroutines: Introduce Frontend Attribute [[clang::coro_await_elidable]] (#99282)
This patch is the frontend implementation of the coroutine elide
improvement project detailed in this
[Clang] C++20 Coroutines: Introduce Frontend Attribute [[clang::coro_await_elidable]] (#99282)
This patch is the frontend implementation of the coroutine elide
improvement project detailed in this discourse post:
https://discourse.llvm.org/t/language-extension-for-better-more-deterministic-halo-for-c-coroutines/80044
This patch proposes a C++ struct/class attribute
`[[clang::coro_await_elidable]]`. This notion of await elidable task
gives developers and library authors a certainty that coroutine heap
elision happens in a predictable way.
Originally, after we lower a coroutine to LLVM IR, CoroElide is
responsible for analysis of whether an elision can happen. Take this as
an example:
```
Task foo();
Task bar() {
co_await foo();
}
```
For CoroElide to happen, the ramp function of `foo` must be inlined into
`bar`. This inlining happens after `foo` has been split but `bar` is
usually still a presplit coroutine. If `foo` is indeed a coroutine, the
inlined `coro.id` intrinsics of `foo` is visible within `bar`. CoroElide
then runs an analysis to figure out whether the SSA value of
`coro.begin()` of `foo` gets destroyed before `bar` terminates.
`Task` types are rarely simple enough for the destroy logic of the task
to reference the SSA value from `coro.begin()` directly. Hence, the pass
is very ineffective for even the most trivial C++ Task types. Improving
CoroElide by implementing more powerful analyses is possible, however it
doesn't give us the predictability when we expect elision to happen.
The approach we want to take with this language extension generally
originates from the philosophy that library implementations of `Task`
types has the control over the structured concurrency guarantees we
demand for elision to happen. That is, the lifetime for the callee's
frame is shorter to that of the caller.
The ``[[clang::coro_await_elidable]]`` is a class attribute which can be
applied to a coroutine return type.
When a coroutine function that returns such a type calls another
coroutine function, the compiler performs heap allocation elision when
the following conditions are all met:
- callee coroutine function returns a type that is annotated with
``[[clang::coro_await_elidable]]``.
- In caller coroutine, the return value of the callee is a prvalue that
is immediately `co_await`ed.
From the C++ perspective, it makes sense because we can ensure the
lifetime of elided callee cannot exceed that of the caller if we can
guarantee that the caller coroutine is never destroyed earlier than the
callee coroutine. This is not generally true for any C++ programs.
However, the library that implements `Task` types and executors may
provide this guarantee to the compiler, providing the user with
certainty that HALO will work on their programs.
After this patch, when compiling coroutines that return a type with such
attribute, the frontend checks that the type of the operand of
`co_await` expressions (not `operator co_await`). If it's also
attributed with `[[clang::coro_await_elidable]]`, the FE emits metadata
on the call or invoke instruction as a hint for a later middle end pass
to elide the elision.
The original patch version is
https://github.com/llvm/llvm-project/pull/94693 and as suggested, the
patch is split into frontend and middle end solutions into stacked PRs.
The middle end CoroSplit patch can be found at
https://github.com/llvm/llvm-project/pull/99283
The middle end transformation that performs the elide can be found at
https://github.com/llvm/llvm-project/pull/99285
show more ...
|
Revision tags: llvmorg-19.1.0-rc4, llvmorg-19.1.0-rc3 |
|
#
55ea3600 |
| 06-Aug-2024 |
Krystian Stasiowski <sdkrystian@gmail.com> |
[Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (#100392)
A class member named by an expression in a member function that may instantiate to
[Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (#100392)
A class member named by an expression in a member function that may instantiate to a static _or_ non-static member is represented by a `UnresolvedLookupExpr` in order to defer the implicit transformation to a class member access expression until instantiation. Since `ASTContext::getDecltypeType` only creates a `DecltypeType` that has a `DependentDecltypeType` as its canonical type when the operand is instantiation dependent, and since we do not transform types unless they are instantiation dependent, we need to mark the `UnresolvedLookupExpr` as instantiation dependent in order to correctly build a `DecltypeType` using the expression as its operand with a `DependentDecltypeType` canonical type. Fixes #99873.
show more ...
|
Revision tags: llvmorg-19.1.0-rc2 |
|
#
db1375f6 |
| 02-Aug-2024 |
ivanaivanovska <iivanovska@google.com> |
Surface error for plain return statement in coroutine earlier (#100985)
When a plain return statement was used in a coroutine, the error "return
statement not allowed in coroutine" was surfaced too
Surface error for plain return statement in coroutine earlier (#100985)
When a plain return statement was used in a coroutine, the error "return
statement not allowed in coroutine" was surfaced too late (e.g. after
other errors in the return statement). Surfacing it earlier now, to make
the issue more obvious.
show more ...
|
Revision tags: llvmorg-19.1.0-rc1, llvmorg-20-init |
|
#
59e56eeb |
| 15-Jul-2024 |
Haojian Wu <hokein.wu@gmail.com> |
Revert "Reapply "[Clang] Implement resolution for CWG1835 (#92957)" (#98547)"
This reverts commit ce4aada6e2135e29839f672a6599db628b53295d and a follow-up patch 8ef26f1289bf069ccc0d6383f2f4c0116a120
Revert "Reapply "[Clang] Implement resolution for CWG1835 (#92957)" (#98547)"
This reverts commit ce4aada6e2135e29839f672a6599db628b53295d and a follow-up patch 8ef26f1289bf069ccc0d6383f2f4c0116a1206c1.
This new warning can not be fully suppressed by the `-Wno-missing-dependent-template-keyword` flag, this gives developer no time to do the cleanup in a large codebase, see https://github.com/llvm/llvm-project/pull/98547#issuecomment-2228250884
show more ...
|
#
ce4aada6 |
| 11-Jul-2024 |
Krystian Stasiowski <sdkrystian@gmail.com> |
Reapply "[Clang] Implement resolution for CWG1835 (#92957)" (#98547)
Reapplies #92957, fixing an instance where the `template` keyword was
missing prior to a dependent name in `llvm/ADT/ArrayRef.h`
Reapply "[Clang] Implement resolution for CWG1835 (#92957)" (#98547)
Reapplies #92957, fixing an instance where the `template` keyword was
missing prior to a dependent name in `llvm/ADT/ArrayRef.h`. An
_alias-declaration_ is used to work around a bug affecting GCC releases
before 11.1 (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94799) which
rejects the use of the `template` keyword prior to the
_nested-name-specifier_ in the class member access.
show more ...
|
#
d3923354 |
| 10-Jul-2024 |
NAKAMURA Takumi <geek4civic@gmail.com> |
Revert "[Clang] Implement resolution for CWG1835 (#92957)"
ppc64le-lld-multistage-test has been failing.
This reverts commit 7bfb98c34687d9784f36937c3ff3e735698b498a.
|
#
7bfb98c3 |
| 09-Jul-2024 |
Krystian Stasiowski <sdkrystian@gmail.com> |
[Clang] Implement resolution for CWG1835 (#92957)
CWG1835 was one of the many core issues resolved by P1787R6: "Declarations and where to
find them" (http://wg21.link/p1787r6). Its resolution chang
[Clang] Implement resolution for CWG1835 (#92957)
CWG1835 was one of the many core issues resolved by P1787R6: "Declarations and where to
find them" (http://wg21.link/p1787r6). Its resolution changes how
member-qualified names (as defined by [basic.lookup.qual.general] p2) are looked
up. This patch implementation that resolution.
Previously, an _identifier_ following `.` or `->` would be first looked
up in the type of the object expression (i.e. qualified lookup), and
then in the context of the _postfix-expression_ (i.e. unqualified
lookup) if nothing was found; the result of the second lookup was
required to name a class template. Notably, this second lookup would
occur even when the object expression was dependent, and its result
would be used to determine whether a `<` token is the start of a
_template-argument_list_.
The new wording in [basic.lookup.qual.general] p2 states:
> A member-qualified name is the (unique) component name, if any, of
> - an _unqualified-id_ or
> - a _nested-name-specifier_ of the form _`type-name ::`_ or
_`namespace-name ::`_
>
> in the id-expression of a class member access expression. A
***qualified name*** is
> - a member-qualified name or
> - the terminal name of
> - a _qualified-id_,
> - a _using-declarator_,
> - a _typename-specifier_,
> - a _qualified-namespace-specifier_, or
> - a _nested-name-specifier_, _elaborated-type-specifier_, or
_class-or-decltype_ that has a _nested-name-specifier_.
>
> The _lookup context_ of a member-qualified name is the type of its
associated object expression (considered dependent if the object
expression is type-dependent). The lookup context of any other qualified
name is the type, template, or namespace nominated by the preceding
_nested-name-specifier_.
And [basic.lookup.qual.general] p3 now states:
> _Qualified name lookup_ in a class, namespace, or enumeration performs
a search of the scope associated with it except as specified below.
Unless otherwise specified, a qualified name undergoes qualified name
lookup in its lookup context from the point where it appears unless the
lookup context either is dependent and is not the current instantiation
or is not a class or class template. If nothing is found by qualified
lookup for a member-qualified name that is the terminal name of a
_nested-name-specifier_ and is not dependent, it undergoes unqualified
lookup.
In non-standardese terms, these two paragraphs essentially state the
following:
- A name that immediately follows `.` or `->` in a class member access
expression is a member-qualified name
- A member-qualified name will be first looked up in the type of the
object expression `T` unless `T` is a dependent type that is _not_ the
current instantiation, e.g.
```
template<typename T>
struct A
{
void f(T* t)
{
this->x; // type of the object expression is 'A<T>'. although 'A<T>' is dependent, it is the
// current instantiation so we look up 'x' in the template definition context.
t->y; // type of the object expression is 'T' ('->' is transformed to '.' per [expr.ref]).
// 'T' is dependent and is *not* the current instantiation, so we lookup 'y' in the
// template instantiation context.
}
};
```
- If the first lookup finds nothing and:
- the member-qualified name is the first component of a
_nested-name-specifier_ (which could be an _identifier_ or a
_simple-template-id_), and either:
- the type of the object expression is the current instantiation and it
has no dependent base classes, or
- the type of the object expression is not dependent
then we lookup the name again, this time via unqualified lookup.
Although the second (unqualified) lookup is stated not to occur when the
member-qualified name is dependent, a dependent name will _not_ be
dependent once the template is instantiated, so the second lookup must
"occur" during instantiation if qualified lookup does not find anything.
This means that we must perform the second (unqualified) lookup during
parsing even when the type of the object expression is dependent, but
those results are _not_ used to determine whether a `<` token is the
start of a _template-argument_list_; they are stored so we can replicate
the second lookup during instantiation.
In even simpler terms (paraphrasing the meeting minutes from the review of P1787; see https://wiki.edg.com/bin/view/Wg21summer2020/P1787%28Lookup%29Review2020-06-15Through2020-06-18):
- Unqualified lookup always happens for the first name in a
_nested-name-specifier_ that follows `.` or `->`
- The result of that lookup is only used to determine whether `<` is the
start of a _template-argument-list_ if the first (qualified) lookup
found nothing and the lookup context:
- is not dependent, or
- is the current instantiation and has no dependent base classes.
An example:
```
struct A
{
void f();
};
template<typename T>
using B = A;
template<typename T>
struct C : A
{
template<typename U>
void g();
void h(T* t)
{
this->g<int>(); // ok, '<' is the start of a template-argument-list ('g' was found via qualified lookup in the current instantiation)
this->B<void>::f(); // ok, '<' is the start of a template-argument-list (current instantiation has no dependent bases, 'B' was found via unqualified lookup)
t->g<int>(); // error: '<' means less than (unqualified lookup does not occur for a member-qualified name that isn't the first component of a nested-name-specifier)
t->B<void>::f(); // error: '<' means less than (unqualified lookup does not occur if the name is dependent)
t->template B<void>::f(); // ok: '<' is the start of a template-argument-list ('template' keyword used)
}
};
```
Some additional notes:
- Per [basic.lookup.qual.general] p1, lookup for a
member-qualified name only considers namespaces, types, and templates
whose specializations are types if it's an _identifier_ followed by
`::`; lookup for the component name of a _simple-template-id_ followed
by `::` is _not_ subject to this rule.
- The wording which specifies when the second unqualified lookup occurs
appears to be paradoxical. We are supposed to do it only for the first
component name of a _nested-name-specifier_ that follows `.` or `->`
when qualified lookup finds nothing. However, when that name is followed
by `<` (potentially starting a _simple-template-id_) we don't _know_
whether it will be the start of a _nested-name-specifier_ until we do
the lookup -- but we aren't supposed to do the lookup until we know it's
part of a _nested-name-specifier_! ***However***, since we only do the
second lookup when the first lookup finds nothing (and the name isn't
dependent), ***and*** since neither lookup is type-only, the only valid
option is for the name to be the _template-name_ in a
_simple-template-id_ that is followed by `::` (it can't be an
_unqualified-id_ naming a member because we already determined that the
lookup context doesn't have a member with that name). Thus, we can lock
into the _nested-name-specifier_ interpretation and do the second lookup
without having to know whether the _simple-template-id_ will be followed
by `::` yet.
show more ...
|
Revision tags: llvmorg-18.1.8, llvmorg-18.1.7, llvmorg-18.1.6, llvmorg-18.1.5 |
|
#
5c4b923c |
| 22-Apr-2024 |
Krystian Stasiowski <sdkrystian@gmail.com> |
Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (#87541, #88311)" (#88731)
Reapplies #8
Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (#87541, #88311)" (#88731)
Reapplies #87541 and #88311 (again) addressing the bug which caused
expressions naming overload sets to be incorrectly rebuilt, as well as
the bug which caused base class members to always be treated as overload
sets.
The primary change since #88311 is `UnresolvedLookupExpr::Create` is called directly in `BuildPossibleImplicitMemberExpr` with `KnownDependent` as `true` (which causes the expression type to be set to `ASTContext::DependentTy`). This ensures that any further semantic analysis involving the type of the potentially implicit class member access expression is deferred until instantiation.
show more ...
|
Revision tags: llvmorg-18.1.4, llvmorg-18.1.3, llvmorg-18.1.2 |
|
#
0f501c30 |
| 11-Mar-2024 |
Chuanqi Xu <yedeng.yd@linux.alibaba.com> |
Revert "[C++20][Coroutines] Lambda-coroutine with operator new in promise_type (#84193)"
This reverts commit 35d3b33ba5c9b90443ac985f2521b78f84b611fe.
See the comments in https://github.com/llvm/ll
Revert "[C++20][Coroutines] Lambda-coroutine with operator new in promise_type (#84193)"
This reverts commit 35d3b33ba5c9b90443ac985f2521b78f84b611fe.
See the comments in https://github.com/llvm/llvm-project/pull/84193 for details
show more ...
|
#
f7868813 |
| 11-Mar-2024 |
fpasserby <125797601+fpasserby@users.noreply.github.com> |
[coroutine] Implement llvm.coro.await.suspend intrinsic (#79712)
Implement `llvm.coro.await.suspend` intrinsics, to deal with performance
regression after prohibiting `.await_suspend` inlining, as
[coroutine] Implement llvm.coro.await.suspend intrinsic (#79712)
Implement `llvm.coro.await.suspend` intrinsics, to deal with performance
regression after prohibiting `.await_suspend` inlining, as suggested in
#64945.
Actually, there are three new intrinsics, which directly correspond to
each of three forms of `await_suspend`:
```
void llvm.coro.await.suspend.void(ptr %awaiter, ptr %frame, ptr @wrapperFunction)
i1 llvm.coro.await.suspend.bool(ptr %awaiter, ptr %frame, ptr @wrapperFunction)
ptr llvm.coro.await.suspend.handle(ptr %awaiter, ptr %frame, ptr @wrapperFunction)
```
There are three different versions instead of one, because in `bool`
case it's result is used for resuming via a branch, and in
`coroutine_handle` case exceptions from `await_suspend` are handled in
the coroutine, and exceptions from the subsequent `.resume()` are
propagated to the caller.
Await-suspend block is simplified down to intrinsic calls only, for
example for symmetric transfer:
```
%id = call token @llvm.coro.save(ptr null)
%handle = call ptr @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %frame, ptr @wrapperFunction)
call void @llvm.coro.resume(%handle)
%result = call i8 @llvm.coro.suspend(token %id, i1 false)
switch i8 %result, ...
```
All await-suspend logic is moved out into a wrapper function, generated
for each suspension point.
The signature of the function is `<type> wrapperFunction(ptr %awaiter,
ptr %frame)` where `<type>` is one of `void` `i1` or `ptr`, depending on
the return type of `await_suspend`.
Intrinsic calls are lowered during `CoroSplit` pass, right after the
split.
Because I'm new to LLVM, I'm not sure if the helper function generation,
calls to them and lowering are implemented in the right way, especially
with regard to various metadata and attributes, i. e. for TBAA. All
things that seemed questionable are marked with `FIXME` comments.
There is another detail: in case of symmetric transfer raw pointer to
the frame of coroutine, that should be resumed, is returned from the
helper function and a direct call to `@llvm.coro.resume` is generated.
C++ standard demands, that `.resume()` method is evaluated. Not sure how
important is this, because code has been generated in the same way
before, sans helper function.
show more ...
|
#
35d3b33b |
| 08-Mar-2024 |
Andreas Fertig <andy@cppinsights.io> |
[C++20][Coroutines] Lambda-coroutine with operator new in promise_type (#84193)
Fix #84064
According to http://eel.is/c++draft/dcl.fct.def.coroutine#9 the first
parameter for overload resolution
[C++20][Coroutines] Lambda-coroutine with operator new in promise_type (#84193)
Fix #84064
According to http://eel.is/c++draft/dcl.fct.def.coroutine#9 the first
parameter for overload resolution of `operator new` is `size_t` followed
by the arguments of the coroutine function.
http://eel.is/c++draft/dcl.fct.def.coroutine#4 states that the first
argument is the lvalue of `*this` if the coroutine is a member function.
Before this patch, Clang handled class types correctly but ignored
lambdas. This patch adds support for lambda coroutines with a
`promise_type` that implements a custom `operator new`.
The patch does consider C++23 `static operator()`, which already worked
as there is no `this` parameter.
show more ...
|
Revision tags: llvmorg-18.1.1, llvmorg-18.1.0, llvmorg-18.1.0-rc4, llvmorg-18.1.0-rc3, llvmorg-18.1.0-rc2, llvmorg-18.1.0-rc1 |
|
#
9dddb3d5 |
| 24-Jan-2024 |
Haojian Wu <hokein.wu@gmail.com> |
[AST] Mark the fallthrough coreturn statement implicit. (#77465)
This is a followup of #77311.
|
Revision tags: llvmorg-19-init |
|
#
498e1c22 |
| 19-Jan-2024 |
Utkarsh Saxena <usx@google.com> |
[coroutine] Create coroutine body in the correct eval context (#78589)
Fixes: https://github.com/llvm/llvm-project/issues/78290
See the bug for more context. ```cpp Gen ACoroutine() { if constexp
[coroutine] Create coroutine body in the correct eval context (#78589)
Fixes: https://github.com/llvm/llvm-project/issues/78290
See the bug for more context. ```cpp Gen ACoroutine() { if constexpr (0) // remove it make clang compile. co_return; co_await Gen{}; } ``` We miss symbol of ctor of promise_type if the first coroutine statement happens to be inside the disabled branch of `if constexpr`.
This happens because the promise object is built when we see the first coroutine statement which is present in `ExpressionEvaluationContext::DiscardedStatement` context due to `if constexpr (0)`. This makes clang believe that the promise constructor is only odr-used and not really "used".
The expr evaluation context for the coroutine body should not be related to the context in which the first coroutine statement appears. We override the context to `PotentiallyEvaluated`.
---------
Co-authored-by: cor3ntin <corentinjabot@gmail.com>
show more ...
|
#
667e58a7 |
| 18-Jan-2024 |
Utkarsh Saxena <usx@google.com> |
[coroutines][coro_lifetimebound] Detect lifetime issues with lambda captures (#77066)
### Problem
```cpp
co_task<int> coro() {
int a = 1;
auto lamb = [a]() -> co_task<int> {
c
[coroutines][coro_lifetimebound] Detect lifetime issues with lambda captures (#77066)
### Problem
```cpp
co_task<int> coro() {
int a = 1;
auto lamb = [a]() -> co_task<int> {
co_return a; // 'a' in the lambda object dies after the iniital_suspend in the lambda coroutine.
}();
co_return co_await lamb;
}
```
[use-after-free](https://godbolt.org/z/GWPEovWWc)
Lambda captures (even by value) are prone to use-after-free once the
lambda object dies. In the above example, the lambda object appears only
as a temporary in the call expression. It dies after the first
suspension (`initial_suspend`) in the lambda.
On resumption in `co_await lamb`, the lambda accesses `a` which is part
of the already-dead lambda object.
---
### Solution
This problem can be formulated by saying that the `this` parameter of
the lambda call operator is a lifetimebound parameter. The lambda object
argument should therefore live atleast as long as the return object.
That said, this requirement does not hold if the lambda does not have a
capture list. In principle, the coroutine frame still has a reference to
a dead lambda object, but it is easy to see that the object would not be
used in the lambda-coroutine body due to no capture list.
It is safe to use this pattern inside a`co_await` expression due to the
lifetime extension of temporaries. Example:
```cpp
co_task<int> coro() {
int a = 1;
int res = co_await [a]() -> co_task<int> { co_return a; }();
co_return res;
}
```
---
### Background
This came up in the discussion with seastar folks on
[RFC](https://discourse.llvm.org/t/rfc-lifetime-bound-check-for-parameters-of-coroutines/74253/19?u=usx95).
This is a fairly common pattern in continuation-style-passing (CSP)
async programming involving futures and continuations. Document ["Lambda
coroutine
fiasco"](https://github.com/scylladb/seastar/blob/master/doc/lambda-coroutine-fiasco.md)
by Seastar captures the problem.
This pattern makes the migration from CSP-style async programming to
coroutines very bugprone.
Fixes https://github.com/llvm/llvm-project/issues/76995
---------
Co-authored-by: Chuanqi Xu <yedeng.yd@linux.alibaba.com>
show more ...
|
Revision tags: llvmorg-17.0.6, llvmorg-17.0.5 |
|
#
858b56e4 |
| 02-Nov-2023 |
Yuxuan Chen <yuxuanchen1997@outlook.com> |
[Clang] Preserve coroutine parameter referenced state (#70973)
This PR is proposing a fix for
https://github.com/llvm/llvm-project/issues/65971.
Previously, given a coroutine like this
```
tas
[Clang] Preserve coroutine parameter referenced state (#70973)
This PR is proposing a fix for
https://github.com/llvm/llvm-project/issues/65971.
Previously, given a coroutine like this
```
task foo(int a) {
co_return;
}
```
Parameter `a` is never used. However, because C++ coroutines move
constructs the variable to a heap allocated coroutine activation frame,
we considered all parameters referenced. When diagnosing unused
parameters, we cannot distinguish if the variable reference was due to
coroutine parameter moves.
Compiler Explorer shows that GCC warns against this case correctly, but
clang does not: https://godbolt.org/z/Wo7dfqeaf
This patch addresses this issue by preserving the original
`ParmVarDecl`'s `Referenced` state.
show more ...
|
#
4ad2ada5 |
| 31-Oct-2023 |
Vlad Serebrennikov <serebrennikov.vladislav@gmail.com> |
[clang][NFC] Refactor ElaboratedTypeKeyword
This patch moves ElaboratedTypeKeyword before `Type` definition so that the enum is complete where bit-field for it is declared. It also converts it to sc
[clang][NFC] Refactor ElaboratedTypeKeyword
This patch moves ElaboratedTypeKeyword before `Type` definition so that the enum is complete where bit-field for it is declared. It also converts it to scoped enum and removes `ETK_` prefix.
show more ...
|
Revision tags: llvmorg-17.0.4 |
|
#
09e8ef97 |
| 26-Oct-2023 |
Aaron Ballman <aaron@aaronballman.com> |
Diagnose use of VLAs in a coroutine (#70341)
Fixes https://github.com/llvm/llvm-project/issues/65858
|
Revision tags: llvmorg-17.0.3, llvmorg-17.0.2, llvmorg-17.0.1, llvmorg-17.0.0, llvmorg-17.0.0-rc4, llvmorg-17.0.0-rc3, llvmorg-17.0.0-rc2, llvmorg-17.0.0-rc1, llvmorg-18-init, llvmorg-16.0.6, llvmorg-16.0.5, llvmorg-16.0.4, llvmorg-16.0.3, llvmorg-16.0.2, llvmorg-16.0.1, llvmorg-16.0.0, llvmorg-16.0.0-rc4, llvmorg-16.0.0-rc3, llvmorg-16.0.0-rc2, llvmorg-16.0.0-rc1, llvmorg-17-init, llvmorg-15.0.7, llvmorg-15.0.6, llvmorg-15.0.5, llvmorg-15.0.4, llvmorg-15.0.3, working, llvmorg-15.0.2, llvmorg-15.0.1, llvmorg-15.0.0, llvmorg-15.0.0-rc3, llvmorg-15.0.0-rc2, llvmorg-15.0.0-rc1, llvmorg-16-init, llvmorg-14.0.6, llvmorg-14.0.5, llvmorg-14.0.4, llvmorg-14.0.3, llvmorg-14.0.2, llvmorg-14.0.1, llvmorg-14.0.0, llvmorg-14.0.0-rc4, llvmorg-14.0.0-rc3, llvmorg-14.0.0-rc2, llvmorg-14.0.0-rc1, llvmorg-15-init |
|
#
af475173 |
| 27-Jan-2022 |
Corentin Jabot <corentinjabot@gmail.com> |
[C++] Implement "Deducing this" (P0847R7)
This patch implements P0847R7 (partially), CWG2561 and CWG2653.
Reviewed By: aaron.ballman, #clang-language-wg
Differential Revision: https://reviews.llvm
[C++] Implement "Deducing this" (P0847R7)
This patch implements P0847R7 (partially), CWG2561 and CWG2653.
Reviewed By: aaron.ballman, #clang-language-wg
Differential Revision: https://reviews.llvm.org/D140828
show more ...
|
#
400d3261 |
| 30-Aug-2023 |
Chris Bieneman <chris.bieneman@me.com> |
[HLSL] Cleanup support for `this` as an l-value
The goal of this change is to clean up some of the code surrounding HLSL using CXXThisExpr as a non-pointer l-value. This change cleans up a bunch of
[HLSL] Cleanup support for `this` as an l-value
The goal of this change is to clean up some of the code surrounding HLSL using CXXThisExpr as a non-pointer l-value. This change cleans up a bunch of assumptions and inconsistencies around how the type of `this` is handled through the AST and code generation.
This change is be mostly NFC for HLSL, and completely NFC for other language modes.
This change introduces a new member to query for the this object's type and seeks to clarify the normal usages of the this type.
With the introudction of HLSL to clang, CXXThisExpr may now be an l-value and behave like a reference type rather than C++'s normal method of it being an r-value of pointer type.
With this change there are now three ways in which a caller might need to query the type of `this`:
* The type of the `CXXThisExpr` * The type of the object `this` referrs to * The type of the implicit (or explicit) `this` argument
This change codifies those three ways you may need to query respectively as:
* CXXMethodDecl::getThisType() * CXXMethodDecl::getThisObjectType() * CXXMethodDecl::getThisArgType()
This change then revisits all uses of `getThisType()`, and in cases where the only use was to resolve the pointee type, it replaces the call with `getThisObjectType()`. In other cases it evaluates whether the desired returned type is the type of the `this` expr, or the type of the `this` function argument. The `this` expr type is used for creating additional expr AST nodes and for member lookup, while the argument type is used mostly for code generation.
Additionally some cases that used `getThisType` in simple queries could be substituted for `getThisObjectType`. Since `getThisType` is implemented in terms of `getThisObjectType` calling the later should be more efficient if the former isn't needed.
Reviewed By: aaron.ballman, bogner
Differential Revision: https://reviews.llvm.org/D159247
show more ...
|
#
20e6515d |
| 29-Aug-2023 |
Chuanqi Xu <yedeng.yd@linux.alibaba.com> |
[Coroutines] Mark 'coroutine_handle<>::address' as always-inline
Close https://github.com/llvm/llvm-project/issues/65054
The direct issue is still the call to coroutine_handle<>::address() after aw
[Coroutines] Mark 'coroutine_handle<>::address' as always-inline
Close https://github.com/llvm/llvm-project/issues/65054
The direct issue is still the call to coroutine_handle<>::address() after await_suspend(). Without optimizations, the current logic will put the temporary result of await_suspend() to the coroutine frame since the middle end feel the temporary is escaped from coroutine_handle<>::address. To fix this fundamentally, we should wrap the whole logic about await-suspend into a standalone function. See https://github.com/llvm/llvm-project/issues/64945
And as a short-term workaround, we probably can mark coroutine_handle<>::address() as always-inline so that the temporary result may not be thought to be escaped then it won't be put on the coroutine frame. Although it looks dirty, it is probably do-able since the compiler are allowed to do special tricks to standard library components.
show more ...
|
#
b32aa72a |
| 28-Aug-2023 |
Chuanqi Xu <yedeng.yd@linux.alibaba.com> |
Recommit [C++20] [Coroutines] Mark await_suspend as noinline if the awaiter is not empty
The original patch is incorrect since it marks too many calls to be noinline. It shows that it is bad to do a
Recommit [C++20] [Coroutines] Mark await_suspend as noinline if the awaiter is not empty
The original patch is incorrect since it marks too many calls to be noinline. It shows that it is bad to do analysis in the frontend again. This patch tries to mark the await_suspend function as noinlne only.
---
Close https://github.com/llvm/llvm-project/issues/56301 Close https://github.com/llvm/llvm-project/issues/64151 Close https://github.com/llvm/llvm-project/issues/65018
See the summary and the discussion of https://reviews.llvm.org/D157070 to get the full context.
As @rjmccall pointed out, the key point of the root cause is that currently we didn't implement the semantics for '@llvm.coro.save' well ("after the await-ready returns false, the coroutine is considered to be suspended ") well. Since the semantics implies that we (the compiler) shouldn't write the spills into the coroutine frame in the await_suspend. But now it is possible due to some combinations of the optimizations so the semantics are broken. And the inlining is the root optimization of such optimizations. So in this patch, we tried to add the `noinline` attribute to the await_suspend function.
This looks slightly problematic since the users are able to call the await_suspend function standalone. This is limited by the implementation. On the one hand, we don't want the workaround solution (See the proposed solution later) to be too complex. On the other hand, it is rare to call await_suspend standalone. Also it is not semantically incorrect to do so since the inlining is not part of the C++ standard.
Also as an optimization, we don't add the `noinline` attribute to the await_suspend function if the awaiter is an empty class. This should be correct since the programmers can't access the local variables in await_suspend if the awaiter is empty. I think this is necessary for the performance since it is pretty common.
The long term solution is:
call @llvm.coro.await_suspend(ptr %awaiter, ptr %handle, ptr @awaitSuspendFn)
Then it is much easier to perform the safety analysis in the middle end. If it is safe to inline the call to awaitSuspend, we can replace it in the CoroEarly pass. Otherwise we could replace it in the CoroSplit pass.
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D157833
show more ...
|
#
8d60e10c |
| 10-Aug-2023 |
dingfei <fding@feysh.com> |
[AST][Coroutine] Fix CoyieldExpr missing end loc
Coroutine co_yield/co_await/co_return are implemented by a serious of synthesized CXXMemberExpr which have no lexical right-side parenthesis.
This f
[AST][Coroutine] Fix CoyieldExpr missing end loc
Coroutine co_yield/co_await/co_return are implemented by a serious of synthesized CXXMemberExpr which have no lexical right-side parenthesis.
This fix uses the end loc of inner expr as the hypothetical RParenLoc of CXXMemberExpr. For tools this might be an issue since the RParen token doesn't exist (but has a valid location).
For future improvement, we might: 1. mark those inner (generated) exprs as implict (tools have chances to skip these nodes) (by @aaron.ballman) 2. borrow the idea from InitListExpr, there are two forms, one is for semantic, the other one is for syntactic, having these two split can make everything easier (by @hokein)
Fixes https://github.com/llvm/llvm-project/issues/64483
Reviewed By: aaron.ballman, hokein
Differential Revision: https://reviews.llvm.org/D157296
show more ...
|