mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[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
This commit is contained in:
parent
b6da4bf1f8
commit
921b45a855
@ -3591,11 +3591,28 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
|
||||
DeclContext *Owner = FunctionTemplate->getDeclContext();
|
||||
if (FunctionTemplate->getFriendObjectKind())
|
||||
Owner = FunctionTemplate->getLexicalDeclContext();
|
||||
FunctionDecl *FD = FunctionTemplate->getTemplatedDecl();
|
||||
// additional check for inline friend,
|
||||
// ```
|
||||
// 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);
|
||||
// ```
|
||||
const FunctionDecl *FDFriend;
|
||||
if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None &&
|
||||
FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) &&
|
||||
FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) {
|
||||
FD = const_cast<FunctionDecl *>(FDFriend);
|
||||
Owner = FD->getLexicalDeclContext();
|
||||
}
|
||||
MultiLevelTemplateArgumentList SubstArgs(
|
||||
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
|
||||
/*Final=*/false);
|
||||
Specialization = cast_or_null<FunctionDecl>(
|
||||
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
|
||||
SubstDecl(FD, Owner, SubstArgs));
|
||||
if (!Specialization || Specialization->isInvalidDecl())
|
||||
return TDK_SubstitutionFailure;
|
||||
|
||||
|
@ -4662,11 +4662,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
|
||||
ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back();
|
||||
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
|
||||
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
|
||||
if (FunctionTemplateDecl *FunTmpl
|
||||
= dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) {
|
||||
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
|
||||
"Deduction from the wrong function template?");
|
||||
(void) FunTmpl;
|
||||
if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) {
|
||||
SemaRef.InstantiatingSpecializations.erase(
|
||||
{ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind});
|
||||
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
|
||||
|
@ -0,0 +1,26 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
template <class F1> int foo1(F1 X1);
|
||||
|
||||
template <int A1> struct A {
|
||||
template <class F2> friend int foo1(F2 X2) {
|
||||
return A1;
|
||||
}
|
||||
};
|
||||
|
||||
template struct A<1>;
|
||||
int main() {
|
||||
foo1(1.0);
|
||||
}
|
||||
|
||||
template <class F1> int foo2(F1 X1);
|
||||
|
||||
template <int A1> struct B {
|
||||
template <class F2> friend int foo2(F2 X2) {
|
||||
return A1;
|
||||
}
|
||||
};
|
||||
|
||||
template struct B<1>;
|
||||
template int foo2<float>(float X1);
|
Loading…
Reference in New Issue
Block a user