diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-11 01:59:33 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-11 01:59:33 +0000 |
commit | 64095fc07c737333f5bab96f2998d54de08a8251 (patch) | |
tree | b65fe3cb29f409f34cf7755afb8b0825cca57770 /clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 5488ab4ddd47af2151d79940e805914da56d6562 (diff) | |
download | bcm5719-llvm-64095fc07c737333f5bab96f2998d54de08a8251.tar.gz bcm5719-llvm-64095fc07c737333f5bab96f2998d54de08a8251.zip |
Remember to instantiate explicit template argument lists in a friend
function declaration.
We'd previously often just drop these on the floor, and friend
redeclaration matching would usually (but not always) figure out the
right redeclaration anyway.
Also, don't try to match a dependent friend function template
specialization to a template until instantiation, and don't forget to
reject qualified friend declarations in dependent contexts that don't
name an already-declared entity.
llvm-svn: 350915
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 31353e45baa..fad3c065e89 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1747,10 +1747,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); } + if (isFriend) + Function->setObjectOfFriendDecl(); + if (InitFunctionInstantiation(Function, D)) Function->setInvalidDecl(); - bool isExplicitSpecialization = false; + bool IsExplicitSpecialization = false; LookupResult Previous( SemaRef, Function->getDeclName(), SourceLocation(), @@ -1763,9 +1766,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, = D->getDependentSpecializationInfo()) { assert(isFriend && "non-friend has dependent specialization info?"); - // This needs to be set now for future sanity. - Function->setObjectOfFriendDecl(); - // Instantiate the explicit template arguments. TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); @@ -1788,8 +1788,25 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Previous)) Function->setInvalidDecl(); - isExplicitSpecialization = true; + IsExplicitSpecialization = true; + } else if (const ASTTemplateArgumentListInfo *Info = + D->getTemplateSpecializationArgsAsWritten()) { + // The name of this function was written as a template-id. + SemaRef.LookupQualifiedName(Previous, DC); + // Instantiate the explicit template arguments. + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return nullptr; + + if (SemaRef.CheckFunctionTemplateSpecialization(Function, + &ExplicitArgs, + Previous)) + Function->setInvalidDecl(); + + IsExplicitSpecialization = true; } else if (TemplateParams || !FunctionTemplate) { // Look only into the namespace where the friend would be declared to // find a previous declaration. This is the innermost enclosing namespace, @@ -1804,11 +1821,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Previous.clear(); } - if (isFriend) - Function->setObjectOfFriendDecl(); - SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, - isExplicitSpecialization); + IsExplicitSpecialization); NamedDecl *PrincipalDecl = (TemplateParams ? cast<NamedDecl>(FunctionTemplate) @@ -2055,7 +2069,54 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, Sema::ForExternalRedeclaration); - if (!FunctionTemplate || TemplateParams || isFriend) { + bool IsExplicitSpecialization = false; + + // If the name of this function was written as a template-id, instantiate + // the explicit template arguments. + if (DependentFunctionTemplateSpecializationInfo *Info + = D->getDependentSpecializationInfo()) { + assert(isFriend && "non-friend has dependent specialization info?"); + + // Instantiate the explicit template arguments. + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return nullptr; + + // Map the candidate templates to their instantiations. + for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { + Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), + Info->getTemplate(I), + TemplateArgs); + if (!Temp) return nullptr; + + Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); + } + + if (SemaRef.CheckFunctionTemplateSpecialization(Method, + &ExplicitArgs, + Previous)) + Method->setInvalidDecl(); + + IsExplicitSpecialization = true; + } else if (const ASTTemplateArgumentListInfo *Info = + D->getTemplateSpecializationArgsAsWritten()) { + SemaRef.LookupQualifiedName(Previous, DC); + + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return nullptr; + + if (SemaRef.CheckFunctionTemplateSpecialization(Method, + &ExplicitArgs, + Previous)) + Method->setInvalidDecl(); + + IsExplicitSpecialization = true; + } else if (!FunctionTemplate || TemplateParams || isFriend) { SemaRef.LookupQualifiedName(Previous, Record); // In C++, the previous declaration we find might be a tag type @@ -2067,7 +2128,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, } if (!IsClassScopeSpecialization) - SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, false); + SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, + IsExplicitSpecialization); if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); |