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
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to