Skip to content

Commit

Permalink
Recommit [Coroutines] Stop supportting std::experimental::coroutine_t…
Browse files Browse the repository at this point in the history
…raits

As we discussed before, we should stop supporting
std::experimental::coroutine_traits in clang17. Now the clang16 is
branched so we can clean them now.

All the removed tests have been duplicated before.
  • Loading branch information
ChuanqiXu9 committed Feb 20, 2023
1 parent fd766ba commit 55900a0
Show file tree
Hide file tree
Showing 46 changed files with 38 additions and 4,730 deletions.
10 changes: 5 additions & 5 deletions clang-tools-extra/clangd/unittests/FindTargetTests.cpp
Expand Up @@ -578,14 +578,14 @@ TEST_F(TargetDeclTest, Coroutine) {
Flags.push_back("-std=c++20");

Code = R"cpp(
namespace std::experimental {
namespace std {
template <typename, typename...> struct coroutine_traits;
template <typename> struct coroutine_handle {
template <typename U>
coroutine_handle(coroutine_handle<U>&&) noexcept;
static coroutine_handle from_address(void* __addr) noexcept;
};
} // namespace std::experimental
} // namespace std
struct executor {};
struct awaitable {};
Expand All @@ -596,20 +596,20 @@ TEST_F(TargetDeclTest, Coroutine) {
struct result_t {
~result_t();
bool await_ready() const noexcept;
void await_suspend(std::experimental::coroutine_handle<void>) noexcept;
void await_suspend(std::coroutine_handle<void>) noexcept;
void await_resume() const noexcept;
};
result_t initial_suspend() noexcept;
result_t final_suspend() noexcept;
result_t await_transform(executor) noexcept;
};
namespace std::experimental {
namespace std {
template <>
struct coroutine_traits<awaitable> {
typedef awaitable_frame promise_type;
};
} // namespace std::experimental
} // namespace std
awaitable foo() {
co_await [[executor]]();
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -53,6 +53,8 @@ C/C++ Language Potentially Breaking Changes
C++ Specific Potentially Breaking Changes
-----------------------------------------
- Clang won't search for coroutine_traits in std::experimental namespace any more.
Clang will only search for std::coroutine_traits for coroutines then.

ABI Changes in This Version
---------------------------
Expand Down
10 changes: 1 addition & 9 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -11283,15 +11283,7 @@ def err_coroutine_invalid_func_context : Error<
"|a consteval function}0">;
def err_implied_coroutine_type_not_found : Error<
"%0 type was not found; include <coroutine> before defining "
"a coroutine; include <experimental/coroutine> if your version "
"of libcxx is less than 14.0">;
def warn_deprecated_coroutine_namespace : Warning<
"support for 'std::experimental::%0' will be removed in Clang 17; "
"use 'std::%0' instead">,
InGroup<DeprecatedExperimentalCoroutine>;
def err_mixed_use_std_and_experimental_namespace_for_coroutine : Error<
"conflicting mixed use of std and std::experimental namespaces for "
"coroutine components">;
"a coroutine">;
def err_implicit_coroutine_std_nothrow_type_not_found : Error<
"std::nothrow was not found; include <new> before defining a coroutine which "
"uses get_return_object_on_allocation_failure()">;
Expand Down
14 changes: 1 addition & 13 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -1143,21 +1143,13 @@ class Sema final {
/// standard library.
LazyDeclPtr StdAlignValT;

/// The C++ "std::experimental" namespace, where the experimental parts
/// of the standard library resides.
NamespaceDecl *StdExperimentalNamespaceCache;

/// The C++ "std::initializer_list" template, which is defined in
/// \<initializer_list>.
ClassTemplateDecl *StdInitializerList;

/// The C++ "std::coroutine_traits" template, which is defined in
/// \<coroutine_traits>
ClassTemplateDecl *StdCoroutineTraitsCache;
/// The namespace where coroutine components are defined. In standard,
/// they are defined in std namespace. And in the previous implementation,
/// they are defined in std::experimental namespace.
NamespaceDecl *CoroTraitsNamespaceCache;

/// The C++ "type_info" declaration, which is defined in \<typeinfo>.
RecordDecl *CXXTypeInfoDecl;
Expand Down Expand Up @@ -6092,9 +6084,6 @@ class Sema final {
NamespaceDecl *getStdNamespace() const;
NamespaceDecl *getOrCreateStdNamespace();

NamespaceDecl *lookupStdExperimentalNamespace();
NamespaceDecl *getCachedCoroNamespace() { return CoroTraitsNamespaceCache; }

CXXRecordDecl *getStdBadAlloc() const;
EnumDecl *getStdAlignValT() const;

Expand Down Expand Up @@ -10911,8 +10900,7 @@ class Sema final {
/// Lookup 'coroutine_traits' in std namespace and std::experimental
/// namespace. The namespace found is recorded in Namespace.
ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
SourceLocation FuncLoc,
NamespaceDecl *&Namespace);
SourceLocation FuncLoc);
/// Check that the expression co_await promise.final_suspend() shall not be
/// potentially-throwing.
bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/Sema.cpp
Expand Up @@ -202,7 +202,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
IsBuildingRecoveryCallExpr(false), LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
StdInitializerList(nullptr),
StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr),
MSVCGuidDecl(nullptr), StdSourceLocationImplDecl(nullptr),
NSNumberDecl(nullptr), NSValueDecl(nullptr), NSStringDecl(nullptr),
Expand Down
93 changes: 28 additions & 65 deletions clang/lib/Sema/SemaCoroutine.cpp
Expand Up @@ -54,12 +54,10 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
const FunctionProtoType *FnType = FD->getType()->castAs<FunctionProtoType>();
const SourceLocation FuncLoc = FD->getLocation();

NamespaceDecl *CoroNamespace = nullptr;
ClassTemplateDecl *CoroTraits =
S.lookupCoroutineTraits(KwLoc, FuncLoc, CoroNamespace);
if (!CoroTraits) {
S.lookupCoroutineTraits(KwLoc, FuncLoc);
if (!CoroTraits)
return QualType();
}

// Form template argument list for coroutine_traits<R, P1, P2, ...> according
// to [dcl.fct.def.coroutine]3
Expand Down Expand Up @@ -117,7 +115,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
QualType PromiseType = S.Context.getTypeDeclType(Promise);

auto buildElaboratedType = [&]() {
auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, CoroNamespace);
auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace());
NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
CoroTrait.getTypePtr());
return S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
Expand All @@ -142,7 +140,7 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
if (PromiseType.isNull())
return QualType();

