diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 9e3ca9d..dce9aa6 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -864,6 +864,17 @@ static bool checkArgPlaceholdersForOverload(Sema &S,
   return false;
 }
 
+enum TryToOverloadResult {
+  TTO_Overload,               // Decl pair is an overload.
+  TTO_Redeclaration,          // Decl pair is a redeclaration.
+  TTO_RedeclarationIfExternC  // Decl pair is a redeclaration if the second decl
+                              // is extern C.
+};
+
+static TryToOverloadResult isOverload(Sema &S, FunctionDecl *New,
+                                      FunctionDecl *Old,
+                                      bool UseUsingDeclRules);
+
 // IsOverload - Determine whether the given New declaration is an
 // overload of the declarations in Old. This routine returns false if
 // New and Old cannot be overloaded, e.g., if New has the same
@@ -901,6 +912,8 @@ static bool checkArgPlaceholdersForOverload(Sema &S,
 Sema::OverloadKind
 Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
                     NamedDecl *&Match, bool NewIsUsingDecl) {
+  Match = NULL;
+
   for (LookupResult::iterator I = Old.begin(), E = Old.end();
          I != E; ++I) {
     NamedDecl *OldD = *I;
@@ -936,16 +949,21 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
         return Ovl_Match;
       }
     } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
-      if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
+      TryToOverloadResult TTO =
+          isOverload(*this, New, OldF, UseMemberUsingDeclRules);
+      if (TTO != TTO_Overload) {
         if (UseMemberUsingDeclRules && OldIsUsingDecl) {
           HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
           continue;
         }
 
+        Match = *I;
+        if (TTO == TTO_RedeclarationIfExternC)
+          continue;
+
         if (!shouldLinkPossiblyHiddenDecl(*I, New))
           continue;
 
-        Match = *I;
         return Ovl_Match;
       }
     } else if (isa<UsingDecl>(OldD)) {
@@ -967,6 +985,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
     }
   }
 
+  // It is now safe to use code that computes the linkage of New. In particular
+  // it is safe to call isExternC. If we found no decl that New would be a
+  // redeclaration of, we know that there is no previous static decl that would
+  // give it internal linkage.
+  if (Match && New->isExternC())
+    return Ovl_Match;
+
   return Ovl_Overload;
 }
 
@@ -983,8 +1008,33 @@ static bool canBeOverloaded(const FunctionDecl &D) {
   return true;
 }
 
-static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
-                                bool UseUsingDeclRules) {
+static TryToOverloadResult
+mayConflictBecauseOfExternC(const Sema &S, const FunctionDecl *New,
+                            const FunctionDecl *Old) {
+  if (!S.getLangOpts().CPlusPlus)
+    return TTO_Overload;
+
+  // Like in C, no conflict if both have the overloadable attribute.
+  if (Old->hasAttr<OverloadableAttr>() && New->hasAttr<OverloadableAttr>())
+    return TTO_Overload;
+
+  // [dcl.link] p6
+  // An entity with C language linkage shall not be declared with
+  // the same name as an entity in global scope, unless both declarations denote
+  // the same entity
+  if (Old->isExternC() &&
+      New->getDeclContext()->getRedeclContext()->isTranslationUnit())
+    return TTO_Redeclaration;
+
+  if (Old->getDeclContext()->getRedeclContext()->isTranslationUnit())
+    return TTO_RedeclarationIfExternC;
+
+  return TTO_Overload;
+}
+
+static TryToOverloadResult shouldTryToOverload(Sema &S, FunctionDecl *New,
+                                               FunctionDecl *Old,
+                                               bool UseUsingDeclRules) {
   FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
   FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
 
@@ -992,7 +1042,7 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
   //   A function template can be overloaded with other function templates
   //   and with normal (non-template) functions.
   if ((OldTemplate == 0) != (NewTemplate == 0))
-    return true;
+    return TTO_Overload;
 
   // Is the function New an overload of the function Old?
   QualType OldQType = S.Context.getCanonicalType(Old->getType());
@@ -1006,7 +1056,11 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
   // prototype), then we consider them to have matching signatures.
   if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
       isa<FunctionNoProtoType>(NewQType.getTypePtr()))
-    return false;
+    return TTO_Redeclaration;
+
+  TryToOverloadResult Ret = mayConflictBecauseOfExternC(S, New, Old);
+  if (Ret == TTO_Redeclaration)
+    return Ret;
 
   const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
   const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
@@ -1018,7 +1072,7 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
       (OldType->getNumArgs() != NewType->getNumArgs() ||
        OldType->isVariadic() != NewType->isVariadic() ||
        !S.FunctionArgTypesAreEqual(OldType, NewType)))
