formatter: avoid crash on attribute instance in for-loop header

TreeUnwrapper::ReshapeTokenPartitions' kForSpec case assumed the
for-loop header always yields two semicolon-leading partitions and
CHECK-failed (SIGABRT) otherwise. An attribute instance ((* ... *)) in
the for-loop init/condition changes the partition structure so those
partitions are absent, aborting the formatter on otherwise valid input,
e.g.:

  module m; initial for(int i=0(* a *);i<4;i++) x=i; endmodule

Replace the two CHECKs with graceful early-outs: when a required
semicolon-leading partition is not found, leave the partitions
unreshaped instead of aborting. Normal for-loops (both partitions
present) reshape exactly as before. Adds a formatter regression test.

Signed-off-by: Eylon Krause <eylon1909@gmail.com>
diff --git a/verible/verilog/formatting/formatter_test.cc b/verible/verilog/formatting/formatter_test.cc
index 5205a01..f9bb19e 100644
--- a/verible/verilog/formatting/formatter_test.cc
+++ b/verible/verilog/formatting/formatter_test.cc
@@ -4707,6 +4707,15 @@
      "  for (int i = 0; i < f(m); i--) begin\n"
      "  end\n"
      "endfunction\n"},
+    {// for loop with an attribute instance in the initializer.
+     // Regression: this used to abort with a CHECK failure while reshaping
+     // the kForSpec partitions when an attribute appears in the header.
+     "module m; initial for(int i=0(* a *);i<4;i++) x=i; endmodule",
+     "module m;\n"
+     "  initial\n"
+     "    for (int i = 0 (* a *); i < 4; i++)\n"
+     "      x = i;\n"
+     "endmodule\n"},
     {// forever loop
      "function\nvoid\tforevah;forever  begin "
      "++k\n;end endfunction\n",
diff --git a/verible/verilog/formatting/tree-unwrapper.cc b/verible/verilog/formatting/tree-unwrapper.cc
index a6601ac..c373590 100644
--- a/verible/verilog/formatting/tree-unwrapper.cc
+++ b/verible/verilog/formatting/tree-unwrapper.cc
@@ -2990,10 +2990,15 @@
       auto &children = partition.Children();
       const auto iter1 = std::find_if(children.begin(), children.end(),
                                       PartitionStartsWithSemicolon);
-      CHECK(iter1 != children.end());
+      // An attribute instance ((* ... *)) in the for-loop header can change
+      // the partition structure so that the expected semicolon-leading
+      // partitions are not present.  When they are missing, leave the
+      // partitions unreshaped rather than aborting (avoids a CHECK-failure
+      // crash on attributed/unusual for-headers).
+      if (iter1 == children.end()) break;
       const auto iter2 =
           std::find_if(iter1 + 1, children.end(), PartitionStartsWithSemicolon);
-      CHECK(iter2 != children.end());
+      if (iter2 == children.end()) break;
       const int dist1 = std::distance(children.begin(), iter1);
       const int dist2 = std::distance(children.begin(), iter2);
       VLOG(4) << "kForSpec got ';' at child " << dist1 << " and " << dist2;