I've reworked this to do the check in CorrectTypo as suggested.  This is just 
a partial post, as I've omitted needed changes to other tests so we can focus 
on the key parts.  I basically would like to know if this is the right 
approach, and what needs to be done to make it right/better.

  Question: I saw that there was some code for handling missing imports, but I 
couldn't see where it searched the global module index, and my new test case 
(with the new code disabled) didn't trigger it.  Was it just for some special 
cases?

  Thanks.

  -John

Hi doug.gregor, rsmith,

http://llvm-reviews.chandlerc.com/D2671

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2671?vs=6814&id=8146#toc

Files:
  include/clang/Frontend/CompilerInstance.h
  include/clang/Frontend/ASTUnit.h
  include/clang/Basic/LangOptions.def
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Lex/ModuleLoader.h
  include/clang/Lex/HeaderSearch.h
  include/clang/Driver/Options.td
  include/clang/Serialization/ASTReader.h
  include/clang/Serialization/GlobalModuleIndex.h
  lib/Frontend/CompilerInstance.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Sema/SemaLookup.cpp
  lib/Lex/HeaderSearch.cpp
  lib/Serialization/GlobalModuleIndex.cpp
  test/Modules/undefined-type-fixit1.cpp
  test/Modules/Inputs/undefined-type-fixit/public2sub.h
  test/Modules/Inputs/undefined-type-fixit/module.map
  test/Modules/Inputs/undefined-type-fixit/public1.h
  test/Modules/Inputs/undefined-type-fixit/public2.h
Index: include/clang/Frontend/CompilerInstance.h
===================================================================
--- include/clang/Frontend/CompilerInstance.h
+++ include/clang/Frontend/CompilerInstance.h
@@ -124,6 +124,9 @@
   /// have finished with this translation unit.
   bool BuildGlobalModuleIndex;
 
+  /// \brief We have a full global module index, with all modules.
+  bool HaveFullGlobalModuleIndex;
+
   /// \brief One or more modules failed to build.
   bool ModuleBuildFailed;
 
@@ -683,6 +686,9 @@
 
   /// }
 
+  // Create module manager.
+  void createModuleManager();
+
   ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
                               Module::NameVisibilityKind Visibility,
                               bool IsInclusionDirective) override;
@@ -694,6 +700,8 @@
     return ModuleLoader::HadFatalFailure;
   }
 
+  virtual GlobalModuleIndex *loadGlobalModuleIndex();
+
 };
 
 } // end namespace clang
Index: include/clang/Frontend/ASTUnit.h
===================================================================
--- include/clang/Frontend/ASTUnit.h
+++ include/clang/Frontend/ASTUnit.h
@@ -869,6 +869,8 @@
   void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
                          SourceLocation ImportLoc, bool Complain) override {}
 
+
+  GlobalModuleIndex *loadGlobalModuleIndex() { return 0; }
 };
 
 } // namespace clang
Index: include/clang/Basic/LangOptions.def
===================================================================
--- include/clang/Basic/LangOptions.def
+++ include/clang/Basic/LangOptions.def
@@ -96,6 +96,7 @@
 BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time")
 LANGOPT(Modules           , 1, 0, "modules extension to C")
 LANGOPT(ModulesDeclUse    , 1, 0, "require declaration of module uses")
+LANGOPT(ModulesSearchAll  , 1, 1, "search even non-imported modules to find unresolved references")
 LANGOPT(Optimize          , 1, 0, "__OPTIMIZE__ predefined macro")
 LANGOPT(OptimizeSize      , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
 LANGOPT(Static            , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -213,6 +213,7 @@
 def MismatchedTags : DiagGroup<"mismatched-tags">;
 def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
 def ModuleConflict : DiagGroup<"module-conflict">;
+def NeedImport : DiagGroup<"need-import">;
 def NewlineEOF : DiagGroup<"newline-eof">;
 def NullArithmetic : DiagGroup<"null-arithmetic">;
 def NullCharacter : DiagGroup<"null-character">;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6946,6 +6946,9 @@
   "declaration of %0 must be imported from module '%1' before it is required">;
 def err_module_private_definition : Error<
   "definition of %0 must be imported from module '%1' before it is required">;
+def warn_need_module_import : Warning<
+  "use of identifier '%0' requires import/inclusion of the module '%1'">,
+  InGroup<NeedImport>;
 def err_module_import_in_extern_c : Error<
   "import of C++ module '%0' appears within extern \"C\" language linkage "
   "specification">;
Index: include/clang/Lex/ModuleLoader.h
===================================================================
--- include/clang/Lex/ModuleLoader.h
+++ include/clang/Lex/ModuleLoader.h
@@ -21,6 +21,7 @@
 
 namespace clang {
 
+class GlobalModuleIndex;
 class IdentifierInfo;
 class Module;
 
@@ -88,6 +89,17 @@
                                  SourceLocation ImportLoc,
                                  bool Complain) = 0;
 
+  /// \brief Load, create, or return global module.
+  /// This function returns an existing global module index, if one
+  /// had already been loaded or created, or loads one if it
+  /// exists, or creates one if it doesn't exist.
+  /// Also, importantly, if the index doesn't cover all the modules
+  /// in the module map, it will be update to do so here, because
+  /// of its use in searching for needed module imports and
+  /// associated fixit messages.
+  /// \returns Returns null if load failed.
+  virtual GlobalModuleIndex *loadGlobalModuleIndex() = 0;
+
   bool HadFatalFailure;
 };
   
Index: include/clang/Lex/HeaderSearch.h
===================================================================
--- include/clang/Lex/HeaderSearch.h
+++ include/clang/Lex/HeaderSearch.h
@@ -503,6 +503,13 @@
   /// \returns The module with the given name.
   Module *lookupModule(StringRef ModuleName, bool AllowSearch = true);
 
+  /// \brief Lookup a top level module given its file name.
+  ///
+  /// \param ModuleFileName The name of the module file.
+  ///
+  /// \returns The module with the given name.
+  Module *lookupModuleFromFile(StringRef ModuleFileName);
+
 
   /// \brief Try to find a module map file in the given directory, returning
   /// \c nullptr if none is found.
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -579,6 +579,9 @@
 def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group<i_Group>,
   Flags<[CC1Option]>, MetaVarName<"<seconds>">,
   HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">;
+def fmodules_search_all : Flag <["-"], "fmodules-search-all">, Group<f_Group>,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Search even non-imported modules to resolve references">;
 def fbuild_session_timestamp : Joined<["-"], "fbuild-session-timestamp=">,
   Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<time since Epoch in seconds>">,
   HelpText<"Time when the current build session started">;
@@ -665,6 +668,9 @@
   Flags<[DriverOption]>;
 def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
   Flags<[DriverOption]>;
+def fno_modules_search_all : Flag <["-"], "fno-modules-search-all">, Group<f_Group>,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Inhibit search of non-imported modules to resolve references">;
 def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>;
 def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>;
 def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>;
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -1358,6 +1358,12 @@
   /// \brief Determine whether this AST reader has a global index.
   bool hasGlobalIndex() const { return (bool)GlobalIndex; }
 
+  /// \brief Return global module index.
+  GlobalModuleIndex *getGlobalIndex() { return GlobalIndex.get(); }
+
+  /// \brief Reset reader for a reload try.
+  void resetForReload() { TriedLoadingGlobalIndex = false; }
+
   /// \brief Attempts to load the global index.
   ///
   /// \returns true if loading the global index has failed for any reason.
Index: include/clang/Serialization/GlobalModuleIndex.h
===================================================================
--- include/clang/Serialization/GlobalModuleIndex.h
+++ include/clang/Serialization/GlobalModuleIndex.h
@@ -186,6 +186,9 @@
   /// \brief Print statistics to standard error.
   void printStats();
 
+  /// \brief Print debugging view to standard error.
+  void dump();
+
   /// \brief Write a global index into the given
   ///
   /// \param FileMgr The file manager to use to load module files.
Index: lib/Frontend/CompilerInstance.cpp
===================================================================
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -31,6 +31,7 @@
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/GlobalModuleIndex.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/CrashRecoveryContext.h"
@@ -51,7 +52,8 @@
 
 CompilerInstance::CompilerInstance()
   : Invocation(new CompilerInvocation()), ModuleManager(0),
-    BuildGlobalModuleIndex(false), ModuleBuildFailed(false) {
+    BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false),
+    ModuleBuildFailed(false) {
 }
 
 CompilerInstance::~CompilerInstance() {
@@ -1085,6 +1087,43 @@
   }
 }
 
