Skip to content

Commit da18e5a

Browse files
premanandraomahesh-attarde
authored andcommitted
[clang] Fix issue with FoldingSet and DependentTemplateSpecialization… (llvm#150559)
…Type PR llvm#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.
1 parent 8d01bdd commit da18e5a

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
238238
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
239239
GeneralTypesLog2InitSize};
240240
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
241-
mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
242-
ASTContext&>
243-
DependentTemplateSpecializationTypes;
241+
mutable llvm::DenseMap<llvm::FoldingSetNodeID,
242+
DependentTemplateSpecializationType *>
243+
DependentTemplateSpecializationTypes;
244244
mutable llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
245245
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
246246
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;

clang/include/clang/AST/Type.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7276,8 +7276,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
72767276
/// Represents a template specialization type whose template cannot be
72777277
/// resolved, e.g.
72787278
/// A<T>::template B<T>
7279-
class DependentTemplateSpecializationType : public TypeWithKeyword,
7280-
public llvm::FoldingSetNode {
7279+
class DependentTemplateSpecializationType : public TypeWithKeyword {
72817280
friend class ASTContext; // ASTContext creates these
72827281

72837282
DependentTemplateStorage Name;

clang/lib/AST/ASTContext.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,6 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
940940
FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize),
941941
DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()),
942942
DependentPackIndexingTypes(this_()), TemplateSpecializationTypes(this_()),
943-
DependentTemplateSpecializationTypes(this_()),
944943
DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()),
945944
DeducedTemplates(this_()), ArrayParameterTypes(this_()),
946945
CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts),
@@ -5979,10 +5978,9 @@ QualType ASTContext::getDependentTemplateSpecializationType(
59795978
llvm::FoldingSetNodeID ID;
59805979
DependentTemplateSpecializationType::Profile(ID, *this, Keyword, Name, Args);
59815980

5982-
void *InsertPos = nullptr;
5983-
if (auto *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(
5984-
ID, InsertPos))
5985-
return QualType(T, 0);
5981+
if (auto const T_iter = DependentTemplateSpecializationTypes.find(ID);
5982+
T_iter != DependentTemplateSpecializationTypes.end())
5983+
return QualType(T_iter->getSecond(), 0);
59865984

59875985
NestedNameSpecifier *NNS = Name.getQualifier();
59885986

@@ -6001,11 +5999,6 @@ QualType ASTContext::getDependentTemplateSpecializationType(
60015999
CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true},
60026000
CanonArgs,
60036001
/*IsCanonical=*/true);
6004-
// Find the insert position again.
6005-
[[maybe_unused]] auto *Nothing =
6006-
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID,
6007-
InsertPos);
6008-
assert(!Nothing && "canonical type broken");
60096002
}
60106003
} else {
60116004
assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword));
@@ -6021,8 +6014,13 @@ QualType ASTContext::getDependentTemplateSpecializationType(
60216014
alignof(DependentTemplateSpecializationType));
60226015
auto *T =
60236016
new (Mem) DependentTemplateSpecializationType(Keyword, Name, Args, Canon);
6017+
#ifndef NDEBUG
6018+
llvm::FoldingSetNodeID InsertedID;
6019+
T->Profile(InsertedID, *this);
6020+
assert(InsertedID == ID && "ID does not match");
6021+
#endif
60246022
Types.push_back(T);
6025-
DependentTemplateSpecializationTypes.InsertNode(T, InsertPos);
6023+
DependentTemplateSpecializationTypes.try_emplace(ID, T);
60266024
return QualType(T, 0);
60276025
}
60286026

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: seq 100 | xargs -Ifoo %clang_cc1 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
// This is a regression test for a non-deterministic stack-overflow.
4+
5+
template <typename C, typename S1, int rbits>
6+
typename C::A Bar(const S1& x, const C& c = C()) {
7+
using T = typename C::A;
8+
T result;
9+
10+
using PreC = typename C::template boop<T::p + rbits>;
11+
using ExactC = typename C::template bap<PreC::p + 2>;
12+
13+
using D = typename ExactC::A;
14+
15+
return result;
16+
}

0 commit comments

Comments
 (0)