Skip to content

Commit b99ff4d

Browse files
authored
Merge pull request #1 from mpusz/P3068-constexpr-exceptions
[clang] Fix non-deterministic infinite recursion... (llvm#118288)
2 parents 46e1e8a + 6b8fe1f commit b99ff4d

File tree

4 files changed

+53
-13
lines changed

4 files changed

+53
-13
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
243243
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
244244
mutable llvm::FoldingSet<DependentUnaryTransformType>
245245
DependentUnaryTransformTypes;
246-
mutable llvm::ContextualFoldingSet<AutoType, ASTContext&> AutoTypes;
246+
// An AutoType can have a dependency on another AutoType via its template
247+
// arguments. Since both dependent and dependency are on the same set,
248+
// we can end up in an infinite recursion when looking for a node if we used
249+
// a `FoldingSet`, since both could end up in the same bucket.
250+
mutable llvm::DenseMap<llvm::FoldingSetNodeID, AutoType *> AutoTypes;
247251
mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
248252
DeducedTemplateSpecializationTypes;
249253
mutable llvm::FoldingSet<AtomicType> AtomicTypes;

clang/include/clang/AST/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6365,7 +6365,7 @@ class DeducedType : public Type {
63656365

63666366
/// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained
63676367
/// by a type-constraint.
6368-
class AutoType : public DeducedType, public llvm::FoldingSetNode {
6368+
class AutoType : public DeducedType {
63696369
friend class ASTContext; // ASTContext creates these
63706370

63716371
ConceptDecl *TypeConstraintConcept;

clang/lib/AST/ASTContext.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,27 @@ enum FloatingRank {
115115
Ibm128Rank
116116
};
117117

118+
template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
119+
static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; }
120+
121+
static FoldingSetNodeID getTombstoneKey() {
122+
FoldingSetNodeID id;
123+
for (size_t i = 0; i < sizeof(id) / sizeof(unsigned); ++i) {
124+
id.AddInteger(std::numeric_limits<unsigned>::max());
125+
}
126+
return id;
127+
}
128+
129+
static unsigned getHashValue(const FoldingSetNodeID &Val) {
130+
return Val.ComputeHash();
131+
}
132+
133+
static bool isEqual(const FoldingSetNodeID &LHS,
134+
const FoldingSetNodeID &RHS) {
135+
return LHS == RHS;
136+
}
137+
};
138+
118139
/// \returns The locations that are relevant when searching for Doc comments
119140
/// related to \p D.
120141
static SmallVector<SourceLocation, 2>
@@ -879,7 +900,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
879900
FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize),
880901
DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()),
881902
TemplateSpecializationTypes(this_()),
882-
DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()),
903+
DependentTemplateSpecializationTypes(this_()),
883904
DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()),
884905
ArrayParameterTypes(this_()), CanonTemplateTemplateParms(this_()),
885906
SourceMgr(SM), LangOpts(LOpts),
@@ -6191,12 +6212,14 @@ QualType ASTContext::getAutoTypeInternal(
61916212
return getAutoDeductType();
61926213

61936214
// Look in the folding set for an existing type.
6194-
void *InsertPos = nullptr;
61956215
llvm::FoldingSetNodeID ID;
6196-
AutoType::Profile(ID, *this, DeducedType, Keyword, IsDependent,
6197-
TypeConstraintConcept, TypeConstraintArgs);
6198-
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
6199-
return QualType(AT, 0);
6216+
bool IsDeducedDependent =
6217+
!DeducedType.isNull() && DeducedType->isDependentType();
6218+
AutoType::Profile(ID, *this, DeducedType, Keyword,
6219+
IsDependent || IsDeducedDependent, TypeConstraintConcept,
6220+
TypeConstraintArgs);
6221+
if (auto const AT_iter = AutoTypes.find(ID); AT_iter != AutoTypes.end())
6222+
return QualType(AT_iter->getSecond(), 0);
62006223

62016224
QualType Canon;
62026225
if (!IsCanon) {
@@ -6211,10 +6234,6 @@ QualType ASTContext::getAutoTypeInternal(
62116234
Canon =
62126235
getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
62136236
CanonicalConcept, CanonicalConceptArgs, true);
6214-
// Find the insert position again.
6215-
[[maybe_unused]] auto *Nothing =
6216-
AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
6217-
assert(!Nothing && "canonical type broken");
62186237
}
62196238
}
62206239
}
@@ -6228,8 +6247,13 @@ QualType ASTContext::getAutoTypeInternal(
62286247
: TypeDependence::None) |
62296248
(IsPack ? TypeDependence::UnexpandedPack : TypeDependence::None),
62306249
Canon, TypeConstraintConcept, TypeConstraintArgs);
6250+
#ifndef NDEBUG
6251+
llvm::FoldingSetNodeID InsertedID;
6252+
AT->Profile(InsertedID, *this);
6253+
assert(InsertedID == ID && "ID does not match");
6254+
#endif
62316255
Types.push_back(AT);
6232-
AutoTypes.InsertNode(AT, InsertPos);
6256+
AutoTypes.try_emplace(ID, AT);
62336257
return QualType(AT, 0);
62346258
}
62356259

clang/test/Parser/gh110231.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: seq 100 | xargs -Ifoo %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
// This is a regression test for a non-deterministic stack-overflow.
4+
5+
template < typename >
6+
concept C1 = true;
7+
8+
template < typename , auto >
9+
concept C2 = true;
10+
11+
template < C1 auto V, C2< V > auto>
12+
struct S;

0 commit comments

Comments
 (0)