szepet updated this revision to Diff 127894.
szepet marked an inline comment as done.
szepet added a comment.

Comment added to LoopEntrance CFGElement.


https://reviews.llvm.org/D41150

Files:
  include/clang/Analysis/CFG.h
  lib/Analysis/CFG.cpp
  lib/StaticAnalyzer/Core/PathDiagnostic.cpp
  test/Analysis/loopexit-cfg-output.cpp

Index: test/Analysis/loopexit-cfg-output.cpp
===================================================================
--- test/Analysis/loopexit-cfg-output.cpp
+++ test/Analysis/loopexit-cfg-output.cpp
@@ -34,6 +34,7 @@
 // CHECK:       [B5]
 // CHECK-NEXT:   1: 0
 // CHECK-NEXT:   2: int i = 0;
+// CHECK-NEXT:   3: ForStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (1): B6
 // CHECK-NEXT:   Succs (1): B4
 
@@ -46,8 +47,8 @@
   return;
 }
 
-// CHECK:       [B4 (ENTRY)]
-// CHECK-NEXT:   Succs (1): B3
+// CHECK:       [B5 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B4
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: ForStmt (LoopExit)
@@ -62,15 +63,20 @@
 // CHECK-NEXT:   Preds (2): B2 B4
 // CHECK-NEXT:   Succs (2): B2 NULL
 
+// CHECK:       [B4]
+// CHECK-NEXT:   1: ForStmt (LoopEntrance)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B3
+
 // CHECK:       [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
 void check_forloop2() {
   for (;;)
     ;
 }
 
-// CHECK:       [B5 (ENTRY)]
-// CHECK-NEXT:   Succs (1): B4
+// CHECK:       [B6 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B5
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: WhileStmt (LoopExit)
@@ -91,6 +97,11 @@
 // CHECK-NEXT:   Preds (2): B2 B5
 // CHECK-NEXT:   Succs (2): B3 NULL
 
+// CHECK:       [B5]
+// CHECK-NEXT:   1: WhileStmt (LoopEntrance)
+// CHECK-NEXT:   Preds (1): B6
+// CHECK-NEXT:   Succs (1): B4
+
 // CHECK:       [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
 void check_while1() {
@@ -125,6 +136,7 @@
 
 // CHECK:       [B4]
 // CHECK-NEXT:   1: int l;
+// CHECK-NEXT:   2: WhileStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B3
 
@@ -138,8 +150,8 @@
   return;
 }
 
-// CHECK:       [B4 (ENTRY)]
-// CHECK-NEXT:   Succs (1): B3
+// CHECK:       [B5 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B4
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: WhileStmt (LoopExit)
@@ -155,16 +167,21 @@
 // CHECK-NEXT:   Preds (2): B2 B4
 // CHECK-NEXT:   Succs (2): NULL B1
 
+// CHECK:       [B4]
+// CHECK-NEXT:   1: WhileStmt (LoopEntrance)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B3
+
 // CHECK:       [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
 void check_while3() {
   while (false) {
     ;
   }
 }
 
-// CHECK:       [B4 (ENTRY)]
-// CHECK-NEXT:   Succs (1): B2
+// CHECK:       [B5 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B4
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: DoStmt (LoopExit)
@@ -180,6 +197,11 @@
 // CHECK:       [B3]
 // CHECK-NEXT:   Succs (1): B2
 
+// CHECK:       [B4]
+// CHECK-NEXT:   1: DoStmt (LoopEntrance)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B2
+
 // CHECK:       [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
 void check_dowhile1() {
@@ -221,6 +243,7 @@
 // CHECK:       [B5]
 // CHECK-NEXT:   1: 2
 // CHECK-NEXT:   2: int j = 2;
+// CHECK-NEXT:   3: DoStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (1): B6
 // CHECK-NEXT:   Succs (1): B3
 
@@ -276,6 +299,7 @@
 // CHECK:       [B7]
 // CHECK-NEXT:   1: 1
 // CHECK-NEXT:   2: int j = 1;
+// CHECK-NEXT:   3: ForStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (1): B8
 // CHECK-NEXT:   Succs (1): B6
 
@@ -292,6 +316,7 @@
 // CHECK-NEXT:   1: 40
 // CHECK-NEXT:   2: -[B9.1]
 // CHECK-NEXT:   3: int i = -40;
+// CHECK-NEXT:   4: WhileStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (1): B10
 // CHECK-NEXT:   Succs (1): B8
 
@@ -305,19 +330,19 @@
   }
 }
 
