aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/c-decl.c31
-rw-r--r--gcc/c-tree.h9
-rw-r--r--gcc/c-typeck.c5
-rw-r--r--gcc/testsuite/gcc.dg/20011029-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/980816-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/990117-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/990213-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/990214-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/990524-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/991214-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/asm-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/asm-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-invalid.c10
-rw-r--r--gcc/testsuite/gcc.dg/attr-noinline.c2
-rw-r--r--gcc/testsuite/gcc.dg/deprecated.c4
-rw-r--r--gcc/testsuite/gcc.dg/struct-ret-2.c2
-rw-r--r--gcc/testsuite/gcc.misc-tests/bprob-1.c2
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-4.c2
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-4b.c2
20 files changed, 86 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 96baa91..c1ba34f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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:
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index af6a2c0..746fa47 100644
--- a/gcc/c-decl.c
+++ b/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;
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 03bd683..8f53b17 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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. */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 8c34a17..dc844bf 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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));
diff --git a/gcc/testsuite/gcc.dg/20011029-2.c b/gcc/testsuite/gcc.dg/20011029-2.c
index 77a5b07..b184af0 100644
--- a/gcc/testsuite/gcc.dg/20011029-2.c
+++ b/gcc/testsuite/gcc.dg/20011029-2.c
@@ -20,4 +20,5 @@ int foo (int s)
: "cc"); r; }))
continue;
}
+ return 0;
}
diff --git a/gcc/testsuite/gcc.dg/980816-1.c b/gcc/testsuite/gcc.dg/980816-1.c
index 2a96ef4..8581d99 100644
--- a/gcc/testsuite/gcc.dg/980816-1.c
+++ b/gcc/testsuite/gcc.dg/980816-1.c
@@ -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;
}
diff --git a/gcc/testsuite/gcc.dg/990117-1.c b/gcc/testsuite/gcc.dg/990117-1.c
index 2e7ea5a..606ba44 100644
--- a/gcc/testsuite/gcc.dg/990117-1.c
+++ b/gcc/testsuite/gcc.dg/990117-1.c
@@ -18,4 +18,5 @@ foo ()
for (i = 0; i < 10; i++)
;
fabs (x - y);
+ return 0;
}
diff --git a/gcc/testsuite/gcc.dg/990213-2.c b/gcc/testsuite/gcc.dg/990213-2.c
index 6e6b924..a0a13b5 100644
--- a/gcc/testsuite/gcc.dg/990213-2.c
+++ b/gcc/testsuite/gcc.dg/990213-2.c
@@ -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;
}
diff --git a/gcc/testsuite/gcc.dg/990214-1.c b/gcc/testsuite/gcc.dg/990214-1.c
index 492c6a7..7ad81b6 100644
--- a/gcc/testsuite/gcc.dg/990214-1.c
+++ b/gcc/testsuite/gcc.dg/990214-1.c
@@ -12,4 +12,6 @@ bar (int64_t which)
case 5 :
case 2 : ;
}
+
+ return 0;
}
diff --git a/gcc/testsuite/gcc.dg/990524-1.c b/gcc/testsuite/gcc.dg/990524-1.c
index b87b588..8b10172 100644
--- a/gcc/testsuite/gcc.dg/990524-1.c
+++ b/gcc/testsuite/gcc.dg/990524-1.c
@@ -34,5 +34,5 @@ p_frames_to_multilayer(t_anim_info *ainfo_ptr,
break;
l_cur_frame_nr += l_step;
}
+ return 0;
}
-
diff --git a/gcc/testsuite/gcc.dg/991214-1.c b/gcc/testsuite/gcc.dg/991214-1.c
index 5b9f56c..c8e3a04 100644
--- a/gcc/testsuite/gcc.dg/991214-1.c
+++ b/gcc/testsuite/gcc.dg/991214-1.c
@@ -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));
}
diff --git a/gcc/testsuite/gcc.dg/asm-2.c b/gcc/testsuite/gcc.dg/asm-2.c
index 5adee41..9c464ce 100644
--- a/gcc/testsuite/gcc.dg/asm-2.c
+++ b/gcc/testsuite/gcc.dg/asm-2.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "" } */
-int f()
+void f()
{
asm volatile ("foo%%bar" : : );
}
diff --git a/gcc/testsuite/gcc.dg/asm-3.c b/gcc/testsuite/gcc.dg/asm-3.c
index e7db804..917942d 100644
--- a/gcc/testsuite/gcc.dg/asm-3.c
+++ b/gcc/testsuite/gcc.dg/asm-3.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "" } */
-int f()
+void f()
{
asm ("foo%%bar");
}
diff --git a/gcc/testsuite/gcc.dg/attr-invalid.c b/gcc/testsuite/gcc.dg/attr-invalid.c
index 768921d..a999c26 100644
--- a/gcc/testsuite/gcc.dg/attr-invalid.c
+++ b/gcc/testsuite/gcc.dg/attr-invalid.c
@@ -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;
}
diff --git a/gcc/testsuite/gcc.dg/attr-noinline.c b/gcc/testsuite/gcc.dg/attr-noinline.c
index 903959e..ee48eb9 100644
--- a/gcc/testsuite/gcc.dg/attr-noinline.c
+++ b/gcc/testsuite/gcc.dg/attr-noinline.c
@@ -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 ();
diff --git a/gcc/testsuite/gcc.dg/deprecated.c b/gcc/testsuite/gcc.dg/deprecated.c
index bc82c6d..8355747 100644
--- a/gcc/testsuite/gcc.dg/deprecated.c
+++ b/gcc/testsuite/gcc.dg/deprecated.c
@@ -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" "" } */
diff --git a/gcc/testsuite/gcc.dg/struct-ret-2.c b/gcc/testsuite/gcc.dg/struct-ret-2.c
index b440bcf..0d9b86f 100644
--- a/gcc/testsuite/gcc.dg/struct-ret-2.c
+++ b/gcc/testsuite/gcc.dg/struct-ret-2.c
@@ -4,7 +4,7 @@
Copyright (C) 1999 Free Software Foundation */
/* { dg-do compile } */
-/* { dg-options "-O3" } */
+/* { dg-options "-O3 -w" } */
struct {
unsigned i[4];
diff --git a/gcc/testsuite/gcc.misc-tests/bprob-1.c b/gcc/testsuite/gcc.misc-tests/bprob-1.c
index 3d6055a..9420250 100644
--- a/gcc/testsuite/gcc.misc-tests/bprob-1.c
+++ b/gcc/testsuite/gcc.misc-tests/bprob-1.c
@@ -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);
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-4.c b/gcc/testsuite/gcc.misc-tests/gcov-4.c
index d5986fe..27ef508 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-4.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-4.c
@@ -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);
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-4b.c b/gcc/testsuite/gcc.misc-tests/gcov-4b.c
index 6bc20e0..72870b2 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-4b.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-4b.c
@@ -41,7 +41,7 @@ test_for2 (int m, int n, int o)
return for_temp;
}
-int
+void
call_for ()
{
for_val1 += test_for1 (0);