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
This commit is contained in:
Joseph Myers 2011-08-18 22:35:42 +01:00 committed by Joseph Myers
parent 32fe396e05
commit bbceee64be
15 changed files with 275 additions and 8 deletions

View File

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

View File

@ -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@

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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:

View File

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

View File

@ -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 */

View File

@ -1,3 +1,9 @@
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.

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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" } */