DWARFv5 DW_TAG_aligned_type.

Message ID 1404944457-4500-1-git-send-email-mjw@redhat.com
State New, archived
Headers

Commit Message

Mark Wielaard July 9, 2014, 10:20 p.m. UTC
  Hi,

This patch is to deal with the corresponding patch to gcc:
https://gcc.gnu.org/ml/gcc-patches/2014-07/msg00667.html
Like the DW_TAG_atomic_type patch (sorry, I haven't dealt yet with all
the comments), this isn't meant to be applied as is (it is currently only
a proposal for DWARFv5). But I would like to get some comments on
the code and whether the proposed DWARF is useful. I only tested this for
C code. If other languages have a similar concept it would be nice to know
what it looks like and how it can be handled in gdb.

Thanks,

Mark

gdb/ChangeLog

	* c-typeprint.c (cp_type_print_method_args): Handle TYPE_USER_ALIGN.
	(c_type_print_varspec_prefix): Likewise.
	(c_type_print_modifier): Likewise.
	* dwarf2read.c (add_array_cv_aligned_type): New function.
	(read_tag_aligned_type): Likewise.
	(read_type_die_1): Handle DW_TAG_aligned_type.
	* gdbtypes.c (make_qualified_type): Calls...
	(make_qualified_aligned_type): New function that handles user
	alignment.
	(make_aligned_type): New function.
	(check_typedef): Handle TYPE_USER_ALIGN.
	(check_types_equal): Likewise.
	(recursive_dump_type): Likewise.
	(copy_type_recursive): Likewise.
	(copy_type): Likewise.
	* gdbtypes.h (struct type): Add user_align.
	(TYPE_USER_ALIGN): New define.
	(make_aligned_type): Define.

include/ChangeLog

	* dwarf2.def: Add DW_TAG_aligned_type and DW_AT_alignment.
---
 gdb/ChangeLog      |   21 ++++++++++++
 gdb/c-typeprint.c  |   19 ++++++++++-
 gdb/dwarf2read.c   |   58 ++++++++++++++++++++++++++++++++++
 gdb/gdbtypes.c     |   88 ++++++++++++++++++++++++++++++++++++++++------------
 gdb/gdbtypes.h     |   17 ++++++++--
 include/ChangeLog  |    4 ++
 include/dwarf2.def |    3 ++
 7 files changed, 184 insertions(+), 26 deletions(-)
  

Comments

Joel Brobecker July 11, 2014, 2:42 p.m. UTC | #1
Hi Mark,

> gdb/ChangeLog
> 
> 	* c-typeprint.c (cp_type_print_method_args): Handle TYPE_USER_ALIGN.
> 	(c_type_print_varspec_prefix): Likewise.
> 	(c_type_print_modifier): Likewise.
> 	* dwarf2read.c (add_array_cv_aligned_type): New function.
> 	(read_tag_aligned_type): Likewise.
> 	(read_type_die_1): Handle DW_TAG_aligned_type.
> 	* gdbtypes.c (make_qualified_type): Calls...
> 	(make_qualified_aligned_type): New function that handles user
> 	alignment.
> 	(make_aligned_type): New function.
> 	(check_typedef): Handle TYPE_USER_ALIGN.
> 	(check_types_equal): Likewise.
> 	(recursive_dump_type): Likewise.
> 	(copy_type_recursive): Likewise.
> 	(copy_type): Likewise.
> 	* gdbtypes.h (struct type): Add user_align.
> 	(TYPE_USER_ALIGN): New define.
> 	(make_aligned_type): Define.

Thanks for the patch!

My only question is regarding the checks for alignments to be stricter
than the alignment of their base types. Why are they needed? I am asking
because, in Ada, it is allowed to be specifying an alignment which is
less strict than the standard alignment. We can ask for byte-aligned
integers, for instance. If I understand your patch correctly, the base
type will have no alignment attribute, and therefore the 1-byte
alignment attribute will be accepted. So my guess is that those checks
are implementing requirements of the proposed DWARF extension. This
leads me to ask why that's necessary? Shouldn't the compiler be able
to provide the actual alignement allowing consumers to just follow it
blindly?

Thanks!
  
Tom Tromey July 11, 2014, 3:23 p.m. UTC | #2
>>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes:

Mark> This patch is to deal with the corresponding patch to gcc:
Mark> https://gcc.gnu.org/ml/gcc-patches/2014-07/msg00667.html

Thanks Mark.

Mark> Like the DW_TAG_atomic_type patch (sorry, I haven't dealt yet with all
Mark> the comments), this isn't meant to be applied as is (it is currently only
Mark> a proposal for DWARFv5).

Understood.

Mark> +      if (TYPE_USER_ALIGN (domain) != 0)
Mark> +	fprintf_filtered (stream, " _Alignas (%u)", TYPE_USER_ALIGN (domain));

I think the preferred spelling in C++ is "alignas", not "_Alignas".
It would be a bit prettier if this were language-dependent.
What do you think?  It affects a few spots.

