From: Ted Kremenek Date: Thu, 12 Apr 2012 20:34:52 +0000 (+0000) Subject: Include lambda capture init expressions in CFG. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83748e2f41ea0ac7c954946feb5da9ccc6ab8bec;p=clang Include lambda capture init expressions in CFG. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154611 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 97d494d7e9..d1334a5431 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -342,6 +342,7 @@ private: CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); CFGBlock *VisitLabelStmt(LabelStmt *L); + CFGBlock *VisitLambdaExpr(LambdaExpr *L); CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); @@ -985,7 +986,6 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { return VisitBinaryOperator(cast(S), asc); case Stmt::BlockExprClass: - case Stmt::LambdaExprClass: return VisitNoRecurse(cast(S), asc); case Stmt::BreakStmtClass: @@ -1066,6 +1066,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::LabelStmtClass: return VisitLabelStmt(cast(S)); + case Stmt::LambdaExprClass: + return VisitLambdaExpr(cast(S), asc); + case Stmt::MemberExprClass: return VisitMemberExpr(cast(S), asc); @@ -1718,6 +1721,19 @@ CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { return LabelBlock; } +CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { + CFGBlock *LastBlock = VisitNoRecurse(E, asc); + for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), + et = E->capture_init_end(); it != et; ++it) { + if (Expr *Init = *it) { + CFGBlock *Tmp = Visit(Init); + if (Tmp != 0) + LastBlock = Tmp; + } + } + return LastBlock; +} + CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { // Goto is a control-flow statement. Thus we stop processing the current // block and create a new one. diff --git a/test/Analysis/lambdas.cpp b/test/Analysis/lambdas.cpp new file mode 100644 index 0000000000..77b36c42cf --- /dev/null +++ b/test/Analysis/lambdas.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -analyze -analyzer-checker=debug.DumpCFG %s > %t 2>&1 +// RUN: FileCheck --input-file=%t %s + +struct X { X(const X&); }; +void f(X x) { (void) [x]{}; } + +// CHECK: [B2 (ENTRY)] +// CHECK: Succs (1): B1 +// CHECK: [B1] +// CHECK: 1: x +// CHECK: 2: [B1.1] (ImplicitCastExpr, NoOp, const struct X) +// CHECK: 3: [B1.2] (CXXConstructExpr, struct X) +// CHECK: 4: [=x] { +// CHECK: } +// CHECK: 5: (void)[B1.4] (CStyleCastExpr, ToVoid, void) +// CHECK: Preds (1): B2 +// CHECK: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK: Preds (1): B1 +