]> granicus.if.org Git - clang/commitdiff
Include lambda capture init expressions in CFG.
authorTed Kremenek <kremenek@apple.com>
Thu, 12 Apr 2012 20:34:52 +0000 (20:34 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 12 Apr 2012 20:34:52 +0000 (20:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154611 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
test/Analysis/lambdas.cpp [new file with mode: 0644]

index 97d494d7e9d75f1047690ff1d6c44b447fdaea66..d1334a54319131961362b700ad43a9eed5c83fd9 100644 (file)
@@ -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<BinaryOperator>(S), asc);
 
     case Stmt::BlockExprClass:
-    case Stmt::LambdaExprClass:
       return VisitNoRecurse(cast<Expr>(S), asc);
 
     case Stmt::BreakStmtClass:
@@ -1066,6 +1066,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
     case Stmt::LabelStmtClass:
       return VisitLabelStmt(cast<LabelStmt>(S));
 
+    case Stmt::LambdaExprClass:
+      return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
+
     case Stmt::MemberExprClass:
       return VisitMemberExpr(cast<MemberExpr>(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 (file)
index 0000000..77b36c4
--- /dev/null
@@ -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
+