Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CfrontCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,8 @@ void CfrontCodeGenerator::InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBod
} else if(const auto* dtor = dyn_cast_or_null<CXXDestructorDecl>(stmt)) {
// Based on: https://www.dre.vanderbilt.edu/~schmidt/PDF/C++-translation.pdf

InsertVtblPtr(stmt, stmt->getParent(), bodyStmts);

if(body) {
bodyStmts.AddBodyStmts(body);
}
Expand All @@ -682,9 +684,9 @@ void CfrontCodeGenerator::InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBod

bodyStmts.Add(
Call(GetSpecialMemberName(stmt, GetRecordDeclType(base.getType()->getAsRecordDecl())), {cast}));

body = mkCompoundStmt({bodyStmts});
}

body = mkCompoundStmt({bodyStmts});
}

params_store params{};
Expand Down
1 change: 1 addition & 0 deletions CoroutinesCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ void CoroutinesCodeGenerator::InsertCoroutine(const FunctionDecl& fd, const Coro
mOutputFormatHelper.AppendNewLine();
mOutputFormatHelper.AppendNewLine();

InsertArg(stmt->getResultDecl());
InsertArg(stmt->getReturnStmt());

mOutputFormatHelper.AppendSemiNewLine();
Expand Down
4 changes: 4 additions & 0 deletions tests/EduCfrontTest22.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class Fruit {
Print();
}

virtual ~Fruit() { Print(); }

virtual void Print() const { puts("Base"); }
};

Expand All @@ -18,6 +20,8 @@ class Apple : public Fruit {
: Fruit{}
{}

virtual ~Apple() override { Print(); }

void Print() const override { puts("Apple"); }
};

Expand Down
20 changes: 16 additions & 4 deletions tests/EduCfrontTest22.expect
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ typedef struct Fruit
inline Fruit * Constructor_Fruit(Fruit * __this)
{
__this->__vptrFruit = __vtbl_array[0];
(*((void (*)(const Fruit *))((__this)->__vptrFruit[0]).f))((((const Fruit *)(char *)(__this)) + ((__this)->__vptrFruit[0]).d));
(*((void (*)(const Fruit *))((__this)->__vptrFruit[1]).f))((((const Fruit *)(char *)(__this)) + ((__this)->__vptrFruit[1]).d));
return __this;
}

inline void Destructor_Fruit(Fruit * __this)
{
__this->__vptrFruit = __vtbl_array[0];
(*((void (*)(const Fruit *))((__this)->__vptrFruit[1]).f))((((const Fruit *)(char *)(__this)) + ((__this)->__vptrFruit[1]).d));
}

inline void PrintFruit(const Fruit * __this)
{
puts("Base");
Expand All @@ -48,6 +54,12 @@ inline Apple * Constructor_Apple(Apple * __this)
return __this;
}

inline void Destructor_Apple(Apple * __this)
{
(*((void (*)(const Apple *))((__this)->__vptrFruit[1]).f))((((const Apple *)(char *)(__this)) + ((__this)->__vptrFruit[1]).d));
Destructor_Fruit((Fruit *)__this);
}

inline void PrintApple(const Apple * __this)
{
puts("Apple");
Expand All @@ -59,7 +71,7 @@ int __main(void)
Apple x;
Constructor_Apple((Apple *)&x);
return 0;
/* x // lifetime ends here */
(*((void (*)(Apple *))((&x)->__vptrFruit[0]).f))((((Apple *)(char *)(&x)) + ((&x)->__vptrFruit[0]).d));
}

int main(void)
Expand All @@ -71,8 +83,8 @@ int main(void)
/* ret // lifetime ends here */
}

__mptr __vtbl_Fruit[1] = {0, 0, (__vptp)PrintFruit};
__mptr __vtbl_Apple[1] = {0, 0, (__vptp)PrintApple};
__mptr __vtbl_Fruit[2] = {{0, 0, (__vptp)Destructor_Fruit}, {0, 0, (__vptp)PrintFruit}};
__mptr __vtbl_Apple[2] = {{0, 0, (__vptp)Destructor_Apple}, {0, 0, (__vptp)PrintApple}};

