# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

# Please email any bugs, comments, and/or additions to this file to:
# bug-gdb@prep.ai.mit.edu

# This file was written by Fred Fish. (fnf@cygnus.com)

if $tracelevel then {
	strace $tracelevel
}

#
# Test ptype of class objects.
#

proc test_ptype_class_objects {} {
    global prompt

    # Note that struct members are public by default, so we don't print
    # "public:" for the public members of structs.
    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype struct default_public_struct\n"
    expect {
	-re "type = struct default_public_struct \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\}\r\n$prompt $" {
	    pass "ptype struct default_public_struct"
	}
	-re "type = class default_public_struct \{\r\n.*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype struct default_public_struct"
	}
	-re ".*$prompt $" { fail "ptype struct default_public_struct" }
	timeout { fail "ptype struct default_public_struct (timeout)" ; return }
    }

    # Note that struct members are public by default, so we don't print
    # "public:" for the public members of structs.
    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype struct explicit_public_struct\n"
    expect {
	-re "type = struct explicit_public_struct \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    pass "ptype struct explicit_public_struct"
	}
	-re "type = class explicit_public_struct \{\r\n.*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype struct explicit_public_struct"
	}
	-re ".*$prompt $" { fail "ptype struct explicit_public_struct" }
	timeout { fail "ptype struct explicit_public_struct (timeout)" ; return }
    }

    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype struct protected_struct\n"
    expect {
	-re "type = struct protected_struct \{\r\n\[ \]*protected:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\}\r\n$prompt $" {
	    pass "ptype struct protected_struct (FIXME)"
	}
	-re "type = class protected_struct \{\r\n\[ \]*protected:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype struct protected_struct (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype struct protected_struct" }
	timeout { fail "ptype struct protected_struct (timeout)" ; return }
    }

    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype struct private_struct\n"
    expect {
	-re "type = struct private_struct \{\r\n\[ \]*private:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\}\r\n$prompt $" {
	    pass "ptype struct private_struct (FIXME)"
	}
	-re "type = class private_struct \{\r\n\[ \]*private:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" { 
	    setup_xfail "*-*-*"
	    fail "ptype struct private_struct (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype struct private_struct" }
	timeout { fail "ptype struct private_struct (timeout)" ; return }
    }

    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype struct mixed_protection_struct\n"
    expect {
	-re "type = struct mixed_protection_struct \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\[ \]*private:\r\n\[ \]*int c;\r\n\[ \]*int d;\r\n\[ \]*protected:\r\n\[ \]*int e;\r\n\[ \]*int f;\r\n\[ \]*public:\r\n\[ \]*int g;\r\n\[ \]*private:\r\n\[ \]*int h;\r\n\[ \]*protected:\r\n\[ \]*int i;\r\n\}\r\n$prompt $" {
	    pass "ptype struct mixed_protection_struct (FIXME)"
	}
	-re "type = class mixed_protection_struct \{\r\n\[ \]*public:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\[ \]*private:\r\n\[ \]*int c;\r\n\[ \]*int d;\r\n\[ \]*protected:\r\n\[ \]*int e;\r\n\[ \]*int f;\r\n\[ \]*public:\r\n\[ \]*int g;\r\n\[ \]*private:\r\n\[ \]*int h;\r\n\[ \]*protected:\r\n\[ \]*int i;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype struct mixed_protection_struct (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype struct mixed_protection_struct" }
	timeout { fail "ptype struct mixed_protection_struct (timeout)" ; return }
    }

    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype class public_class\n"
    expect {
	-re "type = class public_class \{\r\n\[ \]*public:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    pass "ptype class public_class (FIXME)"
	}
	-re "type = struct public_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class public_class (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype class public_class" }
	timeout { fail "ptype class public_class (timeout)" ; return }
    }

    send "ptype class protected_class\n"
    expect {
	-re "type = class protected_class \{\r\n\[ \]*protected:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    pass "ptype class protected_class"
	}
	-re "type = struct protected_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class protected_class"
	}
	-re ".*$prompt $" { fail "ptype class protected_class" }
	timeout { fail "ptype class protected_class (timeout)" ; return }
    }

    # Accept it as an expected failure if gdb just emits a superflous "private:"
    # attribute, since classes default to private and for consistency with
    # structs (where we don't print the "public:" attribute) we don't print
    # the "private:" attribute.

    send "ptype class default_private_class\n"
    expect {
	-re "type = class default_private_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    pass "ptype class default_private_class (FIXME)"
	}
	-re "type = class default_private_class \{\r\n\[ \]*private:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class default_private_class (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype class default_private_class" }
	timeout { fail "ptype class default_private_class (timeout)" ; return }
    }

    send "ptype class explicit_private_class\n"
    expect {
	-re "type = class explicit_private_class \{\r\n\[ \]*private:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    pass "ptype class explicit_private_class"
	}
	-re "type = struct explicit_private_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class explicit_private_class"
	}
	-re ".*$prompt $" { fail "ptype class explicit_private_class" }
	timeout { fail "ptype class explicit_private_class (timeout)" ; return }
    }

    send "ptype class mixed_protection_class\n"
    expect {
	-re "type = class mixed_protection_class \{\r\n\[ \]*public:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\[ \]*private:\r\n\[ \]*int c;\r\n\[ \]*int d;\r\n\[ \]*protected:\r\n\[ \]*int e;\r\n\[ \]*int f;\r\n\[ \]*public:\r\n\[ \]*int g;\r\n\[ \]*private:\r\n\[ \]*int h;\r\n\[ \]*protected:\r\n\[ \]*int i;\r\n.*\}\r\n$prompt $" {
	    pass "ptype class mixed_protection_class"
	}
	-re "type = struct mixed_protection_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\[ \]*int c;\r\n\[ \]*int d;\r\n\[ \]*int e;\r\n\[ \]*int f;\r\n\[ \]*int g;\r\n\[ \]*int h;\r\n\[ \]*int i;\r\n.*\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class mixed_protection_class"
	}
	-re ".*$prompt $" { fail "ptype class mixed_protection_class" }
	timeout { fail "ptype class mixed_protection_class (timeout)" ; return }
    }

    # This class does not use any C++-specific features, so it's fine for
    # it to print as "struct".
    send "ptype class A\n"
    expect {
	-re "type = class A \{\r\n\[ \]*public:\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n(\[\r\n\t \]+A\\(void\\);|)(\[\r\n\t \]+A\\(A const &\\);|)(\[\r\n\t \]+A & operator=\\(A const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    pass "ptype class A"
	}
	-re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$prompt $" {
	    pass "ptype class A"
	}
	-re ".*$prompt $" { fail "ptype class A" }
	timeout { fail "ptype class A (timeout)" ; return }
    }

    # Accept it as an expected failure if gdb just fails to distinguish between
    # class and struct, and everything else is OK.

    send "ptype class B\n"
    expect {
	-re "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;(\[\r\n\t \]+B\\(void\\);|)(\[\r\n\t \]+B\\(B const &\\);|)(\[\r\n\t \]+B & operator=\\(B const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    pass "ptype class B"
	}
	-re "type = struct B \{\r\n\[ \]*struct A A;\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class B"
	}
	-re ".*$prompt $" { fail "ptype class B" }
	timeout { fail "ptype class B (timeout)" ; return }
    }

    send "ptype class C\n"
    expect {
	-re "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;(\[\r\n\t \]+C\\(void\\);|)(\[\r\n\t \]+C\\(C const &\\);|)(\[\r\n\t \]+C & operator=\\(C const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    pass "ptype class C"
	}
	-re "type = struct C \{\r\n\[ \]*struct A A;\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class C"
	}
	-re ".*$prompt $" { fail "ptype class C" }
	timeout { fail "ptype class C (timeout)" ; return }
    }

    send "ptype class D\n"
    expect {
	-re "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;(\[\r\n\t \]+D\\(void\\);|)(\[\r\n\t \]+D\\(D const &\\);|)(\[\r\n\t \]+D & operator=\\(D const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    pass "ptype class D"
	}
	-re "type = struct D \{\r\n\[ \]*struct B B;\r\n\[ \]*struct C C;\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class D"
	}
	-re ".*$prompt $" { fail "ptype class D" }
	timeout { fail "ptype class D (timeout)" ; return }
    }

    send "ptype class E\n"
    expect {
	-re "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;(\[\r\n\t \]+E\\(void\\);|)(\[\r\n\t \]+E\\(E const &\\);|)(\[\r\n\t \]+E & operator=\\(E const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    pass "ptype class D"
	}
	-re "type = struct E \{\r\n\[ \]*struct D D;\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class D"
	}
	-re ".*$prompt $" { fail "ptype class E" }
	timeout { fail "ptype class E (timeout)" ; return }
    }

    # This class does not use any C++-specific features, so it's fine for
    # it to print as "struct".
    send "ptype class vA\n"
    expect {
	-re "type = class vA \{\r\n\[ \]*public:\r\n\[ \]*int va;\r\n\[ \]*int vx;(\[\r\n\t \]+vA\\(void\\);|)(\[\r\n\t \]+vA\\(vA const &\\);|)(\[\r\n\t \]+vA & operator=\\(vA const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    pass "ptype class vA"
	}
	-re "type = struct vA \{\r\n\[ \]*int va;\r\n\[ \]*int vx;\r\n\}\r\n$prompt $" {
	    pass "ptype class vA"
	}
	-re ".*$prompt $" { fail "ptype class vA" }
	timeout { fail "ptype class vA (timeout)" ; return }
    }

    # Accept the form with embedded GNU style mangled virtual table constructs
    # for now, but with a FIXME.  At some future point, gdb should use a
    # portable representation for the virtual table constructs.

    send "ptype class vB\n"
    expect {
	-re "type = class vB : public virtual vA \{\r\n\[ \]*private:\r\n\[ \]*vA \[*\]+_vb.vA;\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;(\[\r\n\t \]+vB\\(int\\);|)(\[\r\n\t \]+vB\\(int, vB const &\\);|)(\[\r\n\t \]+vB & operator=\\(vB const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class vB (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype class vB" }
	timeout { fail "ptype class vB (timeout)" ; return }
    }

    # Accept the form with embedded GNU style mangled virtual table constructs
    # for now, but with a FIXME.  At some future point, gdb should use a
    # portable representation for the virtual table constructs.

    send "ptype class vC\n"
    expect {
	-re "type = class vC : public virtual vA \{\r\n\[ \]*private:\r\n\[ \]*vA \[*\]+_vb.vA;\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;(\[\r\n\t \]+vC\\(int\\);|)(\[\r\n\t \]+vC\\(int, vC const &\\);|)(\[\r\n\t \]+vC & operator=\\(vC const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class vC (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype class vC" }
	timeout { fail "ptype class vC (timeout)" ; return }
    }

    # Accept the form with embedded GNU style mangled virtual table constructs
    # for now, but with a FIXME.  At some future point, gdb should use a
    # portable representation for the virtual table constructs.

    send "ptype class vD\n"
    expect {
	-re "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]+private:\r\n\[ \]+vC \[*\]+_vb.vC;\r\n\[ \]+vB \[*\]+_vb.vB;\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;(\[\r\n\t \]+vD\\(int\\);|)(\[\r\n\t \]+vD\\(int, vD const &\\);|)(\[\r\n\t \]+vD & operator=\\(vD const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class vD (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype class vD" }
	timeout { fail "ptype class vD (timeout)" ; return }
    }

    # Accept the form with embedded GNU style mangled virtual table constructs
    # for now, but with a FIXME.  At some future point, gdb should use a
    # portable representation for the virtual table constructs.

    send "ptype class vE\n"
    expect {
	-re "type = class vE : public virtual vD \{\r\n\[ \]*private:\r\n\[ \]*vD \[*\]+_vb.vD;\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;(\[\r\n\t \]+vE\\(int\\);|)(\[\r\n\t \]+vE\\(int, vE const &\\);|)(\[\r\n\t \]+vE & operator=\\(vE const &\\);|)\[\r\n\t \]+\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class vE (FIXME)"
	}
	-re ".*$prompt $" { fail "ptype class vE" }
	timeout { fail "ptype class vE (timeout)" ; return }
    }

    send "ptype class Base1\n"
    expect {
	-re "type = class Base1 \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\r\n(\[ \]+Base1\\(Base1 const &\\);\r\n|)\[ \]+Base1\\(int\\);\r\n(\[ \]+Base1\\(Base1 const &\\);\r\n|)(\[ \]+Base1 & operator=\\(Base1 const &\\);\r\n|)\}\r\n$prompt $" {
	    pass "ptype class Base1"
	}
	-re "type = struct Base1 \{\r\n\[ \]*int x;\r\n\}\r\n$prompt $" {
	    fail "ptype class Base1"
	}
	-re ".*$prompt $" { fail "ptype class Base1" }
	timeout { fail "ptype class Base1 (timeout)" ; return }
    }

    send "ptype class Foo\n"
    expect {
	-re "type = class Foo \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\[ \]*static int st;\r\n\r\n(\[ \]+Foo\\(Foo const &\\);\r\n|)\[ \]+Foo\\(int, int\\);\r\n(\[ \]+Foo\\(Foo const &\\);\r\n|)(\[ \]+Foo & operator=\\(Foo const &\\);\r\n|)\[ \]*int operator!.void.;\r\n\[ \]*int operator int.void.;\r\n\[ \]*int times.int.;\r\n\}\r\n$prompt $" {
	    pass "ptype class Foo"
	}
	-re "type = class Foo \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\[ \]*static int st;\r\n\r\n(\[ \]+Foo\\(Foo const &\\);\r\n|)\[ \]+Foo\\(int, int\\);\r\n(\[ \]+Foo\\(Foo const &\\);\r\n\[ \]*int operator int.void.;\r\n|)(\[ \]+Foo & operator=\\(Foo const &\\);\r\n|)\[ \]*int operator!.void.;\r\n\[ \]*int times.int.;\r\n\}\r\n$prompt $" {
	    pass "ptype class Foo"
	}
	-re "type = struct Foo \{\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class Foo"
	}
	-re ".*$prompt $" { fail "ptype class Foo" }
	timeout { fail "ptype class Foo (timeout)" ; return }
    }

    send "ptype class Bar\n"
    expect {
	-re "type = class Bar : public Base1, public Foo \{\r\n\[ \]*public:\r\n\[ \]*int z;\r\n\r\n(\[ \]+Bar\\(Bar const &\\);\r\n|)\[ \]+Bar\\(int, int, int\\);\r\n(\[ \]+Bar\\(Bar const &\\);\r\n|)(\[ \]+Bar & operator=\\(Bar const &\\);\r\n|)\}\r\n$prompt $" {
	    pass "ptype class Bar"
	}
	-re "type = struct Bar \{\r\n\[ \]*struct Base1 Base1;\r\n\[ \]*struct Foo Foo;\r\n\[ \]*int z;\r\n\}\r\n$prompt $" {
	    setup_xfail "*-*-*"
	    fail "ptype class Bar"
	}
	-re ".*$prompt $" { fail "ptype class Bar" }
	timeout { fail "ptype class Bar (timeout)" ; return }
    }
}

