Skip to content

Commit b71412a

Browse files
committed
Support Visual Studio's __forceinline
It was previously treated the same as inline/__inline, but Windows header files come with multiple implementations of functions defined in the same file, with an expected behaviour similar to "extern inline" in GCC.
1 parent d393d1c commit b71412a

File tree

6 files changed

+51
-6
lines changed

6 files changed

+51
-6
lines changed

regression/ansi-c/forceinline1/main.i

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#line 1 "test.c"
2+
3+
__inline int foo()
4+
{
5+
return 0;
6+
}
7+
8+
__forceinline int foo()
9+
{
10+
return 1;
11+
}
12+
13+
int main()
14+
{
15+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.i
3+
--i386-win32
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$

src/ansi-c/c_typecheck_base.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,12 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
333333
// gcc allows re-definition if the first
334334
// definition is marked as "extern inline"
335335

336-
if(old_symbol.type.get_bool(ID_C_inlined) &&
337-
(config.ansi_c.mode==configt::ansi_ct::flavourt::GCC ||
338-
config.ansi_c.mode==configt::ansi_ct::flavourt::APPLE ||
339-
config.ansi_c.mode==configt::ansi_ct::flavourt::ARM))
336+
if(
337+
old_symbol.type.get_bool(ID_C_inlined) &&
338+
(config.ansi_c.mode == configt::ansi_ct::flavourt::GCC ||
339+
config.ansi_c.mode == configt::ansi_ct::flavourt::APPLE ||
340+
config.ansi_c.mode == configt::ansi_ct::flavourt::ARM ||
341+
config.ansi_c.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO))
340342
{
341343
// overwrite "extern inline" properties
342344
old_symbol.is_extern=new_symbol.is_extern;

src/ansi-c/parser.y

+15
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ extern char *yyansi_ctext;
164164
%token TOK_MSC_EXCEPT "__except"
165165
%token TOK_MSC_LEAVE "__leave"
166166
%token TOK_MSC_DECLSPEC "__declspec"
167+
%token TOK_MSC_FORCEINLINE "__forceinline"
167168
%token TOK_INTERFACE "__interface"
168169
%token TOK_CDECL "__cdecl"
169170
%token TOK_STDCALL "__stdcall"
@@ -1384,6 +1385,20 @@ storage_class:
13841385
| TOK_THREAD_LOCAL { $$=$1; set($$, ID_thread_local); }
13851386
| TOK_GCC_ASM { $$=$1; set($$, ID_asm); }
13861387
| msc_declspec { $$=$1; }
1388+
| TOK_MSC_FORCEINLINE
1389+
{
1390+
// equivalent to always_inline, and seemingly also has the semantics
1391+
// of extern inline in that multiple definitions can be provided in
1392+
// the same translation unit
1393+
init($$);
1394+
set($$, ID_static);
1395+
set($1, ID_inline);
1396+
$1=merge($1, $$);
1397+
1398+
init($$);
1399+
set($$, ID_always_inline);
1400+
$$=merge($1, $$);
1401+
}
13871402
;
13881403

13891404
basic_type_name:

src/ansi-c/scanner.l

+1-1
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,7 @@ __decltype { if(PARSER.cpp98 &&
11381138

11391139
"__forceinline" { if(PARSER.mode==configt::ansi_ct::flavourt::VISUAL_STUDIO ||
11401140
PARSER.mode==configt::ansi_ct::flavourt::ARM)
1141-
{ loc(); return TOK_INLINE; }
1141+
{ loc(); return TOK_MSC_FORCEINLINE; }
11421142
else
11431143
return make_identifier();
11441144
}

src/cpp/parse.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1986,7 +1986,8 @@ bool Parser::optStorageSpec(cpp_storage_spect &storage_spec)
19861986
t==TOK_REGISTER ||
19871987
t==TOK_MUTABLE ||
19881988
t==TOK_GCC_ASM ||
1989-
t==TOK_THREAD_LOCAL)
1989+
t==TOK_THREAD_LOCAL ||
1990+
t == TOK_MSC_FORCEINLINE)
19901991
{
19911992
cpp_tokent tk;
19921993
lex.get_token(tk);
@@ -2000,6 +2001,10 @@ bool Parser::optStorageSpec(cpp_storage_spect &storage_spec)
20002001
case TOK_MUTABLE: storage_spec.set_mutable(); break;
20012002
case TOK_GCC_ASM: storage_spec.set_asm(); break;
20022003
case TOK_THREAD_LOCAL: storage_spec.set_thread_local(); break;
2004+
case TOK_MSC_FORCEINLINE:
2005+
storage_spec.set_static();
2006+
storage_spec.set_inline();
2007+
break;
20032008
default: UNREACHABLE;
20042009
}
20052010

0 commit comments

Comments
 (0)