]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c-family: Implicitly return zero from main even on freestanding
authorArsen Arsenović <arsen@aarsen.me>
Fri, 14 Oct 2022 10:04:51 +0000 (12:04 +0200)
committerJason Merrill <jason@redhat.com>
Mon, 24 Oct 2022 13:37:33 +0000 (09:37 -0400)
... unless marked noreturn.

This should not get in anyone's way, but should permit the use of main()
in freestanding more easily, especially for writing test cases that
should work both in freestanding and hosted modes.

gcc/c/ChangeLog:

* c-decl.cc (finish_function): Ignore hosted when deciding
whether to implicitly return zero, but check noreturn.
* c-objc-common.cc (c_missing_noreturn_ok_p): Loosen the
requirements to just MAIN_NAME_P when hosted, or `int main'
otherwise.

gcc/cp/ChangeLog:

* cp-tree.h (DECL_MAIN_P): Move most logic, besides the hosted
check, from here...
(DECL_MAIN_ANY_P): ... to here, so that it can be reused ...
(DECL_MAIN_FREESTANDING_P): ... here, with an additional
constraint on (hosted OR return type == int)
* decl.cc (finish_function): Use DECL_MAIN_FREESTANDING_P
instead of DECL_MAIN_P, to loosen the hosted requirement, but
check noreturn, before adding implicit returns.

gcc/testsuite/ChangeLog:

* gcc.dg/noreturn-4.c: Removed.
* g++.dg/freestanding-main.C: New test.
* g++.dg/freestanding-nonint-main.C: New test.
* gcc.dg/freestanding-main.c: New test.
* gcc.dg/freestanding-nonint-main.c: New test.

gcc/c/c-decl.cc
gcc/c/c-objc-common.cc
gcc/cp/cp-tree.h
gcc/cp/decl.cc
gcc/testsuite/g++.dg/freestanding-main.C [new file with mode: 0644]
gcc/testsuite/g++.dg/freestanding-nonint-main.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/freestanding-main.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/freestanding-nonint-main.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/noreturn-4.c [deleted file]

index 80f6e91218787ee62b9509f3fe531f6b2f983243..4746e310d2d6ac2fbd03ac021352b86f330648b6 100644 (file)
@@ -10542,7 +10542,7 @@ finish_function (location_t end_loc)
   if (DECL_RESULT (fndecl) && DECL_RESULT (fndecl) != error_mark_node)
     DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
 
-  if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted
+  if (MAIN_NAME_P (DECL_NAME (fndecl)) && !TREE_THIS_VOLATILE (fndecl)
       && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
       == integer_type_node && flag_isoc99)
     {
index 70e10a98e3363c657f455b600f776834dd2c0e8c..b4680912547c2da9b328c13234d8c85ba7e412af 100644 (file)
@@ -37,9 +37,12 @@ static bool c_tree_printer (pretty_printer *, text_info *, const char *,
 bool
 c_missing_noreturn_ok_p (tree decl)
 {
-  /* A missing noreturn is not ok for freestanding implementations and
-     ok for the `main' function in hosted implementations.  */
-  return flag_hosted && MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
+  /* A missing noreturn is ok for the `main' function.  */
+  if (!MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl)))
+    return false;
+
+  return flag_hosted
+    || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == integer_type_node;
 }
 
 /* Called from check_global_declaration.  */
index 60a251010493d483ae1ca4584f2d38601ffca197..2cca20be6c1d3248ed99c2589037dbff5f5ddb74 100644 (file)
@@ -772,11 +772,20 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
 
 /* Returns nonzero iff NODE is a declaration for the global function
    `main'.  */
