Skip to content

Conversation

@alejandro-colomar
Copy link
Collaborator

@alejandro-colomar alejandro-colomar commented Dec 2, 2025

typeas() is safer than typeof() in that it requires that the input is a type name.

And it is more generally useful than (T *){} in that it accepts any type; T* doesn't work with array types nor function types.

(This PR also does a few other changes that are needed before we can use typeas(), and which also make these APIs more readable, safer, and more useful.)



Revisions:

v1b
  • Fix commit message. That paragraph was true in the past, but not anymore.
$ git rd 
1:  5413a2a7e = 1:  5413a2a7e lib/: Use a consistent name for macro arguments representing a type name
2:  5de573ad6 ! 2:  c8c014c9b lib/search/, lib/, src/: Add a type parameter to the type-safe macros
    @@ Commit message
         This also makes the code more readable, by having the type explicitly
         stated at call site.
     
    -    There's a slight difference: 'void *' will now be acceptable input.
    -    That shouldn't be an issue.  'void *' is used rarely, so it would be
    -    rare to accidentally pass it where it doesn't belong.  Also, elsewhere
    -    in the language, a void * converts to anything, so making one or two
    -    APIs safe against 'void *' wouldn't change much.
    -
         Signed-off-by: Alejandro Colomar <alx@kernel.org>
     
      ## lib/addgrps.c ##
3:  fe626d787 = 3:  fea19948c lib/search/: Simplify CMP()
4:  948fb0bb7 = 4:  597e54089 lib/search/: Split APIs
5:  ff3ca8afa = 5:  9e44c0575 lib/sizeof.h: typeas(): Add macro
6:  8e3450183 = 6:  d52ae9d7e lib/{alloc,search}/: Use typeas() to add support for arbitrary types
v1c
  • Rebase
$ git rd 
1:  5413a2a7e = 1:  4f95f69bc lib/: Use a consistent name for macro arguments representing a type name
2:  c8c014c9b = 2:  a10273be8 lib/search/, lib/, src/: Add a type parameter to the type-safe macros
3:  fea19948c = 3:  01e68361b lib/search/: Simplify CMP()
4:  597e54089 = 4:  822f7da29 lib/search/: Split APIs
5:  9e44c0575 = 5:  34c1f823a lib/sizeof.h: typeas(): Add macro
6:  d52ae9d7e = 6:  9dd442b84 lib/{alloc,search}/: Use typeas() to add support for arbitrary types

hallyn added a commit to hallyn/shadow that referenced this pull request Dec 5, 2025
I just did a 'make dist', then committed the updates to the po and
shadow.pot files.

Closes shadow-maint#1395

Signed-off-by: Serge Hallyn <serge@hallyn.com>
@hallyn hallyn mentioned this pull request Dec 5, 2025
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This simplifies the implementation, allowing us to use _Generic(3) to
replace _Static_assert(3), is_same_type(), and local variables.

Local variables in macros can cause issues when nesting such macros.

This also makes the code more readable, by having the type explicitly
stated at call site.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Have xxx_T() macros that only add type safety to the function they wrap.

Have XXX() macros that do more magic; in this case, they deduce the
comparison function that is appropriate for the type.

This will allow using the xxx_T() macros in more complex cases, where
the function can't be deduced just from the type.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
This macro is like typeof(), but requires that the input is a type name.

This macro is useful because it parenthesizes the type name, which
allows one to create pointers to arbitrary types.  The following code
works for simple types:

	T  x;
	T  *p;

For example, that would work fine for 'int':

	int  x;
	int  *p;

However, that wouldn't work for types such as 'int[3]':

	int[3]  x;
	int[3]  *p;

But if we do instead

	typeas(T)  x;
	typeas(T)  *p;

now we can use 'int[3]' just fine:

	typeof((int[3]){})  x;
	typeof((int[3]){})  *p;

To understand this, we create a compound literal of type int[3], with
default values (zero, zero, zero), then get it's type, which is
obviously int[3].  And then we use that to declare a variable x of that
type, and a pointer p, which has type 'int(*)[3]'.

This would also work with something simpler.  One could use typeof(T)
directly:

	typeof(T)  x;
	typeof(T)  *p;

However, typeof() doesn't require that the input is a type; it accepts
arbitrary input.  The following is valid C:

	typeof(42)  x;

For our macro MALLOC(), where we want the second argument to be a type
name, we want to require that the argument is a type name.  For that, we
need to use typeas().

Reported-by: Alejandro Colomar <alx@kernel.org>
Suggested-by: Thiago Adams <thiago.adams@gmail.com>
Suggested-by: Martin Uecker <uecker@tugraz.at>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
@ikerexxe
Copy link
Collaborator

ikerexxe commented Dec 5, 2025

Reopening since this was incorrectly closed

@ikerexxe ikerexxe reopened this Dec 5, 2025
@hallyn
Copy link
Member

hallyn commented Dec 5, 2025

Holy cow. Github closed the issue that was in the Description? I didn't even
think to manually update that...

@alejandro-colomar
Copy link
Collaborator Author

Holy cow. Github closed the issue that was in the Description? I didn't even think to manually update that...

It's even more funny. I've heard people had closed other projects' issues by having a Closes tag that linked to another repo. Github is quite funny.

@hallyn
Copy link
Member

hallyn commented Dec 5, 2025 via email

@hallyn hallyn merged commit 2f18e7c into shadow-maint:master Dec 5, 2025
20 checks passed
@alejandro-colomar alejandro-colomar deleted the typeas branch December 6, 2025 18:06
@alejandro-colomar alejandro-colomar self-assigned this Dec 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants