diff --git a/tcc.h b/tcc.h index c00c7a15..d74d918a 100644 --- a/tcc.h +++ b/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 */ diff --git a/tccgen.c b/tccgen.c index 88145abf..e49407dd 100644 --- a/tccgen.c +++ b/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; diff --git a/tcctok.h b/tcctok.h index ee18462d..54a778b0 100644 --- a/tcctok.h +++ b/tcctok.h @@ -132,6 +132,8 @@ DEF(TOK_CONSTRUCTOR2, "__constructor__") DEF(TOK_DESTRUCTOR1, "destructor") DEF(TOK_DESTRUCTOR2, "__destructor__") + DEF(TOK_ALWAYS_INLINE1, "always_inline") + DEF(TOK_ALWAYS_INLINE2, "__always_inline__") DEF(TOK_MODE, "__mode__") DEF(TOK_MODE_QI, "__QI__")