Age | Commit message (Collapse) | Author | Files | Lines |
|
Currently a reinterpret_cast may change the pointer value if
multiple inheritance is involved:
```
(gdb) p r
$1 = (Right *) 0x22f75c
(gdb) p reinterpret_cast<LeftRight*>(r)
$2 = (LeftRight *) 0x22f758
```
It's because value_cast is called in this case, which automatically
does up- and downcasting.
Fixed by simply using the target pointer type in a copy of the
original value:
```
(gdb) p r
$1 = (Right *) 0x3bf87c
(gdb) p reinterpret_cast<LeftRight*>(r)
$2 = (LeftRight *) 0x3bf87c
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18861
Approved-By: Tom Tromey <tom@tromey.com>
|
|
PR29011 notes that dynamic_cast does not work correctly if
classes with virtual methods are involved, some of the results
wrongly point into the vtable of the derived class:
```
(gdb) p vlr
$1 = (VirtualLeftRight *) 0x162240
(gdb) p vl
$2 = (VirtualLeft *) 0x162240
(gdb) p vr
$3 = (VirtualRight *) 0x162250
(gdb) p dynamic_cast<VirtualLeftRight*>(vlr)
$4 = (VirtualLeftRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16>
(gdb) p dynamic_cast<VirtualLeftRight*>(vl)
$5 = (VirtualLeftRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16>
(gdb) p dynamic_cast<VirtualLeftRight*>(vr)
$6 = (VirtualLeftRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16>
(gdb) p dynamic_cast<VirtualLeft*>(vlr)
$7 = (VirtualLeft *) 0x162240
(gdb) p dynamic_cast<VirtualLeft*>(vl)
$8 = (VirtualLeft *) 0x13fab89b0 <vtable for VirtualLeftRight+16>
(gdb) p dynamic_cast<VirtualLeft*>(vr)
$9 = (VirtualLeft *) 0x162240
(gdb) p dynamic_cast<VirtualRight*>(vlr)
$10 = (VirtualRight *) 0x162250
(gdb) p dynamic_cast<VirtualRight*>(vl)
$11 = (VirtualRight *) 0x162250
(gdb) p dynamic_cast<VirtualRight*>(vr)
$12 = (VirtualRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16>
```
For the cases where the dynamic_cast type is the same as the
original type, it used the ARG value for the result, which in
case of pointer types was already the dereferenced value.
And the TEM value at the value address was created with the
pointer/reference type, not the actual class type.
With these fixed, the dynamic_cast results make more sense:
```
(gdb) p vlr
$1 = (VirtualLeftRight *) 0x692240
(gdb) p vl
$2 = (VirtualLeft *) 0x692240
(gdb) p vr
$3 = (VirtualRight *) 0x692250
(gdb) p dynamic_cast<VirtualLeftRight*>(vlr)
$4 = (VirtualLeftRight *) 0x692240
(gdb) p dynamic_cast<VirtualLeftRight*>(vl)
$5 = (VirtualLeftRight *) 0x692240
(gdb) p dynamic_cast<VirtualLeftRight*>(vr)
$6 = (VirtualLeftRight *) 0x692240
(gdb) p dynamic_cast<VirtualLeft*>(vlr)
$7 = (VirtualLeft *) 0x692240
(gdb) p dynamic_cast<VirtualLeft*>(vl)
$8 = (VirtualLeft *) 0x692240
(gdb) p dynamic_cast<VirtualLeft*>(vr)
$9 = (VirtualLeft *) 0x692240
(gdb) p dynamic_cast<VirtualRight*>(vlr)
$10 = (VirtualRight *) 0x692250
(gdb) p dynamic_cast<VirtualRight*>(vl)
$11 = (VirtualRight *) 0x692250
(gdb) p dynamic_cast<VirtualRight*>(vr)
$12 = (VirtualRight *) 0x692250
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29011
Approved-By: Tom Tromey <tom@tromey.com>
|
|
When running test-case gdb.cp/casts.exp with target board unix/-m32, I run
into:
...
(gdb) print (unsigned long long) &gd == gd_value^M
$31 = false^M
(gdb) FAIL: gdb.cp/casts.exp: print (unsigned long long) &gd == gd_value
...
With some additional printing, we can see in more detail why the comparison
fails:
...
(gdb) print /x &gd^M
$31 = 0xffffc5c8^M
(gdb) PASS: gdb.cp/casts.exp: print /x &gd
print /x (unsigned long long)&gd^M
$32 = 0xffffc5c8^M
(gdb) PASS: gdb.cp/casts.exp: print /x (unsigned long long)&gd
print /x gd_value^M
$33 = 0xffffffffffffc5c8^M
(gdb) PASS: gdb.cp/casts.exp: print /x gd_value
print (unsigned long long) &gd == gd_value^M
$34 = false^M
(gdb) FAIL: gdb.cp/casts.exp: print (unsigned long long) &gd == gd_value
...
The gd_value is set by this assignment:
...
unsigned long long gd_value = (unsigned long long) &gd;
...
The problem here is directly casting from a pointer to a non-pointer-sized
integer.
Fix this by adding an intermediate cast to std::uintptr_t.
Tested on x86_64-linux with native and target board unix/-m32.
|
|
PR c++/28907 points out that casting from a derived class to a base
class fails in some situations. The problem turned out to be a
missing use of value_embedded_offset. One peculiarity here is that,
if you managed to construct a pointer-to-derived with an embedded
offset of 0, the cast would work -- for example, one of the two new
tests here passes without the patch.
This embedded offset stuff is an endless source of bugs. I wonder if
it's possible to get rid of it somehow.
Regression tested on x86-64 Fedora 34.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28907
|
|
gcc-6.2.1-1.fc26.x86_64
gdb compile failed, /home/jkratoch/redhat/gdb-clean/gdb/testsuite/gdb.cp/casts.cc:40:10: error: expected primary-expression before 'int'
decltype(int x)
^~~
/home/jkratoch/redhat/gdb-clean/gdb/testsuite/gdb.cp/casts.cc:40:10: error: expected ')' before 'int'
/home/jkratoch/redhat/gdb-clean/gdb/testsuite/gdb.cp/casts.cc:40:1: error: expected unqualified-id before 'decltype'
decltype(int x)
^~~~~~~~
/home/jkratoch/redhat/gdb-clean/gdb/testsuite/gdb.cp/casts.cc: In function 'int main(int, char**)':
/home/jkratoch/redhat/gdb-clean/gdb/testsuite/gdb.cp/casts.cc:59:14: error: expected primary-expression before 'decltype'
double y = decltype(2);
^~~~~~~~
'decltype' is a registered keyword since C++11 which is now a default for GCC.
On Thu, 15 Sep 2016 14:06:56 +0200, Pedro Alves wrote:
Seems to be exercising the FLAG_SHADOW bits:
...
{"__typeof__", TYPEOF, OP_TYPEOF, 0 },
{"__typeof", TYPEOF, OP_TYPEOF, 0 },
{"typeof", TYPEOF, OP_TYPEOF, FLAG_SHADOW },
{"__decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX },
{"decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX | FLAG_SHADOW },
...
/* This is used to associate some attributes with a token. */
enum token_flag
{
...
/* If this bit is set, the token is conditional: if there is a
symbol of the same name, then the token is a symbol; otherwise,
the token is a keyword. */
FLAG_SHADOW = 2
};
So perhaps a better fix is to move that particular test to a
separate testcase that force-compiles with -std=c++03.
gdb/testsuite/ChangeLog
2016-09-16 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.cp/casts.cc (decltype): Move it ...
(main): ... with its call to ...
* gdb.cp/casts03.cc: ... a new file.
* gdb.cp/casts.exp: Add new file casts03.cc, move decltype test to it.
|
|
* ax-gdb.c (gen_expr) <OP_TYPEOF, OP_DECLTYPE>: New cases.
* breakpoint.c (watchpoint_exp_is_const) <OP_TYPEOF,
OP_DECLTYPE>: New cases.
* c-exp.y (TYPEOF, DECLTYPE): New tokens.
(type_exp): Add new productions.
(ident_tokens): Add __typeof__, typeof, __typeof, __decltype,
and decltype.
* eval.c (evaluate_subexp_standard) <OP_TYPEOF, OP_DECLTYPE>:
New case.
* expprint.c (dump_subexp_body_standard) <OP_TYPEOF,
OP_DECLTYPE>: New case.
* parse.c (operator_length_standard) <OP_TYPEOF, OP_DECLTYPE>:
New case.
* std-operator.def (OP_TYPEOF, OP_DECLTYPE): New constants.
* varobj.c (varobj_create): Handle OP_TYPEOF, OP_DECLTYPE.
gdb/testsuite
* gdb.cp/casts.exp: Add tests for typeof and decltype.
* gdb.cp/casts.cc (decltype): New function.
(main): Use it.
|
|
PR c++/9680:
* c-exp.y (REINTERPRET_CAST, DYNAMIC_CAST, STATIC_CAST)
(CONST_CAST): New tokens.
(exp): Add new productions.
(ident_tokens): Add const_cast, dynamic_cast, static_cast, and
reinterpret_cast.
(is_cast_operator): New function.
(yylex): Handle cast operators specially.
* eval.c (evaluate_subexp_standard) <UNOP_DYNAMIC_CAST,
UNOP_REINTERPRET_CAST>: New cases.
* expprint.c (print_subexp_standard): Likewise.
(op_name_standard): Likewise.
(dump_subexp_body_standard): Likewise.
* parse.c (operator_length_standard): Likewise.
* expression.h (enum exp_opcode): New constants UNOP_DYNAMIC_CAST,
UNOP_REINTERPRET_CAST.
* gdbtypes.c (class_types_same_p): New function.
(is_ancestor): Use it.
(is_public_ancestor): New function.
(is_unique_ancestor_worker): Likewise.
(is_unique_ancestor): Likewise.
* gdbtypes.h (class_types_same_p, is_public_ancestor)
(is_unique_ancestor): Declare.
* valops.c (value_reinterpret_cast): New function.
(dynamic_cast_check_1): Likewise.
(dynamic_cast_check_2): Likewise.
(value_dynamic_cast): Likewise.
* value.h (value_reinterpret_cast, value_dynamic_cast): Declare.
gdb/testsuite
PR c++/9680:
* gdb.cp/casts.cc: Add new classes and variables.
* gdb.cp/casts.exp: Test new operators.
|
|
* gdb.cp/casts.exp: New test cases for up/down casting references.
|
|
* gdb.cp: New directory.
* gdb.cp/*: Copy from gdb.c++/*.
* gdb.c++/*: Remove.
* Makefile.in: Change gdb.c++ to gdb.cp.
* configure.in: Ditto.
* configure: Regnerate.
|