[patch] Fix C++ regression for bpt conditionals

Jan Kratochvil jan.kratochvil@redhat.com
Fri Jan 4 21:22:00 GMT 2013


Hi Tom,

d2fae92c9d78b49086182385a5bbd086b7a030b6 is the first bad commit
commit d2fae92c9d78b49086182385a5bbd086b7a030b6
Author: Tom Tromey <tromey@redhat.com>
Date:   Tue Dec 6 18:54:35 2011 +0000
    the "ambiguous linespec" series

"break C::m if v == 42" where 'v' is a class field no longer works printing:
	warning: failed to reevaluate condition for breakpoint 1: No symbol "v" in current context.

It is because at the following moment current_language gets reset to
c_language during startup of the inferior.

#0  set_language (lang=language_c) at language.c:440
#1  in select_frame (fi=0x1f908c0) at frame.c:1431
#2  in get_selected_frame (message=0x0) at frame.c:1363
#3  in get_current_arch () at arch-utils.c:757
#4  in parse_exp_in_context (stringptr=0x7fffffffd360, block=0x210fa80, comma=0, void_context_p=0, out_subexp=0x0) at parse.c:1159
#5  in parse_exp_1 (stringptr=0x7fffffffd360, block=0x210fa80, comma=0) at parse.c:1074
#6  in update_breakpoint_locations (b=0x20e2400, sals=..., sals_end=...) at breakpoint.c:11772
#7  in breakpoint_re_set_default (b=0x20e2400) at breakpoint.c:11988

I find it a latent bug that just got exposed by the check-in above.

The testcase is fixed by the classify_name change but I find all the calls of
lookup_symbol from *.y files incorrect.
I would find "#define lookup_symbol BUG" right there but I see here some
opposition to such compiler checking constructs.

No regressions on {x86_64,x86_64-m32,i686}-fedora18-linux-gnu.


Thanks,
Jan


gdb/
2013-01-04  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* c-exp.y (block, variable, name_not_typename, lex_one_token)
	(classify_name): Call parse_lookup_symbol instead of lookup_symbol.
	* f-exp.y (yylex): Likewise.
	* go-exp.y (package_name_p, classify_packaged_name): Likewise.
	* jv-exp.y (push_variable): Likewise.
	* m2-exp.y (fblock): Likewise.
	* p-exp.y (block, variable, yylex): Likewise.
	* parse.c (parse_lookup_symbol): New function.
	* parser-defs.h (parse_lookup_symbol): New declaration.

gdb/testsuite/
2013-01-04  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.cp/parse-lang.cc: New file.
	* gdb.cp/parse-lang.exp: New file.

diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 9847120..f41750c 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -870,8 +870,8 @@ block	:	BLOCKNAME
 
 block	:	block COLONCOLON name
 			{ struct symbol *tem
-			    = lookup_symbol (copy_name ($3), $1,
-					     VAR_DOMAIN, NULL);
+			    = parse_lookup_symbol (copy_name ($3), $1,
+						   VAR_DOMAIN, NULL);
 			  if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
 			    error (_("No function \"%s\" in specified context."),
 				   copy_name ($3));
@@ -895,8 +895,8 @@ variable:	name_not_typename ENTRY
 
 variable:	block COLONCOLON name
 			{ struct symbol *sym;
-			  sym = lookup_symbol (copy_name ($3), $1,
-					       VAR_DOMAIN, NULL);
+			  sym = parse_lookup_symbol (copy_name ($3), $1,
+						     VAR_DOMAIN, NULL);
 			  if (sym == 0)
 			    error (_("No symbol \"%s\" in specified context."),
 				   copy_name ($3));
@@ -909,7 +909,7 @@ variable:	block COLONCOLON name
 			    }
 
 			  write_exp_elt_opcode (OP_VAR_VALUE);
-			  /* block_found is set by lookup_symbol.  */
+			  /* block_found is set by parse_lookup_symbol.  */
 			  write_exp_elt_block (block_found);
 			  write_exp_elt_sym (sym);
 			  write_exp_elt_opcode (OP_VAR_VALUE); }
