diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index cbce757..9d127c0 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
 
 #include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Type.h"
 #include "clang/Sema/Weak.h"
 #include "llvm/ADT/MapVector.h"
 #include <utility>
@@ -177,6 +178,19 @@ public:
                  SmallVectorImpl<std::pair<ValueDecl *, 
                                            SourceLocation> > &Pending) {}
 
+
+  /// \brief Produces a diagnostic note if the external source contains a
+  /// complete definition for T.
+  ///
+  /// \param Loc the location at which a complete type was required but not
+  /// provided
+  ///
+  /// \param T the QualType that should have been complete at Loc
+  ///
+  /// \return true if a diagnostic was produced, false otherwise.
+  virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T)
+    { return false; }
+
   // isa/cast/dyn_cast support
   static bool classof(const ExternalASTSource *Source) {
     return Source->SemaSource;
diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index ff87d05..9c5e4d5 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -322,6 +322,8 @@ public:
   virtual void ReadPendingInstantiations(
               SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending);
 
+  virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T);
+
   // isa/cast/dyn_cast support
   static bool classof(const MultiplexExternalSemaSource*) { return true; }
   //static bool classof(const ExternalSemaSource*) { return true; }
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index d85624b..6fc0be6 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -267,3 +267,12 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
   for(size_t i = 0; i < Sources.size(); ++i)
     Sources[i]->ReadPendingInstantiations(Pending);
 }
+
+bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType(
+    SourceLocation Loc, QualType T) {
+  for (size_t I = 0, E = Sources.size(); I < E; ++I) {
+    if (Sources[I]->MaybeDiagnoseMissingCompleteType(Loc, T))
+      return true;
+  }
+  return false;
+}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index f7a7e61..ab810e1 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -5009,6 +5009,11 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
   if (IFace && !IFace->getDecl()->isInvalidDecl())
     Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
 
+  // If we have external information that we can use to suggest a fix,
+  // produce a note.
+  if (ExternalSource)
+    ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
+
   return true;
 }
 
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index fed775e..479b36f 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -19,4 +19,5 @@ if(CLANG_ENABLE_REWRITER)
   add_subdirectory(AST)
   add_subdirectory(Tooling)
   add_subdirectory(Format)
+  add_subdirectory(Sema)
 endif()
diff --git a/unittests/Makefile b/unittests/Makefile
index e01a6ac..542863e 100644
--- a/unittests/Makefile
+++ b/unittests/Makefile
@@ -23,7 +23,7 @@ PARALLEL_DIRS += Format
 endif
 
 ifeq ($(ENABLE_CLANG_REWRITER),1)
-PARALLEL_DIRS += ASTMatchers AST Tooling
+PARALLEL_DIRS += ASTMatchers AST Tooling Sema
 endif
 
 ifeq ($(ENABLE_CLANG_STATIC_ANALYZER),1)
diff --git a/unittests/Sema/CMakeLists.txt b/unittests/Sema/CMakeLists.txt
new file mode 100644
index 0000000..d491655
--- /dev/null
+++ b/unittests/Sema/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_clang_unittest(SemaTests
+  ExternalSemaSourceTest.cpp
+  )
+
+target_link_libraries(SemaTests
+  clangAST clangASTMatchers clangTooling
+  )
diff --git a/unittests/Sema/ExternalSemaSourceTest.cpp b/unittests/Sema/ExternalSemaSourceTest.cpp
new file mode 100644
index 0000000..bff8475
--- /dev/null
+++ b/unittests/Sema/ExternalSemaSourceTest.cpp
@@ -0,0 +1,100 @@
+//=== unittests/Sema/ExternalSemaSourceTest.cpp - ExternalSemaSource tests ===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::tooling;
+
+namespace {
+
+class CompleteTypeDiagnoser : public clang::ExternalSemaSource {
+public:
+  CompleteTypeDiagnoser(bool MockResult) : CallCount(0), Result(MockResult) {}
+
+  virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation L, QualType T) {
+    ++CallCount;
+    return Result;
+  }
+
+  int CallCount;
+  bool Result;
+};
+
+class ExternalSemaSourceInstaller : public clang::ASTFrontendAction {
+protected:
+  virtual clang::ASTConsumer *
+  CreateASTConsumer(clang::CompilerInstance &Compiler,
+                    llvm::StringRef /* dummy */) {
+    return new clang::ASTConsumer();
+  }
+
+  virtual void ExecuteAction() {
+    CompilerInstance &CI = getCompilerInstance();
+    ASSERT_FALSE(CI.hasSema());
+    CI.createSema(getTranslationUnitKind(), NULL);
+    for (size_t I = 0, E = Sources.size(); I < E; ++I)
+      CI.getSema().addExternalSource(Sources[I]);
+    ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
+             CI.getFrontendOpts().SkipFunctionBodies);
+  }
+
+public:
+  void PushSource(clang::ExternalSemaSource *Source) {
+    Sources.push_back(Source);
+  }
+
+private:
+  std::vector<clang::ExternalSemaSource *> Sources;
+};
+
+// We should only try MaybeDiagnoseMissingCompleteType if we can't otherwise
+// solve the problem.
+TEST(ExternalSemaSource, TryOtherTacticsBeforeDiagnosing) {
+  llvm::OwningPtr<ExternalSemaSourceInstaller> Installer(
+      new ExternalSemaSourceInstaller);
+  CompleteTypeDiagnoser Diagnoser(false);
+  Installer->PushSource(&Diagnoser);
+  std::vector<std::string> Args(1, "-std=c++11");
+  // This code hits the class template specialization/class member of a class
+  // template specialization checks in Sema::RequireCompleteTypeImpl.
+  ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
+      Installer.take(),
+      "template <typename T> struct S { class C { }; }; S<char>::C SCInst;",
+      Args));
+  ASSERT_EQ(0, Diagnoser.CallCount);
+}
+
+// The first ExternalSemaSource where MaybeDiagnoseMissingCompleteType returns
+// true should be the last one called.
+TEST(ExternalSemaSource, FirstDiagnoserTaken) {
+  llvm::OwningPtr<ExternalSemaSourceInstaller> Installer(
+      new ExternalSemaSourceInstaller);
+  CompleteTypeDiagnoser First(false);
+  CompleteTypeDiagnoser Second(true);
+  CompleteTypeDiagnoser Third(true);
+  Installer->PushSource(&First);
+  Installer->PushSource(&Second);
+  Installer->PushSource(&Third);
+  std::vector<std::string> Args(1, "-std=c++11");
+  ASSERT_FALSE(clang::tooling::runToolOnCodeWithArgs(
+      Installer.take(), "class Incomplete; Incomplete IncompleteInstance;",
+      Args));
+  ASSERT_EQ(1, First.CallCount);
+  ASSERT_EQ(1, Second.CallCount);
+  ASSERT_EQ(0, Third.CallCount);
+}
+
+} // anonymous namespace
diff --git a/unittests/Sema/Makefile b/unittests/Sema/Makefile
new file mode 100644
index 0000000..cd1d93d
--- /dev/null
+++ b/unittests/Sema/Makefile
@@ -0,0 +1,19 @@
+##===- unittests/Sema/Makefile -----------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL = ../..
+TESTNAME = Sema
+include $(CLANG_LEVEL)/../../Makefile.config
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+           clangRewriteCore.a clangRewriteFrontend.a \
+           clangParse.a clangSema.a clangAnalysis.a \
+           clangEdit.a clangAST.a clangASTMatchers.a clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
