Skip to content

Commit 39bdf7a

Browse files
dougsonosDoug Wyatt
and
Doug Wyatt
authored
[Clang] SemaFunctionEffects: Fix bug where lambdas produced by template expansion weren't verified. (#116505)
--------- Co-authored-by: Doug Wyatt <[email protected]>
1 parent 78606af commit 39bdf7a

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

clang/lib/Sema/SemaFunctionEffects.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,8 @@ class Analyzer {
807807

808808
auto MaybeAddTemplateNote = [&](const Decl *D) {
809809
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
810-
while (FD != nullptr && FD->isTemplateInstantiation()) {
810+
while (FD != nullptr && FD->isTemplateInstantiation() &&
811+
FD->getPointOfInstantiation().isValid()) {
811812
S.Diag(FD->getPointOfInstantiation(),
812813
diag::note_func_effect_from_template);
813814
FD = FD->getTemplateInstantiationPattern();

clang/lib/Sema/SemaLambda.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,8 +1950,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) {
19501950
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
19511951
ActOnFinishFunctionBody(LSI.CallOperator, Body);
19521952

1953-
maybeAddDeclWithEffects(LSI.CallOperator);
1954-
19551953
return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI);
19561954
}
19571955

@@ -2284,6 +2282,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
22842282
case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
22852283
break;
22862284
}
2285+
maybeAddDeclWithEffects(LSI->CallOperator);
22872286
}
22882287

22892288
return MaybeBindToTemporary(Lambda);

clang/test/Sema/attr-nonblocking-constraints.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,41 @@ void nb9() [[clang::nonblocking]]
144144
expected-note {{in template expansion here}}
145145
}
146146

147+
// Make sure we verify lambdas produced from template expansions.
148+
struct HasTemplatedLambda {
149+
void (*fptr)() [[clang::nonblocking]];
150+
151+
template <typename C>
152+
HasTemplatedLambda(const C&)
153+
: fptr{ []() [[clang::nonblocking]] {
154+
auto* y = new int; // expected-warning {{lambda with 'nonblocking' attribute must not allocate or deallocate memory}}
155+
} }
156+
{}
157+
};
158+
159+
void nb9a()
160+
{
161+
HasTemplatedLambda bad(42);
162+
}
163+
164+
// Templated function and lambda.
165+
template <typename T>
166+
void TemplatedFunc(T x) [[clang::nonblocking]] {
167+
auto* ptr = new T; // expected-warning {{function with 'nonblocking' attribute must not allocate or deallocate memory}}
168+
}
169+
170+
void nb9b() [[clang::nonblocking]] {
171+
TemplatedFunc(42); // expected-note {{in template expansion here}}
172+
173+
auto foo = [](auto x) [[clang::nonblocking]] {
174+
auto* ptr = new int; // expected-warning {{lambda with 'nonblocking' attribute must not allocate or deallocate memory}}
175+
return x;
176+
};
177+
178+
// Note that foo() won't be validated unless instantiated.
179+
foo(42);
180+
}
181+
147182
void nb10(
148183
void (*fp1)(), // expected-note {{function pointer cannot be inferred 'nonblocking'}}
149184
void (*fp2)() [[clang::nonblocking]]

0 commit comments

Comments
 (0)