#
# Test simple access to class members.
#

proc test_non_inherited_member_access {} {
    global prompt
    
    # Print non-inherited members of g_A.

    send "print g_A.a\n"
    expect {
	-re ".* = 1\r\n$prompt $" { pass "g_A.a incorrect" }
	-re ".*$prompt $" { fail "g_A.a incorrect" }
	timeout { fail "print g_A.a (timeout)" ; return }
    }

    send "print g_A.x\n"
    expect {
	-re ".* = 2\r\n$prompt $" { pass "g_A.x incorrect" }
	-re ".*$prompt $" { fail "g_A.x incorrect" }
	timeout { fail "print g_A.x (timeout)" ; return }
    }

    # Print non-inherited members of g_B.

    send "print g_B.b\n"
    expect {
	-re ".* = 5\r\n$prompt $" { pass "g_B.b incorrect" }
	-re ".*$prompt $" { fail "g_B.b incorrect" }
	timeout { fail "print g_B.b (timeout)" ; return }
    }

    send "print g_B.x\n"
    expect {
	-re ".* = 6\r\n$prompt $" { pass "g_B.x incorrect" }
	-re ".*$prompt $" { fail "g_B.x incorrect" }
	timeout { fail "print g_B.x (timeout)" ; return }
    }

    # Print non-inherited members of g_C.

    send "print g_C.c\n"
    expect {
	-re ".* = 9\r\n$prompt $" { pass "g_C.c incorrect" }
	-re ".*$prompt $" { fail "g_C.c incorrect" }
	timeout { fail "print g_C.c (timeout)" ; return }
    }

    send "print g_C.x\n"
    expect {
	-re ".* = 10\r\n$prompt $" { pass "g_C.x incorrect" }
	-re ".*$prompt $" { fail "g_C.x incorrect" }
	timeout { fail "print g_C.x (timeout)" ; return }
    }

    # Print non-inherited members of g_D.

    send "print g_D.d\n"
    expect {
	-re ".* = 19\r\n$prompt $" { pass "g_D.d incorrect" }
	-re ".*$prompt $" { fail "g_D.d incorrect" }
	timeout { fail "print g_D.d (timeout)" ; return }
    }

    send "print g_D.x\n"
    expect {
	-re ".* = 20\r\n$prompt $" { pass "g_D.x incorrect" }
	-re ".*$prompt $" { fail "g_D.x incorrect" }
	timeout { fail "print g_D.x (timeout)" ; return }
    }

    # Print non-inherited members of g_E.

    send "print g_E.e\n"
    expect {
	-re ".* = 31\r\n$prompt $" { pass "g_E.e incorrect" }
	-re ".*$prompt $" { fail "g_E.e incorrect" }
	timeout { fail "print g_E.e (timeout)" ; return }
    }

    send "print g_E.x\n"
    expect {
	-re ".* = 32\r\n$prompt $" { pass "g_E.x incorrect" }
	-re ".*$prompt $" { fail "g_E.x incorrect" }
	timeout { fail "print g_E.x (timeout)" ; return }
    }
}

