diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1b5abb2f0d..73eba465a1 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2018-04-27  Tom Tromey  <tom@tromey.com>
+
+	PR exp/17095:
+	* NEWS: Update.
+	* std-operator.def (UNOP_ALIGNOF): New operator.
+	* expprint.c (dump_subexp_body_standard) <case UNOP_ALIGNOF>:
+	New.
+	* eval.c (evaluate_subexp_standard) <case UNOP_ALIGNOF>: New.
+	* c-lang.c (c_op_print_tab): Add alignof.
+	* c-exp.y (ALIGNOF): New token.
+	(exp): Add "ALIGNOF" production.
+	(ident_tokens): Add _Alignof and alignof.
+
 2018-04-27  Tom Tromey  <tom@tromey.com>
 
 	* i386-tdep.c (i386_type_align): New function.
diff --git a/gdb/NEWS b/gdb/NEWS
index 63fe30d175..6631b53475 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -9,6 +9,9 @@
 * 'info proc' now works on running processes on FreeBSD systems and core
   files created on FreeBSD systems.
 
+* C expressions can now use _Alignof, and C++ expressions can now use
+  alignof.
+
 * New commands
 
 set debug fbsd-nat
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 9e2f80889f..3cee544106 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -173,7 +173,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 %token <ssym> NAME_OR_INT
 
 %token OPERATOR
-%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token STRUCT CLASS UNION ENUM SIZEOF ALIGNOF UNSIGNED COLONCOLON
 %token TEMPLATE
 %token ERROR
 %token NEW DELETE
@@ -307,6 +307,10 @@ exp	:	SIZEOF exp       %prec UNARY
 			{ write_exp_elt_opcode (pstate, UNOP_SIZEOF); }
 	;
 
