ISO/ IEC JTC1/SC22/WG14 N633


                    Document Number:  WG14 N633/X3J11 96-097


                        C9X Revision Proposal
                        =====================

Title: Add "inline" capability to C, DRAFT 2
Author: Leith (Casey) Leedom
Author Affiliation: Silicon Graphics, Inc.
Postal Address: Mail Stop: 8U-500
                2011 N. Shoreline Blvd.
                Mountain View, CA 94043-1389
E-mail Address: [email protected]
Telephone Number: +1 415 9331504
Fax Number: +1 415 9628404
Sponsor: 
Date: 1996-11-26
Proposal Category:
   __ Editorial change/non-normative contribution
   __ Correction
   X_ New feature
   __ Addition to obsolescent feature list
   __ Addition to Future Directions
   __ Other (please specify)  
Area of Standard Affected:
   __ Environment
   X_ Language
   __ Preprocessor
   __ Library
      __ Macro/typedef/tag name
      __ Function
      __ Header
   __ Other (please specify)  
Prior Art: C++, GCC, various vendors including SGI, IBM, SUN, and DEC
Target Audience: Programmers interested in improving application performance
        by specifying that certain functions should be compiled ``inline.''
Related Documents (if any): DRAFT ISO/ANSI C++ Language Standard,
        http://www.cygnus.com/misc/wp/nov96; GCC, File: gcc.info, Node:
        Inline
Proposal Attached: X_ Yes __ No, but what's your interest?
Abstract: C++ has supported a function inlining facility since its
        inception.  Several C compilers now offer a similar facility; the
        GNU C Compiler, GCC, being a notable, widely available example.


Abstract:
=========

The C++ language language has included a function inlining capability since
its inception.  The current ISO/ANSI C++ Standard DRAFT dated November 15,
1996 covers the syntax and semantics of the "inline" keyword in sections 3.2
(One definition rule) and 7.1.2 (Function specifiers).  These sections are
attached in Appendix B of this proposal.

The GNU C Compiler, GCC, is an ISO 9899-1990 compliant compiler which
supports several extensions to the ANSI C standard, including a function
inlining capability very similar to the function inlining of C++.  The
syntax and semantics of the "inline" keyword is covered in the Inline info
node in the gcc.info file.  This info node is attached in Appendix C of this
proposal.

Both C++ and GCC specify that the use of the keyword "inline" in a function
definition serves as a ``hint'' to the compiler that calls to such a
function be substituted with the function body rather than the usual call
mechanism.  There are, however, several differences between the C++ and GCC
"inline" definitions.  The primary difference is the extensive facility in
GCC to control when and where inline functions are allowed to be
instantiated as separate, callable functions.  See Appendix A for a complete
description of the differences between the two definitions.


Proposal:
=========

This proposal advocates the inclusion into the ISO/ANSI C9X standard of a
function inlining facility identical to that implemented by C++.  C++'s
model was chosen over GCC's because of the desire to maintain wherever
possible and reasonable a high degree of compatibility between the C and C++
standards.  Because GCC is a widely available compiler and some application
code may have already adopted its inline model this may lead to problems.
However, 1. it's highly likely that most such uses are guarded by
preprocessor directives active only under GCC, 2. the differences are minor
enough not to introduce problems in a majority of cases, and 3. the desire
to maintain compatibility with the C++ standard is important enough to
accept the remaining problems.

In this proposal:

  o References to Draft 5 of the C9X C Language Standard are of the form
    C9X-D5/section.number.

  o References to the 1996 November 15 ISO/ANSI C++ Standard DRAFT are of
    the form 1996-nov-C++/section.number.

  o References to the Inline info node from the file gcc.info for GCC
    release 2.6.3 are of the form GCC-2.6.3, or simply GCC.


Proposal details:
=================

A new keyword, "inline," is added to the set of declaration-specifiers
allowable for function declarations and definitions (C9X-D5/6.7.1).  The
semantics of this new keyword are identical to those in 1996-nov-C++.  Note
that the C++ Standard Committee has recently changed the traditional C++
semantics of the "inline" keyword.  In previous versions of the C++ language
and standard, "inline" has implied "internal linkage" as if the "static"
storage class keyword had been specified.  In 1996-nov-C++ this implied
linkage semantic has been dropped and "inline" no longer has any effect on
the linkage of a function (1996-nov-C++/7.1.2, footnote 2 in paragraph 4).

