Commit bbceee64 by Joseph Myers Committed by Joseph Myers

c-decl.c (shadow_tag_warned): Check for _Noreturn.

	* 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.

From-SVN: r177881
parent 32fe396e
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> 2011-08-18 Kirill Yukhin <kirill.yukhin@intel.com>
* common/config/i386/i386-common.c (OPTION_MASK_ISA_AVX2_SET): New. * common/config/i386/i386-common.c (OPTION_MASK_ISA_AVX2_SET): New.
......
...@@ -373,6 +373,7 @@ USER_H = $(srcdir)/ginclude/float.h \ ...@@ -373,6 +373,7 @@ USER_H = $(srcdir)/ginclude/float.h \
$(srcdir)/ginclude/stddef.h \ $(srcdir)/ginclude/stddef.h \
$(srcdir)/ginclude/varargs.h \ $(srcdir)/ginclude/varargs.h \
$(srcdir)/ginclude/stdfix.h \ $(srcdir)/ginclude/stdfix.h \
$(srcdir)/ginclude/stdnoreturn.h \
$(EXTRA_HEADERS) $(EXTRA_HEADERS)
USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@ USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
......
...@@ -3714,6 +3714,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) ...@@ -3714,6 +3714,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
warned = 1; warned = 1;
} }
if (declspecs->noreturn_p)
{
error ("%<_Noreturn%> in empty declaration");
warned = 1;
}
if (current_scope == file_scope && declspecs->storage_class == csc_auto) if (current_scope == file_scope && declspecs->storage_class == csc_auto)
{ {
error ("%<auto%> in file-scope empty declaration"); error ("%<auto%> in file-scope empty declaration");
...@@ -3780,6 +3786,7 @@ quals_from_declspecs (const struct c_declspecs *specs) ...@@ -3780,6 +3786,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
&& !specs->unsigned_p && !specs->unsigned_p
&& !specs->complex_p && !specs->complex_p
&& !specs->inline_p && !specs->inline_p
&& !specs->noreturn_p
&& !specs->thread_p); && !specs->thread_p);
return quals; return quals;
} }
...@@ -5734,6 +5741,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5734,6 +5741,8 @@ grokdeclarator (const struct c_declarator *declarator,
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (declspecs->inline_p) if (declspecs->inline_p)
pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl); 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) if (warn_cxx_compat && declarator->u.id != NULL_TREE)
{ {
...@@ -5765,7 +5774,7 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5765,7 +5774,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* Note that the grammar rejects storage classes in typenames /* Note that the grammar rejects storage classes in typenames
and fields. */ and fields. */
gcc_assert (storage_class == csc_none && !threadp gcc_assert (storage_class == csc_none && !threadp
&& !declspecs->inline_p); && !declspecs->inline_p && !declspecs->noreturn_p);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals) && type_quals)
pedwarn (loc, OPT_pedantic, pedwarn (loc, OPT_pedantic,
...@@ -5862,13 +5871,15 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5862,13 +5871,15 @@ grokdeclarator (const struct c_declarator *declarator,
DECL_ARG_TYPE (decl) = promoted_type; DECL_ARG_TYPE (decl) = promoted_type;
if (declspecs->inline_p) if (declspecs->inline_p)
pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl); 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) else if (decl_context == FIELD)
{ {
/* Note that the grammar rejects storage classes in typenames /* Note that the grammar rejects storage classes in typenames
and fields. */ and fields. */
gcc_assert (storage_class == csc_none && !threadp gcc_assert (storage_class == csc_none && !threadp
&& !declspecs->inline_p); && !declspecs->inline_p && !declspecs->noreturn_p);
/* Structure field. It may not be a function. */ /* Structure field. It may not be a function. */
...@@ -5960,15 +5971,23 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -5960,15 +5971,23 @@ grokdeclarator (const struct c_declarator *declarator,
if (declspecs->default_int_p) if (declspecs->default_int_p)
C_FUNCTION_IMPLICIT_INT (decl) = 1; 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 (flag_hosted && MAIN_NAME_P (declarator->u.id))
{ {
if (declspecs->inline_p) if (declspecs->inline_p)
pedwarn (loc, 0, "cannot inline function %<main%>"); 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 else
{ {
...@@ -6004,6 +6023,8 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6004,6 +6023,8 @@ grokdeclarator (const struct c_declarator *declarator,
if (declspecs->inline_p) if (declspecs->inline_p)
pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl); 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 /* At file scope, an initialized extern declaration may follow
a static declaration. In that case, DECL_EXTERNAL will be a static declaration. In that case, DECL_EXTERNAL will be
...@@ -8646,6 +8667,7 @@ build_null_declspecs (void) ...@@ -8646,6 +8667,7 @@ build_null_declspecs (void)
ret->unsigned_p = false; ret->unsigned_p = false;
ret->complex_p = false; ret->complex_p = false;
ret->inline_p = false; ret->inline_p = false;
ret->noreturn_p = false;
ret->thread_p = false; ret->thread_p = false;
ret->const_p = false; ret->const_p = false;
ret->volatile_p = false; ret->volatile_p = false;
...@@ -9367,6 +9389,11 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec) ...@@ -9367,6 +9389,11 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
dupe = false; dupe = false;
specs->inline_p = true; specs->inline_p = true;
break; break;
case RID_NORETURN:
/* Duplicate _Noreturn is permitted. */
dupe = false;
specs->noreturn_p = true;
break;
case RID_THREAD: case RID_THREAD:
dupe = specs->thread_p; dupe = specs->thread_p;
if (specs->storage_class == csc_auto) if (specs->storage_class == csc_auto)
......
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> 2011-08-10 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
* c-common.c (unsafe_conversion_p): New function. Check if it is * c-common.c (unsafe_conversion_p): New function. Check if it is
......
...@@ -414,6 +414,7 @@ const struct c_common_resword c_common_reswords[] = ...@@ -414,6 +414,7 @@ const struct c_common_resword c_common_reswords[] =
{ "_Accum", RID_ACCUM, D_CONLY | D_EXT }, { "_Accum", RID_ACCUM, D_CONLY | D_EXT },
{ "_Sat", RID_SAT, D_CONLY | D_EXT }, { "_Sat", RID_SAT, D_CONLY | D_EXT },
{ "_Static_assert", RID_STATIC_ASSERT, D_CONLY }, { "_Static_assert", RID_STATIC_ASSERT, D_CONLY },
{ "_Noreturn", RID_NORETURN, D_CONLY },
{ "__FUNCTION__", RID_FUNCTION_NAME, 0 }, { "__FUNCTION__", RID_FUNCTION_NAME, 0 },
{ "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
{ "__alignof", RID_ALIGNOF, 0 }, { "__alignof", RID_ALIGNOF, 0 },
...@@ -9793,6 +9794,7 @@ keyword_is_function_specifier (enum rid keyword) ...@@ -9793,6 +9794,7 @@ keyword_is_function_specifier (enum rid keyword)
switch (keyword) switch (keyword)
{ {
case RID_INLINE: case RID_INLINE:
case RID_NORETURN:
case RID_VIRTUAL: case RID_VIRTUAL:
case RID_EXPLICIT: case RID_EXPLICIT:
return true; return true;
......
...@@ -58,7 +58,7 @@ never after. ...@@ -58,7 +58,7 @@ never after.
/* Reserved identifiers. This is the union of all the keywords for C, /* 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 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 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. */ the mask mechanism. */
enum rid enum rid
...@@ -69,6 +69,7 @@ enum rid ...@@ -69,6 +69,7 @@ enum rid
RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN, RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN,
RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE, RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT, RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
RID_NORETURN,
/* C extensions */ /* C extensions */
RID_COMPLEX, RID_THREAD, RID_SAT, RID_COMPLEX, RID_THREAD, RID_SAT,
......
...@@ -621,6 +621,7 @@ c_token_starts_declspecs (c_token *token) ...@@ -621,6 +621,7 @@ c_token_starts_declspecs (c_token *token)
case RID_REGISTER: case RID_REGISTER:
case RID_TYPEDEF: case RID_TYPEDEF:
case RID_INLINE: case RID_INLINE:
case RID_NORETURN:
case RID_AUTO: case RID_AUTO:
case RID_THREAD: case RID_THREAD:
case RID_UNSIGNED: case RID_UNSIGNED:
...@@ -2080,12 +2081,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, ...@@ -2080,12 +2081,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_REGISTER: case RID_REGISTER:
case RID_TYPEDEF: case RID_TYPEDEF:
case RID_INLINE: case RID_INLINE:
case RID_NORETURN:
case RID_AUTO: case RID_AUTO:
case RID_THREAD: case RID_THREAD:
if (!scspec_ok) if (!scspec_ok)
goto out; goto out;
attrs_ok = true; attrs_ok = true;
/* TODO: Distinguish between function specifiers (inline) /* TODO: Distinguish between function specifiers (inline, noreturn)
and storage class specifiers, either here or in and storage class specifiers, either here or in
declspecs_add_scspec. */ declspecs_add_scspec. */
declspecs_add_scspec (specs, c_parser_peek_token (parser)->value); declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
...@@ -3428,6 +3430,7 @@ c_parser_attributes (c_parser *parser) ...@@ -3428,6 +3430,7 @@ c_parser_attributes (c_parser *parser)
case RID_TYPEDEF: case RID_TYPEDEF:
case RID_SHORT: case RID_SHORT:
case RID_INLINE: case RID_INLINE:
case RID_NORETURN:
case RID_VOLATILE: case RID_VOLATILE:
case RID_SIGNED: case RID_SIGNED:
case RID_AUTO: case RID_AUTO:
......
...@@ -266,6 +266,8 @@ struct c_declspecs { ...@@ -266,6 +266,8 @@ struct c_declspecs {
BOOL_BITFIELD complex_p : 1; BOOL_BITFIELD complex_p : 1;
/* Whether "inline" was specified. */ /* Whether "inline" was specified. */
BOOL_BITFIELD inline_p : 1; BOOL_BITFIELD inline_p : 1;
/* Whether "_Noreturn" was speciied. */
BOOL_BITFIELD noreturn_p : 1;
/* Whether "__thread" was specified. */ /* Whether "__thread" was specified. */
BOOL_BITFIELD thread_p : 1; BOOL_BITFIELD thread_p : 1;
/* Whether "const" was specified. */ /* Whether "const" was specified. */
......
/* 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 */
2011-08-18 Joseph Myers <joseph@codesourcery.com> 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. * 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> 2011-08-18 Tobias Burnus <burnus@net-b.de>
......
/* 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;
/* 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);
}
/* 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);
}
/* 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);
}
/* 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" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment