summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-08-22 21:37:34 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-08-22 21:37:34 +0000
commitcd31b85c12456c07d3f01e85eea88d690445c24d (patch)
treef4004155dfecc593f1eb754b99fc428af004a2ad /clang/lib/Sema/SemaLookup.cpp
parent4c0a2a989b9f5661cf52c0713fa4f1a6aa8757aa (diff)
downloadbcm5719-llvm-cd31b85c12456c07d3f01e85eea88d690445c24d.tar.gz
bcm5719-llvm-cd31b85c12456c07d3f01e85eea88d690445c24d.zip
Improve the performance of resolving a lookup result. We usually don't need to
pick the most recent declaration, and we can often tell which declaration is more recent without walking the redeclaration chain. Do so when possible. llvm-svn: 245794
Diffstat (limited to 'clang/lib/Sema/SemaLookup.cpp')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp41
1 files changed, 37 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index bf67ae29c1d..1c6256eb917 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -356,7 +356,7 @@ static DeclContext *getContextForScopeMatching(Decl *D) {
/// \brief Determine whether \p D is a better lookup result than \p Existing,
/// given that they declare the same entity.
-static bool isPreferredLookupResult(Sema::LookupNameKind Kind,
+static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
NamedDecl *D, NamedDecl *Existing) {
// When looking up redeclarations of a using declaration, prefer a using
// shadow declaration over any other declaration of the same entity.
@@ -376,13 +376,46 @@ static bool isPreferredLookupResult(Sema::LookupNameKind Kind,
return false;
}
- // If D is newer than Existing, prefer it.
+ // Pick the function with more default arguments.
+ // FIXME: In the presence of ambiguous default arguments, we should keep both,
+ // so we can diagnose the ambiguity if the default argument is needed.
+ // See C++ [over.match.best]p3.
+ if (auto *DFD = dyn_cast<FunctionDecl>(DUnderlying)) {
+ auto *EFD = cast<FunctionDecl>(EUnderlying);
+ unsigned DMin = DFD->getMinRequiredArguments();
+ unsigned EMin = EFD->getMinRequiredArguments();
+ // If D has more default arguments, it is preferred.
+ if (DMin != EMin)
+ return DMin < EMin;
+ }
+
+ // Pick the template with more default template arguments.
+ if (auto *DTD = dyn_cast<TemplateDecl>(DUnderlying)) {
+ auto *ETD = cast<TemplateDecl>(EUnderlying);
+ unsigned DMin = DTD->getTemplateParameters()->getMinRequiredArguments();
+ unsigned EMin = ETD->getTemplateParameters()->getMinRequiredArguments();
+ // If D has more default arguments, it is preferred.
+ if (DMin != EMin)
+ return DMin < EMin;
+ }
+
+ // For most kinds of declaration, it doesn't really matter which one we pick.
+ if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) {
+ // If the existing declaration is hidden, prefer the new one. Otherwise,
+ // keep what we've got.
+ return !S.isVisible(Existing);
+ }
+
+ // Pick the newer declaration; it might have a more precise type.
for (Decl *Prev = DUnderlying->getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl())
if (Prev == EUnderlying)
return true;
-
return false;
+
+ // If the existing declaration is hidden, prefer the new one. Otherwise,
+ // keep what we've got.
+ return !S.isVisible(Existing);
}
/// Resolves the result kind of this lookup.
@@ -462,7 +495,7 @@ void LookupResult::resolveKind() {
if (ExistingI) {
// This is not a unique lookup result. Pick one of the results and
// discard the other.
- if (isPreferredLookupResult(getLookupKind(), Decls[I],
+ if (isPreferredLookupResult(getSema(), getLookupKind(), Decls[I],
Decls[*ExistingI]))
Decls[*ExistingI] = Decls[I];
Decls[I] = Decls[--N];
OpenPOWER on IntegriCloud