PR exp/13206:
authorTom Tromey <tromey@redhat.com>
Thu, 19 Jul 2012 15:38:18 +0000 (15:38 +0000)
committerTom Tromey <tromey@redhat.com>
Thu, 19 Jul 2012 15:38:18 +0000 (15:38 +0000)
* 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.

12 files changed:
gdb/ChangeLog
gdb/ax-gdb.c
gdb/breakpoint.c
gdb/c-exp.y
gdb/eval.c
gdb/expprint.c
gdb/parse.c
gdb/std-operator.def
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/casts.cc
gdb/testsuite/gdb.cp/casts.exp
gdb/varobj.c

index 8984d6322992c9a2184b6e052a80f1f5fe8f27d6..710978286c4a0fa650d29f1b68b765628a39cecb 100644 (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.
index 2db56bffa49813b06bc41ed5e08424efc2319390..f2c5155b78805b9a73fd8cd6a6568befd00aa734 100644 (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:
index a122f6f4d0c9717440cdd92d0c5220bfe1e298c9..cbb150f4be4388f65331b8a96fb4a980c7c0cea0 100644 (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:
 
index e721995a8796f3d60485b66801a702491a5c389e..174a38c1e9ce326f94b291d1dbba0989a21b7ee0 100644 (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
index a012873c461f26e28c2305063a2beb41bf2664c5..4253820719c44fba3742ff5aa594fff5bc780cc7 100644 (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
index c3f6697f62dae7890fd8c792d0c1ad68ccc69ed2..945389c437d2e5cf2498d2066e392eb7d63d54bd 100644 (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:
       {
index 1f9addf79d9f044ba98b757825cfcb20b9a472d4..269d8fca5f38e48e82832a1fef7cfe338bc7595e 100644 (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;
index 9c6a01be329485261516f820f18d5b0517afa91f..b01368753612e8b2b9bccae0671990c4a8ac4a9c 100644 (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)
index 83984753193db656804c232f8b44a4d72af6b297..593eae8bfd4048978d68bb565c826cef675ffe71 100644 (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.
index 543db896d3de9080882f2b5498b53146490a2a36..43f112f32f165186460e4648178fcb5180cdeeef 100644 (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 */
 }
index 2013ab841bec7e68072f2ba000c3135605c39128..a3fe7435933af4a8688fed3adbfe193eb4b7e4e0 100644 (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\]+"
index 42e2ce4f3bd3db336e4d51cb301737ebf75adbf1..99b158efcfd5d3c0822923271ebb7596bf6be1e9 100644 (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"