mirror of
https://github.com/frida/tinycc
synced 2024-11-24 00:29:38 +03:00
Handle always_inline as GNU inline
this is needed for multi-file testcases using stdio.h, as the __sputc function is implemented as a extern inline function (with gnu_inline attribute, but we don't support that for now). Without this change that leads to multiply defined symbols when using multiple units including stdio.h. It also has an always_inline attribute, which we can use to guide our behaviour, as in ISO-C an always_inline can't be defined with ISO 'extern inline' semantics. This is the minimal change and not a full implementation of GNU inline semantics, which would require thorough testcases. If __clang__ would be defined the header would make use of C99 semantics, which would work for us. It would also do that if _GNUC_ wouldn't be defined. But we can't do the latter (as the whole MacOSX SDK refuses to be compiled with anything not defining that). I haven't tested defining __clang__, but suspect that's going to be problematic.
This commit is contained in:
parent
5d2f4cb403
commit
f18f865159
4
tcc.h
4
tcc.h
@ -494,7 +494,9 @@ struct FuncAttr {
|
||||
func_noreturn : 1, /* attribute((noreturn)) */
|
||||
func_ctor : 1, /* attribute((constructor)) */
|
||||
func_dtor : 1, /* attribute((destructor)) */
|
||||
func_args : 8; /* PE __stdcall args */
|
||||
func_args : 8, /* PE __stdcall args */
|
||||
func_alwinl : 1, /* always_inline */
|
||||
xxxx :15;
|
||||
};
|
||||
|
||||
/* symbol management */
|
||||
|
22
tccgen.c
22
tccgen.c
@ -4075,14 +4075,18 @@ redo:
|
||||
skip(')');
|
||||
break;
|
||||
}
|
||||
case TOK_CONSTRUCTOR1:
|
||||
case TOK_CONSTRUCTOR2:
|
||||
case TOK_CONSTRUCTOR1:
|
||||
case TOK_CONSTRUCTOR2:
|
||||
ad->f.func_ctor = 1;
|
||||
break;
|
||||
case TOK_DESTRUCTOR1:
|
||||
case TOK_DESTRUCTOR2:
|
||||
case TOK_DESTRUCTOR1:
|
||||
case TOK_DESTRUCTOR2:
|
||||
ad->f.func_dtor = 1;
|
||||
break;
|
||||
case TOK_ALWAYS_INLINE1:
|
||||
case TOK_ALWAYS_INLINE2:
|
||||
ad->f.func_alwinl = 1;
|
||||
break;
|
||||
case TOK_SECTION1:
|
||||
case TOK_SECTION2:
|
||||
skip('(');
|
||||
@ -8225,6 +8229,16 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
|
||||
sym = type.ref;
|
||||
if (sym->f.func_type == FUNC_OLD && l == VT_CONST)
|
||||
decl0(VT_CMP, 0, sym);
|
||||
if (sym->f.func_alwinl
|
||||
&& ((type.t & (VT_EXTERN | VT_INLINE))
|
||||
== (VT_EXTERN | VT_INLINE))) {
|
||||
/* always_inline functions must be handled as if they
|
||||
don't generate multiple global defs, even if extern
|
||||
inline, i.e. GNU inline semantics for those. Rewrite
|
||||
them into static inline. */
|
||||
type.t &= ~VT_EXTERN;
|
||||
type.t |= VT_STATIC;
|
||||
}
|
||||
/* always compile 'extern inline' */
|
||||
if (type.t & VT_EXTERN)
|
||||
type.t &= ~VT_INLINE;
|
||||
|
Loading…
Reference in New Issue
Block a user