Mark> +/* Add the given user alignment to the element type of the array.  GCC
Mark> +   outputs DWARF type qualifiers that apply to an array, not the
Mark> +   element type.  But GDB relies on the array element type to carry
Mark> +   the cv-qualifiers.  This is mimics section 6.7.3, point 9 of the
Mark> +   C11 specification (n1570).  */
Mark> +static struct type *
Mark> +add_array_cv_aligned_type (struct die_info *die, struct dwarf2_cu *cu,
Mark> +			   struct type *base_type, unsigned int user_align)
Mark> +{

gdb rules put a blank line between the comment and the start of the
function.

Mark> +      TYPE_TARGET_TYPE (inner_array) =
Mark> +	copy_type (TYPE_TARGET_TYPE (inner_array));

The "=" goes on the start of the next line.

 
Mark> +static struct type *
Mark> +read_tag_aligned_type (struct die_info *die, struct dwarf2_cu *cu)
Mark> +{

Needs some kind of intro comment.

Mark> +/* Make a '_Alignas'-qualified version of TYPE (if user_align is
Mark> +   stricter than the user alignment of TYPE).  */
Mark> +
Mark> +struct type *
Mark> +make_aligned_type (struct type *type, unsigned int user_align)
Mark> +{
Mark> +  if (user_align > TYPE_USER_ALIGN (type))
Mark> +    return make_qualified_aligned_type (type, TYPE_INSTANCE_FLAGS (type),
Mark> +					user_align, NULL);

Like Joel I am curious about the need for this.

I thought maybe it was just following the (C & C++) language standard.
But would DWARF like this really be emitted by the compiler?
It wasn't clear to me.

Mark> +	int new_user_align = TYPE_USER_ALIGN (type);

Most spots are using unsigned for this.

Occasionally I'm tempted to adopt the C++ style of ubiquitous typedefs
to avoid this kind of mismatch.  But I've never really brought that up,
so I suggest just changing this instance.

Mark> +2014-07-09  Mark Wielaard  <mjw@redhat.com>
Mark> +
Mark> +	* dwarf2.def: Add DW_TAG_aligned_type and DW_AT_alignment.

Not important now, but when it's time to put the patch in, this change
will have to go to gcc-patches for approval & checkin; then pulled over
to the binutils-gdb tree.  It won't require any additional approval on
this side at least.

Tom
  
Mark Wielaard July 17, 2014, 10:19 p.m. UTC | #3
On Fri, 2014-07-11 at 07:42 -0700, Joel Brobecker wrote:
> My only question is regarding the checks for alignments to be stricter
> than the alignment of their base types. Why are they needed? I am asking
> because, in Ada, it is allowed to be specifying an alignment which is
> less strict than the standard alignment. We can ask for byte-aligned
> integers, for instance. If I understand your patch correctly, the base
> type will have no alignment attribute, and therefore the 1-byte
> alignment attribute will be accepted. So my guess is that those checks
> are implementing requirements of the proposed DWARF extension. This
> leads me to ask why that's necessary? Shouldn't the compiler be able
> to provide the actual alignement allowing consumers to just follow it
> blindly?

They do that because it assumes the proposed DWARF extension requires
interpreting "layered" user alignments as if they follow C semantics.
But you are right that should not be necessary. I just hadn't considered
anything else than the C semantics when writing the code. Sorry.

We do need to specify what it means when you have a type that is wrapped
in multiple (different) user alignment tags. We could either say that
has to be resolved by the consumer based on the semantics dictated by
the DW_AT_language of the compile unit. Or we could say that a producer
is responsible for interpreting the language semantics by making sure
that the "outer" user alignment overrides any other user alignment tags
(so in the C case, the producer would NOT add an extra user alignment
tag, unless it was stricter than any existing ones for the underlying
type). I think my preference is to do the second, make the producer
responsible. What do you think?

Thanks,

Mark
  
Mark Wielaard July 17, 2014, 10:25 p.m. UTC | #4
Hi Joel,

Forgot to ask...

On Fri, 2014-07-18 at 00:19 +0200, Mark Wielaard wrote:
> On Fri, 2014-07-11 at 07:42 -0700, Joel Brobecker wrote:
> > My only question is regarding the checks for alignments to be stricter
> > than the alignment of their base types. Why are they needed? I am asking
> > because, in Ada, it is allowed to be specifying an alignment which is
> > less strict than the standard alignment. We can ask for byte-aligned
> > integers, for instance.

Could you post an example Ada source code example so I can test a bit
how my gcc and gdb patches interact for an user aligned Ada type?

Thanks,

Mark
  
Mark Wielaard July 17, 2014, 10:36 p.m. UTC | #5
On Fri, 2014-07-11 at 09:23 -0600, Tom Tromey wrote:
> Mark> +      if (TYPE_USER_ALIGN (domain) != 0)
> Mark> +	fprintf_filtered (stream, " _Alignas (%u)", TYPE_USER_ALIGN (domain));
> 
> I think the preferred spelling in C++ is "alignas", not "_Alignas".
> It would be a bit prettier if this were language-dependent.
> What do you think?  It affects a few spots.

Yes, C++ uses a keyword for this with slightly different, but almost
equal, semantics than the C _Alignas qualifier (C11 does define a header
stdalign.h that has #define alignas _Alignas so that you can use alignas
almost like in C++).

How does the c-typeprint.c code determine the current language of the
type?

> Mark> +/* Add the given user alignment to the element type of the array.  GCC
> Mark> +   outputs DWARF type qualifiers that apply to an array, not the
> Mark> +   element type.  But GDB relies on the array element type to carry
> Mark> +   the cv-qualifiers.  This is mimics section 6.7.3, point 9 of the
> Mark> +   C11 specification (n1570).  */
> Mark> +static struct type *
> Mark> +add_array_cv_aligned_type (struct die_info *die, struct dwarf2_cu *cu,
> Mark> +			   struct type *base_type, unsigned int user_align)
> Mark> +{
> 
> gdb rules put a blank line between the comment and the start of the
> function.

Fixed.

> Mark> +      TYPE_TARGET_TYPE (inner_array) =
> Mark> +	copy_type (TYPE_TARGET_TYPE (inner_array));
> 
> The "=" goes on the start of the next line.

Fixed.

> Mark> +static struct type *
> Mark> +read_tag_aligned_type (struct die_info *die, struct dwarf2_cu *cu)
> Mark> +{
> 
> Needs some kind of intro comment.

Added:

/* Handle DW_TAG_aligned_type and DW_AT_alignment.  */

> Mark> +/* Make a '_Alignas'-qualified version of TYPE (if user_align is
> Mark> +   stricter than the user alignment of TYPE).  */
> Mark> +
> Mark> +struct type *
> Mark> +make_aligned_type (struct type *type, unsigned int user_align)
> Mark> +{
> Mark> +  if (user_align > TYPE_USER_ALIGN (type))
> Mark> +    return make_qualified_aligned_type (type, TYPE_INSTANCE_FLAGS (type),
> Mark> +					user_align, NULL);
> 
> Like Joel I am curious about the need for this.
> 
> I thought maybe it was just following the (C & C++) language standard.
> But would DWARF like this really be emitted by the compiler?
> It wasn't clear to me.

Yeah, it wouldn't actually be emitted by my gcc patch. As I explained to
Joel I just wanted to handle the "nested alignment" case somehow and
assumed C11 semantics. We will define something for this and handle it
properly.

> Mark> +	int new_user_align = TYPE_USER_ALIGN (type);
> 
> Most spots are using unsigned for this.
> 
> Occasionally I'm tempted to adopt the C++ style of ubiquitous typedefs
> to avoid this kind of mismatch.  But I've never really brought that up,
> so I suggest just changing this instance.

Changed to unsigned.

Thanks,

Mark
  
Tom Tromey July 18, 2014, 3:37 p.m. UTC | #6
>>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes:

Mark> Or we could say that a producer
Mark> is responsible for interpreting the language semantics by making sure
Mark> that the "outer" user alignment overrides any other user alignment tags
Mark> (so in the C case, the producer would NOT add an extra user alignment
Mark> tag, unless it was stricter than any existing ones for the underlying
Mark> type). I think my preference is to do the second, make the producer
Mark> responsible. What do you think?

That certainly seems both simple and clear.

Tom
  
Tom Tromey July 18, 2014, 3:38 p.m. UTC | #7
>>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes:

Mark> How does the c-typeprint.c code determine the current language of the
Mark> type?

It seems to examine the global "current_language", e.g.:

	  if (current_language->la_language == language_cplus

Tom
  
Joel Brobecker July 30, 2014, 4:59 p.m. UTC | #8
Hi Mark,

> Forgot to ask...
> 
> On Fri, 2014-07-18 at 00:19 +0200, Mark Wielaard wrote:
> > On Fri, 2014-07-11 at 07:42 -0700, Joel Brobecker wrote:
> > > My only question is regarding the checks for alignments to be stricter
> > > than the alignment of their base types. Why are they needed? I am asking
> > > because, in Ada, it is allowed to be specifying an alignment which is
> > > less strict than the standard alignment. We can ask for byte-aligned
> > > integers, for instance.
> 
> Could you post an example Ada source code example so I can test a bit
> how my gcc and gdb patches interact for an user aligned Ada type?

Here it is (credits to Eric Botcazou):

        package P is

          type My_Integer is new Integer;
          for My_Integer'Alignment use 1;

          C : Character;
          I : My_Integer;

        end P;

Save the code in a file called p.ads, and then compile it using:

        % gcc -c -g p.ads

Variable "C" is just there to prevent variable "I" from being
default-aligned by accident.

If you look at the debugging info, you'll find that our variable
is called "p__i". The alignment is handled via putting it inside
a ___PAD struct as a component called "F". Eg:

        .uleb128 0x6    # (DIE (0x70) DW_TAG_variable)
        .long   .LASF1  # DW_AT_name: "p__i"
        .long   0x1d    # DW_AT_type

Following the type of that variable gives us:

        .uleb128 0x2    # (DIE (0x1d) DW_TAG_structure_type)
        .long   .LASF5  # DW_AT_name: "p__my_integer___PAD"
        [...]
        .uleb128 0x3    # (DIE (0x29) DW_TAG_member)
        .ascii "F\0"    # DW_AT_name
        .long   0x38    # DW_AT_type

Following then the type of member "F" yields a subrange type:

        .uleb128 0x4    # (DIE (0x38) DW_TAG_subrange_type)
        .long   0x80000000      # DW_AT_lower_bound
        .long   0x7fffffff      # DW_AT_upper_bound
        .long   .LASF6  # DW_AT_name: "p__my_integer"
        .long   0x4b    # DW_AT_type
        .byte   0x1     # DW_AT_artificial

... which points to the integer base type:

        .uleb128 0x5    # (DIE (0x4b) DW_TAG_base_type)
        .byte   0x4     # DW_AT_byte_size
        .byte   0x5     # DW_AT_encoding
        .long   .LASF7  # DW_AT_name: "p__Tmy_integerB"
        .byte   0x1     # DW_AT_artificial

Ideally, it'd be better if variable I was described without the PAD
wrapper. We may be headed towards that in the long run, not sure.
But, in the meantime, I think the logical location for adding the
alignment info would probably be the PAD struct?
  
Mark Wielaard Sept. 29, 2014, 3:17 p.m. UTC | #9
Hi Joel,

My apologies it took so long before I made time to look at your example.

On Wed, 2014-07-30 at 09:59 -0700, Joel Brobecker wrote:
> > Could you post an example Ada source code example so I can test a
> > bit how my gcc and gdb patches interact for an user aligned Ada
> > type?
> 
> Here it is (credits to Eric Botcazou):
> 
>         package P is
> 
>           type My_Integer is new Integer;
>           for My_Integer'Alignment use 1;
> 
>           C : Character;
>           I : My_Integer;
> 
>         end P;
> 
> Save the code in a file called p.ads, and then compile it using:
> 
>         % gcc -c -g p.ads

Thanks. I used
https://gcc.gnu.org/onlinedocs/gnat_ugn_unw/Running-a-Program-with-Multiple-Units.html to play a bit with it and get something I could inspect under GDB.

I think I see now what you mean with not having alignment needing to be
stricter for sub types in Ada.

    type Another_Integer is new My_Integer;
    for Another_Integer'Alignment use 8;

    type Your_Integer is new Another_Integer;
    for Your_Integer'Alignment use 4;

    C : Character;
    I : My_Integer;
    C2 : Character;
    I2 : Another_Integer;
    C3 : Character;
    I3 : Your_Integer;

Adding some variables of different subtypes shows the compiler uses the
actual user defined aligned, not the the strictest alignment possible
according to the type hierarchy when multiple are defined. On the other
hand, in Ada you don't seem to be able to add the alignment aspect for a
specific type multiple times as you can in C. But at least usage of
"strictest alignment" wording can be a little confusing in this case.

Something that does surprise me is that ptype in gdb seems to always
just give the valid subrange of the variables I, I2, I3, not their
actual type.

(gdb) ptype P.I3
type = range -2147483648 .. 2147483647

While my changes for C types were so that ptype would produce a type
that you could in theory just pass into the compiler again to get you
the same thing. Is the above a deliberate choice for Ada? Hmmm, it seems
the above "type Another_Integer is new My_Integer" construct does not
result in any DWARF output that would make it possible to say
Another_Integer is a subtype of My_Integer?

> Variable "C" is just there to prevent variable "I" from being
> default-aligned by accident.
> 
> If you look at the debugging info, you'll find that our variable
> is called "p__i". The alignment is handled via putting it inside
> a ___PAD struct as a component called "F". Eg:
> 
>         .uleb128 0x6    # (DIE (0x70) DW_TAG_variable)
>         .long   .LASF1  # DW_AT_name: "p__i"
>         .long   0x1d    # DW_AT_type
> 
> Following the type of that variable gives us:
> 
>         .uleb128 0x2    # (DIE (0x1d) DW_TAG_structure_type)
>         .long   .LASF5  # DW_AT_name: "p__my_integer___PAD"
>         [...]
>         .uleb128 0x3    # (DIE (0x29) DW_TAG_member)
>         .ascii "F\0"    # DW_AT_name
>         .long   0x38    # DW_AT_type
> 
> Following then the type of member "F" yields a subrange type:
> 
>         .uleb128 0x4    # (DIE (0x38) DW_TAG_subrange_type)
>         .long   0x80000000      # DW_AT_lower_bound
>         .long   0x7fffffff      # DW_AT_upper_bound
>         .long   .LASF6  # DW_AT_name: "p__my_integer"
>         .long   0x4b    # DW_AT_type
>         .byte   0x1     # DW_AT_artificial
> 
> ... which points to the integer base type:
> 
>         .uleb128 0x5    # (DIE (0x4b) DW_TAG_base_type)
>         .byte   0x4     # DW_AT_byte_size
>         .byte   0x5     # DW_AT_encoding
>         .long   .LASF7  # DW_AT_name: "p__Tmy_integerB"
>         .byte   0x1     # DW_AT_artificial
> 
> Ideally, it'd be better if variable I was described without the PAD
> wrapper. We may be headed towards that in the long run, not sure.
> But, in the meantime, I think the logical location for adding the
> alignment info would probably be the PAD struct?

In my example above do see a PAD for some (the first) variable type, but
not others. Those just point directly to the named DW_TAG_subrange_type.
I think I would expect it to be on the (named) subrange_type either
inside or outside the "PAD" (what does that stand for BTW?) struct.

Thanks,

Mark
  
Joel Brobecker Oct. 2, 2014, 5:08 p.m. UTC | #10
> My apologies it took so long before I made time to look at your example.

No worries. I have been busy too! (still am :-)).

> Something that does surprise me is that ptype in gdb seems to always
> just give the valid subrange of the variables I, I2, I3, not their
> actual type.
> 
> (gdb) ptype P.I3
> type = range -2147483648 .. 2147483647

That's typical for an integral type described as a subrange of
another type. I don't know that you can actually get access to
the subtype from the debugger, but you can use "whatis" to get
the name of the type instead of the range, and you can also use
the 'size attribute if, what you're looking for, is the size
of the type.

    (gdb) p p.i3'size
    $1 = 32
    (gdb) whatis p.i3
    type = p.your_integer

> While my changes for C types were so that ptype would produce a type
> that you could in theory just pass into the compiler again to get you
> the same thing. Is the above a deliberate choice for Ada? Hmmm, it seems
> the above "type Another_Integer is new My_Integer" construct does not
> result in any DWARF output that would make it possible to say
> Another_Integer is a subtype of My_Integer?

The Ada mode, as currently implemented, does not try to do that, no.

Note that, technically speaking, in the example above, Another_Integer
is _not_ a subtype of My_Integer, but a logically distinct types.
If you try to assign a value of type My_Integer to a variable of
type Another_Integer without an explicit type conversion, the compiler
should fail. To create a subtype, we use the subtype keyword. Eg:

    subtype Full_Type is My_Integer;

Or, if you want to add constraints to your subtype:

    subtype Positive_Type is My_Integer range 1 .. My_Integer'Last;

Regardless, I believe that at the debugging info level, both full
(new) type and subtypes are described the same way. So I don't see
us handling both differently for the time being.

> In my example above do see a PAD for some (the first) variable type, but
> not others. Those just point directly to the named DW_TAG_subrange_type.
> I think I would expect it to be on the (named) subrange_type either
> inside or outside the "PAD" (what does that stand for BTW?) struct.

That's a tricky question for me to answer. The scenario I have in
mind where this is going to be particularly useful is when trying
to call a function from the debugger with one of the parameters having
a non-standard alignment. I would be easier to handle if the PAD type
was the type with the alignment info, but I think it's just a detail
that we can deal with later on.

I am not sure whether PAD stands for anything other than "padding".
BMT (Before My Time)! :-)
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 08fba63..cd7d3ed 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,24 @@ 
+2014-07-09  Mark Wielaard  <mjw@redhat.com>
+
+	* c-typeprint.c (cp_type_print_method_args): Handle TYPE_USER_ALIGN.
+	(c_type_print_varspec_prefix): Likewise.
+	(c_type_print_modifier): Likewise.
+	* dwarf2read.c (add_array_cv_aligned_type): New function.
+	(read_tag_aligned_type): Likewise.
+	(read_type_die_1): Handle DW_TAG_aligned_type.
+	* gdbtypes.c (make_qualified_type): Calls...
+	(make_qualified_aligned_type): New function that handles user
+	alignment.
+	(make_aligned_type): New function.
+	(check_typedef): Handle TYPE_USER_ALIGN.
+	(check_types_equal): Likewise.
+	(recursive_dump_type): Likewise.
+	(copy_type_recursive): Likewise.
+	(copy_type): Likewise.
+	* gdbtypes.h (struct type): Add user_align.
+	(TYPE_USER_ALIGN): New define.
+	(make_aligned_type): Define.
+
 2014-07-08  Markus Metzger  <markus.t.metzger@intel.com>
 
 	* infcmd.c (finish_backward): Turn internal error into normal error.
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 72effce..501a994 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -275,6 +275,9 @@  cp_type_print_method_args (struct type *mtype, const char *prefix,
 
       if (TYPE_ATOMIC (domain))
 	fprintf_filtered (stream, " _Atomic");
+
+      if (TYPE_USER_ALIGN (domain) != 0)
+	fprintf_filtered (stream, " _Alignas (%u)", TYPE_USER_ALIGN (domain));
     }
 }
 
@@ -313,6 +316,9 @@  c_type_print_varspec_prefix (struct type *type,
     case TYPE_CODE_PTR:
       c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type),
 				   stream, show, 1, 1, flags);
+      /* _Alignas comes before the "*' pointer unlike the other modifiers.  */
+      if (TYPE_USER_ALIGN (type) != 0)
+	fprintf_filtered (stream, " _Alignas (%u) ", TYPE_USER_ALIGN (type));
       fprintf_filtered (stream, "*");
       c_type_print_modifier (type, stream, 1, need_post_space);
       break;
@@ -394,8 +400,8 @@  c_type_print_varspec_prefix (struct type *type,
     }
 }
 
-/* Print out "const" and "volatile" attributes,
-   and address space id if present.
+/* Print out "const", "volatile", "restrict", "_Atomic" and "_Alignas"
+   attributes, and address space id if present.
    TYPE is a pointer to the type being printed out.
    STREAM is the output destination.
    NEED_PRE_SPACE = 1 indicates an initial white space is needed.
@@ -444,6 +450,15 @@  c_type_print_modifier (struct type *type, struct ui_file *stream,
       did_print_modifier = 1;
     }
 
+  /* For pointers the _Alignas comes before the '*'.  */
+  if (TYPE_USER_ALIGN (type) != 0 && TYPE_CODE (type) != TYPE_CODE_PTR)
+    {
+      if (did_print_modifier || need_pre_space)
+	fprintf_filtered (stream, " ");
+      fprintf_filtered (stream, "_Alignas (%u)", TYPE_USER_ALIGN (type));
+      did_print_modifier = 1;
+    }
+
   address_space_id = address_space_int_to_name (get_type_arch (type),
 						TYPE_INSTANCE_FLAGS (type));
   if (address_space_id)
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 614d6b9..ee3dc1c 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14128,6 +14128,33 @@  add_array_cv_type (struct die_info *die, struct dwarf2_cu *cu,
   return set_die_type (die, base_type, cu);
 }
 
+/* Add the given user alignment to the element type of the array.  GCC
+   outputs DWARF type qualifiers that apply to an array, not the
+   element type.  But GDB relies on the array element type to carry
+   the cv-qualifiers.  This is mimics section 6.7.3, point 9 of the
+   C11 specification (n1570).  */
+static struct type *
+add_array_cv_aligned_type (struct die_info *die, struct dwarf2_cu *cu,
+			   struct type *base_type, unsigned int user_align)
+{
+  struct type *el_type, *inner_array;
+
+  base_type = copy_type (base_type);
+  inner_array = base_type;
+
+  while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
+    {
+      TYPE_TARGET_TYPE (inner_array) =
+	copy_type (TYPE_TARGET_TYPE (inner_array));
+      inner_array = TYPE_TARGET_TYPE (inner_array);
+    }
+
+  el_type = TYPE_TARGET_TYPE (inner_array);
+  TYPE_TARGET_TYPE (inner_array) = make_aligned_type (el_type, user_align);
+
+  return set_die_type (die, base_type, cu);
+}
+
 static struct type *
 read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
 {
@@ -14205,6 +14232,34 @@  read_tag_atomic_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, cv_type, cu);
 }
 
+static struct type *
+read_tag_aligned_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct type *base_type, *align_type;
+  struct attribute *attr;
+  unsigned int user_align = 0;
+
+  base_type = die_type (die, cu);
+
+  /* The die_type call above may have already set the type for this DIE.  */
+  align_type = get_die_type (die, cu);
+  if (align_type)
+    return align_type;
+
+  attr = dwarf2_attr (die, DW_AT_alignment, cu);
+  if (attr)
+    user_align = DW_UNSND (attr);
+
+  /* In case the _Alignas qualifier is applied to an array type, the
+     element type is so qualified, not the array type (section 6.7.3
+     of C99).  */
+  if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
+    return add_array_cv_aligned_type (die, cu, base_type, user_align);
+
+  align_type = make_aligned_type (base_type, user_align);
+  return set_die_type (die, align_type, cu);
+}
+
 /* Extract all information from a DW_TAG_string_type DIE and add to
    the user defined type vector.  It isn't really a user defined type,
    but it behaves like one, with other DIE's using an AT_user_def_type
@@ -18538,6 +18593,9 @@  read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_atomic_type:
       this_type = read_tag_atomic_type (die, cu);
       break;
+    case DW_TAG_aligned_type:
+      this_type = read_tag_aligned_type (die, cu);
+      break;
     default:
       complaint (&symfile_complaints,
 		 _("unexpected tag in read_type_die: '%s'"),
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 42ff588..e12dec7 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -565,21 +565,23 @@  address_space_int_to_name (struct gdbarch *gdbarch, int space_flag)
     return NULL;
 }
 
-/* Create a new type with instance flags NEW_FLAGS, based on TYPE.
+/* Create a new type with instance flags NEW_FLAGS, and NEW_ALIGN (if
+   stricter) based on TYPE.
 
    If STORAGE is non-NULL, create the new type instance there.
    STORAGE must be in the same obstack as TYPE.  */
 
 static struct type *
