Support -Winternal-linkage-in-inline in C++ code.

This includes treating anonymous namespaces like internal linkage, and allowing
const variables to be used even if internal. The whole thing's been broken out
into a separate function to avoid nested ifs.

llvm-svn: 158683
diff --git a/clang/test/Sema/inline.c b/clang/test/Sema/inline.c
index 23eedd6..99df8b1 100644
--- a/clang/test/Sema/inline.c
+++ b/clang/test/Sema/inline.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
 
 #if defined(INCLUDE)
 // -------
@@ -40,7 +41,7 @@
 // Check that the warnings from the "header file" aren't on by default in
 // the main source file.
 
-inline int useStaticMain () {
+inline int useStaticMainFile () {
   staticFunction(); // no-warning
   return staticVar; // no-warning
 }
diff --git a/clang/test/SemaCXX/inline.cpp b/clang/test/SemaCXX/inline.cpp
index e569300..9ef0229 100644
--- a/clang/test/SemaCXX/inline.cpp
+++ b/clang/test/SemaCXX/inline.cpp
@@ -1,5 +1,110 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
+#if defined(INCLUDE)
+// -------
+// This section acts like a header file.
+// -------
+
+// Check the use of static variables in non-static inline functions.
+static int staticVar; // expected-note + {{'staticVar' declared here}}
+static int staticFunction(); // expected-note + {{'staticFunction' declared here}}
+const int constVar = 0; // no-warning
+
+namespace {
+  int anonVar; // expected-note + {{'anonVar' declared here}}
+  int anonFunction(); // expected-note + {{'anonFunction' declared here}}
+  const int anonConstVar = 0; // no-warning
+
+  class Anon {
+  public:
+    static int var; // expected-note + {{'var' declared here}}
+    static const int constVar = 0; // no-warning
+  };
+}
+
+inline void useStatic() { // expected-note + {{use 'static' to give inline function 'useStatic' internal linkage}}
+  staticFunction(); // expected-warning{{function 'staticFunction' has internal linkage but is used in an inline function with external linkage}}
+  (void)staticVar; // expected-warning{{variable 'staticVar' has internal linkage but is used in an inline function with external linkage}}
+  anonFunction(); // expected-warning{{function 'anonFunction' is in an anonymous namespace but is used in an inline function with external linkage}}
+  (void)anonVar; // expected-warning{{variable 'anonVar' is in an anonymous namespace but is used in an inline function with external linkage}}
+  (void)Anon::var; // expected-warning{{variable 'var' is in an anonymous namespace but is used in an inline function with external linkage}}
+
+  (void)constVar; // no-warning
+  (void)anonConstVar; // no-warning
+  (void)Anon::constVar; // no-warning
+}
+
+extern inline int useStaticFromExtern() { // no suggestions
+  staticFunction(); // expected-warning{{function 'staticFunction' has internal linkage but is used in an inline function with external linkage}}
+  return staticVar; // expected-warning{{variable 'staticVar' has internal linkage but is used in an inline function with external linkage}}
+}
+
+class A {
+public:
+  static inline int useInClass() { // no suggestions
+    return staticFunction(); // expected-warning{{function 'staticFunction' has internal linkage but is used in an inline method with external linkage}}
+  }
+  inline int useInInstance() { // no suggestions
+    return staticFunction(); // expected-warning{{function 'staticFunction' has internal linkage but is used in an inline method with external linkage}}
+  }
+};
+
+static inline void useStaticFromStatic () {
+  // No warnings.
+  staticFunction();
+  (void)staticVar;
+  (void)constVar;
+  anonFunction();
+  (void)anonVar;
+  (void)anonConstVar;
+  (void)Anon::var;
+  (void)Anon::constVar;
+}
+
+namespace {
+  inline void useStaticFromAnon() {
+    // No warnings.
+    staticFunction();
+    (void)staticVar;
+    (void)constVar;
+    anonFunction();
+    (void)anonVar;
+    (void)anonConstVar;
+    (void)Anon::var;
+    (void)Anon::constVar;
+  }
+}
+
+#else
+// -------
+// This is the main source file.
+// -------
+
+#define INCLUDE
+#include "inline.cpp"
+
 // Check that we don't allow illegal uses of inline
 // (checking C++-only constructs here)
 struct c {inline int a;}; // expected-error{{'inline' can only appear on functions}}
+
+// Check that the warnings from the "header file" aren't on by default in
+// the main source file.
+
+inline int useStaticMainFile () {
+  anonFunction(); // no-warning
+  return staticVar; // no-warning
+}
+
+// Check that the warnings show up when explicitly requested.
+
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Winternal-linkage-in-inline"
+
+inline int useStaticAgain () { // expected-note 2 {{use 'static' to give inline function 'useStaticAgain' internal linkage}}
+  anonFunction(); // expected-warning{{function 'anonFunction' is in an anonymous namespace but is used in an inline function with external linkage}}
+  return staticVar; // expected-warning{{variable 'staticVar' has internal linkage but is used in an inline function with external linkage}}
+}
+
+#pragma clang diagnostic pop
+
+#endif