This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch 1/2] Search typedefs in namespaces also in other files
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Cc: Sami Wagiaalla <swagiaal at redhat dot com>
- Date: Mon, 14 Jun 2010 17:59:39 +0200
- Subject: [patch 1/2] Search typedefs in namespaces also in other files
Hi,
currently you can access static symbols from not-current CUs (Compilation
Units). In some cases you cannot if it is a name contained in namespace.
==> ns.C <==
int
main ()
{
extern int f ();
return f ();
}
==> ns2.C <==
typedef short i_t;
static i_t i = 1;
namespace N
{
typedef long j_t;
j_t j = 2;
}
int
f ()
{
return i + N::j;
}
(gdb) start
(gdb) ptype i_t
type = short
(gdb) ptype N::j_t
No symbol "j_t" in namespace "N".
-> with the patch: type = long
(gdb) ptype ::N::j_t
No symbol "j_t" in current context.
-> with the patch: type = long
(gdb) ptype j_t
No symbol "j_t" in current context.
(gdb) adv f
f () at ns2.C:11
(gdb) ptype N::j_t
type = long
(gdb) _
That is type gets resolvable only if we are currently in its CU.
It is questionable how it should behave. Such access is already not
compliant with the C++ standard. The implementation tries only to search for
the fully qualified names - without any attempts for imported namespaces.
New types are always local to its CU. You cannot use type from some .o file
without having its types defined for each new compiled CU from a .h file.
Therefore all the types get normally duplicated by each new CU. While one can
use cross-CU references those are AFAIK (seen it only at Portland Group
compiled output) only de-duplicated after the compilation is done. That means
DW_TAG_typedef has never DW_AT_external (is it really true?) and C++ standard
non-compliant other-file lookup makes sense.
While I tried I have not found any proper coding scheme so I just patched some
functions to make it working. I may have missed some design points. Already
the C++ parser calls various functions in not so correct way IMHO and there
also now exists at least the archer-cpparser effort to make it more sane.
Filed two KFAILed GDB Bugs for it, they are not regressions but rather the
unfixed parts:
[Bug c++/11702] New: static const member is not printed
- it is unrelated to the issue this(ese) patch(es) try to solve.
[Bug c++/11703] New: root namespace sometimes not working
- Leading :: works only for types, not other objects.
- IMHO a fix requires patching the C++ parser: -> archer-cpparser
No regressions on {x86_64,x86_64-m32,i686}-fedora13-linux-gnu (gcc-4.4-rh).
For proper testing avoiding some XFAILs one needs at least gcc-4.5.
Thanks,
Jan
gdb/
2010-06-14 Jan Kratochvil <jan.kratochvil@redhat.com>
* cp-namespace.c (cp_lookup_symbol_namespace): Call also
lookup_static_symbol_aux if we failed otherwise.
(cp_lookup_nested_type): New variable concatenated_name. Turn the
current return condition into a reverse one. Call also
lookup_static_symbol_aux on the constructed qualified name.
* symtab.c (lookup_symbol_aux): Move variable objfile and searching in
other files into a called ...
(lookup_static_symbol_aux): ... new function here.
* symtab.h (lookup_static_symbol_aux): New prototype.
gdb/testsuite/
2010-06-14 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.cp/namespace.exp (whatis C::cOtherFileType)
(whatis ::C::cOtherFileType, whatis C::cOtherFileVar)
(whatis ::C::cOtherFileVar, print C::cOtherFileVar)
(print ::C::cOtherFileVar)
(whatis C::OtherFileClass::cOtherFileClassType)
(whatis ::C::OtherFileClass::cOtherFileClassType)
(print C::OtherFileClass::cOtherFileClassVar)
(print ::C::OtherFileClass::cOtherFileClassVar): New tests.
(ptype OtherFileClass, ptype ::C::OtherFileClass): Permit arbitrary
trailing content.
* gdb.cp/namespace1.cc (C::OtherFileClass::cOtherFileClassType)
(C::OtherFileClass::cOtherFileClassVar)
(C::OtherFileClass::cOtherFileClassVar_use, C::cOtherFileType)
(C::cOtherFileVar, C::cOtherFileVar_use): New.
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -440,6 +440,27 @@ cp_lookup_symbol_namespace (const char *scope,
block = BLOCK_SUPERBLOCK (block);
}
+ /* Now search all static file-level symbols. Not strictly correct,
+ but more useful than an error. We do not try to guess any imported
+ namespace as even the fully specified namespace seach is is already not
+ C++ compliant and more assumptions could make it too magic. */
+
+ if (scope[0] == '\0')
+ {
+ sym = lookup_static_symbol_aux (name, domain);
+ if (sym != NULL)
+ return sym;
+ }
+ else
+ {
+ char *concatenated_name = alloca (strlen (scope) + 2 + strlen (name) + 1);
+
+ sprintf (concatenated_name, "%s::%s", scope, name);
+ sym = lookup_static_symbol_aux (concatenated_name, domain);
+ if (sym != NULL)
+ return sym;
+ }
+
return NULL;
}
@@ -578,11 +599,24 @@ cp_lookup_nested_type (struct type *parent_type,
nested_name,
block,
VAR_DOMAIN);
+ char *concatenated_name;
- if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- return NULL;
- else
+ if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
return SYMBOL_TYPE (sym);
+
+ /* Now search all static file-level symbols. Not strictly correct,
+ but more useful than an error. We do not try to guess any imported
+ namespace as even the fully specified namespace seach is is already
+ not C++ compliant and more assumptions could make it too magic. */
+
+ concatenated_name = alloca (strlen (parent_name) + 2
+ + strlen (nested_name) + 1);
+ sprintf (concatenated_name, "%s::%s", parent_name, nested_name);
+ sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN);
+ if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ return SYMBOL_TYPE (sym);
+
+ return NULL;
}
default:
internal_error (__FILE__, __LINE__,
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1054,7 +1054,6 @@ lookup_symbol_aux (const char *name, const struct block *block,
{
struct symbol *sym;
const struct language_defn *langdef;
- struct objfile *objfile;
/* Make sure we do something sensible with is_a_field_of_this, since
the callers that set this parameter to some non-null value will
@@ -1121,11 +1120,20 @@ lookup_symbol_aux (const char *name, const struct block *block,
if (sym != NULL)
return sym;
- /* Now search all static file-level symbols. Not strictly correct,
- but more useful than an error. Do the symtabs first, then check
- the psymtabs. If a psymtab indicates the existence of the
- desired name as a file-level static, then do psymtab-to-symtab
- conversion on the fly and return the found symbol. */
+ return lookup_static_symbol_aux (name, domain);
+}
+
+/* Now search all static file-level symbols. Not strictly correct,
+ but more useful than an error. Do the symtabs first, then check
+ the psymtabs. If a psymtab indicates the existence of the
+ desired name as a file-level static, then do psymtab-to-symtab
+ conversion on the fly and return the found symbol. */
+
+struct symbol *
+lookup_static_symbol_aux (const char *name, const domain_enum domain)
+{
+ struct objfile *objfile;
+ struct symbol *sym;
sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain);
if (sym != NULL)
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -886,6 +886,12 @@ extern struct symbol *lookup_symbol_aux_block (const char *name,
const struct block *block,
const domain_enum domain);
+/* Lookup a symbol only in the file static scope of all the objfiles. */
+
+struct symbol *lookup_static_symbol_aux (const char *name,
+ const domain_enum domain);
+
+
/* lookup a symbol by name, within a specified block */
extern struct symbol *lookup_block_symbol (const struct block *, const char *,
--- a/gdb/testsuite/gdb.cp/namespace.exp
+++ b/gdb/testsuite/gdb.cp/namespace.exp
@@ -165,6 +165,66 @@ gdb_test "print BBB::Class::xyzq" \
gdb_test "break BBB::Class::xyzq" \
"Breakpoint.*at $hex: file.*namespace.cc, line 68\\."
+# Tests accessing static elements in namespace of other file.
+
+gdb_test "whatis C::cOtherFileType" "type = short"
+gdb_test "whatis ::C::cOtherFileType" "type = short"
+gdb_test "whatis C::cOtherFileVar" "type = const C::cOtherFileType"
+setup_kfail "c++/11703" "*-*-*"
+gdb_test "whatis ::C::cOtherFileVar" "type = const C::cOtherFileType"
+gdb_test "print C::cOtherFileVar" "\\$\[0-9\].* = 319"
+setup_kfail "c++/11703" "*-*-*"
+gdb_test "print ::C::cOtherFileVar" "\\$\[0-9\].* = 319"
+
+if {[test_compiler_info {gcc-[0-3]-*}]
+ || [test_compiler_info {gcc-4-[0-4]-*}]} {
+ # The type in class is missing in older GCCs.
+ setup_xfail *-*-*
+}
+gdb_test "whatis C::OtherFileClass::cOtherFileClassType" "type = short"
+if {[test_compiler_info {gcc-[0-3]-*}]
+ || [test_compiler_info {gcc-4-[0-4]-*}]} {
+ # The type in class is missing in older GCCs.
+ setup_xfail *-*-*
+}
+gdb_test "whatis ::C::OtherFileClass::cOtherFileClassType" "type = short"
+
+set test "print C::OtherFileClass::cOtherFileClassVar"
+gdb_test_multiple $test $test {
+ -re "\\$\[0-9\].* = 318\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re "static field cOtherFileClassVar has been optimized out\r\n$gdb_prompt $" {
+ setup_kfail "c++/11702" "*-*-*"
+ fail $test
+ }
+}
+if {[test_compiler_info {gcc-[0-3]-*}]
+ || [test_compiler_info {gcc-4-[0-4]-*}]} {
+ # Older GCCs create unqualified DIE "cOtherFileClassVar" ignoring the
+ # namespace the same way GDB does.
+ setup_xfail *-*-*
+} else {
+ setup_kfail "c++/11703" "*-*-*"
+}
+set test "print ::C::OtherFileClass::cOtherFileClassVar"
+gdb_test_multiple $test $test {
+ -re "\\$\[0-9\].* = 318\r\n$gdb_prompt $" {
+ if {[test_compiler_info {gcc-[0-3]-*}]
+ || [test_compiler_info {gcc-4-[0-4]-*}]} {
+ # Older GCCs create unqualified DIE "cOtherFileClassVar" ignoring the
+ # namespace the same way GDB does.
+ xfail $test
+ } else {
+ pass $test
+ }
+ }
+ -re "$gdb_prompt $" {
+ setup_kfail "c++/11703" "*-*-*"
+ fail $test
+ }
+}
+
# Test to see if the appropriate namespaces are in scope when trying
# to print out stuff from within a function defined within a
# namespace.
@@ -201,8 +261,8 @@ gdb_test "ptype C::NestedClass" "No symbol \"NestedClass\" in namespace \"C::C\"
# Tests involving multiple files
gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
-gdb_test "ptype OtherFileClass" "type = (class C::OtherFileClass \{\r\n public:|struct C::OtherFileClass \{)\r\n int z;\r\n\}"
-gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n public:\r\n int z;\r\n\}"
+gdb_test "ptype OtherFileClass" "type = (class C::OtherFileClass \{\r\n public:|struct C::OtherFileClass \{)\r\n int z;\r\n.*\}"
+gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n public:\r\n int z;\r\n.*\}"
gdb_test "ptype C::OtherFileClass" "No symbol \"OtherFileClass\" in namespace \"C::C\"."
# Some anonymous namespace tests.
--- a/gdb/testsuite/gdb.cp/namespace1.cc
+++ b/gdb/testsuite/gdb.cp/namespace1.cc
@@ -21,7 +21,15 @@ namespace C
class OtherFileClass {
public:
int z;
+
+ typedef short cOtherFileClassType;
+ static const cOtherFileClassType cOtherFileClassVar = 318;
+ cOtherFileClassType cOtherFileClassVar_use ();
};
+ OtherFileClass::cOtherFileClassType OtherFileClass::cOtherFileClassVar_use ()
+ {
+ return cOtherFileClassVar;
+ }
namespace {
int cXOtherFile = 29;
@@ -35,6 +43,13 @@ namespace C
static OtherFileClass *c = new OtherFileClass();
c->z = cOtherFile + cXOtherFile;
}
+
+ typedef short cOtherFileType;
+ static const cOtherFileType cOtherFileVar = 319;
+ cOtherFileType cOtherFileVar_use ()
+ {
+ return cOtherFileVar;
+ }
}
namespace {