Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the typecheck macro from the Linux kernel work?

The file include/linux/typecheck.h of the Linux kernel 4.16 contains this code.

#define typecheck(type,x) \
({      type __dummy; \
        typeof(x) __dummy2; \
        (void)(&__dummy == &__dummy2); \
        1; \
}

which checks if x is the same type as the parameter type.

But I can't understand the line:

 (void)(&__dummy == &__dummy2);

How does comparing the first address of both variables help?

like image 623
lxgeek Avatar asked May 01 '12 05:05

lxgeek


2 Answers

This uses two GCC extensions — expression statements ({ ... }) and typeof().

  1. The first line of the expansion declares a variable of the named type type.
  2. The second line of the expansion declares a variable of the same type as the variable or expression x.
  3. The third line compares the two pointers, which will only match if the types of the two dummy variables match, generating a pointer mismatch warning (or error if compiling with -Werror).
  4. The last line (containing the 1) is the value of the expression — equivalent to true.

So, you get a compilation warning/error if the type of x is not the same as the named type.

Example code:

#include <stdio.h>

#define typecheck(type,x) \
({      type __dummy; \
        typeof(x) __dummy2; \
        (void)(&__dummy == &__dummy2); \
        1; \
})

int main(void)
{
    int x;
    if (typecheck(int, x))
        printf("int x OK\n");
    if (typecheck(double, x))
        printf("double x OK\n");
    return(0);
}

Compilation message:

$ /usr/bin/gcc -O3 -g -std=gnu99 -Wall -Wextra xx.c -o xx  
xx.c: In function ‘main’:
xx.c:15: warning: comparison of distinct pointer types lacks a cast
$

Note that because I did not use -Werror, the code compiled 'OK'. The output was:

int x OK
double x OK
like image 156
Jonathan Leffler Avatar answered Oct 29 '22 07:10

Jonathan Leffler


Comparing pointers with incompatible types is a constraint violation and requires the compiler to issue a diagnostic. See 6.5.9 Equality operators:

Constraints

One of the following shall hold:

  • both operands have arithmetic type;
  • both operands are pointers to qualified or unqualified versions of compatible types;
  • one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void; or
  • one operand is a pointer and the other is a null pointer constant.

and 5.1.1.3 Diagnostics:

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.

like image 28
R.. GitHub STOP HELPING ICE Avatar answered Oct 29 '22 07:10

R.. GitHub STOP HELPING ICE