Skip to content

Commit 921b45a

Browse files
committed
[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
1 parent b6da4bf commit 921b45a

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

clang/lib/Sema/SemaTemplateDeduction.cpp

+18-1
Original file line numberDiff line numberDiff line change
@@ -3591,11 +3591,28 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
35913591
DeclContext *Owner = FunctionTemplate->getDeclContext();
35923592
if (FunctionTemplate->getFriendObjectKind())
35933593
Owner = FunctionTemplate->getLexicalDeclContext();
3594+
FunctionDecl *FD = FunctionTemplate->getTemplatedDecl();
3595+
// additional check for inline friend,
3596+
// ```
3597+
// template <class F1> int foo(F1 X);
3598+
// template <int A1> struct A {
3599+
// template <class F1> friend int foo(F1 X) { return A1; }
3600+
// };
3601+
// template struct A<1>;
3602+
// int a = foo(1.0);
3603+
// ```
3604+
const FunctionDecl *FDFriend;
3605+
if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None &&
3606+
FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) &&
3607+
FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) {
3608+
FD = const_cast<FunctionDecl *>(FDFriend);
3609+
Owner = FD->getLexicalDeclContext();
3610+
}
35943611
MultiLevelTemplateArgumentList SubstArgs(
35953612
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
35963613
/*Final=*/false);
35973614
Specialization = cast_or_null<FunctionDecl>(
3598-
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
3615+
SubstDecl(FD, Owner, SubstArgs));
35993616
if (!Specialization || Specialization->isInvalidDecl())
36003617
return TDK_SubstitutionFailure;
36013618

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

+1-5
Original file line numberDiff line numberDiff line change
@@ -4662,11 +4662,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
46624662
ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back();
46634663
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
46644664
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
4665-
if (FunctionTemplateDecl *FunTmpl
4666-
= dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) {
4667-
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
4668-
"Deduction from the wrong function template?");
4669-
(void) FunTmpl;
4665+
if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) {
46704666
SemaRef.InstantiatingSpecializations.erase(
46714667
{ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind});
46724668
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
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)