-make_qualified_type (struct type *type, int new_flags,
-		     struct type *storage)
+make_qualified_aligned_type (struct type *type, int new_flags,
+			     unsigned int new_align, struct type *storage)
 {
   struct type *ntype;
 
   ntype = type;
   do
     {
-      if (TYPE_INSTANCE_FLAGS (ntype) == new_flags)
+      if (TYPE_INSTANCE_FLAGS (ntype) == new_flags
+	  && TYPE_USER_ALIGN (ntype) == new_align)
 	return ntype;
       ntype = TYPE_CHAIN (ntype);
     }
@@ -616,9 +618,25 @@  make_qualified_type (struct type *type, int new_flags,
   /* Set length of new type to that of the original type.  */
   TYPE_LENGTH (ntype) = TYPE_LENGTH (type);
 
+  /* If new user alignment is stricter (bigger) than the original type
+     then use it, otherwise take the user alignment of the original
+     type.  */
+  if (new_align > TYPE_USER_ALIGN (type))
+    TYPE_USER_ALIGN (ntype) = new_align;
+  else
+    TYPE_USER_ALIGN (ntype) = TYPE_USER_ALIGN (type);
+
   return ntype;
 }
 
+static struct type *
+make_qualified_type (struct type *type, int new_flags,
+		     struct type *storage)
+{
+  return make_qualified_aligned_type (type, new_flags,
+				      TYPE_USER_ALIGN (type), storage);
+}
+
 /* Make an address-space-delimited variant of a type -- a type that
    is identical to the one supplied except that it has an address
    space attribute attached to it (such as "code" or "data").
@@ -717,6 +735,19 @@  make_atomic_type (struct type *type)
 			      NULL);
 }
 
+/* Make a '_Alignas'-qualified version of TYPE (if user_align is
+   stricter than the user alignment of TYPE).  */
+
+struct type *
+make_aligned_type (struct type *type, unsigned int user_align)
+{
+  if (user_align > TYPE_USER_ALIGN (type))
+    return make_qualified_aligned_type (type, TYPE_INSTANCE_FLAGS (type),
+					user_align, NULL);
+  else
+    return type;
+}
+
 /* Replace the contents of ntype with the type *type.  This changes the
    contents, rather than the pointer for TYPE_MAIN_TYPE (ntype); thus
    the changes are propogated to all types in the TYPE_CHAIN.
@@ -1888,9 +1919,9 @@  resolve_dynamic_type (struct type *type, CORE_ADDR addr)
    types.  Completion changes the TYPE argument, but stripping of
    typedefs does not.
 
-   Instance flags (e.g. const/volatile) are preserved as typedefs are
-   stripped.  If necessary a new qualified form of the underlying type
-   is created.
+   Instance flags (e.g. const/volatile/restrict) are preserved as typedefs
+   are stripped.  And user alignment is resolved to the strictest alignment.
+   If necessary a new qualified form of the underlying type is created.
 
    NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
    not been computed and we're either in the middle of reading symbols, or
@@ -1916,8 +1947,9 @@  check_typedef (struct type *type)
 {
   struct type *orig_type = type;
   /* While we're removing typedefs, we don't want to lose qualifiers.
-     E.g., const/volatile.  */
+     E.g., const/volatile/restrict.  Or the (strictest) user alignment.  */
   int instance_flags = TYPE_INSTANCE_FLAGS (type);
+  unsigned int user_align = TYPE_USER_ALIGN (type);
 
   gdb_assert (type);
 
@@ -1931,7 +1963,8 @@  check_typedef (struct type *type)
 	  /* It is dangerous to call lookup_symbol if we are currently
 	     reading a symtab.  Infinite recursion is one danger.  */
 	  if (currently_reading_symtab)
-	    return make_qualified_type (type, instance_flags, NULL);
+	    return make_qualified_aligned_type (type, instance_flags,
+						user_align, NULL);
 
 	  name = type_name_no_tag (type);
 	  /* FIXME: shouldn't we separately check the TYPE_NAME and
@@ -1941,7 +1974,8 @@  check_typedef (struct type *type)
 	  if (name == NULL)
 	    {
 	      stub_noname_complaint ();
-	      return make_qualified_type (type, instance_flags, NULL);
+	      return make_qualified_aligned_type (type, instance_flags,
+						  user_align, NULL);
 	    }
 	  sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
 	  if (sym)
@@ -1967,6 +2001,7 @@  check_typedef (struct type *type)
 				| TYPE_INSTANCE_FLAG_DATA_SPACE);
 	const int ALL_CLASSES = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL;
 	int new_instance_flags = TYPE_INSTANCE_FLAGS (type);
+	int new_user_align = TYPE_USER_ALIGN (type);
 
 	/* Treat code vs data spaces and address classes separately.  */
 	if ((instance_flags & ALL_SPACES) != 0)
@@ -1975,6 +2010,8 @@  check_typedef (struct type *type)
 	  new_instance_flags &= ~ALL_CLASSES;
 
 	instance_flags |= new_instance_flags;
+	if (new_user_align > user_align)
+	  user_align = new_user_align;
       }
     }
 
