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:
parent
32fe396e05
commit
bbceee64be
@ -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.
|
||||
|
@ -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@
|
||||
|
39
gcc/c-decl.c
39
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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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. */
|
||||
|
31
gcc/ginclude/stdnoreturn.h
Normal file
31
gcc/ginclude/stdnoreturn.h
Normal 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 */
|
@ -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.
|
||||
|
59
gcc/testsuite/gcc.dg/c1x-noreturn-1.c
Normal file
59
gcc/testsuite/gcc.dg/c1x-noreturn-1.c
Normal 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;
|
77
gcc/testsuite/gcc.dg/c1x-noreturn-2.c
Normal file
77
gcc/testsuite/gcc.dg/c1x-noreturn-2.c
Normal 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);
|
||||
}
|
11
gcc/testsuite/gcc.dg/c1x-noreturn-3.c
Normal file
11
gcc/testsuite/gcc.dg/c1x-noreturn-3.c
Normal 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);
|
||||
}
|
11
gcc/testsuite/gcc.dg/c1x-noreturn-4.c
Normal file
11
gcc/testsuite/gcc.dg/c1x-noreturn-4.c
Normal 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);
|
||||
}
|
17
gcc/testsuite/gcc.dg/c1x-noreturn-5.c
Normal file
17
gcc/testsuite/gcc.dg/c1x-noreturn-5.c
Normal 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" } */
|
Loading…
Reference in New Issue
Block a user