https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33911
--- Comment #12 from Jonathan Wakely <redi at gcc dot gnu.org> --- The comment below is from Richard Smith. I don't think we do have the same problem for abi_tag, so Jason must have solved this problem there. -------- I was amazed to discover that clang has the *exact* same bug as gcc: template<typename T> struct S {} __attribute__((deprecated)); S<int> s1; // no warning S<int> s2; // warning, deprecated Moving the attribute earlier makes no difference to either compiler. And... I can tell you exactly why this is happening: when we see the use of S<int>, we instantiate the declaration. That does not instantiate attributes. The use is checked, it's not marked deprecated, so no warning occurs. Then we perform initialization of s1. That triggers the instantiation of the definition and the attribute. But we don't use the name S<int> here; that already happened earlier. Finally, we use S<int> again in the declaration of s2, and now we have both a use and an attribute, so we warn. I'm not entirely sure what the right resolution is here. Maybe some attributes should be instantiated when we instantiate a class template specialization declaration, rather than delaying all of them until we instantiate the definition. I expect that your abi_tag attribute has the same bug, by the way, and if you never trigger the instantiation of the definition of basic_string<T>, then that type won't get an ABI tag. =)