PR17592: Ensure we diagnose shadowing a template parameter with a local extern
declaration.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192846 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 6185e23..3029283 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -930,8 +930,10 @@
             LeftStartingScope = true;
 
           // If we found something outside of our starting scope that
-          // does not have linkage, skip it.
-          if (LeftStartingScope && !((*I)->hasLinkage())) {
+          // 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()) {
             R.setShadowed();
             continue;
           }
diff --git a/test/CXX/temp/temp.res/temp.local/p6.cpp b/test/CXX/temp/temp.res/temp.local/p6.cpp
new file mode 100644
index 0000000..eccbb89
--- /dev/null
+++ b/test/CXX/temp/temp.res/temp.local/p6.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -verify %s -fcxx-exceptions -std=c++1y
+
+template<typename T, // expected-note {{declared here}}
+         typename T> struct X {}; // expected-error {{declaration of 'T' shadows template parameter}}
+
+template<typename T> struct Y { // expected-note 15{{declared here}}
+  template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
+
+  struct B {
+    template<typename> struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct C {
+    template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct D {
+    struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct E {
+    typedef int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct F {
+    using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct G {
+    int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct H {
+    static int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct I {
+    void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct J {
+    enum T { e }; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct K {
+    enum E { T }; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+
+  void a() {
+    extern int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void b() {
+    int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void c() {
+    try {}
+    catch (int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void d() {
+    void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+
+  friend struct T; // expected-error {{declaration of 'T' shadows template parameter}}
+};
+
+template<typename T> // expected-note {{declared here}}
+void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
+
+// FIXME: These are ill-formed: a template-parameter shall not have the same name as the template name.
+namespace A {
+  template<typename T> struct T {};
+}
+namespace B {
+  template<typename T> void T() {}
+}
+namespace C {
+  template<typename T> int T;
+}