Hi, On Friday, 7 October 2022 15:51:31 CEST Jason Merrill wrote: > > * gcc.dg/noreturn-4.c: Likewise. > > I'd be inclined to drop this test. That seems like an odd choice, why do that over using another function for the test case? (there's nothing specific to main in this test, and it doesn't even need to link, so using any ol' function should be okay; see attachment)
The attached patch is also v2 of the original builtin-main one submitted earlier. Tested on x86_64-pc-linux-gnu. This revision excludes the mentioned pedwarns unless hosted. Thanks, -- Arsen Arsenović
>From 27a2cf85b1c3eb901413fd135918af0377bd1459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= <ar...@aarsen.me> Date: Tue, 20 Sep 2022 19:17:31 +0200 Subject: [PATCH v2] c-family: Implement new `int main' semantics in freestanding >From now, by default, (specifically) `int main' in freestanding will implicitly return 0, as it does for hosted modes. The old behaviour is still accessible via -fno-builtin-main. gcc/c-family/ChangeLog: * c-common.cc (disable_builtin_function): Support special value `main' that, in freestanding, allows disabling special casing placed around `main'. * c-common.h: Add flag_builtin_main. (want_builtin_main_p): New function, true iff hosted OR builtin_main are set. gcc/c/ChangeLog: * c-decl.cc (grokdeclarator): Consider flag_builtin_main when deciding whether to emit warnings. (finish_function): Consider flag_builtin_main and the noreturn flag when deciding whether to emit an implicit zero return. * c-objc-common.cc (c_missing_noreturn_ok_p): Consider missing noreturn okay only when hosted or when builtin_main is enabled. gcc/cp/ChangeLog: * cp-tree.h (DECL_MAIN_P): Consider flag_builtin_main when deciding whether this function is to be the special function main. * decl.cc (grokfndecl): Only pedwarn on hosted. (finish_function): Do not inject extra return of marked noreturn. gcc/ChangeLog: * doc/invoke.texi: Document -fno-builtin-main. gcc/testsuite/ChangeLog: * gcc.dg/noreturn-4.c: Don't use `main', but a generic function name instead. * g++.dg/freestanding-main-implicitly-returns.C: New test. * g++.dg/no-builtin-main.C: New test. * gcc.dg/freestanding-main-implicitly-returns.c: New test. * gcc.dg/no-builtin-main.c: New test. --- gcc/c-family/c-common.cc | 6 ++++++ gcc/c-family/c-common.h | 10 ++++++++++ gcc/c/c-decl.cc | 4 ++-- gcc/c/c-objc-common.cc | 9 ++++++--- gcc/cp/cp-tree.h | 12 ++++++----- gcc/cp/decl.cc | 6 ++++-- gcc/doc/invoke.texi | 20 ++++++++++++++----- .../freestanding-main-implicitly-returns.C | 5 +++++ gcc/testsuite/g++.dg/no-builtin-main.C | 5 +++++ .../freestanding-main-implicitly-returns.c | 5 +++++ gcc/testsuite/gcc.dg/no-builtin-main.c | 5 +++++ gcc/testsuite/gcc.dg/noreturn-4.c | 6 +++--- 12 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/freestanding-main-implicitly-returns.C create mode 100644 gcc/testsuite/g++.dg/no-builtin-main.C create mode 100644 gcc/testsuite/gcc.dg/freestanding-main-implicitly-returns.c create mode 100644 gcc/testsuite/gcc.dg/no-builtin-main.c diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 9ec9100cc90..f9060cbc171 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -232,6 +232,10 @@ int flag_isoc2x; int flag_hosted = 1; +/* Nonzero means that we want to give main its special meaning */ + +int flag_builtin_main = 1; + /* ObjC language option variables. */ @@ -4879,6 +4883,8 @@ disable_builtin_function (const char *name) { if (startswith (name, "__builtin_")) error ("cannot disable built-in function %qs", name); + else if (strcmp("main", name) == 0) + flag_builtin_main = 0; else { disabled_builtin *new_disabled_builtin = XNEW (disabled_builtin); diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 62ab4ba437b..44537cc6977 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -689,6 +689,16 @@ extern int flag_isoc2x; extern int flag_hosted; +/* Nonzero means that we want to give main its special meaning */ + +extern int flag_builtin_main; + +/* Returns false if both flag_hosted and flag_builtin_main are zero, true + otherwise. */ +inline bool builtin_main_p() { + return flag_hosted || flag_builtin_main; +} + /* ObjC language option variables. */ diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 193e268f04e..891e36b30b6 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -10442,9 +10442,9 @@ 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)) && builtin_main_p() && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) - == integer_type_node && flag_isoc99) + == integer_type_node && flag_isoc99 && !TREE_THIS_VOLATILE (fndecl)) { /* Hack. We don't want the middle-end to warn that this return is unreachable, so we mark its location as special. Using diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index 70e10a98e33..e229580b182 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -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)); + /* Missing a return is only okay when flag_builtin_main is enabled, and we + are `int main'. */ + if (!MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl))) + return false; + return builtin_main_p() + && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == integer_type_node; } /* Called from check_global_declaration. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3b67be651b9..10406fbfb00 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -772,11 +772,13 @@ typedef struct ptrmem_cst * ptrmem_cst_t; /* Returns nonzero iff NODE is a declaration for the global function `main'. */ -#define DECL_MAIN_P(NODE) \ - (DECL_EXTERN_C_FUNCTION_P (NODE) \ - && DECL_NAME (NODE) != NULL_TREE \ - && MAIN_NAME_P (DECL_NAME (NODE)) \ - && flag_hosted) +#define DECL_MAIN_P(NODE) \ + (DECL_EXTERN_C_FUNCTION_P (NODE) \ + && DECL_NAME (NODE) != NULL_TREE \ + && MAIN_NAME_P (DECL_NAME (NODE)) \ + && (flag_hosted || (flag_builtin_main \ + && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (NODE))) \ + == integer_type_node))) /* Lookup walker marking. */ #define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 82eb0c2f22a..54bbd15a1ce 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -10301,7 +10301,8 @@ grokfndecl (tree ctype, if (ctype && funcdef_flag) check_class_member_definition_namespace (decl); - if (ctype == NULL_TREE && DECL_MAIN_P (decl)) + /* We should only be pedantic about main if hosted. */ + if (ctype == NULL_TREE && DECL_MAIN_P (decl) && flag_hosted) { if (PROCESSING_REAL_TEMPLATE_DECL_P()) error_at (location, "cannot declare %<::main%> to be a template"); @@ -17854,7 +17855,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_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/doc/invoke.texi b/gcc/doc/invoke.texi index a9ecc4426a4..41d7fa6f922 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2541,8 +2541,10 @@ the @code{asm} keyword, since @code{typeof} is a standard keyword in ISO C2X. @item -fno-builtin +@itemx -fno-builtin-main @itemx -fno-builtin-@var{function} @opindex fno-builtin +@opindex fno-builtin-main @opindex fbuiltin @cindex built-in functions Don't recognize built-in functions that do not begin with @@ -2581,6 +2583,11 @@ built-in functions selectively when using @option{-fno-builtin} or #define strcpy(d, s) __builtin_strcpy ((d), (s)) @end smallexample +The special form @option{-fno-builtin-main} permits disabling special +handling of the @code{main} function, such as the implicit zero +return. This option has no effect in hosted mode (as hosted takes +precedence over it) and is not implied by @option{-fno-builtin}. + @item -fcond-mismatch @opindex fcond-mismatch Allow conditional expressions with mismatched types in the second and @@ -2589,13 +2596,16 @@ is not supported for C++. @item -ffreestanding @opindex ffreestanding +@opindex fno-builtin-main @cindex hosted environment Assert that compilation targets a freestanding environment. This -implies @option{-fno-builtin}. A freestanding environment -is one in which the standard library may not exist, and program startup may -not necessarily be at @code{main}. The most obvious example is an OS kernel. -This is equivalent to @option{-fno-hosted}. +implies @option{-fno-builtin}. A freestanding environment is one in +which the standard library may not exist, and program startup may not +necessarily be at @code{main}. The most obvious example is an OS +kernel. Note that this option does not imply +@option{-fno-builtin-main}. @option{-ffreestanding} is equivalent to +@option{-fno-hosted}. @xref{Standards,,Language Standards Supported by GCC}, for details of freestanding and hosted environments. @@ -5864,7 +5874,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. -Wimplicit-function-declaration @r{(C and Objective-C only)} @gol -Winit-self @r{(only for C++)} @gol -Wlogical-not-parentheses @gol --Wmain @r{(only for C/ObjC and unless} @option{-ffreestanding}@r{)} @gol +-Wmain @r{(only for C/ObjC and unless} @option{-fno-builtin-main}@r{)} @gol -Wmaybe-uninitialized @gol -Wmemset-elt-size @gol -Wmemset-transposed-args @gol diff --git a/gcc/testsuite/g++.dg/freestanding-main-implicitly-returns.C b/gcc/testsuite/g++.dg/freestanding-main-implicitly-returns.C new file mode 100644 index 00000000000..068ddd4d5ad --- /dev/null +++ b/gcc/testsuite/g++.dg/freestanding-main-implicitly-returns.C @@ -0,0 +1,5 @@ +/* Make sure main is implicitly returned from, even in freestanding. */ +/* { dg-do compile } */ +/* { dg-options "-Wreturn-type -ffreestanding" } */ + +int main() {} diff --git a/gcc/testsuite/g++.dg/no-builtin-main.C b/gcc/testsuite/g++.dg/no-builtin-main.C new file mode 100644 index 00000000000..7431784d018 --- /dev/null +++ b/gcc/testsuite/g++.dg/no-builtin-main.C @@ -0,0 +1,5 @@ +/* Make sure we get warned about missing return with -fno-builtin-main. */ +/* { dg-do compile } */ +/* { dg-options "-Wreturn-type -ffreestanding -fno-builtin-main" } */ + +int main() {} /* { dg-warning "-Wreturn-type" } */ diff --git a/gcc/testsuite/gcc.dg/freestanding-main-implicitly-returns.c b/gcc/testsuite/gcc.dg/freestanding-main-implicitly-returns.c new file mode 100644 index 00000000000..068ddd4d5ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/freestanding-main-implicitly-returns.c @@ -0,0 +1,5 @@ +/* Make sure main is implicitly returned from, even in freestanding. */ +/* { dg-do compile } */ +/* { dg-options "-Wreturn-type -ffreestanding" } */ + +int main() {} diff --git a/gcc/testsuite/gcc.dg/no-builtin-main.c b/gcc/testsuite/gcc.dg/no-builtin-main.c new file mode 100644 index 00000000000..7431784d018 --- /dev/null +++ b/gcc/testsuite/gcc.dg/no-builtin-main.c @@ -0,0 +1,5 @@ +/* Make sure we get warned about missing return with -fno-builtin-main. */ +/* { dg-do compile } */ +/* { dg-options "-Wreturn-type -ffreestanding -fno-builtin-main" } */ + +int main() {} /* { dg-warning "-Wreturn-type" } */ diff --git a/gcc/testsuite/gcc.dg/noreturn-4.c b/gcc/testsuite/gcc.dg/noreturn-4.c index 6fe144754d0..ddedb0896db 100644 --- a/gcc/testsuite/gcc.dg/noreturn-4.c +++ b/gcc/testsuite/gcc.dg/noreturn-4.c @@ -1,10 +1,10 @@ /* Check for "noreturn" warning in main. */ /* { dg-do compile } */ -/* { dg-options "-O2 -Wmissing-noreturn -ffreestanding" } */ +/* { dg-options "-O2 -Wmissing-noreturn" } */ extern void exit (int) __attribute__ ((__noreturn__)); -int -main (void) /* { dg-warning "function might be candidate for attribute 'noreturn'" "warn for main" } */ +void +f (void) /* { dg-warning "function might be candidate for attribute 'noreturn'" "warn for main" } */ { exit (0); } -- 2.38.0
signature.asc
Description: This is a digitally signed message part.