The relevant portions of 1996-nov-C++ are included here:

      3.2  One definition rule ...
    
    1 No translation unit shall contain more than one definition of any
      variable, function, [or] enumeration type, ...
    
    3 Every program shall contain exactly one definition of every non-inline
      function or object that is used in that program; no diagnostic
      required.  The definition can appear explicitly in the program, it can
      be found in the standard or a user-defined library, ...  An inline
      function shall be defined in every transla- tion unit in which it is
      used.
    
    5 There can be more than one definition of a ... inline function with
      external linkage ... in a program provided that each definition
      appears in a different translation unit, and provided the definitions
      satisfy the following requirements.  Given such an entity named D
      defined in more than one translation unit, then
    
      --each definition of D shall consist of the same sequence  of  tokens;
        ...

      7.1.2  Function specifiers ...
    
    1 Function-specifiers can be used only in function declarations.
              function-specifier:
                      inline
                      ...
    
    2 A function declaration ... with an inline specifier declares an inline
      function.  The inline specifier indicates to the implementation that
      inline substitution of the function body at the point of call is to be
      preferred to the usual function call mechanism.  An implementation is
      not required to perform this inline substitution at the point of call;
      however, even if this inline substitution is omitted, the other rules
      for inline functions defined by this subclause shall still be
      respected.
    
    3 ... The inline specifier shall not appear on a block scope function
      declaration. ... The inline keyword has no effect on the linkage of a
      function.
    
    4 An inline function shall be defined in every translation unit in which
      it is used and shall have exactly the same definition in every case
      (see one definition rule, 3.2).  [Note: a call to the inline function
      may be encountered before its definition appears in the translation
      unit.]  If a function with external linkage is declared inline in one
      transla- tion unit, it shall be declared inline in all translation
      units in which it appears; no diagnostic is required.  [Note: a static
      local variable in an extern inline function always refers to the same
      object.]

Note that the use above of the phrase ``the same sequence of tokens'' is
somewhat ambiguous since 1996-nov-C++ doesn't seem to have an explicit
definition of what the word ``token'' means in the context of the body of
the standard.  E.g. in C9X-D5 we have:

    6.1 Lexical elements
    ...
    [4] A token is the minimal lexical element of the language in
    translation phases 7 and 8.  The categories of tokens are: keywords,
    identifiers, constants, strings literals, operators, and puntuators.  A
    preprocessing token is the minimal lexical element of the language in
    translation phases 3 though 3.  The categories of preprocessing token
    are:header names, identifiers, preprocessing numbers, character
    constants, string literals, operators, punctuators, and single
    non-white-space characters that do not lexically match the other
    preprocessing token categories. ...

However, the structure of the two documents is very similar including nearly
identical numbering and wording for the description of translation phases.
Thus we will take the word ``token'' above to mean ``translation phase 7
token'' which is the meaning of the word in C9X-D5.

Unresolved issues:
==================

 1. The above definition will lead to conflict with the ``one definition
    rule'' in C9X-D5/6.7, paragraph 6:

        An external definition is an external declaration that is also a
        definition of a function or an object.  If an identifier declared
        with external linkage is used in an expression (other than as part
        of the operand of a sizeof operator), somewhere in the entire
        program there shall be exactly one external definition for the
        identifier; otherwise, there shall be no more than one. [83. Thus,
        if an identifier declared with external linkage is not used in an
        expression, there need be no external definition for it.]

 2. 1996-nov-C++ is imprecise on whether multiple out-of-line instantiations
    of an ``extern inline'' function result in a single instantiation (i.e.
    if you take the address of such a function in multiple translation
    units, do you get the same address).  This issue has been raised with
    the 1996-nov-C++ committee.

 3. The 1996-nov-C++ would appear to result in multiple out-of-line copies
    of "static inline" functions (one per translation unit).  This is a
    result of the language which states that "inline" indicates that inline
    substitution is preferred.  As a result it appears that a "static"
    out-of-line copy must be generated.  Since these copies would have
    internal linkage, there's no way a linker could collapse such copies.

Appendix A: Differences between C++ and GCC "inline":
=====================================================

While the GCC-2.6.3 inlining facility was almost certainly modeled on the
C++ inline capability there are several differences.

The single largest difference between the GCC-2.6.3 and 1995-C++ definitions
has to do with GCC's extensive ``instantiation control'' capabilities for
inline functions.  With GCC an implementor can explicitly control whether an
inline function should have unsubstitutable references result in
[translation-unit] local copies of the function with internal linkage, local
copies with external linkage, or non-local copies with external linkage.

For example, this could be used to cause external users of a library
function, f(), to use the normal call mechanism while internal uses of f()
could all be inlined.  This would allow the library implementors to
carefully control space, time, and binary compatibility issues of using
inline functions (if user code were allowed to inline f(), then compiled
user code could become binary incompatible with a new version of the library
which used different internal data structures).

Much of this control is probably provided to get around the fact that the
loader won't collapse multiple definitions of a function to a single
instance as is done for uninitialized variables with external linkage.

GCC-2.6.3 also allows an inline function to be used before being defined.
Uses prior to the inline definition will call an out-of-line instantiation
of the function using the normal function call mechanism while uses
following the definition will inline it.  It appears from 1996-nov-C++ that
it is legal to call an inline function before it is defined in C++ but it
isn't 100% clear (see issue #3 above).

Finally, GCC-2.6.3 explicitly states that if all calls to a ``static
inline'' are integrated into the caller and the function's address is never
taken, then no out-of-line code for the function will be emitted.
1996-nov-C++ merely states that "inline" is an indication that inline
substitution should be preferred thus it seems that an internal linkage
out-of-line copy is mandated by the standard ... (see issue #4 above)

Appendix B: relevant material from ISO/ANSI C++ Standard DRAFT
            September 24, 1996 [http://www.cygnus.com/misc/wp/sep96]
====================================================================

  3.2  One definition rule                               [basic.def.odr]

1 No  translation  unit  shall  contain  more than one definition of any
  variable, function, class type, enumeration type or template.

2 An expression is potentially evaluated unless either it is the operand
  of  the  sizeof  operator (_expr.sizeof_), or it is the operand of the
  typeid operator and does not designate an lvalue of polymorphic  class
  type (_expr.typeid_).  An object or non-overloaded function is used if
  its name appears in a  potentially-evaluated  expression.   A  virtual
  member  function is used if it is not pure.  An overloaded function is
  used if it is selected by overload resolution when referred to from  a
  potentially-evaluated  expression.   [Note: this covers calls to named
  functions (_expr.call_), operator overloading  (_over_),  user-defined
  conversions  (_class.conv.fct_), allocation function for placement new
  (_expr.new_), as well as non-default initialization  (_dcl.init_).   A
  copy  constructor  is  used even if the call is actually elided by the
  implementation.  ] An allocation or deallocation function for a  class
  is  used  by  a  new  expression  appearing in a potentially-evaluated
  expression as specified in _expr.new_ and _class.free_.   A  dealloca-
  tion  function for a class is used by a delete expression appearing in
  a potentially-evaluated expression as specified in  _expr.delete_  and
  _class.free_.   A  copy-assignment  function for a class is used by an
  implicitly-defined copy-assignment function for another class as spec-
  ified  in  _class.copy_.  A default constructor for a class is used by
  default initialization as specified in _dcl.init_.  A constructor  for
  a  class is used as specified in _dcl.init_.  A destructor for a class

  is used as specified in _class.dtor_.

3 Every program shall contain exactly one definition of every non-inline
  function  or  object  that  is  used  in  that  program; no diagnostic
  required.  The definition can appear explicitly in the program, it can
  be found in the standard or a user-defined library, or (when appropri-
  ate) it is implicitly  defined  (see  _class.ctor_,  _class.dtor_  and
  _class.copy_).   An inline function shall be defined in every transla-
  tion unit in which it is used.

4 Exactly one definition of a class is required in a translation unit if
  the  class  is  used  in a way that requires the class type to be com-
  plete.  [Example: the following complete  translation  unit  is  well-
  formed, even though it never defines X:
          struct X;      // declare X as a struct type
          struct X* x1;  // use X in pointer formation
          X* x2;         // use X in pointer formation
    --end  example]  [Note:  the  rules for declarations and expressions
  describe in which contexts complete class types are required.  A class
  type T must be complete if:

  --an object of type T is defined (_basic.def_, _expr.new_), or

  --an  lvalue-to-rvalue conversion is applied to an lvalue referring to
    an object of type T (_conv.lval_), or

  --an expression is converted (either implicitly or explicitly) to type
    T        (_conv_,       _expr.type.conv_,       _expr.dynamic.cast_,
    _expr.static.cast_, _expr.cast_), or

  --an expression is converted to the type pointer to T or reference  to
    T   using   an   implicit   conversion   (_conv_),   a  dynamic_cast
    (_expr.dynamic.cast_) or a static_cast (_expr.static.cast_), or

  --a class member access operator is applied to an expression of type T
    (_expr.ref_), or

  --the   typeid   operator   (_expr.typeid_)  or  the  sizeof  operator
    (_expr.sizeof_) is applied to an operand of type T, or

  --a function with a return type or argument type of type T is  defined
    (_basic.def_) or called (_expr.call_), or

  --an lvalue of type T is assigned to (_expr.ass_).  ]

5 There  can be more than one definition of a class type (_class_), enu-
  meration type (_dcl.enum_),  inline  function  with  external  linkage
  (_dcl.fct.spec_),  class  template  (_temp_), non-static function tem-
  plate  (_temp.fct_),  static  data  member   of   a   class   template
  (_temp.static_),  member  function template (_temp.mem.func_), or tem-
  plate specialization for which some template parameters are not speci-
  fied  (_temp.spec_, _temp.class.spec_) in a program provided that each
  definition appears in a different translation unit, and  provided  the
  definitions  satisfy the following requirements.  Given such an entity

  named D defined in more than one translation unit, then

  --each definition of D shall consist of the same sequence  of  tokens;
    and

  --in each definition of D, corresponding names, looked up according to
    _basic.lookup_, shall refer to an entity defined within the  defini-
    tion of D, or shall refer to the same entity, after overload resolu-
    tion (_over.match_) and after matching of partial template  special-
    ization  (_temp.over_),  except  that  a  name  can refer to a const
    object with internal or no linkage if the object has the same  inte-
    gral  or enumeration type in all definitions of D, and the object is
    initialized with a constant expression (_expr.const_), and the value
    (but  not the address) of the object is used, and the object has the
    same value in all definitions of D; and

  --in each definition of D, the overloaded operators referred  to,  the
    implicit  calls  to conversion operators, constructors, operator new
    functions and operator delete functions, shall  refer  to  the  same
    function, or to a function defined within the definition of D; and

  --in  each definition of D, a default argument used by an (implicit or
    explicit) function call is treated as if  its  token  sequence  were
    present  in  the  definition  of D; that is, the default argument is
    subject to the three  requirements  described  above  (and,  if  the
    default  argument  has  sub-expressions with default arguments, this
    requirement applies recursively).2)

  --if   D   is   a   class   with  an  implicitly-declared  constructor
    (_class.ctor_), it is as if the constructor was  implicitly  defined
    in every translation unit where it is used, and the implicit defini-
    tion in every translation unit shall call the same constructor for a
    base class or a class member of D.  [Example:

  _________________________
  2) _dcl.fct.default_  describes how default argument names are  looked
  up.

              // translation unit 1:
              struct X {
                      X(int);
                      X(int, int);
              };
              X::X(int = 0) { }
              class D: public X { };
              D d2; // X(int) called by D()

              // translation unit 2:
              struct X {
                      X(int);
                      X(int, int);
              };
              X::X(int = 0, int = 0) { }
              class D: public X { };     // X(int, int) called by D();
                                         // D()'s implicit definition
                                         // violates the ODR
      --end example] If D is a template, and is defined in more than one
    translation unit, then the last  four  requirements  from  the  list
    above  shall apply to names from the template's enclosing scope used
    in the template definition (_temp.nondep_), and  also  to  dependent
    names  at  the  point of instantiation (_temp.dep_).  If the defini-
    tions of D satisfy all these requirements, then  the  program  shall
    behave  as  if  there were a single definition of D.  If the defini-
    tions of D do not satisfy these requirements, then the  behavior  is
    undefined.

  7.1.2  Function specifiers                              [dcl.fct.spec]

