ISO/ IEC JTC1/SC22/WG14 N709

                  Inlining Proposal, Revision 1
                         WG14/N709 (J11/97-072)


                               Bill Homer
                             Tom MacDonald

                          Cray Research, Inc.
                          655F Lone Oak Drive
                            Eagan, MN  55121
                             homer@cray.com
                              tam@cray.com

                              30 May 1997





      Note:  Revision 1 differs from N700 (J11/97-063) only in the
      Semantics  section for 6.5.x.  Following an email discussion
      on the reflector, that section was rewritten to clarify  its
      intent.


      Introduction

      This proposal adds the inline keyword to Standard C in  such
      a  way that it can be implemented with existing linker tech-
      nology and also is compatible with C++.  This is achieved by
      requiring  that  one  and  only one of the translation units
      containing the definition of an inline function be specified
      as  the  one  that  provides  an external definition for the
      function.  Because that specification consists simply  of  a
      declaration  that  lacks the inline keyword, it will also be
      accepted by a C++ translator.

      This proposal does extend the C++ specification in two ways.
      First,  if  a function is declared inline in one translation
      unit, it need not be declared inline in every other transla-
      tion  unit.   This  allows,  for example, a library function
      that is to be inlined within the library but to be available
      only  through an external definition elsewhere.  (The alter-
      native of using a wrapper function for the external function
      both  requires  an  additional name and may adversely impact
      performance, if a translator does  not  actually  do  inline
      substitution.)

      Second, the requirement that all definitions  of  an  inline
      function be ``exactly the same'' is replaced by the require-
      ment that the behavior of the program should not  depend  on
      whether  a call is implemented with a visible inline defini-
      tion or the external definition of a function.  This  allows
      an  inline definition to be specialized for its use within a
      particular translation  unit.   For  example,  the  external
      definition of a library function might include some argument
      validation that is not needed  for  calls  made  from  other
      functions in the same library.

      These extensions do offer some advantages,  and  programmers
      who  are  concerned  about compatibility can simply abide by
      the stricter C++ rules.  Nevertheless,  the  extensions  are
      not  central  to the proposal and the C++ rules could easily
      be substituted.


      Edits to draft C9X Draft 10

      6.1.1.1 Keywords

      In the Syntax section, add to the list of keywords:  inline


      6.5 Declarations

      In the Syntax section, append to the  list  of  alternatives
      for the definition of declaration-specifiers:

                      function-specifiers


      6.5.x Function-specifiers (a  new  subsection,  intended  to
      follow 6.5.3)

      Syntax
                  function-specifier:
                       inline


      Constraints

           Function-specifiers shall  be  used  only  in  function
           declarations.

           The inline function specifier shall appear  only  in  a
           file  scope  function declaration.  It shall not appear
           in a declaration of main.

      Semantics

           A function declaration with an inline function  specif-
           ier  declares  an inline function.  The inline function
           specifier does not affect the meaning of a program.  It
           simply  indicates  that  a translator should attempt to
           improve the performance of calls to the  function  (by,
           for example, using an alternative to the usual function
           call mechanism known as ``inline substitution'').

           Any function with internal linkage  can  be  an  inline
           function.   For  a  function with external linkage, the
           following  restrictions  apply.   If  a   function   is
           declared  with  an  inline  function specifier, then it
           shall also be defined in the same translation unit.  If
           all  of the file scope declarations for a function in a
           translation unit include the inline function specifier,
           then  the  definition  in  that  translation unit is an
           inline definition.  An inline definition does not  pro-
           vide  an  external definition of the function, and does
           not hide an external definition in another  translation
           unit.   An inline definition provides an alternative to
           an external definition, which a translator may  use  to
           implement any call to the function in the same transla-
           tion unit. The behavior of the program is undefined  if
           it  depends  upon  whether the inline definition or the
           external definition is used.   (Footnote:  Examples  of
           operations  in an inline function with external linkage
           that can lead to undefined behavior  include  modifying
           an  object  declared  with the static storage class, or
           any operation that is present in one  but  not  another
           definition of the function.)


      Example

           The declaration of an inline  function  can  result  in
           either  an  external definition, or a definition avail-
           able for use only within the translation unit.  A  file
           scope  declaration  without  inline creates an external
           definition.  The  following  example  shows  an  entire
           translation unit.


           inline double fahr(double t) {
              return (9.0 * t) / 5.0 + 32.0;
           }

           extern double fahr(double); /* creates an external definition */

           inline double cels(double t) {
              return (5.0 * (t - 32.0)) / 9.0;
           }

           double convert(int is_fahr, double temperature) {
              /* A translator may perform inline substitutions. */
              return is_fahr ? cels(temperature) : fahr(temperature);
           }


           Note that the  declarations  of  inline  function  fahr
           result  in  the creation of an external definition, but
           the declaration of cels requires an external definition
           in another translation unit.