diff mbox

C1X _Noreturn

Message ID Pine.LNX.4.64.1108182136000.20343@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Aug. 18, 2011, 9:37 p.m. UTC
C1X provides a standard way of declaring non-returning functions, with
the _Noreturn keyword and a header stdnoreturn.h defining a macro
"noreturn" to expand to _Noreturn.  This patch implements this syntax
and header.  Bootstrapped with no regressions on
x86_64-unknown-linux-gnu.  Applied to mainline.

I didn't touch the USER_H definition in mips/t-sdemtk (so that target
will not install this new header).  The comment "Remove stdarg.h and
stddef.h from USER_H." suggests that maybe it should be added to that
definition, but stdfix.h is also missing from that definition.  As far
as I know MIPS is no longer using the old SDE library and it is
considered superseded by newlib, so perhaps that configuration
(mips*-sde-elf* without newlib) should actually be deprecated/removed
(and "mipssde" threads along with it).

The new keyword is C-only (C++0x has a different way of declaring
non-returning functions) and I did not try to make the header do
anything useful if included in C++ code.

2011-08-18  Joseph Myers  <joseph@codesourcery.com>

	* c-decl.c (shadow_tag_warned): Check for _Noreturn.
	(quals_from_declspecs): Assert _Noreturn not present.
	(grokdeclarator): Handle _Noreturn.
	(build_null_declspecs): Initialize noreturn_p.
	(declspecs_add_scspec): Handle RID_NORETURN.
	* c-parser.c (c_token_starts_declspecs, c_parser_declspecs)
	(c_parser_attributes): Handle RID_NORETURN.
	* c-tree.h (struct c_declspecs): Add noreturn_p.
	* ginclude/stdnoreturn.h: New.
	* Makefile.in (USER_H): Add stdnoreturn.h.

c-family:
2011-08-18  Joseph Myers  <joseph@codesourcery.com>

	* c-common.c (c_common_reswords): Add _Noreturn.
	(keyword_is_function_specifier): Handle RID_NORETURN.
	* c-common.h (RID_NORETURN): New.

testsuite:
2011-08-18  Joseph Myers  <joseph@codesourcery.com>

	* gcc.dg/c1x-noreturn-1.c, gcc.dg/c1x-noreturn-2.c,
	gcc.dg/c1x-noreturn-3.c, gcc.dg/c1x-noreturn-4.c,
	gcc.dg/c1x-noreturn-5.c: New tests.

Comments

Gabriel Dos Reis Aug. 18, 2011, 9:42 p.m. UTC | #1
On Thu, Aug 18, 2011 at 4:37 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:

> The new keyword is C-only (C++0x has a different way of declaring
> non-returning functions) and I did not try to make the header do
> anything useful if included in C++ code.

I would suggest you don't define it all as macro when __cplusplus is defined.
Richard Sandiford Aug. 19, 2011, 8:09 a.m. UTC | #2
"Joseph S. Myers" <joseph@codesourcery.com> writes:
> As far as I know MIPS is no longer using the old SDE library and it is
> considered superseded by newlib,

Hadn't realised that.

> so perhaps that configuration (mips*-sde-elf* without newlib) should
> actually be deprecated/removed (and "mipssde" threads along with it).

Yeah, sounds like a good plan.

Richard
Rainer Orth Aug. 19, 2011, 1:35 p.m. UTC | #3
Richard Sandiford <rdsandiford@googlemail.com> writes:

>> so perhaps that configuration (mips*-sde-elf* without newlib) should
>> actually be deprecated/removed (and "mipssde" threads along with it).
>
> Yeah, sounds like a good plan.

Good to know :-)  Could have saved me a little bit of work with the
libgcc patches.

	Rainer
Richard Sandiford Aug. 24, 2011, 8:59 a.m. UTC | #4
"Joseph S. Myers" <joseph@codesourcery.com> writes:
> I didn't touch the USER_H definition in mips/t-sdemtk (so that target
> will not install this new header).  The comment "Remove stdarg.h and
> stddef.h from USER_H." suggests that maybe it should be added to that
> definition, but stdfix.h is also missing from that definition.  As far
> as I know MIPS is no longer using the old SDE library and it is
> considered superseded by newlib, so perhaps that configuration
> (mips*-sde-elf* without newlib) should actually be deprecated/removed
> (and "mipssde" threads along with it).

