Add a getLanguageLinkage method to VarDecls and FunctionDecls. Use it to fix
some cases where functions with no language linkage were being treated as having
C language linkage. In particular, don't warn in

extern "C" {
  static NonPod foo();
}

Since getLanguageLinkage checks the language linkage, the linkage computation
cannot use the language linkage. Break the loop by checking just the context
in the linkage computation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175117 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7c31be6..9c7fb6b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2065,6 +2065,22 @@
   return ABIDefaultCC == CC;
 }
 
+template<typename T>
+bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
+  const DeclContext *DC = Old->getDeclContext();
+  if (DC->isRecord())
+    return false;
+
+  LanguageLinkage OldLinkage = Old->getLanguageLinkage();
+  if (OldLinkage == CXXLanguageLinkage &&
+      New->getDeclContext()->isExternCContext())
+    return true;
+  if (OldLinkage == CLanguageLinkage &&
+      New->getDeclContext()->isExternCXXContext())
+    return true;
+  return false;
+}
+
 /// MergeFunctionDecl - We just parsed a function 'New' from
 /// declarator D which has the same name and scope as a previous
 /// declaration 'Old'.  Figure out how to resolve this situation,
@@ -2366,7 +2382,7 @@
       assert(OldQTypeForComparison.isCanonical());
     }
 
-    if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) {
+    if (haveIncompatibleLanguageLinkages(Old, New)) {
       Diag(New->getLocation(), diag::err_different_language_linkage) << New;
       Diag(Old->getLocation(), PrevDiag);
       return true;
@@ -2756,7 +2772,7 @@
     return;
   }
 
-  if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) {
+  if (haveIncompatibleLanguageLinkages(Old, New)) {
     Diag(New->getLocation(), diag::err_different_language_linkage) << New;
     Diag(Old->getLocation(), diag::note_previous_definition);
     New->setInvalidDecl();