NamespaceDecl *CoroNamespace = S.getCachedCoroNamespace();
NamespaceDecl *CoroNamespace = S.getStdNamespace();
assert(CoroNamespace && "Should already be diagnosed");

LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
Expand Down Expand Up @@ -324,7 +322,7 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
}

// See if return type is coroutine-handle and if so, invoke builtin coro-resume
// on its address. This is to enable experimental support for coroutine-handle
// on its address. This is to enable the support for coroutine-handle
// returning await_suspend that results in a guaranteed tail call to the target
// coroutine.
static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
Expand Down Expand Up @@ -432,7 +430,7 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
// type Z.
QualType RetType = AwaitSuspend->getCallReturnType(S.Context);

// Experimental support for coroutine_handle returning await_suspend.
// Support for coroutine_handle returning await_suspend.
if (Expr *TailCallSuspend =
maybeTailCall(S, RetType, AwaitSuspend, Loc))
// Note that we don't wrap the expression with ExprWithCleanups here
Expand Down Expand Up @@ -1842,67 +1840,32 @@ StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
}

ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
SourceLocation FuncLoc,
NamespaceDecl *&Namespace) {
if (!StdCoroutineTraitsCache) {
// Because coroutines moved from std::experimental in the TS to std in
// C++20, we look in both places to give users time to transition their
// TS-specific code to C++20. Diagnostics are given when the TS usage is
// discovered.
// TODO: Become stricter when <experimental/coroutine> is removed.

IdentifierInfo const &TraitIdent =
PP.getIdentifierTable().get("coroutine_traits");

NamespaceDecl *StdSpace = getStdNamespace();
LookupResult ResStd(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
bool InStd = StdSpace && LookupQualifiedName(ResStd, StdSpace);

NamespaceDecl *ExpSpace = lookupStdExperimentalNamespace();
LookupResult ResExp(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
bool InExp = ExpSpace && LookupQualifiedName(ResExp, ExpSpace);

if (!InStd && !InExp) {
// The goggles, they found nothing!
Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
<< "std::coroutine_traits";
return nullptr;
}
SourceLocation FuncLoc) {
if (StdCoroutineTraitsCache)
return StdCoroutineTraitsCache;

// Prefer ::std to std::experimental.
LookupResult &Result = InStd ? ResStd : ResExp;
CoroTraitsNamespaceCache = InStd ? StdSpace : ExpSpace;
IdentifierInfo const &TraitIdent =
PP.getIdentifierTable().get("coroutine_traits");

// coroutine_traits is required to be a class template.
StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>();
if (!StdCoroutineTraitsCache) {
Result.suppressDiagnostics();
NamedDecl *Found = *Result.begin();
Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
return nullptr;
}
NamespaceDecl *StdSpace = getStdNamespace();
LookupResult Result(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
bool Found = StdSpace && LookupQualifiedName(Result, StdSpace);

if (InExp) {
// Found in std::experimental
Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
<< "coroutine_traits";
ResExp.suppressDiagnostics();
NamedDecl *Found = *ResExp.begin();
Diag(Found->getLocation(), diag::note_entity_declared_at) << Found;

if (InStd &&
StdCoroutineTraitsCache != ResExp.getAsSingle<ClassTemplateDecl>()) {
// Also found something different in std
Diag(KwLoc,
diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
Diag(StdCoroutineTraitsCache->getLocation(),
diag::note_entity_declared_at)
<< StdCoroutineTraitsCache;
if (!Found) {
// The goggles, we found nothing!
Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
<< "std::coroutine_traits";
return nullptr;
}

return nullptr;
}
}
// coroutine_traits is required to be a class template.
StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>();
if (!StdCoroutineTraitsCache) {
Result.suppressDiagnostics();
NamedDecl *Found = *Result.begin();
Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
return nullptr;
}
Namespace = CoroTraitsNamespaceCache;

return StdCoroutineTraitsCache;
}
15 changes: 0 additions & 15 deletions clang/lib/Sema/SemaDeclCXX.cpp
Expand Up @@ -11386,21 +11386,6 @@ NamespaceDecl *Sema::getStdNamespace() const {
return cast_or_null<NamespaceDecl>(
StdNamespace.get(Context.getExternalSource()));
}

NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
if (!StdExperimentalNamespaceCache) {
if (auto Std = getStdNamespace()) {
LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"),
SourceLocation(), LookupNamespaceName);
if (!LookupQualifiedName(Result, Std) ||
!(StdExperimentalNamespaceCache =
Result.getAsSingle<NamespaceDecl>()))
Result.suppressDiagnostics();
}
}
return StdExperimentalNamespaceCache;
}

namespace {

enum UnsupportedSTLSelect {
Expand Down
109 changes: 0 additions & 109 deletions clang/test/AST/coroutine-locals-cleanup-exp-namespace.cpp

This file was deleted.

0 comments on commit 55900a0

Please sign in to comment.