From 44d1e0af59188b39e5b55df92f872cd13baaa561 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@woboq.com>
Date: Thu, 16 Jun 2016 21:39:46 +0000
Subject: [PATCH] Functions declared in a scope should not hide previous
 declaration in earlier scopes

This code should be an error:

 void foo(int);
 void f3() {
   int foo(float);
   {
     float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
   }
 }

the foo(float) function declared at function scope should not hide the float(int)
while trying to redeclare functions.

Differential Revision: http://reviews.llvm.org/D19763

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@272961 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaLookup.cpp          | 23 +++++++++++++----------
 test/SemaCXX/function-redecl.cpp |  9 ++++++++-
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index e761436683e..37db9aec637 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1078,32 +1078,35 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
 
   for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
     DeclContext *Ctx = S->getEntity();
-
+    bool SearchNamespaceScope = true;
     // Check whether the IdResolver has anything in this scope.
-    bool Found = false;
     for (; I != IEnd && S->isDeclScope(*I); ++I) {
       if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
-        if (NameKind == LookupRedeclarationWithLinkage) {
+        if (NameKind == LookupRedeclarationWithLinkage &&
+            !(*I)->isTemplateParameter()) {
+          // If it's a template parameter, we still find it, so we can diagnose
+          // the invalid redeclaration.
+
           // Determine whether this (or a previous) declaration is
           // out-of-scope.
           if (!LeftStartingScope && !Initial->isDeclScope(*I))
             LeftStartingScope = true;
 
           // If we found something outside of our starting scope that
-          // does not have linkage, skip it. If it's a template parameter,
-          // we still find it, so we can diagnose the invalid redeclaration.
-          if (LeftStartingScope && !((*I)->hasLinkage()) &&
-              !(*I)->isTemplateParameter()) {
+          // does not have linkage, skip it.
+          if (LeftStartingScope && !((*I)->hasLinkage())) {
             R.setShadowed();
             continue;
           }
+        } else {
+          // We found something in this scope, we should not look at the
+          // namespace scope
+          SearchNamespaceScope = false;
         }
-
-        Found = true;
         R.addDecl(ND);
       }
     }
-    if (Found) {
+    if (!SearchNamespaceScope) {
       R.resolveKind();
       if (S->isClassScope())
         if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx))
diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp
index 2bc0d90cd62..f91e670c0c3 100644
--- a/test/SemaCXX/function-redecl.cpp
+++ b/test/SemaCXX/function-redecl.cpp
@@ -7,7 +7,7 @@ namespace N {
     void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
-  void foo(int); // expected-note 2{{previous declaration is here}}
+  void foo(int); // expected-note 3{{previous declaration is here}}
 
   void f2() {
     int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
@@ -25,6 +25,13 @@ namespace N {
       }
     }
   }
+
+  void f3() {
+    int foo(float);
+    {
+      float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+    }
+  }
 }
 
 class A {
-- 
GitLab