+2017-09-04  Pedro Alves  <palves@redhat.com>
+
+       * c-exp.y (function_method, function_method_void): Add current
+       instance flags to TYPE_INSTANCE.
+       * dwarf2read.c (check_modifier): New.
+       (compute_delayed_physnames): Assert that only C++ adds delayed
+       physnames.  Mark fn_fields as const/volatile depending on
+       physname.
+       * eval.c (make_params): New type_instance_flags parameter.  Use
+       it as the new type's instance flags.
+       (evaluate_subexp_standard) <TYPE_INSTANCE>: Extract the instance
+       flags element and pass it to make_params.
+       * expprint.c (print_subexp_standard) <TYPE_INSTANCE>: Handle
+       instance flags element.
+       (dump_subexp_body_standard) <TYPE_INSTANCE>: Likewise.
+       * gdbtypes.h: Include "enum-flags.h".
+       (type_instance_flags): New enum-flags type.
+       (TYPE_CONST, TYPE_VOLATILE, TYPE_RESTRICT, TYPE_ATOMIC)
+       (TYPE_CODE_SPACE, TYPE_DATA_SPACE): Return boolean.
+       * parse.c (operator_length_standard) <TYPE_INSTANCE>: Adjust.
+       (follow_type_instance_flags): New function.
+       (operator_check_standard) <TYPE_INSTANCE>: Adjust.
+       * parser-defs.h (follow_type_instance_flags): Declare.
+       * valops.c (value_struct_elt_for_reference): const/volatile must
+       match too.
+
 2017-09-04  Pedro Alves  <palves@redhat.com>
 
        * cp-namespace.c (cp_search_static_and_baseclasses): Handle
 
                          LONGEST len = VEC_length (type_ptr, type_list);
 
                          write_exp_elt_opcode (pstate, TYPE_INSTANCE);
+                         /* Save the const/volatile qualifiers as
+                            recorded by the const_or_volatile
+                            production's actions.  */
+                         write_exp_elt_longcst (pstate,
+                                                follow_type_instance_flags ());
                          write_exp_elt_longcst (pstate, len);
                          for (i = 0;
                               VEC_iterate (type_ptr, type_list, i, type_elt);
 
 function_method_void:      exp '(' ')' const_or_volatile
                       { write_exp_elt_opcode (pstate, TYPE_INSTANCE);
+                        /* See above.  */
+                        write_exp_elt_longcst (pstate,
+                                               follow_type_instance_flags ());
                         write_exp_elt_longcst (pstate, 0);
                         write_exp_elt_longcst (pstate, 0);
                         write_exp_elt_opcode (pstate, TYPE_INSTANCE);
 
     }
 }
 
+/* Check whether [PHYSNAME, PHYSNAME+LEN) ends with a modifier like
+   "const" / "volatile".  If so, decrements LEN by the length of the
+   modifier and return true.  Otherwise return false.  */
+
+template<size_t N>
+static bool
+check_modifier (const char *physname, size_t &len, const char (&mod)[N])
+{
+  size_t mod_len = sizeof (mod) - 1;
+  if (len > mod_len && startswith (physname + (len - mod_len), mod))
+    {
+      len -= mod_len;
+      return true;
+    }
+  return false;
+}
+
 /* Compute the physnames of any methods on the CU's method list.
 
    The computation of method physnames is delayed in order to avoid the
 {
   int i;
   struct delayed_method_info *mi;
+
+  /* Only C++ delays computing physnames.  */
+  if (VEC_empty (delayed_method_info, cu->method_list))
+    return;
+  gdb_assert (cu->language == language_cplus);
+
   for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i)
     {
       const char *physname;
       physname = dwarf2_physname (mi->name, mi->die, cu);
       TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi->index)
        = physname ? physname : "";
+
+      /* Since there's no tag to indicate whether a method is a
+        const/volatile overload, extract that information out of the
+        demangled name.  */
+      if (physname != NULL)
+       {
+         size_t len = strlen (physname);
+
+         while (1)
+           {
+             if (physname[len] == ')') /* shortcut */
+               break;
+             else if (check_modifier (physname, len, " const"))
+               TYPE_FN_FIELD_CONST (fn_flp->fn_fields, mi->index) = 1;
+             else if (check_modifier (physname, len, " volatile"))
+               TYPE_FN_FIELD_VOLATILE (fn_flp->fn_fields, mi->index) = 1;
+             else
+               break;
+           }
+       }
     }
 }
 
 
     }
 }
 
