Partial specialization after implicit/explicit template instantiation.

Hi all,

I'm sorry to partially duplicate this post from cfe-commits,
but probably that was wrong place to ask this question.

I recently found that Clang doesn't behave similiar as GCC
in case of partial specialization ater implicit or explicit
specialization of class template. GCC gives diagnostic like

"error: partial specialization of 'A<const T*>' after instantiation of
'A<const char*>'"

while Clang just ignores it and instantiates previously declared
templates by lookup. I looked over the Standard and found:

C++ [temp.class.spec]p1:
"A partial specialization shall be declared before the first
use of a class template specialization that would make use of
the partial specialization as the result of an implicit or explicit
instantiation in every translation unit in which such a use occurs;
no diagnostic is required."

So it seems to me that GCC has a right behaviour for this. I also
submitted a bug http://llvm.org/bugs/show_bug.cgi?id=21156 and
wrote a patch, which I attached to bug. I just was wondering,
does this patch really make sense? I'm newbie in Clang and my code
may be incorrect but I would be extremely thankful if someone
could review it (if it really makes sense).

I'm also not sure, probably Clang has its own politics for this.
If so, what is a reason of such behavior?

Hi Anton, and welcome! Richard (CCed) will tell us if this is indeed a clang bug. I can give you some general comments in the meantime:

Patches that need review are sent to cfe-commits or attached to Phabricator (code review tool we use). They mostly go unnoticed in bugzilla.

Please use clang-format to format the code.

We’ll need a test for this. It’s also a good practice to provide a code sample that demonstrates the issue when reporting a bug (this is what usually ends up being your test). Have a look at existing test infrastructure, namely -verify switch and expected-error “annotation”. The test should probably go to test/SemaTemplate/temp_class_spec.cpp

auto const ThisPartialSpec should be const auto *ThisPartialSpec

auto InstantiatedFrom should be auto *InstantiatedFrom

Other than that your code looks good, but I can’t really comment on the logic.

Nikola

Hi Anton, and welcome! Richard (CCed) will tell us if this is indeed a
clang bug.

It would definitely be good to diagnose this case.

In addition to Nikola's comments:

+ if (!DeduceTemplateArguments(ThisPartialSpec,
+ S->getTemplateArgs(),
+ Info) &&
+ S->getSpecializationKind() != TSK_ExplicitSpecialization) {

Please reverse the order of these two checks; the second check is vastly
cheaper than the first one. You should also skip specializations that have
not been instantiated here; this is fine:

  template<typename T> struct S;
  S<int*> *p;
  template<typename T> struct S<T*> {};

... because the second line does not trigger the instantiation of S<int*>.

+ return true;

We should carry on and produce the declaration in this case.

I can give you some general comments in the meantime:

Thank you, guys.

I just added patch for review in Phabricator and will try to write test later.