P0305R0: Semantic analysis and code generation for C++17 init-statement for 'if' and 'switch':

  if (stmt; condition) { ... }

Patch by Anton Bikineev! Some minor formatting and comment tweets by me.

llvm-svn: 275350
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 0716701..d202a04 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -239,7 +239,8 @@
                                            SourceLocation());
   
   // (5) Create the 'if' statement.
-  IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, UO, CS);
+  IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
+                              UO, CS);
   return If;
 }
 
@@ -342,9 +343,8 @@
   Stmt *Else = M.makeReturn(RetVal);
   
   /// Construct the If.
-  Stmt *If =
-    new (C) IfStmt(C, SourceLocation(), false, nullptr, Comparison, Body,
-                   SourceLocation(), Else);
+  Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
+                            Comparison, Body, SourceLocation(), Else);
 
   return If;  
 }
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 2c502cd..d7a9bdb 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1,4 +1,4 @@
-  //===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===//
+//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -1945,7 +1945,8 @@
     addLocalScopeForStmt(C);
   }
   if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {
-    // If the body ends with a ReturnStmt, the dtors will be added in VisitReturnStmt
+    // If the body ends with a ReturnStmt, the dtors will be added in
+    // VisitReturnStmt.
     addAutomaticObjDtors(ScopePos, scopeBeginPos, C);
   }
 
@@ -2168,6 +2169,13 @@
   // won't be restored when traversing AST.
   SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
 
+  // Create local scope for C++17 if init-stmt if one exists.
+  if (Stmt *Init = I->getInit()) {
+    LocalScope::const_iterator BeginScopePos = ScopePos;
+    addLocalScopeForStmt(Init);
+    addAutomaticObjDtors(ScopePos, BeginScopePos, I);
+  }
+
   // Create local scope for possible condition variable.
   // Store scope position. Add implicit destructor.
   if (VarDecl *VD = I->getConditionVariable()) {
@@ -2268,13 +2276,19 @@
   // blocks will be pointed to be "Block".
   CFGBlock *LastBlock = addStmt(I->getCond());
 
-  // Finally, if the IfStmt contains a condition variable, add it and its
+  // If the IfStmt contains a condition variable, add it and its
   // initializer to the CFG.
   if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) {
     autoCreateBlock();
     LastBlock = addStmt(const_cast<DeclStmt *>(DS));
   }
 
+  // Finally, if the IfStmt contains a C++17 init-stmt, add it to the CFG.
+  if (Stmt *Init = I->getInit()) {
+    autoCreateBlock();
+    LastBlock = addStmt(Init);
+  }
+
   return LastBlock;
 }
 
@@ -3059,6 +3073,13 @@
   // won't be restored when traversing AST.
   SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
 
+  // Create local scope for C++17 switch init-stmt if one exists.
+  if (Stmt *Init = Terminator->getInit()) {
+    LocalScope::const_iterator BeginScopePos = ScopePos;
+    addLocalScopeForStmt(Init);
+    addAutomaticObjDtors(ScopePos, BeginScopePos, Terminator);
+  }
+
   // Create local scope for possible condition variable.
   // Store scope position. Add implicit destructor.
   if (VarDecl *VD = Terminator->getConditionVariable()) {
@@ -3138,7 +3159,7 @@
   Block = SwitchTerminatedBlock;
   CFGBlock *LastBlock = addStmt(Terminator->getCond());
 
-  // Finally, if the SwitchStmt contains a condition variable, add both the
+  // If the SwitchStmt contains a condition variable, add both the
   // SwitchStmt and the condition variable initialization to the CFG.
   if (VarDecl *VD = Terminator->getConditionVariable()) {
     if (Expr *Init = VD->getInit()) {
@@ -3148,6 +3169,12 @@
     }
   }
 
+  // Finally, if the SwitchStmt contains a C++17 init-stmt, add it to the CFG.
+  if (Stmt *Init = Terminator->getInit()) {
+    autoCreateBlock();
+    LastBlock = addStmt(Init);
+  }
+
   return LastBlock;
 }