-// CHECK:       [B9 (ENTRY)]
-// CHECK-NEXT:   Succs (1): B8
+// CHECK:       [B10 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B9
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: ForStmt (LoopExit)
-// CHECK-NEXT:   Preds (1): B7
+// CHECK-NEXT:   Preds (1): B8
 // CHECK-NEXT:   Succs (1): B0
 
 // CHECK:       [B2]
 // CHECK-NEXT:   1: j
 // CHECK-NEXT:   2: [B2.1]++
 // CHECK-NEXT:   Preds (1): B3
-// CHECK-NEXT:   Succs (1): B7
+// CHECK-NEXT:   Succs (1): B8
 
 // CHECK:       [B3]
 // CHECK-NEXT:   1: DoStmt (LoopExit)
@@ -346,22 +371,28 @@
 // CHECK-NEXT:   Succs (1): B5
 
 // CHECK:       [B7]
+// CHECK-NEXT:   1: DoStmt (LoopEntrance)
+// CHECK-NEXT:   Preds (1): B8
+// CHECK-NEXT:   Succs (1): B5
+
+// CHECK:       [B8]
 // CHECK-NEXT:   1: j
-// CHECK-NEXT:   2: [B7.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT:   2: [B8.1] (ImplicitCastExpr, LValueToRValue, int)
 // CHECK-NEXT:   3: 6
-// CHECK-NEXT:   4: [B7.2] < [B7.3]
-// CHECK-NEXT:   T: for (...; [B7.4]; ...)
-// CHECK-NEXT:   Preds (2): B2 B8
-// CHECK-NEXT:   Succs (2): B5 B1
+// CHECK-NEXT:   4: [B8.2] < [B8.3]
+// CHECK-NEXT:   T: for (...; [B8.4]; ...)
+// CHECK-NEXT:   Preds (2): B2 B9
+// CHECK-NEXT:   Succs (2): B7 B1
 
-// CHECK:       [B8]
+// CHECK:       [B9]
 // CHECK-NEXT:   1: 40
-// CHECK-NEXT:   2: -[B8.1]
+// CHECK-NEXT:   2: -[B9.1]
 // CHECK-NEXT:   3: int i = -40;
 // CHECK-NEXT:   4: 1
 // CHECK-NEXT:   5: int j = 1;
-// CHECK-NEXT:   Preds (1): B9
-// CHECK-NEXT:   Succs (1): B7
+// CHECK-NEXT:   6: ForStmt (LoopEntrance)
+// CHECK-NEXT:   Preds (1): B10
+// CHECK-NEXT:   Succs (1): B8
 
 // CHECK:       [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
@@ -418,6 +449,7 @@
 // CHECK-NEXT:   1: ForStmt (LoopExit)
 // CHECK-NEXT:   2: 1
 // CHECK-NEXT:   3: int i = 1;
+// CHECK-NEXT:   4: WhileStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (2): B8 B10
 // CHECK-NEXT:   Succs (1): B5
 
@@ -453,24 +485,24 @@
 // CHECK:       [B11]
 // CHECK-NEXT:   1: 2
 // CHECK-NEXT:   2: int i = 2;
+// CHECK-NEXT:   3: ForStmt (LoopEntrance)
 // CHECK-NEXT:   Preds (1): B12
 // CHECK-NEXT:   Succs (1): B10
 
 // CHECK:       [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
-void check_break()
-{
-  for(int i = 2; i < 6; i++) {
-    if(i == 4)
+void check_break() {
+  for (int i = 2; i < 6; i++) {
+    if (i == 4)
       break;
   }
 
   int i = 1;
-  while(i<5){
+  while (i < 5) {
     i++;
-    if(i%2)
+    if (i % 2)
       break;
   }
-  
+
   return;
 }
Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -581,6 +581,7 @@
     llvm_unreachable("not yet implemented!");
   case CFGElement::LifetimeEnds:
   case CFGElement::LoopExit:
+  case CFGElement::LoopEntrance:
     llvm_unreachable("CFGElement kind should not be on callsite!");
   }
 
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -610,6 +610,7 @@
   }
   CFGBlock *addInitializer(CXXCtorInitializer *I);
   void addLoopExit(const Stmt *LoopStmt);
+  void addLoopEntrance(const Stmt *LoopStmt);
   void addAutomaticObjDtors(LocalScope::const_iterator B,
                             LocalScope::const_iterator E, Stmt *S);
   void addLifetimeEnds(LocalScope::const_iterator B,
@@ -664,6 +665,10 @@
     B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());
   }
 
