aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
authorYounan Zhang <zyn7109@gmail.com>2025-03-11 15:41:56 +0800
committerGitHub <noreply@github.com>2025-03-11 15:41:56 +0800
commitf4218753ad93dd44b019e38bae61dceb93514aee (patch)
treed788b45565304a61352db297810417780096af63 /clang/lib/CodeGen/CGDecl.cpp
parentf120b0d6d2629e226e6fa75974fbd17f46206bca (diff)
downloadllvm-f4218753ad93dd44b019e38bae61dceb93514aee.zip
llvm-f4218753ad93dd44b019e38bae61dceb93514aee.tar.gz
llvm-f4218753ad93dd44b019e38bae61dceb93514aee.tar.bz2
[Clang] Implement P0963R3 "Structured binding declaration as a condition" (#130228)
This implements the R2 semantics of P0963. The R1 semantics, as outlined in the paper, were introduced in Clang 6. In addition to that, the paper proposes swapping the evaluation order of condition expressions and the initialization of binding declarations (i.e. std::tuple-like decompositions).
Diffstat (limited to 'clang/lib/CodeGen/CGDecl.cpp')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp18
1 files changed, 12 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 3ad9ebf..eab1ebf 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -48,7 +48,7 @@ using namespace CodeGen;
static_assert(clang::Sema::MaximumAlignment <= llvm::Value::MaximumAlignment,
"Clang max alignment greater than what LLVM supports?");
-void CodeGenFunction::EmitDecl(const Decl &D) {
+void CodeGenFunction::EmitDecl(const Decl &D, bool EvaluateConditionDecl) {
switch (D.getKind()) {
case Decl::BuiltinTemplate:
case Decl::TranslationUnit:
@@ -152,7 +152,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
return;
case Decl::UsingPack:
for (auto *Using : cast<UsingPackDecl>(D).expansions())
- EmitDecl(*Using);
+ EmitDecl(*Using, /*EvaluateConditionDecl=*/EvaluateConditionDecl);
return;
case Decl::UsingDirective: // using namespace X; [C++]
if (CGDebugInfo *DI = getDebugInfo())
@@ -164,10 +164,8 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
assert(VD.isLocalVarDecl() &&
"Should not see file-scope variables inside a function!");
EmitVarDecl(VD);
- if (auto *DD = dyn_cast<DecompositionDecl>(&VD))
- for (auto *B : DD->flat_bindings())
- if (auto *HD = B->getHoldingVar())
- EmitVarDecl(*HD);
+ if (EvaluateConditionDecl)
+ MaybeEmitDeferredVarDeclInit(&VD);
return;
}
@@ -2059,6 +2057,14 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
/*IsAutoInit=*/false);
}
+void CodeGenFunction::MaybeEmitDeferredVarDeclInit(const VarDecl *VD) {
+ if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
+ for (auto *B : DD->flat_bindings())
+ if (auto *HD = B->getHoldingVar())
+ EmitVarDecl(*HD);
+ }
+}
+
/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location. The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily