Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -13,6 +13,7 @@ #include "CoroutineStmtBuilder.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/Lex/Preprocessor.h" @@ -43,9 +44,10 @@ /// Look up the std::coroutine_traits<...>::promise_type for the given /// function type. -static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, +static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, SourceLocation KwLoc, SourceLocation FuncLoc) { + const FunctionProtoType *FnType = FD->getType()->castAs(); // FIXME: Cache std::coroutine_traits once we've found it. NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); if (!StdExp) { @@ -76,8 +78,15 @@ Args.addArgument(TemplateArgumentLoc( TemplateArgument(FnType->getReturnType()), S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), KwLoc))); - // FIXME: If the function is a non-static member function, add the type + // If the function is a non-static member function, add the type // of the implicit object parameter before the formal parameters. + if (auto *MD = dyn_cast_or_null(FD)) { + if (MD->isInstance()) { + QualType T = MD->getThisType(S.Context); + Args.addArgument(TemplateArgumentLoc( + TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc))); + } + } for (QualType T : FnType->getParamTypes()) Args.addArgument(TemplateArgumentLoc( TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, KwLoc))); @@ -424,12 +433,17 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { assert(isa(CurContext) && "not in a function scope"); auto *FD = cast(CurContext); + bool IsThisDependentType = [&] { + if (auto *MD = dyn_cast_or_null(FD)) + return MD->isInstance() && MD->getThisType(Context)->isDependentType(); + else + return false; + }(); QualType T = - FD->getType()->isDependentType() + FD->getType()->isDependentType() || IsThisDependentType ? Context.DependentTy - : lookupPromiseType(*this, FD->getType()->castAs(), - Loc, FD->getLocation()); + : lookupPromiseType(*this, FD, Loc, FD->getLocation()); if (T.isNull()) return nullptr; Index: test/SemaCXX/coroutine-nonstatic-member-function.cpp =================================================================== --- /dev/null +++ test/SemaCXX/coroutine-nonstatic-member-function.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++1z -fcoroutines-ts -fsyntax-only -Wall -Wextra -Wuninitialized -fblocks +#include "Inputs/std-coroutine.h" + +using namespace std::experimental; + +struct coro_t {}; + +struct coro_promise_type { + coro_t get_return_object() { return {}; } + suspend_never initial_suspend() { return {}; } + suspend_never final_suspend() { return {}; } + void return_void() {} + static void unhandled_exception() {} +}; + +struct C { + coro_t f(); +}; + +namespace std::experimental { + template<> + struct coroutine_traits { + using promise_type = coro_promise_type; + }; +} + +coro_t C::f() { + co_return; +} + +int main() { + C c; + c.f(); +}