Testcase: template<void *> struct X {}; int arr[32]; constexpr void *id(void *p) { return p; } void f(X<id(arr)>) {} // #1 void f(X<id(&arr)>) {} // #2 void f(X<id(&arr[0])>) {} // #3 Here, the three template arguments all represent the same address, but #1 and #3 point to the first array element whereas #2 points to the array itself. But GCC instead says that #1 and #2 are redefinitions, and that #1/#2 and #3 do not conflict -- and mangles #1 and #2 the same, but gives a different mangling to #3. It looks like the array-to-pointer conversion is not being properly handled here.