gcc: Nested Functions

1 
1 6.4 Nested Functions
1 ====================
1 
1 A "nested function" is a function defined inside another function.
1 Nested functions are supported as an extension in GNU C, but are not
1 supported by GNU C++.
1 
1  The nested function's name is local to the block where it is defined.
1 For example, here we define a nested function named 'square', and call
1 it twice:
1 
1      foo (double a, double b)
1      {
1        double square (double z) { return z * z; }
1 
1        return square (a) + square (b);
1      }
1 
1  The nested function can access all the variables of the containing
1 function that are visible at the point of its definition.  This is
1 called "lexical scoping".  For example, here we show a nested function
1 which uses an inherited variable named 'offset':
1 
1      bar (int *array, int offset, int size)
1      {
1        int access (int *array, int index)
1          { return array[index + offset]; }
1        int i;
1        /* ... */
1        for (i = 0; i < size; i++)
1          /* ... */ access (array, i) /* ... */
1      }
1 
1  Nested function definitions are permitted within functions in the
1 places where variable definitions are allowed; that is, in any block,
1 mixed with the other declarations and statements in the block.
1 
1  It is possible to call the nested function from outside the scope of
1 its name by storing its address or passing the address to another
1 function:
1 
1      hack (int *array, int size)
1      {
1        void store (int index, int value)
1          { array[index] = value; }
1 
1        intermediate (store, size);
1      }
1 
1  Here, the function 'intermediate' receives the address of 'store' as an
1 argument.  If 'intermediate' calls 'store', the arguments given to
1 'store' are used to store into 'array'.  But this technique works only
1 so long as the containing function ('hack', in this example) does not
1 exit.
1 
1  If you try to call the nested function through its address after the
1 containing function exits, all hell breaks loose.  If you try to call it
1 after a containing scope level exits, and if it refers to some of the
1 variables that are no longer in scope, you may be lucky, but it's not
1 wise to take the risk.  If, however, the nested function does not refer
1 to anything that has gone out of scope, you should be safe.
1 
1  GCC implements taking the address of a nested function using a
1 technique called "trampolines".  This technique was described in
1 'Lexical Closures for C++' (Thomas M. Breuel, USENIX C++ Conference
1 Proceedings, October 17-21, 1988).
1 
1  A nested function can jump to a label inherited from a containing
1 function, provided the label is explicitly declared in the containing
1 function (⇒Local Labels).  Such a jump returns instantly to the
1 containing function, exiting the nested function that did the 'goto' and
1 any intermediate functions as well.  Here is an example:
1 
1      bar (int *array, int offset, int size)
1      {
1        __label__ failure;
1        int access (int *array, int index)
1          {
1            if (index > size)
1              goto failure;
1            return array[index + offset];
1          }
1        int i;
1        /* ... */
1        for (i = 0; i < size; i++)
1          /* ... */ access (array, i) /* ... */
1        /* ... */
1        return 0;
1 
1       /* Control comes here from 'access'
1          if it detects an error.  */
1       failure:
1        return -1;
1      }
1 
1  A nested function always has no linkage.  Declaring one with 'extern'
1 or 'static' is erroneous.  If you need to declare the nested function
1 before its definition, use 'auto' (which is otherwise meaningless for
1 function declarations).
1 
1      bar (int *array, int offset, int size)
1      {
1        __label__ failure;
1        auto int access (int *, int);
1        /* ... */
1        int access (int *array, int index)
1          {
1            if (index > size)
1              goto failure;
1            return array[index + offset];
1          }
1        /* ... */
1      }
1