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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49551
138bc75d-0d04-0410-961f-
82ee72b054a4
+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:
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. */
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] != '_')
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))
{
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;
/* 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
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;
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;
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;
/* 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. */
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. */
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);
tree res = DECL_RESULT (current_function_decl);
tree inner;
+ current_function_returns_value = 1;
if (t == error_mark_node)
return NULL_TREE;
}
retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
- current_function_returns_value = 1;
}
return add_stmt (build_return_stmt (retval));
: "cc"); r; }))
continue;
}
+ return 0;
}
quo[i] = work / (unsigned int ) lden;
carry = work % (unsigned int ) lden;
}
+ return 0;
}
for (i = 0; i < 10; i++)
;
fabs (x - y);
+ return 0;
}
struct unknown_encoding *e = mem;
for (i = 0; i < sizeof(struct normal_encoding); i++)
((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ return 0;
}
case 5 :
case 2 : ;
}
+
+ return 0;
}
break;
l_cur_frame_nr += l_step;
}
+ return 0;
}
-
/* 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));
}
/* { dg-do compile } */
/* { dg-options "" } */
-int f()
+void f()
{
asm volatile ("foo%%bar" : : );
}
/* { dg-do compile } */
/* { dg-options "" } */
-int f()
+void f()
{
asm ("foo%%bar");
}
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;
}
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;
}
static void function_declaration_noinline_inline_before(void) {}
-int f () {
+void f () {
function_definition ();
function_declaration_both_before ();
function_declaration_both_after ();
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" "" } */
Copyright (C) 1999 Free Software Foundation */
/* { dg-do compile } */
-/* { dg-options "-O3" } */
+/* { dg-options "-O3 -w" } */
struct {
unsigned i[4];
return for_temp; /* count(6) */
}
-int
+void
call_for ()
{
for_val1 += test_for1 (0);
return for_temp; /* count(6) */
}
-int
+void
call_for ()
{
for_val1 += test_for1 (0);
return for_temp;
}
-int
+void
call_for ()
{
for_val1 += test_for1 (0);