ART: Make LogVerifyInfo newlines consistent

Use an RAII helper to make logging to the verifier's info_messages_
consistent - no caller needs to add a final newline.

Test: m
Test: manual
Change-Id: Ic830b816293078873160808fe275b862a672ff47
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index b6497b4..fae3af3 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -57,6 +57,7 @@
 #include "reg_type-inl.h"
 #include "register_line-inl.h"
 #include "runtime.h"
+#include "scoped_newline.h"
 #include "scoped_thread_state_change-inl.h"
 #include "stack.h"
 #include "vdex_file.h"
@@ -690,9 +691,11 @@
   return *failure_message;
 }
 
-std::ostream& MethodVerifier::LogVerifyInfo() {
-  return info_messages_ << "VFY: " << dex_file_->PrettyMethod(dex_method_idx_)
-                        << '[' << reinterpret_cast<void*>(work_insn_idx_) << "] : ";
+ScopedNewLine MethodVerifier::LogVerifyInfo() {
+  ScopedNewLine ret{info_messages_};
+  ret << "VFY: " << dex_file_->PrettyMethod(dex_method_idx_)
+      << '[' << reinterpret_cast<void*>(work_insn_idx_) << "] : ";
+  return ret;
 }
 
 void MethodVerifier::PrependToLastFailMessage(std::string prepend) {
@@ -1814,8 +1817,8 @@
   bool just_set_result = false;
   if (UNLIKELY(VLOG_IS_ON(verifier_debug))) {
     // Generate processing back trace to debug verifier
-    LogVerifyInfo() << "Processing " << inst->DumpString(dex_file_) << "\n"
-                    << work_line_->Dump(this) << "\n";
+    LogVerifyInfo() << "Processing " << inst->DumpString(dex_file_) << std::endl
+                    << work_line_->Dump(this);
   }
 
   /*
@@ -4751,7 +4754,7 @@
                       << " to [" << reinterpret_cast<void*>(next_insn) << "]: " << "\n"
                       << copy->Dump(this) << "  MERGE\n"
                       << merge_line->Dump(this) << "  ==\n"
-                      << target_line->Dump(this) << "\n";
+                      << target_line->Dump(this);
     }
     if (update_merge_line && changed) {
       merge_line->CopyFromLine(target_line);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 92abe9b..06482c4 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -59,6 +59,7 @@
 class RegisterLine;
 using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
 class RegType;
+struct ScopedNewLine;
 
 // We don't need to store the register data for many instructions, because we either only need
 // it at branch points (for verification) or GC points and branches (for verification +
@@ -126,7 +127,7 @@
   std::ostream& Fail(VerifyError error);
 
   // Log for verification information.
-  std::ostream& LogVerifyInfo();
+  ScopedNewLine LogVerifyInfo();
 
   // Dump the failures encountered by the verifier.
   std::ostream& DumpFailures(std::ostream& os);
diff --git a/runtime/verifier/scoped_newline.h b/runtime/verifier/scoped_newline.h
new file mode 100644
index 0000000..eb81bfa
--- /dev/null
+++ b/runtime/verifier/scoped_newline.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_VERIFIER_SCOPED_NEWLINE_H_
+#define ART_RUNTIME_VERIFIER_SCOPED_NEWLINE_H_
+
+#include <ostream>
+
+#include <android-base/logging.h>
+
+namespace art {
+namespace verifier {
+
+// RAII to inject a newline after a message.
+struct ScopedNewLine {
+  explicit ScopedNewLine(std::ostream& os) : stream(os) {}
+
+  ScopedNewLine(ScopedNewLine&& other) : stream(other.stream), active(other.active) {
+    other.active = false;
+  }
+
+  ScopedNewLine(ScopedNewLine&) = delete;
+  ScopedNewLine& operator=(ScopedNewLine&) = delete;
+
+  ~ScopedNewLine() {
+    if (active) {
+      stream << std::endl;
+    }
+  }
+
+  template <class T>
+  ScopedNewLine& operator<<(const T& t) {
+    DCHECK(active);
+    stream << t;
+    return *this;
+  }
+
+  ScopedNewLine& operator<<(std::ostream& (*f)(std::ostream&)) {
+    DCHECK(active);
+    stream << f;
+    return *this;
+  }
+
+  std::ostream& stream;
+  bool active = true;
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_RUNTIME_VERIFIER_SCOPED_NEWLINE_H_