Matching variable declarations if they have the same type as a variable named “foo”

In this example we try to find variables of a specific type. It is similar to the first example but instead of using a fixed type we want to consider all types that were used to declare any variable named “foo”. You will learn how to inherit metavariable bindings from one rule to another and you will be using the metavariable type “type”.

The following semantic patch is the subject of this example:

@find_type@
type t;
@@
 
  t foo;
 
@@
type find_type.t;
identifier id;
@@
 
* t id;

The first rule matches the declaration of every variable named foo, “t” will then be the associated type.

The second rule is very similar to the rule of the first example except the it is using a metavariable to handle the type. The syntax <rule_name>.<metavariable_name> allows the rule where it is used to inherit a metavariable from a previous rule <rule_name>. Here, we inherit the values of “t” that were instantiated in “find_type”.

find_type declares a metavariable of type “type”, we then match declarations using “foo” as identifier and we have Coccinelle bind “t” to the different types.

We use the following C code to illustrate what the above semantic patch matches.

int f1() {
	char foo;
	return foo;
}
 
int f2() {
	int foo;
	foo = 0;
	return foo;
}
 
long f3() {
	long nfoo = 0;
	return nfoo;
}
 
long f4() {
	short var;
	var = 0;
	return var;
}
 
int f5() {
	char var;
	return var;
}
 
int f6() {
	int var;
	var = 0;
	return var;
}
 
long f7() {
	long var = 0;
	return var;
}
 
long f8() {
	short var;
	var = 0;
	return var;
}

The semantic patch generates the following patch:

--- tuto02.c
+++ /tmp/cocci-output-4640-40bc68-tuto02.c
@@ -1,10 +1,8 @@
 char f1() {
-	char foo;
 	return foo;
 }
 
 int f2() {
-	int foo;
 	foo = 0;
 	return foo;
 }
@@ -21,12 +19,10 @@ long f4() {
 }
 
 char f5() {
-	char var;
 	return var;
 }
 
 int f6() {
-	int var;
 	var = 0;
 	return var;
 }

Obviously every “foo” declaration is matched. Morevover “var” declared in “f6” is of type int, that is the same as “foo” declared in “f2” therefore its declaration is matched. Similarly, the declaration of “var” as a “char” in “f5” is matched because “foo” is defined as a “char” in “f1”.