From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25424 invoked by alias); 22 May 2012 15:49:31 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 25322 invoked by uid 9813); 22 May 2012 15:49:28 -0000 Date: Tue, 22 May 2012 15:49:00 -0000 Message-ID: <20120522154928.25300.qmail@sourceware.org> From: sergiodj@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-sergiodj-cpp-template-lookup: [C++-template-lookup] Import of the first patch. X-Git-Refname: refs/heads/archer-sergiodj-cpp-template-lookup X-Git-Reftype: branch X-Git-Oldrev: c46b4e83e39b3a044212841d43d03b23841cf0f6 X-Git-Newrev: 656062dbd8105c467acfa7434f1c8a58d8afe94d X-SW-Source: 2012-q2/txt/msg00032.txt.bz2 List-Id: The branch, archer-sergiodj-cpp-template-lookup has been updated via 656062dbd8105c467acfa7434f1c8a58d8afe94d (commit) from c46b4e83e39b3a044212841d43d03b23841cf0f6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 656062dbd8105c467acfa7434f1c8a58d8afe94d Author: Sergio Durigan Junior Date: Tue May 22 12:48:05 2012 -0300 [C++-template-lookup] Import of the first patch. URL: http://sourceware.org/ml/gdb-patches/2010-07/msg00284.html ----------------------------------------------------------------------- Summary of changes: gdb/cp-name-parser.y | 9 ++- gdb/cp-support.c | 68 +++++++++++++++++++++- gdb/cp-support.h | 4 + gdb/dwarf2read.c | 21 +++++++ gdb/symtab.c | 61 ++++++++++++++++++++ gdb/symtab.h | 11 ++++ gdb/testsuite/gdb.cp/cp-relocate.exp | 4 + gdb/testsuite/gdb.cp/temp-op.cc | 105 ++++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/temp-op.exp | 68 ++++++++++++++++++++++ gdb/valops.c | 2 +- 10 files changed, 348 insertions(+), 5 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/temp-op.cc create mode 100644 gdb/testsuite/gdb.cp/temp-op.exp First 500 lines of diff: diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index 6767fa5..0158774 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -2058,9 +2058,12 @@ cp_merge_demangle_parse_infos (struct demangle_parse_info *dest, cp_demangled_name_parse_free (src); } -/* Convert a demangled name to a demangle_component tree. On success, - a structure containing the root of the new tree is returned; it must - be freed by calling cp_demangled_name_parse_free. On error, NULL is +/* Convert a demangled name to a demangle_component tree. The structure + of the tree depends on the format of each node in the tree. For + information on the structure of a node see the comment corresponding + to its type in demangle_component_type. + On success, the root of the new tree is returned; it is valid until the + next call to this function and should not be freed. On error, NULL is returned, and an error message will be set in *ERRMSG (which does not need to be freed). */ diff --git a/gdb/cp-support.c b/gdb/cp-support.c index bafdb86..467e9ab 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -833,6 +833,72 @@ cp_remove_params (const char *demangled_name) return ret; } +/* Returns 1 if the given name contains template parameters; + otherwise return 0. + Used as a quick heuristic to avoid more expensive template + parsing when not necessary. */ + +int +cp_name_has_template_parameters (const char *name) +{ + char *c = strchr (name, '<'); + return c != NULL && strchr (c+1, '>') != NULL; +} + +/* Remove template parameters components from the give tree. */ + +static struct demangle_component * +cp_remove_template_params_component (struct demangle_component *comp) +{ + + gdb_assert (comp != NULL); + + switch (comp->type) + { + case DEMANGLE_COMPONENT_TEMPLATE: + /* If there is a template component remove this node by re-parenting the + the left child. */ + comp = d_left (comp); + break; + case DEMANGLE_COMPONENT_QUAL_NAME: + /* For a qualified name remove template components from the right + subtree. */ + d_right (comp) = cp_remove_template_params_component (d_right (comp)); + break; + case DEMANGLE_COMPONENT_TYPED_NAME: + /* Template components, if present, will be in the left subtree. Remove + them. */ + d_left (comp) = cp_remove_template_params_component (d_left (comp)); + break; + default: + break; + } + + return comp; +} + +/* Remove template parameters from the given name. The returned string is + malloc'ed and must be properly saved and freed. */ + +char * +cp_remove_template_params (const char *name) +{ + struct demangle_component *ret_comp; + char *ret = NULL; + + if (name == NULL) + return NULL; + + ret_comp = cp_demangled_name_to_comp (name, NULL); + if (ret_comp == NULL) + return NULL; + + ret_comp = cp_remove_template_params_component (ret_comp); + ret = cp_comp_to_string (ret_comp, 10); + + return ret; +} + /* Here are some random pieces of trivia to keep in mind while trying to take apart demangled names: @@ -1069,7 +1135,7 @@ overload_list_add_symbol (struct symbol *sym, return; /* Get the demangled name without parameters */ - sym_name = cp_remove_params (SYMBOL_NATURAL_NAME (sym)); + sym_name = cp_remove_params (SYMBOL_SEARCH_NAME (sym)); if (!sym_name) return; diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 03ccb73..ff07184 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -161,6 +161,10 @@ extern char *cp_func_name (const char *full_name); extern char *cp_remove_params (const char *demangled_name); +extern int cp_name_has_template_parameters (const char *name); + +extern char *cp_remove_template_params (const char *name); + extern struct symbol **make_symbol_overload_list (const char *, const char *); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 6ddf236..33fea34 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -13281,6 +13281,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, if (name) { const char *linkagename; + const char *search_name = NULL; int suppress_add = 0; if (space) @@ -13302,6 +13303,26 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, (char *) dwarf2_full_name (name, die, cu), NULL); + /* For C++ if the name contains template parameters remove them, and set + the cleaned up name to be the search name. */ + if (cu->language == language_cplus && linkagename + && cp_name_has_template_parameters (linkagename)) + { + char *tmp = cp_remove_template_params (linkagename); + + if (tmp != NULL && strcmp (tmp, linkagename) != 0) + { + search_name = obsavestring (tmp, strlen (tmp), + &objfile->objfile_obstack); + + symbol_set_cplus_search_name (&sym->ginfo, + objfile, + search_name); + } + + xfree (tmp); + } + /* Default assumptions. Use the passed type or decode it from the die. */ SYMBOL_DOMAIN (sym) = VAR_DOMAIN; diff --git a/gdb/symtab.c b/gdb/symtab.c index 46c365c..b5ef6fc 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -490,7 +490,33 @@ symbol_get_demangled_name (const struct general_symbol_info *gsymbol) return gsymbol->language_specific.mangled_lang.demangled_name; } +/* Set the search name of the give GSYMBOL to name. */ + +void +symbol_set_cplus_search_name (struct general_symbol_info *gsymbol, + struct objfile *objfile, + const char *name) +{ + if (gsymbol->language_specific.cplus_specific == NULL) + symbol_init_cplus_specific (gsymbol, objfile); + + gsymbol->language_specific.cplus_specific->search_name = (char *) name; +} + +/* Get the search name of the give GSYMBOL. */ + +char* +symbol_get_cplus_search_name (const struct general_symbol_info *gsymbol) +{ + if (gsymbol->language_specific.cplus_specific != NULL + && gsymbol->language_specific.cplus_specific->search_name != NULL) + return gsymbol->language_specific.cplus_specific->search_name; + + return symbol_natural_name (gsymbol); +} + + /* Initialize the language dependent portion of a symbol depending upon the language for the symbol. */ @@ -883,6 +909,8 @@ symbol_search_name (const struct general_symbol_info *gsymbol) { if (gsymbol->language == language_ada) return gsymbol->name; + else if (gsymbol->language == language_cplus) + return symbol_get_cplus_search_name (gsymbol); else return symbol_natural_name (gsymbol); } @@ -1907,6 +1935,18 @@ find_main_filename (void) return (NULL); } +/* Return 1 if NAME matches SYM's template name. */ + +static int +symbol_matches_template_name (const char *name, struct symbol *sym) +{ + const char *template_name = SYMBOL_NATURAL_NAME(sym); + if (template_name == NULL) + return 0; + + return strcmp_iw (template_name, name) == 0; +} + /* Search BLOCK for symbol NAME in DOMAIN. Note that if NAME is the demangled form of a C++ symbol, we will fail @@ -1927,10 +1967,31 @@ lookup_block_symbol (const struct block *block, const char *name, if (!BLOCK_FUNCTION (block)) { + const char *template_name = NULL; + + if (current_language->la_language == language_cplus + && cp_name_has_template_parameters (name)) + { + template_name = name; + name = cp_remove_template_params (name); + + if (name == NULL) + { + /* Not a legal C++ name. */ + return NULL; + } + } + for (sym = block_iter_name_first (block, name, &iter); sym != NULL; sym = block_iter_name_next (name, &iter)) { + /* For C++ if the name being searched for contains template + parameters check the template name of the symbol. */ + if (template_name != NULL + && !symbol_matches_template_name (template_name, sym)) + continue; + if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), SYMBOL_DOMAIN (sym), domain)) return sym; diff --git a/gdb/symtab.h b/gdb/symtab.h index 526fe5a..9888025 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -83,6 +83,11 @@ struct probe; struct cplus_specific { const char *demangled_name; + + /* If the symbol name contains template parameters this is the name with + these parameters removed to be used during search. Otherwise this + should be NULL, and the regular symbol name should be used. */ + char *search_name; }; /* Define a structure for the information that is common to all symbol types, @@ -167,6 +172,12 @@ extern void symbol_set_demangled_name (struct general_symbol_info *, char *, extern const char *symbol_get_demangled_name (const struct general_symbol_info *); +extern void symbol_set_cplus_search_name (struct general_symbol_info *gsymbol, + struct objfile *objfile, + const char *name); + +extern char* symbol_get_cplus_search_name (const struct general_symbol_info *); + extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *); /* Note that all the following SYMBOL_* macros are used with the diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp index 2981228..e658c7b 100644 --- a/gdb/testsuite/gdb.cp/cp-relocate.exp +++ b/gdb/testsuite/gdb.cp/cp-relocate.exp @@ -52,6 +52,8 @@ gdb_start gdb_reinitialize_dir $srcdir/$subdir gdb_file_cmd ${binfile} +gdb_test_no_output "set language c++" "" + # Find the interesting functions. We go to a little effort to find # the right function names here, to work around PR c++/40. set func1_name "" @@ -123,6 +125,8 @@ gdb_exit gdb_start gdb_reinitialize_dir $srcdir/$subdir +gdb_test_no_output "set language c++" "" + gdb_test "add-symbol-file ${binfile} 0 -s ${func1_sec} 0x10000 -s ${func2_sec} 0x20000" \ "Reading symbols from .*${testfile}\\.o\\.\\.\\.done\\.(|\r\nUsing host libthread_db library .*libthread_db.so.*\\.)" \ "add-symbol-file ${testfile}.o" \ diff --git a/gdb/testsuite/gdb.cp/temp-op.cc b/gdb/testsuite/gdb.cp/temp-op.cc new file mode 100644 index 0000000..6d4b13d --- /dev/null +++ b/gdb/testsuite/gdb.cp/temp-op.cc @@ -0,0 +1,105 @@ +class A +{ +}; + +template +int foo (T, char) +{ + T t; + return 11; +} + +template +int foo2 (T, T2, char) +{ + T t; + return 11; +} + +namespace C +{ + namespace D { + template + int foo3 (T, T2, char) + { + T t; + return 11; + } + } +} +int operator<< (A, int) +{ + return 12; +} + +int operator< (A, int) +{ + return 13; +} + +int operator<= (A, int) +{ + return 14; +} + +template +int operator==(T, char) +{ + return 15; +} + +int operator==(A, int) +{ + return 16; +} + +template +class B{ + T t; +public: + int operator==(int) + { + return 17; + } +}; + +int operator== (B, char){ + return 18; +} + +template +class Outer{ + public: + template + class Inner{ + public: + template + class ReallyInner{}; + }; +}; + + +int main () +{ + A a; + + foo (a, 'a'); + foo (a, 1); + foo2 (a, a, 'a'); + C::D::foo3 (a, a, 'a'); + + a << 22; + a < 22; + a <= 22; + + a == 'a'; + a == 1; + + B b; + b == 1; + b == 'a'; + + Outer::Inner::ReallyInner<5> oir; + + return 0; +} diff --git a/gdb/testsuite/gdb.cp/temp-op.exp b/gdb/testsuite/gdb.cp/temp-op.exp new file mode 100644 index 0000000..f48582f --- /dev/null +++ b/gdb/testsuite/gdb.cp/temp-op.exp @@ -0,0 +1,68 @@ +# Copyright 2008 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 . + +if $tracelevel then { + strace $tracelevel +} + +set testfile temp-op +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +############################################ + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +# Test that a templated function can be found +# with out specification of template arguments +gdb_test "p foo(a, 'a')" "= 11" + +# Test that function names with '<' in their names +# are not mistaken for templates +gdb_test "p a << 22" "= 12" +gdb_test "p a < 22" "= 13" +gdb_test "p a <= 22" "= 14" + +# Test that a template operator can be correctly +# evaluated +gdb_test "p a == 'a'" "= 15" + +# Test that overload resolution is still correctly +# performed. +gdb_test "p a == 1" "= 16" + +# Test calling a member function of a template class +gdb_test "p b == 1" "= 17" +gdb_test "p b == 'a'" "= 18" + +# Test that printing the a template name without +# template parameters does not return an arbitrary match + +gdb_test "p foo" "No symbol \"foo\" in current context" +gdb_test "ptype B" "No symbol \"foo\" in current context" diff --git a/gdb/valops.c b/gdb/valops.c index feb47f5..563c9ea 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2686,7 +2686,7 @@ find_overload_match (struct value **args, int nargs, hooks/post-receive -- Repository for Project Archer.