aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-09-30 16:30:51 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-06-18 21:57:34 +0200
commitbe9df1ee611da4eb40ca77f51eb64388b53ca58c (patch)
treebab0f66f809f6b751d12d00edbed06dae5470963
parente6b31b72c25f767b6ac661ef36963ac2c2787ac4 (diff)
downloadsparse-be9df1ee611da4eb40ca77f51eb64388b53ca58c.tar.gz
pre-process: add support for __has_feature() & __has_extension()
Add the trivial methods for the expansion of these macros with: c_alignas, c_alignof, c_generic_selections and c_static_assert. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--ident-list.h4
-rw-r--r--pre-process.c54
-rw-r--r--validation/preprocessor/has-feature.c1
3 files changed, 58 insertions, 1 deletions
diff --git a/ident-list.h b/ident-list.h
index 75740b9d..a3a28258 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -61,6 +61,10 @@ IDENT(defined);
IDENT(once);
IDENT(__has_attribute);
IDENT(__has_builtin);
+IDENT(c_alignas);
+IDENT(c_alignof);
+IDENT(c_generic_selections);
+IDENT(c_static_assert);
__IDENT(pragma_ident, "__pragma__", 0);
__IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0);
__IDENT(__func___ident, "__func__", 0);
diff --git a/pre-process.c b/pre-process.c
index d2e13400..7a39b171 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -2003,6 +2003,58 @@ static int handle_nondirective(struct stream *stream, struct token **line, struc
return 1;
}
+static bool expand_has_extension(struct token *token, struct arg *args)
+{
+ struct token *arg = args[0].expanded;
+ struct ident *ident;
+ bool val = false;
+
+ if (token_type(arg) != TOKEN_IDENT) {
+ sparse_error(arg->pos, "identifier expected");
+ return false;
+ }
+
+ ident = arg->ident;
+ if (ident == &c_alignas_ident)
+ val = true;
+ else if (ident == &c_alignof_ident)
+ val = true;
+ else if (ident == &c_generic_selections_ident)
+ val = true;
+ else if (ident == &c_static_assert_ident)
+ val = true;
+
+ replace_with_bool(token, val);
+ return 1;
+}
+
+static bool expand_has_feature(struct token *token, struct arg *args)
+{
+ struct token *arg = args[0].expanded;
+ struct ident *ident;
+ bool val = false;
+
+ if (token_type(arg) != TOKEN_IDENT) {
+ sparse_error(arg->pos, "identifier expected");
+ return false;
+ }
+
+ ident = arg->ident;
+ if (standard >= STANDARD_C11) {
+ if (ident == &c_alignas_ident)
+ val = true;
+ else if (ident == &c_alignof_ident)
+ val = true;
+ else if (ident == &c_generic_selections_ident)
+ val = true;
+ else if (ident == &c_static_assert_ident)
+ val = true;
+ }
+
+ replace_with_bool(token, val);
+ return 1;
+}
+
static void create_arglist(struct symbol *sym, int count)
{
struct token *token;
@@ -2081,6 +2133,8 @@ static void init_preprocessor(void)
{ "__TIME__", expand_time },
{ "__COUNTER__", expand_counter },
{ "__INCLUDE_LEVEL__", expand_include_level },
+ { "__has_extension", NULL, expand_has_extension },
+ { "__has_feature", NULL, expand_has_feature },
};
for (i = 0; i < ARRAY_SIZE(normal); i++) {
diff --git a/validation/preprocessor/has-feature.c b/validation/preprocessor/has-feature.c
index 3ab7c3e0..e0f2e7f6 100644
--- a/validation/preprocessor/has-feature.c
+++ b/validation/preprocessor/has-feature.c
@@ -12,7 +12,6 @@ __has_feature()??? Quesako?
/*
* check-name: has-feature
* check-command: sparse -E $file
- * check-known-to-fail
*
* check-output-start