Skip to content

Commit d3761e5

Browse files
committed
[Clang] [C++26] Expansion Statements (Part 7)
1 parent 43c4a23 commit d3761e5

File tree

4 files changed

+1092
-0
lines changed

4 files changed

+1092
-0
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6037,6 +6037,12 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
60376037
const VarDecl *VD = dyn_cast_or_null<VarDecl>(D);
60386038
if (VD && !CheckLocalVariableDeclaration(Info, VD))
60396039
return ESR_Failed;
6040+
6041+
if (const auto *ESD = dyn_cast<CXXExpansionStmtDecl>(D)) {
6042+
assert(ESD->getInstantiations() && "not expanded?");
6043+
return EvaluateStmt(Result, Info, ESD->getInstantiations(), Case);
6044+
}
6045+
60406046
// Each declaration initialization is its own full-expression.
60416047
FullExpressionRAII Scope(Info);
60426048
if (!EvaluateDecl(Info, D, /*EvaluateConditionDecl=*/true) &&
@@ -6309,6 +6315,40 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
63096315
return Scope.destroy() ? ESR_Succeeded : ESR_Failed;
63106316
}
63116317

6318+
case Stmt::CXXExpansionStmtInstantiationClass: {
6319+
BlockScopeRAII Scope(Info);
6320+
const auto *Expansion = cast<CXXExpansionStmtInstantiation>(S);
6321+
for (const Stmt *Shared : Expansion->getSharedStmts()) {
6322+
EvalStmtResult ESR = EvaluateStmt(Result, Info, Shared);
6323+
if (ESR != ESR_Succeeded) {
6324+
if (ESR != ESR_Failed && !Scope.destroy())
6325+
return ESR_Failed;
6326+
return ESR;
6327+
}
6328+
}
6329+
6330+
// No need to push an extra scope for these since they're already
6331+
// CompoundStmts.
6332+
EvalStmtResult ESR = ESR_Succeeded;
6333+
for (const Stmt *Instantiation : Expansion->getInstantiations()) {
6334+
ESR = EvaluateStmt(Result, Info, Instantiation);
6335+
if (ESR == ESR_Failed ||
6336+
ShouldPropagateBreakContinue(Info, Expansion, &Scope, ESR))
6337+
return ESR;
6338+
if (ESR != ESR_Continue) {
6339+
// Succeeded here actually means we encountered a 'break'.
6340+
assert(ESR == ESR_Succeeded || ESR == ESR_Returned);
6341+
break;
6342+
}
6343+
}
6344+
6345+
// Map Continue back to Succeeded if we fell off the end of the loop.
6346+
if (ESR == ESR_Continue)
6347+
ESR = ESR_Succeeded;
6348+
6349+
return Scope.destroy() ? ESR : ESR_Failed;
6350+
}
6351+
63126352
case Stmt::SwitchStmtClass:
63136353
return EvaluateSwitch(Result, Info, cast<SwitchStmt>(S));
63146354

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ void CodeGenFunction::EmitDecl(const Decl &D, bool EvaluateConditionDecl) {
143143
// None of these decls require codegen support.
144144
return;
145145

146+
case Decl::CXXExpansionStmt: {
147+
const auto *ESD = cast<CXXExpansionStmtDecl>(&D);
148+
assert(ESD->getInstantiations() && "expansion statement not expanded?");
149+
EmitStmt(ESD->getInstantiations());
150+
return;
151+
}
152+
146153
case Decl::NamespaceAlias:
147154
if (CGDebugInfo *DI = getDebugInfo())
148155
DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D));

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,6 +2027,9 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
20272027
// - using-enum-declaration
20282028
continue;
20292029

2030+
case Decl::CXXExpansionStmt:
2031+
continue;
2032+
20302033
case Decl::Typedef:
20312034
case Decl::TypeAlias: {
20322035
// - typedef declarations and alias-declarations that do not define

0 commit comments

Comments
 (0)