Same behaviour as v6, _Defer as a c extension matchin clang's
implementation, but addressing pinksia's review on v5.

navi (3):
  c: handle expression nodes in push_cleanup
  c: introduce jump barriers for statement expressions
  c: implement defer

 gcc/Makefile.in                |   1 +
 gcc/c-family/c-common.cc       |   1 +
 gcc/c-family/c-common.h        |   1 +
 gcc/c-family/c-cppbuiltin.cc   |   3 +
 gcc/c/c-decl.cc                | 190 ++++++++++++++++--------
 gcc/c/c-parser.cc              |  39 +++++
 gcc/c/c-tree.h                 |   8 +-
 gcc/c/c-typeck.cc              |  60 ++++++--
 gcc/ginclude/stddefer.h        |  38 +++++
 gcc/testsuite/gcc.dg/defer-1.c | 256 +++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/defer-2.c |  78 ++++++++++
 gcc/testsuite/gcc.dg/defer-3.c |  17 +++
 gcc/testsuite/gcc.dg/defer-4.c |   8 ++
 13 files changed, 629 insertions(+), 71 deletions(-)
 create mode 100644 gcc/ginclude/stddefer.h
 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 v6:
-:  ----------- > 1:  3aecc7ff96a c: handle expression nodes in push_cleanup
1:  edcbef53584 ! 2:  3383d769fb2 c: introduce jump barriers for statement 
expressions
    @@ gcc/c/c-decl.cc: set_spot_bindings (struct c_spot_bindings *p, bool 
defining)
      
      /* Update spot bindings P as we pop out of SCOPE.  Return true if we
     @@ gcc/c/c-decl.cc: finish_underspecified_init (tree name, unsigned int 
prev_state)
    +   in_underspecified_init = (prev_state & (1u << 1)) >> 1;
    + }
      
    - /* Adjust the bindings for the start of a statement expression.  */
    - 
    +-/* Adjust the bindings for the start of a statement expression.  */
    ++
    ++/* Push or pop the jump barrier count of a statement expression.  */
    ++
     +static void
     +c_binding_adjust_jump_barrier (struct c_spot_bindings *binding, bool 
start)
     +{
    -+  struct c_jump_barrier *barrier = &binding->stmt_exprs;
    -+  barrier->count += start ? 1 : -1;
    ++  struct c_jump_barrier *barrier = defer
    ++    ? &binding->defer_blocks
    ++    : &binding->stmt_exprs;
    ++
    ++  if (start)
    ++    barrier->count++;
    ++  else
    ++    barrier->count--;
    ++
     +  if (barrier->count < 0)
     +    {
     +      barrier->count = 0;
    @@ gcc/c/c-decl.cc: finish_underspecified_init (tree name, unsigned int 
prev_state)
     +    }
     +}
     +
    ++/* Adjust the bindings for the start of a statement expression or defer 
block.  */
    + 
      void
      c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings)
    - {
     @@ gcc/c/c-decl.cc: c_bindings_start_stmt_expr (struct c_spot_bindings* 
switch_bindings)
          if (TREE_CODE (b->decl) != LABEL_DECL)
            continue;
    @@ gcc/c/c-decl.cc: c_bindings_start_stmt_expr (struct c_spot_bindings* 
switch_bind
     +      c_binding_adjust_jump_barrier (switch_bindings, true);
      }
      
    - /* Adjust the bindings for the end of a statement expression.  */
    +-/* Adjust the bindings for the end of a statement expression.  */
    ++/* Adjust the bindings for the end of a statement expression or defer 
block.  */
    + 
    + void
    + c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings)
     @@ gcc/c/c-decl.cc: c_bindings_end_stmt_expr (struct c_spot_bindings 
*switch_bindings)
          if (TREE_CODE (b->decl) != LABEL_DECL)
            continue;
2:  476d6e8e0d2 ! 3:  c43bf8c8fce c: implement defer
    @@ Commit message
         gcc/ChangeLog:
     
                 * Makefile.in:
    -            * doc/invoke.texi:
                 * ginclude/stddefer.h: New file.
     
         gcc/c-family/ChangeLog:
    @@ 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_BUILTIN_HAS_ATTRIBUTE,   RID_BUILTIN_ASSOC_BARRIER,  
RID_BUILTIN_STDC,
    -   RID_BUILTIN_COUNTED_BY_REF,
    +   RID_BUILTIN_COUNTED_BY_REF,  RID_BUILTIN_BSWAPG,
    +   RID_BUILTIN_BITREVERSEG,
        RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, RID_DFLOAT64X,
     +  RID_DEFER,
      
    @@ gcc/c/c-decl.cc: struct GTY(()) c_spot_bindings {
     @@ gcc/c/c-decl.cc: struct GTY((chain_next ("%h.outer"))) c_scope {
           decl_jump_unsafe would return true for any of the bindings.  This
           is used to avoid looping over all the bindings unnecessarily.  */
    -   BOOL_BITFIELD has_jump_unsafe_decl : 1;
    +   bool has_jump_unsafe_decl : 1;
     +
     +  /* True if this scope has any deferred statement.  This is used to
     +   * check invalid goto jumps. */
    -+  BOOL_BITFIELD has_defer_block : 1;
    ++  bool has_defer_block : 1;
      };
      
      /* The scope currently in effect.  */
    @@ gcc/c/c-decl.cc: set_spot_bindings (struct c_spot_bindings *p, bool 
defining)
      
      /* Update spot bindings P as we pop out of SCOPE.  Return true if we
     @@ gcc/c/c-decl.cc: finish_underspecified_init (tree name, unsigned int 
prev_state)
    - /* Adjust the bindings for the start of a statement expression.  */
    + }
    + 
    + 
    +-/* Push or pop the jump barrier count of a statement expression.  */
    ++/* Push or pop the jump barrier count of a statement expression or defer 
block.  */
      
      static void
     -c_binding_adjust_jump_barrier (struct c_spot_bindings *binding, bool 
start)
     +c_binding_adjust_jump_barrier (struct c_spot_bindings *binding,
     +                         bool defer, bool start)
      {
    --  struct c_jump_barrier *barrier = &binding->stmt_exprs;
    -+  struct c_jump_barrier *barrier = defer
    -+    ? &binding->defer_blocks
    -+    : &binding->stmt_exprs;
    -   barrier->count += start ? 1 : -1;
    -   if (barrier->count < 0)
    -     {
    +   struct c_jump_barrier *barrier = defer
    +     ? &binding->defer_blocks
     @@ gcc/c/c-decl.cc: c_binding_adjust_jump_barrier (struct c_spot_bindings 
*binding, bool start)
    - }
    + /* Adjust the bindings for the start of a statement expression or defer 
block.  */
      
      void
     -c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings)
    @@ gcc/c/c-decl.cc: c_bindings_start_stmt_expr (struct c_spot_bindings* 
switch_bind
     +    }
      }
      
    - /* Adjust the bindings for the end of a statement expression.  */
    + /* Adjust the bindings for the end of a statement expression or defer 
block.  */
      
      void
     -c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings)
    @@ gcc/c/c-typeck.cc: c_finish_stmt_expr (location_t loc, tree body)
      }
     -
     +
    ++/* Starts a new deferred block to be executed on scope exit.  */
    ++
     +tree
     +c_begin_defer_block (void)
     +{
    @@ gcc/c/c-typeck.cc: c_finish_stmt_expr (location_t loc, tree body)
     +  return c_begin_compound_stmt (true);
     +}
     +
    ++/* Ends a deferred block.  */
    ++
     +tree
     +c_end_defer_block (location_t loc, tree body)
     +{
-- 
2.54.0

Reply via email to