I have been able to replicate this technique--using the example linked to godbolt from the blog post--working on clang 7 and failing on clang 8-11 (with the following error)... but it works again on clang 12 ;P. (I am bisecting overnight to see exactly what fixed it; if anyone sees this and is interested, come back to this thread tomorrow for a follow-up.)
note: candidate template ignored: substitution failure [with N = 0]: function 'loophole' with deduced return type cannot be used before it is defined
template <int N, typename T = decltype(loophole(A::tag<N>{}))> T get_type();
~~~~~~~~ ^
commit dd8297b0669f8e69b03ba40171b195b5acf0f963
Author: Richard Smith <richard@metafoo.co.uk>
Date: Fri Oct 30 18:30:56 2020 -0700
PR42513: Fix handling of function definitions lazily instantiated from
friends.
When determining whether a function has a template instantiation
pattern, look for other declarations of that function that were
instantiated from a friend function definition, rather than assuming
that checking for member specialization information on whichever
declaration name lookup found will be sufficient.
clang/include/clang/AST/Decl.h | 14 +++-
clang/lib/AST/Decl.cpp | 61 ++++++++++++--
clang/lib/Sema/SemaDecl.cpp | 84 +++++--------------
clang/lib/Sema/SemaDeclCXX.cpp | 11 +++
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 110 ++++++++++++-------------
clang/test/SemaTemplate/friend.cpp | 7 ++
6 files changed, 159 insertions(+), 128 deletions(-)