Accredited Standards Committee X3 Doc No: X3J16/93-0161 WG21/N0368 Information Processing Systems Date: Nov. 5, 1993 Page 1 of 1 Operating under the procedures of Project: Programming Language C++ American National Standards Institute Ref Doc: Reply to: Josee Lajoie (josee@vnet.ibm.com) Linkage of inline functions --------------------------- 1. The current state of affairs The WP [the September 28th, 1993 version of the working paper] currently states: Section 3.3 Program and Linkage: ... A name of file scope that is explicitly declared inline has internal linkage. ... Inline class member functions have exactly one definition in a program. Section 7.1.2 Function Specifiers: The inline specifier is a hint to the compiler that inline substitution of the function is to be preferred to the usual function call implementation. The hint may be ignored. For a nonmember function inline specifier also gives the function default internal linkage. ... An inline member function must have exactly the same definition in every compilation in which it appears. 2. What can we conclude from these rules? First, that "inline" describes 2 things: 1. it is a hint to the compiler that inline substitution of the function is to be preferred to the usual function call mechanism. 2. it also indicates the function linkage (static or extern). The consequences on the function linkage when a function is declared inline are not all clear and are quite different depending on whether the function is a global function or a class member function. 2.1 Global Functions For global functions, inline means static linkage. This implies: o that the definition of a global inline function with the same name(*) can appear in more than on translation unit ---------- (*) The term name here has the meaning given to "name" in the WP. Especially, it does not have the meaning given to it by R. Michael Anderson's in his paper: A clarification of "Name" in C++, X3J16/93-0016 WG21/N0323. o that definitions in different translation units do not have to be the same, that is, these functions can o have different definitions o access file scope static data and functions, o access classes with internal linkage o use file scope typedefs o that taking the address of a global inline function will yield different results in different compilation units. 2.2 Class Member Functions It is not as clear what the term "inline" means for class member functions. In particular, the linkage of inline member functions is not specified by the WP. The WP seems to imply that class member functions behave somewhat like functions with external linkage. But the following questions are still not clearly answered by the WP: o What are the restrictions on inline class member function definitions? o Does taking the address of an inline class member function yield the same results in different compilation units? o Can a class member function contain static data? o Can a class member function refer to file specific definitions? o file scope static data and functions, o classes with internal linkage I believe the following WP sentences: (1) Section 3.3: Inline class member functions have exactly one definition in a program. (2) Section 7.1.2: An inline member function must have exactly the same definition in every compilation in which it appears. leave the door open for 2 different implementation models for inline class member functions. Existing implementations do not seem to agree either on the model that should be adopted. 2.2.1 Implementation model: single definition Sentence (1) above indicates that inline class member function will have only one definition per program. Certainly, this statement does not apply to the source code the user provides but rather to the object code generated for a complete program. The function definition needs to appear in every compilation unit to enable the compiler to inline the function (replace the function calls by the code for the function body) properly. Therefore, sentence (1) above is a restriction that cannot be imposed on users. It is one for implementations to adhere to. Using sentence (1), one may conclude that the language mandates implementations to provide only one definition per program for any inline class member function. Some conclusions can be drawn for this implementation model: a. Taking the address of an inline class member function is meaningful and guaranteed to yield the same result in different compilation units. b. If an inline class member function contains static data, the results observed by users are as expected: changes to the value of the static data in one compilation unit will be visible all through the program. 2.2.2 Implementation model: multiple definitions Sentence (2) above seems to indicate that inline class member functions can have more than one definition per program, as long as the definitions are "the same". It is not clear if this sentence is intended only as a restriction on user source code. It could also mean that implementations are free to provide more than one definition for inline class member functions, as long as users cannot tell that there is more than one definition provided. One would have the rely on the ODR definition to determine what "the same" mean when two definitions for a particular inline class member function are provided. If an implementation decided to support this model, users should expect the following behavior: a. Taking the address of an inline class member function will yield different results in different compilation units. Users should be aware that such results are to be expected. b. If users are not supposed to notice that there are more than one definition, we need to impose some restrictions on what the users can define and use in inline class member functions. For example, the inline class member functions cannot be defined to contain local static data, because such static data would not behave like local static data: there would be multiple definitions of the static data, each associated with a particular member function definition, and changes to the value of the static data in one compilation unit would not be visible throughout the program. This would have very surprising effects for users. 2.2.3 Which model should we adopt? I believe that the "single definition" model defines the concept of inline member function the best and has the least amount of surprises for users. Unfortunately, it is not certain that every C++ implementation can support it. We may have to leave the decision of choosing the best model to the implementations. If this is the case, we will need to adopt language rules that fit both models. This means that features such as: a. Taking the address of an inline class member function and expect the address to be the same in different compilation unit b. Defining a class member function to contain static data would lead to undefined behavior. 3. Proposal: extern inline functions A question that was raised at the last meeting was the following: Since, in order to support inline class member functions, implementations already support mechanisms for inline functions with external linkage, why isn't it possible for users to declare global inline functions with external linkage? This seems to make sense, especially for users of implementations choosing to support the single definition model for "extern inline" functions (model for which taking the address of an inline with external linkage and declaring local static data are meaningful). A user could then write: extern inline int f() { .... } to mean: (1) the function has external linkage (2) inline the function if possible For symmetry, we would also have to allow users to explicitly declare "static inline" functions, as follows: static inline int f() { .... } I believe this request is a reasonable one, and should be adopted. It clarifies the meaning of "inline", allowing users to be explicit about the linkage of the functions they declare. It offers more flexibility for users without requiring much more support from implementations (since the support is already there for inline class member functions). 3.1 default linkage for global inline functions Some have requested that the default linkage for global inline functions be "extern" instead of "static". I am not convinced this is the way to go. First (and foremost), this may break some code. Inline functions accessing file static data and functions or using file specific definitions, like typedef and classes, may change behavior. There may be some advantages to have global inline functions defaulting to external linkage, especially for users of implementations supporting the single definition model: local static data will work nicely. But this small usability improvement is not guaranteed to be seen across all implementations, while the potential of breaking code is ;-). I therefore do not recommend to make the default linkage of global inline functions external linkage. 3.2 static inline member function ??? Do we want to allow users to declare class member function to have static linkage??? I cannot see why this could be useful, but I thought I'd ask in case I overlooked something.