Switch the semantic DeclContext for a block-scope declaration of a function or
variable from being the function to being the enclosing namespace scope (in
C++) or the TU (in C). This allows us to fix a selection of related issues
where we would build incorrect redeclaration chains for such declarations, and
fail to notice type mismatches.

Such declarations are put into a new IdentifierNamespace, IDNS_LocalExtern,
which is only found when searching scopes, and not found when searching
DeclContexts. Such a declaration is only made visible in its DeclContext if
there are no non-LocalExtern declarations.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191064 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/basic/basic.link/p7.cpp b/test/CXX/basic/basic.link/p7.cpp
new file mode 100644
index 0000000..9a85eac
--- /dev/null
+++ b/test/CXX/basic/basic.link/p7.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -verify -std=c++1y %s
+
+// Example from the standard.
+namespace X {
+  void p() {
+    q(); // expected-error {{undeclared}}
+    extern void q();
+  }
+  void middle() {
+    q(); // expected-error {{undeclared}}
+  }
+  void q() { /*...*/ }
+  void bottom() {
+    q();
+  }
+}
+int q();
+
+namespace Test1 {
+  void f() {
+    extern int a; // expected-note {{previous}}
+    int g(void); // expected-note {{previous}}
+  }
+  double a; // expected-error {{different type: 'double' vs 'int'}}
+  double g(); // expected-error {{differ only in their return type}}
+}
+
+namespace Test2 {
+  void f() {
+    extern int a; // expected-note {{previous}}
+    int g(void); // expected-note {{previous}}
+  }
+  void h() {
+    extern double a; // expected-error {{different type: 'double' vs 'int'}}
+    double g(void); // expected-error {{differ only in their return type}}
+  }
+}
+
+namespace Test3 {
+  constexpr void (*f())() {
+    void h();
+    return &h;
+  }
+  constexpr void (*g())() {
+    void h();
+    return &h;
+  }
+  static_assert(f() == g(), "");
+}
+
+namespace Test4 {
+  template<typename T>
+  constexpr void (*f())() {
+    void h();
+    return &h;
+  }
+  static_assert(f<int>() == f<char>(), "");
+  void h();
+  static_assert(f<int>() == &h, "");
+}
+
+namespace Test5 {
+  constexpr auto f() -> void (*)() {
+    void g();
+    struct X {
+      friend void g();
+      static constexpr auto h() -> void (*)() { return g; }
+    };
+    return X::h();
+  }
+  void g();
+  static_assert(f() == g, "");
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
index 2dbc143..e040d5b 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp
@@ -61,6 +61,8 @@
       int x = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}}
     }
     int y = sizeof(array);
+    extern int array[];
+    int z = sizeof(array);
   }
 }
 
@@ -71,6 +73,19 @@
     int x = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}}
   }
   int y = sizeof(array);
+  extern int array[];
+  int z = sizeof(array);
+}
+
+namespace test8 {
+  extern int array[];
+  void test() {
+    extern int array[100];
+    int x = sizeof(array);
+  }
+  int y = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}}
+  extern int array[];
+  int z = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}}
 }
 
 namespace dependent {
@@ -143,10 +158,52 @@
   }
 
   template<typename T> void n() {
-    extern T n_var;
+    extern T n_var; // expected-error {{redefinition of 'n_var' with a different type: 'double' vs 'int'}} expected-note {{previous}}
+    extern T n_fn(); // expected-error {{functions that differ only in their return type cannot be overloaded}} expected-note {{previous}}
   }
   template void n<int>();
-  // FIXME: Diagnose this!
-  float n_var;
-  template void n<double>();
+  template void n<double>(); // expected-note {{in instantiation of}}
+
+  template<typename T> void o() {
+    extern T o_var; // expected-note {{previous}}
+    extern T o_fn(); // expected-note {{previous}}
+  }
+  template void o<int>();
+  float o_var; // expected-error {{redefinition of 'o_var' with a different type: 'float' vs 'int'}}
+  float o_fn(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+
+  int p_var;
+  int p_fn();
+  template<typename T> void p() {
+    extern T p_var;
+    extern T p_fn();
+  }
+}
+
+namespace use_outside_ns {
+  namespace A {
+    extern int a[3];
+    extern int b[];
+    extern int c[3];
+    void f() {
+      extern int a[];
+      extern int b[3];
+    }
+    template<typename T> void x() {
+      extern T c;
+      extern T d;
+    }
+    extern int d[3];
+    template void x<int[]>();
+  }
+  int w = sizeof(A::a);
+  int x = sizeof(A::b); // expected-error {{incomplete}}
+  int y = sizeof(A::c);
+  int z = sizeof(A::d);
+  namespace A {
+    int g() { return sizeof(a); }
+    int h() { return sizeof(b); } // expected-error {{incomplete}}
+    int i() { return sizeof(c); }
+    int j() { return sizeof(d); }
+  }
 }
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index f8ac57f..70a9e49 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -280,7 +280,7 @@
 
 // dr28: na
 