-/* Constructs a fake method with the given parameter types.
-   This function is used by the parser to construct an "expected"
-   type for method overload resolution.  */
+/* Constructs a fake method with the given parameter types.  This
+   function is used by the parser to construct an "expected" type for
+   method overload resolution.  FLAGS is used as instance flags of the
+   new type, in order to be able to make the new type represent a
+   const/volatile overload.  */
 
 static struct type *
-make_params (int num_types, struct type **param_types)
+make_params (type_instance_flags flags,
+            int num_types, struct type **param_types)
 {
   struct type *type = XCNEW (struct type);
   TYPE_MAIN_TYPE (type) = XCNEW (struct main_type);
   TYPE_LENGTH (type) = 1;
   TYPE_CODE (type) = TYPE_CODE_METHOD;
   TYPE_CHAIN (type) = type;
+  TYPE_INSTANCE_FLAGS (type) = flags;
   if (num_types > 0)
     {
       if (param_types[num_types - 1] == NULL)
        }
 
     case TYPE_INSTANCE:
-      nargs = longest_to_int (exp->elts[pc + 1].longconst);
-      arg_types = (struct type **) alloca (nargs * sizeof (struct type *));
-      for (ix = 0; ix < nargs; ++ix)
-       arg_types[ix] = exp->elts[pc + 1 + ix + 1].type;
-
-      expect_type = make_params (nargs, arg_types);
-      *(pos) += 3 + nargs;
-      arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
-      xfree (TYPE_FIELDS (expect_type));
-      xfree (TYPE_MAIN_TYPE (expect_type));
-      xfree (expect_type);
-      return arg1;
+      {
+       type_instance_flags flags
+         = (type_instance_flag_value) longest_to_int (exp->elts[pc + 1].longconst);
+       nargs = longest_to_int (exp->elts[pc + 2].longconst);
+       arg_types = (struct type **) alloca (nargs * sizeof (struct type *));
+       for (ix = 0; ix < nargs; ++ix)
+         arg_types[ix] = exp->elts[pc + 2 + ix + 1].type;
+
+       expect_type = make_params (flags, nargs, arg_types);
+       *(pos) += 4 + nargs;
+       arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
+       xfree (TYPE_FIELDS (expect_type));
+       xfree (TYPE_MAIN_TYPE (expect_type));
+       xfree (expect_type);
+       return arg1;
+      }
 
     case BINOP_CONCAT:
       arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
 
 
     case TYPE_INSTANCE:
       {
-       LONGEST count = exp->elts[pc + 1].longconst;
+       type_instance_flags flags
+         = (type_instance_flag_value) longest_to_int (exp->elts[pc + 1].longconst);
+       LONGEST count = exp->elts[pc + 2].longconst;
 
+       /* The FLAGS.  */
+       (*pos)++;
        /* The COUNT.  */
        (*pos)++;
-       fputs_unfiltered ("TypesInstance(", stream);
+       fputs_unfiltered ("TypeInstance(", stream);
        while (count-- > 0)
          {
            type_print (exp->elts[(*pos)++].type, "", stream, 0);
        /* Ending COUNT and ending TYPE_INSTANCE.  */
        (*pos) += 2;
        print_subexp (exp, pos, stream, PREC_PREFIX);
+
+       if (flags & TYPE_INSTANCE_FLAG_CONST)
+         fputs_unfiltered (",const", stream);
+       if (flags & TYPE_INSTANCE_FLAG_VOLATILE)
+         fputs_unfiltered (",volatile", stream);
+
        fputs_unfiltered (")", stream);
        return;
       }
 
     case TYPE_INSTANCE:
       {
-       LONGEST len;
-
-       len = exp->elts[elt++].longconst;
+       type_instance_flags flags
+         = (type_instance_flag_value) longest_to_int (exp->elts[elt++].longconst);
+       LONGEST len = exp->elts[elt++].longconst;
        fprintf_filtered (stream, "%s TypeInstance: ", plongest (len));
        while (len-- > 0)
          {
            if (len > 0)
              fputs_filtered (", ", stream);
          }
+
+       fprintf_filtered (stream, " Flags: %s (", hex_string (flags));
+       bool space = false;
+       auto print_one = [&] (const char *mod)
+         {
+           if (space)
+             fputs_filtered (" ", stream);
+           space = true;
+           fprintf_filtered (stream, mod);
+         };
+       if (flags & TYPE_INSTANCE_FLAG_CONST)
+         print_one ("const");
+       if (flags & TYPE_INSTANCE_FLAG_VOLATILE)
+         print_one ("volatile");
+       fprintf_filtered (stream, ")");
+
        /* Ending LEN and ending TYPE_INSTANCE.  */
        elt += 2;
        elt = dump_subexp (exp, stream, elt);
 
 
 #include "hashtab.h"
 #include "common/offset-type.h"
+#include "common/enum-flags.h"
 
 /* Forward declarations for prototypes.  */
 struct field;
   TYPE_INSTANCE_FLAG_ATOMIC = (1 << 8)
 };
 
+DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags);
+
 /* * Unsigned integer type.  If this is not set for a TYPE_CODE_INT,
    the type is signed (unless TYPE_NOSIGN (below) is set).  */
 
 /* * Constant type.  If this is set, the corresponding type has a
    const modifier.  */
 
-#define TYPE_CONST(t) (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_CONST)
+#define TYPE_CONST(t) ((TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_CONST) != 0)
 
 /* * Volatile type.  If this is set, the corresponding type has a
    volatile modifier.  */
 
 #define TYPE_VOLATILE(t) \
-  (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_VOLATILE)
+  ((TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_VOLATILE) != 0)
 
 /* * Restrict type.  If this is set, the corresponding type has a
    restrict modifier.  */
 
 #define TYPE_RESTRICT(t) \
-  (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_RESTRICT)
+  ((TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_RESTRICT) != 0)
 
 /* * Atomic type.  If this is set, the corresponding type has an
    _Atomic modifier.  */
 
 #define TYPE_ATOMIC(t) \
-  (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_ATOMIC)
+  ((TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_ATOMIC) != 0)
 
 /* * True if this type represents either an lvalue or lvalue reference type.  */
 
    is instruction space, and for data objects is data memory.  */
 
 #define TYPE_CODE_SPACE(t) \
-  (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_CODE_SPACE)
+  ((TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_CODE_SPACE) != 0)
 
 #define TYPE_DATA_SPACE(t) \
-  (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_DATA_SPACE)
+  ((TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_DATA_SPACE) != 0)
 
 /* * Address class flags.  Some environments provide for pointers
    whose size is different from that of a normal pointer or address
 
       break;
 
     case TYPE_INSTANCE:
-      oplen = 4 + longest_to_int (expr->elts[endpos - 2].longconst);
+      oplen = 5 + longest_to_int (expr->elts[endpos - 2].longconst);
       args = 1;
       break;
 
   push_type (tp_function_with_arguments);
 }
 
+/* Pop the type stack and return a type_instance_flags that
+   corresponds the const/volatile qualifiers on the stack.  This is
+   called by the C++ parser when parsing methods types, and as such no
+   other kind of type in the type stack is expected.  */
+
+type_instance_flags
+follow_type_instance_flags ()
+{
+  type_instance_flags flags = 0;
+
+  for (;;)
+    switch (pop_type ())
+      {
+      case tp_end:
+       return flags;
+      case tp_const:
+       flags |= TYPE_INSTANCE_FLAG_CONST;
+       break;
+      case tp_volatile:
+       flags |= TYPE_INSTANCE_FLAG_VOLATILE;
+       break;
+      default:
+       gdb_assert_not_reached ("unrecognized tp_ value in follow_types");
+      }
+}
+
+
 /* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
    as modified by all the stuff on the stack.  */
 struct type *
 
     case TYPE_INSTANCE:
       {
-       LONGEST arg, nargs = elts[pos + 1].longconst;
+       LONGEST arg, nargs = elts[pos + 2].longconst;
 
        for (arg = 0; arg < nargs; arg++)
          {
-           struct type *type = elts[pos + 2 + arg].type;
+           struct type *type = elts[pos + 3 + arg].type;
            struct objfile *objfile = TYPE_OBJFILE (type);
 
            if (objfile && (*objfile_func) (objfile, data))
 
 
 extern struct type *follow_types (struct type *);
 
+extern type_instance_flags follow_type_instance_flags ();
+
 extern void null_post_parser (struct expression **, int);
 
 extern int parse_float (const char *p, int len, DOUBLEST *d,
 
+2017-09-04  Pedro Alves  <palves@redhat.com>
+
+       * gdb.base/func-static.c (S::method const, S::method volatile)
+       (S::method volatile const): New methods.
+       (c_s, v_s, cv_s): New instances.
+       (main): Call method() on them.
+       * gdb.base/func-static.exp (syntax_re, cannot_resolve_re): New variables.
+       (cannot_resolve): New procedure.
+       (cxx_scopes_list): Test cv methods.  Add print-scope-quote and
+       print-quote-unquoted columns.
+       (do_test): Test printing each scope too.
+
 2017-09-04  Pedro Alves  <palves@redhat.com>
 
        * gdb.base/local-static.exp: Also test with
 
   }
 
   void method ();
+  void method () const;
+  void method () volatile;
+  void method () volatile const;
+
   static void static_method ();
 };
 
 S s;
+const S c_s = {};
+volatile S v_s = {};
+const volatile S cv_s = {};
 
 void
 S::method ()
   DEF_STATICS (S_M);
 }
 
+void
+S::method () const
+{
+  DEF_STATICS (S_M_C);
+}
+
+void
+S::method () volatile
+{
+  DEF_STATICS (S_M_V);
+}
+
+void
+S::method () const volatile
+{
+  DEF_STATICS (S_M_CV);
+}
+
 void
 S::static_method ()
 {
 
 #ifdef __cplusplus
       s.method ();
+      c_s.method ();
+      v_s.method ();
+      cv_s.method ();
       s.inline_method ();
       S::static_method ();
       S::static_inline_method ();
 
 
 standard_testfile .c
 
+# A few expected errors.
+set syntax_re "A syntax error in expression, near.*"
+set cannot_resolve_re "Cannot resolve method S::method to any overloaded instance"
+
+# Build an "Cannot resolve method ..." expected error string for
+# method METH.
+#
+proc cannot_resolve {meth} {
+    return "Cannot resolve method $meth to any overloaded instance"
+}
+
 # A list of scopes that have the static variables that we want to
 # print.  Each entry has, in order, the scope/function name, and the
-# prefix used by the static variables.  (The prefix exists to make it
-# easier to debug the test if something goes wrong.)
-
-     #SCOPE                            #PREFIX
+# prefix used by the static variables.  The prefix exists both to make
+# it easier to debug the test if something goes wrong, and, to make
+# sure that printing the static local of one method overload doesn't
+# find the variables of the wrong overload.
+#
+# While at it, we also try printing each scope without the static
+# local, to check that the parse copes with cv overloads without
+# quoting.  That's what the third and forth columns are for.  Note
+# that printing "func()" is different from "func(void)".  The former
+# is an inferior function call, while the latter is a reference to the
+# function.
+
+     #SCOPE                            #PREFIX         #PRINT-SCOPE-QUOTED
+                                                       #PRINT-SCOPE-UNQUOTED (opt)
 set cxx_scopes_list {
-    {"S::method()"                     "S_M"}
-    {"S::static_method()"              "S_SM"}
-    {"S::inline_method()"              "S_IM"}
-    {"S::static_inline_method()"       "S_SIM"}
-    {"S2<int>::method()"               "S2_M"}
-    {"S2<int>::static_method()"                "S2_SM"}
-    {"S2<int>::inline_method()"                "S2_IM"}
-    {"S2<int>::static_inline_method()" "S2_SIM"}
-    {"free_func()"                     "FF"}
-    {"free_inline_func()"              "FIF"}
+    {"S::method()"                     "S_M"           {= \\{void \\(S \\* const\\)\\} $hex <S::method\\(\\)>}
+                                                       {[cannot_resolve "S::method"]}}
+
+    {"S::method() const"               "S_M_C"         {= \\{void \\(const S \\* const\\)\\} $hex <S::method\\(\\) const>}
+                                                       $syntax_re}
+
+    {"S::method() volatile"            "S_M_V"         {= \\{void \\(volatile S \\* const\\)\\} $hex <S::method\\(\\) volatile>}
+                                                       $syntax_re}
+
+    {"S::method() const volatile"      "S_M_CV"        {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>}
+                                                       $syntax_re}
+
+    {"S::method() volatile const"      "S_M_CV"        {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>}
+                                                       $syntax_re}
+
+    {"S::method(void)"                 "S_M"           {= \\{void \\(S \\* const\\)\\} $hex <S::method\\(\\)>}}
+    {"S::method(void) const"           "S_M_C"         {= \\{void \\(const S \\* const\\)\\} $hex <S::method\\(\\) const>}}
+    {"S::method(void) volatile"                "S_M_V"         {= \\{void \\(volatile S \\* const\\)\\} $hex <S::method\\(\\) volatile>}}
+    {"S::method(void) const volatile"  "S_M_CV"        {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>}}
+    {"S::method(void) volatile const"  "S_M_CV"        {= \\{void \\(const volatile S \\* const\\)\\} $hex <S::method\\(\\) const volatile>}}
+
+    {"S::static_method()"              "S_SM"          {= \\{void \\(void\\)\\} $hex <S::static_method\\(\\)>}
+                                                       "void"}
+
+    {"S::static_method(void)"          "S_SM"          {= \\{void \\(void\\)\\} $hex <S::static_method\\(\\)>}}
+
+    {"S::inline_method()"              "S_IM"          {= \\{void \\(S \\* const\\)\\} $hex <S::inline_method\\(\\)>}
+                                                       {[cannot_resolve "S::inline_method"]}}
+
+    {"S::inline_method(void)"          "S_IM"          {= \\{void \\(S \\* const\\)\\} $hex <S::inline_method\\(\\)>}}
+
+    {"S::static_inline_method()"       "S_SIM"         {= \\{void \\(void\\)\\} $hex <S::static_inline_method\\(\\)>}
+                                                       "void"}
+
+    {"S::static_inline_method(void)"   "S_SIM"         {= \\{void \\(void\\)\\} $hex <S::static_inline_method\\(\\)>}}
+
+    {"S2<int>::method()"               "S2_M"          {= \\{void \\(S2<int> \\* const\\)\\} $hex <S2<int>::method\\(\\)>}
+                                                       {[cannot_resolve "S2<int>::method"]}}
+
+    {"S2<int>::static_method()"                "S2_SM"         {= \\{void \\(void\\)\\} $hex <S2<int>::static_method\\(\\)>}
+                                                       "void"}
+
+    {"S2<int>::inline_method()"                "S2_IM"         {= \\{void \\(S2<int> \\* const\\)\\} $hex <S2<int>::inline_method\\(\\)>}
+                                                       {[cannot_resolve "S2<int>::inline_method"]}}
+
+    {"S2<int>::static_inline_method()" "S2_SIM"        {= \\{void \\(void\\)\\} $hex <S2<int>::static_inline_method\\(\\)>}
+                                                       "void"}
+
+    {"free_func"                       "FF"            {= \\{void \\(void\\)\\} $hex <free_func\\(\\)>}}
+
+    {"free_func()"                     "FF"            {= \\{void \\(void\\)\\} $hex <free_func\\(\\)>}
+                                                       "void"}
+
+    {"free_func(void)"                 "FF"            {= \\{void \\(void\\)\\} $hex <free_func\\(\\)>}}
+
+    {"free_inline_func()"              "FIF"           {= \\{void \\(void\\)\\} $hex <free_inline_func\\(\\)>}
+                                                       "void"}
+
+    {"free_inline_func(void)"          "FIF"           {= \\{void \\(void\\)\\} $hex <free_inline_func\\(\\)>}}
 }
 
 set c_scopes_list {
-    {"free_func"                       "FF"}
-    {"free_inline_func"                        "FIF"}
+    {"free_func"                       "FF"            {= \\{void \\(void\\)\\} $hex <free_func>}}
+    {"free_inline_func"                        "FIF"           {= \\{void \\(void\\)\\} $hex <free_inline_func>}}
 }
 
 # A list of all the static varibles defined in each scope.  The first
        set scopes_list $cxx_scopes_list
     }
 
+    # Print each scope/function using these syntaxes:
+    #
+    #  "(gdb) p 'S::method() const'"    # quoted
+    #  "(gdb) p S::method() const"      # unquoted
+    #
+    foreach scope_line $scopes_list  {
+       set scope [lindex $scope_line 0]
+
+       set print_quoted_re [lindex $scope_line 2]
+       set print_quoted_re [uplevel 1 "subst -nobackslashes -nocommands \"$print_quoted_re\""]
+
+       set print_unquoted_re [lindex $scope_line 3]
+       set print_unquoted_re [uplevel 1 "subst -nobackslashes -nocommands \"$print_unquoted_re\""]
+
+       gdb_test "print '${scope}'" $print_quoted_re
+
+       if {$print_unquoted_re != ""} {
+           gdb_test "print ${scope}" $print_unquoted_re
+       } else {
+           gdb_test "print ${scope}" $print_quoted_re
+       }
+    }
+
     # Print each variable using these syntaxes:
     #
     #  'func()'::var
 
            {
              for (j = 0; j < len; ++j)
                {
+                 if (TYPE_CONST (intype) != TYPE_FN_FIELD_CONST (f, j))
+                   continue;
+                 if (TYPE_VOLATILE (intype) != TYPE_FN_FIELD_VOLATILE (f, j))
+                   continue;
+
                  if (compare_parameters (TYPE_FN_FIELD_TYPE (f, j), intype, 0)
                      || compare_parameters (TYPE_FN_FIELD_TYPE (f, j),
                                             intype, 1))