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 446914ed0e1f75ce4e591165c3c94b5ac730ff1d..f7a0c9e5457a7d4889f50a83bcca7078f17b6662 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 aea9f3ccf9a9b50db2d43e21395c65037cee457d..c61f1bfbca5df0a9ea2144de28bc219c18eebc16 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 34f7729eb5f4fd507a0108ad474d7993eaf6f7ae..0c279db23d154b912276c902b962174035d179be 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 40959a589a44ca54dc38215048452fb34b17072e..75104ac2d6eae49014f6f451902e33eb58352a6d 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 169fbaf71c39fa976007b7a59dc8f17f80ed9fa4..d8cb5252d55eecab2aeec577ea4dde33c73e1fa1 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 cda14946eb697262aae13bab2bafbef877369ade..a44d0c7fbe2390ed1008a6867c257db96d4fa554 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 f3981c13007754124255667d1ad8c61ec41a9b2c..5c18f82152cd67a3ce6348aa2b039486806314c0 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 7b9a173d819b8b745d87c668cb58e66cee3ee4eb..a0814ee707c66360523fe55acfbeb2d4d7d9bdbb 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 6952c8fb53c831578cd10a36f8b05911cfc30609..228d791ad66ea098d2f9d059cc8854a9fc1c3622 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 8deb473a083f3f656c391ef6b9aa20bd921a0e87..08036de5e2c8ebef1f4f328cc098c67c35353204 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 *);
@@ -2207,6 +2219,30 @@ check_field (struct value *arg1, const char *name)
   return check_field_in (t, 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
@@ -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 afec1609e7bd62769f5cd2117b0be0bb4154f48a..2040c86381d3980153a300e529ba57d451007665 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);