r325291 - [Coroutines] Use allocator overload when available

Brian Gesiak via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 16 06:16:09 PST 2018


This should be fixed in https://reviews.llvm.org/rL325342. Thanks for your
help!

- Brian

On Fri, Feb 16, 2018 at 9:07 AM, Brian Gesiak <modocache at gmail.com> wrote:

> Ah I'm sorry, I've reproduced this with a `-triple armeb-none-eabi`
> argument. Douglas, do you mind if I fix forward?
>
> - Brian
>
> On Fri, Feb 16, 2018 at 8:55 AM, Brian Gesiak <modocache at gmail.com> wrote:
>
>> Hi Douglas, thanks for letting me know. I'm looking into this now.
>>
>> At first these error messages made me think
>> https://reviews.llvm.org/rL325291 was merged in, but not
>> https://reviews.llvm.org/rL325288. But I guess that's not possible.
>>
>> Is there a way to find out the host triple used on this buildbot? Off the
>> top of my head I can't think of any reasons why frontend diagnostics would
>> be output for this platform but not others.
>>
>> Thanks for your patience!
>>
>>
>> On Fri, Feb 16, 2018 at 5:31 AM, <douglas.yung at sony.com> wrote:
>>
>>> Hi Brian,
>>>
>>> Your change is causing a test failure on the clang-cmake-armv7-a15 bot
>>> in the test Clang::SemaCXX/coroutines.cpp.
>>>
>>> http://lab.llvm.org:8011/builders/clang-cmake-armv7-a15/builds/15742
>>>
>>> error: 'error' diagnostics seen but not expected:
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 790: 'operator new' takes type
>>> size_t ('unsigned int') as first parameter
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 806: 'operator new' takes type
>>> size_t ('unsigned int') as first parameter
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 816: 'operator new' takes type
>>> size_t ('unsigned int') as first parameter
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 839: 'operator new' takes type
>>> size_t ('unsigned int') as first parameter
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 856: 'operator new' takes type
>>> size_t ('unsigned int') as first parameter
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 872: 'operator new' takes type
>>> size_t ('unsigned int') as first parameter
>>> error: 'note' diagnostics expected but not seen:
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 816 (directive at
>>> /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp:815): candidate function not viable:
>>> requires 2 arguments, but 1 was provided
>>>   File /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp Line 839 (directive at
>>> /home/buildslave/buildslave/clang-cmake-armv7-a15/llvm/tools
>>> /clang/test/SemaCXX/coroutines.cpp:838): candidate function not viable:
>>> requires 4 arguments, but 1 was provided
>>> 8 errors generated.
>>>
>>> Can you take a look?
>>>
>>> Douglas Yung
>>>
>>> > -----Original Message-----
>>> > From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org] On
>>> Behalf Of
>>> > Brian Gesiak via cfe-commits
>>> > Sent: Thursday, February 15, 2018 12:37
>>> > To: cfe-commits at lists.llvm.org
>>> > Subject: r325291 - [Coroutines] Use allocator overload when available
>>> >
>>> > Author: modocache
>>> > Date: Thu Feb 15 12:37:22 2018
>>> > New Revision: 325291
>>> >
>>> > URL: http://llvm.org/viewvc/llvm-project?rev=325291&view=rev
>>> > Log:
>>> > [Coroutines] Use allocator overload when available
>>> >
>>> > Summary:
>>> > Depends on https://reviews.llvm.org/D42605.
>>> >
>>> > An implementation of the behavior described in
>>> `[dcl.fct.def.coroutine]/7`:
>>> > when a promise type overloads `operator new` using a "placement new"
>>> > that takes the same argument types as the coroutine function, that
>>> overload is
>>> > used when allocating the coroutine frame.
>>> >
>>> > Simply passing references to the coroutine function parameters
>>> directly to
>>> > `operator new` results in invariant violations in LLVM's coroutine
>>> splitting
>>> > pass, so this implementation modifies Clang codegen to produce
>>> allocator-
>>> > specific alloc/store/loads for each parameter being forwarded to the
>>> > allocator.
>>> >
>>> > Test Plan: `check-clang`
>>> >
>>> > Reviewers: rsmith, GorNishanov, eric_niebler
>>> >
>>> > Reviewed By: GorNishanov
>>> >
>>> > Subscribers: lewissbaker, EricWF, cfe-commits
>>> >
>>> > Differential Revision: https://reviews.llvm.org/D42606
>>> >
>>> > Modified:
>>> >     cfe/trunk/lib/Sema/SemaCoroutine.cpp
>>> >     cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
>>> >     cfe/trunk/test/CodeGenCoroutines/coro-gro-nrvo.cpp
>>> >     cfe/trunk/test/CodeGenCoroutines/coro-params.cpp
>>> >     cfe/trunk/test/SemaCXX/coroutines.cpp
>>> >
>>> > Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
>>> > URL: http://llvm.org/viewvc/llvm-
>>> > project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=325291&r1=3
>>> 25290&r2=325291&vi
>>> > ew=diff
>>> > ============================================================
>>> ==================
>>> > --- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
>>> > +++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Thu Feb 15 12:37:22 2018
>>> > @@ -12,6 +12,7 @@
>>> >  //===-------------------------------------------------------
>>> ---------------
>>> > ===//
>>> >
>>> >  #include "CoroutineStmtBuilder.h"
>>> > +#include "clang/AST/ASTLambda.h"
>>> >  #include "clang/AST/Decl.h"
>>> >  #include "clang/AST/ExprCXX.h"
>>> >  #include "clang/AST/StmtCXX.h"
>>> > @@ -506,24 +507,15 @@ VarDecl *Sema::buildCoroutinePromise(Sou
>>> >
>>> >      auto RefExpr = ExprEmpty();
>>> >      auto Move = Moves.find(PD);
>>> > -    if (Move != Moves.end()) {
>>> > -      // If a reference to the function parameter exists in the
>>> coroutine
>>> > -      // frame, use that reference.
>>> > -      auto *MoveDecl =
>>> > -          cast<VarDecl>(cast<DeclStmt>(M
>>> ove->second)->getSingleDecl());
>>> > -      RefExpr = BuildDeclRefExpr(MoveDecl, MoveDecl->getType(),
>>> > -                                 ExprValueKind::VK_LValue, FD-
>>> > >getLocation());
>>> > -    } else {
>>> > -      // If the function parameter doesn't exist in the coroutine
>>> frame, it
>>> > -      // must be a scalar value. Use it directly.
>>> > -      assert(!PD->getType()->getAsCXXRecordDecl() &&
>>> > -             "Non-scalar types should have been moved and inserted
>>> into the "
>>> > -             "parameter moves map");
>>> > -      RefExpr =
>>> > -          BuildDeclRefExpr(PD, PD->getOriginalType().getNonRe
>>> ferenceType(),
>>> > -                           ExprValueKind::VK_LValue,
>>> FD->getLocation());
>>> > -    }
>>> > -
>>> > +    assert(Move != Moves.end() &&
>>> > +           "Coroutine function parameter not inserted into move map");
>>> > +    // If a reference to the function parameter exists in the
>>> coroutine
>>> > +    // frame, use that reference.
>>> > +    auto *MoveDecl =
>>> > +        cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
>>> > +    RefExpr =
>>> > +        BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonRefe
>>> renceType(),
>>> > +                         ExprValueKind::VK_LValue, FD->getLocation());
>>> >      if (RefExpr.isInvalid())
>>> >        return nullptr;
>>> >      CtorArgExprs.push_back(RefExpr.get());
>>> > @@ -1050,7 +1042,12 @@ bool CoroutineStmtBuilder::makeNewAndDel
>>> >
>>> >    const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure !=
>>> nullptr;
>>> >
>>> > -  // FIXME: Add support for stateful allocators.
>>> > +  // [dcl.fct.def.coroutine]/7
>>> > +  // Lookup allocation functions using a parameter list composed of
>>> the
>>> > + // requested size of the coroutine state being allocated, followed by
>>> > + // the coroutine function's arguments. If a matching allocation
>>> > + function  // exists, use it. Otherwise, use an allocation function
>>> > + that just takes  // the requested size.
>>> >
>>> >    FunctionDecl *OperatorNew = nullptr;
>>> >    FunctionDecl *OperatorDelete = nullptr; @@ -1058,10 +1055,62 @@ bool
>>> > CoroutineStmtBuilder::makeNewAndDel
>>> >    bool PassAlignment = false;
>>> >    SmallVector<Expr *, 1> PlacementArgs;
>>> >
>>> > +  // [dcl.fct.def.coroutine]/7
>>> > +  // "The allocation function’s name is looked up in the scope of P.
>>> > +  // [...] If the lookup finds an allocation function in the scope of
>>> > + P,  // overload resolution is performed on a function call created by
>>> > + assembling  // an argument list. The first argument is the amount of
>>> > + space requested,  // and has type std::size_t. The lvalues p1 ... pn
>>> > + are the succeeding  // arguments."
>>> > +  //
>>> > +  // ...where "p1 ... pn" are defined earlier as:
>>> > +  //
>>> > +  // [dcl.fct.def.coroutine]/3
>>> > +  // "For a coroutine f that is a non-static member function, let P1
>>> > + denote the  // type of the implicit object parameter (13.3.1) and P2
>>> > + ... Pn be the types  // of the function parameters; otherwise let P1
>>> > + ... Pn be the types of the  // function parameters. Let p1 ... pn be
>>> lvalues
>>> > denoting those objects."
>>> > +  if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
>>> > +    if (MD->isInstance() && !isLambdaCallOperator(MD)) {
>>> > +      ExprResult ThisExpr = S.ActOnCXXThis(Loc);
>>> > +      if (ThisExpr.isInvalid())
>>> > +        return false;
>>> > +      ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref,
>>> ThisExpr.get());
>>> > +      if (ThisExpr.isInvalid())
>>> > +        return false;
>>> > +      PlacementArgs.push_back(ThisExpr.get());
>>> > +    }
>>> > +  }
>>> > +  for (auto *PD : FD.parameters()) {
>>> > +    if (PD->getType()->isDependentType())
>>> > +      continue;
>>> > +
>>> > +    // Build a reference to the parameter.
>>> > +    auto PDLoc = PD->getLocation();
>>> > +    ExprResult PDRefExpr =
>>> > +        S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonRe
>>> ferenceType(),
>>> > +                           ExprValueKind::VK_LValue, PDLoc);
>>> > +    if (PDRefExpr.isInvalid())
>>> > +      return false;
>>> > +
>>> > +    PlacementArgs.push_back(PDRefExpr.get());
>>> > +  }
>>> >    S.FindAllocationFunctions(Loc, SourceRange(),
>>> >                              /*UseGlobal*/ false, PromiseType,
>>> >                              /*isArray*/ false, PassAlignment,
>>> PlacementArgs,
>>> > -                            OperatorNew, UnusedResult);
>>> > +                            OperatorNew, UnusedResult, /*Diagnose*/
>>> > + false);
>>> > +
>>> > +  // [dcl.fct.def.coroutine]/7
>>> > +  // "If no matching function is found, overload resolution is
>>> > + performed again  // on a function call created by passing just the
>>> > + amount of space required as  // an argument of type std::size_t."
>>> > +  if (!OperatorNew && !PlacementArgs.empty()) {
>>> > +    PlacementArgs.clear();
>>> > +    S.FindAllocationFunctions(Loc, SourceRange(),
>>> > +                              /*UseGlobal*/ false, PromiseType,
>>> > +                              /*isArray*/ false, PassAlignment,
>>> > +                              PlacementArgs, OperatorNew,
>>> > + UnusedResult);  }
>>> >
>>> >    bool IsGlobalOverload =
>>> >        OperatorNew && !isa<CXXRecordDecl>(OperatorNe
>>> w->getDeclContext());
>>> > @@ -1080,7 +1129,8 @@ bool CoroutineStmtBuilder::makeNewAndDel
>>> >                                OperatorNew, UnusedResult);
>>> >    }
>>> >
>>> > -  assert(OperatorNew && "expected definition of operator new to be
>>> found");
>>> > +  if (!OperatorNew)
>>> > +    return false;
>>> >
>>> >    if (RequiresNoThrowAlloc) {
>>> >      const auto *FT = OperatorNew->getType()->getAs<
>>> FunctionProtoType>();
>>> > @@ -1386,25 +1436,28 @@ bool Sema::buildCoroutineParameterMoves(
>>> >      if (PD->getType()->isDependentType())
>>> >        continue;
>>> >
>>> > -    // No need to copy scalars, LLVM will take care of them.
>>> > -    if (PD->getType()->getAsCXXRecordDecl()) {
>>> > -      ExprResult PDRefExpr = BuildDeclRefExpr(
>>> > -          PD, PD->getType(), ExprValueKind::VK_LValue, Loc); //
>>> FIXME: scope?
>>> > -      if (PDRefExpr.isInvalid())
>>> > -        return false;
>>> > +    ExprResult PDRefExpr =
>>> > +        BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
>>> > +                         ExprValueKind::VK_LValue, Loc); // FIXME:
>>> scope?
>>> > +    if (PDRefExpr.isInvalid())
>>> > +      return false;
>>> >
>>> > -      Expr *CExpr = castForMoving(*this, PDRefExpr.get());
>>> > +    Expr *CExpr = nullptr;
>>> > +    if (PD->getType()->getAsCXXRecordDecl() ||
>>> > +        PD->getType()->isRValueReferenceType())
>>> > +      CExpr = castForMoving(*this, PDRefExpr.get());
>>> > +    else
>>> > +      CExpr = PDRefExpr.get();
>>> >
>>> > -      auto D = buildVarDecl(*this, Loc, PD->getType(),
>>> PD->getIdentifier());
>>> > -      AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
>>> > +    auto D = buildVarDecl(*this, Loc, PD->getType(),
>>> PD->getIdentifier());
>>> > +    AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
>>> >
>>> > -      // Convert decl to a statement.
>>> > -      StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D),
>>> Loc, Loc);
>>> > -      if (Stmt.isInvalid())
>>> > -        return false;
>>> > +    // Convert decl to a statement.
>>> > +    StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc,
>>> Loc);
>>> > +    if (Stmt.isInvalid())
>>> > +      return false;
>>> >
>>> > -      ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD,
>>> > Stmt.get()));
>>> > -    }
>>> > +    ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD,
>>> > + Stmt.get()));
>>> >    }
>>> >    return true;
>>> >  }
>>> >
>>> > Modified: cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
>>> > URL: http://llvm.org/viewvc/llvm-
>>> > project/cfe/trunk/test/CodeGenCoroutines/coro-
>>> > alloc.cpp?rev=325291&r1=325290&r2=325291&view=diff
>>> > ============================================================
>>> ==================
>>> > --- cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp (original)
>>> > +++ cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp Thu Feb 15
>>> 12:37:22
>>> > +++ 2018
>>> > @@ -106,6 +106,34 @@ extern "C" void f1(promise_new_tag ) {
>>> >    co_return;
>>> >  }
>>> >
>>> > +struct promise_matching_placement_new_tag {};
>>> > +
>>> > +template<>
>>> > +struct std::experimental::coroutine_traits<void,
>>> > +promise_matching_placement_new_tag, int, float, double> {
>>> > +  struct promise_type {
>>> > +    void *operator new(unsigned long, promise_matching_placement_new
>>> _tag,
>>> > +                       int, float, double);
>>> > +    void get_return_object() {}
>>> > +    suspend_always initial_suspend() { return {}; }
>>> > +    suspend_always final_suspend() { return {}; }
>>> > +    void return_void() {}
>>> > +  };
>>> > +};
>>> > +
>>> > +// CHECK-LABEL: f1a(
>>> > +extern "C" void f1a(promise_matching_placement_new_tag, int x, float
>>> y
>>> > +, double z) {
>>> > +  // CHECK: store i32 %x, i32* %x.addr, align 4
>>> > +  // CHECK: store float %y, float* %y.addr, align 4
>>> > +  // CHECK: store double %z, double* %z.addr, align 8
>>> > +  // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
>>> > +  // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
>>> > +  // CHECK: %[[INT:.+]] = load i32, i32* %x.addr, align 4
>>> > +  // CHECK: %[[FLOAT:.+]] = load float, float* %y.addr, align 4
>>> > +  // CHECK: %[[DOUBLE:.+]] = load double, double* %z.addr, align 8
>>> > +  // CHECK: call i8*
>>> > + at _ZNSt12experimental16coroutine_traitsIJv34promise_matching
>>> _placement_n
>>> > +ew_tagifdEE12promise_typenwEmS1_ifd(i64 %[[SIZE]], i32 %[[INT]],
>>> float
>>> > +%[[FLOAT]], double %[[DOUBLE]])
>>> > +  co_return;
>>> > +}
>>> > +
>>> >  struct promise_delete_tag {};
>>> >
>>> >  template<>
>>> >
>>> > Modified: cfe/trunk/test/CodeGenCoroutines/coro-gro-nrvo.cpp
>>> > URL: http://llvm.org/viewvc/llvm-
>>> > project/cfe/trunk/test/CodeGenCoroutines/coro-gro-
>>> > nrvo.cpp?rev=325291&r1=325290&r2=325291&view=diff
>>> > ============================================================
>>> ==================
>>> > --- cfe/trunk/test/CodeGenCoroutines/coro-gro-nrvo.cpp (original)
>>> > +++ cfe/trunk/test/CodeGenCoroutines/coro-gro-nrvo.cpp Thu Feb 15
>>> > +++ 12:37:22 2018
>>> > @@ -41,7 +41,7 @@ coro f(int) {
>>> >
>>> >  // CHECK: {{.*}}[[CoroInit]]:
>>> >  // CHECK: store i1 false, i1* %gro.active -// CHECK-NEXT: call void
>>> > @{{.*get_return_objectEv}}(%struct.coro* sret %agg.result
>>> > +// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro* sret
>>> > +%agg.result
>>> >  // CHECK-NEXT: store i1 true, i1* %gro.active
>>> >    co_return;
>>> >  }
>>> > @@ -78,7 +78,7 @@ struct coro_two {
>>> >
>>> >  // CHECK: {{.*}}[[InitOnSuccess]]:
>>> >  // CHECK: store i1 false, i1* %gro.active -// CHECK-NEXT: call void
>>> > @{{.*get_return_objectEv}}(%struct.coro_two* sret %agg.result
>>> > +// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro_two* sret
>>> > +%agg.result
>>> >  // CHECK-NEXT: store i1 true, i1* %gro.active
>>> >
>>> >  // CHECK: [[RetLabel]]:
>>> >
>>> > Modified: cfe/trunk/test/CodeGenCoroutines/coro-params.cpp
>>> > URL: http://llvm.org/viewvc/llvm-
>>> > project/cfe/trunk/test/CodeGenCoroutines/coro-
>>> > params.cpp?rev=325291&r1=325290&r2=325291&view=diff
>>> > ============================================================
>>> ==================
>>> > --- cfe/trunk/test/CodeGenCoroutines/coro-params.cpp (original)
>>> > +++ cfe/trunk/test/CodeGenCoroutines/coro-params.cpp Thu Feb 15
>>> 12:37:22
>>> > +++ 2018
>>> > @@ -69,12 +69,12 @@ void f(int val, MoveOnly moParam, MoveAn
>>> >    // CHECK: store i32 %val, i32* %[[ValAddr:.+]]
>>> >
>>> >    // CHECK: call i8* @llvm.coro.begin(
>>> > -  // CHECK-NEXT: call void @_ZN8MoveOnlyC1EOS_(%struct.MoveOnly*
>>> %[[MoCopy]],
>>> > %struct.MoveOnly* dereferenceable(4) %[[MoParam]])
>>> > +  // CHECK: call void @_ZN8MoveOnlyC1EOS_(%struct.MoveOnly*
>>> > + %[[MoCopy]], %struct.MoveOnly* dereferenceable(4) %[[MoParam]])
>>> >    // CHECK-NEXT: call void @_ZN11MoveAndCopyC1EOS_(%struc
>>> t.MoveAndCopy*
>>> > %[[McCopy]], %struct.MoveAndCopy* dereferenceable(4) %[[McParam]]) #
>>> >    // CHECK-NEXT: invoke void
>>> > @_ZNSt12experimental16coroutine_traitsIJvi8MoveOnly11MoveAnd
>>> CopyEE12promise_ty
>>> > peC1Ev(
>>> >
>>> >    // CHECK: call void @_ZN14suspend_always12await_resumeEv(
>>> > -  // CHECK: %[[IntParam:.+]] = load i32, i32* %val.addr
>>> > +  // CHECK: %[[IntParam:.+]] = load i32, i32* %val1
>>> >    // CHECK: %[[MoGep:.+]] = getelementptr inbounds %struct.MoveOnly,
>>> > %struct.MoveOnly* %[[MoCopy]], i32 0, i32 0
>>> >    // CHECK: %[[MoVal:.+]] = load i32, i32* %[[MoGep]]
>>> >    // CHECK: %[[McGep:.+]] =  getelementptr inbounds
>>> %struct.MoveAndCopy,
>>> > %struct.MoveAndCopy* %[[McCopy]], i32 0, i32 0 @@ -150,9 +150,9 @@
>>> struct
>>> > std::experimental::coroutine_trai
>>> >
>>> >  // CHECK-LABEL: void
>>> > @_Z38coroutine_matching_promise_constructor28promise_matchin
>>> g_constructorifd(i
>>> > 32, float, double)  void
>>> > coroutine_matching_promise_constructor(promise_matching_constructor,
>>> int,
>>> > float, double) {
>>> > -  // CHECK: %[[INT:.+]] = load i32, i32* %.addr, align 4
>>> > -  // CHECK: %[[FLOAT:.+]] = load float, float* %.addr1, align 4
>>> > -  // CHECK: %[[DOUBLE:.+]] = load double, double* %.addr2, align 8
>>> > +  // CHECK: %[[INT:.+]] = load i32, i32* %5, align 4  // CHECK:
>>> > + %[[FLOAT:.+]] = load float, float* %6, align 4  // CHECK:
>>> > + %[[DOUBLE:.+]] = load double, double* %7, align 8
>>> >    // CHECK: invoke void
>>> > @_ZNSt12experimental16coroutine_traitsIJv28promise_matching_
>>> constructorifdEE12
>>> > promise_typeC1ES1_ifd(%"struct.std::experimental::coroutine_
>>> traits<void,
>>> > promise_matching_constructor, int, float, double>::promise_type"*
>>> %__promise,
>>> > i32 %[[INT]], float %[[FLOAT]], double %[[DOUBLE]])
>>> >    co_return;
>>> >  }
>>> >
>>> > Modified: cfe/trunk/test/SemaCXX/coroutines.cpp
>>> > URL: http://llvm.org/viewvc/llvm-
>>> > project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=325291&r1=
>>> 325290&r2=325291&v
>>> > iew=diff
>>> > ============================================================
>>> ==================
>>> > --- cfe/trunk/test/SemaCXX/coroutines.cpp (original)
>>> > +++ cfe/trunk/test/SemaCXX/coroutines.cpp Thu Feb 15 12:37:22 2018
>>> > @@ -781,6 +781,102 @@ coro<T> dependent_uses_nothrow_new(T) {  }
>>> template
>>> > coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13);
>>> >
>>> > +struct good_promise_custom_new_operator {
>>> > +  coro<good_promise_custom_new_operator> get_return_object();
>>> > +  suspend_always initial_suspend();
>>> > +  suspend_always final_suspend();
>>> > +  void return_void();
>>> > +  void unhandled_exception();
>>> > +  void *operator new(unsigned long, double, float, int); };
>>> > +
>>> > +coro<good_promise_custom_new_operator>
>>> > +good_coroutine_calls_custom_new_operator(double, float, int) {
>>> > +  co_return;
>>> > +}
>>> > +
>>> > +struct coroutine_nonstatic_member_struct;
>>> > +
>>> > +struct good_promise_nonstatic_member_custom_new_operator {
>>> > +  coro<good_promise_nonstatic_member_custom_new_operator>
>>> > +get_return_object();
>>> > +  suspend_always initial_suspend();
>>> > +  suspend_always final_suspend();
>>> > +  void return_void();
>>> > +  void unhandled_exception();
>>> > +  void *operator new(unsigned long, coroutine_nonstatic_member_struct
>>> > +&, double); };
>>> > +
>>> > +struct bad_promise_nonstatic_member_mismatched_custom_new_operator {
>>> > +  coro<bad_promise_nonstatic_member_mismatched_custom_new_operator>
>>> > +get_return_object();
>>> > +  suspend_always initial_suspend();
>>> > +  suspend_always final_suspend();
>>> > +  void return_void();
>>> > +  void unhandled_exception();
>>> > +  // expected-note at +1 {{candidate function not viable: requires 2
>>> > +arguments, but 1 was provided}}
>>> > +  void *operator new(unsigned long, double); };
>>> > +
>>> > +struct coroutine_nonstatic_member_struct {
>>> > +  coro<good_promise_nonstatic_member_custom_new_operator>
>>> > +  good_coroutine_calls_nonstatic_member_custom_new_operator(double) {
>>> > +    co_return;
>>> > +  }
>>> > +
>>> > +  coro<bad_promise_nonstatic_member_mismatched_custom_new_operator>
>>> > +
>>> > bad_coroutine_calls_nonstatic_member_mistmatched_custom_new_operator(double)
>>> {
>>> > +    // expected-error at -1 {{no matching function for call to
>>> 'operator new'}}
>>> > +    co_return;
>>> > +  }
>>> > +};
>>> > +
>>> > +struct bad_promise_mismatched_custom_new_operator {
>>> > +  coro<bad_promise_mismatched_custom_new_operator>
>>> get_return_object();
>>> > +  suspend_always initial_suspend();
>>> > +  suspend_always final_suspend();
>>> > +  void return_void();
>>> > +  void unhandled_exception();
>>> > +  // expected-note at +1 {{candidate function not viable: requires 4
>>> > +arguments, but 1 was provided}}
>>> > +  void *operator new(unsigned long, double, float, int); };
>>> > +
>>> > +coro<bad_promise_mismatched_custom_new_operator>
>>> > +bad_coroutine_calls_mismatched_custom_new_operator(double) {
>>> > +  // expected-error at -1 {{no matching function for call to 'operator
>>> > +new'}}
>>> > +  co_return;
>>> > +}
>>> > +
>>> > +struct bad_promise_throwing_custom_new_operator {
>>> > +  static coro<bad_promise_throwing_custom_new_operator>
>>> > +get_return_object_on_allocation_failure();
>>> > +  coro<bad_promise_throwing_custom_new_operator> get_return_object();
>>> > +  suspend_always initial_suspend();
>>> > +  suspend_always final_suspend();
>>> > +  void return_void();
>>> > +  void unhandled_exception();
>>> > +  // expected-error at +1 {{'operator new' is required to have a
>>> > +non-throwing noexcept specification when the promise type declares
>>> > +'get_return_object_on_allocation_failure()'}}
>>> > +  void *operator new(unsigned long, double, float, int); };
>>> > +
>>> > +coro<bad_promise_throwing_custom_new_operator>
>>> > +bad_coroutine_calls_throwing_custom_new_operator(double, float, int)
>>> {
>>> > +  // expected-note at -1 {{call to 'operator new' implicitly required by
>>> > +coroutine function here}}
>>> > +  co_return;
>>> > +}
>>> > +
>>> > +struct good_promise_noexcept_custom_new_operator {
>>> > +  static coro<good_promise_noexcept_custom_new_operator>
>>> > +get_return_object_on_allocation_failure();
>>> > +  coro<good_promise_noexcept_custom_new_operator>
>>> get_return_object();
>>> > +  suspend_always initial_suspend();
>>> > +  suspend_always final_suspend();
>>> > +  void return_void();
>>> > +  void unhandled_exception();
>>> > +  void *operator new(unsigned long, double, float, int) noexcept; };
>>> > +
>>> > +coro<good_promise_noexcept_custom_new_operator>
>>> > +good_coroutine_calls_noexcept_custom_new_operator(double, float,
>>> int) {
>>> > +  co_return;
>>> > +}
>>> > +
>>> >  struct mismatch_gro_type_tag1 {};
>>> >  template<>
>>> >  struct std::experimental::coroutine_traits<int,
>>> mismatch_gro_type_tag1> {
>>> >
>>> >
>>> > _______________________________________________
>>> > cfe-commits mailing list
>>> > cfe-commits at lists.llvm.org
>>> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180216/9ea4b68e/attachment-0001.html>


More information about the cfe-commits mailing list