+exp	:	ALIGNOF '(' type_exp ')'	%prec UNARY
+			{ write_exp_elt_opcode (pstate, UNOP_ALIGNOF); }
+	;
+
 exp	:	exp ARROW name
 			{ write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 			  write_exp_string (pstate, $3);
@@ -2329,6 +2333,8 @@ static const struct token ident_tokens[] =
     {"struct", STRUCT, OP_NULL, 0},
     {"signed", SIGNED_KEYWORD, OP_NULL, 0},
     {"sizeof", SIZEOF, OP_NULL, 0},
+    {"_Alignof", ALIGNOF, OP_NULL, 0},
+    {"alignof", ALIGNOF, OP_NULL, FLAG_CXX},
     {"double", DOUBLE_KEYWORD, OP_NULL, 0},
     {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX},
     {"class", CLASS, OP_NULL, FLAG_CXX},
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 658c7f7826..15e633f8c8 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -751,6 +751,7 @@ const struct op_print c_op_print_tab[] =
   {"*", UNOP_IND, PREC_PREFIX, 0},
   {"&", UNOP_ADDR, PREC_PREFIX, 0},
   {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"alignof ", UNOP_ALIGNOF, PREC_PREFIX, 0},
   {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
   {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
   {NULL, OP_NULL, PREC_PREFIX, 0}
diff --git a/gdb/eval.c b/gdb/eval.c
index ad66f7c32c..2fdfdf9353 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -2667,6 +2667,19 @@ evaluate_subexp_standard (struct type *expect_type,
 	}
       return evaluate_subexp_for_sizeof (exp, pos, noside);
 
+    case UNOP_ALIGNOF:
+      {
+	struct type *type
+	  = value_type (evaluate_subexp (NULL_TYPE, exp, pos,
+					 EVAL_AVOID_SIDE_EFFECTS));
+	/* FIXME: This should be size_t.  */
+	struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
+	ULONGEST align = type_align (type);
+	if (align == 0)
+	  error (_("could not determine alignment of type"));
+	return value_from_longest (size_type, align);
+      }
+
     case UNOP_CAST:
       (*pos) += 2;
       type = exp->elts[pc + 1].type;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index c906904599..5985f70a8f 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -846,6 +846,7 @@ dump_subexp_body_standard (struct expression *exp,
     case UNOP_PREDECREMENT:
     case UNOP_POSTDECREMENT:
     case UNOP_SIZEOF:
+    case UNOP_ALIGNOF:
     case UNOP_PLUS:
     case UNOP_CAP:
     case UNOP_CHR:
diff --git a/gdb/std-operator.def b/gdb/std-operator.def
index 87bb518877..1297c1edeb 100644
--- a/gdb/std-operator.def
+++ b/gdb/std-operator.def
@@ -234,6 +234,7 @@ OP (UNOP_POSTINCREMENT)		/* ++ after an expression */
 OP (UNOP_PREDECREMENT)		/* -- before an expression */
 OP (UNOP_POSTDECREMENT)		/* -- after an expression */
 OP (UNOP_SIZEOF)		/* Unary sizeof (followed by expression) */
+OP (UNOP_ALIGNOF)		/* Unary alignof (followed by expression) */
 
 OP (UNOP_PLUS)			/* Unary plus */
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 34da102c62..6909e8e0b1 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2018-04-27  Tom Tromey  <tom@tromey.com>
+
+	PR exp/17095:
+	* gdb.dwarf2/dw2-align.exp: New file.
+	* gdb.cp/align.exp: New file.
+	* gdb.base/align.exp: New file.
+
 2018-04-26  Pedro Alves  <palves@redhat.com>
 
 	* gdb.base/gnu-ifunc.exp (set-break): Test that GDB resolves
diff --git a/gdb/testsuite/gdb.base/align.exp b/gdb/testsuite/gdb.base/align.exp
new file mode 100644
index 0000000000..6c13e24106
--- /dev/null
+++ b/gdb/testsuite/gdb.base/align.exp
@@ -0,0 +1,101 @@
+# Copyright 2018 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
+
+# This tests that C11 _Alignof works in gdb, and that it agrees with
+# the compiler.
+
+# The types we're going to test.
+
+set typelist {
+    char {unsigned char}
+    short {unsigned short}
+    int {unsigned int}
+    long {unsigned long}
+    {long long} {unsigned long long}
+    float
+    double {long double}
+}
+
+# Create the test file.
+
+set filename [standard_output_file align.c]
+set outfile [open $filename w]
+
+# Prologue.
+puts -nonewline $outfile "#define DEF(T,U) struct align_pair_ ## T ## _x_ ## U "
+puts $outfile "{ T one; U two; }"
+puts $outfile "unsigned a_void = _Alignof(void);"
+
+# First emit single items.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    if {$type != $utype} {
+	puts $outfile "typedef $type $utype;"
+    }
+    puts $outfile "$type item_$utype;"
+    puts $outfile "unsigned a_$utype\n  = _Alignof ($type);"
+    set utype [join [split $type] _]
+}
+
+# Now emit all pairs.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	puts $outfile "DEF ($utype, $uinner);"
+	set joined "${utype}_x_${uinner}"
+	puts $outfile "struct align_pair_$joined item_${joined};"
+	puts $outfile "unsigned a_${joined}"
+	puts $outfile "  = _Alignof (struct align_pair_${joined});"
+    }
+}
+
+# Epilogue.
+puts $outfile {
+    int main() {
+	return 0;
+    }
+}
+
+close $outfile
+
+standard_testfile $filename
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    perror "test suppressed"
+    return
+}
+
+foreach type $typelist {
+    set utype [join [split $type] _]
+    set expected [get_integer_valueof a_$utype 0]
+    gdb_test "print _Alignof($type)" " = $expected"
+
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	set expected [get_integer_valueof a_${utype}_x_${uinner} 0]
+	gdb_test "print _Alignof(struct align_pair_${utype}_x_${uinner})" \
+	    " = $expected"
+    }
+}
+
+set expected [get_integer_valueof a_void 0]
+gdb_test "print _Alignof(void)" " = $expected"
diff --git a/gdb/testsuite/gdb.cp/align.exp b/gdb/testsuite/gdb.cp/align.exp
new file mode 100644
index 0000000000..fb5fb46a07
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/align.exp
@@ -0,0 +1,145 @@
+# Copyright 2018 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
+
+# This tests that C++ alignof works in gdb, and that it agrees with
+# the compiler.
+
+if {[skip_cplus_tests]} { continue }
+
+# The types we're going to test.
+
+set typelist {
+    char {unsigned char}
+    short {unsigned short}
+    int {unsigned int}
+    long {unsigned long}
+    {long long} {unsigned long long}
+    float
+    double {long double}
+    empty
+    bigenum
+    vstruct
+    bfstruct
+    arrstruct
+}
+
+# Create the test file.
+
+set filename [standard_output_file align.cc]
+set outfile [open $filename w]
+
+# Prologue.
+puts $outfile {
+    template<typename T, typename U>
+    struct align_pair
+    {
+	T one;
+	U two;
+    };
+
+    template<typename T, typename U>
+    struct align_union
+    {
+	T one;
+	U two;
+    };
+
+    enum bigenum { VALUE = 0xffffffffull };
+
+    struct empty { };
+
+    struct vstruct { virtual ~vstruct() {}  char c; };
+
+    struct bfstruct { unsigned b : 3; };
+
+    struct arrstruct { short fld[7]; };
+}
+
+# First emit single items.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    puts $outfile "$type item_$utype;"
+    puts $outfile "unsigned a_$utype\n  = alignof ($type);"
+    puts $outfile "typedef $type t_$utype;"
+    puts $outfile "t_$utype item_t_$utype;"
+}
+
+# Now emit all pairs.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	puts $outfile "align_pair<$type, $inner> item_${utype}_x_${uinner};"
+	puts $outfile "unsigned a_${utype}_x_${uinner}"
+	puts $outfile "  = alignof (align_pair<$type, $inner>);"
+
+	puts $outfile "align_union<$type, $inner> item_${utype}_u_${uinner};"
+	puts $outfile "unsigned a_${utype}_u_${uinner}"
+	puts $outfile "  = alignof (align_union<$type, $inner>);"
+    }
+}
+
+# Epilogue.
+puts $outfile {
+    int main() {
+	return 0;
+    }
+}
+
+close $outfile
+
+standard_testfile $filename
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
+	 {debug c++ additional_flags=-std=c++11}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    perror "test suppressed"
+    return
+}
+
+proc maybe_xfail {type} {
+    # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560
+    # The g++ implementation of alignof is changing to match C11.
+    if {[is_x86_like_target]
+	&& ($type == "double" || $type == "long long"
+	    || $type == "unsigned long long")} {
+	setup_xfail *-*-*
+    }
+}
+
+foreach type $typelist {
+    set utype [join [split $type] _]
+    set expected [get_integer_valueof a_$utype 0]
+
+    maybe_xfail $type
+    gdb_test "print alignof($type)" " = $expected"
+
+    maybe_xfail $type
+    gdb_test "print alignof(t_$utype)" " = $expected"
+
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	set expected [get_integer_valueof a_${utype}_x_${uinner} 0]
+	gdb_test "print alignof(align_pair<${type},${inner}>)" " = $expected"
+
+	set expected [get_integer_valueof a_${utype}_u_${uinner} 0]
+	gdb_test "print alignof(align_union<${type},${inner}>)" " = $expected"
+    }
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-align.exp b/gdb/testsuite/gdb.dwarf2/dw2-align.exp
new file mode 100644
index 0000000000..2c2faf7591
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-align.exp
@@ -0,0 +1,83 @@
+# Copyright 2018 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/>.
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile main.c align-dw.S
+
+# Make some DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    global srcdir subdir srcfile
+
+    cu {} {
+	DW_TAG_compile_unit {
+                {DW_AT_language @DW_LANG_C_plus_plus}
+                {DW_AT_name     dw2-align.c}
+                {DW_AT_comp_dir /tmp}
+        } {
+	    declare_labels itype ptype
+
+            itype: DW_TAG_base_type {
+                {DW_AT_byte_size 4 DW_FORM_sdata}
+                {DW_AT_encoding  @DW_ATE_signed}
+                {DW_AT_name int_4096}
+		{DW_AT_alignment 4096 DW_FORM_sdata}
+            }
+
+            ptype: DW_TAG_pointer_type {
+                {DW_AT_byte_size 8 DW_FORM_sdata}
+                {DW_AT_type :$itype}
+		{DW_AT_alignment 4096 DW_FORM_sdata}
+            }
+
+            DW_TAG_typedef {
+                {DW_AT_name ptr_4096}
+                {DW_AT_type :$ptype}
+            }
+
+	    DW_TAG_structure_type {
+		{DW_AT_name "struct_4096"}
+		{DW_AT_byte_size 4096 DW_FORM_sdata}
+		{DW_AT_alignment 4096 DW_FORM_udata}
+	    } {
+		member {
+		    {name a}
+		    {type :$itype}
+		    {data_member_location 0 data1}
+		}
+	    }
+	}
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test_no_output "set lang c++"
+gdb_test "print alignof(int_4096)" " = 4096"
+gdb_test "print alignof(ptr_4096)" " = 4096"
+gdb_test "print alignof(struct_4096)" " = 4096"
