diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 1d780de..8d37224 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3562,6 +3562,7 @@ public:
 
   NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
                                    SourceLocation UsingLoc,
+                                   SourceLocation DeclEnd,
                                    CXXScopeSpec &SS,
                                    const DeclarationNameInfo &NameInfo,
                                    AttributeList *AttrList,
@@ -3575,6 +3576,7 @@ public:
                               AccessSpecifier AS,
                               bool HasUsingKeyword,
                               SourceLocation UsingLoc,
+                              SourceLocation DeclEnd,
                               CXXScopeSpec &SS,
                               UnqualifiedId &Name,
                               AttributeList *AttrList,
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 940ecc1..f533b33 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -610,8 +610,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
                                          TypeAlias);
   }
 
-  return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
-                                       Name, Attrs.getList(),
+  return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc,
+                                       DeclEnd, SS, Name, Attrs.getList(),
                                        IsTypeName, TypenameLoc);
 }
 
@@ -1971,7 +1971,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
         return;
 
       Actions.ActOnUsingDeclaration(getCurScope(), AS,
-                                    false, SourceLocation(),
+                                    false, SourceLocation(), SourceLocation(),
                                     SS, Name,
                                     /* AttrList */ 0,
                                     /* IsTypeName */ false,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e42d249..98a66a9 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -6725,6 +6725,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
                                   AccessSpecifier AS,
                                   bool HasUsingKeyword,
                                   SourceLocation UsingLoc,
+                                  SourceLocation DeclEnd,
                                   CXXScopeSpec &SS,
                                   UnqualifiedId &Name,
                                   AttributeList *AttrList,
@@ -6786,7 +6787,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
       DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
     return 0;
 
-  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
+  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, DeclEnd, SS,
                                         TargetNameInfo, AttrList,
                                         /* IsInstantiation */ false,
                                         IsTypeName, TypenameLoc);
@@ -7024,6 +7025,30 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
   // be possible for this to happen, because...?
 }
 
+class UsingValidatorCCC : public CorrectionCandidateCallback {
+public:
+  UsingValidatorCCC(bool IsTypeName, bool IsInstantiation)
+      : IsTypeName(IsTypeName), IsInstantiation(IsInstantiation) {}
+  
+  virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+    if (NamedDecl *ND = Candidate.getCorrectionDecl()) {
+      if (isa<NamespaceDecl>(ND))
+        return false;
+      else if (isa<TypeDecl>(ND))
+        return IsTypeName || !IsInstantiation;
+      else
+        return !IsTypeName;
+    } else {
+      // Keywords are not valid here.
+      return false;
+    }
+  }
+
+private:
+  bool IsTypeName;
+  bool IsInstantiation;
+};
+
 /// Builds a using declaration.
 ///
 /// \param IsInstantiation - Whether this call arises from an
@@ -7031,6 +7056,7 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
 ///   the lookup differently for these declarations.
 NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
                                        SourceLocation UsingLoc,
+                                       SourceLocation DeclEnd,
                                        CXXScopeSpec &SS,
                                        const DeclarationNameInfo &NameInfo,
                                        AttributeList *AttrList,
@@ -7133,11 +7159,55 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
 
   LookupQualifiedName(R, LookupContext);
 
+  // Try to correct typos if possible.
   if (R.empty()) {
-    Diag(IdentLoc, diag::err_no_member) 
-      << NameInfo.getName() << LookupContext << SS.getRange();
-    UD->setInvalidDecl();
-    return UD;
+    UsingValidatorCCC CCC(IsTypeName, IsInstantiation);
+    if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
+                                               R.getLookupKind(), S, &SS, CCC)){
+      if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+        std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+        std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+        bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+                                R.getLookupName().getAsString() == CorrectedStr;
+        if (!droppedSpecifier) {
+          R.setLookupName(Corrected.getCorrection());
+          R.addDecl(ND);
+          Diag(R.getNameLoc(), diag::err_no_member_suggest)
+            << NameInfo.getName() << LookupContext << droppedSpecifier
+            << CorrectedQuotedStr << SS.getRange()
+            << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
+                                            CorrectedStr);
+          Diag(ND->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+        } else {
+          // Remove the 'using' decl, since we're suggesting the use of an
+          // identifier with its specifier dropped. Some callers may not give
+          // us the location of the end of the decl (eg, instantiations and
+          // some class members), so we'll check whether we can provide a
+          // valid FixItHint.
+          if (DeclEnd.isValid())
+            Diag(R.getNameLoc(), diag::err_no_member_suggest)
+              << NameInfo.getName() << LookupContext << droppedSpecifier
+              << CorrectedQuotedStr << SS.getRange()
+              << FixItHint::CreateRemoval(SourceRange(UsingLoc, DeclEnd));
+          else
+            Diag(R.getNameLoc(), diag::err_no_member_suggest)
+              << NameInfo.getName() << LookupContext << droppedSpecifier
+              << CorrectedQuotedStr << SS.getRange();
+          Diag(ND->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+          UD->setInvalidDecl();
+          return UD;
+        }
+      }
+    }
+
+    if (R.empty()) {
+      Diag(IdentLoc, diag::err_no_member) 
+        << NameInfo.getName() << LookupContext << SS.getRange();
+      UD->setInvalidDecl();
+      return UD;
+    }
   }
 
   if (R.isAmbiguous()) {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index df38615..b30aa3a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2195,8 +2195,8 @@ Decl * TemplateDeclInstantiator
   DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
   NamedDecl *UD =
     SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
-                                  D->getUsingLoc(), SS, NameInfo, 0,
-                                  /*instantiation*/ true,
+                                  D->getUsingLoc(), SourceLocation(), SS,
+                                  NameInfo, 0, /*instantiation*/ true,
                                   /*typename*/ true, D->getTypenameLoc());
   if (UD)
     SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
