[clang] 8b7dc4c - [clang] Fix issue with FoldingSet and DependentTemplateSpecialization… (#150559)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 25 12:21:33 PDT 2025
Author: premanandrao
Date: 2025-07-25T15:21:30-04:00
New Revision: 8b7dc4cadb622e2b4a13155bffa5cec8c8fb6b8b
URL: https://github.com/llvm/llvm-project/commit/8b7dc4cadb622e2b4a13155bffa5cec8c8fb6b8b
DIFF: https://github.com/llvm/llvm-project/commit/8b7dc4cadb622e2b4a13155bffa5cec8c8fb6b8b.diff
LOG: [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.
Added:
clang/test/Parser/dep_template_spec_type.cpp
Modified:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/Type.h
clang/lib/AST/ASTContext.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 17cbfb2693308..0273109f8a698 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 764e9d508a25a..98810fbea726e 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -7276,8 +7276,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
/// 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;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6b6275faa215a..16cf114981824 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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);
}
diff --git a/clang/test/Parser/dep_template_spec_type.cpp b/clang/test/Parser/dep_template_spec_type.cpp
new file mode 100644
index 0000000000000..65544bba76d35
--- /dev/null
+++ b/clang/test/Parser/dep_template_spec_type.cpp
@@ -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;
+}
More information about the cfe-commits
mailing list