summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp17
-rw-r--r--clang/test/Modules/Inputs/template-default-args/a.h4
-rw-r--r--clang/test/Modules/Inputs/template-default-args/module.modulemap3
-rw-r--r--clang/test/Modules/template-default-args.cpp2
4 files changed, 25 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 923da4e06b6..bda535bc654 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -387,6 +387,8 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
// If D has more default arguments, it is preferred.
if (DMin != EMin)
return DMin < EMin;
+ // FIXME: When we track visibility for default function arguments, check
+ // that we pick the declaration with more visible default arguments.
}
// Pick the template with more default template arguments.
@@ -394,9 +396,22 @@ static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
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 D has more default arguments, it is preferred. Note that default
+ // arguments (and their visibility) is monotonically increasing across the
+ // redeclaration chain, so this is a quick proxy for "is more recent".
if (DMin != EMin)
return DMin < EMin;
+ // If D has more *visible* default arguments, it is preferred. Note, an
+ // earlier default argument being visible does not imply that a later
+ // default argument is visible, so we can't just check the first one.
+ for (unsigned I = DMin, N = DTD->getTemplateParameters()->size();
+ I != N; ++I) {
+ if (!S.hasVisibleDefaultArgument(
+ ETD->getTemplateParameters()->getParam(I)) &&
+ S.hasVisibleDefaultArgument(
+ DTD->getTemplateParameters()->getParam(I)))
+ return true;
+ }
}
// For most kinds of declaration, it doesn't really matter which one we pick.
diff --git a/clang/test/Modules/Inputs/template-default-args/a.h b/clang/test/Modules/Inputs/template-default-args/a.h
index a8a01a9e313..532cbc8be03 100644
--- a/clang/test/Modules/Inputs/template-default-args/a.h
+++ b/clang/test/Modules/Inputs/template-default-args/a.h
@@ -9,4 +9,8 @@ template<typename T = int> struct H;
template<typename T> struct J {};
template<typename T = int> struct J;
struct K : J<> {};
+template<typename T = void> struct L;
+struct FriendL {
+ template<typename T> friend struct L;
+};
END
diff --git a/clang/test/Modules/Inputs/template-default-args/module.modulemap b/clang/test/Modules/Inputs/template-default-args/module.modulemap
index d54dfc345ab..21bf40c3bcc 100644
--- a/clang/test/Modules/Inputs/template-default-args/module.modulemap
+++ b/clang/test/Modules/Inputs/template-default-args/module.modulemap
@@ -3,3 +3,6 @@ module X {
module B { header "b.h" }
module C { header "c.h" }
}
+module Y {
+ module D { header "d.h" }
+}
diff --git a/clang/test/Modules/template-default-args.cpp b/clang/test/Modules/template-default-args.cpp
index 3a519f2d8a7..9d16cbf4342 100644
--- a/clang/test/Modules/template-default-args.cpp
+++ b/clang/test/Modules/template-default-args.cpp
@@ -13,6 +13,7 @@ template<typename T = int, typename U = int> struct I {};
END
#include "b.h"
+#include "d.h"
BEGIN
template<typename T = int> struct A {};
@@ -41,4 +42,5 @@ G<> g; // expected-error {{default argument of 'G' must be imported from module
H<> h; // expected-error {{default argument of 'H' must be imported from module 'X.A' before it is required}}
// expected-note@a.h:8 {{default argument declared here}}
I<> i;
+L<> *l;
END
OpenPOWER on IntegriCloud