summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-01-07 06:00:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-01-07 06:00:46 +0000
commit8ce732b46f5570d21f0e92ea783387b2e5a3b846 (patch)
tree3cf8aefe6223556ba47b2d07890d3bce1301252f /clang/lib/Sema/SemaTemplate.cpp
parent1ac0839098029ce987ce89f0a8c3faf380e50bd1 (diff)
downloadbcm5719-llvm-8ce732b46f5570d21f0e92ea783387b2e5a3b846.tar.gz
bcm5719-llvm-8ce732b46f5570d21f0e92ea783387b2e5a3b846.zip
DR674, PR38883, PR40238: Qualified friend lookup should look for a
template specialization if there is no matching non-template function. This exposed a couple of related bugs: - we would sometimes substitute into a friend template instead of a suitable non-friend declaration; this would now crash because we'd decide the specialization of the friend is a redeclaration of itself - ADL failed to properly handle the case where an invisible local extern declaration redeclares an invisible friend Both are fixed herein: in particular, we now never make invisible friends or local extern declarations visible to name lookup unless they are the only declaration of the entity. (We already mostly did this for local extern declarations.) llvm-svn: 350505
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp25
1 files changed, 22 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 8485ecd3a3b..35935f994ca 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -8104,9 +8104,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
///
/// \param Previous the set of declarations that may be specialized by
/// this function specialization.
+///
+/// \param QualifiedFriend whether this is a lookup for a qualified friend
+/// declaration with no explicit template argument list that might be
+/// befriending a function template specialization.
bool Sema::CheckFunctionTemplateSpecialization(
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
- LookupResult &Previous) {
+ LookupResult &Previous, bool QualifiedFriend) {
// The set of function template specializations that could match this
// explicit function template specialization.
UnresolvedSet<8> Candidates;
@@ -8193,10 +8197,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
}
+ // For a qualified friend declaration (with no explicit marker to indicate
+ // that a template specialization was intended), note all (template and
+ // non-template) candidates.
+ if (QualifiedFriend && Candidates.empty()) {
+ Diag(FD->getLocation(), diag::err_qualified_friend_no_match)
+ << FD->getDeclName() << FDLookupContext;
+ // FIXME: We should form a single candidate list and diagnose all
+ // candidates at once, to get proper sorting and limiting.
+ for (auto *OldND : Previous) {
+ if (auto *OldFD = dyn_cast<FunctionDecl>(OldND->getUnderlyingDecl()))
+ NoteOverloadCandidate(OldND, OldFD, FD->getType(), false);
+ }
+ FailedCandidates.NoteCandidates(*this, FD->getLocation());
+ return true;
+ }
+
// Find the most specialized function template.
UnresolvedSetIterator Result = getMostSpecialized(
- Candidates.begin(), Candidates.end(), FailedCandidates,
- FD->getLocation(),
+ Candidates.begin(), Candidates.end(), FailedCandidates, FD->getLocation(),
PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
PDiag(diag::err_function_template_spec_ambiguous)
<< FD->getDeclName() << (ExplicitTemplateArgs != nullptr),
OpenPOWER on IntegriCloud