Skip to content

Commit d4ab1ec

Browse files
committed
[clang] Allow delayed function instantiation at TU end if initial instantiation fails
1 parent ade0750 commit d4ab1ec

File tree

5 files changed

+42
-12
lines changed

5 files changed

+42
-12
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,8 @@ class Sema final : public SemaBase {
865865
/// checks.
866866
const TranslationUnitKind TUKind;
867867

868+
bool AtEndOfTU = false;
869+
868870
/// Translation Unit Scope - useful to Objective-C actions that need
869871
/// to lookup file scope declarations in the "ordinary" C decl namespace.
870872
/// For example, user-defined classes, built-in "id" type, etc.
@@ -13523,7 +13525,9 @@ class Sema final : public SemaBase {
1352313525
S.PendingLocalImplicitInstantiations);
1352413526
}
1352513527

13526-
void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
13528+
void perform() {
13529+
S.PerformPendingInstantiations(/*LocalOnly=*/true);
13530+
}
1352713531

1352813532
~LocalEagerInstantiationScope() {
1352913533
assert(S.PendingLocalImplicitInstantiations.empty() &&
@@ -13571,7 +13575,7 @@ class Sema final : public SemaBase {
1357113575
void perform() {
1357213576
if (Enabled) {
1357313577
S.DefineUsedVTables();
13574-
S.PerformPendingInstantiations();
13578+
S.PerformPendingInstantiations(false);
1357513579
}
1357613580
}
1357713581

@@ -13682,8 +13686,7 @@ class Sema final : public SemaBase {
1368213686
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
1368313687
FunctionDecl *Function,
1368413688
bool Recursive = false,
13685-
bool DefinitionRequired = false,
13686-
bool AtEndOfTU = false);
13689+
bool DefinitionRequired = false);
1368713690
VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
1368813691
VarTemplateDecl *VarTemplate, VarDecl *FromVar,
1368913692
const TemplateArgumentList *PartialSpecArgs,

clang/lib/Sema/Sema.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,7 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
11381138

11391139
{
11401140
llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
1141-
PerformPendingInstantiations();
1141+
PerformPendingInstantiations(/*LocalOnly=*/false);
11421142
}
11431143

11441144
emitDeferredDiags();
@@ -1160,6 +1160,7 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
11601160
void Sema::ActOnEndOfTranslationUnit() {
11611161
assert(DelayedDiagnostics.getCurrentPool() == nullptr
11621162
&& "reached end of translation unit with a pool attached?");
1163+
AtEndOfTU = true;
11631164

11641165
// If code completion is enabled, don't perform any end-of-translation-unit
11651166
// work.

clang/lib/Sema/SemaExpr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21054,8 +21054,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
2105421054
// precedes this use.
2105521055
InstantiateFunctionDefinition(E->getBeginLoc(), FD,
2105621056
/*Recursive=*/false,
21057-
/*DefinitionRequired=*/true,
21058-
/*AtEndOfTU=*/false);
21057+
/*DefinitionRequired=*/true);
2105921058
}
2106021059
// Produce a properly-typed reference to the function.
2106121060
CXXScopeSpec SS;

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ static void instantiateOMPDeclareVariantAttr(
513513
return;
514514
S.InstantiateFunctionDefinition(
515515
New->getLocation(), SubstFD, /* Recursive */ true,
516-
/* DefinitionRequired */ false, /* AtEndOfTU */ false);
516+
/* DefinitionRequired */ false);
517517
SubstFD->setInstantiationIsPending(!SubstFD->isDefined());
518518
E = DeclRefExpr::Create(S.Context, NestedNameSpecifierLoc(),
519519
SourceLocation(), SubstFD,
@@ -4932,8 +4932,7 @@ FunctionDecl *Sema::InstantiateFunctionDeclaration(
49324932
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
49334933
FunctionDecl *Function,
49344934
bool Recursive,
4935-
bool DefinitionRequired,
4936-
bool AtEndOfTU) {
4935+
bool DefinitionRequired) {
49374936
if (Function->isInvalidDecl() || isa<CXXDeductionGuideDecl>(Function))
49384937
return;
49394938

@@ -6470,15 +6469,17 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
64706469
getASTContext().forEachMultiversionedFunctionVersion(
64716470
Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) {
64726471
InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true,
6473-
DefinitionRequired, true);
6472+
DefinitionRequired);
64746473
if (CurFD->isDefined())
64756474
CurFD->setInstantiationIsPending(false);
64766475
});
64776476
} else {
64786477
InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true,
6479-
DefinitionRequired, true);
6478+
DefinitionRequired);
64806479
if (Function->isDefined())
64816480
Function->setInstantiationIsPending(false);
6481+
else if (!AtEndOfTU)
6482+
LateParsedInstantiations.push_back(Inst);
64826483
}
64836484
// Definition of a PCH-ed template declaration may be available only in the TU.
64846485
if (!LocalOnly && LangOpts.PCHInstantiateTemplates &&
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify %s
2+
// expected-no-diagnostics
3+
4+
template <typename T>
5+
auto foo(T const& arg) -> T;
6+
7+
template <typename Fp, typename Vis>
8+
auto dispatch(Fp fp, Vis vis) {
9+
return fp(vis);
10+
}
11+
12+
auto baz(int v) {
13+
auto callable = []<typename Arg>(Arg const& arg) -> int {
14+
return foo(arg);
15+
};
16+
return dispatch(callable, v);
17+
}
18+
19+
template <typename T>
20+
auto foo(T const& arg) -> T {
21+
return arg;
22+
}
23+
24+
int main() {
25+
return baz(5);
26+
}

0 commit comments

Comments
 (0)