From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8229 invoked by alias); 10 Jan 2013 19:51:11 -0000 Received: (qmail 8214 invoked by uid 22791); 10 Jan 2013 19:51:10 -0000 X-SWARE-Spam-Status: No, hits=-6.5 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_YY X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 Jan 2013 19:50:58 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r0AJowwW000503 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 10 Jan 2013 14:50:58 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r0AJouUw009110 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Thu, 10 Jan 2013 14:50:57 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFC: fix PR symtab/11464 Date: Thu, 10 Jan 2013 19:51:00 -0000 Message-ID: <87hamovmu7.fsf@fleche.redhat.com> MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2013-01/txt/msg00203.txt.bz2 This patch fixes PR symtab/11464. The bug is that using a quoted destructor in an expression crashes gdb. The example from the PR is: ptype gnu_obj_1::'~gnu_obj_1' This is odd, but of course shouldn't crash. The basic problem was that when yylex and classify_inner_name were updated to handle NAME in addition to TYPENAME, nothing was done to ensure that the value of yylval seen by classify_inner_name actually had a valid 'tsym.type' field. And, in this case, it doesn't. The patch fixes this by making some state more explicit. I think this is a plus -- really the whole lexer could use a cleanup along these lines, removing most uses of yylval, ensuring that the proper union fields are always used, etc. But, I didn't go that far. Built and regtested on x86-64 Fedora 16. A new test case, from the PR, is included -- I didn't include the full patch from the PR as it also covers a couple of unrelated bugs. Tom 2013-01-10 Tom Tromey PR symtab/11464: * c-exp.y (lex_one_token): Initialize other fields of yylval on NAME return. (classify_inner_name): Remove 'first_name' argument, add 'context'. Remove unused variable. (yylex): Explicitly maintain the context type. Exit loop earlier if NAME result is seen. 2013-01-10 Tom Tromey * gdb.cp/m-static.cc (gnu_obj_1::~gnu_obj_1): New destructor. * gdb.cp/m-static.exp: Add tests to print quoted destructor. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 9847120..9ef4b39 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -2719,6 +2719,10 @@ lex_one_token (void) if (parse_completion && *lexptr == '\0') saw_name_at_eof = 1; + + yylval.ssym.stoken = yylval.sval; + yylval.ssym.sym = NULL; + yylval.ssym.is_a_field_of_this = 0; return NAME; } @@ -2859,26 +2863,26 @@ classify_name (const struct block *block) } /* Like classify_name, but used by the inner loop of the lexer, when a - name might have already been seen. FIRST_NAME is true if the token - in `yylval' is the first component of a name, false otherwise. */ + name might have already been seen. CONTEXT is the context type, or + NULL if this is the first component of a name. */ static int -classify_inner_name (const struct block *block, int first_name) +classify_inner_name (const struct block *block, struct type *context) { - struct type *type, *new_type; + struct type *type; char *copy; - if (first_name) + if (context == NULL) return classify_name (block); - type = check_typedef (yylval.tsym.type); + type = check_typedef (context); if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) return ERROR; - copy = copy_name (yylval.tsym.stoken); - yylval.ssym.sym = cp_lookup_nested_symbol (yylval.tsym.type, copy, block); + copy = copy_name (yylval.ssym.stoken); + yylval.ssym.sym = cp_lookup_nested_symbol (type, copy, block); if (yylval.ssym.sym == NULL) return ERROR; @@ -2893,7 +2897,6 @@ classify_inner_name (const struct block *block, int first_name) return TYPENAME; default: - yylval.ssym.is_a_field_of_this = 0; return NAME; } internal_error (__FILE__, __LINE__, _("not reached")); @@ -2915,6 +2918,7 @@ yylex (void) { token_and_value current; int first_was_coloncolon, last_was_coloncolon, first_iter; + struct type *context_type = NULL; if (popping && !VEC_empty (token_and_value, token_fifo)) { @@ -2936,7 +2940,10 @@ yylex (void) last_was_coloncolon = first_was_coloncolon; obstack_free (&name_obstack, obstack_base (&name_obstack)); if (!last_was_coloncolon) - obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length); + { + obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length); + context_type = yylval.tsym.type; + } current.value = yylval; first_iter = 1; while (1) @@ -2953,7 +2960,7 @@ yylex (void) classification = classify_inner_name (first_was_coloncolon ? NULL : expression_context_block, - first_iter); + context_type); /* We keep going until we either run out of names, or until we have a qualified name which is not a type. */ if (classification != TYPENAME && classification != NAME) @@ -2964,7 +2971,7 @@ yylex (void) } /* Update the partial name we are constructing. */ - if (!first_iter) + if (context_type != NULL) { /* We don't want to put a leading "::" into the name. */ obstack_grow_str (&name_obstack, "::"); @@ -2978,6 +2985,11 @@ yylex (void) current.token = classification; last_was_coloncolon = 0; + + if (classification == NAME) + break; + + context_type = yylval.tsym.type; } else if (next.token == COLONCOLON && !last_was_coloncolon) last_was_coloncolon = 1; diff --git a/gdb/testsuite/gdb.cp/m-static.cc b/gdb/testsuite/gdb.cp/m-static.cc index e9dce18..8472988 100644 --- a/gdb/testsuite/gdb.cp/m-static.cc +++ b/gdb/testsuite/gdb.cp/m-static.cc @@ -17,6 +17,7 @@ protected: public: gnu_obj_1(antiquities a, long l) {} + ~gnu_obj_1() {} long method () { diff --git a/gdb/testsuite/gdb.cp/m-static.exp b/gdb/testsuite/gdb.cp/m-static.exp index 38d2498..ae4b2ad 100644 --- a/gdb/testsuite/gdb.cp/m-static.exp +++ b/gdb/testsuite/gdb.cp/m-static.exp @@ -64,6 +64,14 @@ gdb_test "print test1.key2" "\\$\[0-9\]* = 77" "simple object, static long" # simple object, static enum gdb_test "print test1.value" "\\$\[0-9\]* = oriental" "simple object, static enum" +gdb_test "print test1.'~gnu_obj_1'" \ + { = {void \(gnu_obj_1 \*( const)?, int\)} 0x[0-9a-f]+ } \ + "simple object instance, print quoted destructor" + +gdb_test "ptype gnu_obj_1::'~gnu_obj_1'" \ + {type = void \(gnu_obj_1 \* const\)} \ + "simple object class, ptype quoted destructor" + # Two. # derived template object, base static const bool