summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog19
-rw-r--r--gdb/ax-gdb.c2
-rw-r--r--gdb/breakpoint.c2
-rw-r--r--gdb/c-exp.y24
-rw-r--r--gdb/eval.c39
-rw-r--r--gdb/expprint.c6
-rw-r--r--gdb/parse.c2
-rw-r--r--gdb/std-operator.def9
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.cp/casts.cc10
-rw-r--r--gdb/testsuite/gdb.cp/casts.exp19
-rw-r--r--gdb/varobj.c4
12 files changed, 140 insertions, 2 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8984d632299..710978286c4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,24 @@
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.
(struct token) <cxx_only>: Remove.
<flags>: New field.
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 2db56bffa49..f2c5155b788 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 a122f6f4d0c..cbb150f4be4 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 e721995a879..174a38c1e9c 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -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
diff --git a/gdb/eval.c b/gdb/eval.c
index a012873c461..4253820719c 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 c3f6697f62d..945389c437d 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 1f9addf79d9..269d8fca5f3 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 9c6a01be329..b0136875361 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 83984753193..593eae8bfd4 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/gdb.cp/casts.cc b/gdb/testsuite/gdb.cp/casts.cc
index 543db896d3d..43f112f32f1 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 2013ab841be..a3fe7435933 100644
--- a/gdb/testsuite/gdb.cp/casts.exp
+++ b/gdb/testsuite/gdb.cp/casts.exp
@@ -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\]+"
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 42e2ce4f3bd..99b158efcfd 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"