Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,8 @@ class Analyzer {

auto MaybeAddTemplateNote = [&](const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
while (FD != nullptr && FD->isTemplateInstantiation()) {
while (FD != nullptr && FD->isTemplateInstantiation() &&
FD->getPointOfInstantiation().isValid()) {
S.Diag(FD->getPointOfInstantiation(),
diag::note_func_effect_from_template);
FD = FD->getTemplateInstantiationPattern();
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1950,8 +1950,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) {
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
ActOnFinishFunctionBody(LSI.CallOperator, Body);

maybeAddDeclWithEffects(LSI.CallOperator);

return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI);
}

Expand Down Expand Up @@ -2284,6 +2282,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
break;
}
maybeAddDeclWithEffects(LSI->CallOperator);
}

return MaybeBindToTemporary(Lambda);
Expand Down
35 changes: 35 additions & 0 deletions clang/test/Sema/attr-nonblocking-constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,41 @@ void nb9() [[clang::nonblocking]]
expected-note {{in template expansion here}}
}

// Make sure we verify lambdas produced from template expansions.
struct HasTemplatedLambda {
void (*fptr)() [[clang::nonblocking]];

template <typename C>
HasTemplatedLambda(const C&)
: fptr{ []() [[clang::nonblocking]] {
auto* y = new int; // expected-warning {{lambda with 'nonblocking' attribute must not allocate or deallocate memory}}
} }
{}
};

void nb9a()
{
HasTemplatedLambda bad(42);
}

// Templated function and lambda.
template <typename T>
void TemplatedFunc(T x) [[clang::nonblocking]] {
auto* ptr = new T; // expected-warning {{function with 'nonblocking' attribute must not allocate or deallocate memory}}
}

void nb9b() [[clang::nonblocking]] {
TemplatedFunc(42); // expected-note {{in template expansion here}}

auto foo = [](auto x) [[clang::nonblocking]] {
auto* ptr = new int; // expected-warning {{lambda with 'nonblocking' attribute must not allocate or deallocate memory}}
return x;
};

// Note that foo() won't be validated unless instantiated.
foo(42);
}

void nb10(
void (*fp1)(), // expected-note {{function pointer cannot be inferred 'nonblocking'}}
void (*fp2)() [[clang::nonblocking]]
Expand Down
Loading