[jwalden@wheres-wally reduction]$ cat minimal.cpp template <int T> struct S { static void f() { typedef int q[1]; typedef int q[T]; } }; [jwalden@wheres-wally reduction]$ ~/Programs/gcc-build/prefixdir/bin/g++ minimal.cpp minimal.cpp: In static member function ‘static void S<T>::f()’: minimal.cpp:7:20: error: conflicting declaration ‘typedef int q [T]’ minimal.cpp:6:17: error: ‘q’ has a previous declaration as ‘typedef int q [1]’ [jwalden@wheres-wally reduction]$ (cd ~/Programs/gcc-build/trunk/ && svn info) Path: . URL: svn://gcc.gnu.org/svn/gcc/trunk Repository Root: svn://gcc.gnu.org/svn/gcc Repository UUID: 138bc75d-0d04-0410-961f-82ee72b054a4 Revision: 182676 Node Kind: directory Schedule: normal Last Changed Author: torvald Last Changed Rev: 182676 Last Changed Date: 2011-12-23 20:42:48 -0500 (Fri, 23 Dec 2011) If S is only instantiated with T = 1, the second typedef redefines q to the same type as the first, so it should be allowed. I happened to hit this while attempting to roll my own static_assert macro. (The C++11 static_assert isn't an option for various reasons.)
For what it's worth, clang also has this bug. See <http://llvm.org/bugs/show_bug.cgi?id=11630>, which is this bug plus an extra testcase that GCC handles correctly.
ICC is fine instead, indeed in my experience in quite a few cases tries to do less at definition time. Delaying the check shouldn't be too hard.
I suppose tweaking comp_array_types should do it...
Another testcase: template <typename T, typename U> struct S { static void f() { typedef T q; typedef U q; } };