The article is an okay start, but it wasn't written by an expert. It lists some real pitfalls but doesn't provide commonly accepted solutions. Some examples...
multiple lines: wrap in do { } while (0) - can use a multiline macro like a function call, terminated with ; or ({foo; bar;}) - multiple lines evaluate to 'bar'...
Function calls: - in general anything with side effects could be harmful if evaluated more than once. - But possible to write MIN()/MAX() with single evaluation of 'a' and 'b'. #define MAX(a, b) \ ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b;})
And other important things like stringify, variadics, etc...