+2020-12-15  Tom Tromey  <tom@tromey.com>
+
+       * varobj.c (varobj_create): Use first_opcode.
+       * value.c (init_if_undefined_command): Use first_opcode.
+       * typeprint.c (whatis_exp): Use first_opcode.
+       * tracepoint.c (validate_actionline): Use first_opcode.
+       (encode_actions_1): Use first_opcode.
+       * stack.c (return_command): Use first_opcode.
+       * expression.h (struct expression) <first_opcode>: New method.
+       * eval.c (parse_and_eval_type): Use first_opcode.
+       * dtrace-probe.c (dtrace_process_dof_probe): Use first_opcode.
+
 2020-12-15  Tom Tromey  <tom@tromey.com>
 
        * f-lang.c (evaluate_subexp_f): Update.
 
            {
            }
 
-         if (expr != NULL && expr.get ()->elts[0].opcode == OP_TYPE)
+         if (expr != NULL && expr->first_opcode () == OP_TYPE)
            type = value_type (evaluate_type (expr.get ()));
 
          args.emplace_back (type, std::move (type_str), std::move (expr));
 
   tmp[length + 2] = '0';
   tmp[length + 3] = '\0';
   expression_up expr = parse_expression (tmp);
-  if (expr->elts[0].opcode != UNOP_CAST)
+  if (expr->first_opcode () != UNOP_CAST)
     error (_("Internal error in eval_type."));
   return expr->elts[1].type;
 }
 
 
   void resize (size_t);
 
+  /* Return the opcode for the outermost sub-expression of this
+     expression.  */
+  enum exp_opcode first_opcode () const
+  {
+      return elts[0].opcode;
+  }
+
   /* Language it was entered in.  */
   const struct language_defn *language_defn;
   /* Architecture it was parsed in.  */
 
        return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
       if (return_type == NULL)
        {
-         if (retval_expr->elts[0].opcode != UNOP_CAST
-             && retval_expr->elts[0].opcode != UNOP_CAST_TYPE)
+         if (retval_expr->first_opcode () != UNOP_CAST
+             && retval_expr->first_opcode () != UNOP_CAST_TYPE)
            error (_("Return value type not available for selected "
                     "stack frame.\n"
                     "Please use an explicit cast of the value to return."));
 
              expression_up exp = parse_exp_1 (&p, loc->address,
                                               block_for_pc (loc->address), 1);
 
-             if (exp->elts[0].opcode == OP_VAR_VALUE)
+             if (exp->first_opcode () == OP_VAR_VALUE)
                {
                  if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
                    {
                                                   block_for_pc (tloc->address),
                                                   1);
 
-                 switch (exp->elts[0].opcode)
+                 switch (exp->first_opcode ())
                    {
                    case OP_REGISTER:
                      {
 
       val = evaluate_type (expr.get ());
       type = value_type (val);
 
-      if (show == -1 && expr->elts[0].opcode == OP_TYPE)
+      if (show == -1 && expr->first_opcode () == OP_TYPE)
        {
          /* The user expression names a type directly.  */
 
 
   /* Validate the expression.
      Was the expression an assignment?
      Or even an expression at all?  */
-  if (expr->nelts == 0 || expr->elts[0].opcode != BINOP_ASSIGN)
+  if (expr->nelts == 0 || expr->first_opcode () != BINOP_ASSIGN)
     error (_("Init-if-undefined requires an assignment expression."));
 
   /* Extract the variable from the parsed expression.
 
        }
 
       /* Don't allow variables to be created for types.  */
-      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)
+      enum exp_opcode opcode = var->root->exp->first_opcode ();
+      if (opcode == OP_TYPE
+         || opcode == OP_TYPEOF
+         || opcode == OP_DECLTYPE)
        {
          fprintf_unfiltered (gdb_stderr, "Attempt to use a type name"
                              " as an expression.\n");