[clang] Fix issue with FoldingSet and DependentTemplateSpecialization… (#150559)
…Type PR #118288 fixed a re-entrancy issue with the usage of `FoldingSet` and `AutoType`. The following test case (reduced with `creduce` by @Fznamznon): ``` template <typename C, typename S1, int rbits> typename C::A Bar(const S1& x, const C& c = C()) { using T = typename C::A; T result; using PreC = typename C::template boop<T::p + rbits>; using ExactC = typename C::template bap<PreC::p + 2>; using D = typename ExactC::A; return result; } ``` shows a similar non-deterministic recursion with the use of `FoldingSet` but with `DependentTemplateSepcializationType`. A nearly identical fix is needed here too.
This commit is contained in:
parent
400ce1a3d3
commit
8b7dc4cadb
@ -238,9 +238,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
|
||||
GeneralTypesLog2InitSize};
|
||||
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
|
||||
mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
|
||||
ASTContext&>
|
||||
DependentTemplateSpecializationTypes;
|
||||
mutable llvm::DenseMap<llvm::FoldingSetNodeID,
|
||||
DependentTemplateSpecializationType *>
|
||||
DependentTemplateSpecializationTypes;
|
||||
mutable llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
|
||||
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
|
||||
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
|
||||
|
@ -7276,8 +7276,7 @@ public:
|
||||
/// Represents a template specialization type whose template cannot be
|
||||
/// resolved, e.g.
|
||||
/// A<T>::template B<T>
|
||||
class DependentTemplateSpecializationType : public TypeWithKeyword,
|
||||
public llvm::FoldingSetNode {
|
||||
class DependentTemplateSpecializationType : public TypeWithKeyword {
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
|
||||
DependentTemplateStorage Name;
|
||||
|
@ -940,7 +940,6 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
|
||||
FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize),
|
||||
DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()),
|
||||
DependentPackIndexingTypes(this_()), TemplateSpecializationTypes(this_()),
|
||||
DependentTemplateSpecializationTypes(this_()),
|
||||
DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()),
|
||||
DeducedTemplates(this_()), ArrayParameterTypes(this_()),
|
||||
CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts),
|
||||
@ -5979,10 +5978,9 @@ QualType ASTContext::getDependentTemplateSpecializationType(
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentTemplateSpecializationType::Profile(ID, *this, Keyword, Name, Args);
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
if (auto *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(
|
||||
ID, InsertPos))
|
||||
return QualType(T, 0);
|
||||
if (auto const T_iter = DependentTemplateSpecializationTypes.find(ID);
|
||||
T_iter != DependentTemplateSpecializationTypes.end())
|
||||
return QualType(T_iter->getSecond(), 0);
|
||||
|
||||
NestedNameSpecifier *NNS = Name.getQualifier();
|
||||
|
||||
@ -6001,11 +5999,6 @@ QualType ASTContext::getDependentTemplateSpecializationType(
|
||||
CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true},
|
||||
CanonArgs,
|
||||
/*IsCanonical=*/true);
|
||||
// Find the insert position again.
|
||||
[[maybe_unused]] auto *Nothing =
|
||||
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID,
|
||||
InsertPos);
|
||||
assert(!Nothing && "canonical type broken");
|
||||
}
|
||||
} else {
|
||||
assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword));
|
||||
@ -6021,8 +6014,13 @@ QualType ASTContext::getDependentTemplateSpecializationType(
|
||||
alignof(DependentTemplateSpecializationType));
|
||||
auto *T =
|
||||
new (Mem) DependentTemplateSpecializationType(Keyword, Name, Args, Canon);
|
||||
#ifndef NDEBUG
|
||||
llvm::FoldingSetNodeID InsertedID;
|
||||
T->Profile(InsertedID, *this);
|
||||
assert(InsertedID == ID && "ID does not match");
|
||||
#endif
|
||||
Types.push_back(T);
|
||||
DependentTemplateSpecializationTypes.InsertNode(T, InsertPos);
|
||||
DependentTemplateSpecializationTypes.try_emplace(ID, T);
|
||||
return QualType(T, 0);
|
||||
}
|
||||
|
||||
|
16
clang/test/Parser/dep_template_spec_type.cpp
Normal file
16
clang/test/Parser/dep_template_spec_type.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// RUN: seq 100 | xargs -Ifoo %clang_cc1 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
// This is a regression test for a non-deterministic stack-overflow.
|
||||
|
||||
template <typename C, typename S1, int rbits>
|
||||
typename C::A Bar(const S1& x, const C& c = C()) {
|
||||
using T = typename C::A;
|
||||
T result;
|
||||
|
||||
using PreC = typename C::template boop<T::p + rbits>;
|
||||
using ExactC = typename C::template bap<PreC::p + 2>;
|
||||
|
||||
using D = typename ExactC::A;
|
||||
|
||||
return result;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user