1 Function-specifiers can be used only in function declarations.
          function-specifier:
                  inline
                  virtual
                  explicit

2 A function declaration (_dcl.fct_, _class.mfct_, _class.friend_)  with
  an inline specifier declares an inline function.  The inline specifier
  indicates to the implementation that inline substitution of the  func-
  tion  body  at the point of call is to be preferred to the usual func-
  tion call mechanism.  An implementation is  not  required  to  perform
  this  inline  substitution at the point of call; however, even if this
  inline substitution is omitted, the other rules for  inline  functions
  defined by this subclause shall still be respected.

3 A  function  defined  within a class definition is an inline function.
  The inline specifier shall  not  appear  on  a  block  scope  function
  declaration.2)

4 An inline function shall be defined in every translation unit in which
  it is used and shall have exactly the same definition  in  every  case
  (_basic.def.odr_).   [Note:  a  call  to  the  inline  function may be
  _________________________
  2) The inline keyword has no effect on the linkage of a function.

  encountered before its definition appears in the translation unit.   ]
  If a function with external linkage is declared inline in one transla-
  tion unit, it shall be declared inline in  all  translation  units  in
  which  it  appears;  no diagnostic is required.  [Note: a static local
  variable in an extern  inline  function  always  refers  to  the  same
  object.  ]