+  void appendLoopEntrance(CFGBlock *B, const Stmt *LoopStmt) {
+    B->appendLoopEntrance(LoopStmt, cfg->getBumpVectorContext());
+  }
+
   void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
     B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());
   }
@@ -1275,6 +1280,13 @@
   appendLoopExit(Block, LoopStmt);
 }
 
+void CFGBuilder::addLoopEntrance(const Stmt *LoopStmt) {
+  if (!BuildOpts.AddLoopExit)
+    return;
+  autoCreateBlock();
+  appendLoopEntrance(Block, LoopStmt);
+}
+
 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
                                          LocalScope::const_iterator E,
                                          Stmt *S) {
@@ -2820,22 +2832,24 @@
 
   // Link up the loop-back block to the entry condition block.
   addSuccessor(TransitionBlock, EntryConditionBlock);
-  
-  // The condition block is the implicit successor for any code above the loop.
+
+  // The condition block is the implicit sucacessor for any code above the loop.
   Succ = EntryConditionBlock;
 
   // If the loop contains initialization, create a new block for those
   // statements.  This block can also contain statements that precede the loop.
   if (Stmt *I = F->getInit()) {
     Block = createBlock();
+    addLoopEntrance(F);
     return addStmt(I);
   }
 
   // There is no loop initialization.  We are thus basically a while loop.
   // NULL out Block to force lazy block construction.
   Block = nullptr;
   Succ = EntryConditionBlock;
-  return EntryConditionBlock;
+  addLoopEntrance(F);
+  return (Block ? Block : Succ);
 }
 
 CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
@@ -3141,7 +3155,8 @@
 
   // Return the condition block, which is the dominating block for the loop.
   Succ = EntryConditionBlock;
-  return EntryConditionBlock;
+  addLoopEntrance(W);
+  return (Block ? Block : Succ);
 }
 
 
@@ -3291,7 +3306,8 @@
 
   // Return the loop body, which is the dominating block for the loop.
   Succ = BodyBlock;
-  return BodyBlock;
+  addLoopEntrance(D);
+  return (Block ? Block : Succ);
 }
 
 CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {
@@ -4176,6 +4192,7 @@
     case CFGElement::Initializer:
     case CFGElement::NewAllocator:
     case CFGElement::LoopExit:
+    case CFGElement::LoopEntrance:
     case CFGElement::LifetimeEnds:
       llvm_unreachable("getDestructorDecl should only be used with "
                        "ImplicitDtors");
@@ -4597,6 +4614,9 @@
 
     OS << " (Lifetime ends)\n";
 
+  } else if (Optional<CFGLoopEntrance> LE = E.getAs<CFGLoopEntrance>()) {
+    const Stmt *LoopStmt = LE->getLoopStmt();
+    OS << LoopStmt->getStmtClassName() << " (LoopEntrance)\n";
   } else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) {
     const Stmt *LoopStmt = LE->getLoopStmt();
     OS << LoopStmt->getStmtClassName() << " (LoopExit)\n";
Index: include/clang/Analysis/CFG.h
===================================================================
--- include/clang/Analysis/CFG.h
+++ include/clang/Analysis/CFG.h
@@ -59,6 +59,7 @@
     Initializer,
     NewAllocator,
     LifetimeEnds,
+    LoopEntrance,
     LoopExit,
     // dtor kind
     AutomaticObjectDtor,
@@ -169,6 +170,26 @@
   }
 };
 
+/// Represents the point where a loop begins. This element is encountered right
+/// before the first loop element.  This element is is only produced when
+/// building the CFG for the static analyzer and hidden behind the
+/// 'cfg-loopexit' analyzer config flag.
+class CFGLoopEntrance : public CFGElement {
+public:
+  explicit CFGLoopEntrance(const Stmt *stmt) : CFGElement(LoopEntrance, stmt) {}
+
+  const Stmt *getLoopStmt() const {
+    return static_cast<Stmt *>(Data1.getPointer());
+  }
+
+private:
+  friend class CFGElement;
+  CFGLoopEntrance() {}
+  static bool isKind(const CFGElement &elem) {
+    return elem.getKind() == LoopEntrance;
+  }
+};
+
 /// Represents the point where a loop ends.
 /// This element is is only produced when building the CFG for the static
 /// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag.
@@ -756,6 +777,10 @@
     Elements.push_back(CFGLoopExit(LoopStmt), C);
   }
 
+  void appendLoopEntrance(const Stmt *LoopStmt, BumpVectorContext &C) {
+    Elements.push_back(CFGLoopEntrance(LoopStmt), C);
+  }
+
   void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
     Elements.push_back(CFGDeleteDtor(RD, DE), C);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to