summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp64
-rw-r--r--clang/test/SemaCXX/nested-name-spec.cpp16
-rw-r--r--clang/test/SemaTemplate/nested-name-spec-template.cpp7
3 files changed, 71 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 337a4a3ce3f..31c33e963ca 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -761,10 +761,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// context as well as walking through the scopes.
for (; S; S = S->getParent()) {
- DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
- if (Ctx && Ctx->isTransparentContext())
- continue;
-
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
@@ -778,21 +774,57 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
}
}
- // If we have a context, and it's not a context stashed in the
- // template parameter scope for an out-of-line definition, also
- // look into that context.
- if (Ctx && !(Found && S && S->isTemplateParamScope())) {
- assert(Ctx->isFileContext() &&
- "We should have been looking only at file context here already.");
+ if (Found && S->isTemplateParamScope()) {
+ R.resolveKind();
+ return true;
+ }
- // Look into context considering using-directives.
- if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
- Found = true;
+ DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+ S->getParent() && !S->getParent()->isTemplateParamScope()) {
+ // We've just searched the last template parameter scope and
+ // found nothing, so look into the the contexts between the
+ // lexical and semantic declaration contexts returned by
+ // findOuterContext(). This implements the name lookup behavior
+ // of C++ [temp.local]p8.
+ Ctx = OutsideOfTemplateParamDC;
+ OutsideOfTemplateParamDC = 0;
}
+
+ if (Ctx) {
+ DeclContext *OuterCtx;
+ bool SearchAfterTemplateScope;
+ llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ if (SearchAfterTemplateScope)
+ OutsideOfTemplateParamDC = OuterCtx;
- if (Found) {
- R.resolveKind();
- return true;
+ for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
+ // We do not directly look into transparent contexts, since
+ // those entities will be found in the nearest enclosing
+ // non-transparent context.
+ if (Ctx->isTransparentContext())
+ continue;
+
+ // If we have a context, and it's not a context stashed in the
+ // template parameter scope for an out-of-line definition, also
+ // look into that context.
+ if (!(Found && S && S->isTemplateParamScope())) {
+ assert(Ctx->isFileContext() &&
+ "We should have been looking only at file context here already.");
+
+ // Look into context considering using-directives.
+ if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+ Found = true;
+ }
+
+ if (Found) {
+ R.resolveKind();
+ return true;
+ }
+
+ if (R.isForRedeclaration() && !Ctx->isTransparentContext())
+ return false;
+ }
}
if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp
index 59a8e8c45dc..0dc1097e386 100644
--- a/clang/test/SemaCXX/nested-name-spec.cpp
+++ b/clang/test/SemaCXX/nested-name-spec.cpp
@@ -228,3 +228,19 @@ namespace test3 {
A::execute(path); // expected-error {{incomplete type 'test3::A' named in nested name specifier}}
}
}
+
+namespace PR7133 {
+ namespace A {
+ class Foo;
+ }
+
+ namespace A {
+ namespace B {
+ bool foo(Foo &);
+ }
+ }
+
+ bool A::B::foo(Foo &) {
+ return false;
+ }
+}
diff --git a/clang/test/SemaTemplate/nested-name-spec-template.cpp b/clang/test/SemaTemplate/nested-name-spec-template.cpp
index 9d25a051e8a..54e615b4ab6 100644
--- a/clang/test/SemaTemplate/nested-name-spec-template.cpp
+++ b/clang/test/SemaTemplate/nested-name-spec-template.cpp
@@ -64,3 +64,10 @@ namespace test1 {
template <class T>
T pair<T>::* const pair<T>::mem_array[2] = { &pair<T>::x, &pair<T>::y };
}
+
+typedef int T;
+namespace N1 {
+ template<typename T> T f0();
+}
+
+template<typename T> T N1::f0() { }
OpenPOWER on IntegriCloud