BTW, do you know whether the same applies to -mno-float, which at the
moment is specific to sdemtk?  That option was never really implemented,
and just relied on the user being very, very careful.  It would be nice
to deprecate it at the same time.

If so, I'll do a patch this weekend to deprecate all three (the thread
model, the option, and the configuration).

Richard
Joseph Myers Aug. 24, 2011, 11:24 a.m. UTC | #5
On Wed, 24 Aug 2011, Richard Sandiford wrote:

> "Joseph S. Myers" <joseph@codesourcery.com> writes:
> > I didn't touch the USER_H definition in mips/t-sdemtk (so that target
> > will not install this new header).  The comment "Remove stdarg.h and
> > stddef.h from USER_H." suggests that maybe it should be added to that
> > definition, but stdfix.h is also missing from that definition.  As far
> > as I know MIPS is no longer using the old SDE library and it is
> > considered superseded by newlib, so perhaps that configuration
> > (mips*-sde-elf* without newlib) should actually be deprecated/removed
> > (and "mipssde" threads along with it).
> 
> BTW, do you know whether the same applies to -mno-float, which at the
> moment is specific to sdemtk?  That option was never really implemented,
> and just relied on the user being very, very careful.  It would be nice
> to deprecate it at the same time.

I don't know - Catherine, do you know if MIPS has ceased to use -mno-float 
along with replacing the SDE library with newlib?
Paolo Bonzini Aug. 24, 2011, 1:07 p.m. UTC | #6
On 08/18/2011 11:37 PM, Joseph S. Myers wrote:
> C1X provides a standard way of declaring non-returning functions, with
> the _Noreturn keyword and a header stdnoreturn.h defining a macro
> "noreturn" to expand to _Noreturn.  This patch implements this syntax
> and header.  Bootstrapped with no regressions on
> x86_64-unknown-linux-gnu.  Applied to mainline.
>
> I didn't touch the USER_H definition in mips/t-sdemtk (so that target
> will not install this new header).  The comment "Remove stdarg.h and
> stddef.h from USER_H." suggests that maybe it should be added to that
> definition, but stdfix.h is also missing from that definition.  As far
> as I know MIPS is no longer using the old SDE library and it is
> considered superseded by newlib, so perhaps that configuration
> (mips*-sde-elf* without newlib) should actually be deprecated/removed
> (and "mipssde" threads along with it).
>
> The new keyword is C-only (C++0x has a different way of declaring
> non-returning functions) and I did not try to make the header do
> anything useful if included in C++ code.
>
> 2011-08-18  Joseph Myers<joseph@codesourcery.com>
>
> 	* c-decl.c (shadow_tag_warned): Check for _Noreturn.
> 	(quals_from_declspecs): Assert _Noreturn not present.
> 	(grokdeclarator): Handle _Noreturn.
> 	(build_null_declspecs): Initialize noreturn_p.
> 	(declspecs_add_scspec): Handle RID_NORETURN.
> 	* c-parser.c (c_token_starts_declspecs, c_parser_declspecs)
> 	(c_parser_attributes): Handle RID_NORETURN.
> 	* c-tree.h (struct c_declspecs): Add noreturn_p.
> 	* ginclude/stdnoreturn.h: New.
> 	* Makefile.in (USER_H): Add stdnoreturn.h.
>
> c-family:
> 2011-08-18  Joseph Myers<joseph@codesourcery.com>
>
> 	* c-common.c (c_common_reswords): Add _Noreturn.
> 	(keyword_is_function_specifier): Handle RID_NORETURN.
> 	* c-common.h (RID_NORETURN): New.
>
> testsuite:
> 2011-08-18  Joseph Myers<joseph@codesourcery.com>
>
> 	* gcc.dg/c1x-noreturn-1.c, gcc.dg/c1x-noreturn-2.c,
> 	gcc.dg/c1x-noreturn-3.c, gcc.dg/c1x-noreturn-4.c,
> 	gcc.dg/c1x-noreturn-5.c: New tests.