@@ -1994,7 +2031,8 @@  check_typedef (struct type *type)
       if (name == NULL)
 	{
 	  stub_noname_complaint ();
-	  return make_qualified_type (type, instance_flags, NULL);
+	  return make_qualified_aligned_type (type, instance_flags,
+					      user_align, NULL);
 	}
       newtype = lookup_transparent_type (name);
 
@@ -2011,9 +2049,10 @@  check_typedef (struct type *type)
 	     move over any other types NEWTYPE refers to, which could
 	     be an unbounded amount of stuff.  */
 	  if (TYPE_OBJFILE (newtype) == TYPE_OBJFILE (type))
-	    type = make_qualified_type (newtype,
-					TYPE_INSTANCE_FLAGS (type),
-					type);
+	    type = make_qualified_aligned_type (newtype,
+						TYPE_INSTANCE_FLAGS (type),
+						TYPE_USER_ALIGN (type),
+						type);
 	  else
 	    type = newtype;
 	}
@@ -2032,7 +2071,8 @@  check_typedef (struct type *type)
       if (name == NULL)
 	{
 	  stub_noname_complaint ();
-	  return make_qualified_type (type, instance_flags, NULL);
+	  return make_qualified_aligned_type (type, instance_flags,
+					      user_align, NULL);
 	}
       sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
       if (sym)