#
# Try access to non-members that are members of another class.
# Should give errors.
#

proc test_wrong_class_members {} {
    global prompt

    send "print g_A.b\n"
    expect {
	-re "There is no member( or method|) named b.\r\n$prompt $" { pass "print g_A.b should be error" }
	-re ".*$prompt $" { fail "print g_A.b should be error" }
	timeout { fail "print g_A.b (timeout)" ; return }
    }

    send "print g_B.c\n"
    expect {
	-re "There is no member( or method|) named c.\r\n$prompt $" { pass "print g_B.c should be error" }
	-re ".*$prompt $" { fail "print g_B.c should be error" }
	timeout { fail "print g_B.c (timeout)" ; return }
    }

    send "print g_B.d\n"
    expect {
	-re "There is no member( or method|) named d.\r\n$prompt $" { pass "print g_B.d should be error" }
	-re ".*$prompt $" { fail "print g_B.d should be error" }
	timeout { fail "print g_B.d (timeout)" ; return }
    }

    send "print g_C.b\n"
    expect {
	-re "There is no member( or method|) named b.\r\n$prompt $" { pass "print g_C.b should be error" }
	-re ".*$prompt $" { fail "print g_C.b should be error" }
	timeout { fail "print g_C.b (timeout)" ; return }
    }

    send "print g_C.d\n"
    expect {
	-re "There is no member( or method|) named d.\r\n$prompt $" { pass "print g_C.d should be error" }
	-re ".*$prompt $" { fail "print g_C.d should be error" }
	timeout { fail "print g_C.d (timeout)" ; return }
    }

    send "print g_D.e\n"
    expect {
	-re "There is no member( or method|) named e.\r\n$prompt $" { pass "print g_D.e should be error" }
	-re ".*$prompt $" { fail "print g_D.e should be error" }
	timeout { fail "print g_D.e (timeout)" ; return }
    }
}