__mptr * __vtbl_array[2] = {__vtbl_Fruit, __vtbl_Apple};

Expand Down
2 changes: 2 additions & 0 deletions tests/EduCfrontTest5.expect
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ typedef struct Base

inline void Destructor_Base(Base * __this)
{
__this->__vptrBase = __vtbl_array[0];
}

inline Base * Constructor_Base(Base * __this)
Expand All @@ -68,6 +69,7 @@ typedef struct BaseSecond

inline void Destructor_BaseSecond(BaseSecond * __this)
{
__this->__vptrBaseSecond = __vtbl_array[1];
}

inline BaseSecond * Constructor_BaseSecond(BaseSecond * __this)
Expand Down
2 changes: 2 additions & 0 deletions tests/EduCfrontTest7.expect
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef struct Base

inline void Destructor_Base(Base * __this)
{
__this->__vptrBase = __vtbl_array[0];
}

inline Base * Constructor_Base(Base * __this)
Expand Down Expand Up @@ -87,6 +88,7 @@ typedef struct BaseThird

inline void Destructor_BaseThird(BaseThird * __this)
{
__this->__vptrBaseThird = __vtbl_array[2];
}

inline BaseThird * Constructor_BaseThird(BaseThird * __this)
Expand Down
1 change: 1 addition & 0 deletions tests/EduCfrontVtable4Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ typedef struct A

inline void Destructor_A(A * __this)
{
__this->__vptrA = __vtbl_array[0];
puts("dtor");
}

Expand Down
1 change: 1 addition & 0 deletions tests/EduCfrontVtable5Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ typedef struct Base

inline void Destructor_Base(Base * __this)
{
__this->__vptrBase = __vtbl_array[0];
puts("~Base");
}

Expand Down
1 change: 1 addition & 0 deletions tests/EduCfrontVtable7Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ typedef struct Fruit

inline void Destructor_Fruit(Fruit * __this)
{
__this->__vptrFruit = __vtbl_array[0];
puts("~Fruit");
}

Expand Down
1 change: 1 addition & 0 deletions tests/Issue701.expect
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ typedef struct Fruit

inline void Destructor_Fruit(Fruit * __this)
{
__this->__vptrFruit = __vtbl_array[0];
puts("~Fruit");
}

Expand Down
42 changes: 42 additions & 0 deletions tests/Issue728.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// cmdline:-std=c++20
// cmdlineinsights:-edu-show-coroutine-transformation

#include <cstdio>
#include <iostream>
#include <coroutine>
struct P {
std::suspend_always initial_suspend()
{
return {};
}
void return_void() const noexcept
{
std::cout<<"return_void()\n";
}
std::coroutine_handle<> get_return_object()
{
return std::coroutine_handle<P>::from_promise(*this);
};
void unhandled_exception() { throw; }
std::suspend_never final_suspend() noexcept
{
return {};
}
};
struct R {
R(
std::coroutine_handle<> d) noexcept
: data(d)
{
}
std::coroutine_handle<> data;
using promise_type = P;
};
R funcA(){
co_await std::suspend_never{};
}
int main()
{
funcA().data.resume();
return 0;
}
167 changes: 167 additions & 0 deletions tests/Issue728.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*************************************************************************************
* NOTE: The coroutine transformation you've enabled is a hand coded transformation! *
* Most of it is _not_ present in the AST. What you see is an approximation. *
*************************************************************************************/
#include <cstdio>
#include <iostream>
#include <coroutine>
struct P
{
inline std::suspend_always initial_suspend()
{
return {};
}

inline void return_void() const noexcept
{
std::operator<<(std::cout, "return_void()\n");
}

inline std::coroutine_handle<void> get_return_object()
{
return std::coroutine_handle<P>::from_promise(*this).operator std::coroutine_handle<void>();
}

inline void unhandled_exception()
{
throw ;
}

inline std::suspend_never final_suspend() noexcept
{
return {};
}

// inline constexpr P() noexcept = default;
};


