Here is the relevant part of C11 talking about inline function:

 

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 without extern, then the definition in that translation unit is an
inline

definition. An inline definition does not provide an external definition for
the function,

and does not forbid 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 translation unit. It is unspecified
whether a call to the

function uses the inline definition or the external definition.

 

EXAMPLE 1 The declaration of an inline function with external linkage can
result in either an external

definition, or a definition available for use only within the translation
unit. A file scope declaration with

extern 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;

}

inline double cels(double t)

{

return (5.0 * (t - 32.0)) / 9.0;

}

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

 

double convert(int is_fahr, double temp)

{

/* A translator may perform inline substitutions */

return is_fahr ? cels(temp) : fahr(temp);

}

11 Note that the definition of fahr is an external definition because fahr
is also declared with extern, but

the definition of cels is an inline definition. Because cels has external
linkage and is referenced, an

external definition has to appear in another translation unit (see 6.9); the
inline definition and the external

definition are distinct and either may be used for the call.

 

 

 

From: [email protected]
[mailto:[email protected]] On Behalf Of
Pierre
Sent: jeudi 12 décembre 2013 00:48
To: [email protected]
Subject: Re: [Tinycc-devel] RE :Re: inline functions

 

Yes in fact gen_inline_functions just convert refferenced inline function to
normal function.
I have remove my changes (line 3042 & 3030) and just added in
gen_inline_functions around line 5597

                if (file)
                    pstrcpy(file->filename, sizeof file->filename,
fn->filename);
                sym->r = VT_SYM | VT_CONST;
                sym->type.t &= ~VT_INLINE;
#ifdef _HACK
                if (!(sym->type.t & VT_EXTERN))            // extern inline
= extern
                  sym->type.t |= VT_STATIC;                     // else
static
#endif
                macro_ptr = str;
                next();
                cur_text_section = text_section;

I will do some test tomorrow
Pierre

Le 12/12/2013 00:27, Rob a écrit :

Odd, msvc isn't a C99 compiler, didn't expect it to conform. 

Anyway - I know the tcc code somewhat, but I'm not sure about inline 
functions. They're handled as sort-of-macros in some cases, see 
gen_inline_functions(). 

In short, I'm not sure of the changes and I'm off to bed shortly. I do 
think tcc should remain standard-compliant though, and not imply static 
or extern from just 'inline'. Perhaps we need another flag? 


Rob 


On Wed, 11 Dec 2013, Pierre wrote: 



yes I think you are right, it is same with msvc v6. 

I don't know well the tcc code, but I don't think it inline functions (like
a macro, should be complicated to do). 
So defining inline (alone) as static maybe a good idea ? 

int tccgen.c line 3042 

change: 

        case TOK_INLINE1: 
        case TOK_INLINE2: 
        case TOK_INLINE3: 
            t |= VT_INLINE; 
            next(); 
            break; 

to 

        case TOK_INLINE1: 
        case TOK_INLINE2: 
        case TOK_INLINE3: 
            if (!(t & VT_EXTERN))                   // if extern defined
ignore 'inline' 
                t |= VT_INLINE | VT_STATIC;   // if not extern, set static
as default 
            next(); 
            break; 

and line 3030 

change 
        case TOK_EXTERN: 
            t |= VT_EXTERN; 

to 
    
        case TOK_EXTERN: 
        { 
            t |= VT_EXTERN; 
            t &= ~VT_INLINE;                            // remove 'inline' 
        } 


I don't know if some more changes are required ? 
Pierre 


Le 11/12/2013 23:22, Rob a écrit : 
      'inline' alone should not generate code, I'm pretty certain. It's an 
      inline-only definition. If it can't be inlined, you get a linker
error. 

      For example: 

      inline int f() 
      { 
          return 3; 
      } 

      int main() 
      { 
          return f(); 
      } 

      A standalone function named 'f' will never appear in the generated
code. 
      If the compiler inlines 'f' into main, the program will link. If the 
      compiler doesn't or can't inline 'f', you'll get a linker error. 

      So we get a linker error with 'gcc -std=c99 -O0', but the program
