]> gcc.gnu.org Git - gcc.git/commitdiff
c-decl.c (finish_function): Warn about a non-void function with no return statement...
authorJason Merrill <jason@redhat.com>
Wed, 6 Feb 2002 20:40:18 +0000 (15:40 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 6 Feb 2002 20:40:18 +0000 (15:40 -0500)
        * 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

20 files changed:
gcc/ChangeLog
gcc/c-decl.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/testsuite/gcc.dg/20011029-2.c
gcc/testsuite/gcc.dg/980816-1.c
gcc/testsuite/gcc.dg/990117-1.c
gcc/testsuite/gcc.dg/990213-2.c
gcc/testsuite/gcc.dg/990214-1.c
gcc/testsuite/gcc.dg/990524-1.c
gcc/testsuite/gcc.dg/991214-1.c
gcc/testsuite/gcc.dg/asm-2.c
gcc/testsuite/gcc.dg/asm-3.c
gcc/testsuite/gcc.dg/attr-invalid.c
gcc/testsuite/gcc.dg/attr-noinline.c
gcc/testsuite/gcc.dg/deprecated.c
gcc/testsuite/gcc.dg/struct-ret-2.c
gcc/testsuite/gcc.misc-tests/bprob-1.c
gcc/testsuite/gcc.misc-tests/gcov-4.c
gcc/testsuite/gcc.misc-tests/gcov-4b.c

index 96baa91fc6cb7a17d020cfdb9416673577f7ffc1..c1ba34f534fb2065f9541b4599bf0116da9913db 100644 (file)
@@ -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:
index af6a2c0ef597ead60758d1e06d805609d27b5982..746fa470dff44c302c24f5f87b009b77f1556486 100644 (file)
@@ -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;
index 03bd683716a5b4faa5cf935d7aef780f09ac94a8..8f53b17e6bce7b1808cd1d9d9e2f320930993ec4 100644 (file)
@@ -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.  */
 
index 8c34a17c5d3ab1b278bb288f489474c1fc7b45f4..dc844bfb7a3a0ba9e589b8b79507d4f0fa767a83 100644 (file)
@@ -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));
index 77a5b0776cd6790a7e464ea3ad3bed445256606b..b184af088d10d444f6f6fd1cd8301a37db084c7d 100644 (file)
@@ -20,4 +20,5 @@ int foo (int s)
                                        : "cc"); r; }))
         continue;
     }
+  return 0;
 }
index 2a96ef4bcc95b65e79bcf0e39c5f6ed7a545e9bc..8581d999dbd64a74631a8bbbc23e939155742c8e 100644 (file)
@@ -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;
 }
index 2e7ea5a1551da3b4c75f2c327251cf80223e85f8..606ba440ca8245b435f8ff543c8d248e6c745fda 100644 (file)
@@ -18,4 +18,5 @@ foo ()
   for (i = 0; i < 10; i++)
     ;
   fabs (x - y);
+  return 0;
 }
index 6e6b924ed898053e2c26ad07dd61dac2c6bf1bed..a0a13b560f9b52c9ca4a2e4f7878d15f2f4551e7 100644 (file)
@@ -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;
 }
index 492c6a7dcea29e60ef2bd2ea066cc201a555067b..7ad81b6b90bcdeced8d1457f27af3d3cde0580f6 100644 (file)
@@ -12,4 +12,6 @@ bar (int64_t which)
        case 5 :
        case 2 : ;
        }
+
+       return 0;
 }
index b87b5883a115e62fd0e7de20fcdf163989eb2b1f..8b1017245033d7d9fa149c1356dcc2f98c687dc7 100644 (file)
@@ -34,5 +34,5 @@ p_frames_to_multilayer(t_anim_info *ainfo_ptr,
        break;
     l_cur_frame_nr += l_step;
   }
+  return 0;
 }
-
index 5b9f56c277e11b8242f359263c41f325a98130c0..c8e3a04049d39f6557b273eeb1b98ed0d9dfe935 100644 (file)
@@ -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));
 }
index 5adee41b9c6f28a15ed5ca806a2cc86d4c5cc14a..9c464ce89412f63c4fda350da423220ab38b4857 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "" } */
 
-int f()
+void f()
 {
   asm volatile ("foo%%bar" : : );
 }
index e7db804c18adbbf8e4ada24d00adb2c3b6b9e40a..917942d7b698a39b92d907dbb25af7d176921c88 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "" } */
 
-int f()
+void f()
 {
   asm ("foo%%bar");
 }
index 768921d8b18c9a85a9e2f24e04a5f1a4c9b721ad..a999c267c3aba4bd98239d573a5d753b502f19c3 100644 (file)
@@ -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;
 }
index 903959e09f174e538900cabac0956b7a7f183c95..ee48eb9ed7e29cd226e5b9b449bb641357c9507e 100644 (file)
@@ -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 ();
index bc82c6d620093bdee9ef27097d6689b0a6c62603..83557475c445f865f87948d9c4117e3c9f38ca10 100644 (file)
@@ -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" "" } */
 
index b440bcfb9146137505dd774b7169c19f4a9ead23..0d9b86f6fe53718f1406cf5d80bccef1cf7c5ea9 100644 (file)
@@ -4,7 +4,7 @@
    Copyright (C) 1999 Free Software Foundation  */
 
 /* { dg-do compile } */
-/* { dg-options "-O3" } */
+/* { dg-options "-O3 -w" } */
 
 struct {
   unsigned i[4];
index 3d6055a2f9f9e4a5d26f5245ddd69e1b344f0f7d..94202504fb586996ee0247c203dc9f608fd1f0f4 100644 (file)
@@ -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);
index d5986fe4b8b7f1420e39cd425ab89d2bf66a897d..27ef508cfe6cc39889897b24918dcc54ecda0ea9 100644 (file)
@@ -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);
index 6bc20e0005a4dd3eaa5852147407695a6071eed2..72870b20952d566aba487ef94091f3ffa10d21b3 100644 (file)
@@ -41,7 +41,7 @@ test_for2 (int m, int n, int o)
   return for_temp;
 }
 
-int
+void
 call_for ()
 {
   for_val1 += test_for1 (0);
This page took 0.091235 seconds and 5 git commands to generate.