From 608b49672edd92191a25a2c365def9d2f4f51db7 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 19 Jul 2012 15:38:18 +0000 Subject: [PATCH] PR exp/13206: * ax-gdb.c (gen_expr) : New cases. * breakpoint.c (watchpoint_exp_is_const) : 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) : New case. * expprint.c (dump_subexp_body_standard) : New case. * parse.c (operator_length_standard) : 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. --- gdb/ChangeLog | 19 +++++++++++++++++ gdb/ax-gdb.c | 2 ++ gdb/breakpoint.c | 2 ++ gdb/c-exp.y | 24 ++++++++++++++++++++- gdb/eval.c | 39 ++++++++++++++++++++++++++++++++++ gdb/expprint.c | 6 ++++++ gdb/parse.c | 2 ++ gdb/std-operator.def | 9 ++++++++ gdb/testsuite/ChangeLog | 6 ++++++ gdb/testsuite/gdb.cp/casts.cc | 10 +++++++++ gdb/testsuite/gdb.cp/casts.exp | 19 +++++++++++++++++ gdb/varobj.c | 4 +++- 12 files changed, 140 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8984d63229..710978286c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2012-07-19 Tom Tromey + + PR exp/13206: + * ax-gdb.c (gen_expr) : New cases. + * breakpoint.c (watchpoint_exp_is_const) : 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) : + New case. + * expprint.c (dump_subexp_body_standard) : New case. + * parse.c (operator_length_standard) : + New case. + * std-operator.def (OP_TYPEOF, OP_DECLTYPE): New constants. + * varobj.c (varobj_create): Handle OP_TYPEOF, OP_DECLTYPE. + 2012-07-19 Tom Tromey * c-exp.y (enum token_flags): New. diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 2db56bffa4..f2c5155b78 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -2255,6 +2255,8 @@ gen_expr (struct expression *exp, union exp_element **pc, break; case OP_TYPE: + case OP_TYPEOF: + case OP_DECLTYPE: error (_("Attempt to use a type name as an expression.")); default: diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index a122f6f4d0..cbb150f4be 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -10162,6 +10162,8 @@ watchpoint_exp_is_const (const struct expression *exp) case OP_BITSTRING: case OP_ARRAY: case OP_TYPE: + case OP_TYPEOF: + case OP_DECLTYPE: case OP_NAME: case OP_OBJC_NSSTRING: diff --git a/gdb/c-exp.y b/gdb/c-exp.y index e721995a87..174a38c1e9 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -219,6 +219,8 @@ static void check_parameter_typelist (VEC (type_ptr) *); %type operator %token REINTERPRET_CAST DYNAMIC_CAST STATIC_CAST CONST_CAST %token ENTRY +%token TYPEOF +%token DECLTYPE /* Special type cases, put in to allow the parser to distinguish different legal basetypes. */ @@ -268,6 +270,20 @@ type_exp: type { write_exp_elt_opcode(OP_TYPE); write_exp_elt_type($1); write_exp_elt_opcode(OP_TYPE);} + | TYPEOF '(' exp ')' + { + write_exp_elt_opcode (OP_TYPEOF); + } + | TYPEOF '(' type ')' + { + write_exp_elt_opcode (OP_TYPE); + write_exp_elt_type ($3); + write_exp_elt_opcode (OP_TYPE); + } + | DECLTYPE '(' exp ')' + { + write_exp_elt_opcode (OP_DECLTYPE); + } ; /* Expressions, including the comma operator. */ @@ -2059,7 +2075,13 @@ static const struct token ident_tokens[] = {"const_cast", CONST_CAST, OP_NULL, FLAG_CXX }, {"dynamic_cast", DYNAMIC_CAST, OP_NULL, FLAG_CXX }, {"static_cast", STATIC_CAST, OP_NULL, FLAG_CXX }, - {"reinterpret_cast", REINTERPRET_CAST, OP_NULL, FLAG_CXX } + {"reinterpret_cast", REINTERPRET_CAST, OP_NULL, FLAG_CXX }, + + {"__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 } }; /* When we find that lexptr (the global var defined in parse.c) is diff --git a/gdb/eval.c b/gdb/eval.c index a012873c46..4253820719 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -2900,6 +2900,45 @@ evaluate_subexp_standard (struct type *expect_type, else error (_("Attempt to use a type name as an expression")); + case OP_TYPEOF: + case OP_DECLTYPE: + if (noside == EVAL_SKIP) + { + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + goto nosideret; + } + else if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + enum exp_opcode sub_op = exp->elts[*pos].opcode; + struct value *result; + + result = evaluate_subexp (NULL_TYPE, exp, pos, + EVAL_AVOID_SIDE_EFFECTS); + + /* 'decltype' has special semantics for lvalues. */ + if (op == OP_DECLTYPE + && (sub_op == BINOP_SUBSCRIPT + || sub_op == STRUCTOP_MEMBER + || sub_op == STRUCTOP_MPTR + || sub_op == UNOP_IND + || sub_op == STRUCTOP_STRUCT + || sub_op == STRUCTOP_PTR + || sub_op == OP_SCOPE)) + { + struct type *type = value_type (result); + + if (TYPE_CODE (check_typedef (type)) != TYPE_CODE_REF) + { + type = lookup_reference_type (type); + result = allocate_value (type); + } + } + + return result; + } + else + error (_("Attempt to use a type as an expression")); + default: /* Removing this case and compiling with gcc -Wall reveals that a lot of cases are hitting this case. Some of these should diff --git a/gdb/expprint.c b/gdb/expprint.c index c3f6697f62..945389c437 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -971,6 +971,12 @@ dump_subexp_body_standard (struct expression *exp, fprintf_filtered (stream, ")"); elt += 2; break; + case OP_TYPEOF: + case OP_DECLTYPE: + fprintf_filtered (stream, "Typeof ("); + elt = dump_subexp (exp, stream, elt); + fprintf_filtered (stream, ")"); + break; case STRUCTOP_STRUCT: case STRUCTOP_PTR: { diff --git a/gdb/parse.c b/gdb/parse.c index 1f9addf79d..269d8fca5f 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -938,6 +938,8 @@ operator_length_standard (const struct expression *expr, int endpos, case UNOP_ODD: case UNOP_ORD: case UNOP_TRUNC: + case OP_TYPEOF: + case OP_DECLTYPE: oplen = 1; args = 1; break; diff --git a/gdb/std-operator.def b/gdb/std-operator.def index 9c6a01be32..b013687536 100644 --- a/gdb/std-operator.def +++ b/gdb/std-operator.def @@ -332,3 +332,12 @@ OP (OP_DECFLOAT) /* OP_ADL_FUNC specifies that the function is to be looked up in an Argument Dependent manner (Koenig lookup). */ OP (OP_ADL_FUNC) + +/* The typeof operator. This has one expression argument, which is + evaluated solely for its type. */ +OP (OP_TYPEOF) + +/* The decltype operator. This has one expression argument, which is + evaluated solely for its type. This is similar to typeof, but has + slight different semantics. */ +OP (OP_DECLTYPE) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8398475319..593eae8bfd 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-07-19 Tom Tromey + + * gdb.cp/casts.exp: Add tests for typeof and decltype. + * gdb.cp/casts.cc (decltype): New function. + (main): Use it. + 2012-07-19 Pedro Alves * gdb.base/sigall.exp (signals): New list. diff --git a/gdb/testsuite/gdb.cp/casts.cc b/gdb/testsuite/gdb.cp/casts.cc index 543db896d3..43f112f32f 100644 --- a/gdb/testsuite/gdb.cp/casts.cc +++ b/gdb/testsuite/gdb.cp/casts.cc @@ -34,6 +34,14 @@ struct DoublyDerived : public VirtuallyDerived, { }; +// Confuse a simpler approach. + +double +decltype(int x) +{ + return x + 2.0; +} + int main (int argc, char **argv) { @@ -48,5 +56,7 @@ main (int argc, char **argv) Alpha *ad = &derived; Alpha *add = &doublyderived; + double y = decltype(2); + return 0; /* breakpoint spot: casts.exp: 1 */ } diff --git a/gdb/testsuite/gdb.cp/casts.exp b/gdb/testsuite/gdb.cp/casts.exp index 2013ab841b..a3fe743593 100644 --- a/gdb/testsuite/gdb.cp/casts.exp +++ b/gdb/testsuite/gdb.cp/casts.exp @@ -107,6 +107,25 @@ gdb_test "print reinterpret_cast (b)" "Invalid reinterpret_cast" \ gdb_test "print reinterpret_cast (*b)" " = \\(A \\&\\) @$hex: {a = 42}" \ "reinterpret_cast to reference type" +# Test that keyword shadowing works. + +gdb_test "whatis decltype(5)" " = double" + +# Basic tests using typeof. + +foreach opname {__typeof__ __typeof __decltype} { + gdb_test "print (${opname}(a)) (b)" " = \\(A \\*\\) $hex" \ + "old-style cast using $opname" + + gdb_test "print static_cast<${opname}(a)> (b)" " = \\(A \\*\\) $hex" \ + "static_cast using $opname" + + gdb_test "print reinterpret_cast<${opname}(a)> (b)" " = \\(A \\*\\) $hex" \ + "reinterpret_cast using $opname" +} + +gdb_test "whatis __decltype(*a)" "type = A \\&" + # Tests of dynamic_cast. set nonzero_hex "0x\[0-9A-Fa-f\]\[0-9A-Fa-f\]+" diff --git a/gdb/varobj.c b/gdb/varobj.c index 42e2ce4f3b..99b158efcf 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -675,7 +675,9 @@ varobj_create (char *objname, } /* Don't allow variables to be created for types. */ - if (var->root->exp->elts[0].opcode == OP_TYPE) + if (var->root->exp->elts[0].opcode == OP_TYPE + || var->root->exp->elts[0].opcode == OP_TYPEOF + || var->root->exp->elts[0].opcode == OP_DECLTYPE) { do_cleanups (old_chain); fprintf_unfiltered (gdb_stderr, "Attempt to use a type name" -- 2.34.1