Existem restrições ao padrão C que permitem que as funções sejam implementadas como macros?

Muitas vezes, além de fornecer uma declaração de função, os cabeçalhos padrão C podem fornecer uma "macro de mascaramento" para tornar as coisas mais rápidas. Por exemplo, se eu incluirctype.h, o arquivo de cabeçalho irá declarar

int isdigit(int c);

Mas também pode mascarar a declaração com uma macro. Eu acredito que este é um portátilisdigit macro de acordo com o padrão C:

#define isdigit(c) ((c) >= '0' && (c) <= '9')

Naturalmente, essa macro também é perigosa porque introduz um comportamento indefinido se você fizer isso enquanto a macro é definida:

int c = 'A';
printf("%d\n", isdigit(c++));

Para evitar o UB neste caso hipotético, tenho que cercar o nome da função com parens:(isdigit)(c++). Então, minha pergunta é: há alguma restrição em que tipo de macros de mascaramento um cabeçalho padrão pode definir? Eles garantem que não causarão comportamentos indefinidos se uma expressão de argumento tiver efeitos colaterais, ou se eles tecnicamente puderem ter um comportamento estranho, como vemos acima? Onde estão os limites?