-#define DECL_MAIN_P(NODE)                              \
+#define DECL_MAIN_ANY_P(NODE)                          \
    (DECL_EXTERN_C_FUNCTION_P (NODE)                    \
     && DECL_NAME (NODE) != NULL_TREE                   \
-    && MAIN_NAME_P (DECL_NAME (NODE))                  \
-    && flag_hosted)
+    && MAIN_NAME_P (DECL_NAME (NODE)))
+
+/* Nonzero iff NODE is a declaration for `int main', or we are hosted. */
+#define DECL_MAIN_FREESTANDING_P(NODE)                         \
+  (DECL_MAIN_ANY_P(NODE)                                       \
+   && (flag_hosted                                             \
+       || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (NODE)))     \
+         == integer_type_node))
+
+/* Nonzero iff NODE is a declaration for `main', and we are hosted. */
+#define DECL_MAIN_P(NODE) (DECL_MAIN_ANY_P(NODE) && flag_hosted)
 
 /* Lookup walker marking.  */
 #define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE)
index 85b892cddf043fd19f490f4cd4c2ead48c1275e0..bc085f8fcce4c0c25640f195d21568c6d524bf0b 100644 (file)
@@ -17852,7 +17852,8 @@ finish_function (bool inline_p)
   if (!DECL_CLONED_FUNCTION_P (fndecl))
     {
       /* Make it so that `main' always returns 0 by default.  */
-      if (DECL_MAIN_P (current_function_decl))
+      if (DECL_MAIN_FREESTANDING_P (current_function_decl)
+         && !TREE_THIS_VOLATILE (current_function_decl))
        finish_return_stmt (integer_zero_node);
 
       if (use_eh_spec_block (current_function_decl))
diff --git a/gcc/testsuite/g++.dg/freestanding-main.C b/gcc/testsuite/g++.dg/freestanding-main.C
new file mode 100644 (file)
index 0000000..3718cc4
--- /dev/null
@@ -0,0 +1,5 @@
+/* Make sure we don't get a missing return warning on freestanding. */
+/* { dg-do compile } */
+/* { dg-options "-ffreestanding -Wreturn-type" } */
+
+int main() {}
diff --git a/gcc/testsuite/g++.dg/freestanding-nonint-main.C b/gcc/testsuite/g++.dg/freestanding-nonint-main.C
new file mode 100644 (file)
index 0000000..a8571cc
--- /dev/null
@@ -0,0 +1,5 @@
+/* Check that we get the right warning for nonint main in freestanding. */
+/* { dg-do compile } */
+/* { dg-options "-ffreestanding -Wreturn-type" } */
+
+const char *main() {} /* { dg-warning "-Wreturn-type" } */
diff --git a/gcc/testsuite/gcc.dg/freestanding-main.c b/gcc/testsuite/gcc.dg/freestanding-main.c
new file mode 100644 (file)
index 0000000..3718cc4
--- /dev/null
@@ -0,0 +1,5 @@
+/* Make sure we don't get a missing return warning on freestanding. */
+/* { dg-do compile } */
+/* { dg-options "-ffreestanding -Wreturn-type" } */
+
+int main() {}
diff --git a/gcc/testsuite/gcc.dg/freestanding-nonint-main.c b/gcc/testsuite/gcc.dg/freestanding-nonint-main.c
new file mode 100644 (file)
index 0000000..d839334
--- /dev/null
@@ -0,0 +1,5 @@
+/* Check that we get the right warning for nonint main in freestanding. */
+/* { dg-do compile } */
+/* { dg-options "-ffreestanding -Wreturn-type" } */
+
+const char *main(void) {} /* { dg-warning "-Wreturn-type" } */
diff --git a/gcc/testsuite/gcc.dg/noreturn-4.c b/gcc/testsuite/gcc.dg/noreturn-4.c
deleted file mode 100644 (file)
index 6fe1447..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* Check for "noreturn" warning in main. */
-/* { dg-do compile } */
-/* { dg-options "-O2 -Wmissing-noreturn -ffreestanding" } */
-extern void exit (int) __attribute__ ((__noreturn__));
-
-int
-main (void) /* { dg-warning "function might be candidate for attribute 'noreturn'" "warn for main" } */
-{
-  exit (0);
-}