Skip to content

Commit 4ac1501

Browse files
committed
Interpret __attribute__((alias("foo")))
1 parent fb25eb8 commit 4ac1501

File tree

8 files changed

+73
-6
lines changed

8 files changed

+73
-6
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <assert.h>
2+
3+
int foo(int a)
4+
{
5+
return a;
6+
}
7+
8+
// this is a GCC extension
9+
10+
int bar(int b) __attribute__((alias("foo")));
11+
12+
__typeof__(foo) bar2 __attribute__((alias("foo")));
13+
14+
int main()
15+
{
16+
#ifdef __GNUC__
17+
assert(bar(42)==42);
18+
assert(bar2(42)==42);
19+
#endif
20+
return 0;
21+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$

src/ansi-c/ansi_c_convert_type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ void ansi_c_convert_typet::read_rec(const typet &type)
233233
constructor=true;
234234
else if(type.id()==ID_destructor)
235235
destructor=true;
236+
else if(type.id()==ID_alias &&
237+
type.has_subtype() &&
238+
type.subtype().id()==ID_string_constant)
239+
{
240+
c_storage_spec.alias=type.subtype().get(ID_value);
241+
}
236242
else
237243
other.push_back(type);
238244
}

src/ansi-c/c_storage_spec.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,10 @@ void c_storage_spect::read(const typet &type)
5555
if(it->id()==ID_thread)
5656
is_thread_local=true;
5757
}
58+
else if(type.id()==ID_alias &&
59+
type.has_subtype() &&
60+
type.subtype().id()==ID_string_constant)
61+
{
62+
alias=type.subtype().get(ID_value);
63+
}
5864
}

src/ansi-c/c_storage_spec.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ class c_storage_spect
3434
is_register=false;
3535
is_inline=false;
3636
is_weak=false;
37+
alias.clear();
3738
}
3839

3940
bool is_typedef, is_extern, is_static, is_register,
4041
is_inline, is_thread_local, is_weak;
42+
43+
// __attribute__((alias("foo")))
44+
irep_idt alias;
4145

4246
friend bool operator == (
4347
const c_storage_spect &a,
@@ -49,7 +53,8 @@ class c_storage_spect
4953
a.is_register==b.is_register &&
5054
a.is_thread_local==b.is_thread_local &&
5155
a.is_inline==b.is_inline &&
52-
a.is_weak==b.is_weak;
56+
a.is_weak==b.is_weak &&
57+
a.alias==b.alias;
5358
}
5459

5560
friend bool operator != (
@@ -70,6 +75,7 @@ class c_storage_spect
7075
a.is_inline |=b.is_inline;
7176
a.is_thread_local |=b.is_thread_local;
7277
a.is_weak |=b.is_weak;
78+
if(!b.alias.empty()) a.alias=b.alias;
7379

7480
return a;
7581
}

