Skip to content

Commit 91abcd2

Browse files
HerrCai0907ahatanaka
authored andcommitted
[Sema]Select correct lexical context during template instantiate
This patch wants to fix inline friend decl like ``` template <class F1> int foo(F1 X); template <int A1> struct A { template <class F1> friend int foo(F1 X) { return A1; } }; template struct A<1>; int a = foo(1.0); ``` Differential Revision: https://reviews.llvm.org/D149009 (cherry picked from commit 921b45a) Conflicts: clang/lib/Sema/SemaTemplateDeduction.cpp
1 parent 0d4d579 commit 91abcd2

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3578,9 +3578,26 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
35783578
DeclContext *Owner = FunctionTemplate->getDeclContext();
35793579
if (FunctionTemplate->getFriendObjectKind())
35803580
Owner = FunctionTemplate->getLexicalDeclContext();
3581+
FunctionDecl *FD = FunctionTemplate->getTemplatedDecl();
3582+
// additional check for inline friend,
3583+
// ```
3584+
// template <class F1> int foo(F1 X);
3585+
// template <int A1> struct A {
3586+
// template <class F1> friend int foo(F1 X) { return A1; }
3587+
// };
3588+
// template struct A<1>;
3589+
// int a = foo(1.0);
3590+
// ```
3591+
const FunctionDecl *FDFriend;
3592+
if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None &&
3593+
FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) &&
3594+
FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) {
3595+
FD = const_cast<FunctionDecl *>(FDFriend);
3596+
Owner = FD->getLexicalDeclContext();
3597+
}
35813598
MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList);
35823599
Specialization = cast_or_null<FunctionDecl>(
3583-
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
3600+
SubstDecl(FD, Owner, SubstArgs));
35843601
if (!Specialization || Specialization->isInvalidDecl())
35853602
return TDK_SubstitutionFailure;
35863603

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4630,11 +4630,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
46304630
ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back();
46314631
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
46324632
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
4633-
if (FunctionTemplateDecl *FunTmpl
4634-
= dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) {
4635-
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
4636-
"Deduction from the wrong function template?");
4637-
(void) FunTmpl;
4633+
if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) {
46384634
SemaRef.InstantiatingSpecializations.erase(
46394635
{ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind});
46404636
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
4+
template <class F1> int foo1(F1 X1);
5+
6+
template <int A1> struct A {
7+
template <class F2> friend int foo1(F2 X2) {
8+
return A1;
9+
}
10+
};
11+
12+
template struct A<1>;
13+
int main() {
14+
foo1(1.0);
15+
}
16+
17+
template <class F1> int foo2(F1 X1);
18+
19+
template <int A1> struct B {
20+
template <class F2> friend int foo2(F2 X2) {
21+
return A1;
22+
}
23+
};
24+
25+
template struct B<1>;
26+
template int foo2<float>(float X1);

0 commit comments

Comments
 (0)