@@ -970,9 +970,8 @@ variable:	qualified_name
 			  struct symbol *sym;
 			  struct minimal_symbol *msymbol;
 
-			  sym =
-			    lookup_symbol (name, (const struct block *) NULL,
-					   VAR_DOMAIN, NULL);
+			  sym = parse_lookup_symbol (name, NULL, VAR_DOMAIN,
+						     NULL);
 			  if (sym)
 			    {
 			      write_exp_elt_opcode (OP_VAR_VALUE);
@@ -1580,10 +1579,10 @@ name_not_typename :	NAME
 			  struct field_of_this_result is_a_field_of_this;
 
 			  $$.stoken = $1;
-			  $$.sym = lookup_symbol ($1.ptr,
-						  expression_context_block,
-						  VAR_DOMAIN,
-						  &is_a_field_of_this);
+			  $$.sym = parse_lookup_symbol ($1.ptr,
+						       expression_context_block,
+							VAR_DOMAIN,
+							&is_a_field_of_this);
 			  $$.is_a_field_of_this
 			    = is_a_field_of_this.type != NULL;
 			}
@@ -2696,11 +2695,12 @@ lex_one_token (void)
 	  {
 	    struct field_of_this_result is_a_field_of_this;
 
-	    if (lookup_symbol (copy, expression_context_block,
-			       VAR_DOMAIN,
-			       (parse_language->la_language == language_cplus
-				? &is_a_field_of_this
-				: NULL))
+	    if (parse_lookup_symbol (copy, expression_context_block,
+				     VAR_DOMAIN,
+				     (parse_language->la_language
+				      == language_cplus
+				      ? &is_a_field_of_this
+				      : NULL))
 		!= NULL)
 	      {
 		/* The keyword is shadowed.  */
@@ -2759,9 +2759,9 @@ classify_name (const struct block *block)
      we can refer to it unconditionally below.  */
   memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this));
 
-  sym = lookup_symbol (copy, block, VAR_DOMAIN, 
-		       parse_language->la_name_of_this
-		       ? &is_a_field_of_this : NULL);
+  sym = parse_lookup_symbol (copy, block, VAR_DOMAIN, 
+			     (parse_language->la_name_of_this
+			      ? &is_a_field_of_this : NULL));
 
   if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
     {
@@ -2792,8 +2792,8 @@ classify_name (const struct block *block)
 	{
 	  struct field_of_this_result inner_is_a_field_of_this;
 
-	  sym = lookup_symbol (copy, block, STRUCT_DOMAIN,
-			       &inner_is_a_field_of_this);
+	  sym = parse_lookup_symbol (copy, block, STRUCT_DOMAIN,
+				     &inner_is_a_field_of_this);
 	  if (sym != NULL)
 	    {
 	      yylval.tsym.type = SYMBOL_TYPE (sym);
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 846cc02..420c460 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -1181,10 +1181,10 @@ yylex (void)
        way we can refer to it unconditionally below.  */
     memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this));
 
-    sym = lookup_symbol (tmp, expression_context_block,
-			 VAR_DOMAIN,
-			 parse_language->la_language == language_cplus
-			 ? &is_a_field_of_this : NULL);
+    sym = parse_lookup_symbol (tmp, expression_context_block,
+			       VAR_DOMAIN,
+			       (parse_language->la_language == language_cplus
+			        ? &is_a_field_of_this : NULL));
     if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
       {
 	yylval.tsym.type = SYMBOL_TYPE (sym);
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 66d9149..12fe8bb 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -1367,7 +1367,7 @@ package_name_p (const char *name, const struct block *block)
   struct symbol *sym;
   struct field_of_this_result is_a_field_of_this;
 
-  sym = lookup_symbol (name, block, STRUCT_DOMAIN, &is_a_field_of_this);
+  sym = parse_lookup_symbol (name, block, STRUCT_DOMAIN, &is_a_field_of_this);
 
   if (sym
       && SYMBOL_CLASS (sym) == LOC_TYPEDEF
@@ -1410,7 +1410,7 @@ classify_packaged_name (const struct block *block)
 
   copy = copy_name (yylval.sval);
 
-  sym = lookup_symbol (copy, block, VAR_DOMAIN, &is_a_field_of_this);
+  sym = parse_lookup_symbol (copy, block, VAR_DOMAIN, &is_a_field_of_this);
 
   if (sym)
     {
@@ -1453,7 +1453,7 @@ classify_name (const struct block *block)
 
   /* TODO: What about other types?  */
 
-  sym = lookup_symbol (copy, block, VAR_DOMAIN, &is_a_field_of_this);
+  sym = parse_lookup_symbol (copy, block, VAR_DOMAIN, &is_a_field_of_this);
 
   if (sym)
     {
@@ -1478,8 +1478,8 @@ classify_name (const struct block *block)
 			       copy, strlen (copy));
 
 	xfree (current_package_name);
-	sym = lookup_symbol (sval.ptr, block, VAR_DOMAIN,
-			     &is_a_field_of_this);
+	sym = parse_lookup_symbol (sval.ptr, block, VAR_DOMAIN,
+				   &is_a_field_of_this);
 	if (sym)
 	  {
 	    yylval.ssym.stoken = sval;
diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y
index ea56296..2d9cf5a 100644
--- a/gdb/jv-exp.y
+++ b/gdb/jv-exp.y
@@ -1229,8 +1229,8 @@ push_variable (struct stoken name)
   char *tmp = copy_name (name);
   struct field_of_this_result is_a_field_of_this;
   struct symbol *sym;
-  sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN,
-		       &is_a_field_of_this);
+  sym = parse_lookup_symbol (tmp, expression_context_block, VAR_DOMAIN,
+			     &is_a_field_of_this);
   if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF)
     {
       if (symbol_read_needs_frame (sym))
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index 69e17d8..97617d2 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -545,8 +545,9 @@ block	:	fblock
 
 fblock	:	BLOCKNAME
 			{ struct symbol *sym
-			    = lookup_symbol (copy_name ($1), expression_context_block,
-					     VAR_DOMAIN, 0);
+			    = parse_lookup_symbol (copy_name ($1),
+						   expression_context_block,
+						   VAR_DOMAIN, 0);
 			  $$ = sym;}
 	;
 			     
@@ -554,8 +555,8 @@ fblock	:	BLOCKNAME
 /* GDB scope operator */
 fblock	:	block COLONCOLON BLOCKNAME
 			{ struct symbol *tem
-			    = lookup_symbol (copy_name ($3), $1,
-					     VAR_DOMAIN, 0);
+			    = parse_lookup_symbol (copy_name ($3), $1,
+						   VAR_DOMAIN, 0);
 			  if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
 			    error (_("No function \"%s\" in specified context."),
 				   copy_name ($3));
@@ -578,8 +579,8 @@ variable:	INTERNAL_VAR
 /* GDB scope operator */
 variable:	block COLONCOLON NAME
 			{ struct symbol *sym;
-			  sym = lookup_symbol (copy_name ($3), $1,
-					       VAR_DOMAIN, 0);
+			  sym = parse_lookup_symbol (copy_name ($3), $1,
+						     VAR_DOMAIN, 0);
 			  if (sym == 0)
 			    error (_("No symbol \"%s\" in specified context."),
 				   copy_name ($3));
@@ -592,7 +593,7 @@ variable:	block COLONCOLON NAME
 			    }
 
 			  write_exp_elt_opcode (OP_VAR_VALUE);
-			  /* block_found is set by lookup_symbol.  */
+			  /* block_found is set by parse_lookup_symbol.  */
 			  write_exp_elt_block (block_found);
 			  write_exp_elt_sym (sym);
 			  write_exp_elt_opcode (OP_VAR_VALUE); }
@@ -603,10 +604,10 @@ variable:	NAME
 			{ struct symbol *sym;
 			  struct field_of_this_result is_a_field_of_this;
 
- 			  sym = lookup_symbol (copy_name ($1),
-					       expression_context_block,
-					       VAR_DOMAIN,
-					       &is_a_field_of_this);
+ 			  sym = parse_lookup_symbol (copy_name ($1),
+						     expression_context_block,
+						     VAR_DOMAIN,
+						     &is_a_field_of_this);
 			  if (sym)
 			    {
 			      if (symbol_read_needs_frame (sym))
@@ -1009,7 +1010,7 @@ yylex (void)
 
     if (lookup_symtab (tmp))
       return BLOCKNAME;
-    sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN, 0);
+    sym = parse_lookup_symbol (tmp, expression_context_block, VAR_DOMAIN, 0);
     if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
       return BLOCKNAME;
     if (lookup_typename (parse_language, parse_gdbarch,
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index a989ac4..381ca49 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -657,8 +657,8 @@ block	:	BLOCKNAME
 
 block	:	block COLONCOLON name
 			{ struct symbol *tem
-			    = lookup_symbol (copy_name ($3), $1,
-					     VAR_DOMAIN, NULL);
+			    = parse_lookup_symbol (copy_name ($3), $1,
+						   VAR_DOMAIN, NULL);
 			  if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
 			    error (_("No function \"%s\" in specified context."),
 				   copy_name ($3));
@@ -667,14 +667,14 @@ block	:	block COLONCOLON name
 
 variable:	block COLONCOLON name
 			{ struct symbol *sym;
-			  sym = lookup_symbol (copy_name ($3), $1,
-					       VAR_DOMAIN, NULL);
+			  sym = parse_lookup_symbol (copy_name ($3), $1,
+						     VAR_DOMAIN, NULL);
 			  if (sym == 0)
 			    error (_("No symbol \"%s\" in specified context."),
 				   copy_name ($3));
 
 			  write_exp_elt_opcode (OP_VAR_VALUE);
-			  /* block_found is set by lookup_symbol.  */
+			  /* block_found is set by parse_lookup_symbol.  */
 			  write_exp_elt_block (block_found);
 			  write_exp_elt_sym (sym);
 			  write_exp_elt_opcode (OP_VAR_VALUE); }
@@ -702,9 +702,8 @@ variable:	qualified_name
 			  struct symbol *sym;
 			  struct minimal_symbol *msymbol;
 
-			  sym =
-			    lookup_symbol (name, (const struct block *) NULL,
-					   VAR_DOMAIN, NULL);
+			  sym = parse_lookup_symbol (name, NULL, VAR_DOMAIN,
+						     NULL);
 			  if (sym)
 			    {
 			      write_exp_elt_opcode (OP_VAR_VALUE);
@@ -1482,8 +1481,8 @@ yylex (void)
              inserted in FPC stabs debug info.  */
 	  static const char this_name[] = "this";
 
-	  if (lookup_symbol (this_name, expression_context_block,
-			     VAR_DOMAIN, NULL))
+	  if (parse_lookup_symbol (this_name, expression_context_block,
+				   VAR_DOMAIN, NULL))
 	    {
 	      free (uptokstart);
 	      return THIS;
@@ -1532,8 +1531,8 @@ yylex (void)
     if (is_a_field || parse_completion)
       sym = NULL;
     else
-      sym = lookup_symbol (tmp, expression_context_block,
-			   VAR_DOMAIN, &is_a_field_of_this);
+      sym = parse_lookup_symbol (tmp, expression_context_block,
+				 VAR_DOMAIN, &is_a_field_of_this);
     /* second chance uppercased (as Free Pascal does).  */
     if (!sym && is_a_field_of_this.type == NULL && !is_a_field)
       {
@@ -1547,8 +1546,8 @@ yylex (void)
        if (is_a_field || parse_completion)
 	 sym = NULL;
        else
-	 sym = lookup_symbol (tmp, expression_context_block,
-			      VAR_DOMAIN, &is_a_field_of_this);
+	 sym = parse_lookup_symbol (tmp, expression_context_block,
+				    VAR_DOMAIN, &is_a_field_of_this);
        if (sym || is_a_field_of_this.type != NULL || is_a_field)
          for (i = 0; i <= namelen; i++)
            {
@@ -1575,8 +1574,8 @@ yylex (void)
        if (is_a_field || parse_completion)
 	 sym = NULL;
        else
-	 sym = lookup_symbol (tmp, expression_context_block,
-			      VAR_DOMAIN, &is_a_field_of_this);
+	 sym = parse_lookup_symbol (tmp, expression_context_block,
+				    VAR_DOMAIN, &is_a_field_of_this);
        if (sym || is_a_field_of_this.type != NULL || is_a_field)
           for (i = 0; i <= namelen; i++)
             {
@@ -1672,8 +1671,9 @@ yylex (void)
 		      tmp1 += 2;
 		      memcpy (tmp1, namestart, p - namestart);
 		      tmp1[p - namestart] = '\0';
-		      cur_sym = lookup_symbol (ncopy, expression_context_block,
-					       VAR_DOMAIN, NULL);
+		      cur_sym = parse_lookup_symbol (ncopy,
+						     expression_context_block,
+						     VAR_DOMAIN, NULL);
 		      if (cur_sym)
 			{
 			  if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
diff --git a/gdb/parse.c b/gdb/parse.c
index 2d530df..623a172 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -1886,6 +1886,19 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile)
   return exp_iterate (exp, exp_uses_objfile_iter, objfile);
 }
 
+/* Behave like lookup_symbol_in_language, but performed with
+   parse_language.  */
+
+struct symbol *
+parse_lookup_symbol (const char *name, const struct block *block,
+		     domain_enum domain,
+		     struct field_of_this_result *is_a_field_of_this)
+{
+  return lookup_symbol_in_language (name, block, domain,
+				    parse_language->la_language,
+				    is_a_field_of_this);
+}
+
 void
 _initialize_parse (void)
 {
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 8d25311..7d72607 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -374,5 +374,10 @@ extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile);
 extern void mark_completion_tag (enum type_code, const char *ptr,
 				 int length);
 
+extern struct symbol *
+  parse_lookup_symbol (const char *name, const struct block *block,
+		       domain_enum domain,
+		       struct field_of_this_result *is_a_field_of_this);
+
 #endif /* PARSER_DEFS_H */
 
diff --git a/gdb/testsuite/gdb.cp/parse-lang.cc b/gdb/testsuite/gdb.cp/parse-lang.cc
new file mode 100644
index 0000000..46af670
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/parse-lang.cc
@@ -0,0 +1,40 @@
+/* Copyright 2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+class C
+{
+public:
+  int v;
+  void m ();
+};
+
+void
+C::m ()
+{
+}
+
+void
+marker ()
+{
+}
+
+int
+main ()
+{
+  C c = { 42 };
+
+  c.m ();
+  marker ();
+}
diff --git a/gdb/testsuite/gdb.cp/parse-lang.exp b/gdb/testsuite/gdb.cp/parse-lang.exp
new file mode 100644
index 0000000..c0051e9
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/parse-lang.exp
@@ -0,0 +1,31 @@
+# Copyright 2012-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .cc
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
+    return -1
+}
+
+# Place the breakpoint before inferior gets started.  Then the breakpoint
+# condition will be re-evaluated in non-C++ startup code.
+gdb_breakpoint "C::m if v == 42"
+
+gdb_breakpoint "marker"
+
+# runto_main would delete the breakpoint.
+gdb_run_cmd
+
+gdb_test "" {Breakpoint [0-9]+, C::m .*} "breakpoint hit"



More information about the Gdb-patches mailing list