-    return true;
+    return Ret;
 
   // C++ [temp.over.link]p4:
   //   The signature of a function template consists of its function
@@ -1037,7 +1091,7 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
                                          OldTemplate->getTemplateParameters(),
                                          false, S.TPL_TemplateMatch) ||
        OldType->getResultType() != NewType->getResultType()))
-    return true;
+    return Ret;
 
   // If the function is a class member, its signature includes the
   // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself.
@@ -1065,7 +1119,7 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
           << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
         S.Diag(OldMethod->getLocation(), diag::note_previous_declaration);
       }
-      return true;
+      return Ret;
     }
 
     // We may not have applied the implicit const for a constexpr member
@@ -1076,24 +1130,39 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
     if (NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod))
       NewQuals |= Qualifiers::Const;
     if (OldMethod->getTypeQualifiers() != NewQuals)
-      return true;
+      return Ret;
   }
 
   // The signatures match; this is not an overload.
-  return false;
+  return TTO_Redeclaration;
 }
 
-bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
-                      bool UseUsingDeclRules) {
-  if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules))
-    return false;
+static TryToOverloadResult isOverload(Sema &S, FunctionDecl *New,
+                                      FunctionDecl *Old,
+                                      bool UseUsingDeclRules) {
+  TryToOverloadResult TTO = shouldTryToOverload(S, New, Old, UseUsingDeclRules);
+  if (TTO == TTO_Redeclaration)
+    return TTO;
 
   // If both of the functions are extern "C", then they are not
   // overloads.
   if (!canBeOverloaded(*Old) && !canBeOverloaded(*New))
-    return false;
+    return TTO_Redeclaration;
 
-  return true;
+  return TTO;
+}
+
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
+                      bool UseUsingDeclRules) {
+  TryToOverloadResult TTO = isOverload(*this, New, Old, UseUsingDeclRules);
+  switch (TTO) {
+  case TTO_Redeclaration:
+    return false;
+  case TTO_Overload:
+    return true;
+  case TTO_RedeclarationIfExternC:
+    return !New->isExternC();
+  }
 }
 
 /// \brief Checks availability of the function depending on the current
diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp
index fc14081..01a03ae 100644
--- a/test/SemaCXX/linkage-spec.cpp
+++ b/test/SemaCXX/linkage-spec.cpp
@@ -41,15 +41,14 @@ namespace pr5430 {
 using namespace pr5430;
 extern "C" void pr5430::func(void) { }
 
-// PR5404
-int f2(char *)
+int f2(char *) // expected-note {{previous definition is here}}
 {
         return 0;
 }
 
 extern "C"
 {
-    int f2(int)
+    int f2(int) // expected-error {{declaration of 'f2' has a different language linkage}}
     {
         return f2((char *)0);
     }
diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp
index a811575..bca9c1e 100644
--- a/test/SemaCXX/linkage2.cpp
+++ b/test/SemaCXX/linkage2.cpp
@@ -201,3 +201,29 @@ namespace test18 {
   }
   void *h() { return f(); }
 }
+
+extern "C" void pr16247_foo(int); // expected-note {{previous declaration is here}}
+static void pr16247_foo(double); // expected-error {{static declaration of 'pr16247_foo' follows non-static declaration}}
+void pr16247_foo(int) { } // expected-note {{previous definition is here}}
+void pr16247_foo(double) {} // expected-error {{conflicting types for 'pr16247_foo'}}
+
+extern "C" void pr16247_foo2(int); // expected-note {{previous declaration is here}}
+extern "C++" void pr16247_foo2(double); // expected-error {{declaration of 'pr16247_foo2' has a different language linkage}}
+
+extern "C++" void pr16247_foo3(double); // expected-note {{previous declaration is here}}
+extern "C" void pr16247_foo3(int); // expected-error {{declaration of 'pr16247_foo3' has a different language linkage}}
+
+extern "C" {
+  static void pr16247_foo4(int x);
+  static void pr16247_foo4() {
+  }
+  void pr16247_foo4(int x) {
+  }
+}
+
+extern "C" {
+  static void pr16247_foo5() { // expected-note {{previous definition is here}}
+  }
+  void pr16247_foo5(int x) { // expected-error {{conflicting types for 'pr16247_foo5'}}
+  }
+}
