* [PATCH 1/3] add testcases for multiple deref of calls
2017-12-21 0:19 [PATCH 0/3] multiple dereference in function calls Luc Van Oostenryck
@ 2017-12-21 0:19 ` Luc Van Oostenryck
2017-12-21 0:19 ` [PATCH 2/3] avoid unneeded alloc on error path Luc Van Oostenryck
2017-12-21 0:19 ` [PATCH 3/3] dereference of a function is a no-op Luc Van Oostenryck
2 siblings, 0 replies; 4+ messages in thread
From: Luc Van Oostenryck @ 2017-12-21 0:19 UTC (permalink / raw)
To: linux-sparse; +Cc: Luc Van Oostenryck
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
validation/function-pointer-type.c | 4 ++++
validation/linear/call-builtin.c | 6 +++++-
validation/linear/call-direct.c | 6 +++++-
validation/linear/call-indirect.c | 5 ++++-
validation/linear/call-inline.c | 6 +++++-
5 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/validation/function-pointer-type.c b/validation/function-pointer-type.c
index 8fd792b3b..cb1f59b2a 100644
--- a/validation/function-pointer-type.c
+++ b/validation/function-pointer-type.c
@@ -2,8 +2,12 @@ extern int fun(void);
void fa(void) { int (*f)(void); f = &fun; }
void f0(void) { int (*f)(void); f = fun; } // C99,C11 6.3.2.1p4
+void f1(void) { int (*f)(void); f = *fun; } // C99,C11 6.5.3.2p4
+void f2(void) { int (*f)(void); f = **fun; } // C99,C11 6.5.3.2p4
+void f3(void) { int (*f)(void); f = ***fun; } // C99,C11 6.5.3.2p4
/*
* check-name: type of function pointers
* check-command: sparse -Wno-decl $file
+ * check-known-to-fail
*/
diff --git a/validation/linear/call-builtin.c b/validation/linear/call-builtin.c
index af0148aa4..b0261e992 100644
--- a/validation/linear/call-builtin.c
+++ b/validation/linear/call-builtin.c
@@ -3,12 +3,16 @@ typedef unsigned int u32;
u32 ff(u32 a) { return __builtin_popcount(a); }
u32 f0(u32 a) { return (__builtin_popcount)(a); }
+u32 f1(u32 a) { return (*__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
+u32 f2(u32 a) { return (**__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
+u32 f3(u32 a) { return (***__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
/*
* check-name: builtin calls
* check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
- * check-output-pattern(2): call\..*__builtin_.*, %arg1
+ * check-output-pattern(5): call\..*__builtin_.*, %arg1
*/
diff --git a/validation/linear/call-direct.c b/validation/linear/call-direct.c
index 78321ab02..176bfe229 100644
--- a/validation/linear/call-direct.c
+++ b/validation/linear/call-direct.c
@@ -3,12 +3,16 @@ extern int fun(void);
int ff(void) { return fun(); }
int f0(void) { return (fun)(); }
+int f1(void) { return (*fun)(); } // C99,C11 6.5.3.2p4
+int f2(void) { return (**fun)(); } // C99,C11 6.5.3.2p4
+int f3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4
/*
* check-name: direct calls
* check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
- * check-output-pattern(2): call\..* fun
+ * check-output-pattern(5): call\..* fun
*/
diff --git a/validation/linear/call-indirect.c b/validation/linear/call-indirect.c
index f5f2adaf1..d8797b024 100644
--- a/validation/linear/call-indirect.c
+++ b/validation/linear/call-indirect.c
@@ -2,12 +2,15 @@ int gg(int (*fun)(void)) { return fun(); }
int g0(int (*fun)(void)) { return (fun)(); }
int g1(int (*fun)(void)) { return (*fun)(); } // C99,C11 6.5.3.2p4
+int g2(int (*fun)(void)) { return (**fun)(); } // C99,C11 6.5.3.2p4
+int g3(int (*fun)(void)) { return (***fun)(); } // C99,C11 6.5.3.2p4
/*
* check-name: indirect calls
* check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
- * check-output-pattern(3): call\..* %arg1
+ * check-output-pattern(5): call\..* %arg1
*/
diff --git a/validation/linear/call-inline.c b/validation/linear/call-inline.c
index 32f32461c..d931a3cba 100644
--- a/validation/linear/call-inline.c
+++ b/validation/linear/call-inline.c
@@ -3,13 +3,17 @@ static inline int fun(void) { return 42; }
int fi(void) { return fun(); }
int i0(void) { return (fun)(); }
+int i1(void) { return (*fun)(); } // C99,C11 6.5.3.2p4
+int i2(void) { return (**fun)(); } // C99,C11 6.5.3.2p4
+int i3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4
/*
* check-name: inline calls
* check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
* check-output-excludes: call
- * check-output-pattern(2): ret\..* \\$42
+ * check-output-pattern(5): ret\..* \\$42
*/
--
2.15.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/3] avoid unneeded alloc on error path
2017-12-21 0:19 [PATCH 0/3] multiple dereference in function calls Luc Van Oostenryck
2017-12-21 0:19 ` [PATCH 1/3] add testcases for multiple deref of calls Luc Van Oostenryck
@ 2017-12-21 0:19 ` Luc Van Oostenryck
2017-12-21 0:19 ` [PATCH 3/3] dereference of a function is a no-op Luc Van Oostenryck
2 siblings, 0 replies; 4+ messages in thread
From: Luc Van Oostenryck @ 2017-12-21 0:19 UTC (permalink / raw)
To: linux-sparse; +Cc: Luc Van Oostenryck
In evaluate_dereference(), a node is allocated but
is not used if there is an error.
Fix this by allocating the node after the error checks.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
evaluate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/evaluate.c b/evaluate.c
index 6b3e2c257..e6dbe3d8d 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1776,7 +1776,6 @@ static struct symbol *evaluate_dereference(struct expression *expr)
if (ctype->type == SYM_NODE)
ctype = ctype->ctype.base_type;
- node = alloc_symbol(expr->pos, SYM_NODE);
target = ctype->ctype.base_type;
switch (ctype->type) {
@@ -1784,6 +1783,7 @@ static struct symbol *evaluate_dereference(struct expression *expr)
expression_error(expr, "cannot dereference this type");
return NULL;
case SYM_PTR:
+ node = alloc_symbol(expr->pos, SYM_NODE);
node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER;
merge_type(node, ctype);
break;
@@ -1801,6 +1801,7 @@ static struct symbol *evaluate_dereference(struct expression *expr)
* When an array is dereferenced, we need to pick
* up the attributes of the original node too..
*/
+ node = alloc_symbol(expr->pos, SYM_NODE);
merge_type(node, op->ctype);
merge_type(node, ctype);
break;
--
2.15.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 3/3] dereference of a function is a no-op
2017-12-21 0:19 [PATCH 0/3] multiple dereference in function calls Luc Van Oostenryck
2017-12-21 0:19 ` [PATCH 1/3] add testcases for multiple deref of calls Luc Van Oostenryck
2017-12-21 0:19 ` [PATCH 2/3] avoid unneeded alloc on error path Luc Van Oostenryck
@ 2017-12-21 0:19 ` Luc Van Oostenryck
2 siblings, 0 replies; 4+ messages in thread
From: Luc Van Oostenryck @ 2017-12-21 0:19 UTC (permalink / raw)
To: linux-sparse; +Cc: Luc Van Oostenryck
For the '*' operator and functions, the C standard says:
"If the operand points to a function, the result is a
function designator; ... If the operand has type
‘pointer to type’, the result has type ‘type’".
but also (C11 6.3.2.1p4):
"(except with 'sizeof' ...) a function designator with type
‘function returning type’ is converted to an expression
that has type ‘pointer to function returning type’".
This means that in dereferencement of a function-designator is
a no-op since the resulting expression is immediately back converted
to a pointer to the function.
The change effectively drop any dereferencement of function types
during their evaluation.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
evaluate.c | 3 +++
validation/function-pointer-type.c | 1 -
validation/linear/call-builtin.c | 1 -
validation/linear/call-direct.c | 1 -
validation/linear/call-indirect.c | 1 -
validation/linear/call-inline.c | 1 -
validation/sizeof-function.c | 1 -
7 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/evaluate.c b/evaluate.c
index e6dbe3d8d..840f98d3e 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1782,6 +1782,9 @@ static struct symbol *evaluate_dereference(struct expression *expr)
default:
expression_error(expr, "cannot dereference this type");
return NULL;
+ case SYM_FN:
+ *expr = *op;
+ return expr->ctype;
case SYM_PTR:
node = alloc_symbol(expr->pos, SYM_NODE);
node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER;
diff --git a/validation/function-pointer-type.c b/validation/function-pointer-type.c
index cb1f59b2a..ebc4007ba 100644
--- a/validation/function-pointer-type.c
+++ b/validation/function-pointer-type.c
@@ -9,5 +9,4 @@ void f3(void) { int (*f)(void); f = ***fun; } // C99,C11 6.5.3.2p4
/*
* check-name: type of function pointers
* check-command: sparse -Wno-decl $file
- * check-known-to-fail
*/
diff --git a/validation/linear/call-builtin.c b/validation/linear/call-builtin.c
index b0261e992..b15113593 100644
--- a/validation/linear/call-builtin.c
+++ b/validation/linear/call-builtin.c
@@ -10,7 +10,6 @@ u32 f3(u32 a) { return (***__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
/*
* check-name: builtin calls
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
diff --git a/validation/linear/call-direct.c b/validation/linear/call-direct.c
index 176bfe229..52f86306b 100644
--- a/validation/linear/call-direct.c
+++ b/validation/linear/call-direct.c
@@ -10,7 +10,6 @@ int f3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4
/*
* check-name: direct calls
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
diff --git a/validation/linear/call-indirect.c b/validation/linear/call-indirect.c
index d8797b024..1275910c4 100644
--- a/validation/linear/call-indirect.c
+++ b/validation/linear/call-indirect.c
@@ -8,7 +8,6 @@ int g3(int (*fun)(void)) { return (***fun)(); } // C99,C11 6.5.3.2p4
/*
* check-name: indirect calls
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
diff --git a/validation/linear/call-inline.c b/validation/linear/call-inline.c
index d931a3cba..a33f0a1c8 100644
--- a/validation/linear/call-inline.c
+++ b/validation/linear/call-inline.c
@@ -10,7 +10,6 @@ int i3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4
/*
* check-name: inline calls
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-excludes: load
diff --git a/validation/sizeof-function.c b/validation/sizeof-function.c
index 20c795e94..27d535d4e 100644
--- a/validation/sizeof-function.c
+++ b/validation/sizeof-function.c
@@ -36,7 +36,6 @@ int test(void)
/*
* check-name: sizeof-function
* check-command: sparse -Wno-decl $file
- * check-known-to-fail
*
* check-error-start
sizeof-function.c:22:14: warning: expression using sizeof on a function
--
2.15.0
^ permalink raw reply related [flat|nested] 4+ messages in thread