gdb: fix invalid arg coercion when calling static member functions
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 23 Jun 2021 21:55:16 +0000 (22:55 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 25 Jun 2021 19:43:07 +0000 (20:43 +0100)
In this commit:

  commit 7022349d5c86bae74b49225515f42d2e221bd368
  Date:   Mon Sep 4 20:21:13 2017 +0100

      Stop assuming no-debug-info functions return int

A new if case was added to call_function_by_hand_dummy to decide if a
function should be considered prototyped or not.  Previously the code
was structured like this:

  if (COND_1)
    ACTION_1
  else if (COND_2)
    ACTION_2
  else
    ACTION_3

With the new block the code now looks like this:

  if (COND_1)
    ACTION_1
  if (NEW_COND)
    NEW_ACTION
  else if (COND_2)
    ACTION_2
  else
    ACTION_3

Notice the new block was added as and 'if' not 'else if'.  I'm running
into a case where GDB executes ACTION_1 and then ACTION_2.  Prior to
the above commit GDB would only have executed ACTION_1.

The actions in the code in question are trying to figure out if a
function should be considered prototyped or not.  When a function is
not prototyped some arguments will be coerced, e.g. floats to doubles.

The COND_1 / ACTION_1 are a very broad, any member function should be
considered prototyped, however, after the above patch GDB is now
executing the later ACTION_2 which checks to see if the function's
type has the 'prototyped' flag set - this is not the case for the
member functions I'm testing, and so GDB treats the function as
unprototyped and casts the float argument to a double.

I believe that adding the new check as 'if' rather than 'else if' was
a mistake, and so in this commit I add in the missing 'else'.

gdb/ChangeLog:

* infcall.c (call_function_by_hand_dummy): Add missing 'else' when
setting prototyped flag.

gdb/testsuite/ChangeLog:

* gdb.cp/method-call-in-c.cc (struct foo_type): Add static member
function static_method.
(global_var): New global.
(main): Use new static_method to ensure it is compiled in.
* gdb.cp/method-call-in-c.exp: Test calls to static member
function.

gdb/ChangeLog
gdb/infcall.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/method-call-in-c.cc
gdb/testsuite/gdb.cp/method-call-in-c.exp

index 1d10ae0f6c8b965639ef1f34768acd92d1fa7f2d..9613e3e02ca54bf40343d138bee409deecc34ed5 100644 (file)
@@ -1,3 +1,8 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * infcall.c (call_function_by_hand_dummy): Add missing 'else' when
+       setting prototyped flag.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * ada-lang.c (desc_bounds): Use '{}' instead of NULL to indicate
index ca3347fbb9dec1852856c03b6f3dca4e5638112e..40298fb1318604a7bb301ad163427640c6b85cee 100644 (file)
@@ -1026,8 +1026,8 @@ call_function_by_hand_dummy (struct value *function,
         prototyped.  Can we respect TYPE_VARARGS?  Probably not.  */
       if (ftype->code () == TYPE_CODE_METHOD)
        prototyped = 1;
-      if (TYPE_TARGET_TYPE (ftype) == NULL && ftype->num_fields () == 0
-         && default_return_type != NULL)
+      else if (TYPE_TARGET_TYPE (ftype) == NULL && ftype->num_fields () == 0
+              && default_return_type != NULL)
        {
          /* Calling a no-debug function with the return type
             explicitly cast.  Assume the function is prototyped,
index b155c71f7ce16fa856f4b061132dc94020a0feef..9bf8e9ebcc111e24dbbbaac1028e604d977be1ae 100644 (file)
@@ -1,3 +1,12 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.cp/method-call-in-c.cc (struct foo_type): Add static member
+       function static_method.
+       (global_var): New global.
+       (main): Use new static_method to ensure it is compiled in.
+       * gdb.cp/method-call-in-c.exp: Test calls to static member
+       function.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        PR gdb/27994
index 95f3f3c22de2db656c3b68a5fbe3a19b7607b27b..846a9111ef90751dfc0eebe01b2a2349b5a6483d 100644 (file)
@@ -35,9 +35,16 @@ struct foo_type
     return *this;
   }
 
+  static int static_method (float f, baz_type b)
+  {
+    return b.a + b.b + b.c + (int) f;
+  }
+
   int var = 120;
 };
 
+volatile int global_var;
+
 int
 main (void)
 {
@@ -48,5 +55,7 @@ main (void)
 
   foo += b;
 
+  global_var = foo.static_method (f, b);
+
   return foo.func (b, f);      /* Break here.  */
 }
index 411ba6790b12bfb073abb631046b406e0d13dd6f..5debc0e9a7a58280e0759b4ac716825b10349d8e 100644 (file)
@@ -43,5 +43,8 @@ foreach_with_prefix lang { c++ c } {
        set result [expr $result + 3]
        gdb_test "print foo += b" \
            " = \\((?:struct )?foo_type &\\) @${hex}: \\\{var = ${result}\\\}"
+
+       gdb_test "print foo.static_method (f, b)" " = 4"
+       gdb_test "print foo_type::static_method (f, b)" " = 4"
     }
 }