Author: Aaron Ballman Date: 2023-10-26T11:59:17-04:00 New Revision: 09e8ef975d9970560b893f79ec283f69ea8db953
URL: https://github.com/llvm/llvm-project/commit/09e8ef975d9970560b893f79ec283f69ea8db953 DIFF: https://github.com/llvm/llvm-project/commit/09e8ef975d9970560b893f79ec283f69ea8db953.diff LOG: Diagnose use of VLAs in a coroutine (#70341) Fixes https://github.com/llvm/llvm-project/issues/65858 Added: clang/test/SemaCXX/coroutine-vla.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/ScopeInfo.h clang/lib/Sema/SemaCoroutine.cpp clang/lib/Sema/SemaType.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 074116d2edf9f99..7238386231e1a28 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -636,6 +636,10 @@ Bug Fixes to C++ Support (`#46200 <https://github.com/llvm/llvm-project/issues/46200>`_) (`#57812 <https://github.com/llvm/llvm-project/issues/57812>`_) +- Diagnose use of a variable-length array in a coroutine. The design of + coroutines is such that it is not possible to support VLA use. Fixes: + (`#65858 <https://github.com/llvm/llvm-project/issues/65858>`_) + - Fix bug where we were overriding zero-initialization of class members when default initializing a base class in a constant expression context. Fixes: (`#69890 <https://github.com/llvm/llvm-project/issues/69890>`_) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a673ce726d6c220..453bd8a9a340425 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -166,6 +166,8 @@ def ext_vla_folded_to_constant : ExtWarn< InGroup<GNUFoldingConstant>; def err_vla_unsupported : Error< "variable length arrays are not supported for %select{the current target|'%1'}0">; +def err_vla_in_coroutine_unsupported : Error< + "variable length arrays in a coroutine are not supported">; def note_vla_unsupported : Note< "variable length arrays are not supported for the current target">; diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 02b22af89ff035d..b2f6e3289f41fce 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -189,6 +189,9 @@ class FunctionScopeInfo { /// First SEH '__try' statement in the current function. SourceLocation FirstSEHTryLoc; + /// First use of a VLA within the current function. + SourceLocation FirstVLALoc; + private: /// Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; @@ -473,6 +476,11 @@ class FunctionScopeInfo { FirstSEHTryLoc = TryLoc; } + void setHasVLA(SourceLocation VLALoc) { + if (FirstVLALoc.isInvalid()) + FirstVLALoc = VLALoc; + } + bool NeedsScopeChecking() const { return !HasDroppedStmt && (HasIndirectGoto || HasMustTail || (HasBranchProtectedScope && HasBranchIntoScope)); diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index d2b0922a4bb9c4c..cfaa93fbea4dd37 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -1198,6 +1198,11 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) { if (FD->hasAttr<AlwaysInlineAttr>()) Diag(FD->getLocation(), diag::warn_always_inline_coroutine); + // The design of coroutines means we cannot allow use of VLAs within one, so + // diagnose if we've seen a VLA in the body of this function. + if (Fn->FirstVLALoc.isValid()) + Diag(Fn->FirstVLALoc, diag::err_vla_in_coroutine_unsupported); + // [stmt.return.coroutine]p1: // A coroutine shall not enclose a return statement ([stmt.return]). if (Fn->FirstReturnLoc.isValid()) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 28b81c1768a3004..dea77fae4cadb59 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2706,12 +2706,18 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } } - if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) { - // CUDA device code and some other targets don't support VLAs. - bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice); - targetDiag(Loc, - IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported) - << (IsCUDADevice ? CurrentCUDATarget() : 0); + if (T->isVariableArrayType()) { + if (!Context.getTargetInfo().isVLASupported()) { + // CUDA device code and some other targets don't support VLAs. + bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice); + targetDiag(Loc, + IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported) + << (IsCUDADevice ? CurrentCUDATarget() : 0); + } else if (sema::FunctionScopeInfo *FSI = getCurFunction()) { + // VLAs are supported on this target, but we may need to do delayed + // checking that the VLA is not being used within a coroutine. + FSI->setHasVLA(Loc); + } } // If this is not C99, diagnose array size modifiers on non-VLAs. diff --git a/clang/test/SemaCXX/coroutine-vla.cpp b/clang/test/SemaCXX/coroutine-vla.cpp new file mode 100644 index 000000000000000..176e35f346e2b45 --- /dev/null +++ b/clang/test/SemaCXX/coroutine-vla.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -Wno-vla-cxx-extension -verify +#include "Inputs/std-coroutine.h" + +struct promise; + +struct coroutine : std::coroutine_handle<promise> { + using promise_type = ::promise; +}; + +struct promise +{ + coroutine get_return_object(); + std::suspend_always initial_suspend() noexcept; + std::suspend_always final_suspend() noexcept; + void return_void(); + void unhandled_exception(); +}; + +coroutine foo(int n) { + int array[n]; // expected-error {{variable length arrays in a coroutine are not supported}} + co_return; +} + +void lambda() { + [](int n) -> coroutine { + int array[n]; // expected-error {{variable length arrays in a coroutine are not supported}} + co_return; + }(10); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits