[clang] fix profiling of template arguments of template and declaration kind

Template arguments of template and declaration kind were being profiled
only by their canonical properties, which would cause incorrect
uniquing of constrained AutoTypes, leading to a crash in some cases.

This exposed some places in CheckTemplateArgumentList where non-canonical
arguments where being pushed into the resulting converted list.

We also throw in some asserts to catch early and explain the crashes.

Note that the fix for the 'declaration' kind is untestable at this point,
because there should be no cases right now in the AST where we try
to unique a non-canonical converted template argument.

This fixes GH55567.

Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>

Differential Revision: https://reviews.llvm.org/D133072
This commit is contained in:
Matheus Izvekov 2022-09-01 01:44:38 +02:00
parent 10e0f3e948
commit acb767f5cd
No known key found for this signature in database
GPG Key ID: 22C080C6DC4E70F8
4 changed files with 25 additions and 23 deletions

View File

@ -5116,7 +5116,9 @@ ASTContext::getDependentTemplateSpecializationType(
CanonArgs);
// Find the insert position again.
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
[[maybe_unused]] auto *Nothing =
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!Nothing && "canonical type broken");
}
void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
@ -5731,7 +5733,9 @@ QualType ASTContext::getAutoTypeInternal(
Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
TypeConstraintConcept, CanonArgs, true);
// Find the insert position again.
AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
[[maybe_unused]] auto *Nothing =
AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!Nothing && "canonical type broken");
}
} else {
Canon = DeducedType.getCanonicalType();

View File

@ -321,26 +321,15 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
case Declaration:
getParamTypeForDecl().Profile(ID);
ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
ID.AddPointer(getAsDecl());
break;
case TemplateExpansion:
ID.AddInteger(TemplateArg.NumExpansions);
LLVM_FALLTHROUGH;
case Template:
case TemplateExpansion: {
TemplateName Template = getAsTemplateOrTemplatePattern();
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
Template.getAsTemplateDecl())) {
ID.AddBoolean(true);
ID.AddInteger(TTP->getDepth());
ID.AddInteger(TTP->getPosition());
ID.AddBoolean(TTP->isParameterPack());
} else {
ID.AddBoolean(false);
ID.AddPointer(Context.getCanonicalTemplateName(Template)
.getAsVoidPointer());
}
getAsTemplateOrTemplatePattern().Profile(ID);
break;
}
case Integral:
getAsIntegral().Profile(ID);

View File

@ -5643,7 +5643,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
if (CheckTemplateTemplateArgument(TempParm, Params, Arg))
return true;
Converted.push_back(Arg.getArgument());
Converted.push_back(
Context.getCanonicalTemplateArgument(Arg.getArgument()));
break;
case TemplateArgument::Expression:
@ -5813,13 +5814,14 @@ bool Sema::CheckTemplateArgumentList(
if (!ArgumentPack.empty()) {
// If we were part way through filling in an expanded parameter pack,
// fall back to just producing individual arguments.
Converted.insert(Converted.end(),
ArgumentPack.begin(), ArgumentPack.end());
for (const TemplateArgument &I : ArgumentPack)
Converted.push_back(Context.getCanonicalTemplateArgument(I));
ArgumentPack.clear();
}
while (ArgIdx < NumArgs) {
Converted.push_back(NewArgs[ArgIdx].getArgument());
Converted.push_back(Context.getCanonicalTemplateArgument(
NewArgs[ArgIdx].getArgument()));
++ArgIdx;
}
@ -5952,7 +5954,8 @@ bool Sema::CheckTemplateArgumentList(
if (ArgIdx < NumArgs && CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument().isPackExpansion())
Converted.push_back(NewArgs[ArgIdx++].getArgument());
Converted.push_back(Context.getCanonicalTemplateArgument(
NewArgs[ArgIdx++].getArgument()));
}
// If we have any leftover arguments, then there were too many arguments.

View File

@ -256,3 +256,9 @@ C auto **j1 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'
C auto **&j2 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
C auto **&&j3 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
}
namespace GH55567 {
template<class, template <class> class> concept C = true;
template <class> struct S {};
void f(C<GH55567::S> auto);
} // namespace GH55567