#
# Try access to non-members that are not members of any class.
# Should give errors.
#

proc test_nonexistant_members {} {
    global prompt

    send "print g_A.y\n"
    expect {
	-re "There is no member( or method|) named y.\r\n$prompt $" { pass "print g_A.y should be error" }
	-re ".*$prompt $" { fail "print g_A.y should be error" }
	timeout { fail "print g_A.y (timeout)" ; return }
    }

    send "print g_B.z\n"
    expect {
	-re "There is no member( or method|) named z.\r\n$prompt $" { pass "print g_B.z should be error" }
	-re ".*$prompt $" { fail "print g_B.z should be error" }
	timeout { fail "print g_B.z (timeout)" ; return }
    }

    send "print g_C.q\n"
    expect {
	-re "There is no member( or method|) named q.\r\n$prompt $" { pass "print g_C.q should be error" }
	-re ".*$prompt $" { fail "print g_C.q should be error" }
	timeout { fail "print g_C.q (timeout)" ; return }
    }

    send "print g_D.p\n"
    expect {
	-re "There is no member( or method|) named p.\r\n$prompt $" { pass "print g_D.p should be error" }
	-re ".*$prompt $" { fail "print g_D.p should be error" }
	timeout { fail "print g_D.p (timeout)" ; return }
    }
}

