I have tested the changes in gen_inline_functions but do not work.
I have made change in decl0() in tccgen around line 5706

                while ((sym = sym->next) != NULL)
                    if (!(sym->v & ~SYM_FIELD))
                       expect("identifier");
#ifdef _HACK
                if (type.t & VT_INLINE)
                  if (type.t & VT_EXTERN)
                    type.t &= ~VT_INLINE;
                  else
                    type.t |= VT_STATIC;
#else
/* XXX: cannot do better now: convert extern inline to static inline */ if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
                    type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
#endif
                sym = sym_find(v);
                if (sym) {
                    if ((sym->type.t & VT_BTYPE) != VT_FUNC)
                        goto func_error1;


this works to link my project with inline code in .h
Pierre


Le 12/12/2013 06:45, Christian Jullien a écrit :

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] <mailto:[email protected]>
    https://lists.nongnu.org/mailman/listinfo/tinycc-devel






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






    _______________________________________________

    Tinycc-devel mailing list

    [email protected]  <mailto:[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