Skip to content

Commit 52499a2

Browse files
committed
[clang] Check captured variables for noreturn attribute
Anaysis for noreturn attribute now misses the case when an assignment to a variable is made inside a lambda function call. This change fixes that case.
1 parent 6b200e2 commit 52499a2

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,41 @@ struct TransferFunctions : public StmtVisitor<TransferFunctions> {
467467
AllValuesAreNoReturn = false;
468468
}
469469
}
470+
471+
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
472+
if (CE->getOperator() == OO_Call && CE->getNumArgs() > 0) {
473+
Expr *Obj = CE->getArg(0)->IgnoreParenCasts();
474+
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Obj))
475+
Obj = MTE->getSubExpr();
476+
if (auto *DRE = dyn_cast<DeclRefExpr>(Obj)) {
477+
auto *D = dyn_cast<VarDecl>(DRE->getDecl());
478+
if (D->hasInit())
479+
Obj = D->getInit();
480+
}
481+
Visit(Obj);
482+
}
483+
}
484+
485+
void VisitLambdaExpr(LambdaExpr *LE) {
486+
for (const LambdaCapture &Capture : LE->captures())
487+
if (Capture.capturesVariable())
488+
if (const VarDecl *VD = dyn_cast<VarDecl>(Capture.getCapturedVar()))
489+
if (VD == Var)
490+
if (Capture.getCaptureKind() == LCK_ByRef)
491+
AllValuesAreNoReturn = false;
492+
}
493+
494+
void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) {
495+
Visit(MTE->getSubExpr());
496+
}
497+
498+
void VisitExprWithCleanups(FullExpr *FE) {
499+
Visit(FE->getSubExpr());
500+
}
501+
502+
void VisitCXXConstructExpr(CXXConstructExpr *CE) {
503+
Visit(CE->getArg(0));
504+
}
470505
};
471506
} // namespace
472507

clang/test/SemaCXX/noreturn-vars.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,16 @@ extern void abc_02(func_type *);
225225
abc_02(&func_ptr);
226226
func_ptr();
227227
} // expected-warning {{function declared 'noreturn' should not return}}
228+
229+
[[noreturn]] void test_lambda() {
230+
func_type func_ptr = noret;
231+
[&func_ptr]() { func_ptr = ordinary; } ();
232+
func_ptr();
233+
} // expected-warning {{function declared 'noreturn' should not return}}
234+
235+
[[noreturn]] void test_lambda_var(int x) {
236+
func_type func_ptr = noret;
237+
auto LF = [&](){func_ptr = ordinary;};
238+
LF();
239+
func_ptr();
240+
} // expected-warning {{function declared 'noreturn' should not return}}

0 commit comments

Comments
 (0)