struct R
{
inline R(std::coroutine_handle<void> d) noexcept
: data{std::coroutine_handle<void>(d)}
{
}

std::coroutine_handle<void> data;
using promise_type = P;
};


struct __funcAFrame
{
void (*resume_fn)(__funcAFrame *);
void (*destroy_fn)(__funcAFrame *);
std::__coroutine_traits_sfinae<R>::promise_type __promise;
int __suspend_index;
bool __initial_await_suspend_called;
std::suspend_always __suspend_35_3;
std::suspend_never __suspend_36_12;
std::suspend_never __suspend_35_3_1;
};

R funcA()
{
/* Allocate the frame including the promise */
/* Note: The actual parameter new is __builtin_coro_size */
__funcAFrame * __f = reinterpret_cast<__funcAFrame *>(operator new(sizeof(__funcAFrame)));
__f->__suspend_index = 0;
__f->__initial_await_suspend_called = false;

/* Construct the promise. */
new (&__f->__promise)std::__coroutine_traits_sfinae<R>::promise_type{};

/* Forward declare the resume and destroy function. */
void __funcAResume(__funcAFrame * __f);
void __funcADestroy(__funcAFrame * __f);

/* Assign the resume and destroy function pointers. */
__f->resume_fn = &__funcAResume;
__f->destroy_fn = &__funcADestroy;

/* Call the made up function with the coroutine body for initial suspend.
This function will be called subsequently by coroutine_handle<>::resume()
which calls __builtin_coro_resume(__handle_) */
__funcAResume(__f);


std::coroutine_handle<void> __coro_gro = __f->__promise.get_return_object();
return R(std::coroutine_handle<void>(static_cast<std::coroutine_handle<void> &&>(__coro_gro)));
}

/* This function invoked by coroutine_handle<>::resume() */
void __funcAResume(__funcAFrame * __f)
{
try
{
/* Create a switch to get to the correct resume point */
switch(__f->__suspend_index) {
case 0: break;
case 1: goto __resume_funcA_1;
case 2: goto __resume_funcA_2;
case 3: goto __resume_funcA_3;
}

/* co_await Issue728.cpp:35 */
__f->__suspend_35_3 = __f->__promise.initial_suspend();
if(!__f->__suspend_35_3.await_ready()) {
__f->__suspend_35_3.await_suspend(std::coroutine_handle<P>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 1;
__f->__initial_await_suspend_called = true;
return;
}

__resume_funcA_1:
__f->__suspend_35_3.await_resume();

/* co_await Issue728.cpp:36 */
__f->__suspend_36_12 = std::suspend_never{};
if(!__f->__suspend_36_12.await_ready()) {
__f->__suspend_36_12.await_suspend(std::coroutine_handle<P>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 2;
return;
}

__resume_funcA_2:
__f->__suspend_36_12.await_resume();
/* co_return Issue728.cpp:35 */
__f->__promise.return_void()/* implicit */;
goto __final_suspend;
} catch(...) {
if(!__f->__initial_await_suspend_called) {
throw ;
}

__f->__promise.unhandled_exception();
}

__final_suspend:

/* co_await Issue728.cpp:35 */
__f->__suspend_35_3_1 = __f->__promise.final_suspend();
if(!__f->__suspend_35_3_1.await_ready()) {
__f->__suspend_35_3_1.await_suspend(std::coroutine_handle<P>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 3;
return;
}

__resume_funcA_3:
__f->destroy_fn(__f);
}

/* This function invoked by coroutine_handle<>::destroy() */
void __funcADestroy(__funcAFrame * __f)
{
/* destroy all variables with dtors */
__f->~__funcAFrame();
/* Deallocating the coroutine frame */
/* Note: The actual argument to delete is __builtin_coro_frame with the promise as parameter */
operator delete(static_cast<void *>(__f), sizeof(__funcAFrame));
}


int main()
{
static_cast<const std::coroutine_handle<void> &&>(funcA().data).resume();
return 0;
}
Loading