Skip to content

Commit c3aeec3

Browse files
committed
Limit scope of the change to inline friend functions.
1 parent efb41e6 commit c3aeec3

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,16 +1976,14 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
19761976
if (!InstParams)
19771977
return nullptr;
19781978

1979-
// Use canonical templated decl because only canonical decl has body
1980-
// if declarations were merged during loading from modules.
1981-
FunctionDecl *TemplatedDecl = D->getTemplatedDecl()->getCanonicalDecl();
19821979
FunctionDecl *Instantiated = nullptr;
1983-
if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(TemplatedDecl))
1984-
Instantiated =
1985-
cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod, InstParams));
1980+
if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
1981+
Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
1982+
InstParams));
19861983
else
1987-
Instantiated = cast_or_null<FunctionDecl>(
1988-
VisitFunctionDecl(TemplatedDecl, InstParams));
1984+
Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl(
1985+
D->getTemplatedDecl(),
1986+
InstParams));
19891987

19901988
if (!Instantiated)
19911989
return nullptr;
@@ -2003,7 +2001,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
20032001
// Link the instantiation back to the pattern *unless* this is a
20042002
// non-definition friend declaration.
20052003
if (!InstTemplate->getInstantiatedFromMemberTemplate() &&
2006-
!(isFriend && !TemplatedDecl->isThisDeclarationADefinition()))
2004+
!(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition()))
20072005
InstTemplate->setInstantiatedFromMemberTemplate(D);
20082006

20092007
// Make declarations visible in the appropriate context.
@@ -2148,6 +2146,21 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
21482146
// Check whether there is already a function template specialization for
21492147
// this declaration.
21502148
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
2149+
bool isFriend;
2150+
if (FunctionTemplate)
2151+
isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
2152+
else
2153+
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
2154+
// Friend function defined withing class template may stop being function
2155+
// definition during AST merges from different modules, in this case decl
2156+
// with function body should be used for instantiation.
2157+
if (isFriend) {
2158+
const FunctionDecl* Defn = nullptr;
2159+
if (D->hasBody(Defn)) {
2160+
D = const_cast<FunctionDecl*>(Defn);
2161+
FunctionTemplate = Defn->getDescribedFunctionTemplate();
2162+
}
2163+
}
21512164
if (FunctionTemplate && !TemplateParams) {
21522165
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
21532166

@@ -2160,12 +2173,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
21602173
return SpecFunc;
21612174
}
21622175

2163-
bool isFriend;
2164-
if (FunctionTemplate)
2165-
isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
2166-
else
2167-
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
2168-
21692176
bool MergeWithParentScope = (TemplateParams != nullptr) ||
21702177
Owner->isFunctionOrMethod() ||
21712178
!(isa<Decl>(Owner) &&

0 commit comments

Comments
 (0)