* Remove backwards jump constraint, as per v3 of the ts[2]. bringing the behaviour more in line with the cleanup attribute.
--- * remove the need of -std=c2y for -fdefer-ts to take effect --- * added a test jumping into a defer block from above. * reworded the lookup_label_for_goto error message to mention the error is a jump into the defer block, instead of out. * moved the 'defer' keyword behind a -fdefer-ts flag, and added texinfo docs plus related failure test. --- based on n3589[1], this feature mostly makes use of already-established logic, namely push_cleanup used by the cleanup attribute, and the constraints put in place for checking local jumps against statement expressions 1: https://open-std.org/JTC1/SC22/WG14/www/docs/n3589.pdf 2: https://open-std.org/JTC1/SC22/WG14/www/docs/n3688.pdf Anna (navi) Figueiredo Gomes (3): c: handle expression nodes in push_cleanup c: introduce jump barriers for statement expressions c: implement the defer keyword gcc/c-family/c-common.cc | 1 + gcc/c-family/c-common.h | 2 + gcc/c-family/c-cppbuiltin.cc | 3 + gcc/c-family/c.opt | 4 + gcc/c/c-decl.cc | 136 +++++++++++++----- gcc/c/c-parser.cc | 41 ++++++ gcc/c/c-tree.h | 8 +- gcc/c/c-typeck.cc | 56 ++++++-- gcc/doc/invoke.texi | 6 +- gcc/doc/standards.texi | 3 +- gcc/testsuite/gcc.dg/defer-1.c | 255 +++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/defer-2.c | 76 ++++++++++ gcc/testsuite/gcc.dg/defer-3.c | 15 ++ gcc/testsuite/gcc.dg/defer-4.c | 6 + 14 files changed, 562 insertions(+), 50 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/defer-1.c create mode 100644 gcc/testsuite/gcc.dg/defer-2.c create mode 100644 gcc/testsuite/gcc.dg/defer-3.c create mode 100644 gcc/testsuite/gcc.dg/defer-4.c Range-diff against v3: 1: da835e79572 = 1: da835e79572 c: handle expression nodes in push_cleanup 2: b0fd9d8165a = 2: b0fd9d8165a c: introduce jump barriers for statement expressions 3: 466a5360e73 ! 3: 113bd001f17 c: implement the defer keyword @@ Commit message Signed-off-by: Anna (navi) Figueiredo Gomes <[email protected]> - - ## Notes ## - v3: - * remove the need of -std=c2y for -fdefer-ts to take effect - v2: - * added a test jumping into a defer block from above. - * reworded the lookup_label_for_goto error message to mention the error - is a jump into the defer block, instead of out. - * moved the 'defer' keyword behind a -fdefer-ts flag, and added texinfo - docs plus related failure test. - ## gcc/c-family/c-common.cc ## @@ gcc/c-family/c-common.cc: const struct c_common_resword c_common_reswords[] = { "continue", RID_CONTINUE, 0 }, @@ gcc/c-family/c-common.cc: const struct c_common_resword c_common_reswords[] = ## gcc/c-family/c-common.h ## @@ gcc/c-family/c-common.h: enum rid - RID_IMAGINARY, - - /* C */ -- RID_INT, RID_CHAR, RID_FLOAT, RID_DOUBLE, RID_VOID, -- RID_ENUM, RID_STRUCT, RID_UNION, RID_IF, RID_ELSE, -- RID_WHILE, RID_DO, RID_FOR, RID_SWITCH, RID_CASE, -- RID_DEFAULT, RID_BREAK, RID_CONTINUE, RID_RETURN, RID_GOTO, -- RID_SIZEOF, RID_BITINT, -+ RID_INT, RID_CHAR, RID_FLOAT, RID_DOUBLE, RID_VOID, -+ RID_ENUM, RID_STRUCT, RID_UNION, RID_IF, RID_ELSE, -+ RID_WHILE, RID_DO, RID_FOR, RID_SWITCH, RID_CASE, -+ RID_DEFAULT, RID_DEFER, RID_BREAK, RID_CONTINUE, RID_RETURN, -+ RID_GOTO, RID_SIZEOF, RID_BITINT, - - /* C extensions */ - RID_ASM, RID_TYPEOF, RID_TYPEOF_UNQUAL, RID_ALIGNOF, RID_ATTRIBUTE, + RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER, RID_BUILTIN_STDC, + RID_BUILTIN_COUNTED_BY_REF, + RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, RID_DFLOAT64X, ++ RID_DEFER, + + /* TS 18661-3 keywords, in the same sequence as the TI_* values. */ + RID_FLOAT16, @@ gcc/c-family/c-common.h: extern machine_mode c_default_pointer_mode; - #define D_CXXONLY 0x0002 /* C++ only (not in C). */ - #define D_C99 0x0004 /* In C, C99 only. */ - #define D_C23 0x0008 /* In C, C23 only. */ --#define D_CXX11 0x0010 /* In C++, C++11 only. */ --#define D_EXT 0x0020 /* GCC extension. */ --#define D_EXT89 0x0040 /* GCC extension incorporated in C99. */ --#define D_EXT11 0x0080 /* GCC extension incorporated in C23. */ --#define D_ASM 0x0100 /* Disabled by -fno-asm. */ --#define D_OBJC 0x0200 /* In Objective C and neither C nor C++. */ --#define D_CXX_OBJC 0x0400 /* In Objective C, and C++, but not C. */ --#define D_CXXWARN 0x0800 /* In C warn with -Wcxx-compat. */ --#define D_CXX_CONCEPTS 0x1000 /* In C++, only with concepts. */ --#define D_TRANSMEM 0x2000 /* C++ transactional memory TS. */ --#define D_CXX_CHAR8_T 0x4000 /* In C++, only with -fchar8_t. */ --#define D_CXX20 0x8000 /* In C++, C++20 only. */ --#define D_CXX_COROUTINES 0x10000 /* In C++, only with coroutines. */ --#define D_CXX_MODULES 0x20000 /* In C++, only with modules. */ -+#define D_DEFER 0x0010 /* C defer statements TS. */ -+#define D_CXX11 0x0020 /* In C++, C++11 only. */ -+#define D_EXT 0x0040 /* GCC extension. */ -+#define D_EXT89 0x0080 /* GCC extension incorporated in C99. */ -+#define D_EXT11 0x0100 /* GCC extension incorporated in C23. */ -+#define D_ASM 0x0200 /* Disabled by -fno-asm. */ -+#define D_OBJC 0x0400 /* In Objective C and neither C nor C++. */ -+#define D_CXX_OBJC 0x0800 /* In Objective C, and C++, but not C. */ -+#define D_CXXWARN 0x1000 /* In C warn with -Wcxx-compat. */ -+#define D_CXX_CONCEPTS 0x2000 /* In C++, only with concepts. */ -+#define D_TRANSMEM 0x4000 /* C++ transactional memory TS. */ -+#define D_CXX_CHAR8_T 0x8000 /* In C++, only with -fchar8_t. */ -+#define D_CXX20 0x10000 /* In C++, C++20 only. */ -+#define D_CXX_COROUTINES 0x20000 /* In C++, only with coroutines. */ -+#define D_CXX_MODULES 0x40000 /* In C++, only with modules. */ + #define D_CXX20 0x8000 /* In C++, C++20 only. */ + #define D_CXX_COROUTINES 0x10000 /* In C++, only with coroutines. */ + #define D_CXX_MODULES 0x20000 /* In C++, only with modules. */ ++#define D_DEFER 0x40000 /* In C, only with -fdefer-ts */ #define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS #define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T @@ gcc/c/c-decl.cc: lookup_label_for_goto (location_t loc, tree name) + error_at (loc, "jump into defer block"); + inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label); + } -+ else if (label_vars->label_bindings.scope->has_defer_block) -+ { -+ error_at (loc, "jump over defer block"); -+ inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label); -+ } + return label; } @@ gcc/testsuite/gcc.dg/defer-1.c (new) + return *arg; +} + -+ int ++int q () ++{ ++ int r = 1; ++ { ++b: ++ defer r *= 2; ++ if (r < 10) ++ goto b; ++ } ++ ++ return r; ++} ++ ++int r () ++{ ++ int r = 1; ++ { ++ defer r *= 2; ++b: ++ if (r < 10) ++ { ++ r++; ++ goto b; ++ } ++ } ++ ++ return r; ++} ++ ++int +main () +{ + int arg; @@ gcc/testsuite/gcc.dg/defer-1.c (new) + assert (n () == 1); + assert (o () == 6); + assert (p (&arg) == 2 && arg == 4); ++ assert (q () == 32); ++ assert (r () == 20); + + return 0; +} @@ gcc/testsuite/gcc.dg/defer-2.c (new) + continue; /* { dg-error "continue statement jumps out of defer block" } */ + } + } -+} -+ -+int i () -+{ -+ int r = 1; -+ { -+b: -+ r++; -+ defer r *= 2; -+ if (r < 10) -+ goto b; /* { dg-error "jump over defer block" } */ -+ } -+ -+ return r; +} ## gcc/testsuite/gcc.dg/defer-3.c (new) ## -- 2.49.1
