Skip to content

C

This page curates a list of example ast-grep rules to check and to rewrite C code.

Rewrite Method to Function Call Has Fix

Description

In C, there is no built-in support for object-oriented programming, but some programmers use structs and function pointers to simulate classes and methods. However, this style can have some drawbacks, such as:

  • extra memory allocation and deallocation for the struct and the function pointer.
  • indirection overhead when calling the function pointer.

A possible alternative is to use a plain function call with the struct pointer as the first argument.

YAML

yaml
id: method_receiver
language: c
rule:
  pattern: $R.$METHOD($$$ARGS)
transform:
  MAYBE_COMMA:
    replace:
      source: $$$ARGS
      replace: '^.+'
      by: ', '
fix:
  $METHOD(&$R$MAYBE_COMMA$$$ARGS)

Example

c
void test_func() {
    some_struct->field.method();
    some_struct->field.other_method(1, 2, 3);
}

Diff

c
void test_func() {
    some_struct->field.method();
    method(&some_struct->field);
    some_struct->field.other_method(1, 2, 3);
    other_method(&some_struct->field, 1, 2, 3);
}

Contributed by

Surma, adapted from the original tweet

Rewrite Check to Yoda Condition Has Fix

Description

In programming jargon, a Yoda condition is a style that places the constant portion of the expression on the left side of the conditional statement. It is used to prevent assignment errors that may occur in languages like C.

YAML

yaml
id: may-the-force-be-with-you
language: c
rule:
  pattern: $A == $B                 # Find equality comparison
  inside:                           # inside an if_statement
    kind: parenthesized_expression
    inside: {kind: if_statement}
constraints:                        # with the constraint that
  B: { kind: number_literal }       # right side is a number
fix: $B == $A

The rule targets an equality comparison, denoted by the pattern $A == $B. This comparison must occur inside an if_statement. Additionally, there’s a constraint that the right side of the comparison, $B, must be a number_literal like 42.

Example

c
if (myNumber == 42) { /* ... */}
if (notMatch == another) { /* ... */}
if (notMatch) { /* ... */}

Diff

c
if (myNumber == 42) { /* ... */}
if (42 == myNumber) { /* ... */}
if (notMatch == another) { /* ... */}
if (notMatch) { /* ... */}

Contributed by

Inspired by this thread

Made with ❤️ with Rust