Skip to content

[Clang] Prevent assignment to captured structured bindings inside immutable lambda #120849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
[Clang] Refactored to use common code and updated variables name
  • Loading branch information
TilakChad committed Dec 23, 2024
commit fda25e8e97ffb6f5038c73e204114e81fc862c5c
32 changes: 17 additions & 15 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13291,22 +13291,24 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
if (!DRE) return NCCK_None;
if (!DRE->refersToEnclosingVariableOrCapture()) return NCCK_None;

// The declaration must be a variable which is not declared 'const'.
VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl());
if (!var) {
// Bindings also can be captured by lambda in C++
BindingDecl *binding = dyn_cast<BindingDecl>(DRE->getDecl());
if (!binding || binding->getType().isConstQualified())
return NCCK_None;
ValueDecl *Value = dyn_cast<ValueDecl>(DRE->getDecl());

assert(S.getLangOpts().CPlusPlus && "BindingDecl outside of C++?");
assert(!isa<BlockDecl>(binding->getDeclContext()));
// The declaration must be a value which is not declared 'const'.
if (!Value || Value->getType().isConstQualified())
return NCCK_None;

BindingDecl *Binding = dyn_cast<BindingDecl>(Value);
if (Binding) {
assert(S.getLangOpts().CPlusPlus && "BindingDecl outside of C++?");
assert(!isa<BlockDecl>(Binding->getDeclContext()));
return NCCK_Lambda;
}

if (var->getType().isConstQualified()) return NCCK_None;
assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
VarDecl *Var = dyn_cast<VarDecl>(Value);
if (!Var)
return NCCK_None;

assert(Var->hasLocalStorage() && "capture added 'const' to non-local?");

// Decide whether the first capture was for a block or a lambda.
DeclContext *DC = S.CurContext, *Prev = nullptr;
Expand All @@ -13315,16 +13317,16 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
// For init-capture, it is possible that the variable belongs to the
// template pattern of the current context.
if (auto *FD = dyn_cast<FunctionDecl>(DC))
if (var->isInitCapture() &&
FD->getTemplateInstantiationPattern() == var->getDeclContext())
if (Var->isInitCapture() &&
FD->getTemplateInstantiationPattern() == Var->getDeclContext())
break;
if (DC == var->getDeclContext())
if (DC == Var->getDeclContext())
break;
Prev = DC;
DC = DC->getParent();
}
// Unless we have an init-capture, we've gone one step too far.
if (!var->isInitCapture())
if (!Var->isInitCapture())
DC = Prev;
return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
}
Expand Down
Loading