tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[PATCH] style(5): No struct typedefs



I propose the attached change to KNF style(5) to advise against
typedefs for structs or unions, or pointers to them.

Passing around pointers to structs and unions doesn't require the
definition, only a forward declaration:

struct vnode;
int frobnitz(struct vnode *);

This can dramatically cut down on header file dependencies so that
touching one header file doesn't cause the entire kernel to rebuild.
This also makes it clearer whether you are passing around a copy of a
struct or a pointer to a struct, which is often semantically important
not to conceal.

Typedefs are not necessary for opaque cookies to have labels, like
`typedef void *bus_dma_tag_t;'.  In fact, using void * here is bad
because it prevents the C compiler from checking types; bus_dma_tag_t
is indistinguishable from audio_dai_tag_t, and from pckbc_tag_t, and
from acpipmtimer_t, and from sdmmc_chipset_handle_t.

If we used `struct bus_dma_tag *' instead, the forward declaration
could be `struct bus_dma_tag;' instead of having to pull in all of
sys/bus.h, _and_ the C compiler would actually check types.  There
isn't even any need to define `struct bus_dma_tag' anywhere; the
pointer can be cast in sys/arch/x86/x86/bus_dma.c to `struct
x86_bus_dma_tag', for instance (at some risk in type safety, but a
much smaller risk than having void * as the public interface), and it
doesn't even violate strict aliasing rules.

(Typedefs for integer, function, and function pointer types are not
covered by this advice.)

Objections?
From 69dc9658454c8edce695630d2e1bc75db86c43eb Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Tue, 11 Jul 2023 09:57:54 +0000
Subject: [PATCH] style(5): Prohibit new struct typedefs and explain why.

---
 share/misc/style | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/share/misc/style b/share/misc/style
index 1c02dccecf2a..85790024f3f0 100644
--- a/share/misc/style
+++ b/share/misc/style
@@ -130,6 +130,13 @@ int frobnicate(const char *);
 /* Then, there's a blank line, and the user include files. */
 #include "pathnames.h"		/* Local includes in double quotes. */
 
+/*
+ * Forward declarations for struct (and union) tags that don't need
+ * definitions go next.
+ */
+struct dirent;
+struct statfs;
+
 /*
  * Declarations for file-static functions go at the top of the file.
  * Don't associate a name with the parameter types.  I.e. use:
@@ -207,10 +214,17 @@ struct foo {
 };
 struct foo *foohead;		/* Head of global foo list */
 
-/* Make the structure name match the typedef. */
+/*
+ * Do not create typedefs for structs or pointers to structs.  Using a
+ * typedef obscures whether the object is a struct or a pointer to a
+ * struct, and creates unnecessary header file dependencies when only
+ * pointers to them are passed around.
+ */
+#ifdef BAD
 typedef struct BAR {
 	int level;
 } BAR;
+#endif
 
 /* C99 uintN_t is preferred over u_intN_t. */
 uint32_t zero;


Home | Main Index | Thread Index | Old Index