links 
      fine with 'gcc -std=c99 -O1', as f isn't referenced (since it's 
      inlined by an optimiser). 

      Also, I checked - gcc defaults to -std=gnu89, which means gnu89 inline

      semantics, so when testing, make sure you give it '-std=c99'. 

      Clang exhibits the same behaviour w.r.t. inline, so I'm pretty sure
I've 
      interpreted the standard correctly. Note that clang defaults to C99. 


      Thanks, 
      Rob 


      On Wed, 11 Dec 2013, Pierre wrote: 
            So inline alone should export nothing if not refferenced (with
code or forward declared), and at most, create a static function if cannot
be inlined ? 

            And an 'extern inline ' simply ignore 'inline' ? 


            Le 11/12/2013 22:33, Rob a écrit : 
                  On Wed, 11 Dec 2013, Thomas Preud'homme wrote: 
                        Le mercredi 11 décembre 2013, 09:28:07 Christian
JULLIEN a écrit : 
                        I knew about the fact that it is a hint and I knew
even when inlined, the 
                        function still needs to be output in case its
address is used. However I 
                        forgot about the other details. I stand corrected,
thanks. 

                        I remembered extern and inline has a special meaning
as well but I forgot so I 
                        checked online and I think the documentation of gcc
[0] explains pretty well 
                        how inline behave. I'm a bit surprised though
because I thought the special 
                        meaning of extern inline was not in the standard but
something gcc specific. 
                        Again, I stand corrected. 

                        [0] http://gcc.gnu.org/onlinedocs/gcc/Inline.html 

                              If you want to avoid problems when you define
an inlined function in a .h is 
                              to declare this function static. This way, if
compiler is not able to 
                              inline function, the two or more translation
units using it will have their 
                              own static copy that will make linker happy. 


                        Or extern inline which has a slightly different
meaning. With static inline you 
                        need to provide two implementation of the function,
one with static inline in 
                        the header, and one normal implementation somewhere
else in case there is a 
                        call that cannot be inlined or if the address of the
function is used. With 
                        extern inline you make it clear that you want the
function inlined no matter 
                        what. At least that is my understanding after a
quick read but again, I might 
                        have read too quickly. 



                  There are very subtle differences and with gcc I'm pretty
sure you have 
                  to specify -std=c99 otherwise it defaults to gnu89 which
has different, 
                  GNU inline semantics. 

                  'inline', unfortunately is not just a hint to the
compiler. There are a 
                  few checks compilers have to perform too. 


                  So we have three forms of inline: 

                  extern inline void func() { ... } // 1 
                  static inline void func() { ... } // 2 
                         inline void func() { ... } // 3 


                  The first form, 'extern inline', will always cause a 
                  standalone/non-inlined function to be emitted, just as if
'inline' 
                  wasn't present. The inline modifier here simply acts as a
hint that this 
                  function may be inlined. 

                  The second form, 'static inline', will cause function code
to be 
                  emitted, but the compiler may omit this if it knows the
function is 
                  never used (since it's static, it's not called from
another translation 
                  unit). Again, 'inline' acts only as a hint. 

                  The final form, 'inline' without a storage class is where
we have 
                  special handling. In this case, standalone function code
is never 
                  emitted, this version is _only_ to be used for inline
substitution. 


                  For the final form to take affect, none of the
declarations of `func' 
                  must mention extern, for example: 


                  inline f(); 
                  inline f(); 
                  extern inline f(); // this causes `f' to be in form 2 
                  inline f() { ... } 



                  At least, that's what I've gathered from the standard and
various 
                  searches. 


                  Thanks, Rob 


            _______________________________________________ 
            Tinycc-devel mailing list 
            [email protected] 
            https://lists.nongnu.org/mailman/listinfo/tinycc-devel 






_______________________________________________ 
Tinycc-devel mailing list 
[email protected] 
https://lists.nongnu.org/mailman/listinfo/tinycc-devel 










_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

 

_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to