Skip to content

Commit 8091dce

Browse files
authored
Revert "[clang] separate recursive instantiation check from CodeSynthesisContext" (#164174)
Reverts #162224 Broke buildbot here: #162224 (comment)
1 parent e6b0be3 commit 8091dce

File tree

5 files changed

+62
-142
lines changed

5 files changed

+62
-142
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13007,37 +13007,6 @@ class Sema final : public SemaBase {
1300713007
/// default arguments of its methods have been parsed.
1300813008
UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations;
1300913009

13010-
using InstantiatingSpecializationsKey = llvm::PointerIntPair<Decl *, 2>;
13011-
13012-
struct RecursiveInstGuard {
13013-
enum class Kind {
13014-
Template,
13015-
DefaultArgument,
13016-
ExceptionSpec,
13017-
};
13018-
13019-
RecursiveInstGuard(Sema &S, Decl *D, Kind Kind)
13020-
: S(S), Key(D->getCanonicalDecl(), unsigned(Kind)) {
13021-
auto [_, Created] = S.InstantiatingSpecializations.insert(Key);
13022-
if (!Created)
13023-
Key = {};
13024-
}
13025-
13026-
~RecursiveInstGuard() {
13027-
if (Key.getOpaqueValue()) {
13028-
[[maybe_unused]] bool Erased =
13029-
S.InstantiatingSpecializations.erase(Key);
13030-
assert(Erased);
13031-
}
13032-
}
13033-
13034-
operator bool() const { return Key.getOpaqueValue() == nullptr; }
13035-
13036-
private:
13037-
Sema &S;
13038-
Sema::InstantiatingSpecializationsKey Key;
13039-
};
13040-
1304113010
/// A context in which code is being synthesized (where a source location
1304213011
/// alone is not sufficient to identify the context). This covers template
1304313012
/// instantiation and various forms of implicitly-generated functions.
@@ -13399,9 +13368,14 @@ class Sema final : public SemaBase {
1339913368
/// recursive template instantiations.
1340013369
bool isInvalid() const { return Invalid; }
1340113370

13371+
/// Determine whether we are already instantiating this
13372+
/// specialization in some surrounding active instantiation.
13373+
bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
13374+
1340213375
private:
1340313376
Sema &SemaRef;
1340413377
bool Invalid;
13378+
bool AlreadyInstantiating;
1340513379

1340613380
InstantiatingTemplate(Sema &SemaRef,
1340713381
CodeSynthesisContext::SynthesisKind Kind,
@@ -13531,7 +13505,7 @@ class Sema final : public SemaBase {
1353113505
SmallVector<CodeSynthesisContext, 16> CodeSynthesisContexts;
1353213506

1353313507
/// Specializations whose definitions are currently being instantiated.
13534-
llvm::DenseSet<InstantiatingSpecializationsKey> InstantiatingSpecializations;
13508+
llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations;
1353513509

1353613510
/// Non-dependent types used in templates that have already been instantiated
1353713511
/// by some template instantiation.
@@ -13806,14 +13780,6 @@ class Sema final : public SemaBase {
1380613780
const MultiLevelTemplateArgumentList &TemplateArgs,
1380713781
TemplateSpecializationKind TSK, bool Complain = true);
1380813782

13809-
private:
13810-
bool InstantiateClassImpl(SourceLocation PointOfInstantiation,
13811-
CXXRecordDecl *Instantiation,
13812-
CXXRecordDecl *Pattern,
13813-
const MultiLevelTemplateArgumentList &TemplateArgs,
13814-
TemplateSpecializationKind TSK, bool Complain);
13815-
13816-
public:
1381713783
/// Instantiate the definition of an enum from a given pattern.
1381813784
///
1381913785
/// \param PointOfInstantiation The point of instantiation within the

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 38 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -639,8 +639,15 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
639639
}
640640

641641
Invalid = SemaRef.pushCodeSynthesisContext(Inst);
642-
if (!Invalid)
642+
if (!Invalid) {
643+
AlreadyInstantiating =
644+
!Inst.Entity
645+
? false
646+
: !SemaRef.InstantiatingSpecializations
647+
.insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
648+
.second;
643649
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
650+
}
644651
}
645652

646653
Sema::InstantiatingTemplate::InstantiatingTemplate(
@@ -895,6 +902,13 @@ void Sema::popCodeSynthesisContext() {
895902

896903
void Sema::InstantiatingTemplate::Clear() {
897904
if (!Invalid) {
905+
if (!AlreadyInstantiating) {
906+
auto &Active = SemaRef.CodeSynthesisContexts.back();
907+
if (Active.Entity)
908+
SemaRef.InstantiatingSpecializations.erase(
909+
{Active.Entity->getCanonicalDecl(), Active.Kind});
910+
}
911+
898912
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
899913
SemaRef.CodeSynthesisContexts.back());
900914

@@ -3298,20 +3312,17 @@ bool Sema::SubstDefaultArgument(
32983312
FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
32993313
Expr *PatternExpr = Param->getUninstantiatedDefaultArg();
33003314

3301-
RecursiveInstGuard AlreadyInstantiating(
3302-
*this, Param, RecursiveInstGuard::Kind::DefaultArgument);
3303-
if (AlreadyInstantiating) {
3304-
Param->setInvalidDecl();
3305-
return Diag(Param->getBeginLoc(), diag::err_recursive_default_argument)
3306-
<< FD << PatternExpr->getSourceRange();
3307-
}
3308-
33093315
EnterExpressionEvaluationContext EvalContext(
33103316
*this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
33113317

33123318
InstantiatingTemplate Inst(*this, Loc, Param, TemplateArgs.getInnermost());
33133319
if (Inst.isInvalid())
33143320
return true;
3321+
if (Inst.isAlreadyInstantiating()) {
3322+
Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
3323+
Param->setInvalidDecl();
3324+
return true;
3325+
}
33153326

33163327
ExprResult Result;
33173328
// C++ [dcl.fct.default]p5:
@@ -3543,26 +3554,12 @@ namespace clang {
35433554
}
35443555
}
35453556

3546-
bool Sema::InstantiateClass(SourceLocation PointOfInstantiation,
3547-
CXXRecordDecl *Instantiation,
3548-
CXXRecordDecl *Pattern,
3549-
const MultiLevelTemplateArgumentList &TemplateArgs,
3550-
TemplateSpecializationKind TSK, bool Complain) {
3551-
#ifndef NDEBUG
3552-
RecursiveInstGuard AlreadyInstantiating(*this, Instantiation,
3553-
RecursiveInstGuard::Kind::Template);
3554-
assert(!AlreadyInstantiating && "should have been caught by caller");
3555-
#endif
3556-
3557-
return InstantiateClassImpl(PointOfInstantiation, Instantiation, Pattern,
3558-
TemplateArgs, TSK, Complain);
3559-
}
3560-
3561-
bool Sema::InstantiateClassImpl(
3562-
SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation,
3563-
CXXRecordDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs,
3564-
TemplateSpecializationKind TSK, bool Complain) {
3565-
3557+
bool
3558+
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
3559+
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
3560+
const MultiLevelTemplateArgumentList &TemplateArgs,
3561+
TemplateSpecializationKind TSK,
3562+
bool Complain) {
35663563
CXXRecordDecl *PatternDef
35673564
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
35683565
if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
@@ -3599,6 +3596,7 @@ bool Sema::InstantiateClassImpl(
35993596
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
36003597
if (Inst.isInvalid())
36013598
return true;
3599+
assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
36023600
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
36033601
"instantiating class definition");
36043602

@@ -3810,12 +3808,6 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
38103808
EnumDecl *Instantiation, EnumDecl *Pattern,
38113809
const MultiLevelTemplateArgumentList &TemplateArgs,
38123810
TemplateSpecializationKind TSK) {
3813-
#ifndef NDEBUG
3814-
RecursiveInstGuard AlreadyInstantiating(*this, Instantiation,
3815-
RecursiveInstGuard::Kind::Template);
3816-
assert(!AlreadyInstantiating && "should have been caught by caller");
3817-
#endif
3818-
38193811
EnumDecl *PatternDef = Pattern->getDefinition();
38203812
if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
38213813
Instantiation->getInstantiatedFromMemberEnum(),
@@ -3833,6 +3825,8 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
38333825
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
38343826
if (Inst.isInvalid())
38353827
return true;
3828+
if (Inst.isAlreadyInstantiating())
3829+
return false;
38363830
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
38373831
"instantiating enum definition");
38383832

@@ -3871,14 +3865,6 @@ bool Sema::InstantiateInClassInitializer(
38713865
Pattern->getInClassInitStyle() &&
38723866
"pattern and instantiation disagree about init style");
38733867

3874-
RecursiveInstGuard AlreadyInstantiating(*this, Instantiation,
3875-
RecursiveInstGuard::Kind::Template);
3876-
if (AlreadyInstantiating)
3877-
// Error out if we hit an instantiation cycle for this initializer.
3878-
return Diag(PointOfInstantiation,
3879-
diag::err_default_member_initializer_cycle)
3880-
<< Instantiation;
3881-
38823868
// Error out if we haven't parsed the initializer of the pattern yet because
38833869
// we are waiting for the closing brace of the outer class.
38843870
Expr *OldInit = Pattern->getInClassInitializer();
@@ -3897,6 +3883,12 @@ bool Sema::InstantiateInClassInitializer(
38973883
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
38983884
if (Inst.isInvalid())
38993885
return true;
3886+
if (Inst.isAlreadyInstantiating()) {
3887+
// Error out if we hit an instantiation cycle for this initializer.
3888+
Diag(PointOfInstantiation, diag::err_default_member_initializer_cycle)
3889+
<< Instantiation;
3890+
return true;
3891+
}
39003892
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
39013893
"instantiating default member init");
39023894

@@ -3980,6 +3972,8 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
39803972
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
39813973
if (Inst.isInvalid())
39823974
return {/*Invalid=*/true};
3975+
if (Inst.isAlreadyInstantiating())
3976+
return {/*Invalid=*/false};
39833977

39843978
llvm::PointerUnion<ClassTemplateDecl *,
39853979
ClassTemplatePartialSpecializationDecl *>
@@ -4142,11 +4136,6 @@ bool Sema::InstantiateClassTemplateSpecialization(
41424136
if (ClassTemplateSpec->isInvalidDecl())
41434137
return true;
41444138

4145-
Sema::RecursiveInstGuard AlreadyInstantiating(
4146-
*this, ClassTemplateSpec, Sema::RecursiveInstGuard::Kind::Template);
4147-
if (AlreadyInstantiating)
4148-
return false;
4149-
41504139
bool HadAvaibilityWarning =
41514140
ShouldDiagnoseAvailabilityOfDecl(ClassTemplateSpec, nullptr, nullptr)
41524141
.first != AR_Available;
@@ -4159,7 +4148,7 @@ bool Sema::InstantiateClassTemplateSpecialization(
41594148
if (!Pattern.isUsable())
41604149
return Pattern.isInvalid();
41614150

4162-
bool Err = InstantiateClassImpl(
4151+
bool Err = InstantiateClass(
41634152
PointOfInstantiation, ClassTemplateSpec, Pattern.get(),
41644153
getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain);
41654154

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5312,16 +5312,6 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
53125312
if (Proto->getExceptionSpecType() != EST_Uninstantiated)
53135313
return;
53145314

5315-
RecursiveInstGuard AlreadyInstantiating(
5316-
*this, Decl, RecursiveInstGuard::Kind::ExceptionSpec);
5317-
if (AlreadyInstantiating) {
5318-
// This exception specification indirectly depends on itself. Reject.
5319-
// FIXME: Corresponding rule in the standard?
5320-
Diag(PointOfInstantiation, diag::err_exception_spec_cycle) << Decl;
5321-
UpdateExceptionSpec(Decl, EST_None);
5322-
return;
5323-
}
5324-
53255315
InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
53265316
InstantiatingTemplate::ExceptionSpecification());
53275317
if (Inst.isInvalid()) {
@@ -5330,6 +5320,13 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
53305320
UpdateExceptionSpec(Decl, EST_None);
53315321
return;
53325322
}
5323+
if (Inst.isAlreadyInstantiating()) {
5324+
// This exception specification indirectly depends on itself. Reject.
5325+
// FIXME: Corresponding rule in the standard?
5326+
Diag(PointOfInstantiation, diag::err_exception_spec_cycle) << Decl;
5327+
UpdateExceptionSpec(Decl, EST_None);
5328+
return;
5329+
}
53335330

53345331
// Enter the scope of this instantiation. We don't use
53355332
// PushDeclContext because we don't have a scope.
@@ -5389,6 +5386,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
53895386
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
53905387
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
53915388
if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) {
5389+
SemaRef.InstantiatingSpecializations.erase(
5390+
{ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind});
53925391
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
53935392
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
53945393
ActiveInst.Entity = New;
@@ -5546,12 +5545,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
55465545
Function = const_cast<FunctionDecl*>(ExistingDefn);
55475546
}
55485547

5549-
#ifndef NDEBUG
5550-
RecursiveInstGuard AlreadyInstantiating(*this, Function,
5551-
RecursiveInstGuard::Kind::Template);
5552-
assert(!AlreadyInstantiating && "should have been caught by caller");
5553-
#endif
5554-
55555548
// Find the function body that we'll be substituting.
55565549
const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
55575550
assert(PatternDecl && "instantiating a non-template");
@@ -5691,7 +5684,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
56915684
}
56925685

56935686
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
5694-
if (Inst.isInvalid())
5687+
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
56955688
return;
56965689
PrettyDeclStackTraceEntry CrashInfo(Context, Function, SourceLocation(),
56975690
"instantiating function definition");
@@ -6260,11 +6253,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
62606253
if (TSK == TSK_ExplicitSpecialization)
62616254
return;
62626255

6263-
RecursiveInstGuard AlreadyInstantiating(*this, Var,
6264-
RecursiveInstGuard::Kind::Template);
6265-
if (AlreadyInstantiating)
6266-
return;
6267-
62686256
// Find the pattern and the arguments to substitute into it.
62696257
VarDecl *PatternDecl = Var->getTemplateInstantiationPattern();
62706258
assert(PatternDecl && "no pattern for templated variable");
@@ -6288,7 +6276,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
62886276
// FIXME: Factor out the duplicated instantiation context setup/tear down
62896277
// code here.
62906278
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
6291-
if (Inst.isInvalid())
6279+
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
62926280
return;
62936281
PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
62946282
"instantiating variable initializer");
@@ -6392,7 +6380,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
63926380
}
63936381

63946382
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
6395-
if (Inst.isInvalid())
6383+
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
63966384
return;
63976385
PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
63986386
"instantiating variable definition");

clang/test/SemaCXX/libstdcxx_pair_swap_hack.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@ namespace sad {
8282
template<typename T> void swap(T &, T &);
8383

8484
template<typename A, typename B> struct CLASS {
85-
void swap(CLASS &other) // expected-note {{declared here}}
86-
noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}}
87-
// expected-error@-1{{uses itself}}
85+
void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}}
86+
// expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}}
8887
};
8988

9089
CLASS<int, int> pi;
9190

92-
static_assert(!noexcept(pi.swap(pi)), ""); // expected-note {{in instantiation of exception specification for 'swap'}}
91+
static_assert(!noexcept(pi.swap(pi)), ""); // expected-note 2{{in instantiation of exception specification for 'swap'}}
9392
}
9493

9594
#endif

0 commit comments

Comments
 (0)