#
# Pointers to class members
#

proc test_pointers_to_class_members {} {
    global prompt
    global decimal

    send "print Bar::z\n"
    expect {
	-re ".* = .int\[ \]*\[( \]*Bar::&\[)\]+\[ \]*Bar::z\r\n$prompt $" {
	    pass "print Bar::z"
	}
	-re ".*$prompt $" { fail "print Bar::z" }
	timeout { fail "print Bar::z (timeout)" ; return }
    }

    send "print &Foo::x\n"
    expect {
	-re ".* = .int\[ \]*\[( \]*Foo::\[*)\]+\[ \]*&Foo::x\r\n$prompt $" {
	    pass "print &Foo::x"
	}
	-re ".*$prompt $" { fail "print &Foo::x" }
	timeout { fail "print &Foo::x (timeout)" ; return }
    }

    send "print (int)&Foo::x\n"
    expect {
	-re ".* = 0\r\n$prompt $" {
	    pass "print (int)&Foo::x"
	}
	-re ".*$prompt $" { fail "print (int)&Foo::x" }
	timeout { fail "print (int)&Foo::x (timeout)" ; return}
    }

    send "print (int)&Bar::y == 2*sizeof(int)\n"
    expect {
	-re ".* = 1\r\n$prompt $" {
	    pass "print (int)&Bar::y == 2*sizeof(int)"
	}
	-re "There is no field named y.*$prompt $" {
	    setup_xfail "*-*-*"
	    fail "print (int)&Bar::y == 2*sizeof(int)"
	}
	-re ".*$prompt $" { fail "print (int)&Bar::y == 2*sizeof(int)" }
	timeout { fail "print (int)&Bar::y == 2*sizeof(int) (timeout)" ; return }
    }

    send "next\n"
    setup_xfail "*-*-*"
    expect {
	-re "$decimal\[ \t\]+inheritance3 \[)(\]+;\r\n$prompt $" {}
	-re ".*$prompt $" { fail "next to inheritance3" ; return }
    }

    send "print (int)pmi == sizeof(int)\n"
    expect {
	-re ".* = 0\r\n$prompt $" {
	    pass "print (int)pmi == sizeof(int)"
	}
	-re ".*$prompt $" { fail "print (int)pmi == sizeof(int)" }
	timeout { fail "print (int)pmi == sizeof(int) (timeout)" ; return }
    }
}

