[gdb/testsuite] Move start-of-function brace to handle Clang/GCC difference

Message ID CAENS6Ev3-fbm4P++YZ3o6Q2nFV_SjSgWTpc12uvZ4ui-qRsnYA@mail.gmail.com
State Committed
Headers

Commit Message

David Blaikie April 14, 2014, 8:12 p.m. UTC
  gdb.cp/cpexprs.exp is verifying behavior that's likely a GCC bug (GCC
PR60815 and some in person and IRC conversations with GCC developers).
GCC inconsistently places the prologue on either the line with the
function name or the line with the function's open brace. Clang
consistently uses the function's open brace.

Either these tests can be fixed by moving the line to break on and
XFAILing them all under GCC, or just making the test neutral to the
bug by moving the brace. I generally think it's best to just make the
test bug-neutral.

I've also had to update the .exp file to tolerate differences in the
type of vtable pointers (GCC's "const void ** const" versus Clang's
"void **") which required some refactoring.
commit c532bc93335823e6ddbaa58abe6f5f58a1dda62e
Author: David Blaikie <dblaikie@gmail.com>
Date:   Sun Apr 13 17:37:56 2014 -0700

    Adjust start-of-function braces to be compatible with Clang
    
    gdb/testsuite/
    	* gdb.cp/cpexprs.cc: Move braces to the same line as the start
    	of the function to work across GCC and Clang.
    	* gdb.cp/cpexprs.exp: Account for GCC/Clang difference in vtable
    	pointer types (const void ** const V void **).
  

Comments

Doug Evans April 23, 2014, 9:55 p.m. UTC | #1
David Blaikie writes:
 > gdb.cp/cpexprs.exp is verifying behavior that's likely a GCC bug (GCC
 > PR60815 and some in person and IRC conversations with GCC developers).
 > GCC inconsistently places the prologue on either the line with the
 > function name or the line with the function's open brace. Clang
 > consistently uses the function's open brace.
 > 
 > Either these tests can be fixed by moving the line to break on and
 > XFAILing them all under GCC, or just making the test neutral to the
 > bug by moving the brace. I generally think it's best to just make the
 > test bug-neutral.
 > 
 > I've also had to update the .exp file to tolerate differences in the
 > type of vtable pointers (GCC's "const void ** const" versus Clang's
 > "void **") which required some refactoring.
 > commit c532bc93335823e6ddbaa58abe6f5f58a1dda62e
 > Author: David Blaikie <dblaikie@gmail.com>
 > Date:   Sun Apr 13 17:37:56 2014 -0700
 > 
 >     Adjust start-of-function braces to be compatible with Clang
 >     
 >     gdb/testsuite/
 >     	* gdb.cp/cpexprs.cc: Move braces to the same line as the start
 >     	of the function to work across GCC and Clang.
 >     	* gdb.cp/cpexprs.exp: Account for GCC/Clang difference in vtable
 >     	pointer types (const void ** const V void **).

I'm don't have an opinion, so in the interests of moving things along,
and since the patch has been out for awhile,
let's go with this.

When you commit this, *please* add the entirety of the above text to the commit entry.

Thanks!
  
David Blaikie April 24, 2014, 8:20 p.m. UTC | #2
On Wed, Apr 23, 2014 at 2:55 PM, Doug Evans <dje@google.com> wrote:
> David Blaikie writes:
>  > gdb.cp/cpexprs.exp is verifying behavior that's likely a GCC bug (GCC
>  > PR60815 and some in person and IRC conversations with GCC developers).
>  > GCC inconsistently places the prologue on either the line with the
>  > function name or the line with the function's open brace. Clang
>  > consistently uses the function's open brace.
>  >
>  > Either these tests can be fixed by moving the line to break on and
>  > XFAILing them all under GCC, or just making the test neutral to the
>  > bug by moving the brace. I generally think it's best to just make the
>  > test bug-neutral.
>  >
>  > I've also had to update the .exp file to tolerate differences in the
>  > type of vtable pointers (GCC's "const void ** const" versus Clang's
>  > "void **") which required some refactoring.
>  > commit c532bc93335823e6ddbaa58abe6f5f58a1dda62e
>  > Author: David Blaikie <dblaikie@gmail.com>
>  > Date:   Sun Apr 13 17:37:56 2014 -0700
>  >
>  >     Adjust start-of-function braces to be compatible with Clang
>  >
>  >     gdb/testsuite/
>  >      * gdb.cp/cpexprs.cc: Move braces to the same line as the start
>  >      of the function to work across GCC and Clang.
>  >      * gdb.cp/cpexprs.exp: Account for GCC/Clang difference in vtable
>  >      pointer types (const void ** const V void **).
>
> I'm don't have an opinion, so in the interests of moving things along,
> and since the patch has been out for awhile,
> let's go with this.
>
> When you commit this, *please* add the entirety of the above text to the commit entry.
>
> Thanks!