-namespace dr29 { // dr29: no
+namespace dr29 { // dr29: 3.4
   void dr29_f0(); // expected-note {{here}}
   void g0() { void dr29_f0(); }
   extern "C++" void g0_cxx() { void dr29_f0(); }
@@ -291,17 +291,14 @@
   extern "C" void g1_c() { void dr29_f1(); }
   extern "C++" void g1_cxx() { void dr29_f1(); } // expected-error {{different language linkage}}
 
-  // FIXME: We should reject this.
-  void g2() { void dr29_f2(); }
-  extern "C" void dr29_f2();
+  void g2() { void dr29_f2(); } // expected-note {{here}}
+  extern "C" void dr29_f2(); // expected-error {{different language linkage}}
 
-  // FIXME: We should reject this.
-  extern "C" void g3() { void dr29_f3(); }
-  extern "C++" void dr29_f3();
+  extern "C" void g3() { void dr29_f3(); } // expected-note {{here}}
+  extern "C++" void dr29_f3(); // expected-error {{different language linkage}}
 
-  // FIXME: We should reject this.
-  extern "C++" void g4() { void dr29_f4(); }
-  extern "C" void dr29_f4();
+  extern "C++" void g4() { void dr29_f4(); } // expected-note {{here}}
+  extern "C" void dr29_f4(); // expected-error {{different language linkage}}
 
   extern "C" void g5();
   extern "C++" void dr29_f5();
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index f03f499..775cf00 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -9,7 +9,7 @@
 // CHECK: @_ZGVZN1N1gEvE1a = internal global
 
 //CHECK: @pr5966_i = external global
-//CHECK: @_ZL8pr5966_i = internal global
+//CHECK: @_ZL8pr5966_j = internal global
 
 // CHECK-LABEL: define zeroext i1 @_ZplRK1YRA100_P1X
 bool operator+(const Y&, X* (&xs)[100]) { return false; }
@@ -314,10 +314,10 @@
   pr5966_i = 0;
 }
 
-static int pr5966_i;
+static int pr5966_j;
 
 void pr5966_bar() {
-  pr5966_i = 0;
+  pr5966_j = 0;
 }
 
 namespace test0 {
@@ -652,10 +652,10 @@
     foo();
   }
 
-  static char foo() {}
+  static char bar() {}
   void test1() {
-    // CHECK: call signext i8 @_ZN6test24L3fooEv()
-    foo();
+    // CHECK: call signext i8 @_ZN6test24L3barEv()
+    bar();
   }
 }
 
diff --git a/test/Index/usrs.m b/test/Index/usrs.m
index dccfb75..cc2e0fd 100644
--- a/test/Index/usrs.m
+++ b/test/Index/usrs.m
@@ -118,7 +118,7 @@
 // CHECK: usrs.m c:objc(cs)Foo Extent=[34:1 - 45:2]
 // CHECK: usrs.m c:objc(cs)Foo(im)godzilla Extent=[35:1 - 39:2]
 // CHECK: usrs.m c:usrs.m@402objc(cs)Foo(im)godzilla@a Extent=[36:3 - 36:19]
-// CHECK: usrs.m c:objc(cs)Foo(im)godzilla@z Extent=[37:3 - 37:15]
+// CHECK: usrs.m c:@z Extent=[37:3 - 37:15]
 // CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[40:1 - 43:2]
 // CHECK: usrs.m c:usrs.m@470objc(cs)Foo(cm)kingkong@local_var Extent=[41:3 - 41:16]
 // CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[44:1 - 44:15]
diff --git a/test/Sema/struct-decl.c b/test/Sema/struct-decl.c
index 819e856..8d3d74d 100644
--- a/test/Sema/struct-decl.c
+++ b/test/Sema/struct-decl.c
@@ -57,3 +57,12 @@
 inline struct test3 { // expected-error {{'inline' can only appear on functions}}
   int x;
 };