@@ -2041,9 +2081,10 @@  check_typedef (struct type *type)
              with the complete type only if they are in the same
              objfile.  */
 	  if (TYPE_OBJFILE (SYMBOL_TYPE(sym)) == TYPE_OBJFILE (type))
-            type = make_qualified_type (SYMBOL_TYPE (sym),
-					TYPE_INSTANCE_FLAGS (type),
-					type);
+            type = make_qualified_aligned_type (SYMBOL_TYPE (sym),
+						TYPE_INSTANCE_FLAGS (type),
+						TYPE_USER_ALIGN (type),
+						type);
 	  else
 	    type = SYMBOL_TYPE (sym);
         }
@@ -2065,7 +2106,7 @@  check_typedef (struct type *type)
 	}
     }
 
-  type = make_qualified_type (type, instance_flags, NULL);
+  type = make_qualified_aligned_type (type, instance_flags, user_align, NULL);
 
   /* Cache TYPE_LENGTH for future use.  */
   TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
@@ -2881,7 +2922,8 @@  check_types_equal (struct type *type1, struct type *type2,
       || TYPE_VECTOR (type1) != TYPE_VECTOR (type2)
       || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2)
       || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2)
-      || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
+      || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2)
+      || TYPE_USER_ALIGN (type1) != TYPE_USER_ALIGN (type2))
     return 0;
 
   if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1),