Would it make any sense to accept _Noreturn as an alternative spelling 
for the __noreturn__ attribute, in case someone is using the 
non-underscore-wrapped variant?

Thanks,

Paolo
Catherine Moore Aug. 24, 2011, 1:42 p.m. UTC | #7
On 08/24/2011 07:24 AM, Joseph S. Myers wrote:
> On Wed, 24 Aug 2011, Richard Sandiford wrote:
>
>> "Joseph S. Myers"<joseph@codesourcery.com>  writes:
>>> I didn't touch the USER_H definition in mips/t-sdemtk (so that target
>>> will not install this new header).  The comment "Remove stdarg.h and
>>> stddef.h from USER_H." suggests that maybe it should be added to that
>>> definition, but stdfix.h is also missing from that definition.  As far
>>> as I know MIPS is no longer using the old SDE library and it is
>>> considered superseded by newlib, so perhaps that configuration
>>> (mips*-sde-elf* without newlib) should actually be deprecated/removed
>>> (and "mipssde" threads along with it).
>>
>> BTW, do you know whether the same applies to -mno-float, which at the
>> moment is specific to sdemtk?  That option was never really implemented,
>> and just relied on the user being very, very careful.  It would be nice
>> to deprecate it at the same time.
>
> I don't know - Catherine, do you know if MIPS has ceased to use -mno-float
> along with replacing the SDE library with newlib?
>

MIPS continues to use the -mno-float option.  That should not be 
dperecated.  As Joseph points out, the configuration for mips-sde-elf* 
without newlib is no longer in use and may be deprecated.

Catherine
Joseph Myers Aug. 24, 2011, 3:19 p.m. UTC | #8
On Wed, 24 Aug 2011, Paolo Bonzini wrote:

> Would it make any sense to accept _Noreturn as an alternative spelling for the
> __noreturn__ attribute, in case someone is using the non-underscore-wrapped
> variant?

I suppose it might help some people use stdnoreturn.h, though I'm not 
really sure stdnoreturn.h is that useful.
diff mbox