+void CompilerInstance::createModuleManager() {
+  if (!ModuleManager) {
+    if (!hasASTContext())
+      createASTContext();
+
+    // If we're not recursively building a module, check whether we
+    // need to prune the module cache.
+    if (getSourceManager().getModuleBuildStack().empty() &&
+        getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
+        getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
+      pruneModuleCache(getHeaderSearchOpts());
+    }
+
+    HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
+    std::string Sysroot = HSOpts.Sysroot;
+    const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+    ModuleManager = new ASTReader(getPreprocessor(), *Context,
+                                  Sysroot.empty() ? "" : Sysroot.c_str(),
+                                  PPOpts.DisablePCHValidation,
+                                  /*AllowASTWithCompilerErrors=*/false,
+                                  /*AllowConfigurationMismatch=*/false,
+                                  HSOpts.ModulesValidateSystemHeaders,
+                                  getFrontendOpts().UseGlobalModuleIndex);
+    if (hasASTConsumer()) {
+      ModuleManager->setDeserializationListener(
+        getASTConsumer().GetASTDeserializationListener());
+      getASTContext().setASTMutationListener(
+        getASTConsumer().GetASTMutationListener());
+    }
+    getASTContext().setExternalSource(ModuleManager);
+    if (hasSema())
+      ModuleManager->InitializeSema(getSema());
+    if (hasASTConsumer())
+      ModuleManager->StartTranslationUnit(&getASTConsumer());
+  }
+}
+
 ModuleLoadResult
 CompilerInstance::loadModule(SourceLocation ImportLoc,
                              ModuleIdPath Path,
@@ -1131,40 +1170,8 @@
     std::string ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
 
     // If we don't already have an ASTReader, create one now.
-    if (!ModuleManager) {
-      if (!hasASTContext())
-        createASTContext();
-
-      // If we're not recursively building a module, check whether we
-      // need to prune the module cache.
-      if (getSourceManager().getModuleBuildStack().empty() &&
-          getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
-          getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
-        pruneModuleCache(getHeaderSearchOpts());
-      }
-
-      HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
-      std::string Sysroot = HSOpts.Sysroot;
-      const PreprocessorOptions &PPOpts = getPreprocessorOpts();
-      ModuleManager = new ASTReader(getPreprocessor(), *Context,
-                                    Sysroot.empty() ? "" : Sysroot.c_str(),
-                                    PPOpts.DisablePCHValidation,
-                                    /*AllowASTWithCompilerErrors=*/false,
-                                    /*AllowConfigurationMismatch=*/false,
-                                    HSOpts.ModulesValidateSystemHeaders,
-                                    getFrontendOpts().UseGlobalModuleIndex);
-      if (hasASTConsumer()) {
-        ModuleManager->setDeserializationListener(
-          getASTConsumer().GetASTDeserializationListener());
-        getASTContext().setASTMutationListener(
-          getASTConsumer().GetASTMutationListener());
-      }
-      getASTContext().setExternalSource(ModuleManager);
-      if (hasSema())
-        ModuleManager->InitializeSema(getSema());
-      if (hasASTConsumer())
-        ModuleManager->StartTranslationUnit(&getASTConsumer());
-    }
+    if (!ModuleManager)
+      createModuleManager();
 
     if (TheDependencyFileGenerator)
       TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
@@ -1391,3 +1398,59 @@
   ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain);
 }
 
+GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex() {
+  if (!ModuleManager)
+    createModuleManager();
+  // Can't do anything if we don't have the module manager.
+  if (!ModuleManager)
+    return 0;
+  // Get an existing global index.  This load it if not already
+  // loaded.
+  ModuleManager->loadGlobalIndex();
+  GlobalModuleIndex *GlobalIndex = ModuleManager->getGlobalIndex();
+  // If the global index doesn't exist, create it.
+  if (!GlobalIndex && shouldBuildGlobalModuleIndex() && hasFileManager() &&
+      hasPreprocessor()) {
+    llvm::sys::fs::create_directories(
+      getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+    GlobalModuleIndex::writeIndex(
+      getFileManager(),
+      getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+    ModuleManager->resetForReload();
+    ModuleManager->loadGlobalIndex();
+    GlobalIndex = ModuleManager->getGlobalIndex();
+  }
+  // For finding modules needing to be imported for fixit messages,
+  // we need to make the global index cover all modules, so we do that here.
+  if (!HaveFullGlobalModuleIndex && GlobalIndex) {
+    ModuleMap &MMap = getPreprocessor().getHeaderSearchInfo().getModuleMap();
+    bool recreateIndex = false;
+    for (ModuleMap::module_iterator I = MMap.module_begin(),
+        E = MMap.module_end(); I != E; ++I) {
+      Module *TheModule = I->second;
+      const FileEntry *Entry = TheModule->getASTFile();
+      if (!Entry) {
+        SourceLocation dummyLoc;
+        SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
+        for (Module *Mod = TheModule; Mod; Mod = Mod->Parent)
+          Path.push_back(std::make_pair(
+				    getPreprocessor().getIdentifierInfo(Mod->Name), Mod->DefinitionLoc));
+          std::reverse(Path.begin(), Path.end());
+		    // Load a module as hidden.  This also adds it to the global index.
+        ModuleLoadResult Result = loadModule(TheModule->DefinitionLoc, Path,
+          Module::Hidden, false);
+        recreateIndex = true;
+      }
+    }
+    if (recreateIndex) {
+      GlobalModuleIndex::writeIndex(
+        getFileManager(),
+        getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+      ModuleManager->resetForReload();
+      ModuleManager->loadGlobalIndex();
+      GlobalIndex = ModuleManager->getGlobalIndex();
+    }
+    HaveFullGlobalModuleIndex = true;
+  }
+  return GlobalIndex;
+}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1343,6 +1343,9 @@
   Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
   Opts.Modules = Args.hasArg(OPT_fmodules);
   Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse);
+  Opts.ModulesSearchAll = Opts.Modules &&
+   (!Args.hasArg(OPT_fno_modules_search_all) ||
+     Args.hasArg(OPT_fmodules_search_all));
   Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
   Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
   Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -23,6 +23,9 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ExternalSemaSource.h"
 #include "clang/Sema/Overload.h"
@@ -32,6 +35,8 @@
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/Sema/TypoCorrection.h"
+#include "clang/Serialization/GlobalModuleIndex.h"
+#include "clang/Serialization/Module.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -4050,10 +4055,60 @@
   if (getLangOpts().AltiVec && Typo->isStr("vector"))
     return TypoCorrection();
 
-  NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
-
   TypoCorrectionConsumer Consumer(*this, Typo);
 
+  // Look for the symbol in non-imported modules.
+  if (getLangOpts().Modules && getLangOpts().ModulesSearchAll) {
+    // Try to find the type in modules via the global module index.
+    ModuleLoader &Loader = PP.getModuleLoader();
+    // Load global module index, or retrieve a previously loaded one.
+    GlobalModuleIndex *GlobalIndex = Loader.loadGlobalModuleIndex();
+
+    // Only if we have a global index.
+    if (GlobalIndex) {
+      GlobalModuleIndex::HitSet FoundModules;
+
+      // Find the modules that reference the identifier.
+      // Note that this only finds top-level modules.
+      // We'll let diagnoseTypo find the actual declaration module.
+      if (GlobalIndex->lookupIdentifier(Typo->getName(), FoundModules)) {
+        TypoCorrection TC(TypoName.getName(), (NestedNameSpecifier *)0, 0);
+        TC.setCorrectionRange(SS, TypoName);
+        // Walk the found modules that reference the identifier.
+        for (GlobalModuleIndex::HitSet::iterator I = FoundModules.begin(),
+            E = FoundModules.end(); I != E; ++I) {
+          ModuleFile *TheModuleFile = *I;
+          // Find the module from the file name.
+          Module *TheModule = PP.getHeaderSearchInfo().lookupModuleFromFile(
+            TheModuleFile->FileName);
+          assert(TheModule && "Should be able to find the module.");
+          // Make the module visible so we can do a name lookup.
+          Loader.makeModuleVisible(TheModule, Module::AllVisible,
+            TypoName.getLoc(), false);
+          // Do a name lookup.
+          LookupResult ModRes(*this, TypoName, LookupKind);
+          LookupPotentialTypoResult(*this, ModRes, Typo, S, SS, MemberContext,
+            EnteringContext, OPT, false);
+          // If we have an exact match, save the decl in the coorection
+          // to let diagnoseTypo do a fixit message.
+          if (ModRes.getResultKind() == LookupResult::Found)
+            TC.setCorrectionDecl(ModRes.getAsSingle<NamedDecl>());
+          // Hide the module again. diagnoseTypo will unhide the decl module.
+          Loader.makeModuleVisible(TheModule, Module::Hidden,
+            TypoName.getLoc(), false);
+        }
+        // If the name lookup found something, we set a flag to tell
+        // diagnoseTypo we have a case of possibly missing module import.
+        if (TC.isResolved()) {
+          TC.setRequiresImport(true);
+          return TC;
+        }
+      }
+    }
+  }
+
+  NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
+
   // If a callback object considers an empty typo correction candidate to be
   // viable, assume it does not do any actual validation of the candidates.
   TypoCorrection EmptyCorrection;
@@ -4127,6 +4182,8 @@
   unsigned TypoLen = Typo->getName().size();
   bool AllowOnlyNNSChanges = TypoLen < 3;
 
+  // FIXME: Can we do this partial match check on modules known but not
+  // imported via the global module index?
   if (IsUnqualifiedLookup || SearchNamespaces) {
     // For unqualified lookup, look through all of the names that we have
     // seen in this translation unit.
@@ -4629,9 +4686,14 @@
     Module *Owner = Def->getOwningModule();
     assert(Owner && "definition of hidden declaration is not in a module");
 
-    Diag(Correction.getCorrectionRange().getBegin(),
-         diag::err_module_private_declaration)
-      << Def << Owner->getFullModuleName();
+    std::string fixit = "#import ";
+    fixit += Owner->Name;
+    SourceLocation TypoLoc = Correction.getCorrectionRange().getBegin();
+    // FIXME: Figure out how to find the right insertion point,
+    // For now we just use the type location.
+    Diag(TypoLoc, diag::warn_need_module_import)
+      << CorrectedStr << Owner->getFullModuleName() <<
+      FixItHint::CreateInsertion(TypoLoc, fixit);
     Diag(Def->getLocation(), diag::note_previous_declaration);
 
     // Recover by implicitly importing this module.
Index: lib/Lex/HeaderSearch.cpp
===================================================================
--- lib/Lex/HeaderSearch.cpp
+++ lib/Lex/HeaderSearch.cpp
@@ -205,6 +205,10 @@
   return Module;
 }
 
+Module *HeaderSearch::lookupModuleFromFile(StringRef ModuleFileName) {
+  return lookupModule(llvm::sys::path::stem(ModuleFileName), false);
+}
+
 //===----------------------------------------------------------------------===//
 // File lookup within a DirectoryLookup scope
 //===----------------------------------------------------------------------===//
Index: lib/Serialization/GlobalModuleIndex.cpp
===================================================================
--- lib/Serialization/GlobalModuleIndex.cpp
+++ lib/Serialization/GlobalModuleIndex.cpp
@@ -342,6 +342,21 @@
   std::fprintf(stderr, "\n");
 }
 
+void GlobalModuleIndex::dump() {
+  std::fprintf(stderr, "*** Global Module Index Dump:\n");
+  std::fprintf(stderr, "Module files:\n");
+  for (llvm::SmallVector<ModuleInfo, 16>::iterator I = Modules.begin(),
+      E = Modules.end(); I != E; ++I) {
+    ModuleInfo *MI = (ModuleInfo*)I;
+    std::fprintf(stderr, "** %s\n", MI->FileName.c_str());
+    if (MI->File)
+      MI->File->dump();
+    else
+      std::fprintf(stderr, "\n");
+  }
+  std::fprintf(stderr, "\n");
+}
+
 //----------------------------------------------------------------------------//
 // Global module index writer.
 //----------------------------------------------------------------------------//
Index: test/Modules/undefined-type-fixit1.cpp
===================================================================
--- test/Modules/undefined-type-fixit1.cpp
+++ test/Modules/undefined-type-fixit1.cpp
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -I %S/Inputs/undefined-type-fixit %s -verify
+
+//#include "public1.h"
+#include "public2.h"
+#include "public2sub.h"
+
+use_this1 client_variable1; // expected-warning {{use of identifier 'use_this1' requires import/inclusion of the module 'public1'}}
+use_this2 client_variable2;
+use_this2sub client_variable2sub;
+
+// expected-note@Inputs/undefined-type-fixit/public1.h:4 {{previous declaration is here}}
Index: test/Modules/Inputs/undefined-type-fixit/public2sub.h
===================================================================
--- test/Modules/Inputs/undefined-type-fixit/public2sub.h
+++ test/Modules/Inputs/undefined-type-fixit/public2sub.h
@@ -0,0 +1,6 @@
+#ifndef PUBLIC2SUB_H
+#define PUBLIC2SUB_H
+
+struct use_this2sub { int field; };
+
+#endif
Index: test/Modules/Inputs/undefined-type-fixit/module.map
===================================================================
--- test/Modules/Inputs/undefined-type-fixit/module.map
+++ test/Modules/Inputs/undefined-type-fixit/module.map
@@ -0,0 +1,9 @@
+module public1 {
+  header "public1.h"
+}
+module public2 {
+  header "public2.h"
+  module public2sub {
+    header "public2sub.h"
+  }
+}
Index: test/Modules/Inputs/undefined-type-fixit/public1.h
===================================================================
--- test/Modules/Inputs/undefined-type-fixit/public1.h
+++ test/Modules/Inputs/undefined-type-fixit/public1.h
@@ -0,0 +1,6 @@
+#ifndef PUBLIC1_H
+#define PUBLIC1_H
+
+struct use_this1 { int field; };
+
+#endif
Index: test/Modules/Inputs/undefined-type-fixit/public2.h
===================================================================
--- test/Modules/Inputs/undefined-type-fixit/public2.h
+++ test/Modules/Inputs/undefined-type-fixit/public2.h
@@ -0,0 +1,6 @@
+#ifndef PUBLIC2_H
+#define PUBLIC2_H
+
+struct use_this2 { int field; };
+
+#endif
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to