This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[rfa] teach parser about C++ nested types
- From: David Carlton <carlton at kealia dot com>
- To: gdb-patches at sources dot redhat dot com
- Cc: Daniel Jacobowitz <drow at mvista dot com>
- Date: Wed, 24 Sep 2003 17:27:31 -0700
- Subject: [rfa] teach parser about C++ nested types
A recap of the state of C++: our main goal is to embrace nested types.
So if you have a type (a class, a namespace, a typedef, whatever) D
defined within a class or namespace C, then the symbol associated to
that type should be called C::D, and our parsers, evaluators,
etc. should be happy about that.
The current state of affairs is: right now we only generate symbols
with the right names if both C and D are namespaces, and the parsers,
etc. are fairly ignorant of the situation. So we have two issues to
deal with:
1) Generate all the symbols correctly.
2) Tell the parsers, etc. to use them.
This patch implements some of issue 2. This seems to be the correct
order: if we finish implementing issue 1 before doing any of issue 2,
probably the parser will get really confused, but fortunately the fact
that we've done just a bit of issue 1 (namely nested namespaces) means
that, if we implement issue 2 now, we can test it.
Specifically, what this patch does is:
* Move parsing of names containing '::' completely out of the lexer,
so it's all in the parser. As I comment in the code, this is a
lesser-of-two-evils choice; I've tried working on the lexer instead,
and it just didn't work as well.
* Tell eval.c that, when it encounters an OP_SCOPE, to call a new
function value_aggregate_elt instead of
value_struct_elt_for_reference.
* Teach value_aggregate_elt about namespaces.
Some of this code will need to be slightly tweaked when we start
generating appropriately-named symbols for other nested types; this
gets the infrastructure in place, however.
More details available on request. When reading through the code, be
alert for possible coding style mistakes I might have made: it's been
a few months since I've been immersed in GDB's house style, so I might
well have spaces in the wrong place or something. (Fortunately, most
of this code is cut and pasted from my branch, and was originally
written when I was immersed in GDB's house style.)
Tested on i686-pc-linux-gnu, GCC 3.2, with DWARF 2, with a version
patched to generate DW_TAG_namespace, and with stabs. In no cases
were there any regressions; in both DWARF 2 cases, all the new tests
pass, while in the stabs case, all the new tests fail (which is
expected).
Ok to commit? I think I only need approval from Daniel for this one;
it doesn't touch symtab stuff at all.
David Carlton
carlton@kealia.com
2003-09-24 David Carlton <carlton@kealia.com>
* c-exp.y: Include cp-support.h. Add qualified_type.
(yylex): Comment out nested type hack; add comments.
* cp-namespace.c (cp_lookup_nested_type): New function.
* cp-support.h: Declare cp_lookup_nested_type.
* eval.c (evaluate_subexp_standard): Call value_aggregate_elt
instead of value_struct_elt_for_reference.
* valops.c: Include cp-support.h.
(value_aggregate_elt): New function.
(value_namespace_elt): Ditto.
(value_struct_elt_for_reference): Make static.
* value.h: Delete declaration of value_struct_elt_for_reference;
add declaration for value_aggregate_elt.
* Makefile.in (c-exp.tab.o): Depend on $(cp_support_h).
(valops.o): Ditto.
2003-09-24 David Carlton <carlton@kealia.com>
* gdb.cp/namespace.exp: Tweak comments. Add non-quoted versions
of some print tests, where appropriate. Add tests for C::D::cd,
E::ce, F::cXfX, G::XgX.
* gdb.cp/namespace.cc: Add XgX, cXfX, ce.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.445
diff -u -p -r1.445 Makefile.in
--- Makefile.in 17 Sep 2003 21:34:29 -0000 1.445
+++ Makefile.in 24 Sep 2003 23:38:31 -0000
@@ -1412,7 +1412,7 @@ ada-lex.c: ada-lex.l
.PRECIOUS: c-exp.tab.c
c-exp.tab.o: c-exp.tab.c $(defs_h) $(gdb_string_h) $(expression_h) \
$(value_h) $(parser_defs_h) $(language_h) $(c_lang_h) $(bfd_h) \
- $(symfile_h) $(objfiles_h) $(charset_h) $(block_h)
+ $(symfile_h) $(objfiles_h) $(charset_h) $(block_h) $(cp_support_h)
c-exp.tab.c: c-exp.y
$(SHELL) $(YLWRAP) "$(YACC)" \
$(srcdir)/c-exp.y y.tab.c c-exp.tmp -- $(YFLAGS)
@@ -2417,7 +2417,8 @@ valarith.o: valarith.c $(defs_h) $(value
valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(block_h) $(infcall_h) \
- $(dictionary_h) $(cp_support_h) $(gdb_string_h) $(gdb_assert_h)
+ $(dictionary_h) $(cp_support_h) $(gdb_string_h) $(gdb_assert_h) \
+ $(cp_support_h)
valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \
$(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h)
Index: c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.21
diff -u -p -r1.21 c-exp.y
--- c-exp.y 18 May 2003 17:39:45 -0000 1.21
+++ c-exp.y 24 Sep 2003 23:38:31 -0000
@@ -51,6 +51,7 @@ Foundation, Inc., 59 Temple Place - Suit
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
#include "charset.h"
#include "block.h"
+#include "cp-support.h"
/* Flag indicating we're dealing with HP-compiled objects */
extern int hp_som_som_object_present;
@@ -153,7 +154,7 @@ static int parse_number (char *, int, in
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
%type <lval> rcurly
-%type <tval> type typebase
+%type <tval> type typebase qualified_type
%type <tvec> nonempty_typelist
/* %type <bval> block */
@@ -595,7 +596,8 @@ qualified_name: typebase COLONCOLON name
{
struct type *type = $1;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
- && TYPE_CODE (type) != TYPE_CODE_UNION)
+ && TYPE_CODE (type) != TYPE_CODE_UNION
+ && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
@@ -609,7 +611,8 @@ qualified_name: typebase COLONCOLON name
struct type *type = $1;
struct stoken tmp_token;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
- && TYPE_CODE (type) != TYPE_CODE_UNION)
+ && TYPE_CODE (type) != TYPE_CODE_UNION
+ && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
@@ -888,6 +891,54 @@ typebase /* Implements (approximately):
{ $$ = follow_types ($2); }
| typebase const_or_volatile_or_space_identifier_noopt
{ $$ = follow_types ($1); }
+ | qualified_type
+ ;
+
+/* FIXME: carlton/2003-09-24: This next bit leads to lots of
+ reduce-reduce conflicts, because the parser doesn't know whether or
+ not to use qualified_name or qualified_type. There's no good way
+ to fix this with the grammar as it stands; as far as I can tell,
+ some of the problems arise from ambiguities that GDB introduces
+ ('start' can be either an expression or a type), but some of it is
+ inherent to the nature of C++ (you want to treat the input "(FOO)"
+ fairly differently depending on whether FOO is an expression or a
+ type, and if FOO is a complex expression, this can be hard to
+ determine at the right time.
+
+ Perhaps we could fix this by making the lexer smarter. Some of
+ this functionality used to be in the lexer, but in a way that
+ worked even less well than the current solution: life is much
+ easier if either the parser always handles '::' or the lexer always
+ handles it. Ideally, the code in question could be shared by the
+ lexer and by decode_line_1. I'm not holding my breath waiting for
+ somebody to get around to cleaning this up, however... */
+
+/* FIXME: carlton/2003-09-24: Currently, the only qualified type
+ symbols that we generate are nested namespaces. Next on my TODO
+ list is to generate all nested type names properly (or at least as
+ well as possible, assuming that we're using DWARF-2). */
+
+qualified_type: typebase COLONCOLON name
+ {
+ struct type *type = $1;
+ struct type *new_type;
+ char *ncopy = alloca ($3.length + 1);
+
+ memcpy (ncopy, $3.ptr, $3.length);
+ ncopy[$3.length] = '\0';
+
+ if (TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
+ error ("`%s' is not defined as a namespace.",
+ TYPE_NAME (type));
+
+ new_type = cp_lookup_nested_type (type, ncopy,
+ expression_context_block);
+ if (new_type == NULL)
+ error ("No type \"%s\" in namespace \"%s\".",
+ ncopy, TYPE_NAME (type));
+
+ $$ = new_type;
+ }
;
typename: TYPENAME
@@ -1633,7 +1684,13 @@ yylex ()
string to get a reasonable class/namespace spec or a
fully-qualified name. This is a kludge to get around the
HP aCC compiler's generation of symbol names with embedded
- colons for namespace and nested classes. */
+ colons for namespace and nested classes. */
+
+ /* NOTE: carlton/2003-09-24: I don't entirely understand the
+ HP-specific code, either here or in linespec. Having said that,
+ I suspect that we're actually moving towards their model: we want
+ symbols whose names are fully qualified, which matches the
+ description above. */
if (unquoted_expr)
{
/* Only do it if not inside single quotes */
@@ -1687,7 +1744,16 @@ yylex ()
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
-#if 1
+ /* FIXME: carlton/2003-09-24: I've turned off the code
+ below, because it seems to me to work better to deal with
+ nested types in the parser instead of the lexer. See the
+ comment before qualified_type for more info. If you're
+ interested in figuring out the code below, be aware that
+ it dates from a time when we handled nested types very
+ differently than we do now, and I don't believe the
+ comments within it had been entirely accurate for a
+ while. */
+#if 0
/* Despite the following flaw, we need to keep this code enabled.
Because we can get called from check_stub_method, if we don't
handle nested types then it screws many operations in any
Index: cp-namespace.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-namespace.c,v
retrieving revision 1.4
diff -u -p -r1.4 cp-namespace.c
--- cp-namespace.c 11 Sep 2003 19:49:17 -0000 1.4
+++ cp-namespace.c 24 Sep 2003 23:38:31 -0000
@@ -508,6 +508,41 @@ lookup_symbol_file (const char *name,
return NULL;
}
+/* Look up a type named NESTED_NAME that is nested inside the C++
+ class or namespace given by PARENT_TYPE, from within the context
+ given by BLOCK. Return NULL if there is no such nested type. */
+
+/* FIXME: carlton/2003-09-24: For now, this only works for nested
+ namespaces; the patch to make this work on other sorts of nested
+ types is next on my TODO list. */
+
+struct type *
+cp_lookup_nested_type (struct type *parent_type,
+ const char *nested_name,
+ const struct block *block)
+{
+ switch (TYPE_CODE (parent_type))
+ {
+ case TYPE_CODE_NAMESPACE:
+ {
+ const char *parent_name = TYPE_TAG_NAME (parent_type);
+ struct symbol *sym = cp_lookup_symbol_namespace (parent_name,
+ nested_name,
+ NULL,
+ block,
+ VAR_DOMAIN,
+ NULL);
+ if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ return NULL;
+ else
+ return SYMBOL_TYPE (sym);
+ }
+ default:
+ internal_error (__FILE__, __LINE__,
+ "cp_lookup_nested_type called on a non-namespace.");
+ }
+}
+
/* Now come functions for dealing with symbols associated to
namespaces. (They're used to store the namespaces themselves, not
objects that live in the namespaces.) These symbols come in two
Index: cp-support.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.h,v
retrieving revision 1.8
diff -u -p -r1.8 cp-support.h
--- cp-support.h 14 Sep 2003 02:04:44 -0000 1.8
+++ cp-support.h 24 Sep 2003 23:38:31 -0000
@@ -97,6 +97,10 @@ extern struct symbol *cp_lookup_symbol_n
const domain_enum domain,
struct symtab **symtab);
+extern struct type *cp_lookup_nested_type (struct type *parent_type,
+ const char *nested_name,
+ const struct block *block);
+
extern void cp_check_possible_namespace_symbols (const char *name,
struct objfile *objfile);
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.36
diff -u -p -r1.36 eval.c
--- eval.c 16 Sep 2003 18:56:35 -0000 1.36
+++ eval.c 24 Sep 2003 23:38:31 -0000
@@ -406,11 +406,9 @@ evaluate_subexp_standard (struct type *e
case OP_SCOPE:
tem = longest_to_int (exp->elts[pc + 2].longconst);
(*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
- arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
- 0,
- exp->elts[pc + 1].type,
- &exp->elts[pc + 3].string,
- NULL_TYPE);
+ arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
+ &exp->elts[pc + 3].string,
+ noside);
if (arg1 == NULL)
error ("There is no field named %s", &exp->elts[pc + 3].string);
return arg1;
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.115
diff -u -p -r1.115 valops.c
--- valops.c 16 Sep 2003 18:56:35 -0000 1.115
+++ valops.c 24 Sep 2003 23:38:31 -0000
@@ -41,6 +41,7 @@
#include <errno.h>
#include "gdb_string.h"
#include "gdb_assert.h"
+#include "cp-support.h"
/* Flag indicating HP compilers were used; needed to correctly handle some
value operations with HP aCC code/runtime. */
@@ -63,6 +64,17 @@ static struct value *search_struct_metho
static int check_field_in (struct type *, const char *);
+
+static struct value *value_struct_elt_for_reference (struct type *domain,
+ int offset,
+ struct type *curtype,
+ char *name,
+ struct type *intype);
+
+static struct value *value_namespace_elt (const struct type *curtype,
+ const char *name,
+ enum noside noside);
+
static CORE_ADDR allocate_space_in_inferior (int);
static struct value *cast_into_complex (struct type *, struct value *);
@@ -2208,6 +2220,29 @@ check_field (struct value *arg1, const c
}
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
+ return the appropriate member. This function is used to resolve
+ user expressions of the form "DOMAIN::NAME". For more details on
+ what happens, see the comment before
+ value_struct_elt_for_reference. */
+
+struct value *
+value_aggregate_elt (struct type *curtype,
+ char *name,
+ enum noside noside)
+{
+ switch (TYPE_CODE (curtype))
+ {
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ return value_struct_elt_for_reference (curtype, 0, curtype, name, NULL);
+ case TYPE_CODE_NAMESPACE:
+ return value_namespace_elt (curtype, name, noside);
+ default:
+ error ("Internal error: non-aggregate type in value_aggregate_elt");
+ }
+}
+
+/* C++: Given an aggregate type CURTYPE, and a member name NAME,
return the address of this member as a "pointer to member"
type. If INTYPE is non-null, then it will be the type
of the member we are looking for. This will help us resolve
@@ -2345,6 +2380,37 @@ value_struct_elt_for_reference (struct t
return v;
}
return 0;
+}
+
+/* C++: Return the member NAME of the namespace given by the type
+ CURTYPE. */
+
+static struct value *
+value_namespace_elt (const struct type *curtype,
+ const char *name,
+ enum noside noside)
+{
+ const char *namespace_name = TYPE_TAG_NAME (curtype);
+ struct symbol *sym;
+ struct value *retval;
+
+ sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
+ get_selected_block (0), VAR_DOMAIN,
+ NULL);
+
+ if (sym == NULL)
+ retval = NULL;
+ else if ((noside == EVAL_AVOID_SIDE_EFFECTS)
+ && (SYMBOL_CLASS (sym) == LOC_TYPEDEF))
+ retval = allocate_value (SYMBOL_TYPE (sym));
+ else
+ retval = value_of_variable (sym, get_selected_block (0));
+
+ if (retval == NULL)
+ error ("No symbol \"%s\" in namespace \"%s\".", name,
+ TYPE_TAG_NAME (curtype));
+
+ return retval;
}
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.51
diff -u -p -r1.51 value.h
--- value.h 13 Sep 2003 21:31:33 -0000 1.51
+++ value.h 24 Sep 2003 23:38:31 -0000
@@ -379,11 +379,9 @@ extern struct value *value_struct_elt (s
char *name, int *static_memfuncp,
char *err);
-extern struct value *value_struct_elt_for_reference (struct type *domain,
- int offset,
- struct type *curtype,
- char *name,
- struct type *intype);
+extern struct value *value_aggregate_elt (struct type *curtype,
+ char *name,
+ enum noside noside);
extern struct value *value_static_field (struct type *type, int fieldno);
Index: testsuite/gdb.cp/namespace.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/namespace.cc,v
retrieving revision 1.1
diff -u -p -r1.1 namespace.cc
--- testsuite/gdb.cp/namespace.cc 23 Aug 2003 03:55:59 -0000 1.1
+++ testsuite/gdb.cp/namespace.cc 24 Sep 2003 23:38:31 -0000
@@ -75,6 +75,11 @@ namespace
namespace G
{
int Xg = 10;
+
+ namespace
+ {
+ int XgX = 11;
+ }
}
}
@@ -90,6 +95,11 @@ namespace C
namespace F
{
int cXf = 7;
+
+ namespace
+ {
+ int cXfX = 8;
+ }
}
}
@@ -98,6 +108,11 @@ namespace C
int cc = 2;
}
+ namespace E
+ {
+ int ce = 4;
+ }
+
namespace D
{
int cd = 3;
@@ -118,14 +133,18 @@ namespace C
//cc;
C::cc;
cd;
+ //C::D::cd;
E::cde;
shadow;
+ //E::ce;
cX;
F::cXf;
+ F::cXfX;
X;
G::Xg;
//cXOtherFile;
//XOtherFile;
+ G::XgX;
return;
}
Index: testsuite/gdb.cp/namespace.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/namespace.exp,v
retrieving revision 1.2
diff -u -p -r1.2 namespace.exp
--- testsuite/gdb.cp/namespace.exp 11 Sep 2003 19:49:20 -0000 1.2
+++ testsuite/gdb.cp/namespace.exp 24 Sep 2003 23:38:31 -0000
@@ -18,11 +18,11 @@
# bug-gdb@prep.ai.mit.edu
# tests for namespaces
-# Written by Satish Pai <pai@apollo.hp.com> 1997-07-23
+# Originally written by Satish Pai <pai@apollo.hp.com> 1997-07-23
# This file is part of the gdb testsuite
-# Note: These tests are geared to the HP aCC compiler,
+# Note: The original tests were geared to the HP aCC compiler,
# which has an idiosyncratic way of emitting debug info
# for namespaces.
# Note: As of 2000-06-03, these pass under g++ - djb
@@ -84,6 +84,11 @@ gdb_test "up" ".*main.*" "up from marker
# Access a data item inside a namespace using colons and
# single quotes :-(
+# NOTE: carlton/2003-09-24: the quotes are becoming less necessary (or
+# even desirable.) For tests where it should still work with quotes,
+# I'm including versions both with and without quotes; for tests that
+# shouldn't work with quotes, I'm only including one version.
+
send_gdb "print 'AAA::c'\n"
gdb_expect {
-re "\\$\[0-9\]* = 0 '\\\\(0|000)'\r\n$gdb_prompt $" { pass "print 'AAA::c'" }
@@ -91,6 +96,13 @@ gdb_expect {
timeout { fail "(timeout) print 'AAA::c'" }
}
+send_gdb "print AAA::c\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 0 '\\\\(0|000)'\r\n$gdb_prompt $" { pass "print AAA::c" }
+ -re ".*$gdb_prompt $" { fail "print AAA::c" }
+ timeout { fail "(timeout) print AAA::c" }
+}
+
# An object declared using "using".
send_gdb "print ina\n"
@@ -137,6 +149,15 @@ gdb_expect {
timeout { fail "(timeout) print 'AAA::xyzq'('x')" }
}
+send_gdb "print AAA::xyzq('x')\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 97 'a'\r\n$gdb_prompt $" {
+ pass "print AAA::xyzq('x')"
+ }
+ -re ".*$gdb_prompt $" { fail "print AAA::xyzq('x')" }
+ timeout { fail "(timeout) print AAA::xyzq('x')" }
+}
+
# Break on a function in a namespace
send_gdb "break AAA::xyzq\n"
@@ -159,6 +180,15 @@ gdb_expect {
timeout { fail "(timeout) print 'BBB::CCC::xyzq'('x')" }
}
+send_gdb "print BBB::CCC::xyzq('x')\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 122 'z'\r\n$gdb_prompt $" {
+ pass "print BBB::CCC::xyzq('x')"
+ }
+ -re ".*$gdb_prompt $" { fail "print BBB::CCC::xyzq('x')" }
+ timeout { fail "(timeout) print BBB::CCC::xyzq('x')" }
+}
+
# Break on a function in a nested namespace
send_gdb "break BBB::CCC::xyzq\n"
@@ -204,9 +234,13 @@ if ![runto "C::D::marker2"] then {
gdb_test "print c" "\\$\[0-9\].* = 1"
gdb_test "print cc" "No symbol \"cc\" in current context."
gdb_test "print 'C::cc'" "\\$\[0-9\].* = 2"
+gdb_test "print C::cc" "\\$\[0-9\].* = 2"
gdb_test "print cd" "\\$\[0-9\].* = 3"
+gdb_test "print C::D::cd" "No type \"D\" in namespace \"C::C\"."
gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5"
+gdb_test "print E::cde" "\\$\[0-9\].* = 5"
gdb_test "print shadow" "\\$\[0-9\].* = 13"
+gdb_test "print E::ce" "No symbol \"ce\" in namespace \"C::D::E\"."
gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
gdb_test "ptype C" "type = namespace C::C"
gdb_test "ptype E" "type = namespace C::D::E"
@@ -215,7 +249,11 @@ gdb_test "ptype E" "type = namespace C::
gdb_test "print cX" "\\$\[0-9\].* = 6"
gdb_test "print 'F::cXf'" "\\$\[0-9\].* = 7"
+gdb_test "print F::cXf" "\\$\[0-9\].* = 7"
+gdb_test "print F::cXfX" "\\$\[0-9\].* = 8"
gdb_test "print X" "\\$\[0-9\].* = 9"
gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10"
+gdb_test "print G::Xg" "\\$\[0-9\].* = 10"
+gdb_test "print G::XgX" "\\$\[0-9\].* = 11"
gdb_test "print cXOtherFile" "No symbol \"cXOtherFile\" in current context."
gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."