5 The  virtual specifier shall only be used in declarations of nonstatic
  class member functions that appear within a member-specification of  a
  class declaration; see _class.virtual_.

6 The explicit specifier shall be used only in declarations of construc-
  tors within a class declaration; see _class.conv.ctor_.

Appendix C: relevant material from GNU GCC 2.6.3:
=================================================

File: gcc.info,  Node: Inline,  Next: Extended Asm,  Prev: Alignment,  Up: C Extensions

An Inline Function is As Fast As a Macro
========================================

   By declaring a function `inline', you can direct GNU CC to integrate
that function's code into the code for its callers.  This makes
execution faster by eliminating the function-call overhead; in
addition, if any of the actual argument values are constant, their known
values may permit simplifications at compile time so that not all of the
inline function's code needs to be included.  The effect on code size is
less predictable; object code may be larger or smaller with function
inlining, depending on the particular case.  Inlining of functions is an
optimization and it really "works" only in optimizing compilation.  If
you don't use `-O', no function is really inline.

   To declare a function inline, use the `inline' keyword in its
declaration, like this:

     inline int
     inc (int *a)
     {
       (*a)++;
     }

   (If you are writing a header file to be included in ANSI C programs,
write `__inline__' instead of `inline'.  *Note Alternate Keywords::.)

   You can also make all "simple enough" functions inline with the
option `-finline-functions'.  Note that certain usages in a function
definition can make it unsuitable for inline substitution.

   Note that in C and Objective C, unlike C++, the `inline' keyword
does not affect the linkage of the function.

   GNU CC automatically inlines member functions defined within the
class body of C++ programs even if they are not explicitly declared
`inline'.  (You can override this with `-fno-default-inline'; *note
Options Controlling C++ Dialect: C++ Dialect Options..)

   When a function is both inline and `static', if all calls to the
function are integrated into the caller, and the function's address is
never used, then the function's own assembler code is never referenced.
In this case, GNU CC does not actually output assembler code for the
function, unless you specify the option `-fkeep-inline-functions'.
Some calls cannot be integrated for various reasons (in particular,
calls that precede the function's definition cannot be integrated, and
neither can recursive calls within the definition).  If there is a
nonintegrated call, then the function is compiled to assembler code as
usual.  The function must also be compiled as usual if the program
refers to its address, because that can't be inlined.

   When an inline function is not `static', then the compiler must
assume that there may be calls from other source files; since a global
symbol can be defined only once in any program, the function must not
be defined in the other source files, so the calls therein cannot be
integrated.  Therefore, a non-`static' inline function is always
compiled on its own in the usual fashion.

   If you specify both `inline' and `extern' in the function
definition, then the definition is used only for inlining.  In no case
is the function compiled on its own, not even if you refer to its
address explicitly.  Such an address becomes an external reference, as
if you had only declared the function, and had not defined it.

   This combination of `inline' and `extern' has almost the effect of a
macro.  The way to use it is to put a function definition in a header
file with these keywords, and put another copy of the definition
(lacking `inline' and `extern') in a library file.  The definition in
the header file will cause most calls to the function to be inlined.
If any uses of the function remain, they will refer to the single copy
in the library.

   GNU C does not inline any functions when not optimizing.  It is not
clear whether it is better to inline or not, in this case, but we found
that a correct implementation when not optimizing was difficult.  So we
did the easy thing, and turned it off.