@@ -3800,6 +3842,10 @@  recursive_dump_type (struct type *type, int spaces)
     {
       puts_filtered (" TYPE_FLAG_ATOMIC");
     }
+  if (TYPE_USER_ALIGN (type) != 0)
+    {
+      printf_filtered (" TYPE_USER_ALIGN (%u)", TYPE_USER_ALIGN (type));
+    }
   puts_filtered ("\n");
 
   printfi_filtered (spaces, "flags");
@@ -4038,6 +4084,7 @@  copy_type_recursive (struct objfile *objfile,
     TYPE_TAG_NAME (new_type) = xstrdup (TYPE_TAG_NAME (type));
 
   TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type);
+  TYPE_USER_ALIGN (new_type) = TYPE_USER_ALIGN (type);
   TYPE_LENGTH (new_type) = TYPE_LENGTH (type);
 
   /* Copy the fields.  */
@@ -4135,6 +4182,7 @@  copy_type (const struct type *type)
 
   new_type = alloc_type_copy (type);
   TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type);
+  TYPE_USER_ALIGN (new_type) = TYPE_USER_ALIGN (type);
   TYPE_LENGTH (new_type) = TYPE_LENGTH (type);
   memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type),
 	  sizeof (struct main_type));
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 03468f8..8d70e6b 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -752,10 +752,10 @@  struct type
 
   /* * Variant chain.  This points to a type that differs from this
      one only in qualifiers and length.  Currently, the possible
-     qualifiers are const, volatile, code-space, data-space, and
-     address class.  The length may differ only when one of the
-     address class flags are set.  The variants are linked in a
-     circular ring and share MAIN_TYPE.  */
+     qualifiers are const, volatile, restrict, code-space, data-space,
+     address class and use alignment.  The length may differ only when
+     one of the address class flags are set.  The variants are linked
+     in a circular ring and share MAIN_TYPE.  */
 
   struct type *chain;
 
