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; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits