forked from Imagelibrary/binutils-gdb
Compare commits
3 Commits
users/palv
...
users/keit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1ecccc4cd | ||
|
|
f79a008250 | ||
|
|
a1c8ba9846 |
4
gdb/NEWS
4
gdb/NEWS
@@ -6,6 +6,10 @@
|
||||
* 'info proc' now works on running processes on FreeBSD systems and core
|
||||
files created on FreeBSD systems.
|
||||
|
||||
* C++ developers may now ignore template parameter lists when specifying
|
||||
locations, e.g., while setting breakpoints. This is analogous to how
|
||||
completion and symbol lookup handles overloaded functions or ABI tags.
|
||||
|
||||
*** Changes in GDB 8.1
|
||||
|
||||
* GDB now supports dynamically creating arbitrary register groups specified
|
||||
|
||||
@@ -1643,6 +1643,12 @@ cp_search_name_hash (const char *search_name)
|
||||
&& string[5] != ':')
|
||||
break;
|
||||
|
||||
/* Ignore template parameter lists. */
|
||||
if (string[0] == '<'
|
||||
&& string[1] != '(' && string[1] != '<' && string[1] != '='
|
||||
&& string[1] != ' ' && string[1] != '\0')
|
||||
break;
|
||||
|
||||
hash = SYMBOL_HASH_NEXT (hash, *string);
|
||||
}
|
||||
return hash;
|
||||
@@ -1696,7 +1702,7 @@ cp_symbol_name_matches_1 (const char *symbol_search_name,
|
||||
while (true)
|
||||
{
|
||||
if (strncmp_iw_with_mode (sname, lookup_name, lookup_name_len,
|
||||
mode, language_cplus, match_for_lcd) == 0)
|
||||
mode, language_cplus, match_for_lcd, true) == 0)
|
||||
{
|
||||
if (comp_match_res != NULL)
|
||||
{
|
||||
|
||||
@@ -15188,6 +15188,52 @@ also use the @value{GDBN} command-line word completion facilities to list the
|
||||
available choices, or to finish the type list for you.
|
||||
@xref{Completion,, Command Completion}, for details on how to do this.
|
||||
|
||||
@item @r{Breakpoints in template functions}
|
||||
|
||||
Similar to overloaded symbols, @value{GDBN} will set breakpoints in all
|
||||
template instantiations with the user-specified name. To set a breakpoint in
|
||||
a specific template instantiation, include the template parameter list.
|
||||
|
||||
@smallexample
|
||||
(gdb) b mytemplate
|
||||
Breakpoint 1 at 0x40085b: mytemplate. (2 locations)
|
||||
(gdb) info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
1 breakpoint keep y <MULTIPLE>
|
||||
1.1 y 0x40085b in mytemplate<int>(int)
|
||||
at mytemplate.cc:8
|
||||
1.2 y 0x40087a in mytemplate<double>(double)
|
||||
at mytemplate.cc:8
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
In the above example, @value{GDBN} searches all namespaces and types for
|
||||
functions named @code{mytemplate}, ignoring template parameter lists and
|
||||
function arguments.
|
||||
|
||||
In the below example, a template parameter list is specified, and @value{GDBN}
|
||||
searches all namespaces and types for the specific instantiation:
|
||||
|
||||
@smallexample
|
||||
(gdb) b mytemplate<int>
|
||||
Breakpoint 2 at 0x40085b: file mytemplate.cc, line 8.
|
||||
(gdb) info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
2 breakpoint keep y 0x40085b in mytemplate<int>(int)
|
||||
at mytemplate.cc:8
|
||||
@end smallexample
|
||||
|
||||
Just as with function overloads, the @kbd{-qualified} flag may be used to
|
||||
override this behavior, causing @value{GDBN} to search for a specific
|
||||
function without ignoring template parameter lists.
|
||||
|
||||
@smallexample
|
||||
(gdb) b mytemplate
|
||||
Breakpoint 3 at 0x40085b: mytemplate. (2 locations)
|
||||
(gdb) b -qualified mytemplate
|
||||
Function "mytemplate" not defined.
|
||||
@end smallexample
|
||||
|
||||
@item @r{Breakpoints in functions with ABI tags}
|
||||
|
||||
The GNU C@t{++} compiler introduced the notion of ABI ``tags'', which
|
||||
|
||||
@@ -1277,83 +1277,6 @@ find_methods (struct type *t, enum language t_lang, const char *name,
|
||||
VEC_safe_push (typep, *superclasses, TYPE_BASECLASS (t, ibase));
|
||||
}
|
||||
|
||||
/* Find an instance of the character C in the string S that is outside
|
||||
of all parenthesis pairs, single-quoted strings, and double-quoted
|
||||
strings. Also, ignore the char within a template name, like a ','
|
||||
within foo<int, int>, while considering C++ operator</operator<<. */
|
||||
|
||||
const char *
|
||||
find_toplevel_char (const char *s, char c)
|
||||
{
|
||||
int quoted = 0; /* zero if we're not in quotes;
|
||||
'"' if we're in a double-quoted string;
|
||||
'\'' if we're in a single-quoted string. */
|
||||
int depth = 0; /* Number of unclosed parens we've seen. */
|
||||
const char *scan;
|
||||
|
||||
for (scan = s; *scan; scan++)
|
||||
{
|
||||
if (quoted)
|
||||
{
|
||||
if (*scan == quoted)
|
||||
quoted = 0;
|
||||
else if (*scan == '\\' && *(scan + 1))
|
||||
scan++;
|
||||
}
|
||||
else if (*scan == c && ! quoted && depth == 0)
|
||||
return scan;
|
||||
else if (*scan == '"' || *scan == '\'')
|
||||
quoted = *scan;
|
||||
else if (*scan == '(' || *scan == '<')
|
||||
depth++;
|
||||
else if ((*scan == ')' || *scan == '>') && depth > 0)
|
||||
depth--;
|
||||
else if (*scan == 'o' && !quoted && depth == 0)
|
||||
{
|
||||
/* Handle C++ operator names. */
|
||||
if (strncmp (scan, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0)
|
||||
{
|
||||
scan += CP_OPERATOR_LEN;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
while (isspace (*scan))
|
||||
{
|
||||
++scan;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
}
|
||||
if (*scan == '\0')
|
||||
break;
|
||||
|
||||
switch (*scan)
|
||||
{
|
||||
/* Skip over one less than the appropriate number of
|
||||
characters: the for loop will skip over the last
|
||||
one. */
|
||||
case '<':
|
||||
if (scan[1] == '<')
|
||||
{
|
||||
scan++;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (scan[1] == '>')
|
||||
{
|
||||
scan++;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The string equivalent of find_toplevel_char. Returns a pointer
|
||||
to the location of NEEDLE in HAYSTACK, ignoring any occurrences
|
||||
inside "()" and "<>". Returns NULL if NEEDLE was not found. */
|
||||
|
||||
@@ -163,13 +163,6 @@ extern const char *get_gdb_linespec_parser_quote_characters (void);
|
||||
|
||||
extern int is_ada_operator (const char *string);
|
||||
|
||||
/* Find an instance of the character C in the string S that is outside
|
||||
of all parenthesis pairs, single-quoted strings, and double-quoted
|
||||
strings. Also, ignore the char within a template name, like a ','
|
||||
within foo<int, int>. */
|
||||
|
||||
extern const char *find_toplevel_char (const char *s, char c);
|
||||
|
||||
/* Find the end of the (first) linespec pointed to by *STRINGP.
|
||||
STRINGP will be advanced to this point. */
|
||||
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 1992-2018 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/>. */
|
||||
|
||||
/* This test code is from Wendell Baker (wbaker@comet.berkeley.edu) */
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -730,6 +747,34 @@ template<class C> int FunctionArg<C>::method(Empty<void (FunctionArg<C>)> &arg)
|
||||
Empty<void(FunctionArg<int>)> empty;
|
||||
FunctionArg<int> arg;
|
||||
|
||||
template <typename T1>
|
||||
struct Foozle
|
||||
{
|
||||
int x;
|
||||
T1 t;
|
||||
template <typename T2>
|
||||
T2 fogey (T2 plop);
|
||||
};
|
||||
|
||||
template <typename T1>
|
||||
template <typename T2>
|
||||
T2 Foozle<T1>::fogey (T2 plop)
|
||||
{
|
||||
return plop;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int operator< (T &lhs, T &rhs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int operator<< (T &obj, T &val)
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
@@ -801,5 +846,24 @@ int main()
|
||||
|
||||
arg.method(empty);
|
||||
|
||||
return 0;
|
||||
Empty<int> e;
|
||||
Foozle<int> fzi;
|
||||
x = fzi.fogey (0);
|
||||
c = fzi.fogey<char> ('a');
|
||||
e = fzi.fogey<Empty<int>> (e);
|
||||
Foozle<char> fzc;
|
||||
c = fzc.fogey ('b');
|
||||
x = fzc.fogey<int> (0);
|
||||
e = fzc.fogey<Empty<int>> (e);
|
||||
Foozle<Empty<int>> fze;
|
||||
e = fze.fogey (e);
|
||||
c = fze.fogey<char> ('c');
|
||||
x = fze.fogey<int> (0);
|
||||
|
||||
z = e < e;
|
||||
z += e << e;
|
||||
z += fzi < fzi;
|
||||
z += fzi << fzi;
|
||||
|
||||
return 0; // break here
|
||||
}
|
||||
|
||||
@@ -283,12 +283,8 @@ do_tests
|
||||
# weren't breakpointing past a point where the below expressions were
|
||||
# initialized in the actual source. - djb
|
||||
|
||||
gdb_test "b 770" \
|
||||
"Breakpoint .* at .*, line 770."
|
||||
|
||||
gdb_test "c" \
|
||||
"Continuing.*Breakpoint .*" \
|
||||
"continue to line 770"
|
||||
gdb_breakpoint [gdb_get_line_number "break here"]
|
||||
gdb_continue_to_breakpoint "continue to test marker"
|
||||
|
||||
gdb_test "print fint" \
|
||||
"\\$\[0-9\]* = \\{x = 0, t = 0\\}"
|
||||
@@ -584,3 +580,70 @@ gdb_test "print Garply<Garply<char> >::garply" \
|
||||
# Now should work fine
|
||||
gdb_test "break Garply<Garply<char> >::garply" \
|
||||
"Breakpoint \[0-9\]* at $hex: file .*templates.cc, line.*"
|
||||
|
||||
#
|
||||
# Template wild-matching tests
|
||||
#
|
||||
|
||||
# Turn off "ask" when multiple symbols are seen.
|
||||
gdb_test_no_output "set multiple-symbols all"
|
||||
|
||||
# Test setting breakpoints in a method of all class template instantiations,
|
||||
# including overloads.
|
||||
gdb_test "break Foo::foo" "Breakpoint.*at.* \\(3 locations\\)"
|
||||
foreach t [list "int" "char" "volatile char *"] {
|
||||
gdb_breakpoint "Foo<$t>::foo (int, $t)"
|
||||
gdb_breakpoint "Foo::foo (int, $t)"
|
||||
}
|
||||
|
||||
gdb_test "break Bar::bar" "Breakpoint.*at.* \\(2 locations\\)"
|
||||
gdb_test "break Bar::bar (int, int)" "Breakpoint.*at.* \\(2 locations\\)"
|
||||
foreach val [list 1 33] {
|
||||
gdb_breakpoint "Bar<int, $val>::bar (int, int)"
|
||||
}
|
||||
|
||||
# Test setting breakpoints in a member function template of a class template,
|
||||
# including overloads.
|
||||
gdb_test "break Foozle::fogey" "Breakpoint.*at.* \\(9 locations\\)" \
|
||||
"break at template method fogey"
|
||||
foreach t [list "int" "char" "Empty<int>"] {
|
||||
gdb_test "break Foozle::fogey ($t)" "Breakpoint.*at.* \\(3 locations\\)"
|
||||
gdb_test "break Foozle::fogey<$t>" "Breakpoint.*at.* \\(3 locations\\)"
|
||||
foreach u [list "int" "char" "Empty<int>"] {
|
||||
gdb_breakpoint "Foozle<$t>::fogey<$u>" message
|
||||
gdb_breakpoint "Foozle<$t>::fogey<$u> ($u)" message
|
||||
}
|
||||
}
|
||||
|
||||
# Test templated operators < and <<. Restrict results to only the test
|
||||
# source file.
|
||||
# operator<:
|
||||
# 1. operator< (const T2&, const T2&)
|
||||
# 2. operator< (const T2&, char)
|
||||
# 3. operator< <Empty<int>>
|
||||
# 4. operator< <Foozle<in>>
|
||||
#
|
||||
# operator<<:
|
||||
# 1. operator<< <Empty<int>>
|
||||
# 2. operator<< <Foozle<int>>
|
||||
gdb_test "break -source $srcfile -func operator<" \
|
||||
"Breakpoint.*at.* \\(4 locations\\)"
|
||||
gdb_test "break -source $srcfile -func operator<<" \
|
||||
"Breakpoint.*at.* \\(2 locations\\)"
|
||||
foreach t [list "Empty" "Foozle"] {
|
||||
set tt "$t<int>"
|
||||
gdb_breakpoint "operator< <$tt>" message
|
||||
gdb_breakpoint "operator<< <$tt>" message
|
||||
|
||||
# Try a specific instance, both with and without whitespace
|
||||
# after the template-template parameter.
|
||||
gdb_breakpoint "operator< <$tt> ($tt&, $tt&)" message
|
||||
gdb_breakpoint "operator< <$tt > ($tt&, $tt&)" message
|
||||
gdb_breakpoint "operator<< <$tt> ($tt&, $tt&)" message
|
||||
gdb_breakpoint "operator<< <$tt > ($tt&, $tt&)" message
|
||||
}
|
||||
|
||||
# Test that "-qualified" finds no matching locations.
|
||||
gdb_test_no_output "set breakpoint pending off"
|
||||
gdb_test "break -qualified Foozle::fogey" \
|
||||
"Function \"Foozle::fogey\" not defined."
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# This file is part of the gdb testsuite.
|
||||
|
||||
load_lib completion-support.exp
|
||||
load_lib data-structures.exp
|
||||
|
||||
standard_testfile cpls.cc cpls2.cc cpls-hyphen.cc
|
||||
|
||||
@@ -24,6 +25,217 @@ if {[prepare_for_testing "failed to prepare" $testfile \
|
||||
return -1
|
||||
}
|
||||
|
||||
#
|
||||
# Some convenience procedures for testing template parameter list
|
||||
# completion.
|
||||
#
|
||||
|
||||
# For the variable named ARGLISTVAR, which should be the name of an
|
||||
# argument list in the calling frame, "consume" the top-most token.
|
||||
# [See comments for makefoo for description of arglist format.]
|
||||
|
||||
proc consume {arglistvar} {
|
||||
upvar $arglistvar arglist
|
||||
|
||||
# ARGLIST is a string -- simply strip off the first character.
|
||||
set arglist [string range $arglist 1 end]
|
||||
}
|
||||
|
||||
# Create a function template named NAME, using the given stack ID to grab
|
||||
# NUM template parameters. The result is pushed back onto the
|
||||
# stack. NUM may be "all," in which case we use the entire stack
|
||||
# to create the function template, including function arguments.
|
||||
# The resulting template function's arguments are taken from the test
|
||||
# source code for the function "foo" and is not generalized.
|
||||
|
||||
proc maket {sid name {num 1}} {
|
||||
|
||||
# Set up a temporary stack of parameters. This will reverse
|
||||
# the order in SID so that when they are popped again below,
|
||||
# we get them in the correct order. This also takes into account
|
||||
# how many levels of the result stack we want to consider.
|
||||
|
||||
set paramstack [::Stack::new]
|
||||
if {[string equal $num "all"]} {
|
||||
while {![stack empty $sid]} {
|
||||
stack push $paramstack [stack pop $sid]
|
||||
}
|
||||
} else {
|
||||
for {set i 0} {$i < $num} {incr i} {
|
||||
stack push $paramstack [stack pop $sid]
|
||||
}
|
||||
}
|
||||
|
||||
# Construct the function template and push it back to the
|
||||
# top of the stack given by SID.
|
||||
set result ""
|
||||
set first true
|
||||
while {![stack empty $paramstack]} {
|
||||
set top [stack pop $paramstack]
|
||||
if {$first} {
|
||||
set first false
|
||||
} else {
|
||||
append result ", "
|
||||
}
|
||||
append result $top
|
||||
}
|
||||
|
||||
# Save argument list.
|
||||
set args $result
|
||||
|
||||
# GDB outputs "> >" instead of ">>".
|
||||
if {[string index $top end] == ">"} {
|
||||
append result " "
|
||||
}
|
||||
set result "$name<$result>"
|
||||
if {[string equal $num "all"]} {
|
||||
append result "($args)"
|
||||
}
|
||||
stack push $sid $result
|
||||
stack delete $paramstack
|
||||
}
|
||||
|
||||
# Given the stack SID and the name of a variable of the desired template
|
||||
# parameters, construct the actual template parameter and push it to the
|
||||
# top of the stack.
|
||||
|
||||
proc makearg {sid arglistvar} {
|
||||
upvar $arglistvar arglist
|
||||
|
||||
set c [string index $arglist 0]
|
||||
consume arglist
|
||||
switch $c {
|
||||
A -
|
||||
B {
|
||||
makearg $sid arglist
|
||||
makearg $sid arglist
|
||||
maket $sid $c 2
|
||||
}
|
||||
|
||||
a -
|
||||
b -
|
||||
c -
|
||||
d {
|
||||
makearg $sid arglist
|
||||
maket $sid $c
|
||||
}
|
||||
|
||||
i {
|
||||
stack push $sid "int"
|
||||
}
|
||||
|
||||
n {
|
||||
# These are not templates.
|
||||
set c [string index $arglist 0]
|
||||
stack push $sid "n::n$c"
|
||||
consume arglist
|
||||
}
|
||||
|
||||
N {
|
||||
set c [string index $arglist 0]
|
||||
makearg $sid arglist
|
||||
set top [stack pop $sid]
|
||||
stack push $sid "n::N$top"
|
||||
}
|
||||
|
||||
default { error "unhandled arglist identifier: '$c'" }
|
||||
}
|
||||
}
|
||||
|
||||
# Given ARGLIST, construct a class template for the type and return
|
||||
# it as a string.
|
||||
|
||||
proc maketype {arglist} {
|
||||
set s [Stack::new]
|
||||
makearg $s arglist
|
||||
set result [stack pop $s]
|
||||
stack delete $s
|
||||
return $result
|
||||
}
|
||||
|
||||
# Returns a function template declaration for the function "foo" in the
|
||||
# corresponding test source code. ARGLIST specifies the exact instantiation
|
||||
# that is desired.
|
||||
#
|
||||
# Generically, this procedure returns a string of the form,
|
||||
# "foo<parameter-list> (arg-list)", where ARGLIST describes the parameter(s).
|
||||
#
|
||||
# Valid specifiers for ARGLIST (must be kept in sync with source code):
|
||||
#
|
||||
# i: Creates an "int" type.
|
||||
# a, b, c, d: Creates the struct template of the same name, taking a single
|
||||
# template parameter.
|
||||
# A, B: Creates the struct template of the same name, taking two template
|
||||
# parameters.
|
||||
# na, nb: Creates the non-template structs n::na and n::nb, respectively.
|
||||
# NA, NB: Creates the struct templates n::NA and n::NB, respectively, which
|
||||
# take two template parameters.
|
||||
#
|
||||
# Examples:
|
||||
# makefoo i
|
||||
# --> foo<int> (int)
|
||||
# makefoo ii
|
||||
# --> foo<int, int> (int, int)
|
||||
# makefoo Aiabi
|
||||
# --> foo<A<int, a<b<int> > > > (A<int, a<b<int> > >)
|
||||
# makefoo NANAiaiNBbiabi
|
||||
# --> foo<n::NA<n::NA<int, a<int> >, n::NB<b<int>, a<b<int> > > > >
|
||||
# (n::NA<n::NA<int, a<int> >, n::NB<b<int>, a<b<int> > > >)
|
||||
|
||||
proc makefoo {arglist} {
|
||||
set s [::Stack::new]
|
||||
while {[string length $arglist] > 0} {
|
||||
makearg $s arglist
|
||||
}
|
||||
|
||||
maket $s "foo" all
|
||||
set result [stack pop $s]
|
||||
stack delete $s
|
||||
return $result
|
||||
}
|
||||
|
||||
# Test wrapper for a single "makefoo" unit test.
|
||||
|
||||
proc test_makefoo_1 {arglist expected} {
|
||||
set exp "foo<$expected"
|
||||
if {[string index $exp end] == ">"} {
|
||||
append exp " "
|
||||
}
|
||||
append exp ">"
|
||||
append exp "($expected)"
|
||||
|
||||
set calc [makefoo $arglist]
|
||||
send_log "makefoo $arglist = $calc\n"
|
||||
send_log "expecting: $exp\n"
|
||||
if {[string equal $exp $calc]} {
|
||||
pass "makefoo unit test: $arglist"
|
||||
} else {
|
||||
fail "makefoo unit test: $arglist"
|
||||
}
|
||||
}
|
||||
|
||||
# Test whether the procedure "makefoo" is functioning as expected.
|
||||
|
||||
proc test_makefoo {} {
|
||||
test_makefoo_1 "i" "int"
|
||||
test_makefoo_1 "ai" "a<int>"
|
||||
test_makefoo_1 "aai" "a<a<int> >"
|
||||
test_makefoo_1 "ii" "int, int"
|
||||
test_makefoo_1 "aaibi" "a<a<int> >, b<int>"
|
||||
test_makefoo_1 \
|
||||
"ababiibababai" "a<b<a<b<int> > > >, int, b<a<b<a<b<a<int> > > > > >"
|
||||
test_makefoo_1 "Aii" "A<int, int>"
|
||||
test_makefoo_1 "ABaibibi" "A<B<a<int>, b<int> >, b<int> >"
|
||||
test_makefoo_1 "na" "n::na"
|
||||
test_makefoo_1 "nana" "n::na, n::na"
|
||||
test_makefoo_1 "NAii" "n::NA<int, int>"
|
||||
test_makefoo_1 "NANAiiNAii" "n::NA<n::NA<int, int>, n::NA<int, int> >"
|
||||
}
|
||||
|
||||
#
|
||||
# Tests start here.
|
||||
#
|
||||
|
||||
# Disable the completion limit for the whole testcase.
|
||||
gdb_test_no_output "set max-completions unlimited"
|
||||
|
||||
@@ -377,12 +589,11 @@ proc_with_prefix template-ret-type {} {
|
||||
test_complete_prefix_range $complete_line $start
|
||||
}
|
||||
|
||||
# Setting a breakpoint without the template params doesn't work.
|
||||
check_setting_bp_fails "$cmd_prefix template2_fn"
|
||||
# However, setting a breakpoint with template params and without
|
||||
# the method params does work, just like with non-template
|
||||
# functions. It also works with or without return type.
|
||||
# Setting a breakpoint with or without template params and without
|
||||
# the method params works, just like with non-template functions.
|
||||
# It also works with or without return type.
|
||||
foreach linespec [list \
|
||||
"template2_fn" \
|
||||
"${method_name}" \
|
||||
"${method_name}${param_list}" \
|
||||
"${struct_type}::${method_name}" \
|
||||
@@ -396,6 +607,218 @@ proc_with_prefix template-ret-type {} {
|
||||
}
|
||||
}
|
||||
|
||||
# Test completion of function template foo.
|
||||
|
||||
proc_with_prefix template-function-foo {} {
|
||||
|
||||
foreach cmd_prefix {"b" "b -function"} {
|
||||
# "foo" is ambiguous, this will set many different breakpoints.
|
||||
set completion_list \
|
||||
[list \
|
||||
[makefoo Aabiaai] \
|
||||
[makefoo Aabiabi] \
|
||||
[makefoo Aabicdi] \
|
||||
[makefoo AabicdiAabiaai] \
|
||||
[makefoo AabicdiAabiabi] \
|
||||
[makefoo AabicdiBabicdi] \
|
||||
[makefoo Babicdi] \
|
||||
[makefoo aai] \
|
||||
[makefoo aaiabi] \
|
||||
[makefoo aaicci] \
|
||||
[makefoo aaicdi] \
|
||||
[makefoo abi] \
|
||||
[makefoo anabnb] \
|
||||
[makefoo cci] \
|
||||
[makefoo cdi] \
|
||||
[makefoo NAnanbNBnanb] \
|
||||
[makefoo nanb]]
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo" "<" $completion_list
|
||||
check_bp_locations_match_list "$cmd_prefix foo" $completion_list
|
||||
|
||||
# "foo<" should give the same result, but it should not set any
|
||||
# breakpoints.
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<" "" $completion_list
|
||||
check_setting_bp_fails "$cmd_prefix foo<"
|
||||
|
||||
# "foo<A" should only give completions in COMPLETION_LIST that
|
||||
# start with "A" but should set no breakpoints.
|
||||
set completion_list \
|
||||
[list \
|
||||
[makefoo Aabiaai] \
|
||||
[makefoo Aabiabi] \
|
||||
[makefoo Aabicdi] \
|
||||
[makefoo AabicdiAabiaai] \
|
||||
[makefoo AabicdiAabiabi] \
|
||||
[makefoo AabicdiBabicdi]]
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<A" "<a<b<int> >, " \
|
||||
$completion_list
|
||||
check_setting_bp_fails "$cmd_prefix foo<A"
|
||||
|
||||
# "foo<A>" should give any function with one parameter of any type
|
||||
# of A. While the parameter list in the template should be ignored,
|
||||
# the function's argument list should not be ignored.
|
||||
set completion_list \
|
||||
[list \
|
||||
[makefoo Aabiaai] \
|
||||
[makefoo Aabiabi] \
|
||||
[makefoo Aabicdi]]
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<A>" \
|
||||
"(A<a<b<int> >, " $completion_list
|
||||
check_bp_locations_match_list "$cmd_prefix foo<A>" $completion_list
|
||||
|
||||
# "foo<A," should complete to any function with more than one
|
||||
# parameter where the first parameter is any type of A. Insufficient
|
||||
# location to set breakpoints.
|
||||
set completion_list \
|
||||
[list \
|
||||
[makefoo AabicdiAabiaai] \
|
||||
[makefoo AabicdiAabiabi] \
|
||||
[makefoo AabicdiBabicdi]]
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<A," " " \
|
||||
$completion_list
|
||||
check_setting_bp_fails "$cmd_prefix foo<A,"
|
||||
|
||||
# "foo<A<a<b<int>, a" should give all completions starting with
|
||||
# "Aabia" but it is insufficient to set breakpoints.
|
||||
set completion_list \
|
||||
[list \
|
||||
[makefoo Aabiaai] \
|
||||
[makefoo Aabiabi]]
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<A<a<b<int> >, a" \
|
||||
"<" $completion_list
|
||||
check_setting_bp_fails "$cmd_prefix foo<A<a<b<int> >, a"
|
||||
|
||||
# "foo<A<a<b<int>, a<" should yield the same results as above.
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<A<a<b<int> >, a<" \
|
||||
"" $completion_list
|
||||
check_setting_bp_fails "$cmd_prefix foo<A<a<b<int> >, a<"
|
||||
|
||||
# "foo<A<a<b<int>, a<a" is unique but insufficient to set a
|
||||
# breakpoint. This has an ignored template parameter list, so
|
||||
# the completion will contain an ignored list ("a<a>")
|
||||
test_gdb_complete_unique "$cmd_prefix foo<A<a<b<int> >, a<a" \
|
||||
"$cmd_prefix [makefoo Aabiaai]"
|
||||
check_setting_bp_fails "$cmd_prefix foo<A<b<int> >, a<a"
|
||||
|
||||
# "foo<A<a<b<int>, a<b" is also unique. Same parameter ignoring
|
||||
# happens here, too (except "a<b>").
|
||||
test_gdb_complete_unique "$cmd_prefix foo<A<a<b<int> >, a<b" \
|
||||
"$cmd_prefix [makefoo Aabiabi]"
|
||||
check_setting_bp_fails "$cmd_prefix foo<A<a<b<int> >, a<b"
|
||||
|
||||
# "foo<B" is unique but insufficient to set a breakpoint.
|
||||
test_gdb_complete_unique "$cmd_prefix foo<B" \
|
||||
"$cmd_prefix [makefoo Babicdi]"
|
||||
check_setting_bp_fails "$cmd_prefix foo<B"
|
||||
|
||||
# "foo<B>" yields the same unique result and sets a breakpoint.
|
||||
# Since the input skips the parameter list, so does the completion.
|
||||
test_gdb_complete_unique "$cmd_prefix foo<B>" \
|
||||
"$cmd_prefix foo<B>(B<a<b<int> >, c<d<int> > >)"
|
||||
check_bp_locations_match_list "$cmd_prefix foo<B>" \
|
||||
[list [makefoo Babicdi]]
|
||||
|
||||
# "foo<B," should return no completions and no breakpoints.
|
||||
test_gdb_complete_none "$cmd_prefix foo<B,"
|
||||
check_setting_bp_fails "$cmd_prefix foo<B,"
|
||||
|
||||
# "foo<n::" should yield only the functions starting with
|
||||
# "n" and "N" and no breakpoints.
|
||||
set completion_list \
|
||||
[list \
|
||||
[makefoo NAnanbNBnanb] \
|
||||
[makefoo nanb]]
|
||||
test_gdb_complete_multiple "$cmd_prefix " "foo<n::" "" \
|
||||
$completion_list
|
||||
check_setting_bp_fails "$cmd_prefix foo<n::"
|
||||
|
||||
# "foo<A<a, c> >" is unique and sets a breakpoint.
|
||||
# Multiple template parameter lists are skipped, so GDB will ignore
|
||||
# them in the completion.
|
||||
test_gdb_complete_unique "$cmd_prefix foo<A<a, c> >" \
|
||||
"$cmd_prefix foo<A<a, c> >(A<a<b<int> >, c<d<int> > >)"
|
||||
check_bp_locations_match_list "$cmd_prefix foo<A<a, c> >" \
|
||||
[list [makefoo Aabicdi]]
|
||||
}
|
||||
}
|
||||
|
||||
# Helper for template-class-with-method to build completion lists.
|
||||
|
||||
proc makem {arglist_list} {
|
||||
set completion_list {}
|
||||
foreach arglist $arglist_list {
|
||||
lappend completion_list "[maketype $arglist]::method()"
|
||||
}
|
||||
return $completion_list
|
||||
}
|
||||
|
||||
# Returns a list of elements that look like
|
||||
# void TYPE::method()
|
||||
# where TYPE is derived from each arglist in ARGLIST_LIST.
|
||||
|
||||
proc test_makem_1 {arglist_list expected_list} {
|
||||
set result [makem $arglist_list]
|
||||
send_log "makem $arglist = $result\n"
|
||||
send_log "expecting $expected_list\n"
|
||||
|
||||
# Do list equality via canonical strings.
|
||||
if {[expr {[list {*}$expected_list] eq [list {*}$result]}]} {
|
||||
pass "makem unit test: $arglist"
|
||||
} else {
|
||||
fail "makem unit test: $arglist"
|
||||
}
|
||||
}
|
||||
|
||||
# Unit tests for makem.
|
||||
|
||||
proc test_makem {} {
|
||||
test_makem_1 ai {"a<int>::method()"}
|
||||
test_makem_1 bi {"b<int>::method()"}
|
||||
test_makem_1 {ai bi} {"a<int>::method()" "b<int>::method()"}
|
||||
test_makem_1 {Aaiaai Bbibbi abi cdi} {
|
||||
"A<a<int>, a<a<int> > >::method()"
|
||||
"B<b<int>, b<b<int> > >::method()"
|
||||
"a<b<int> >::method()"
|
||||
"c<d<int> >::method()"
|
||||
}
|
||||
}
|
||||
|
||||
# Test class template containing a (non-templated) method called "method."
|
||||
|
||||
proc_with_prefix template-class-with-method {} {
|
||||
|
||||
foreach {type type_list} \
|
||||
[list \
|
||||
"" {aai abi cci cdi Aabicdi Aabiaai Aabiabi Babicdi} \
|
||||
"a" {aai abi} \
|
||||
"b" {} \
|
||||
"c" {cci cdi} \
|
||||
"A" {Aabicdi Aabiaai Aabiabi} \
|
||||
"B" {Babicdi} \
|
||||
"A<a, a>" {Aabiaai Aabiabi} \
|
||||
"A<a<b>, c>" {Aabicdi}\
|
||||
"A<a, d>" {} \
|
||||
"B<a, a>" {} \
|
||||
"B<a, b>" {} \
|
||||
"B<a, c>" {Babicdi}] \
|
||||
{
|
||||
foreach cmd_prefix {"b" "b -function"} {
|
||||
set c "$cmd_prefix "
|
||||
if {$type != ""} {
|
||||
append c "${type}::"
|
||||
}
|
||||
append c "method"
|
||||
|
||||
if {[llength $type_list] > 0} {
|
||||
test_gdb_complete_unique $c "${c}()"
|
||||
check_bp_locations_match_list $c [makem $type_list]
|
||||
} else {
|
||||
test_gdb_complete_none $c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Test completion of a const-overloaded funtion (const-overload).
|
||||
# Note that "const" appears after the function/method parameters.
|
||||
|
||||
@@ -935,6 +1358,10 @@ proc test_driver {} {
|
||||
overload-3
|
||||
template-overload
|
||||
template-ret-type
|
||||
#test_makefoo
|
||||
template-function-foo
|
||||
#test_makem
|
||||
template-class-with-method
|
||||
const-overload
|
||||
const-overload-quoted
|
||||
append-end-quote-char-when-unambiguous
|
||||
|
||||
@@ -240,20 +240,6 @@ proc test_operator_ambiguous {class_name opn cls} {
|
||||
test_gdb_complete_multiple \
|
||||
"$cmd_prefix " "$linespec_noparams" "" $location_list
|
||||
|
||||
# Setting the breakpoint doesn't create a breakpoint location
|
||||
# for the template, because immediately after
|
||||
# "operator()/operator[]" we have the template parameters, not
|
||||
# the parameter list.
|
||||
set location_list \
|
||||
[list \
|
||||
"${class_name}::operator${opn}${cls}(int)" \
|
||||
"${class_name}::operator${opn}${cls}(long)"]
|
||||
if {$opn == "("} {
|
||||
set location_list \
|
||||
[concat \
|
||||
[list "${class_name}::operator${opn}${cls}()"] \
|
||||
$location_list]
|
||||
}
|
||||
check_bp_locations_match_list "$cmd_prefix $linespec_noparams" \
|
||||
$location_list
|
||||
check_bp_locations_match_list "$cmd_prefix $linespec_noparams<int>" \
|
||||
@@ -261,26 +247,33 @@ proc test_operator_ambiguous {class_name opn cls} {
|
||||
|
||||
# Test the template version. Test both with and without
|
||||
# return type.
|
||||
test_gdb_complete_unique \
|
||||
"$cmd_prefix ${class_name}::operator${opn}${cls}<int>(in" \
|
||||
"$cmd_prefix ${class_name}::operator${opn}${cls}<int>(int*)"
|
||||
check_bp_locations_match_list \
|
||||
"$cmd_prefix ${class_name}::operator${opn}${cls}<int>(int*)" \
|
||||
[list "${class_name}::operator${opn}${cls}<int>(int*)"]
|
||||
test_gdb_complete_unique \
|
||||
"$cmd_prefix void ${class_name}::operator${opn}${cls}<int>(in" \
|
||||
"$cmd_prefix void ${class_name}::operator${opn}${cls}<int>(int*)"
|
||||
check_bp_locations_match_list \
|
||||
"$cmd_prefix void ${class_name}::operator${opn}${cls}<int>(int*)" \
|
||||
[list "${class_name}::operator${opn}${cls}<int>(int*)"]
|
||||
set f "${class_name}::operator"
|
||||
foreach ws1 {"" " "} {
|
||||
foreach ws2 {"" " "} {
|
||||
foreach ws3 {"" " "} {
|
||||
test_gdb_complete_unique \
|
||||
"$cmd_prefix ${f}${opn}${ws1}${cls}<${ws2}int${ws3}>(in" \
|
||||
"$cmd_prefix ${f}${opn}${ws1}${cls}<${ws2}int${ws3}>(int*)"
|
||||
check_bp_locations_match_list \
|
||||
"$cmd_prefix ${f}${opn}${ws1}${cls}<${ws2}int${ws3}>(int*)" \
|
||||
[list "${f}${opn}${cls}<int>(int*)"]
|
||||
test_gdb_complete_unique \
|
||||
"$cmd_prefix void ${f}${opn}${ws1}${cls}<${ws2}int${ws3}>(in" \
|
||||
"$cmd_prefix void ${f}${opn}${ws1}${cls}<${ws2}int${ws3}>(int*)"
|
||||
check_bp_locations_match_list \
|
||||
"$cmd_prefix void ${f}${opn}${ws1}${cls}<${ws2}int${ws3}>(int*)" \
|
||||
[list "${f}${opn}${cls}<int>(int*)"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Add extra spaces.
|
||||
test_gdb_complete_unique \
|
||||
"$cmd_prefix ${class_name}::operator ${opn} ${cls} ( in" \
|
||||
"$cmd_prefix ${class_name}::operator ${opn} ${cls} ( int)"
|
||||
"$cmd_prefix ${class_name}::operator ${opn} ${cls} ( lo" \
|
||||
"$cmd_prefix ${class_name}::operator ${opn} ${cls} ( long)"
|
||||
check_bp_locations_match_list \
|
||||
"$cmd_prefix ${class_name}::operator ${opn} ${cls} ( int )" \
|
||||
[list "${class_name}::operator${opn}${cls}(int)"]
|
||||
"$cmd_prefix ${class_name}::operator ${opn} ${cls} ( long )" \
|
||||
[list "${class_name}::operator${opn}${cls}(long)"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace ns_overload3_test
|
||||
}
|
||||
}
|
||||
|
||||
/* Code for the template-overload tests. */
|
||||
/* Code for the template-function_foo (template parameter completion) tests. */
|
||||
|
||||
template <typename T>
|
||||
struct template_struct
|
||||
@@ -163,6 +163,113 @@ T template_struct<T>::template_overload_fn (T t)
|
||||
template_struct<int> template_struct_int;
|
||||
template_struct<long> template_struct_long;
|
||||
|
||||
/* Code for the template-parameter-overload test. */
|
||||
|
||||
template <typename T>
|
||||
void foo (T c) {}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
void foo (T1 a, T2 b) {}
|
||||
|
||||
template <typename T>
|
||||
struct a
|
||||
{
|
||||
void method () {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct b
|
||||
{
|
||||
void method () {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct c
|
||||
{
|
||||
void method () {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct d
|
||||
{
|
||||
void method () {};
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct A
|
||||
{
|
||||
void method () {}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct B
|
||||
{
|
||||
void method () {}
|
||||
};
|
||||
|
||||
namespace n
|
||||
{
|
||||
struct na {};
|
||||
struct nb {};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct NA {};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct NB {};
|
||||
};
|
||||
|
||||
static void
|
||||
template_function_foo ()
|
||||
{
|
||||
a<a<int>> aa;
|
||||
aa.method ();
|
||||
a<b<int>> ab;
|
||||
ab.method ();
|
||||
c<c<int>> cc;
|
||||
cc.method ();
|
||||
c<d<int>> cd;
|
||||
cd.method ();
|
||||
foo (aa);
|
||||
foo (ab);
|
||||
foo (cc);
|
||||
foo (cd);
|
||||
foo (aa, ab);
|
||||
foo (aa, cc);
|
||||
foo (aa, cd);
|
||||
|
||||
A<a<b<int>>, c<d<int>>> Aabcd;
|
||||
Aabcd.method ();
|
||||
foo (Aabcd);
|
||||
|
||||
A<a<b<int>>, a<a<int>>> Aabaa;
|
||||
Aabaa.method ();
|
||||
foo (Aabaa);
|
||||
|
||||
A<a<b<int>>, a<b<int>>> Aabab;
|
||||
Aabab.method ();
|
||||
foo (Aabab);
|
||||
|
||||
B<a<b<int>>, c<d<int>>> Babcd;
|
||||
Babcd.method ();
|
||||
foo (Babcd);
|
||||
|
||||
foo (Aabcd, Babcd);
|
||||
foo (Aabcd, Aabaa);
|
||||
foo (Aabcd, Aabab);
|
||||
|
||||
n::na na;
|
||||
n::nb nb;
|
||||
foo (na, nb);
|
||||
a<n::na> ana;
|
||||
b<n::nb> bnb;
|
||||
foo (ana, bnb);
|
||||
|
||||
n::NA<n::na, n::nb> NAnanb;
|
||||
n::NB<n::na, n::nb> Nbnanb;
|
||||
foo (NAnanb, Nbnanb);
|
||||
}
|
||||
|
||||
/* Code for the template2-ret-type tests. */
|
||||
|
||||
template <typename T>
|
||||
@@ -381,6 +488,7 @@ main ()
|
||||
template2_struct_inst.template2_fn<int, int> ();
|
||||
template_struct_int.template_overload_fn(0);
|
||||
template_struct_long.template_overload_fn(0);
|
||||
template_function_foo ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
156
gdb/utils.c
156
gdb/utils.c
@@ -2271,13 +2271,45 @@ skip_abi_tag (const char **name)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If *NAME points at a template parameter list, skip it and return true.
|
||||
Otherwise do nothing and return false. */
|
||||
|
||||
static bool
|
||||
skip_template_parameter_list (const char **name)
|
||||
{
|
||||
const char *p = *name;
|
||||
|
||||
if (*p == '<')
|
||||
{
|
||||
const char *template_param_list_end = find_toplevel_char (p + 1, '>');
|
||||
|
||||
if (template_param_list_end == NULL)
|
||||
return false;
|
||||
|
||||
p = template_param_list_end + 1;
|
||||
|
||||
/* Skip any whitespace that might occur after the closing of the
|
||||
parameter list, but only if it is the end of parameter list. */
|
||||
const char *q = p;
|
||||
while (isspace (*q))
|
||||
++q;
|
||||
if (*q == '>')
|
||||
p = q;
|
||||
*name = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See utils.h. */
|
||||
|
||||
int
|
||||
strncmp_iw_with_mode (const char *string1, const char *string2,
|
||||
size_t string2_len, strncmp_iw_mode mode,
|
||||
enum language language,
|
||||
completion_match_for_lcd *match_for_lcd)
|
||||
completion_match_for_lcd *match_for_lcd,
|
||||
bool ignore_template_params)
|
||||
{
|
||||
const char *string1_start = string1;
|
||||
const char *end_str2 = string2 + string2_len;
|
||||
@@ -2327,6 +2359,48 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
|
||||
string1++;
|
||||
}
|
||||
|
||||
/* Skip template parameters in STRING1 if STRING2 does not contain
|
||||
any. E.g.:
|
||||
|
||||
Case 1: User is looking for all functions named "foo".
|
||||
string1: foo <...> (...)
|
||||
string2: foo
|
||||
|
||||
Case 2: User is looking for all methods named "foo" in all template
|
||||
class instantiations.
|
||||
string1: Foo<...>::foo <...> (...)
|
||||
string2: Foo::foo (...)
|
||||
|
||||
Case 3: User is looking for a specific overload of a template
|
||||
function or method.
|
||||
string1: foo<...>
|
||||
string2: foo(...)
|
||||
|
||||
Case 4: User is looking for a specific overload of a specific
|
||||
template instantiation.
|
||||
string1: foo<A> (...)
|
||||
string2: foo<B> (...)
|
||||
|
||||
Case 5: User is looking wild parameter match.
|
||||
string1: foo<A<a<b<...> > > > (...)
|
||||
string2: foo<A
|
||||
*/
|
||||
if (language == language_cplus && ignore_template_params
|
||||
&& *string1 == '<' && *string2 != '<')
|
||||
{
|
||||
/* Skip any parameter list in STRING1. */
|
||||
const char *template_start = string1;
|
||||
|
||||
if (skip_template_parameter_list (&string1))
|
||||
{
|
||||
/* Don't mark the parameter list ignored if the user didn't
|
||||
try to ignore it. [Case #5 above] */
|
||||
if (*string2 != '\0'
|
||||
&& match_for_lcd != NULL && template_start != string1)
|
||||
match_for_lcd->mark_ignored_range (template_start, string1);
|
||||
}
|
||||
}
|
||||
|
||||
if (*string1 == '\0' || string2 == end_str2)
|
||||
break;
|
||||
|
||||
@@ -2435,6 +2509,12 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
|
||||
break;
|
||||
if (*string1 == '(' || *string2 == '(')
|
||||
break;
|
||||
|
||||
/* If STRING1 or STRING2 starts with a template
|
||||
parameter list, break out of operator processing. */
|
||||
skip_ws (string1, string2, end_str2);
|
||||
if (*string1 == '<' || *string2 == '<')
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -3431,6 +3511,80 @@ strip_leading_path_elements (const char *path, int n)
|
||||
return p;
|
||||
}
|
||||
|
||||
/* See description in utils.h. */
|
||||
|
||||
const char *
|
||||
find_toplevel_char (const char *s, char c)
|
||||
{
|
||||
int quoted = 0; /* zero if we're not in quotes;
|
||||
'"' if we're in a double-quoted string;
|
||||
'\'' if we're in a single-quoted string. */
|
||||
int depth = 0; /* Number of unclosed parens we've seen. */
|
||||
const char *scan;
|
||||
|
||||
for (scan = s; *scan; scan++)
|
||||
{
|
||||
if (quoted)
|
||||
{
|
||||
if (*scan == quoted)
|
||||
quoted = 0;
|
||||
else if (*scan == '\\' && *(scan + 1))
|
||||
scan++;
|
||||
}
|
||||
else if (*scan == c && ! quoted && depth == 0)
|
||||
return scan;
|
||||
else if (*scan == '"' || *scan == '\'')
|
||||
quoted = *scan;
|
||||
else if (*scan == '(' || *scan == '<')
|
||||
depth++;
|
||||
else if ((*scan == ')' || *scan == '>') && depth > 0)
|
||||
depth--;
|
||||
else if (*scan == 'o' && !quoted && depth == 0)
|
||||
{
|
||||
/* Handle C++ operator names. */
|
||||
if (strncmp (scan, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0)
|
||||
{
|
||||
scan += CP_OPERATOR_LEN;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
while (isspace (*scan))
|
||||
{
|
||||
++scan;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
}
|
||||
if (*scan == '\0')
|
||||
break;
|
||||
|
||||
switch (*scan)
|
||||
{
|
||||
/* Skip over one less than the appropriate number of
|
||||
characters: the for loop will skip over the last
|
||||
one. */
|
||||
case '<':
|
||||
if (scan[1] == '<')
|
||||
{
|
||||
scan++;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (scan[1] == '>')
|
||||
{
|
||||
scan++;
|
||||
if (*scan == c)
|
||||
return scan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_utils (void)
|
||||
{
|
||||
|
||||
14
gdb/utils.h
14
gdb/utils.h
@@ -57,11 +57,14 @@ enum class strncmp_iw_mode
|
||||
|
||||
MATCH_FOR_LCD is passed down so that the function can mark parts of
|
||||
the symbol name as ignored for completion matching purposes (e.g.,
|
||||
to handle abi tags). */
|
||||
to handle abi tags). If IGNORE_TEMPLATE_PARAMS is true, all template
|
||||
parameter lists will be ignored when language is C++. */
|
||||
|
||||
extern int strncmp_iw_with_mode
|
||||
(const char *string1, const char *string2, size_t string2_len,
|
||||
strncmp_iw_mode mode, enum language language,
|
||||
completion_match_for_lcd *match_for_lcd = NULL);
|
||||
completion_match_for_lcd *match_for_lcd = NULL,
|
||||
bool ignore_template_params = false);
|
||||
|
||||
/* Do a strncmp() type operation on STRING1 and STRING2, ignoring any
|
||||
differences in whitespace. STRING2_LEN is STRING2's length.
|
||||
@@ -559,4 +562,11 @@ extern void dump_core (void);
|
||||
|
||||
extern char *make_hex_string (const gdb_byte *data, size_t length);
|
||||
|
||||
/* Find an instance of the character C in the string S that is outside
|
||||
of all parenthesis pairs, single-quoted strings, and double-quoted
|
||||
strings. Also, ignore the char within a template name, like a ','
|
||||
within foo<int, int>. */
|
||||
|
||||
extern const char *find_toplevel_char (const char *s, char c);
|
||||
|
||||
#endif /* UTILS_H */
|
||||
|
||||
Reference in New Issue
Block a user