mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 11:40:54 +08:00
c-decl.c (finish_function): Warn about a non-void function with no return statement and no abnormal exit.
* c-decl.c (finish_function): Warn about a non-void function with no return statement and no abnormal exit. (current_function_returns_abnormally): New variable. (start_function): Clear it. (struct c_language_function): Add returns_abnormally. (push_c_function_context): Save it. (pop_c_function_context): Restore it. (builtin_function): Set TREE_THIS_VOLATILE on return fns. (grokdeclarator): Set C_FUNCTION_IMPLICIT_INT on functions without an explicit return type. * c-tree.h: Declare current_function_returns_abnormally. (C_FUNCTION_IMPLICIT_INT): New macro. * c-typeck.c (build_function_call): Set it. (c_expand_return): Set current_function_returns_value even if the value is erroneous. From-SVN: r49551
This commit is contained in:
parent
caaf2272c0
commit
5ce89b2ef0
@ -1,3 +1,21 @@
|
||||
2002-02-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c-decl.c (finish_function): Warn about a non-void function with
|
||||
no return statement and no abnormal exit.
|
||||
(current_function_returns_abnormally): New variable.
|
||||
(start_function): Clear it.
|
||||
(struct c_language_function): Add returns_abnormally.
|
||||
(push_c_function_context): Save it.
|
||||
(pop_c_function_context): Restore it.
|
||||
(builtin_function): Set TREE_THIS_VOLATILE on return fns.
|
||||
(grokdeclarator): Set C_FUNCTION_IMPLICIT_INT on functions without
|
||||
an explicit return type.
|
||||
* c-tree.h: Declare current_function_returns_abnormally.
|
||||
(C_FUNCTION_IMPLICIT_INT): New macro.
|
||||
* c-typeck.c (build_function_call): Set it.
|
||||
(c_expand_return): Set current_function_returns_value even if the
|
||||
value is erroneous.
|
||||
|
||||
2002-02-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/5420:
|
||||
|
31
gcc/c-decl.c
31
gcc/c-decl.c
@ -134,6 +134,11 @@ int current_function_returns_value;
|
||||
|
||||
int current_function_returns_null;
|
||||
|
||||
/* Set to 0 at beginning of a function definition, set to 1 if
|
||||
a call to a noreturn function is seen. */
|
||||
|
||||
int current_function_returns_abnormally;
|
||||
|
||||
/* Set to nonzero by `grokdeclarator' for a function
|
||||
whose return type is defaulted, if warnings for this are desired. */
|
||||
|
||||
@ -3214,6 +3219,10 @@ builtin_function (name, type, function_code, class, library_name)
|
||||
DECL_BUILT_IN_CLASS (decl) = class;
|
||||
DECL_FUNCTION_CODE (decl) = function_code;
|
||||
|
||||
/* The return builtins leave the current function. */
|
||||
if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
|
||||
TREE_THIS_VOLATILE (decl) = 1;
|
||||
|
||||
/* Warn if a function in the namespace for users
|
||||
is used without an occasion to consider it declared. */
|
||||
if (name[0] != '_' || name[1] != '_')
|
||||
@ -5086,6 +5095,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
TREE_PUBLIC (decl)
|
||||
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
|
||||
|
||||
if (defaulted_int)
|
||||
C_FUNCTION_IMPLICIT_INT (decl) = 1;
|
||||
|
||||
/* Record presence of `inline', if it is reasonable. */
|
||||
if (MAIN_NAME_P (declarator))
|
||||
{
|
||||
@ -6175,6 +6187,7 @@ start_function (declspecs, declarator, attributes)
|
||||
|
||||
current_function_returns_value = 0; /* Assume, until we see it does. */
|
||||
current_function_returns_null = 0;
|
||||
current_function_returns_abnormally = 0;
|
||||
warn_about_return_type = 0;
|
||||
current_extern_inline = 0;
|
||||
c_function_varargs = 0;
|
||||
@ -6904,6 +6917,21 @@ finish_function (nested)
|
||||
|
||||
/* Tie off the statement tree for this function. */
|
||||
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
|
||||
|
||||
/* Complain if there's just no return statement. */
|
||||
if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
|
||||
&& !current_function_returns_value && !current_function_returns_null
|
||||
/* Don't complain if we abort. */
|
||||
&& !current_function_returns_abnormally
|
||||
/* Don't warn for main(). */
|
||||
&& !MAIN_NAME_P (DECL_NAME (fndecl))
|
||||
/* Or if they didn't actually specify a return type. */
|
||||
&& !C_FUNCTION_IMPLICIT_INT (fndecl)
|
||||
/* If we have -Wreturn-type, let flow complain. Unless we're an
|
||||
inline function, as we might never be compiled separately. */
|
||||
&& (!warn_return_type || DECL_INLINE (fndecl)))
|
||||
warning ("no return statement in function returning non-void");
|
||||
|
||||
/* Clear out memory we no longer need. */
|
||||
free_after_parsing (cfun);
|
||||
/* Since we never call rest_of_compilation, we never clear
|
||||
@ -7193,6 +7221,7 @@ struct c_language_function
|
||||
tree shadowed_labels;
|
||||
int returns_value;
|
||||
int returns_null;
|
||||
int returns_abnormally;
|
||||
int warn_about_return_type;
|
||||
int extern_inline;
|
||||
struct binding_level *binding_level;
|
||||
@ -7216,6 +7245,7 @@ push_c_function_context (f)
|
||||
p->shadowed_labels = shadowed_labels;
|
||||
p->returns_value = current_function_returns_value;
|
||||
p->returns_null = current_function_returns_null;
|
||||
p->returns_abnormally = current_function_returns_abnormally;
|
||||
p->warn_about_return_type = warn_about_return_type;
|
||||
p->extern_inline = current_extern_inline;
|
||||
p->binding_level = current_binding_level;
|
||||
@ -7253,6 +7283,7 @@ pop_c_function_context (f)
|
||||
shadowed_labels = p->shadowed_labels;
|
||||
current_function_returns_value = p->returns_value;
|
||||
current_function_returns_null = p->returns_null;
|
||||
current_function_returns_abnormally = p->returns_abnormally;
|
||||
warn_about_return_type = p->warn_about_return_type;
|
||||
current_extern_inline = p->extern_inline;
|
||||
current_binding_level = p->binding_level;
|
||||
|
@ -132,6 +132,10 @@ struct lang_type
|
||||
/* Record whether a typedef for type `int' was actually `signed int'. */
|
||||
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
|
||||
|
||||
/* For a FUNCTION_DECL, nonzero if it was defined without an explicit
|
||||
return type. */
|
||||
#define C_FUNCTION_IMPLICIT_INT(EXP) DECL_LANG_FLAG_1 (EXP)
|
||||
|
||||
/* Nonzero for a declaration of a built in function if there has been no
|
||||
occasion that would declare the function in ordinary C.
|
||||
Using the function draws a pedantic warning in this case. */
|
||||
@ -277,6 +281,11 @@ extern int current_function_returns_value;
|
||||
|
||||
extern int current_function_returns_null;
|
||||
|
||||
/* Set to 0 at beginning of a function definition, set to 1 if
|
||||
a call to a noreturn function is seen. */
|
||||
|
||||
extern int current_function_returns_abnormally;
|
||||
|
||||
/* Nonzero means the expression being parsed will never be evaluated.
|
||||
This is a count, since unevaluated expressions can nest. */
|
||||
|
||||
|
@ -1547,6 +1547,9 @@ build_function_call (function, params)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (fundecl && TREE_THIS_VOLATILE (fundecl))
|
||||
current_function_returns_abnormally = 1;
|
||||
|
||||
/* fntype now gets the type of function pointed to. */
|
||||
fntype = TREE_TYPE (fntype);
|
||||
|
||||
@ -7084,6 +7087,7 @@ c_expand_return (retval)
|
||||
tree res = DECL_RESULT (current_function_decl);
|
||||
tree inner;
|
||||
|
||||
current_function_returns_value = 1;
|
||||
if (t == error_mark_node)
|
||||
return NULL_TREE;
|
||||
|
||||
@ -7141,7 +7145,6 @@ c_expand_return (retval)
|
||||
}
|
||||
|
||||
retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
|
||||
current_function_returns_value = 1;
|
||||
}
|
||||
|
||||
return add_stmt (build_return_stmt (retval));
|
||||
|
@ -20,4 +20,5 @@ int foo (int s)
|
||||
: "cc"); r; }))
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,4 +17,5 @@ div_and_round_double (lden_orig, hden_orig)
|
||||
quo[i] = work / (unsigned int ) lden;
|
||||
carry = work % (unsigned int ) lden;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,4 +18,5 @@ foo ()
|
||||
for (i = 0; i < 10; i++)
|
||||
;
|
||||
fabs (x - y);
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,4 +12,5 @@ XmlInitUnknownEncoding(void *mem)
|
||||
struct unknown_encoding *e = mem;
|
||||
for (i = 0; i < sizeof(struct normal_encoding); i++)
|
||||
((char *)mem)[i] = ((char *)&latin1_encoding)[i];
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,4 +12,6 @@ bar (int64_t which)
|
||||
case 5 :
|
||||
case 2 : ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -34,5 +34,5 @@ p_frames_to_multilayer(t_anim_info *ainfo_ptr,
|
||||
break;
|
||||
l_cur_frame_nr += l_step;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
/* Test against a problem with the combiner substituting explicit hard reg
|
||||
references when it shouldn't. */
|
||||
int foo (int, int) __attribute__ ((regparm (3)));
|
||||
int foo (int x, int y)
|
||||
void foo (int, int) __attribute__ ((regparm (3)));
|
||||
void foo (int x, int y)
|
||||
{
|
||||
__asm__ __volatile__("" : : "d" (x), "r" (y));
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
int f()
|
||||
void f()
|
||||
{
|
||||
asm volatile ("foo%%bar" : : );
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
int f()
|
||||
void f()
|
||||
{
|
||||
asm ("foo%%bar");
|
||||
}
|
||||
|
@ -21,13 +21,14 @@ int ATSYM(var) ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
|
||||
int ATSYM(fn_knrarg) (arg)
|
||||
int arg ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
{}
|
||||
{ return 0; }
|
||||
|
||||
int ATSYM(fn_isoarg) (int arg ATTR) {} /* { dg-warning "attribute ignored" "" } */
|
||||
int ATSYM(fn_isoarg) (int arg ATTR) { return 0; } /* { dg-warning "attribute ignored" "" } */
|
||||
|
||||
int ATSYM(fn_vars) (void) {
|
||||
static int svar ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
auto int lvar ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -46,11 +47,12 @@ int ATSYM(var) ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
|
||||
int ATSYM(fn_knrarg) (arg)
|
||||
int arg ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
{}
|
||||
{ return 0; }
|
||||
|
||||
int ATSYM(fn_isoarg) (int arg ATTR) {} /* { dg-warning "attribute ignored" "" } */
|
||||
int ATSYM(fn_isoarg) (int arg ATTR) { return 0; } /* { dg-warning "attribute ignored" "" } */
|
||||
|
||||
int ATSYM(fn_vars) (void) {
|
||||
static int svar ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
auto int lvar ATTR; /* { dg-warning "attribute ignored" "" } */
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ static inline void function_declaration_noinline_inline_before(void); /* { dg-wa
|
||||
|
||||
static void function_declaration_noinline_inline_before(void) {}
|
||||
|
||||
int f () {
|
||||
void f () {
|
||||
function_definition ();
|
||||
function_declaration_both_before ();
|
||||
function_declaration_both_after ();
|
||||
|
@ -13,10 +13,10 @@ INT1 should_be_unavailable; /* { dg-warning "`INT1' is deprecated" "" } */
|
||||
INT1a should_not_be_deprecated;
|
||||
|
||||
INT1 f1(void) __attribute__ ((deprecated));
|
||||
INT1 f2(void) {} /* { dg-warning "`INT1' is deprecated" "" } */
|
||||
INT1 f2(void) { return 0; } /* { dg-warning "`INT1' is deprecated" "" } */
|
||||
|
||||
INT2 f3(void) __attribute__ ((__deprecated__));
|
||||
INT2 f4(void) {} /* { dg-warning "`INT2' is deprecated" "" } */
|
||||
INT2 f4(void) { return 0; } /* { dg-warning "`INT2' is deprecated" "" } */
|
||||
int f5(INT2 x); /* { dg-warning "`INT2' is deprecated" "" } */
|
||||
int f6(INT2 x) __attribute__ ((__deprecated__)); /* { dg-warning "`INT2' is deprecated" "" } */
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
Copyright (C) 1999 Free Software Foundation */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3" } */
|
||||
/* { dg-options "-O3 -w" } */
|
||||
|
||||
struct {
|
||||
unsigned i[4];
|
||||
|
@ -68,7 +68,7 @@ test_for2 (int m, int n, int o)
|
||||
return for_temp; /* count(6) */
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
call_for ()
|
||||
{
|
||||
for_val1 += test_for1 (0);
|
||||
|
@ -68,7 +68,7 @@ test_for2 (int m, int n, int o)
|
||||
return for_temp; /* count(6) */
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
call_for ()
|
||||
{
|
||||
for_val1 += test_for1 (0);
|
||||
|
@ -41,7 +41,7 @@ test_for2 (int m, int n, int o)
|
||||
return for_temp;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
call_for ()
|
||||
{
|
||||
for_val1 += test_for1 (0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user