Committed in 25d4e99db83ba758e3c888d321b9f2f7845701a0

Thanks Doug!
  

Patch

diff --git gdb/testsuite/ChangeLog gdb/testsuite/ChangeLog
index e8aefbc..5bcac13 100644
--- gdb/testsuite/ChangeLog
+++ gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@ 
+2014-04-14  David Blaikie  <dblaikie@gmail.com>
+
+	* gdb.cp/cpexprs.cc: Move braces to the same line as the start
+	of the function to work across GCC and Clang.
+	* gdb.cp/cpexprs.exp: Account for GCC/Clang difference in vtable
+	pointer types (const void ** const V void **).
+
 2014-04-14  Tom Tromey  <tromey@redhat.com>
 
 	* gdb.cp/classes.exp (test_enums): Handle underlying type.
diff --git gdb/testsuite/gdb.cp/cpexprs.cc gdb/testsuite/gdb.cp/cpexprs.cc
index ee89451..270811b 100644
--- gdb/testsuite/gdb.cp/cpexprs.cc
+++ gdb/testsuite/gdb.cp/cpexprs.cc
@@ -49,8 +49,7 @@  void tclass<short>::do_something () { } // tclass<short>::do_something
 
 // A simple template with multiple template parameters
 template <class A, class B, class C, class D, class E>