#
# Test static members.
#

proc test_static_members {} {
    global prompt
    global hex

    send "print Foo::st\n"
    expect {
	-re ".* = 100\r\n$prompt $" {
	    pass "print Foo::st"
	}
	-re "There is no field named st.*$prompt $" {
	    setup_xfail "*-*-*"
	    fail "print Foo::st"
	}
	-re ".*$prompt $" { fail "print Foo::st" }
       timeout { fail "print Foo::st (timeout)" ; return }
    }

    send "set foo.st = 200\n"
    expect {
	-re ".*$prompt $" {}
    }

    send "print bar.st\n"
    expect {
	-re ".* = 200\r\n$prompt $" {
	    pass "print bar.st"
	}
	-re "There is no member( or method|) named st.*$prompt $" {
	    setup_xfail "*-*-*"
	    fail "print bar.st"
	}
	-re ".*$prompt $" { fail "print bar.st" }
       timeout { fail "print bar.st (timeout)" ; return }
    }

    send "print &foo.st\n"
    expect {
	-re ".* = .int \[*)\]+ $hex\r\n$prompt $" {
	    pass "print &foo.st"
	}
	-re "There is no member( or method|) named st.*$prompt $" {
	    setup_xfail "*-*-*"
	    fail "print &foo.st"
	}
	-re ".*$prompt $" { fail "print &foo.st" }
       timeout { fail "print &foo.st (timeout)" ; return }
    }

    set got_bar_st 0
    send "print &Bar::st\n"
    expect {
	-re ".* = .int \[*)\]+ $hex\r\n$prompt $" {
	    pass "print &Bar::st"
	    set got_bar_st 1
	}
	-re "There is no field named st.*$prompt $" {
	    setup_xfail "*-*-*"
	    fail "print &Bar::st"
	}
	-re ".*$prompt $" { fail "print &Bar::st" }
       timeout { fail "print &Bar::st (timeout)" ; return }
    }

    if $got_bar_st then {
	send "print *\$\n"
	expect {
	    -re ".* = 200\r\n$prompt $" {
		pass "print *\$"
	    }
	    -re ".*$prompt $" { fail "print *\$" }
           timeout { fail "print *\$ (timeout)" ; return }
	}
    }

    gdb_test "set print static-members off" ""
    gdb_test "print csi" \
	"{x = 10, y = 20}" \
	"print csi without static members"
    gdb_test "print cnsi" \
	"{x = 30, y = 40}" \
	"print cnsi without static members"

    gdb_test "set print static-members on" ""
    gdb_test "print csi" \
	"{x = 10, y = 20, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>}}" \
	"print csi with static members"
    gdb_test "print cnsi" \
	"{x = 30, y = 40, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>, static yy = {z = 5, static xx = {x = 1, y = 2, static null = <same as static member of an already seen type>, static yy = <same as static member of an already seen type>}}}, static yy = <same as static member of an already seen type>}" \
	"print cnsi with static members"
}

