typedef struct S S; の2つの S は名前空間が違うから問題ない。
これはよく言われる事だから確実かと。

で、S* S; の2つの S は名前空間同じなんじゃないかな。
VC++ で通るのは処理系独自の拡張?