Skip to content

Commit 36d13f7

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 c749b8f commit 36d13f7

File tree

6 files changed

+57
-7
lines changed

6 files changed

+57
-7
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

+20
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,25 @@ 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+
#if 0
1397+
// enable once always_inline support is reinstantiated
1398+
$1=merge($1, $$);
1399+
1400+
init($$);
1401+
set($$, ID_always_inline);
1402+
$$=merge($1, $$);
1403+
#else
1404+
$$=merge($1, $$);
1405+
#endif
1406+
}
13871407
;
13881408

13891409
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

+7-2
Original file line numberDiff line numberDiff line change
@@ -1952,14 +1952,19 @@ bool Parser::optMemberSpec(cpp_member_spect &member_spec)
19521952

19531953
int t=lex.LookAhead(0);
19541954

1955-
while(t==TOK_FRIEND || t==TOK_INLINE || t==TOK_VIRTUAL || t==TOK_EXPLICIT)
1955+
while(
1956+
t == TOK_FRIEND || t == TOK_INLINE || t == TOK_VIRTUAL ||
1957+
t == TOK_EXPLICIT || t == TOK_MSC_FORCEINLINE)
19561958
{
19571959
cpp_tokent tk;
19581960
lex.get_token(tk);
19591961

19601962
switch(t)
19611963
{
1962-
case TOK_INLINE: member_spec.set_inline(true); break;
1964+
case TOK_INLINE:
1965+
case TOK_MSC_FORCEINLINE:
1966+
member_spec.set_inline(true);
1967+
break;
19631968
case TOK_VIRTUAL: member_spec.set_virtual(true); break;
19641969
case TOK_FRIEND: member_spec.set_friend(true); break;
19651970
case TOK_EXPLICIT: member_spec.set_explicit(true); break;

0 commit comments

Comments
 (0)