proc do_tests {} {
    global prms_id
    global bug_id
    global subdir
    global objdir
    global srcdir
    global binfile
    global prompt

    set prms_id 0
    set bug_id 0

    # Start with a fresh gdb.

    gdb_exit
    gdb_start
    gdb_reinitialize_dir $srcdir/$subdir
    gdb_load $objdir/$subdir/$binfile

    send "set language c++\n"
    expect -re "$prompt $"
    send "set width 0\n"
    expect -re "$prompt $"

    test_ptype_class_objects

    if [ runto 'inheritance2(void)' ] then {
	test_non_inherited_member_access
	test_wrong_class_members
	test_nonexistant_members
    }

    if [istarget "mips-idt-*"] then {
	# Restart because IDT/SIM runs out of file descriptors.
	gdb_exit
	gdb_start
	gdb_reinitialize_dir $srcdir/$subdir
	gdb_load $objdir/$subdir/$binfile
    }

    if [ runto_main ] then {
	test_pointers_to_class_members
	test_static_members
    }

    if [istarget "mips-idt-*"] then {
	# Restart because IDT/SIM runs out of file descriptors.
	gdb_exit
	gdb_start
	gdb_reinitialize_dir $srcdir/$subdir
	gdb_load $objdir/$subdir/$binfile
    }
 
    if [ runto marker_reg1 ] then {

	gdb_test "finish" "Run till exit from.*" "finish from marker_reg1"

	send "print v.method ()\n"
	expect {
	    -re "= 82.*$prompt $" {
		pass "calling method for small class"
	    }
	    -re "Address requested for identifier .v. which is in a register.*$prompt $" {
		setup_xfail "*-*-*" 2972
		fail "calling method for small class"
	    }
	    -re ".*$prompt $" { fail "calling method for small class" }
	    timeout { fail "calling method for small class (timeout)" }
	    eof { fail "calling method for small class (eof)" }
	}
    }

}

# Check to see if we have an executable to test.  If not, then either we
# haven't tried to compile one, or the compilation failed for some reason.
# In either case, just notify the user and skip the tests in this file.

set binfile "misc"
set srcfile $binfile.cc

if ![file exists $objdir/$subdir/$binfile] then {
    warning "$binfile does not exist; tests suppressed."
} else {
    do_tests
}
