diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 39bd5ac..cffaf4e 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -200,6 +200,9 @@ def warn_decl_shadow :
           "static data member of %2|"
           "field of %2}1">,
   InGroup<Shadow>, DefaultIgnore;
+def warn_function_shadows_tag_type : Warning<
+  "function %0 shadows %1 %0; uses of %1 %0 will require %select{a|an}2 '%1' tag">,
+  InGroup<Shadow>, DefaultIgnore;
 
 // C++ using declarations
 def err_using_requires_qualname : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 31c410a..ade3df9 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1118,7 +1118,7 @@ public:
   // Returns true if the variable declaration is a redeclaration
   bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
   void CheckCompleteVariableDeclaration(VarDecl *var);
-  void ActOnStartFunctionDeclarator();
+  void ActOnStartFunctionDeclarator(Scope *S, Declarator &D);
   void ActOnEndFunctionDeclarator();
   NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                      TypeSourceInfo *TInfo,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0851941..ca2d312 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4136,7 +4136,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
   ParsedAttributes FnAttrs(AttrFactory);
   ParsedType TrailingReturnType;
 
-  Actions.ActOnStartFunctionDeclarator();
+  Actions.ActOnStartFunctionDeclarator(getCurScope(), D);
 
   SourceLocation EndLoc;
   if (isFunctionDeclaratorIdentifierList()) {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f54f0fd..d3f073a 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1264,7 +1264,23 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
   }
 }
 
-void Sema::ActOnStartFunctionDeclarator() {
+void Sema::ActOnStartFunctionDeclarator(Scope *S, Declarator &D) {
+  IdentifierInfo *Name = D.getIdentifier();
+  LookupResult R(*this, DeclarationNameInfo(Name, D.getIdentifierLoc()),
+                 Sema::LookupTagName);
+  if (LookupName(R, S)) {
+    for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) {
+      if ((*I)->getDeclContext() != getCurLexicalContext())
+        continue;
+      if (TagDecl *TD = dyn_cast<TagDecl>(*I)) {
+        Diag(D.getIdentifierLoc(), diag::warn_function_shadows_tag_type)
+            << Name << TD->getKindName()
+            << (TD->getKind() == Decl::Enum ? 1 : 0);
+        Diag(TD->getLocStart(), diag::note_previous_decl) << Name;
+      }
+    }
+  }
+
   ++InFunctionDeclarator;
 }
 
diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp
index 68e9467..da43e67 100644
--- a/test/SemaCXX/warn-shadow.cpp
+++ b/test/SemaCXX/warn-shadow.cpp
@@ -81,3 +81,18 @@ void rdar8883302() {
 void test8() {
   int bob; // expected-warning {{declaration shadows a variable in the global namespace}}
 }
+
+namespace TagShadow {
+class Foo {
+ public:
+  enum Bar { X, Y }; // expected-note {{'Bar' declared here}}
+  void SetBar(Bar bar);
+  Bar Bar(); // expected-warning {{function 'Bar' shadows enum 'Bar'; uses of enum 'Bar' will require an 'enum' tag}}
+};
+class Fiz {
+ public:
+  struct Bin { int X; int Y; }; // expected-note {{'Bin' declared here}}
+  void SetBin(Bin bin);
+  Bin Bin(); // expected-warning {{function 'Bin' shadows struct 'Bin'; uses of struct 'Bin' will require a 'struct' tag}}
+};
+}
