================
@@ -2697,6 +2697,14 @@ void
ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
+ // A partial specialization whose primary template is invalid cannot be
+ // instantiated. Mark it invalid too so InstantiateClass skips it, the same
+ // way it already skips the invalid primary, instead of later looking for an
+ // instantiated primary that was never created.
+ if (VarTemplateDecl *Primary = D->getSpecializedTemplate();
+ Primary && Primary->isInvalidDecl())
+ D->setInvalidDecl();
----------------
RexTechnology1 wrote:
Researched. The asymmetry is created at parse time, not by
serialization. Declaring the primary cons_from substitutes its default arg
type_identity_t<T>; since the unresolved include already raised a fatal error,
that substitution bails via the hasFatalErrorOccurred() &&
hasUncompilableErrorOccurred() guard, so the primary is marked invalid. The
partial spec has no such default arg, so nothing substitutes and it stays valid.
It doesn't crash without a PCH because that same fatal error suppresses
instantiation of wrapper<int,int> entirely (same guard in
InstantiatingTemplate). Through a PCH the invalid-primary/valid-partial-spec
state is serialized, and the consuming TU has no fatal error, so it
instantiates the class: InstantiateClass skips the invalid primary but still
instantiates the valid partial spec, which looks up the never-created primary
and crashes.
So the fix should keep the primary invalid (the fatal-error guard is
doing its job) and invalidate the partial specs alongside it, so the AST stays
consistent and the asserts hold. Invalidating the partial spec at the point the
primary is invalidated seems cleanest. I'll go that route unless you'd prefer
it handled elsewhere.
https://github.com/llvm/llvm-project/pull/202958
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits