It is provably impossible to change a macro in any way without rewriting it from scratch. In the standard 6.10.3, you have:
An identifier currently defined as an object-like macro shall not be redefined by another
#define preprocessing directive unless the second definition is an object-like macro
definition and the two replacement lists are identical. Likewise, an identifier currently
defined as a function-like macro shall not be redefined by another #define
preprocessing directive unless the second definition is a function-like macro definition
that has the same number and spelling of parameters, and the two replacement lists are
identical.
So, you either have that a macro will expand exactly according to its definition, or else you need to #undef it. If you #undef it, to redefine it you need to write it from scratch. The old definition will not be available at that point, even to help in defining the new version.
You can't "reach" the old definition through any sort of intermediary because the preprocessor acts on definitions active at the point of the invocation, not at the points where the macros involved were defined. So, if you define temp(x) like you did, it expands in the context of your new definition of mat, not the old one (not to mention that there needed to be an undef between the two definitions of mat(x) and the anti-recursion rules will stop macro expansion at mat(x) anyway).
In short, there is absolutely no way, according to the standard, to redefine a macro in a way that is based on its original definition. This is mathematically provable from the standard.
Is there any reason you don't just modify the original definitions of the macros to deal with each type you are interested in? Or use some modification of the naming scheme to indicate your own version (like append _o to indicate a macro that deals with more types but ultimately relies on the corresponding macro)? Or, better yet, modify the names of the original macros, so that you can redefine them but have the originals available?
Edit
Going by the comment below, here is one way to maybe achieve some of what OP desires. Its not perfect, but the C preprocessor does have limitations. Here is an example that converts objects into a modifiable string.
write this in the header where you define the macro in the first place:
#define get_length(x) get_length_help(x)
#define get_length_help(x) sizeof(#x)
#define to_string(x) _Generic( (x), \
int: sprintf( (char[get_length(INT_MAX)]){0}, "%d", x ), \
char: sprintf( (char[2]){0}, "%c", x ), \
to_string_1,
to_string_2,
// ...
)
// make sure all extra spots expand to nothing until used
#define to_string_1
#define to_string_2
// ...
// macro to test if an extension slot is used
// requires that extensions do not begin with '('
#define used(...) used_help2( (used_help1 __VA_ARGS__ ()), 0, 1, )
#define used_help1() ),(
#define used_help2(_1,_2,_3,...) _3
Write this in foo.c
typedef struct {
int x,
int y
} plot_point
// this part is important, all generic selections must be valid expressions
// for the other types as well
#define safe_plot_point(x) _Generic( x, plot_point: x, default: (plot_point){0,0} )
// this could define a comma delimited list of selection statements as well
#define to_string_foo \
plot_point: sprintf( \
(char[get_length((INT_MAX,INT_MAX))]){0}, \
"(%i,%i)", \
safe_plot_point(x).x, safe_plot_point(x).y \
)
// this is the only real complication for the user
#if used(to_string_1)
#undef to_string_1
#define to_string_1 to_string_foo
#elif used(to_string_2)
#undef to_string_2
#define to_string_2 to_string_foo
// ...
#else
_Static_assert( 0, "no to_string_#'s left!" );
#endif
So, you can get some degree of modifiability. Note that no macro could just perform the modification, as it is undefined behavior for a macro to expand into another preprocessing directives, and as stated above preprocessing directives are the only way to change the behavior of a macro. Macro invocations are simply blind to other invocations, they only see other definitions.
Also note that you could define any number of extension slots. You can define more slots than a given file checks for, and only add the extra lines (the #if's), if they are needed.