2015-07-22 21:30:57 +08:00
|
|
|
/* Code dealing with "using" directives for GDB.
|
2023-01-01 20:49:04 +08:00
|
|
|
Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
2015-07-22 21:30:57 +08:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
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/>. */
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
#include "namespace.h"
|
gdb/c++: validate 'using' directives based on the current line
When asking GDB to print a variable from an imported namespace, we only
want to see variables imported in lines that the inferior has already
gone through, as is being tested last in gdb.cp/nsusing.exp. However
with the proposed change to gdb.cp/nsusing.exp, we get the following
failures:
(gdb) PASS: gdb.cp/nsusing.exp: continue to breakpoint: marker10 stop
print x
$9 = 911
(gdb) FAIL: gdb.cp/nsusing.exp: print x, before using statement
next
15 y += x;
(gdb) PASS: gdb.cp/nsusing.exp: using namespace M
print x
$10 = 911
(gdb) PASS: gdb.cp/nsusing.exp: print x, only using M
Showing that the feature wasn't functioning properly, it just so
happened that gcc ordered the namespaces in a convenient way.
This happens because GDB doesn't take into account the line where the
"using namespace" directive is written. So long as it shows up in the
current scope, we assume it is valid.
To fix this, add a new member to struct using_direct, that stores the
line where the directive was written, and a new function that informs if
the using directive is valid already.
Unfortunately, due to a GCC bug, the failure still shows up. Compilers
that set the declaration line of the using directive correctly (such as
Clang) do not show such a bug, so the test includes an XFAIL for gcc
code.
Finally, because the final test of gdb.cp/nsusing.exp has turned into
multiple that all would need XFAILs for older GCCs (<= 4.3), and that
GCC is very old, if it is detected, the test just exits early.
Approved-by: Tom Tromey <tom@tromey.com>
2022-10-19 22:57:44 +08:00
|
|
|
#include "frame.h"
|
2022-12-14 11:34:31 +08:00
|
|
|
#include "symtab.h"
|
2015-07-22 21:30:57 +08:00
|
|
|
|
|
|
|
/* Add a using directive to USING_DIRECTIVES. If the using directive
|
|
|
|
in question has already been added, don't add it twice.
|
|
|
|
|
|
|
|
Create a new struct using_direct which imports the namespace SRC
|
|
|
|
into the scope DEST. ALIAS is the name of the imported namespace
|
|
|
|
in the current scope. If ALIAS is NULL then the namespace is known
|
|
|
|
by its original name. DECLARATION is the name if the imported
|
2019-10-18 08:48:08 +08:00
|
|
|
variable if this is a declaration import (Eg. using A::x), otherwise
|
2015-07-22 21:30:57 +08:00
|
|
|
it is NULL. EXCLUDES is a list of names not to import from an
|
|
|
|
imported module or NULL. If COPY_NAMES is non-zero, then the
|
|
|
|
arguments are copied into newly allocated memory so they can be
|
2019-10-07 23:45:24 +08:00
|
|
|
temporaries. For EXCLUDES the contents of the vector are copied,
|
|
|
|
but the pointed to characters are not copied. */
|
2015-07-22 21:30:57 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
add_using_directive (struct using_direct **using_directives,
|
|
|
|
const char *dest,
|
|
|
|
const char *src,
|
|
|
|
const char *alias,
|
|
|
|
const char *declaration,
|
2017-09-07 07:18:23 +08:00
|
|
|
const std::vector<const char *> &excludes,
|
gdb/c++: validate 'using' directives based on the current line
When asking GDB to print a variable from an imported namespace, we only
want to see variables imported in lines that the inferior has already
gone through, as is being tested last in gdb.cp/nsusing.exp. However
with the proposed change to gdb.cp/nsusing.exp, we get the following
failures:
(gdb) PASS: gdb.cp/nsusing.exp: continue to breakpoint: marker10 stop
print x
$9 = 911
(gdb) FAIL: gdb.cp/nsusing.exp: print x, before using statement
next
15 y += x;
(gdb) PASS: gdb.cp/nsusing.exp: using namespace M
print x
$10 = 911
(gdb) PASS: gdb.cp/nsusing.exp: print x, only using M
Showing that the feature wasn't functioning properly, it just so
happened that gcc ordered the namespaces in a convenient way.
This happens because GDB doesn't take into account the line where the
"using namespace" directive is written. So long as it shows up in the
current scope, we assume it is valid.
To fix this, add a new member to struct using_direct, that stores the
line where the directive was written, and a new function that informs if
the using directive is valid already.
Unfortunately, due to a GCC bug, the failure still shows up. Compilers
that set the declaration line of the using directive correctly (such as
Clang) do not show such a bug, so the test includes an XFAIL for gcc
code.
Finally, because the final test of gdb.cp/nsusing.exp has turned into
multiple that all would need XFAILs for older GCCs (<= 4.3), and that
GCC is very old, if it is detected, the test just exits early.
Approved-by: Tom Tromey <tom@tromey.com>
2022-10-19 22:57:44 +08:00
|
|
|
unsigned int decl_line,
|
2015-07-22 21:30:57 +08:00
|
|
|
int copy_names,
|
|
|
|
struct obstack *obstack)
|
|
|
|
{
|
|
|
|
struct using_direct *current;
|
|
|
|
struct using_direct *newobj;
|
2015-09-26 02:08:06 +08:00
|
|
|
int alloc_len;
|
2015-07-22 21:30:57 +08:00
|
|
|
|
|
|
|
/* Has it already been added? */
|
|
|
|
|
|
|
|
for (current = *using_directives; current != NULL; current = current->next)
|
|
|
|
{
|
|
|
|
int ix;
|
|
|
|
|
|
|
|
if (strcmp (current->import_src, src) != 0)
|
|
|
|
continue;
|
|
|
|
if (strcmp (current->import_dest, dest) != 0)
|
|
|
|
continue;
|
|
|
|
if ((alias == NULL && current->alias != NULL)
|
|
|
|
|| (alias != NULL && current->alias == NULL)
|
|
|
|
|| (alias != NULL && current->alias != NULL
|
|
|
|
&& strcmp (alias, current->alias) != 0))
|
|
|
|
continue;
|
|
|
|
if ((declaration == NULL && current->declaration != NULL)
|
|
|
|
|| (declaration != NULL && current->declaration == NULL)
|
|
|
|
|| (declaration != NULL && current->declaration != NULL
|
|
|
|
&& strcmp (declaration, current->declaration) != 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Compare the contents of EXCLUDES. */
|
2017-09-07 07:18:23 +08:00
|
|
|
for (ix = 0; ix < excludes.size (); ++ix)
|
2015-07-22 21:30:57 +08:00
|
|
|
if (current->excludes[ix] == NULL
|
2017-09-07 07:18:23 +08:00
|
|
|
|| strcmp (excludes[ix], current->excludes[ix]) != 0)
|
2015-07-22 21:30:57 +08:00
|
|
|
break;
|
2017-09-07 07:18:23 +08:00
|
|
|
if (ix < excludes.size () || current->excludes[ix] != NULL)
|
2015-07-22 21:30:57 +08:00
|
|
|
continue;
|
|
|
|
|
gdb/c++: validate 'using' directives based on the current line
When asking GDB to print a variable from an imported namespace, we only
want to see variables imported in lines that the inferior has already
gone through, as is being tested last in gdb.cp/nsusing.exp. However
with the proposed change to gdb.cp/nsusing.exp, we get the following
failures:
(gdb) PASS: gdb.cp/nsusing.exp: continue to breakpoint: marker10 stop
print x
$9 = 911
(gdb) FAIL: gdb.cp/nsusing.exp: print x, before using statement
next
15 y += x;
(gdb) PASS: gdb.cp/nsusing.exp: using namespace M
print x
$10 = 911
(gdb) PASS: gdb.cp/nsusing.exp: print x, only using M
Showing that the feature wasn't functioning properly, it just so
happened that gcc ordered the namespaces in a convenient way.
This happens because GDB doesn't take into account the line where the
"using namespace" directive is written. So long as it shows up in the
current scope, we assume it is valid.
To fix this, add a new member to struct using_direct, that stores the
line where the directive was written, and a new function that informs if
the using directive is valid already.
Unfortunately, due to a GCC bug, the failure still shows up. Compilers
that set the declaration line of the using directive correctly (such as
Clang) do not show such a bug, so the test includes an XFAIL for gcc
code.
Finally, because the final test of gdb.cp/nsusing.exp has turned into
multiple that all would need XFAILs for older GCCs (<= 4.3), and that
GCC is very old, if it is detected, the test just exits early.
Approved-by: Tom Tromey <tom@tromey.com>
2022-10-19 22:57:44 +08:00
|
|
|
if (decl_line != current->decl_line)
|
|
|
|
continue;
|
|
|
|
|
2015-07-22 21:30:57 +08:00
|
|
|
/* Parameters exactly match CURRENT. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-26 02:08:06 +08:00
|
|
|
alloc_len = (sizeof(*newobj)
|
2017-09-07 07:18:23 +08:00
|
|
|
+ (excludes.size () * sizeof(*newobj->excludes)));
|
2015-09-26 02:08:06 +08:00
|
|
|
newobj = (struct using_direct *) obstack_alloc (obstack, alloc_len);
|
2015-07-22 21:30:57 +08:00
|
|
|
memset (newobj, 0, sizeof (*newobj));
|
|
|
|
|
|
|
|
if (copy_names)
|
|
|
|
{
|
2019-05-19 05:56:03 +08:00
|
|
|
newobj->import_src = obstack_strdup (obstack, src);
|
|
|
|
newobj->import_dest = obstack_strdup (obstack, dest);
|
2015-07-22 21:30:57 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newobj->import_src = src;
|
|
|
|
newobj->import_dest = dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alias != NULL && copy_names)
|
2019-05-19 05:56:03 +08:00
|
|
|
newobj->alias = obstack_strdup (obstack, alias);
|
2015-07-22 21:30:57 +08:00
|
|
|
else
|
|
|
|
newobj->alias = alias;
|
|
|
|
|
|
|
|
if (declaration != NULL && copy_names)
|
2019-05-19 05:56:03 +08:00
|
|
|
newobj->declaration = obstack_strdup (obstack, declaration);
|
2015-07-22 21:30:57 +08:00
|
|
|
else
|
|
|
|
newobj->declaration = declaration;
|
|
|
|
|
2018-07-27 07:48:40 +08:00
|
|
|
if (!excludes.empty ())
|
|
|
|
memcpy (newobj->excludes, excludes.data (),
|
|
|
|
excludes.size () * sizeof (*newobj->excludes));
|
2017-09-07 07:18:23 +08:00
|
|
|
newobj->excludes[excludes.size ()] = NULL;
|
2015-07-22 21:30:57 +08:00
|
|
|
|
gdb/c++: validate 'using' directives based on the current line
When asking GDB to print a variable from an imported namespace, we only
want to see variables imported in lines that the inferior has already
gone through, as is being tested last in gdb.cp/nsusing.exp. However
with the proposed change to gdb.cp/nsusing.exp, we get the following
failures:
(gdb) PASS: gdb.cp/nsusing.exp: continue to breakpoint: marker10 stop
print x
$9 = 911
(gdb) FAIL: gdb.cp/nsusing.exp: print x, before using statement
next
15 y += x;
(gdb) PASS: gdb.cp/nsusing.exp: using namespace M
print x
$10 = 911
(gdb) PASS: gdb.cp/nsusing.exp: print x, only using M
Showing that the feature wasn't functioning properly, it just so
happened that gcc ordered the namespaces in a convenient way.
This happens because GDB doesn't take into account the line where the
"using namespace" directive is written. So long as it shows up in the
current scope, we assume it is valid.
To fix this, add a new member to struct using_direct, that stores the
line where the directive was written, and a new function that informs if
the using directive is valid already.
Unfortunately, due to a GCC bug, the failure still shows up. Compilers
that set the declaration line of the using directive correctly (such as
Clang) do not show such a bug, so the test includes an XFAIL for gcc
code.
Finally, because the final test of gdb.cp/nsusing.exp has turned into
multiple that all would need XFAILs for older GCCs (<= 4.3), and that
GCC is very old, if it is detected, the test just exits early.
Approved-by: Tom Tromey <tom@tromey.com>
2022-10-19 22:57:44 +08:00
|
|
|
newobj->decl_line = decl_line;
|
|
|
|
|
2015-07-22 21:30:57 +08:00
|
|
|
newobj->next = *using_directives;
|
|
|
|
*using_directives = newobj;
|
|
|
|
}
|
gdb/c++: validate 'using' directives based on the current line
When asking GDB to print a variable from an imported namespace, we only
want to see variables imported in lines that the inferior has already
gone through, as is being tested last in gdb.cp/nsusing.exp. However
with the proposed change to gdb.cp/nsusing.exp, we get the following
failures:
(gdb) PASS: gdb.cp/nsusing.exp: continue to breakpoint: marker10 stop
print x
$9 = 911
(gdb) FAIL: gdb.cp/nsusing.exp: print x, before using statement
next
15 y += x;
(gdb) PASS: gdb.cp/nsusing.exp: using namespace M
print x
$10 = 911
(gdb) PASS: gdb.cp/nsusing.exp: print x, only using M
Showing that the feature wasn't functioning properly, it just so
happened that gcc ordered the namespaces in a convenient way.
This happens because GDB doesn't take into account the line where the
"using namespace" directive is written. So long as it shows up in the
current scope, we assume it is valid.
To fix this, add a new member to struct using_direct, that stores the
line where the directive was written, and a new function that informs if
the using directive is valid already.
Unfortunately, due to a GCC bug, the failure still shows up. Compilers
that set the declaration line of the using directive correctly (such as
Clang) do not show such a bug, so the test includes an XFAIL for gcc
code.
Finally, because the final test of gdb.cp/nsusing.exp has turned into
multiple that all would need XFAILs for older GCCs (<= 4.3), and that
GCC is very old, if it is detected, the test just exits early.
Approved-by: Tom Tromey <tom@tromey.com>
2022-10-19 22:57:44 +08:00
|
|
|
|
|
|
|
/* See namespace.h. */
|
|
|
|
|
|
|
|
bool
|
|
|
|
using_direct::valid_line (unsigned int boundary) const
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
CORE_ADDR curr_pc = get_frame_pc (get_selected_frame (nullptr));
|
|
|
|
symtab_and_line curr_sal = find_pc_line (curr_pc, 0);
|
|
|
|
return (decl_line <= curr_sal.line)
|
|
|
|
|| (decl_line >= boundary);
|
|
|
|
}
|
|
|
|
catch (const gdb_exception &ex)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|