Robustify guality tests, fix and improve check_guality

From: Alexandre Oliva <aoliva@redhat.com>

for  gcc/testsuite/ChangeLog

	* gcc.dg/guality/guality.exp (check_guality): Fix compilation
	attempt with -O0 -g, and retry with -O2 -g upon failure.
	* gcc.dg/guality/guality.h (guality_xvalue): New variable.
	(guality_unavailable): Likewise.
	(guality_check): Robustify to cope with failure to set user
	variables, now using the new guality_* variables.
---

 gcc/testsuite/gcc.dg/guality/guality.exp |   19 +++++++++++++
 gcc/testsuite/gcc.dg/guality/guality.h   |   43 +++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 11 deletions(-)


diff --git a/gcc/testsuite/gcc.dg/guality/guality.exp b/gcc/testsuite/gcc.dg/guality/guality.exp
index 49e2ac5..0c47fa4 100644
--- a/gcc/testsuite/gcc.dg/guality/guality.exp
+++ b/gcc/testsuite/gcc.dg/guality/guality.exp
@@ -9,7 +9,24 @@ if { [istarget *-*-darwin*] } {
 }
 
 proc check_guality {args} {
-    set result [eval check_compile guality_check executable $args "-g -O0"]
+    set options [list "-O0" "-g"]
+    set result [eval check_compile guality_check \
+		    executable $args "\"\$options\""]
+    set lines [lindex $result 0]
+    set output [lindex $result 1]
+    set ret 0
+    if {[string match "" $lines]} {
+      set execout [gcc_load "./$output"]
+      set ret [string match "*1 PASS, 0 FAIL, 0 UNRESOLVED*" $execout]
+    }
+    remote_file build delete $output
+    if {$ret} {
+	return $ret
+    }
+    # Retry with -O2 -g
+    set options [list "-O2" "-g"]
+    set result [eval check_compile guality_check \
+		    executable $args "\"\$options\""]
     set lines [lindex $result 0]
     set output [lindex $result 1]
     set ret 0
diff --git a/gcc/testsuite/gcc.dg/guality/guality.h b/gcc/testsuite/gcc.dg/guality/guality.h
index 8b657f2..9d51893 100644
--- a/gcc/testsuite/gcc.dg/guality/guality.h
+++ b/gcc/testsuite/gcc.dg/guality/guality.h
@@ -194,6 +194,14 @@ int guality_breakpoint_line;
 /* GDB should set this to true once it's connected.  */
 int volatile guality_attached;
 
+/* GDB should set this to the value of the expression we're checking.  */
+gualchk_t volatile guality_xvalue;
+
+/* GDB should set this to a value that tells whether the value was
+   optimized away.  */
+int volatile guality_unavailable;
+
+
 /* This function is the main guality program.  It may actually be
    defined as main, because we #define main to it afterwards.  Because
    of this wrapping, guality_main may not have an empty argument
@@ -283,8 +291,12 @@ guality_check (const char *name, gualchk_t value, int unknown_ok)
     return;
 
   {
-    volatile gualchk_t xvalue = -1;
-    volatile int unavailable = 0;
+    static int test_count;
+    int retry_count = test_count;
+  retry:
+    ++test_count;
+    guality_xvalue = test_count;
+    guality_unavailable = test_count;
     if (name)
       {
 	/* The sequence below cannot distinguish an optimized away
@@ -300,8 +312,8 @@ set $value4 = $value1 + 1\n\
 set $value3 = (%s)++\n\
 set $value4 = --(%s)\n\
 down\n\
-set xvalue = $value1\n\
-set unavailable = $value1 != $value2 ? -1 : $value3 != $value4 ? 1 : 0\n\
+set guality_xvalue = $value1\n\
+set guality_unavailable = $value1 != $value2 ? -1 : $value3 != $value4 ? 1 : 0\n\
 continue\n\
 ", name, name, name, name) <= 0
 	    || fflush (guality_gdb_input))
@@ -322,7 +334,7 @@ continue\n\
 	      ;
 	    if (!timeout && !guality_attached)
 	      {
-		fprintf (stderr, "gdb: took too long to attach\n");
+		fprintf (stderr, "ERROR: gdb: took too long to attach\n");
 		abort ();
 	      }
 	  }
@@ -334,28 +346,39 @@ continue\n\
       }
     /* Do NOT add lines between the __LINE__ above and the line below,
        without also adjusting the added constant to match.  */
-    if (!unavailable || (unavailable > 0 && xvalue))
+    if (guality_xvalue == test_count || guality_unavailable == test_count)
+      {
+	if (test_count - retry_count < 4)
+	  goto retry;
+	  
+	fprintf (stderr, "ERROR: gdb: failed to set interface variables\n");
+	abort ();
+      }
+    if (!guality_unavailable || (guality_unavailable > 0 && guality_xvalue))
       {
-	if (xvalue == value)
+	if (guality_xvalue == value)
 	  result = PASS;
 	else
 	  result = INCORRECT;
       }
     else
       result = INCOMPLETE;
-    asm ("" : : "X" (name), "X" (value), "X" (unknown_ok), "m" (xvalue));
+    asm ("" : : "X" (name), "X" (value), "X" (unknown_ok),
+	 "m" (guality_xvalue));
     switch (result)
       {
       case PASS:
 	fprintf (stderr, "PASS: %s is %lli\n", name, value);
 	break;
       case INCORRECT:
-	fprintf (stderr, "FAIL: %s is %lli, not %lli\n", name, xvalue, value);
+	fprintf (stderr, "FAIL: %s is %lli, not %lli\n", name,
+		 guality_xvalue, value);
 	break;
       case INCOMPLETE:
 	fprintf (stderr, "%s: %s is %s, expected %lli\n",
 		 unknown_ok ? "UNRESOLVED" : "FAIL", name,
-		 unavailable < 0 ? "not computable" : "optimized away", value);
+		 guality_unavailable < 0
+		 ? "not computable" : "optimized away", value);
 	result = unknown_ok ? INCOMPLETE : INCORRECT;
 	break;
       default:
