From 254e6b9ed4abf109cb8399aa3f8f387f7eb2465c Mon Sep 17 00:00:00 2001
From: Doug Evans <dje@google.com>
Date: Tue, 29 Jun 2010 16:53:10 +0000
Subject: [PATCH] 	PR c++/11702 	* NEWS: Add entry. 	* dwarf2read.c
 (dwarf2_add_field): If DW_AT_const_value is present, 	create a symbol for
 the field and record the value. 	(new_symbol): Handle DW_TAG_member. 
 * gdbtypes.c (field_is_static): Remove FIXME. 	* symtab.c (search_symbols):
 When searching for VARIABLES_DOMAIN, 	only ignore LOC_CONST symbols that are
 enums.

	testsuite/
	Test PR c++/11702.
	* gdb.cp/m-static.exp: Add testcase.
	* gdb.cp/m-static.h (gnu_obj_4): Add initialized static const member.
---
 gdb/ChangeLog                     |  9 +++++++++
 gdb/NEWS                          |  5 +++++
 gdb/dwarf2read.c                  | 25 +++++++++++++++++++++++++
 gdb/gdbtypes.c                    |  4 +---
 gdb/symtab.c                      |  9 +++++++--
 gdb/testsuite/ChangeLog           |  6 ++++++
 gdb/testsuite/gdb.cp/m-static.exp | 14 +++++++++++++-
 gdb/testsuite/gdb.cp/m-static.h   |  4 ++--
 8 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index df91ef95ae6..07f2bf4db8e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
 2010-06-29  Doug Evans  <dje@google.com>
 
+	PR gdb/11702
+	* NEWS: Add entry.
+	* dwarf2read.c (dwarf2_add_field): If DW_AT_const_value is present,
+	create a symbol for the field and record the value.
+	(new_symbol): Handle DW_TAG_member.
+	* gdbtypes.c (field_is_static): Remove FIXME.
+	* symtab.c (search_symbols): When searching for VARIABLES_DOMAIN,
+	only ignore LOC_CONST symbols that are enums.
+
 	* dwarf2read.c: Remove trailing whitespace.
 
 	Delete FIELD_LOC_KIND_DWARF_BLOCK, unused.
diff --git a/gdb/NEWS b/gdb/NEWS
index 73ff05fd37b..4764c01d147 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -32,6 +32,11 @@
   GDB now also supports proper overload resolution for all the previously
   mentioned flavors of operators.
 
+  ** static const class members
+
+  Printing of static const class members that are initialized in the
+  class definition has been fixed.
+
 * Windows Thread Information Block access.
 
   On Windows targets, GDB now supports displaying the Windows Thread
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index c1727525c9e..127d10fc741 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -4528,6 +4528,11 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   fp = &new_field->field;
 