-void flubber (void) // flubber
-{
+void flubber (void) { // flubber
   A a;
   B b;
   C c;
@@ -144,128 +143,128 @@  public:
   int overload (base& b) const { return 5; } // base::overload(base&) const
 
   // Operators
-  int operator+ (base const& o) const // base::operator+
-  { return foo_ + o.foo_; }
+  int operator+ (base const& o) const { // base::operator+
+    return foo_ + o.foo_;  }
 
-  base operator++ (void) // base::operator++
-  { ++foo_; return *this; }
+  base operator++ (void) { // base::operator++
+    ++foo_; return *this; }
 
-  base operator+=(base const& o) // base::operator+=
-  { foo_ += o.foo_; return *this; }
+  base operator+=(base const& o) { // base::operator+=
+    foo_ += o.foo_; return *this; }
 
-  int operator- (base const& o) const // base::operator-
-  { return foo_ - o.foo_; }
+  int operator- (base const& o) const { // base::operator-
+    return foo_ - o.foo_; }
 
-  base operator-- (void) // base::operator--
-  { --foo_; return *this; }
+  base operator-- (void) { // base::operator--
+    --foo_; return *this; }
 
-  base operator-= (base const& o) // base::operator-=
-  { foo_ -= o.foo_; return *this; }
+  base operator-= (base const& o) { // base::operator-=
+    foo_ -= o.foo_; return *this; }
 
-  int operator* (base const& o) const // base::operator*
-  { return foo_ * o.foo_; }
+  int operator* (base const& o) const { // base::operator*
+    return foo_ * o.foo_; }
 
-  base operator*= (base const& o) // base::operator*=
-  { foo_ *= o.foo_; return *this; }
+  base operator*= (base const& o) { // base::operator*=
+    foo_ *= o.foo_; return *this; }
 
-  int operator/ (base const& o) const // base::operator/
-  { return foo_ / o.foo_; }
+  int operator/ (base const& o) const { // base::operator/
+    return foo_ / o.foo_; }
 
-  base operator/= (base const& o) // base::operator/=
-  { foo_ /= o.foo_; return *this; }
+  base operator/= (base const& o) { // base::operator/=
+    foo_ /= o.foo_; return *this; }
 
-  int operator% (base const& o) const // base::operator%
-  { return foo_ % o.foo_; }
+  int operator% (base const& o) const { // base::operator%
+    return foo_ % o.foo_; }
   
-  base operator%= (base const& o) // base::operator%=
-  { foo_ %= o.foo_; return *this; }
+  base operator%= (base const& o) { // base::operator%=
+    foo_ %= o.foo_; return *this; }
 
-  bool operator< (base const& o) const // base::operator<
-  { return foo_ < o.foo_; }
+  bool operator< (base const& o) const { // base::operator<
+    return foo_ < o.foo_; }
 
-  bool operator<= (base const& o) const // base::operator<=
-  { return foo_ <= o.foo_; }
+  bool operator<= (base const& o) const { // base::operator<=
+    return foo_ <= o.foo_; }
 
-  bool operator> (base const& o) const // base::operator>
-  { return foo_ > o.foo_; }
+  bool operator> (base const& o) const { // base::operator>
+    return foo_ > o.foo_; }
 
-  bool operator>= (base const& o) const // base::operator>=
-  { return foo_ >= o.foo_; }
+  bool operator>= (base const& o) const { // base::operator>=
+    return foo_ >= o.foo_; }
 
-  bool operator!= (base const& o) const // base::operator!=
-  { return foo_ != o.foo_; }
+  bool operator!= (base const& o) const { // base::operator!=
+    return foo_ != o.foo_; }
 
-  bool operator== (base const& o) const // base::operator==
-  { return foo_ == o.foo_; }
+  bool operator== (base const& o) const { // base::operator==
+    return foo_ == o.foo_; }
 
-  bool operator! (void) const // base::operator!
-  { return !foo_; }
+  bool operator! (void) const { // base::operator!
+    return !foo_; }
 
-  bool operator&& (base const& o) const // base::operator&&
-  { return foo_ && o.foo_; }
+  bool operator&& (base const& o) const { // base::operator&&
+    return foo_ && o.foo_; }
 
-  bool operator|| (base const& o) const // base::operator||
-  { return foo_ || o.foo_; }
+  bool operator|| (base const& o) const { // base::operator||
+    return foo_ || o.foo_; }
 
-  int operator<< (int value) const // base::operator<<
-  { return foo_  << value; }
+  int operator<< (int value) const { // base::operator<<
+    return foo_  << value; }
 
-  base operator<<= (int value) // base::operator<<=
-  { foo_ <<= value; return *this; }
+  base operator<<= (int value) { // base::operator<<=
+    foo_ <<= value; return *this; }
 
-  int operator>> (int value) const // base::operator>>
-  { return foo_  >> value; }
+  int operator>> (int value) const { // base::operator>>
+    return foo_  >> value; }
 
-  base operator>>= (int value) // base::operator>>=
-  { foo_ >>= value; return *this; }
+  base operator>>= (int value) { // base::operator>>=
+    foo_ >>= value; return *this; }
 
-  int operator~ (void) const // base::operator~
-  { return ~foo_; }
+  int operator~ (void) const { // base::operator~
+    return ~foo_; }
 
-  int operator& (base const& o) const // base::operator&
-  { return foo_ & o.foo_; }
+  int operator& (base const& o) const { // base::operator&
+    return foo_ & o.foo_; }
 
-  base operator&= (base const& o) // base::operator&=
-  { foo_ &= o.foo_; return *this; }
+  base operator&= (base const& o) { // base::operator&=
+    foo_ &= o.foo_; return *this; }
 
-  int operator| (base const& o) const // base::operator|
-  { return foo_ | o.foo_; }
+  int operator| (base const& o) const { // base::operator|
+    return foo_ | o.foo_; }
 
-  base operator|= (base const& o) // base::operator|=
-  { foo_ |= o.foo_; return *this; }
+  base operator|= (base const& o) { // base::operator|=
+    foo_ |= o.foo_; return *this; }
   
-  int operator^ (base const& o) const // base::operator^
-  { return foo_ ^ o.foo_; }
+  int operator^ (base const& o) const { // base::operator^
+    return foo_ ^ o.foo_; }
 
-  base operator^= (base const& o) // base::operator^=
-  { foo_ ^= o.foo_; return *this; }
+  base operator^= (base const& o) { // base::operator^=
+    foo_ ^= o.foo_; return *this; }
 
-  base operator= (base const& o) // base::operator=
-  { foo_ = o.foo_; return *this; }
+  base operator= (base const& o) { // base::operator=
+    foo_ = o.foo_; return *this; }
 
-  void operator() (void) const // base::operator()
-  { return; }
+  void operator() (void) const { // base::operator()
+    return; }
 
-  int operator[] (int idx) const // base::operator[]
-  { return idx; }
+  int operator[] (int idx) const { // base::operator[]
+    return idx; }
 
-  void* operator new (size_t size) throw () // base::operator new
-  { return malloc (size); }
+  void* operator new (size_t size) throw () { // base::operator new
+    return malloc (size); }
 
-  void operator delete (void* ptr) // base::operator delete
-  { free (ptr); }
+  void operator delete (void* ptr) { // base::operator delete
+    free (ptr); }
 
-  void* operator new[] (size_t size) throw () // base::operator new[]
-  { return malloc (size); }
+  void* operator new[] (size_t size) throw () { // base::operator new[]
+    return malloc (size); }
 
-  void operator delete[] (void* ptr) // base::operator delete[]
-  { free (ptr); }
+  void operator delete[] (void* ptr) { // base::operator delete[]
+    free (ptr); }
 
-  base const* operator-> (void) const // base::opeartor->
-  { return this; }
+  base const* operator-> (void) const { // base::opeartor->
+    return this; }
 
-  int operator->* (base const& b) const // base::operator->*
-  {  return foo_ * b.foo_; }
+  int operator->* (base const& b) const { // base::operator->*
+    return foo_ * b.foo_; }
 
   operator char* () const { return const_cast<char*> ("hello"); } // base::operator char*
   operator int () const { return 21; } // base::operator int
@@ -298,8 +297,7 @@  class derived : public base1, public base2
 {
   public:
   derived(void) : foo_ (4) { } // derived::derived
-  void a_function (void) const // derived::a_function
-  { 
+  void a_function (void) const { // derived::a_function
     this->base1::a_function ();
     this->base2::a_function ();
   }
diff --git gdb/testsuite/gdb.cp/cpexprs.exp gdb/testsuite/gdb.cp/cpexprs.exp
index e998d10..beceff5 100644
--- gdb/testsuite/gdb.cp/cpexprs.exp
+++ gdb/testsuite/gdb.cp/cpexprs.exp
@@ -54,7 +54,7 @@  proc test_breakpoint {func} {
 # Usage:
 # add NAME TYPE PRINT LST
 # add NAME TYPE PRINT -
-proc add {func type print lst} {
+proc add_type_regexp {func type print lst} {
     global all_functions CONVAR ADDR
 
     set all_functions($func,type) $type
@@ -67,13 +67,17 @@  proc add {func type print lst} {
     regsub {\(void\)} $print {()} print
 
     set all_functions($func,print) \
-	"$CONVAR = {[string_to_regexp $type]} $ADDR <[string_to_regexp $print].*>"
+	"$CONVAR = {$type} $ADDR <[string_to_regexp $print].*>"
     if {$lst == "-"} {
 	set lst "$func"
     }
     set all_functions($func,list) ".*// [string_to_regexp $lst]"
 }
 
+proc add {func type print lst} {
+    add_type_regexp $func [string_to_regexp $type] $print $lst
+}
+
 proc get {func cmd} {
     global all_functions
     return $all_functions($func,$cmd)
@@ -139,32 +143,40 @@  add {base2::a_function} \
 
 # On targets using the ARM EABI, the constructor is expected to return
 # "this".
-proc ctor { type arglist } {
+proc ctor_ret { type } {
     if { [istarget arm*-*eabi*] } {
-	set ret "$type *"
+	return "$type *"
     } else {
-	set ret "void "
+	return "void "
     }
+}
+
+proc ctor_prefix { type } {
+    set ret [ctor_ret $type]
+    return "${ret}($type * const"
+}
+
+proc ctor { type arglist } {
     if { $arglist != "" } {
 	set arglist ", $arglist"
     }
-    return "${ret}($type * const$arglist)"
+    return "[ctor_prefix $type]$arglist)"
 }
 
 add {derived::derived} \
     [ctor derived ""] \
     - \
     -
-add {base1::base1(void)} \
-    [ctor base1 "const void ** const"] \
+add_type_regexp {base1::base1(void)} \
+    "[string_to_regexp [ctor_prefix base1]], (const )?void \\*\\*( const)?\\)" \
     - \
     -
 add {base1::base1(int)} \
     [ctor base1 "int"] \
     - \
     -
-add {base2::base2} \
-    [ctor base2 "const void ** const"] \
+add_type_regexp {base2::base2} \
+    "[string_to_regexp [ctor_prefix base2]], (const )?void \\*\\*( const)?\\)" \
     - \
     -
 add {base::base(void)} \