+2014-07-15  Pierre Langlois  <pierre.langlois@embecosm.com>
+
+       * avr-tdep.c (AVR_TYPE_ADDRESS_CLASS_FLASH): New macro.
+       (AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH): Likewise.
+       (avr_address_to_pointer): Check for AVR_TYPE_ADDRESS_CLASS_FLASH.
+       (avr_pointer_to_address): Likewise.
+       (avr_address_class_type_flags): New function.
+       (avr_address_class_type_flags_to_name): Likewise.
+       (avr_address_class_name_to_type_flags): Likewise.
+       (avr_gdbarch_init): Set address_class_type_flags,
+       address_class_type_flags_to_name and
+       address_class_name_to_type_flags.
+
 2014-07-15  Pedro Alves  <palves@redhat.com>
 
        * linux-nat.c (kill_callback): Save errno and work with saved
 
 
 /* Constants: prefixed with AVR_ to avoid name space clashes */
 
+/* Address space flags */
+
+/* We are assigning the TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1 to the flash address
+   space.  */
+
+#define AVR_TYPE_ADDRESS_CLASS_FLASH TYPE_ADDRESS_CLASS_1
+#define AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH  \
+  TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1
+
+
 enum
 {
   AVR_REG_W = 24,
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
+  /* Is it a data address in flash?  */
+  if (AVR_TYPE_ADDRESS_CLASS_FLASH (type))
+    {
+      /* A data address in flash is always byte addressed.  */
+      store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order,
+                             avr_convert_iaddr_to_raw (addr));
+    }
   /* Is it a code address?  */
-  if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
-      || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
+  else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
+          || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
     {
+      /* A code address, either a function pointer or the program counter, is
+        word (16 bits) addressed.  */
       store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order,
                              avr_convert_iaddr_to_raw (addr >> 1));
     }
   CORE_ADDR addr
     = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
 
+  /* Is it a data address in flash?  */
+  if (AVR_TYPE_ADDRESS_CLASS_FLASH (type))
+    return avr_make_iaddr (addr);
   /* Is it a code address?  */
-  if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
-      || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
-      || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
+  else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
+          || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
+          || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
     return avr_make_iaddr (addr << 1);
   else
     return avr_make_saddr (addr);
   return -1;
 }
 
+/* Implementation of `address_class_type_flags' gdbarch method.
+
+   This method maps DW_AT_address_class attributes to a
+   type_instance_flag_value.  */
+
+static int
+avr_address_class_type_flags (int byte_size, int dwarf2_addr_class)
+{
+  /* The value 1 of the DW_AT_address_class attribute corresponds to the
+     __flash qualifier.  Note that this attribute is only valid with
+     pointer types and therefore the flag is set to the pointer type and
+     not its target type.  */
+  if (dwarf2_addr_class == 1 && byte_size == 2)
+    return AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH;
+  return 0;
+}
+
+/* Implementation of `address_class_type_flags_to_name' gdbarch method.
+
+   Convert a type_instance_flag_value to an address space qualifier.  */
+
+static const char*
+avr_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags)
+{
+  if (type_flags & AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH)
+    return "flash";
+  else
+    return NULL;
+}
+
+/* Implementation of `address_class_name_to_type_flags' gdbarch method.
+
+   Convert an address space qualifier to a type_instance_flag_value.  */
+
+static int
+avr_address_class_name_to_type_flags (struct gdbarch *gdbarch,
+                                      const char* name,
+                                      int *type_flags_ptr)
+{
+  if (strcmp (name, "flash") == 0)
+    {
+      *type_flags_ptr = AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH;
+      return 1;
+    }
+  else
+    return 0;
+}
+
 /* Initialize the gdbarch structure for the AVR's.  */
 
 static struct gdbarch *
   set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, avr_unwind_sp);
 
+  set_gdbarch_address_class_type_flags (gdbarch, avr_address_class_type_flags);
+  set_gdbarch_address_class_name_to_type_flags
+    (gdbarch, avr_address_class_name_to_type_flags);
+  set_gdbarch_address_class_type_flags_to_name
+    (gdbarch, avr_address_class_type_flags_to_name);
+
   return gdbarch;
 }
 
 
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+const __flash char data_in_flash = 0xab;
+
+static void
+pass_to_function (const __flash char *p)
+{
+}
+
+int
+main (void)
+{
+  const __flash char *pointer_to_flash = &data_in_flash;
+
+  /* break here.  */
+  pass_to_function (&data_in_flash);
+  return 0;
+}
 
--- /dev/null
+# Copyright 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# This file is part of the gdb testsuite.
+#
+# Contributed by Pierre Langlois  <pierre.langlois@embecosm.com>
+# Tests for the AVR __flash named address space qualifier.
+
+if {![istarget "avr*"]} {
+  verbose "Skipping ${gdb_test_file_name}."
+  return
+}
+
+# The __flash qualifier was added in GCC 4.7.
+if {[test_compiler_info {gcc-[0-4]-[0-6]}]} {
+  verbose "Skipping ${gdb_test_file_name}."
+  return
+}
+
+standard_testfile
+if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}]} {
+  return -1
+}
+
+if ![runto [gdb_get_line_number "break here."]] {
+  untested "could not run to \"break here.\""
+  return -1
+}
+
+gdb_test "print pointer_to_flash" \
+  " = $hex <data_in_flash> .*"
+
+gdb_breakpoint "pass_to_function"
+gdb_continue_to_breakpoint "pass_to_function"
+
+gdb_test "print p" \
+  " = $hex <data_in_flash> .*"
+
+gdb_test "backtrace 1" \
+  "\#0  pass_to_function \\(p=$hex <data_in_flash> .*\\).*"