summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-18 21:35:42 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-18 21:35:42 +0000
commit985c6e3a7f5ac7ed72400d90fa5529c9370f61aa (patch)
tree7cac89ed01db35f3172a81cb7429efeb4d9798e7
parent985e7f1028ffb3c6e18d66e9c9ae8d0baaa3f74b (diff)
downloadgcc-985c6e3a7f5ac7ed72400d90fa5529c9370f61aa.tar.gz
* 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: * c-common.c (c_common_reswords): Add _Noreturn. (keyword_is_function_specifier): Handle RID_NORETURN. * c-common.h (RID_NORETURN): New. testsuite: * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177881 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/c-decl.c39
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-common.c2
-rw-r--r--gcc/c-family/c-common.h3
-rw-r--r--gcc/c-parser.c5
-rw-r--r--gcc/c-tree.h2
-rw-r--r--gcc/ginclude/stdnoreturn.h31
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-1.c59
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-2.c77
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-4.c11
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-5.c17
15 files changed, 275 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5ade55a1564..14723eb314a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+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.
+
2011-08-18 Kirill Yukhin <kirill.yukhin@intel.com>
* common/config/i386/i386-common.c (OPTION_MASK_ISA_AVX2_SET): New.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 762b72bdae9..8c501dd2e53 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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@
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 927beb0a33d..d824e12b5bb 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3714,6 +3714,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
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_declspecs *specs)
&& !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_declarator *declarator,
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_declarator *declarator,
/* 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_declarator *declarator,
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_declarator *declarator,
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_declarator *declarator,
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 *specs, tree scspec)
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)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 5f56369f3c3..9a8d953eec8 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+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.
+
2011-08-10 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
* c-common.c (unsafe_conversion_p): New function. Check if it is
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 1ef7e3c42e2..d4dceab30da 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -414,6 +414,7 @@ const struct c_common_resword c_common_reswords[] =
{ "_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 keyword)
switch (keyword)
{
case RID_INLINE:
+ case RID_NORETURN:
case RID_VIRTUAL:
case RID_EXPLICIT:
return true;
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 6905737c28e..a771c33033a 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -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,
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 0d2a1b7dfca..d0f8fba50ea 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -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, struct c_declspecs *specs,
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:
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 95a0ba2e1f4..cda5d06863a 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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. */
diff --git a/gcc/ginclude/stdnoreturn.h b/gcc/ginclude/stdnoreturn.h
new file mode 100644
index 00000000000..c92537ce2d7
--- /dev/null
+++ b/gcc/ginclude/stdnoreturn.h
@@ -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 */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d8f7f1140ef..47379668f81 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
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.
+
+2011-08-18 Joseph Myers <joseph@codesourcery.com>
+
* gcc.dg/c1x-uni-string-1.c, gcc.dg/c1x-uni-string-2.c: New tests.
2011-08-18 Tobias Burnus <burnus@net-b.de>
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-1.c b/gcc/testsuite/gcc.dg/c1x-noreturn-1.c
new file mode 100644
index 00000000000..d9c141d5326
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-noreturn-1.c
@@ -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;
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-2.c b/gcc/testsuite/gcc.dg/c1x-noreturn-2.c
new file mode 100644
index 00000000000..81972f1e8be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-noreturn-2.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-3.c b/gcc/testsuite/gcc.dg/c1x-noreturn-3.c
new file mode 100644
index 00000000000..b12c23efafc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-noreturn-3.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-4.c b/gcc/testsuite/gcc.dg/c1x-noreturn-4.c
new file mode 100644
index 00000000000..72dceafba19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-noreturn-4.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-5.c b/gcc/testsuite/gcc.dg/c1x-noreturn-5.c
new file mode 100644
index 00000000000..73f22165cb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-noreturn-5.c
@@ -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" } */