* Add '_Defer' as an extension to all c versions, while keeping 'defer'
gated behind '-fdefer-ts'. This matches the behaviour that clang is
going[3] for and the new ts revision[4].

---

* 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
3: https://github.com/llvm/llvm-project/pull/162848
4: 
https://thephd.dev/_vendor/future_cxx/technical%20specification/C%20-%20defer/C%20-%20defer%20Technical%20Specification.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       |   2 +
 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 |   8 ++
 14 files changed, 565 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 v4:
1:  da835e79572 = 1:  da835e79572 c: handle expression nodes in push_cleanup
2:  b0fd9d8165a = 2:  b0fd9d8165a c: introduce jump barriers for statement 
expressions
3:  a43878af76c ! 3:  60197f74dab c: implement the defer keyword
    @@ Metadata
      ## Commit message ##
         c: implement the defer keyword
     
    -    based on the technical specification n3589[1], and set behind the
    -    command line flag '-fdefer-ts'
    +    based on the technical specification 25755[1][2]
    +
    +    the keyword '_Defer' is enabled by default as an extension, while
    +    'defer' is gated by '-fdefer-ts'
     
         deferred statements execute at the end of the scope they're added on,
         similar to the cleanup attribute, and they have much of the same
    @@ Commit message
         and continue, jump out of one
     
         1: https://open-std.org/JTC1/SC22/WG14/www/docs/n3589.pdf
    +    2: 
https://thephd.dev/_vendor/future_cxx/technical%20specification/C%20-%20defer/C%20-%20defer%20Technical%20Specification.pdf
     
         gcc/ChangeLog:
     
    @@ Commit message
     
         gcc/c-family/ChangeLog:
     
    -            * c-common.cc: Add defer keyword.
    +            * c-common.cc: Add defer and _Defer keywords.
                 * c-common.h (enum rid): Add RID_DEFER.
                 (D_CXX11): Adjust.
                 (D_EXT): Likewise.
    @@ Commit message
     
         Signed-off-by: Anna (navi) Figueiredo Gomes <[email protected]>
     
      ## gcc/c-family/c-common.cc ##
    +@@ gcc/c-family/c-common.cc: const struct c_common_resword 
c_common_reswords[] =
    +   { "_Decimal64",       RID_DFLOAT64,  D_CONLY },
    +   { "_Decimal128",      RID_DFLOAT128, D_CONLY },
    +   { "_Decimal64x",      RID_DFLOAT64X, D_CONLY },
    ++  { "_Defer",           RID_DEFER,     D_CONLY | D_EXT },
    +   { "_Fract",           RID_FRACT,     D_CONLY | D_EXT },
    +   { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
    +   { "_Sat",             RID_SAT,       D_CONLY | D_EXT },
     @@ gcc/c-family/c-common.cc: const struct c_common_resword 
c_common_reswords[] =
        { "continue",           RID_CONTINUE,   0 },
        { "decltype",         RID_DECLTYPE,   D_CXXONLY | D_CXX11 | D_CXXWARN },
    @@ 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-family/c-cppbuiltin.cc: c_cpp_builtins (cpp_reader *pfile)
        if (flag_iso)
          cpp_define (pfile, "__STRICT_ANSI__");
      
    -+  if (flag_defer_ts)
    ++  if (!flag_no_gnu_keywords || flag_defer_ts)
     +    builtin_define_with_int_value ("__STDC_DEFER_TS25755__", 1);
     +
        if (!flag_signed_char)
    @@ gcc/testsuite/gcc.dg/defer-3.c (new)
      ## gcc/testsuite/gcc.dg/defer-4.c (new) ##
     @@
     +/* { dg-do compile } */
    ++/* { dg-options "" } */
     +
     +int main(void)
     +{
    ++  _Defer;
     +  defer; /* { dg-error "'defer' undeclared" "undeclared identifier" } */
     +}
-- 
2.51.0

Reply via email to