diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1283,8 +1283,8 @@ // C++ Coroutines defm coroutines : BoolFOption<"coroutines", LangOpts<"Coroutines">, Default, - PosFlag, - NegFlag>; + PosFlag, + NegFlag>; defm coro_aligned_allocation : BoolFOption<"coro-aligned-allocation", LangOpts<"CoroAlignedAllocation">, DefaultFalse, diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -229,6 +229,8 @@ if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015)) return KS_Disabled; + if (LangOpts.CPlusPlus20 && !LangOpts.Coroutines && (Flags & KEYCOROUTINES)) + return KS_Disabled; KeywordStatus CurStatus = KS_Unknown; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3803,6 +3803,8 @@ // the sequence "<::" will be unconditionally treated as "[:". // Cf. Lexer::LexTokenInternal. LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; + // Do not miss coroutine keywords. + LangOpts.Coroutines = LexingStd >= FormatStyle::LS_Cpp20; LangOpts.LineComment = 1; bool AlternativeOperators = Style.isCpp(); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -701,12 +701,14 @@ Builder.defineMacro("__cpp_consteval", "202211L"); Builder.defineMacro("__cpp_constexpr_dynamic_alloc", "201907L"); Builder.defineMacro("__cpp_constinit", "201907L"); - Builder.defineMacro("__cpp_impl_coroutine", "201902L"); + // __cpp_impl_coroutine is below as it can be enabled with `-fcoroutines`. Builder.defineMacro("__cpp_designated_initializers", "201707L"); Builder.defineMacro("__cpp_impl_three_way_comparison", "201907L"); //Builder.defineMacro("__cpp_modules", "201907L"); Builder.defineMacro("__cpp_using_enum", "201907L"); } + if (LangOpts.Coroutines) + Builder.defineMacro("__cpp_impl_coroutine", "201902L"); // C++23 features. if (LangOpts.CPlusPlus23) { Builder.defineMacro("__cpp_implicit_move", "202011L"); diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -2,7 +2,8 @@ // found at http://wg21.link/coroutines. // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s -fcxx-exceptions -fexceptions -Wunused-result -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -fcxx-exceptions -fexceptions -Wunused-result +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20,cxx20_23 %s -fcxx-exceptions -fexceptions -Wunused-result +// RUN: %clang_cc1 -std=c++17 -fcoroutines -fsyntax-only -verify=expected,cxx14_20 %s -fcxx-exceptions -fexceptions -Wunused-result void no_coroutine_traits_bad_arg_await() { co_await a; // expected-error {{include }} diff --git a/clang/test/SemaCXX/cxx20-disabled-coroutines.cpp b/clang/test/SemaCXX/cxx20-disabled-coroutines.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/cxx20-disabled-coroutines.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 -fno-coroutines %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -fno-coroutines %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 -fno-coroutines %s + +#if __cpp_impl_coroutine +#else +// expected-error@+1 {{coroutines disabled}} +#error "coroutines disabled" +#endif + +int co_await; +int co_return; +int co_yield; \ No newline at end of file