gollvm: fixes for unit test remastering machinery

Makes the unit test remastering feature a little more resilient with
respect to C++ compiler's interpretation of the line number for a
macro instantiation. If you have something like

   #define RAW_RESULT(x) #x
   #define PLINE(x) printf("%s %d\n", x, __LINE__)

and then instantiate with

  L10:   PLINE(R"RAW_RESULT(
  L11:     abc
  L12:     def
  L13:   )RAW_RESULT");

some C++ compilers will assign a value of 10 to the __LINE__
reference, and some will assign a value of 13. This patch adds
auto-detection for each of these two scenarios, and adjusts
accordingly.

Change-Id: Id9b29a6e13c6cab2dffe9432ed43200083daa29c
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/235558
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/unittests/TestUtils/DiffUtils.cpp b/unittests/TestUtils/DiffUtils.cpp
index 9bf7c14..40a100e 100644
--- a/unittests/TestUtils/DiffUtils.cpp
+++ b/unittests/TestUtils/DiffUtils.cpp
@@ -8,11 +8,37 @@
 
 #include "DiffUtils.h"
 
+#include <assert.h>
 #include <iostream>
 #include <sstream>
 
 namespace goBackendUnitTests {
 
+DECLARE_EXPECTED_OUTPUT(baseline, R"RAW_RESULT(
+    abc
+    def
+    xyz
+)RAW_RESULT");
+
+// macroLineAtStart returns TRUE if the line number reported by the
+// compiler for __LINE__ in a macro instantiation points to the start
+// of the DECLARE_EXPECTED_OUTPUT macro use, as opposed to the end.
+//
+// Fun fact: there is some disagreement among C++ compilers about what
+// the line is. Some compilers decided that __LINE__ for the macro
+// above is the starting line (16) and some decide that it's the
+// ending line (20). Which one will matter for the machinery that does
+// test remastering.
+static bool macroLineAtStart() {
+  if (baseline.line == 16) {
+    return true;
+  } else if (baseline.line == 20) {
+    return false;
+  } else {
+    assert(false && "macroLineAtStart broken -- source edited?");
+  }
+}
+
 std::string trimsp(const std::string &s) {
   size_t firstsp = s.find_first_not_of(" \n");
   if (firstsp == std::string::npos)
@@ -143,6 +169,7 @@
   const std::string &expected = ed.content;
   std::cerr << "expected dump:\n" << expected << "\n";
   std::cerr << "actual dump:\n" << actual << "\n";
+  unsigned mls = macroLineAtStart() ? 1 : 0;
   if (emitDump) {
     static unsigned filecount;
     static FILE *outfp; // script
@@ -155,7 +182,7 @@
         outfp = fopen("/tmp/remaster-inputs.txt", "w");
         fprintf(stderr, "... emitting remaster inputs to file '/tmp/remaster-inputs.txt'\n");
       }
-      fprintf(outfp, "%s %d %s %s\n", ed.file, ed.line,
+      fprintf(outfp, "%d %s %d %s %s\n", mls, ed.file, ed.line,
               dumpfilename("expected", filecount).c_str(),
               dumpfilename("actual", filecount).c_str());
       fflush(outfp);
diff --git a/unittests/remaster-tests.go b/unittests/remaster-tests.go
index 89f8dd5..503f77f 100644
--- a/unittests/remaster-tests.go
+++ b/unittests/remaster-tests.go
@@ -55,6 +55,7 @@
 	expected string
 	actual   string
 	line     int
+	mls      bool // macro line at start (vs end)
 }
 
 type FileChanges struct {
@@ -71,18 +72,31 @@
 		line := scanner.Text()
 		verb(3, "=-= line is %s", line)
 		tokens := strings.Split(line, " ")
-		if len(tokens) != 4 {
+		if len(tokens) != 5 {
 			panic(fmt.Sprintf("malformed line %d in input file: %s", lno, line))
 		}
-		srcfile := tokens[0]
-		spot, err := strconv.ParseInt(tokens[1], 10, 64)
+		macroLineAtStart, errm := strconv.ParseInt(tokens[0], 10, 64)
+		if errm != nil {
+			panic(fmt.Sprintf("malformed srcline in input line %d: %s", lno, line))
+		}
+		mls := false
+		if macroLineAtStart == 1 {
+			mls = true
+		}
+		srcfile := tokens[1]
+		spot, err := strconv.ParseInt(tokens[2], 10, 64)
 		if err != nil {
 			panic(fmt.Sprintf("malformed srcline in input line %d: %s", lno, line))
 		}
-		exp := tokens[2]
-		act := tokens[3]
+		exp := tokens[3]
+		act := tokens[4]
 		fc := fm[srcfile]
-		newchange := Change{expected: exp, actual: act, line: int(spot)}
+		newchange := Change{
+			expected: exp,
+			actual:   act,
+			line:     int(spot),
+			mls:      mls,
+		}
 		fc.changes = append(fc.changes, newchange)
 		fm[srcfile] = fc
 	}
@@ -173,7 +187,12 @@
 	}
 
 	// Add content before the result.
-	startres := change.line + delta
+	var startres int
+	if change.mls {
+		startres = change.line + delta
+	} else {
+		startres = change.line + delta - len(ca) - 1
+	}
 	verb(2, "startres = %d", startres)
 	newlines = append(newlines, srclines[0:startres]...)