aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorArsen Arsenović <arsen@aarsen.me>2022-10-14 12:04:51 +0200
committerJason Merrill <jason@redhat.com>2022-10-24 09:37:33 -0400
commitf44575cb88727193386428e9ced3439e4f98f493 (patch)
tree676300379ab6560f5333503d820489ecab859ef0 /gcc/cp
parent5bcd92d0d4029f3d1d2eacc0e2bff1685545b74f (diff)
downloadgcc-f44575cb88727193386428e9ced3439e4f98f493.zip
gcc-f44575cb88727193386428e9ced3439e4f98f493.tar.gz
gcc-f44575cb88727193386428e9ced3439e4f98f493.tar.bz2
c-family: Implicitly return zero from main even on freestanding
... 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.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/cp-tree.h15
-rw-r--r--gcc/cp/decl.cc3
2 files changed, 14 insertions, 4 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 60a2510..2cca20b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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)
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 85b892c..bc085f8 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -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))