Hi,

the returns are a little problematic for coverage info because they are 
commonalized in GIMPLE, i.e. turned into gotos to a representative return.
This means that you need to clear the location of the representative return, 
see lower_gimple_return:

          /* Remove the line number from the representative return statement.
             It now fills in for many such returns.  Failure to remove this
             will result in incorrect results for coverage analysis.  */
          gimple_set_location (tmp_rs.stmt, UNKNOWN_LOCATION);

otherwise the coverage info is blatantly wrong.  But this in turn means that 
such representative returns are vulneable to inheriting random source location 
information in the debug info generated by the compiler.

I have attached an Ada testcase that demonstrates the problem at -O0:

        .loc 1 14 10 discriminator 2
        movl    $0, %r13d
.L12:
        movl    %r13d, %eax
        jmp     .L23

.L12 is what's left at the RTL level of a representative return in GIMPLE and 
it inherits the location directive, which gives wrong coverage info (that's 
not visible with gcov because the instrumentation done by -fprofile-arcs 
papers over the issue, but for example with callgrind).

The proposed fix is attached: it sets the current location to the function's 
end locus when expanding such a representative return to RTL.  That's a bit on 
the kludgy side, but doing something in GIMPLE, e.g. in lower_gimple_return, 
leads to various regressions in terms of quality of diagnostics.

Tested on x86_64-suse-linux, both GCC and GDB, OK for mainline?


2019-07-10  Eric Botcazou  <ebotca...@adacore.com>

        * cfgexpand.c (expand_gimple_stmt_1) <GIMPLE_RETURN>: If the statement
        doesn't have a location, set the current location to the function's end.

-- 
Eric Botcazou
Index: cfgexpand.c
===================================================================
--- cfgexpand.c	(revision 273294)
+++ cfgexpand.c	(working copy)
@@ -3712,6 +3712,12 @@ expand_gimple_stmt_1 (gimple *stmt)
       {
 	op0 = gimple_return_retval (as_a <greturn *> (stmt));
 
+	/* If a return doesn't have a location, it very likely represents
+	   multiple user returns so we cannot let it inherit the location
+	   of the last statement of the previous basic block in RTL.  */
+	if (!gimple_has_location (stmt))
+	  set_curr_insn_location (cfun->function_end_locus);
+
 	if (op0 && op0 != error_mark_node)
 	  {
 	    tree result = DECL_RESULT (current_function_decl);
pragma Unsuppress (All_Checks);
pragma Check_Float_Overflow;
   
package body Ops is
   
   function Both_Ok (A, B : Capsum) return Boolean is
   begin
      if A.X + A. Y <= A.Cap and then B.X + B.Y <= B.Cap then -- # test
	 N_Ok := N_Ok + 1; -- # ok
	 return True;      -- # ok
      else
	 N_Ko := N_Ko + 1; -- # ko
	 return False;     -- # ko
      end if;
   exception
      when Constraint_Error =>
	 N_Ov := N_Ov + 1; -- # ov
	 return False; -- # ov
   end;
end;
package Ops is
   
   type Constrained_Float is new Float range Float'Range;
   
   type Capsum is record
      X, Y, Cap : Constrained_Float;
   end record;
   
   Cs_Ok : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0);
   Cs_Ko : constant Capsum := (X => 1.0, Y => 2.0, Cap => 1.0);
   Cs_Ov : constant Capsum := (X => Constrained_Float'Last,
			       Y => Constrained_Float'Last,
			       Cap => 3.0);
   
   N_Ok, N_Ko, N_Ov : Integer := 0;
   
   function Both_Ok (A, B : Capsum) return Boolean;
   
end;

Reply via email to