@@ -2219,8 +2219,8 @@ Decl * TemplateDeclInstantiator
 
   NamedDecl *UD =
     SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
-                                  D->getUsingLoc(), SS, NameInfo, 0,
-                                  /*instantiation*/ true,
+                                  D->getUsingLoc(), SourceLocation(), SS,
+                                  NameInfo, 0, /*instantiation*/ true,
                                   /*typename*/ false, SourceLocation());
   if (UD)
     SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
diff --git a/test/FixIt/typo-using.cpp b/test/FixIt/typo-using.cpp
new file mode 100644
index 0000000..79b70de
--- /dev/null
+++ b/test/FixIt/typo-using.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: cp %s %t
+// RUN: not %clang_cc1 -fsyntax-only -fixit -x c++ %t
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Werror -x c++ %t
+// RUN: grep using_suggestion_tyname_ty_dropped_specifier %t
+
+// These tests have been separated from typo.cpp to keep the maximum typo
+// correction counter from ticking over; this causes spurious failures.
+
+namespace using_suggestion_ty {
+namespace N { class AAA {}; } // expected-note {{'AAA' declared here}}
+using N::AAB; // expected-error {{no member named 'AAB' in namespace 'using_suggestion_ty::N'; did you mean 'AAA'?}}
+}
+
+namespace using_suggestion_tyname_ty {
+namespace N { class AAA {}; } // expected-note {{'AAA' declared here}}
+using typename N::AAB; // expected-error {{no member named 'AAB' in namespace 'using_suggestion_tyname_ty::N'; did you mean 'AAA'?}}
+}
+
+namespace using_suggestion_val {
+namespace N { void FFF() {} } // expected-note {{'FFF' declared here}}
+using N::FFG; // expected-error {{no member named 'FFG' in namespace 'using_suggestion_val::N'; did you mean 'FFF'?}}
+}
+
+namespace using_suggestion_ty_dropped_specifier {
+class AAA {}; // expected-note {{'AAA' declared here}}
+namespace N { }
+using N::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_ty_dropped_specifier::N'; did you mean simply 'AAA'?}}
+}
+
+namespace using_suggestion_tyname_ty_dropped_specifier {
+class AAA {}; // expected-note {{'AAA' declared here}}
+namespace N { }
+using typename N::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_tyname_ty_dropped_specifier::N'; did you mean simply 'AAA'?}}
+}
+
+namespace using_suggestion_val_dropped_specifier {
+void FFF() {} // expected-note {{'FFF' declared here}}
+namespace N { }
+using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean simply 'FFF'?}}
+}
+
+namespace using_suggestion_member_ty {
+class CCC { public: typedef int AAA; }; // expected-note {{'AAA' declared here}}
+class DDD : public CCC { public: using CCC::AAB; }; // expected-error {{no member named 'AAB' in 'using_suggestion_member_ty::CCC'; did you mean 'AAA'?}}
+}
+
+namespace using_suggestion_member_val {
+class CCC { public: void AAA() { } }; // expected-note {{'AAA' declared here}}
+class DDD : public CCC { public: using CCC::AAB; }; // expected-error {{no member named 'AAB' in 'using_suggestion_member_val::CCC'; did you mean 'AAA'?}}
+}
+
+namespace using_suggestion_member_tyname_ty {
+class CCC { public: typedef int AAA; }; // expected-note {{'AAA' declared here}}
+class DDD : public CCC { public: using typename CCC::AAB; }; // expected-error {{no member named 'AAB' in 'using_suggestion_member_tyname_ty::CCC'; did you mean 'AAA'?}}
+}
diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp
index ebe97f6..48e4eed 100644
--- a/test/SemaCXX/using-decl-1.cpp
+++ b/test/SemaCXX/using-decl-1.cpp
@@ -118,3 +118,47 @@ namespace foo
     using ::foo::Class1::Function; // expected-error{{incomplete type 'foo::Class1' named in nested name specifier}}
   };
 }
+
+// Don't suggest non-typenames for positions requiring typenames.
+namespace using_suggestion_tyname_val {
+namespace N { void FFF() {} }
+using typename N::FFG; // expected-error {{no member named 'FFG' in namespace 'using_suggestion_tyname_val::N'}}
+}
+
+namespace using_suggestion_member_tyname_val {
+class CCC { public: void AAA() { } };
+class DDD : public CCC { public: using typename CCC::AAB; }; // expected-error {{no member named 'AAB' in 'using_suggestion_member_tyname_val::CCC'}}
+}
+
+namespace using_suggestion_tyname_val_dropped_specifier {
+void FFF() {}
+namespace N { }
+using typename N::FFG; // expected-error {{no member named 'FFG' in namespace 'using_suggestion_tyname_val_dropped_specifier::N'}}
+}
+
+// Currently hints aren't provided to drop out the incorrect M::.
+namespace using_suggestion_ty_dropped_nested_specifier {
+namespace N {
+class AAA {};
+namespace M { }
+}
+using N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_ty_dropped_nested_specifier::N::M'}}
+}
+
+namespace using_suggestion_tyname_ty_dropped_nested_specifier {
+namespace N {
+class AAA {};
+namespace M { }
+}
+using typename N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_tyname_ty_dropped_nested_specifier::N::M'}}
+}
+
+namespace using_suggestion_val_dropped_nested_specifier {
+namespace N {
+void FFF() {}
+namespace M { }
+}
+using N::M::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_nested_specifier::N::M'}}
+}
+
+
