[clang] [Clang] [Sema] Don't crash on unexpanded pack in invalid block literal (PR #110762)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 2 18:46:46 PDT 2024
https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/110762
>From a471d32c94bfcbd10291053bb6ce0541ea2e626c Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 2 Oct 2024 00:59:37 +0200
Subject: [PATCH 1/4] [Clang] [Sema] Don't crash on unexpanded pack in invalid
block literal
---
clang/docs/ReleaseNotes.rst | 2 +
clang/include/clang/Sema/ScopeInfo.h | 10 ++++
clang/lib/Sema/Sema.cpp | 8 +++-
clang/lib/Sema/SemaExpr.cpp | 11 +++++
clang/test/SemaCXX/block-unexpanded-pack.cpp | 48 ++++++++++++++++++++
5 files changed, 77 insertions(+), 2 deletions(-)
create mode 100644 clang/test/SemaCXX/block-unexpanded-pack.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 34d2b584274a5f..ed4a7affcf6919 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -457,6 +457,8 @@ Bug Fixes to C++ Support
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
- Fixed a bug in constraint expression comparison where the ``sizeof...`` expression was not handled properly
in certain friend declarations. (#GH93099)
+- Clang no longer crashes when a lambda contains an invalid block declaration that contains an unexpanded
+ parameter pack. (#GH109148)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 700e361ef83f13..a943f2edc51fba 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -793,6 +793,16 @@ class BlockScopeInfo final : public CapturingScopeInfo {
/// Its return type may be BuiltinType::Dependent.
QualType FunctionType;
+ /// We sometimes diagnose unexpanded parameter packs in block literals,
+ /// but an error while the block is parsed causes it to be discarded, in
+ /// which case we need to reset the enclosing lambda's
+ /// ContainsUnexpandedParameterPackFlag.
+ ///
+ /// Note: This issue does not exist with lambdas because they push a new
+ /// LambdaScopeInfo, so if the expression is discarded, the 'enclosing
+ /// lambda' is discarded along with it.
+ bool EnclosingLambdaContainsUnexpandedParameterPack = false;
+
BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
: CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
TheScope(BlockScope) {
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 4be7dfbc293927..1e72910da27d5e 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2187,9 +2187,13 @@ void Sema::PushFunctionScope() {
}
void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
- FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
- BlockScope, Block));
+ auto *BSI = new BlockScopeInfo(getDiagnostics(), BlockScope, Block);
+ FunctionScopes.push_back(BSI);
CapturingFunctionScopes++;
+
+ LambdaScopeInfo *Enclosing = getEnclosingLambda();
+ BSI->EnclosingLambdaContainsUnexpandedParameterPack =
+ Enclosing && Enclosing->ContainsUnexpandedParameterPack;
}
LambdaScopeInfo *Sema::PushLambdaScope() {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2db9d1fc69ed1e..29745b1f3edff1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16187,6 +16187,15 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
}
void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
+ // If the enclosing lambda did not contain any unexpanded parameter
+ // packs before this block, then reset the unexpanded parameter pack
+ // flag, otherwise, we might end up crashing trying to find a pack
+ // that we are about to discard along with the rest of the block.
+ if (!getCurBlock()->EnclosingLambdaContainsUnexpandedParameterPack) {
+ LambdaScopeInfo *L = getEnclosingLambda();
+ if (L) L->ContainsUnexpandedParameterPack = false;
+ }
+
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -16379,6 +16388,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (getCurFunction())
getCurFunction()->addBlock(BD);
+ // This can happen if the block's return type is deduced, but
+ // the return expression is invalid.
if (BD->isInvalidDecl())
return CreateRecoveryExpr(Result->getBeginLoc(), Result->getEndLoc(),
{Result}, Result->getType());
diff --git a/clang/test/SemaCXX/block-unexpanded-pack.cpp b/clang/test/SemaCXX/block-unexpanded-pack.cpp
new file mode 100644
index 00000000000000..c1435b8e314a81
--- /dev/null
+++ b/clang/test/SemaCXX/block-unexpanded-pack.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -fsyntax-only -verify %s -frecovery-ast -frecovery-ast-type
+
+// This checks that when a block is discarded, the enclosing lambda’s
+// unexpanded parameter pack flag is reset to what it was before the
+// block is parsed so we don't crash when trying to diagnose unexpanded
+// parameter packs in the lambda.
+
+template <typename ...Ts>
+void gh109148() {
+ (^Ts); // expected-error {{expected expression}} expected-error {{unexpanded parameter pack 'Ts'}}
+
+ [] {
+ (^Ts); // expected-error {{expected expression}}
+ ^Ts; // expected-error {{expected expression}}
+ ^(Ts); // expected-error {{expected expression}}
+ ^ Ts); // expected-error {{expected expression}}
+ };
+
+ ([] {
+ (^Ts); // expected-error {{expected expression}}
+ ^Ts; // expected-error {{expected expression}}
+ ^(Ts); // expected-error {{expected expression}}
+ ^ Ts); // expected-error {{expected expression}}
+ }, ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}}
+
+ [] { // expected-error {{unexpanded parameter pack 'Ts'}}
+ ^ (Ts) {};
+ };
+
+ [] { // expected-error {{unexpanded parameter pack 'Ts'}}
+ (void) ^ { Ts x; };
+ };
+
+ [] { // expected-error {{unexpanded parameter pack 'Ts'}}
+ Ts s;
+ (^Ts); // expected-error {{expected expression}}
+ };
+
+ ([] {
+ Ts s;
+ (^Ts); // expected-error {{expected expression}}
+ }, ...)
+
+ [] { // expected-error {{unexpanded parameter pack 'Ts'}}
+ ^ { Ts s; return not_defined; }; // expected-error {{use of undeclared identifier 'not_defined'}}
+ };
+}
>From 69ce3193bfd0a507f6eac6336bef599c2d6d53e9 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 2 Oct 2024 01:21:56 +0200
Subject: [PATCH 2/4] clang-format
---
clang/lib/Sema/SemaExpr.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 29745b1f3edff1..d1c91296a9d468 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16193,7 +16193,8 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
// that we are about to discard along with the rest of the block.
if (!getCurBlock()->EnclosingLambdaContainsUnexpandedParameterPack) {
LambdaScopeInfo *L = getEnclosingLambda();
- if (L) L->ContainsUnexpandedParameterPack = false;
+ if (L)
+ L->ContainsUnexpandedParameterPack = false;
}
// Leave the expression-evaluation context.
>From 48ca9d63084310087b3d86878b9ae100ccdc3f52 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 2 Oct 2024 01:22:59 +0200
Subject: [PATCH 3/4] Fix typo in comment
---
clang/include/clang/Sema/ScopeInfo.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index a943f2edc51fba..3bad1e3bad4312 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -794,9 +794,9 @@ class BlockScopeInfo final : public CapturingScopeInfo {
QualType FunctionType;
/// We sometimes diagnose unexpanded parameter packs in block literals,
- /// but an error while the block is parsed causes it to be discarded, in
- /// which case we need to reset the enclosing lambda's
- /// ContainsUnexpandedParameterPackFlag.
+ /// but an error while the block is parsed can cause it to be discarded,
+ /// in which case we need to reset the enclosing lambda's
+ /// ContainsUnexpandedParameterPack flag.
///
/// Note: This issue does not exist with lambdas because they push a new
/// LambdaScopeInfo, so if the expression is discarded, the 'enclosing
>From 06ac9be526b8c9046d9be147f7b6fb733096b7ff Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 3 Oct 2024 03:46:33 +0200
Subject: [PATCH 4/4] Add missing semicolon in test
---
clang/test/SemaCXX/block-unexpanded-pack.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/SemaCXX/block-unexpanded-pack.cpp b/clang/test/SemaCXX/block-unexpanded-pack.cpp
index c1435b8e314a81..ce88db236d437c 100644
--- a/clang/test/SemaCXX/block-unexpanded-pack.cpp
+++ b/clang/test/SemaCXX/block-unexpanded-pack.cpp
@@ -40,7 +40,7 @@ void gh109148() {
([] {
Ts s;
(^Ts); // expected-error {{expected expression}}
- }, ...)
+ }, ...);
[] { // expected-error {{unexpanded parameter pack 'Ts'}}
^ { Ts s; return not_defined; }; // expected-error {{use of undeclared identifier 'not_defined'}}
More information about the cfe-commits
mailing list