+  /* NOTE: According to the dwarf standard, static data members are
+     indicated by having DW_AT_external.
+     The check here for ! die_is_declaration is historical.
+     This test is replicated in new_symbol.  */
+
   if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
     {
       /* Data member other than a C++ static data member.  */
@@ -4643,6 +4648,14 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
       if (fieldname == NULL)
 	return;
 
+      attr = dwarf2_attr (die, DW_AT_const_value, cu);
+      if (attr)
+	{
+	  /* A static const member, not much different than an enum as far as
+	     we're concerned, except that we can support more types.  */
+	  new_symbol (die, NULL, cu);
+	}
+
       /* Get physical name.  */
       physname = (char *) dwarf2_physname (fieldname, die, cu);
 
@@ -8824,6 +8837,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	     BLOCK_FUNCTION from the blockvector.  */
 	  break;
 	case DW_TAG_variable:
+	case DW_TAG_member:
 	  /* Compilation with minimal debug info may result in variables
 	     with missing type entries. Change the misleading `void' type
 	     to something sensible.  */
@@ -8832,6 +8846,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	      = objfile_type (objfile)->nodebug_data_symbol;
 
 	  attr = dwarf2_attr (die, DW_AT_const_value, cu);
+	  /* In the case of DW_TAG_member, we should only be called for
+	     static const members.  */
+	  if (die->tag == DW_TAG_member)
+	    {
+	      /* NOTE: This test seems wrong according to the dwarf standard.
+		 static data members are represented by DW_AT_external.
+		 However, dwarf2_add_field is currently calling
+		 die_is_declaration to check, so we do the same.  */
+	      gdb_assert (die_is_declaration (die, cu));
+	      gdb_assert (attr);
+	    }
 	  if (attr)
 	    {
 	      dwarf2_const_value (attr, sym, cu);
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 5d1d4203e79..ba8c7e41243 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2512,9 +2512,7 @@ field_is_static (struct field *f)
      to the address of the enclosing struct.  It would be nice to
      have a dedicated flag that would be set for static fields when
      the type is being created.  But in practice, checking the field
-     loc_kind should give us an accurate answer (at least as long as
-     we assume that DWARF block locations are not going to be used
-     for static fields).  FIXME?  */
+     loc_kind should give us an accurate answer.  */
   return (FIELD_LOC_KIND (*f) == FIELD_LOC_KIND_PHYSNAME
 	  || FIELD_LOC_KIND (*f) == FIELD_LOC_KIND_PHYSADDR);
 }
diff --git a/gdb/symtab.c b/gdb/symtab.c
index feb986f17c8..9472c24e4b7 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3057,10 +3057,15 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
 	      if (file_matches (real_symtab->filename, files, nfiles)
 		  && ((regexp == NULL
 		       || re_exec (SYMBOL_NATURAL_NAME (sym)) != 0)
-		      && ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+		      && ((kind == VARIABLES_DOMAIN
+			   && SYMBOL_CLASS (sym) != LOC_TYPEDEF
 			   && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
 			   && SYMBOL_CLASS (sym) != LOC_BLOCK
-			   && SYMBOL_CLASS (sym) != LOC_CONST)
+			   /* LOC_CONST can be used for more than just enums,
+			      e.g., c++ static const members.
+			      We only want to skip enums here.  */
+			   && !(SYMBOL_CLASS (sym) == LOC_CONST
+				&& TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM))
 			  || (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (sym) == LOC_BLOCK)
 			  || (kind == TYPES_DOMAIN && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
 		{
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 21a1be11eb3..65f0db3618a 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-06-29  Doug Evans  <dje@google.com>
+
+	Test PR c++/11702.
+	* gdb.cp/m-static.exp: Add testcase.
+	* gdb.cp/m-static.h (gnu_obj_4): Add initialized static const member.
+
 2010-06-28  Phil Muldoon  <pmuldoon@redhat.com>
             Tom Tromey  <tromey@redhat.com>
             Thiago Jung Bauermann  <bauerman@br.ibm.com>
diff --git a/gdb/testsuite/gdb.cp/m-static.exp b/gdb/testsuite/gdb.cp/m-static.exp
index dda8d844e9b..6b457d295d0 100644
--- a/gdb/testsuite/gdb.cp/m-static.exp
+++ b/gdb/testsuite/gdb.cp/m-static.exp
@@ -56,12 +56,14 @@ gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 gdb_load ${binfile}
 
-
 if ![runto_main] then {
     perror "couldn't run to breakpoint"
     continue
 }
 
+get_debug_format
+set non_dwarf [expr ! [test_debug_format "DWARF 2"]]
+
 # First, run to after we've constructed all the objects:
 
 gdb_breakpoint [gdb_get_line_number "constructs-done"]
@@ -125,6 +127,16 @@ gdb_test "print test4.elsewhere" "\\$\[0-9\].* = 221" "static const int initiali
 # static const int that nobody initializes.  From PR gdb/635.
 gdb_test "print test4.nowhere" "field nowhere is nonexistent or has been optimized out" "static const int initialized nowhere"
 
+# static const initialized in the class definition, PR gdb/11702.
+if { $non_dwarf } { setup_xfail *-*-* }
+gdb_test "print test4.everywhere" "\\$\[0-9\].* = 317" "static const int initialized in class definition"
+if { $non_dwarf } { setup_xfail *-*-* }
+gdb_test "print test4.somewhere" "\\$\[0-9\].* = 3.14\[0-9\]*" "static const float initialized in class definition"
+
+# Also make sure static const members can be found via "info var".
+if { $non_dwarf } { setup_xfail *-*-* }
+gdb_test "info variable everywhere" "File .*/m-static\[.\]h.*const int gnu_obj_4::everywhere;" "info variable everywhere"
+
 # Perhaps at some point test4 should also include a test for a static
 # const int that was initialized in the header file.  But I'm not sure
 # that GDB's current behavior in such situations is either consistent
diff --git a/gdb/testsuite/gdb.cp/m-static.h b/gdb/testsuite/gdb.cp/m-static.h
index 012cd770e47..bcedfff4eea 100644
--- a/gdb/testsuite/gdb.cp/m-static.h
+++ b/gdb/testsuite/gdb.cp/m-static.h
@@ -5,8 +5,8 @@ class gnu_obj_4
  public:
   static const int elsewhere;
   static const int nowhere;
-  // At some point, perhaps:
-  // static const int everywhere = 317;
+  static const int everywhere = 317;
+  static const float somewhere = 3.14159;
 
   // try to ensure test4 is actually allocated
   int dummy;