2. I have noticed that the discussed filter pattern needs another
extension.
What is the best way to express the other uses besides direct function
calls in
the semantic patch language?
How should function pointers be generally handled here that are used
with the
access operators "." or "->"?
I have extended the suggested approach a bit more.
elfring@Sonne:~/Projekte/Coccinelle/Probe> SRC=f-ptr-test1.c && cat $SRC &&
echo '-----' && PAT=../my_pattern2.cocci && cat $PAT && echo '-----' &&
spatch -sp_file $PAT $SRC
void my_log(char const * text)
{
/* Write something ... */
}
int my_safe_log(char const * text)
{
if (!text)
return 1;
my_log(text);
return 0;
}
char const * const my_message(void)
{
return "Surprise!";
}
int my_status(void)
{
return 1;
}
int my_addition(char a, char b)
{
return a + b;
}
int main(void)
{
struct my_operations
{
void (*log)(char const * t);
int (*safe_log)(char const * t);
char const * const (*get_message)(void);
int (*is_ready)(void);
int (*add)(char a, char b);
} mo = {my_log, my_safe_log, my_message, my_status, my_addition}, * mop =
&mo;
char const * const x = mo.get_message();
int y = mop->is_ready();
y = mop->add(1, 2);
y = mo.add(3, 4);
mo.log(mo.get_message());
mo.is_ready();
my_safe_log(0);
mo.safe_log(0);
mop->safe_log(0);
}
-----
@r@
identifier f;
@@
f(...);
@is_void@
identifier r.f;
@@
void f(...);
@depends on !is_void@
identifier r.f != {strcpy, strcat};
identifier g;
@@
g(...)
{<+...
* f(...);
...+>}
@is_member_function@
identifier f, s;
type t;
@@
struct s
{
...
t (*f)(...);
...
}
@is_void_member_function@
identifier is_member_function.f, s;
@@
struct s
{
...
void (*f)(...);
...
}
@depends on !is_void_member_function@
identifier is_member_function.f != {my_strcpy, my_strcat, my_fread,
my_fclose, log, add};
identifier g;
expression a, b;
@@
g(...)
{<+...
(
* (a)->f(...);
|
* (b).f(...);
)
...+>}
@is_assigned@
position p;
expression a, b, v, w, x, y;
expression f != {strcpy, strcat, fread, fclose};
identifier g != {my_strcpy, my_strcat, my_fread, my_fclose, log, add};
identifier h != {my_strcpy, my_strcat, my_fread, my_fclose, log, add};
identifier c, d;
statement S1, S2, S3, S4;
type t;
@@
(
y@p = (t) (x)(...)
|
y@p = (t) (a)->c(...)
|
y@p = (t) (b).d(...)
)
... when != if (<+...y...+>) S1 else S2
when != (f)(...,<+...y...+>,...)
when != (v)->g(...,<+...y...+>,...)
when != (w).h(...,<+...y...+>,...)
when != for (...;<+...y...+>;...) S3
when != while (<+...y...+>) S4
when != switch (<+...y...+>) { case ... : ... }
when != (<+...y...+>) ? ... : ...
@is_assigned_without_when_filters@
position p != is_assigned.p;
expression a, b, x, y;
identifier is_assigned.c, is_assigned.d;
type t;
@@
(
*y@p = (t) (x)(...)
|
*y@p = (t) (a)->c(...)
|
*y@p = (t) (b).d(...)
)
-----
init_defs_builtins: /usr/share/coccinelle/standard.h
HANDLING: f-ptr-test1.c
diff =
--- f-ptr-test1.c
+++ /tmp/cocci-output-6499-ab8654-f-ptr-test1.c
@@ -8,7 +8,6 @@ int my_safe_log(char const * text)
if (!text)
return 1;
- my_log(text);
return 0;
}
@@ -39,12 +38,6 @@ int main(void)
} mo = {my_log, my_safe_log, my_message, my_status, my_addition}, * mop =
&mo;
char const * const x = mo.get_message();
- int y = mop->is_ready();
- y = mop->add(1, 2);
y = mo.add(3, 4);
mo.log(mo.get_message());
- mo.is_ready();
- my_safe_log(0);
- mo.safe_log(0);
- mop->safe_log(0);
}
Now I wonder why the line "y = mo.add(3, 4);" is not marked in the promising
analysis result.
Would you like to suggest another fine-tuning for this selection pattern?
Regards,
Markus