@@ -797,6 +797,12 @@  struct type
   
   unsigned length;
 
+  /* * User alignment of this type.  This is what alignof(type) would
+     return when explicitly set by the user with c11 _Alignas or
+     __attribute__ ((aligned (X)).  If not explicitly set by the user
+     it is zero and the default alignment would apply.  */
+  unsigned user_align;
+
   /* * Core type, shared by a group of qualified types.  */
 
   struct main_type *main_type;
@@ -1195,6 +1201,7 @@  extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_CODE(thistype) TYPE_MAIN_TYPE(thistype)->code
 #define TYPE_NFIELDS(thistype) TYPE_MAIN_TYPE(thistype)->nfields
 #define TYPE_FIELDS(thistype) TYPE_MAIN_TYPE(thistype)->flds_bnds.fields
+#define TYPE_USER_ALIGN(thistype) (thistype)->user_align
 
 #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
 #define TYPE_RANGE_DATA(thistype) TYPE_MAIN_TYPE(thistype)->flds_bnds.bounds
@@ -1636,6 +1643,8 @@  extern struct type *make_restrict_type (struct type *);
 
 extern struct type *make_atomic_type (struct type *);
 
+extern struct type *make_aligned_type (struct type *, unsigned int);
+
 extern void replace_type (struct type *, struct type *);
 
 extern int address_space_name_to_int (struct gdbarch *, char *);
diff --git a/include/ChangeLog b/include/ChangeLog
index 23f27a9..30d82a2 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@ 
+2014-07-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2.def: Add DW_TAG_aligned_type and DW_AT_alignment.
+
 2014-06-22  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf2.def: Add DW_TAG_atomic_type.
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 6941922..1b34623 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -135,6 +135,7 @@  DW_TAG (DW_TAG_rvalue_reference_type, 0x42)
 DW_TAG (DW_TAG_template_alias, 0x43)
 /* DWARF 5.  */
 DW_TAG (DW_TAG_atomic_type, 0x47)
+DW_TAG (DW_TAG_aligned_type, 0x48) /* XXX not yet assigned constant.  */
 
 DW_TAG_DUP (DW_TAG_lo_user, 0x4080)
 DW_TAG_DUP (DW_TAG_hi_user, 0xffff)
@@ -310,6 +311,8 @@  DW_AT (DW_AT_data_bit_offset, 0x6b)
 DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
+/* DWARF 5.  */
+DW_TAG (DW_AT_alignment, 0x6f) /* XXX not yet assigned constant.  */
 
 DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */
 DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end.  */