Lably
Skip to content

Sparse

Computer software coding tool

  • 3 min read
  • 1 chapter

Related on Lably

Through Data type

Sparse checks for known problems and allows the developer to include annotations in the code that convey information about data types, such as the address space that pointers point to and the locks that a function acquires or releases.

Linus Torvalds started writing Sparse in 2003. Josh Triplett was its maintainer from 2006, a role taken over by Christopher Li in 2009 and by Luc Van Oostenryck in November 2018. Sparse is released under the MIT License.

Annotations

Some of the checks performed by Sparse require annotating the source code using the __attribute__ GCC extension, or the Sparse-specific __context__ specifier. Sparse defines the following list of attributes:

  • address_space(num)
  • bitwise
  • force
  • context(expression,in_context,out_context)

When an API is defined with a macro, the specifier __attribute__((context(...))) can be replaced by __context__(...).

Linux kernel definitions

The Linux kernel defines the following short forms as pre-processor macros in files linux/compiler.h and linux/types.h (when building without the __CHECKER__ flag, all these annotations are removed from the code):

<span id="mwRQ"></span><span class="cp" id="mwRg">#ifdef __CHECKER__</span> <span class="cp" id="mwRw"># define __user __attribute__((noderef, address_space(1)))</span> <span class="cp" id="mwSA"># define __kernel __attribute__((address_space(0)))</span> <span class="cp" id="mwSQ"># define __safe __attribute__((safe))</span> <span class="cp" id="mwSg"># define __force __attribute__((force))</span> <span class="cp" id="mwSw"># define __nocast __attribute__((nocast))</span> <span class="cp" id="mwTA"># define __iomem __attribute__((noderef, address_space(2)))</span> <span class="cp" id="mwTQ"># define __must_hold(x) __attribute__((context(x,1,1)))</span> <span class="cp" id="mwTg"># define __acquires(x) __attribute__((context(x,0,1)))</span> <span class="cp" id="mwTw"># define __releases(x) __attribute__((context(x,1,0)))</span> <span class="cp" id="mwUA"># define __acquire(x) __context__(x,1)</span> <span class="cp" id="mwUQ"># define __release(x) __context__(x,-1)</span> <span class="cp" id="mwUg"># define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)</span> <span class="cp" id="mwUw"># define __percpu __attribute__((noderef, address_space(3)))</span> <span class="cp" id="mwVA">#ifdef CONFIG_SPARSE_RCU_POINTER</span> <span class="cp" id="mwVQ"># define __rcu __attribute__((noderef, address_space(4)))</span> <span class="cp" id="mwVg">#else</span> <span class="cp" id="mwVw"># define __rcu</span> <span class="cp" id="mwWA">#endif</span> <span class="k" id="mwWQ">extern</span><span class="w" id="mwWg"> </span><span class="kt" id="mwWw">void</span><span class="w" id="mwXA"> </span><span class="nf" id="mwXQ">__chk_user_ptr</span><span class="p" id="mwXg">(</span><span class="k" id="mwXw">const</span><span class="w" id="mwYA"> </span><span class="k" id="mwYQ">volatile</span><span class="w" id="mwYg"> </span><span class="kt" id="mwYw">void</span><span class="w" id="mwZA"> </span><span class="n" id="mwZQ">__user</span><span class="w" id="mwZg"> </span><span class="o" id="mwZw">*</span><span class="p" id="mwaA">);</span> <span class="k" id="mwaQ">extern</span><span class="w" id="mwag"> </span><span class="kt" id="mwaw">void</span><span class="w" id="mwbA"> </span><span class="nf" id="mwbQ">__chk_io_ptr</span><span class="p" id="mwbg">(</span><span class="k" id="mwbw">const</span><span class="w" id="mwcA"> </span><span class="k" id="mwcQ">volatile</span><span class="w" id="mwcg"> </span><span class="kt" id="mwcw">void</span><span class="w" id="mwdA"> </span><span class="n" id="mwdQ">__iomem</span><span class="w" id="mwdg"> </span><span class="o" id="mwdw">*</span><span class="p" id="mweA">);</span> <span class="cp" id="mweQ">#else</span> <span class="cp" id="mweg"># define __user</span> <span class="cp" id="mwew"># define __kernel</span> <span class="cp" id="mwfA"># define __safe</span> <span class="cp" id="mwfQ"># define __force</span> <span class="cp" id="mwfg"># define __nocast</span> <span class="cp" id="mwfw"># define __iomem</span> <span class="cp" id="mwgA"># define __chk_user_ptr(x) (void)0</span> <span class="cp" id="mwgQ"># define __chk_io_ptr(x) (void)0</span> <span class="cp" id="mwgg"># define __builtin_warning(x, y...) (1)</span> <span class="cp" id="mwgw"># define __must_hold(x)</span> <span class="cp" id="mwhA"># define __acquires(x)</span> <span class="cp" id="mwhQ"># define __releases(x)</span> <span class="cp" id="mwhg"># define __acquire(x) (void)0</span> <span class="cp" id="mwhw"># define __release(x) (void)0</span> <span class="cp" id="mwiA"># define __cond_lock(x,c) (c)</span> <span class="cp" id="mwiQ"># define __percpu</span> <span class="cp" id="mwig"># define __rcu</span> <span class="cp" id="mwiw">#endif</span>
<span id="mwjg"></span><span class="cp" id="mwjw">#ifdef __CHECKER__</span> <span class="cp" id="mwkA"># define __bitwise __attribute__((bitwise))</span> <span class="cp" id="mwkQ">#else</span> <span class="cp" id="mwkg"># define __bitwise</span> <span class="cp" id="mwkw">#endif</span>

Examples

The types __le32 and __be32 represent 32-bit integer types with different endianness. However, the C language does not allow to specify that variables of these types should not be mixed. The bitwise attribute is used to mark these types as restricted, so Sparse will give a warning if variables of these types or other integer variables are mixed:

<span id="mwnA"></span><span class="k" id="mwnQ">typedef</span><span class="w" id="mwng"> </span><span class="n" id="mwnw">__u32</span><span class="w" id="mwoA"> </span><span class="n" id="mwoQ">__bitwise</span><span class="w" id="mwog"> </span><span class="n" id="mwow">__le32</span><span class="p" id="mwpA">;</span> <span class="k" id="mwpQ">typedef</span><span class="w" id="mwpg"> </span><span class="n" id="mwpw">__u32</span><span class="w" id="mwqA"> </span><span class="n" id="mwqQ">__bitwise</span><span class="w" id="mwqg"> </span><span class="n" id="mwqw">__be32</span><span class="p" id="mwrA">;</span>

To mark valid conversions between restricted types, a casting with the force attribute is used to avoid Sparse giving a warning.

More in From Lably lessons