Skip to content

Commit 9d75cb0

Browse files
committed
Revise __has_attribute() and __has_c_attribute()
1 parent 68d6b0c commit 9d75cb0

File tree

2 files changed

+38
-22
lines changed

2 files changed

+38
-22
lines changed

preprocess.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ static bool has_macro(Token *tok);
8484
static bool expand_macro(Token **rest, Token *tok, bool is_root);
8585
static Token *directives(Token **cur, Token *start);
8686
static Token *subst(Token *tok, MacroContext *ctx);
87-
static bool is_supported_attr(bool is_bracket, Token *vendor, Token *tok);
87+
static bool is_supported_attr(Token *tok);
88+
static char *is_supported_c_attr(Token *vendor, Token *tok);
8889
static void newline_to_space(Token *tok);
8990
static Token *pragma_macro(Token *start);
9091

@@ -1727,7 +1728,7 @@ static Token *has_embed_macro(Token *start) {
17271728
static Token *has_attribute_macro(Token *start) {
17281729
Token *tok = skip(start->next, "(");
17291730

1730-
bool val = is_supported_attr(false, NULL, tok);
1731+
bool val = is_supported_attr(tok);
17311732

17321733
tok = skip(tok->next, ")");
17331734
pop_macro_lock_until(start, tok);
@@ -1742,11 +1743,11 @@ static Token *has_c_attribute_macro(Token *start) {
17421743
vendor = tok;
17431744
tok = skip(tok->next->next, ":");
17441745
}
1745-
bool val = is_supported_attr(true, vendor, tok);
1746+
char *str = is_supported_c_attr(vendor, tok);
17461747

17471748
tok = skip(tok->next, ")");
17481749
pop_macro_lock_until(start, tok);
1749-
return new_num_token(val, start, tok);
1750+
return make_token(str ? str : "0", start, tok);
17501751
}
17511752

17521753
static Token *has_builtin_macro(Token *start) {
@@ -1961,6 +1962,7 @@ static bool is_gnu_attr(Token *tok) {
19611962
PutAttr("destructor");
19621963
PutAttr("gnu_inline");
19631964
PutAttr("naked");
1965+
PutAttr("noreturn");
19641966
PutAttr("packed");
19651967
PutAttr("returns_twice");
19661968
PutAttr("section");
@@ -1975,19 +1977,24 @@ static bool is_gnu_attr(Token *tok) {
19751977
return hashmap_get2(&map, tok->loc, tok->len);
19761978
}
19771979

1978-
static bool is_supported_attr(bool is_bracket, Token *vendor, Token *tok) {
1980+
static bool is_supported_attr(Token *tok) {
19791981
if (tok->kind != TK_IDENT)
19801982
error_tok(tok, "expected attribute name");
19811983

1982-
bool gnu_if_battr = !is_bracket || (vendor && equal_ext(vendor, "gnu"));
1984+
return is_gnu_attr(tok);
1985+
}
19831986

1984-
if (gnu_if_battr && is_gnu_attr(tok))
1985-
return true;
1987+
static char *is_supported_c_attr(Token *vendor, Token *tok) {
1988+
if (tok->kind != TK_IDENT)
1989+
error_tok(tok, "expected attribute name");
19861990

1987-
if (equal_ext(tok, "noreturn"))
1988-
return true;
1991+
if (vendor && equal_ext(vendor, "gnu") && is_gnu_attr(tok))
1992+
return "1";
19891993

1990-
return false;
1994+
if (equal_ext(tok, "noreturn") || equal_ext(tok, "_Noreturn"))
1995+
return "202311L";
1996+
1997+
return NULL;
19911998
}
19921999

19932000
static void filter_attr(Token *tok, Token **lst, bool is_bracket) {
@@ -2008,14 +2015,12 @@ static void filter_attr(Token *tok, Token **lst, bool is_bracket) {
20082015
tok = skip(tok->next->next, ":");
20092016
}
20102017
Token *start = tok;
2011-
bool is_sup_attr = is_supported_attr(is_bracket, vendor, tok);
2012-
20132018
if (consume(&tok, tok->next, "("))
20142019
tok = skip_paren(tok);
20152020
else
20162021
tok = tok->next;
20172022

2018-
if (is_sup_attr) {
2023+
if (is_bracket ? !!is_supported_c_attr(vendor, start) : is_supported_attr(start)) {
20192024
Token head = {0};
20202025
Token *cur = &head;
20212026
for (Token *t = start; t != tok; t = t->next)

test/attribute2.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,28 @@
1212
#error
1313
#endif
1414

15+
#define STRH(x) #x
16+
#define STR(x) STRH(x)
1517
#define CAT(x,y) x##y
1618

17-
int has_attr(void) {
18-
DASSERT(__has_attribute(packed) == 1);
19-
DASSERT( CAT(__has,_attribute)(packed) == 1);
20-
DASSERT(__has_c_attribute(gnu::packed) == 1);
21-
DASSERT(__has_c_attribute(gnu::__packed__) == 1);
22-
DASSERT(__has_c_attribute(__gnu__::packed) == 1);
23-
DASSERT(__has_c_attribute(clang::packed) == 0);
24-
}
19+
void has_attr(void) {
20+
ASSERT(0, strcmp("1", STR(__has_attribute(packed))));
21+
ASSERT(0, strcmp("1", STR(CAT(__has,_attribute)(packed))));
22+
23+
ASSERT(0, strcmp("1", STR(__has_c_attribute(gnu::packed))));
24+
ASSERT(0, strcmp("1", STR(__has_c_attribute(gnu::__packed__))));
25+
ASSERT(0, strcmp("1", STR(__has_c_attribute(__gnu__::packed))));
26+
27+
ASSERT(0, strcmp("0", STR(__has_c_attribute(packed))));
28+
ASSERT(0, strcmp("0", STR(__has_c_attribute(zzzzzz::packed))));
2529

30+
#ifdef __slimcc__
31+
ASSERT(0, strcmp("202311L", STR(__has_c_attribute(noreturn))));
32+
ASSERT(0, strcmp("202311L", STR(__has_c_attribute(__noreturn__))));
33+
ASSERT(0, strcmp("202311L", STR(__has_c_attribute(_Noreturn))));
34+
ASSERT(0, strcmp("202311L", STR(__has_c_attribute(___Noreturn__))));
35+
#endif
36+
}
2637

2738
[[_Noreturn]]
2839
int fallthrough(int i) {

0 commit comments

Comments
 (0)