Author: Ben Jackson Date: 2023-12-12T07:30:23+01:00 New Revision: c88d73164a3960c5ef3ff578631f0e765b893809
URL: https://github.com/llvm/llvm-project/commit/c88d73164a3960c5ef3ff578631f0e765b893809 DIFF: https://github.com/llvm/llvm-project/commit/c88d73164a3960c5ef3ff578631f0e765b893809.diff LOG: [clang] Crash when referencing capture in static lambda (#74661) The constant evaluator could try to reference a lambda capture in a static lambda call operator. Static lambdas can't have captures, so we simply abort. Either the lambda needs to be made non-static, or the capture (and reference to it) need to be removed. Fixes: https://github.com/llvm/llvm-project/issues/74608 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ExprConstant.cpp clang/test/Parser/cxx2b-lambdas.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d6719680d2ac70..b62293a33bb9ff 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -870,6 +870,10 @@ Miscellaneous Clang Crashes Fixed `Issue 41302 <https://github.com/llvm/llvm-project/issues/41302>`_ - Fixed a crash when ``-ast-dump=json`` was used for code using class template deduction guides. +- Fixed a crash when a lambda marked as ``static`` referenced a captured + variable in an expression. + `Issue 74608 <https://github.com/llvm/llvm-project/issues/74608>`_ + OpenACC Specific Changes ------------------------ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f035c1419f4c98..f6aeee1a4e935d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8514,14 +8514,24 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return false; if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { + const auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee); + + // Static lambda function call operators can't have captures. We already + // diagnosed this, so bail out here. + if (MD->isStatic()) { + assert(Info.CurrentCall->This == nullptr && + "This should not be set for a static call operator"); + return false; + } + // Start with 'Result' referring to the complete closure object... - if (auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee); - MD->isExplicitObjectMemberFunction()) { + if (MD->isExplicitObjectMemberFunction()) { APValue *RefValue = Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0)); Result.setFrom(Info.Ctx, *RefValue); } else Result = *Info.CurrentCall->This; + // ... then update it to refer to the field of the closure object // that represents the capture. if (!HandleLValueMember(Info, E, Result, FD)) diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp index bb9ed226afffaf..ad975a17b6e476 100644 --- a/clang/test/Parser/cxx2b-lambdas.cpp +++ b/clang/test/Parser/cxx2b-lambdas.cpp @@ -66,3 +66,15 @@ void static_captures() { } }; } + +constexpr auto static_capture_constexpr() { + char n = 'n'; + return [n] static { return n; }(); // expected-error {{a static lambda cannot have any captures}} +} +static_assert(static_capture_constexpr()); // expected-error {{static assertion expression is not an integral constant expression}} + +constexpr auto capture_constexpr() { + char n = 'n'; + return [n] { return n; }(); +} +static_assert(capture_constexpr()); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits