PR exp/13206:

* 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.
This commit is contained in:
Tom Tromey 2012-07-19 15:38:18 +00:00
parent 274b54d7e2
commit 608b49672e
12 changed files with 140 additions and 2 deletions

View File

@ -1,3 +1,22 @@
2012-07-19 Tom Tromey <tromey@redhat.com>
PR exp/13206:
* 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.
2012-07-19 Tom Tromey <tromey@redhat.com>
* c-exp.y (enum token_flags): New.

View File

@ -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:

View File

@ -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:

View File

@ -219,6 +219,8 @@ static void check_parameter_typelist (VEC (type_ptr) *);
%type <sval> 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

View File

@ -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

View File

@ -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:
{

View File

@ -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;

View File

@ -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)

View File

@ -1,3 +1,9 @@
2012-07-19 Tom Tromey <tromey@redhat.com>
* 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 <palves@redhat.com>
* gdb.base/sigall.exp (signals): New list.

View File

@ -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 */
}

View File

@ -107,6 +107,25 @@ gdb_test "print reinterpret_cast<void> (b)" "Invalid reinterpret_cast" \
gdb_test "print reinterpret_cast<A &> (*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\]+"

View File

@ -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"