+
+struct hiding_1 {};
+struct hiding_2 {};
+void test_hiding() {
+  struct hiding_1 *hiding_1();
+  extern struct hiding_2 *hiding_2;
+  struct hiding_1 *p = hiding_1();
+  struct hiding_2 *q = hiding_2;
+}
diff --git a/test/SemaCXX/blocks-1.cpp b/test/SemaCXX/blocks-1.cpp
index 02e9cac..e11fd92 100644
--- a/test/SemaCXX/blocks-1.cpp
+++ b/test/SemaCXX/blocks-1.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++11
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++1y
 
 extern "C" int exit(int);
 
@@ -57,3 +56,18 @@
     foo(a);
   };
 }
+
+namespace LocalDecls {
+  void f() {
+    (void) ^{
+      extern int a; // expected-note {{previous}}
+      extern int b(); // expected-note {{previous}}
+    };
+  }
+  void g() {
+    (void) ^{
+      extern float a; // expected-error {{different type}}
+      extern float b(); // expected-error {{cannot be overloaded}}
+    };
+  }
+}
diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp
index 48236fd..9096c8a 100644
--- a/test/SemaCXX/cxx0x-initializer-references.cpp
+++ b/test/SemaCXX/cxx0x-initializer-references.cpp
@@ -36,10 +36,10 @@
   };
 
   void call() {
-    void f(const int&);
+    one f(const int&);
     f({1});
 
-    void g(int&); // expected-note {{passing argument}}
+    one g(int&); // expected-note {{passing argument}}
     g({1}); // expected-error {{cannot bind to an initializer list temporary}}
     int i = 0;
     g({i});
diff --git a/test/SemaCXX/extern-c.cpp b/test/SemaCXX/extern-c.cpp
index 30b8fe69..2bf9535 100644
--- a/test/SemaCXX/extern-c.cpp
+++ b/test/SemaCXX/extern-c.cpp
@@ -29,16 +29,27 @@
   }
 }
 
-extern "C" {
-  void test4_f() {
-    extern int test4_b; // expected-note {{declared with C language linkage here}}
+namespace N {
+  extern "C" {
+    void test4_f() {
+      extern int test4_b; // expected-note {{declared with C language linkage here}}
+    }
   }
 }
 static float test4_b; // expected-error {{declaration of 'test4_b' in global scope conflicts with declaration with C language linkage}}
 
 extern "C" {
-  void test5_f() {
-    extern int test5_b; // expected-note {{declared with C language linkage here}}
+  void test4c_f() {
+    extern int test4_c; // expected-note {{previous}}
+  }
+}
+static float test4_c; // expected-error {{redefinition of 'test4_c' with a different type: 'float' vs 'int'}}
+
+namespace N {
+  extern "C" {
+    void test5_f() {
+      extern int test5_b; // expected-note {{declared with C language linkage here}}
+    }
   }
 }
 extern "C" {
@@ -46,6 +57,15 @@
 }
 
 extern "C" {
+  void test5c_f() {
+    extern int test5_c; // expected-note {{previous}}
+  }
+}
+extern "C" {
+  static float test5_c; // expected-error {{redefinition of 'test5_c' with a different type: 'float' vs 'int'}}
+}
+
+extern "C" {
   void f() {
     extern int test6_b;
   }
diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp
index deb8e9d..2bc0d90 100644
--- a/test/SemaCXX/function-redecl.cpp
+++ b/test/SemaCXX/function-redecl.cpp
@@ -4,17 +4,14 @@
 namespace N {
   void f1() {
     void foo(int); // okay
-    void bar(int);
+    void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
   void foo(int); // expected-note 2{{previous declaration is here}}
 
   void f2() {
     int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
-    // FIXME: We should be able to diagnose the conflict between this
-    // declaration of 'bar' and the previous one, even though they come
-    // from different lexical scopes.
-    int bar(int); // expected-note {{previous declaration is here}}
+    int bar(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
     int baz(int); // expected-note {{previous declaration is here}}
 
     {
diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp
index f36300a..dd07125 100644
--- a/test/SemaCXX/warn-unreachable.cpp
+++ b/test/SemaCXX/warn-unreachable.cpp
@@ -62,8 +62,8 @@
   struct S {
     int mem;
   } s;
-  S &foor() __attribute__((noreturn));
-  foor()
+  S &foonr() __attribute__((noreturn));
+  foonr()
     .mem;       // expected-warning {{will never be executed}}
 }