2003-09-25 David Carlton <carlton@kealia.com>
authorDavid Carlton <carlton@bactrian.org>
Thu, 25 Sep 2003 16:39:39 +0000 (16:39 +0000)
committerDavid Carlton <carlton@bactrian.org>
Thu, 25 Sep 2003 16:39:39 +0000 (16:39 +0000)
* c-exp.y: Include cp-support.h.  Add qualified_type.
(yylex): Delete 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-25  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.

gdb/ChangeLog
gdb/Makefile.in
gdb/c-exp.y
gdb/cp-namespace.c
gdb/cp-support.h
gdb/eval.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/namespace.cc
gdb/testsuite/gdb.cp/namespace.exp
gdb/valops.c
gdb/value.h

index 446914e..f7a0c9e 100644 (file)
@@ -1,3 +1,20 @@
+2003-09-25  David Carlton  <carlton@kealia.com>
+
+       * c-exp.y: Include cp-support.h.  Add qualified_type.
+       (yylex): Delete 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-25  Daniel Jacobowitz  <drow@mvista.com>
 
        * stack.c: Include "reggroups.h".
index aea9f3c..c61f1bf 100644 (file)
@@ -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) 
@@ -2418,7 +2418,8 @@ valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
 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 34f7729..0c279db 100644 (file)
@@ -51,6 +51,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #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, int, YYSTYPE *);
 
 %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,80 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
                        { $$ = follow_types ($2); }
        | typebase const_or_volatile_or_space_identifier_noopt 
                        { $$ = follow_types ($1); }
+       | qualified_type
+       ;
+
+/* FIXME: carlton/2003-09-25: 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: the rules are
+   identical.  If the parser is parsing 'A::B::x', then, when it sees
+   the second '::', it knows that the expression to the left of it has
+   to be a type, so it uses qualified_type.  But if it is parsing just
+   'A::B', then it doesn't have any way of knowing which rule to use,
+   so there's a reduce-reduce conflict; it picks qualified_name, since
+   that occurs earlier in this file than 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).  Fortunately, it works
+   pretty well in most cases.  For example, if you do 'ptype A::B',
+   where A::B is a nested type, then the parser will mistakenly
+   misidentify it as an expression; but evaluate_subexp will get
+   called with 'noside' set to EVAL_AVOID_SIDE_EFFECTS, and everything
+   will work out anyways.  But there are situations where the parser
+   will get confused: the most common one that I've run into is when
+   you want to do
+
+     print *((A::B *) x)"
+
+   where the parser doesn't realize that A::B has to be a type until
+   it hits the first right paren, at which point it's too late.  (The
+   workaround is to type "print *(('A::B' *) x)" instead.)  (And
+   another solution is to fix our symbol-handling code so that the
+   user never wants to type something like that in the first place,
+   because we get all the types right without the user's help!)
+
+   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: that attempt
+   involved having the parser sometimes handle '::' and having the
+   lexer sometimes handle it, and without a clear division of
+   responsibility, it quickly degenerated into a big mess.  Probably
+   the eventual correct solution will give more of a role to the lexer
+   (ideally via code that is shared between the lexer and
+   decode_line_1), but I'm not holding my breath waiting for somebody
+   to get around to cleaning this up...  */
+
+/* FIXME: carlton/2003-09-25: 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 +1710,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,92 +1770,10 @@ yylex ()
 
     if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
         {
-#if 1
-         /* 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
-            program which uses nested types.  */
-         /* In "A::x", if x is a member function of A and there happens
-            to be a type (nested or not, since the stabs don't make that
-            distinction) named x, then this code incorrectly thinks we
-            are dealing with nested types rather than a member function.  */
-
-         char *p;
-         char *namestart;
-         struct symbol *best_sym;
-
-         /* Look ahead to detect nested types.  This probably should be
-            done in the grammar, but trying seemed to introduce a lot
-            of shift/reduce and reduce/reduce conflicts.  It's possible
-            that it could be done, though.  Or perhaps a non-grammar, but
-            less ad hoc, approach would work well.  */
-
-         /* Since we do not currently have any way of distinguishing
-            a nested type from a non-nested one (the stabs don't tell
-            us whether a type is nested), we just ignore the
-            containing type.  */
-
-         p = lexptr;
-         best_sym = sym;
-         while (1)
-           {
-             /* Skip whitespace.  */
-             while (*p == ' ' || *p == '\t' || *p == '\n')
-               ++p;
-             if (*p == ':' && p[1] == ':')
-               {
-                 /* Skip the `::'.  */
-                 p += 2;
-                 /* Skip whitespace.  */
-                 while (*p == ' ' || *p == '\t' || *p == '\n')
-                   ++p;
-                 namestart = p;
-                 while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
-                        || (*p >= 'a' && *p <= 'z')
-                        || (*p >= 'A' && *p <= 'Z'))
-                   ++p;
-                 if (p != namestart)
-                   {
-                     struct symbol *cur_sym;
-                     /* As big as the whole rest of the expression, which is
-                        at least big enough.  */
-                     char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
-                     char *tmp1;
-
-                     tmp1 = ncopy;
-                     memcpy (tmp1, tmp, strlen (tmp));
-                     tmp1 += strlen (tmp);
-                     memcpy (tmp1, "::", 2);
-                     tmp1 += 2;
-                     memcpy (tmp1, namestart, p - namestart);
-                     tmp1[p - namestart] = '\0';
-                     cur_sym = lookup_symbol (ncopy, expression_context_block,
-                                              VAR_DOMAIN, (int *) NULL,
-                                              (struct symtab **) NULL);
-                     if (cur_sym)
-                       {
-                         if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
-                           {
-                             best_sym = cur_sym;
-                             lexptr = p;
-                           }
-                         else
-                           break;
-                       }
-                     else
-                       break;
-                   }
-                 else
-                   break;
-               }
-             else
-               break;
-           }
-
-         yylval.tsym.type = SYMBOL_TYPE (best_sym);
-#else /* not 0 */
+         /* NOTE: carlton/2003-09-25: There used to be code here to
+            handle nested types.  It didn't work very well.  See the
+            comment before qualified_type for more info.  */
          yylval.tsym.type = SYMBOL_TYPE (sym);
-#endif /* not 0 */
          return TYPENAME;
         }
     if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
index 40959a5..75104ac 100644 (file)
@@ -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 169fbaf..d8cb525 100644 (file)
@@ -97,6 +97,10 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
                                                  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 cda1494..a44d0c7 100644 (file)
@@ -408,11 +408,9 @@ evaluate_subexp_standard (struct type *expect_type,
     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 f3981c1..5c18f82 100644 (file)
@@ -1,3 +1,10 @@
+2003-09-25  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.
+
 2003-09-25  Richard Earnshaw  <rearnsha@arm.com>
 
        * lib/java.exp (java_init): Import target_alias before using it.
index 7b9a173..a0814ee 100644 (file)
@@ -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 6952c8f..228d791 100644 (file)
 # 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 marker1"
 # 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::D::E"
 
 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."
index 8deb473..08036de 100644 (file)
@@ -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_method (char *, struct value **,
 
 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,30 @@ check_field (struct value *arg1, const char *name)
 }
 
 /* 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:
+      internal_error (__FILE__, __LINE__,
+                     "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
@@ -2347,6 +2383,37 @@ value_struct_elt_for_reference (struct type *domain, int offset,
   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;
+}
+
 
 /* Given a pointer value V, find the real (RTTI) type
    of the object it points to.
index afec160..2040c86 100644 (file)
@@ -379,11 +379,9 @@ extern struct value *value_struct_elt (struct value **argp,
                                       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);