src/ansi-c/c_typecheck_base.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,17 @@ void c_typecheck_baset::typecheck_declaration(
759759
// now check other half of type
760760
typecheck_type(symbol.type);
761761

762+
if(!full_spec.alias.empty())
763+
{
764+
if(symbol.value.is_not_nil())
765+
throw "alias attribute cannot be used with a body";
766+
767+
// alias function need not have been declared yet, thus
768+
// can't lookup
769+
symbol.value=symbol_exprt(full_spec.alias);
770+
symbol.is_macro=true;
771+
}
772+
762773
typecheck_symbol(symbol);
763774

764775
// add code contract (if any); we typecheck this after the

src/ansi-c/parser.y

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ extern char *yyansi_ctext;
132132
%token TOK_GCC_ATTRIBUTE_MODE "mode"
133133
%token TOK_GCC_ATTRIBUTE_GNU_INLINE "__gnu_inline__"
134134
%token TOK_GCC_ATTRIBUTE_WEAK "weak"
135+
%token TOK_GCC_ATTRIBUTE_ALIAS "alias"
135136
%token TOK_GCC_ATTRIBUTE_NORETURN "noreturn"
136137
%token TOK_GCC_ATTRIBUTE_CONSTRUCTOR "constructor"
137138
%token TOK_GCC_ATTRIBUTE_DESTRUCTOR "destructor"
@@ -1564,6 +1565,8 @@ gcc_type_attribute:
15641565
{ $$=$1; set($$, ID_static); } /* GCC extern inline - cleanup in ansi_c_declarationt::to_symbol */
15651566
| TOK_GCC_ATTRIBUTE_WEAK TOK_GCC_ATTRIBUTE_END
15661567
{ $$=$1; set($$, ID_weak); }
1568+
| TOK_GCC_ATTRIBUTE_ALIAS '(' TOK_STRING ')' TOK_GCC_ATTRIBUTE_END
1569+
{ $$=$1; set($$, ID_alias); mto($$, $3); }
15671570
| TOK_NORETURN
15681571
{ $$=$1; set($$, ID_noreturn); }
15691572
| TOK_GCC_ATTRIBUTE_NORETURN TOK_GCC_ATTRIBUTE_END

src/ansi-c/scanner.l

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
%option nounput
22
%option noinput
3+
%option stack
34

45
%{
56

@@ -230,7 +231,7 @@ void ansi_c_scanner_init()
230231
}
231232

232233
<STRING_LITERAL_COMMENT>{
233-
"*/" { BEGIN(STRING_LITERAL); } /* end comment state, back to STRING_LITERAL */
234+
"*/" { yy_pop_state(); } /* end comment state, back to STRING_LITERAL */
234235
"/*" { yyansi_cerror("Probably nested comments"); }
235236
<<EOF>> { yyansi_cerror("Unterminated comment"); return TOK_SCANNER_ERROR; }
236237
[^*/\n]* { /* ignore every char except '*' and NL (performance!) */ }
@@ -252,14 +253,16 @@ void ansi_c_scanner_init()
252253
return TOK_CHARACTER;
253254
}
254255

255-
<GRAMMAR>{string_lit} {
256+
<GRAMMAR,GCC_ATTRIBUTE3>{string_lit} {
256257
PARSER.string_literal.clear();
257258
PARSER.string_literal.append(yytext);
258259
newstack(yyansi_clval);
259260
PARSER.set_source_location(stack(yyansi_clval));
260261
// String literals can be continued in
261262
// the next line
262-
BEGIN(STRING_LITERAL);
263+
yy_push_state(STRING_LITERAL);
264+
// use yy_top_state() to keep the compiler happy
265+
(void)yy_top_state();
263266
}
264267

265268
<STRING_LITERAL>{string_lit} { PARSER.string_literal.append(yytext); }
@@ -270,13 +273,13 @@ void ansi_c_scanner_init()
270273
PARSER.set_line_no(PARSER.get_line_no()-1);
271274
}
272275
<STRING_LITERAL>{cppdirective} { /* ignore */ }
273-
<STRING_LITERAL>"/*" { BEGIN(STRING_LITERAL_COMMENT); /* C comment, ignore */ }
276+
<STRING_LITERAL>"/*" { yy_push_state(STRING_LITERAL_COMMENT); /* C comment, ignore */ }
274277
<STRING_LITERAL>"//".*\n { /* C++ comment, ignore */ }
275278
<STRING_LITERAL>. { // anything else: back to normal
276279
source_locationt l=stack(yyansi_clval).source_location();
277280
stack(yyansi_clval)=convert_string_literal(PARSER.string_literal);
278281
stack(yyansi_clval).add_source_location().swap(l);
279-
BEGIN(GRAMMAR); // back to normal
282+
yy_pop_state(); // back to normal
280283
yyless(0); // put back
281284
return TOK_STRING;
282285
}
@@ -1390,6 +1393,9 @@ __decltype { if(PARSER.cpp98 && PARSER.mode==ansi_c_parsert::GCC)
13901393
"weak" |
13911394
"__weak__" { BEGIN(GCC_ATTRIBUTE3); loc(); return TOK_GCC_ATTRIBUTE_WEAK; }
13921395

1396+
"alias" |
1397+
"__alias__" { BEGIN(GCC_ATTRIBUTE3); loc(); return TOK_GCC_ATTRIBUTE_ALIAS; }
1398+
13931399
"noreturn" |
13941400
"__noreturn__" { BEGIN(GCC_ATTRIBUTE3); loc(); return TOK_GCC_ATTRIBUTE_NORETURN; }
13951401

0 commit comments

Comments
 (0)