Patch

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 177868)
+++ gcc/c-family/c-common.c	(working copy)
@@ -414,6 +414,7 @@  const struct c_common_resword c_common_r
   { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
   { "_Sat",             RID_SAT,       D_CONLY | D_EXT },
   { "_Static_assert",   RID_STATIC_ASSERT, D_CONLY },
+  { "_Noreturn",        RID_NORETURN,  D_CONLY },
   { "__FUNCTION__",	RID_FUNCTION_NAME, 0 },
   { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
   { "__alignof",	RID_ALIGNOF,	0 },
@@ -9793,6 +9794,7 @@  keyword_is_function_specifier (enum rid 
   switch (keyword)
     {
     case RID_INLINE:
+    case RID_NORETURN:
     case RID_VIRTUAL:
     case RID_EXPLICIT:
       return true;
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 177868)
+++ gcc/c-family/c-common.h	(working copy)
@@ -58,7 +58,7 @@  never after.
 /* Reserved identifiers.  This is the union of all the keywords for C,
    C++, and Objective-C.  All the type modifiers have to be in one
    block at the beginning, because they are used as mask bits.  There
-   are 27 type modifiers; if we add many more we will have to redesign
+   are 28 type modifiers; if we add many more we will have to redesign
    the mask mechanism.  */
 
 enum rid
@@ -69,6 +69,7 @@  enum rid
   RID_UNSIGNED, RID_LONG,    RID_CONST, RID_EXTERN,
   RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
   RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
+  RID_NORETURN,
 
   /* C extensions */
   RID_COMPLEX, RID_THREAD, RID_SAT,
Index: gcc/ginclude/stdnoreturn.h
===================================================================
--- gcc/ginclude/stdnoreturn.h	(revision 0)
+++ gcc/ginclude/stdnoreturn.h	(revision 0)
@@ -0,0 +1,31 @@ 
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* ISO C1X: 7.23 _Noreturn <stdnoreturn.h>.  */
+
+#ifndef _STDNORETURN_H
+#define _STDNORETURN_H
+
+#define noreturn _Noreturn
+
+#endif	/* stdnoreturn.h */
Index: gcc/testsuite/gcc.dg/c1x-noreturn-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-noreturn-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-noreturn-1.c	(revision 0)
@@ -0,0 +1,59 @@ 
+/* Test C1X _Noreturn.  Test valid code.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+_Noreturn void exit (int);
+
+_Noreturn int f1 (void);
+
+_Noreturn void f2 (void);
+
+static void _Noreturn f3 (void) { exit (0); }
+
+/* Returning from a noreturn function is undefined at runtime, not a
+   constraint violation, but recommended practice is to diagnose if
+   such a return appears possible.  */
+
+_Noreturn int
+f4 (void)
+{
+  return 1; /* { dg-warning "has a 'return' statement" } */
+  /* { dg-warning "does return" "second warning" { target *-*-* } 20 } */
+}
+
+_Noreturn void
+f5 (void)
+{
+  return; /* { dg-warning "has a 'return' statement" } */
+  /* { dg-warning "does return" "second warning" { target *-*-* } 27 } */
+}
+
+_Noreturn void
+f6 (void)
+{
+} /* { dg-warning "does return" } */
+
+_Noreturn void
+f7 (int a)
+{
+  if (a)
+    exit (0);
+} /* { dg-warning "does return" } */
+
+/* Declarations need not all have _Noreturn.  */
+
+void f2 (void);
+
+void f8 (void);
+_Noreturn void f8 (void);
+
+/* Duplicate _Noreturn is OK.  */
+_Noreturn _Noreturn void _Noreturn f9 (void);
+
+/* _Noreturn does not affect type compatibility.  */
+
+void (*fp) (void) = f5;
+
+/* noreturn is an ordinary identifier.  */
+
+int noreturn;
Index: gcc/testsuite/gcc.dg/c1x-noreturn-5.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-noreturn-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-noreturn-5.c	(revision 0)
@@ -0,0 +1,17 @@ 
+/* Test C1X _Noreturn.  Test invalid uses.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+_Noreturn struct s; /* { dg-error "empty declaration" } */
+
+typedef _Noreturn void f (void); /* { dg-error "typedef" } */
+
+void g (_Noreturn void fp (void)); /* { dg-error "parameter" } */
+
+_Noreturn void (*p) (void); /* { dg-error "variable" } */
+
+struct t { int a; _Noreturn void (*f) (void); }; /* { dg-error "expected" } */
+
+int *_Noreturn *q; /* { dg-error "expected" } */
+
+int i = sizeof (_Noreturn int (*) (void)); /* { dg-error "expected" } */
Index: gcc/testsuite/gcc.dg/c1x-noreturn-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-noreturn-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-noreturn-2.c	(revision 0)
@@ -0,0 +1,77 @@ 
+/* Test C1X _Noreturn.  Test valid code using stdnoreturn.h.  */
+/* { dg-do run } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+#include <stdnoreturn.h>
+
+extern int strcmp (const char *, const char *);
+
+noreturn void exit (int);
+noreturn void abort (void);
+
+noreturn int f1 (void);
+
+noreturn void f2 (void);
+
+static void noreturn f3 (void) { exit (0); }
+
+/* Returning from a noreturn function is undefined at runtime, not a
+   constraint violation, but recommended practice is to diagnose if
+   such a return appears possible.  */
+
+noreturn int
+f4 (void)
+{
+  return 1; /* { dg-warning "has a 'return' statement" } */
+  /* { dg-warning "does return" "second warning" { target *-*-* } 25 } */
+}
+
+noreturn void
+f5 (void)
+{
+  return; /* { dg-warning "has a 'return' statement" } */
+  /* { dg-warning "does return" "second warning" { target *-*-* } 32 } */
+}
+
+noreturn void
+f6 (void)
+{
+} /* { dg-warning "does return" } */
+
+noreturn void
+f7 (int a)
+{
+  if (a)
+    exit (0);
+} /* { dg-warning "does return" } */
+
+/* Declarations need not all have noreturn.  */
+
+void f2 (void);
+
+void f8 (void);
+noreturn void f8 (void);
+
+/* Duplicate noreturn is OK.  */
+noreturn noreturn void noreturn f9 (void);
+
+/* noreturn does not affect type compatibility.  */
+
+void (*fp) (void) = f5;
+
+#ifndef noreturn
+#error "noreturn not defined"
+#endif
+
+#define str(x) #x
+#define xstr(x) str(x)
+
+const char *s = xstr(noreturn);
+
+int
+main (void)
+{
+  if (strcmp (s, "_Noreturn") != 0)
+    abort ();
+  exit (0);
+}
Index: gcc/testsuite/gcc.dg/c1x-noreturn-3.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-noreturn-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-noreturn-3.c	(revision 0)
@@ -0,0 +1,11 @@ 
+/* Test C1X _Noreturn.  Test _Noreturn on main, hosted.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors -fhosted" } */
+
+_Noreturn void exit (int);
+
+_Noreturn int
+main (void) /* { dg-error "'main' declared '_Noreturn'" } */
+{
+  exit (0);
+}
Index: gcc/testsuite/gcc.dg/c1x-noreturn-4.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-noreturn-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-noreturn-4.c	(revision 0)
@@ -0,0 +1,11 @@ 
+/* Test C1X _Noreturn.  Test _Noreturn on main, freestanding.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors -ffreestanding" } */
+
+_Noreturn void exit (int);
+
+_Noreturn int
+main (void)
+{
+  exit (0);
+}
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h	(revision 177868)
+++ gcc/c-tree.h	(working copy)
@@ -266,6 +266,8 @@  struct c_declspecs {
   BOOL_BITFIELD complex_p : 1;
   /* Whether "inline" was specified.  */
   BOOL_BITFIELD inline_p : 1;
+  /* Whether "_Noreturn" was speciied.  */
+  BOOL_BITFIELD noreturn_p : 1;
   /* Whether "__thread" was specified.  */
   BOOL_BITFIELD thread_p : 1;
   /* Whether "const" was specified.  */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 177868)
+++ gcc/c-decl.c	(working copy)
@@ -3714,6 +3714,12 @@  shadow_tag_warned (const struct c_declsp
       warned = 1;
     }
 
+  if (declspecs->noreturn_p)
+    {
+      error ("%<_Noreturn%> in empty declaration");
+      warned = 1;
+    }
+
   if (current_scope == file_scope && declspecs->storage_class == csc_auto)
     {
       error ("%<auto%> in file-scope empty declaration");
@@ -3780,6 +3786,7 @@  quals_from_declspecs (const struct c_dec
 	      && !specs->unsigned_p
 	      && !specs->complex_p
 	      && !specs->inline_p
+	      && !specs->noreturn_p
 	      && !specs->thread_p);
   return quals;
 }
@@ -5734,6 +5741,8 @@  grokdeclarator (const struct c_declarato
 	C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
       if (declspecs->inline_p)
 	pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl);
+      if (declspecs->noreturn_p)
+	pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
 
       if (warn_cxx_compat && declarator->u.id != NULL_TREE)
 	{
@@ -5765,7 +5774,7 @@  grokdeclarator (const struct c_declarato
       /* Note that the grammar rejects storage classes in typenames
 	 and fields.  */
       gcc_assert (storage_class == csc_none && !threadp
-		  && !declspecs->inline_p);
+		  && !declspecs->inline_p && !declspecs->noreturn_p);
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
 	  && type_quals)
 	pedwarn (loc, OPT_pedantic,
@@ -5862,13 +5871,15 @@  grokdeclarator (const struct c_declarato
 	DECL_ARG_TYPE (decl) = promoted_type;
 	if (declspecs->inline_p)
 	  pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl);
+	if (declspecs->noreturn_p)
+	  pedwarn (loc, 0, "parameter %q+D declared %<_Noreturn%>", decl);
       }
     else if (decl_context == FIELD)
       {
 	/* Note that the grammar rejects storage classes in typenames
 	   and fields.  */
 	gcc_assert (storage_class == csc_none && !threadp
-		    && !declspecs->inline_p);
+		    && !declspecs->inline_p && !declspecs->noreturn_p);
 
 	/* Structure field.  It may not be a function.  */
 
@@ -5960,15 +5971,23 @@  grokdeclarator (const struct c_declarato
 	if (declspecs->default_int_p)
 	  C_FUNCTION_IMPLICIT_INT (decl) = 1;
 
-	/* Record presence of `inline', if it is reasonable.  */
+	/* Record presence of `inline' and `_Noreturn', if it is
+	   reasonable.  */
 	if (flag_hosted && MAIN_NAME_P (declarator->u.id))
 	  {
 	    if (declspecs->inline_p)
 	      pedwarn (loc, 0, "cannot inline function %<main%>");
+	    if (declspecs->noreturn_p)
+	      pedwarn (loc, 0, "%<main%> declared %<_Noreturn%>");
+	  }
+	else
+	  {
+	    if (declspecs->inline_p)
+	      /* Record that the function is declared `inline'.  */
+	      DECL_DECLARED_INLINE_P (decl) = 1;
+	    if (declspecs->noreturn_p)
+	      TREE_THIS_VOLATILE (decl) = 1;
 	  }
-	else if (declspecs->inline_p)
-	  /* Record that the function is declared `inline'.  */
-	  DECL_DECLARED_INLINE_P (decl) = 1;
       }
     else
       {
@@ -6004,6 +6023,8 @@  grokdeclarator (const struct c_declarato
 
 	if (declspecs->inline_p)
 	  pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl);
+	if (declspecs->noreturn_p)
+	  pedwarn (loc, 0, "variable %q+D declared %<_Noreturn%>", decl);
 
 	/* At file scope, an initialized extern declaration may follow
 	   a static declaration.  In that case, DECL_EXTERNAL will be
@@ -8646,6 +8667,7 @@  build_null_declspecs (void)
   ret->unsigned_p = false;
   ret->complex_p = false;
   ret->inline_p = false;
+  ret->noreturn_p = false;
   ret->thread_p = false;
   ret->const_p = false;
   ret->volatile_p = false;
@@ -9367,6 +9389,11 @@  declspecs_add_scspec (struct c_declspecs
       dupe = false;
       specs->inline_p = true;
       break;
+    case RID_NORETURN:
+      /* Duplicate _Noreturn is permitted.  */
+      dupe = false;
+      specs->noreturn_p = true;
+      break;
     case RID_THREAD:
       dupe = specs->thread_p;
       if (specs->storage_class == csc_auto)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 177868)
+++ gcc/Makefile.in	(working copy)
@@ -373,6 +373,7 @@  USER_H = $(srcdir)/ginclude/float.h \
 	 $(srcdir)/ginclude/stddef.h \
 	 $(srcdir)/ginclude/varargs.h \
 	 $(srcdir)/ginclude/stdfix.h \
+	 $(srcdir)/ginclude/stdnoreturn.h \
 	 $(EXTRA_HEADERS)
 
 USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 177868)
+++ gcc/c-parser.c	(working copy)
@@ -621,6 +621,7 @@  c_token_starts_declspecs (c_token *token
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_INLINE:
+	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	case RID_UNSIGNED:
@@ -2080,12 +2081,13 @@  c_parser_declspecs (c_parser *parser, st
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_INLINE:
+	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	  if (!scspec_ok)
 	    goto out;
 	  attrs_ok = true;
-	  /* TODO: Distinguish between function specifiers (inline)
+	  /* TODO: Distinguish between function specifiers (inline, noreturn)
 	     and storage class specifiers, either here or in
 	     declspecs_add_scspec.  */
 	  declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
@@ -3428,6 +3430,7 @@  c_parser_attributes (c_parser *parser)
 		case RID_TYPEDEF:
 		case RID_SHORT:
 		case RID_INLINE:
+		case RID_NORETURN:
 		case RID_VOLATILE:
 		case RID_SIGNED:
 		case RID_AUTO: