diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx
index 106cc74aaf541037a13df377fe17eb1603c7ffc7..5061a5bc991edde989338772a2a12903e58e3b96 100644
--- a/core/metacling/src/TCling.cxx
+++ b/core/metacling/src/TCling.cxx
@@ -1074,40 +1074,18 @@ std::string TCling::ToString(const char* type, void* obj)
 ///\returns true if the module was loaded.
 static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp, bool Complain = true)
 {
-   clang::CompilerInstance &CI = *interp.getCI();
-
-   assert(CI.getLangOpts().Modules && "Function only relevant when C++ modules are turned on!");
-
-   clang::Preprocessor &PP = CI.getPreprocessor();
-   clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
-
-   cling::Interpreter::PushTransactionRAII RAII(&interp);
-   if (clang::Module *M = headerSearch.lookupModule(ModuleName, true /*AllowSearch*/, true /*AllowExtraSearch*/)) {
-      clang::IdentifierInfo *II = PP.getIdentifierInfo(M->Name);
-      SourceLocation ValidLoc = M->DefinitionLoc;
-      bool success = !CI.getSema().ActOnModuleImport(ValidLoc, ValidLoc, std::make_pair(II, ValidLoc)).isInvalid();
-      if (success) {
-         // Also make the module visible in the preprocessor to export its macros.
-         PP.makeModuleVisible(M, ValidLoc);
-         return success;
-      }
-      if (Complain) {
-         if (M->IsSystem)
-            Error("TCling::LoadModule", "Module %s failed to load", M->Name.c_str());
-         else
-            Info("TCling::LoadModule", "Module %s failed to load", M->Name.c_str());
-      }
-   }
+   if (interp.loadModule(ModuleName, Complain))
+      return true;
 
    // Load modulemap if we have one in current directory
-   SourceManager& SM = PP.getSourceManager();
-   FileManager& FM = SM.getFileManager();
-   const clang::DirectoryEntry *DE = FM.getDirectory(".");
+   Preprocessor &PP = interp.getCI()->getPreprocessor();
+   FileManager& FM = PP.getFileManager();
+   const DirectoryEntry *DE = FM.getDirectory(".");
    if (DE) {
-      const clang::FileEntry *FE = headerSearch.lookupModuleMapFile(DE, /*IsFramework*/ false);
-      // Check if "./module.modulemap is already loaded or not
-      if (!gCling->IsLoaded("./module.modulemap") && FE) {
-         if(!headerSearch.loadModuleMapFile(FE, /*IsSystem*/ false))
+      HeaderSearch& HS = PP.getHeaderSearchInfo();
+      const FileEntry *FE = HS.lookupModuleMapFile(DE, /*IsFramework*/ false);
+      if (FE && !gCling->IsLoaded("./module.modulemap")) {
+         if (!HS.loadModuleMapFile(FE, /*IsSystem*/ false))
             return LoadModule(ModuleName, interp, Complain);
          Error("TCling::LoadModule", "Could not load modulemap in the current directory");
       }
@@ -1115,6 +1093,7 @@ static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp
 
    if (Complain)
       Error("TCling::LoadModule", "Module %s not found!", ModuleName.c_str());
+
    return false;
 }
 
diff --git a/interpreter/cling/include/cling/Interpreter/Interpreter.h b/interpreter/cling/include/cling/Interpreter/Interpreter.h
index 668389928c5194b590a8b95129dfd4ea31448de2..fe94b7a8cad348bf5428998b096d58a2c0233ede 100644
--- a/interpreter/cling/include/cling/Interpreter/Interpreter.h
+++ b/interpreter/cling/include/cling/Interpreter/Interpreter.h
@@ -40,6 +40,7 @@ namespace clang {
   class FunctionDecl;
   class GlobalDecl;
   class MacroInfo;
+  class Module;
   class NamedDecl;
   class Parser;
   class Preprocessor;
@@ -479,16 +480,23 @@ namespace cling {
     ///
     CompilationResult parse(const std::string& input,
                             Transaction** T = 0) const;
-
-    ///\brief Looks for a already generated PCM for the given header file and
-    /// loads it.
+    /// Loads a C++ Module with a given name by synthesizing an Import decl.
+    /// This routine checks if there is a modulemap in the current directory
+    /// and loads it.
     ///
-    ///\param[in] headerFile - The header file for which a module should be
-    ///                        loaded.
+    /// This is useful when we start up the interpreter and programatically,
+    /// later generate a modulemap.
     ///
-    ///\returns Whether the operation was fully successful.
+    ///\returns true if the module was loaded.
+    ///
+    bool loadModule(const std::string& moduleName, bool complain = true);
+
+    /// Loads a C++ Module with a given name by synthesizing an Import decl.
+    /// This routine checks if there is a modulemap in the current directory
+    /// and loads it.
     ///
-    CompilationResult loadModuleForHeader(const std::string& headerFile);
+    ///\returns true if the module was loaded or already visible.
+    bool loadModule(clang::Module* M, bool complain = true);
 
     ///\brief Parses input line, which doesn't contain statements. Code
     /// generation needed to make the module functional.
diff --git a/interpreter/cling/lib/Interpreter/Interpreter.cpp b/interpreter/cling/lib/Interpreter/Interpreter.cpp
index 9577cf043a8753162cf5a130692e577a2f1623a9..d2fa3535998da3baf509c7d1db6a773bc9503d5a 100644
--- a/interpreter/cling/lib/Interpreter/Interpreter.cpp
+++ b/interpreter/cling/lib/Interpreter/Interpreter.cpp
@@ -803,9 +803,66 @@ namespace cling {
     return DeclareInternal(input, CO, T);
   }
 
-  Interpreter::CompilationResult
-  Interpreter::loadModuleForHeader(const std::string& headerFile) {
+  ///\returns true if the module was loaded.
+  bool Interpreter::loadModule(const std::string& moduleName,
+                               bool complain /*= true*/) {
+    assert(getCI()->getLangOpts().Modules
+           && "Function only relevant when C++ modules are turned on!");
+
+    Preprocessor& PP = getCI()->getPreprocessor();
+    HeaderSearch &HS = PP.getHeaderSearchInfo();
+
+    if (Module *M = HS.lookupModule(moduleName, /*AllowSearch*/true,
+                                    /*AllowExtraSearch*/ true))
+      return loadModule(M, complain);
+
+   if (complain)
+     llvm::errs() << "Module " << moduleName << " not found.\n";
+
+
+   return false;
+  }
+
+  bool Interpreter::loadModule(clang::Module* M, bool complain /* = true*/) {
+    assert(getCI()->getLangOpts().Modules
+           && "Function only relevant when C++ modules are turned on!");
+    assert(M && "Module missing");
+    if (getSema().isModuleVisible(M))
+      return true;
+
     Preprocessor& PP = getCI()->getPreprocessor();
+
+    IdentifierInfo *II = PP.getIdentifierInfo(M->Name);
+    SourceLocation ValidLoc = M->DefinitionLoc;
+    Interpreter::PushTransactionRAII RAII(this);
+    bool success = !getCI()->getSema().ActOnModuleImport(ValidLoc, ValidLoc,
+                                      std::make_pair(II, ValidLoc)).isInvalid();
+    if (success) {
+      // Also make the module visible in the preprocessor to export its macros.
+      PP.makeModuleVisible(M, ValidLoc);
+      return success;
+    }
+    if (complain) {
+      if (M->IsSystem)
+        llvm::errs() << "Failed to load module " << M->Name << "\n";
+      else
+        llvm::outs() << "Failed to load module " << M->Name << "\n";
+    }
+
+   return false;
+  }
+
+  ///\brief Looks for a already generated PCM for the given header file and
+  /// loads it.
+  ///
+  ///\param[in] headerFile - The header file for which a module should be
+  ///                        loaded.
+  ///
+  ///\returns Whether the operation was fully successful.
+  ///
+  static Interpreter::CompilationResult
+  loadModuleForHeader(Interpreter& interp, const std::string& headerFile) {
+    Preprocessor& PP = interp.getCI()->getPreprocessor();
     //Copied from clang's PPDirectives.cpp
     bool isAngled = false;
     // Clang doc says:
@@ -828,8 +885,7 @@ namespace cling {
     // Copied from PPDirectives.cpp
     SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> path;
     for (auto mod = suggestedModule.getModule(); mod; mod = mod->Parent) {
-      IdentifierInfo* II
-        = &getSema().getPreprocessor().getIdentifierTable().get(mod->Name);
+      IdentifierInfo* II = &PP.getIdentifierTable().get(mod->Name);
       path.push_back(std::make_pair(II, fileNameLoc));
     }
 
@@ -839,10 +895,10 @@ namespace cling {
     // will create an implicit import declaration to capture it in the AST.
     bool isInclude = true;
     SourceLocation includeLoc;
-    if (getCI()->loadModule(includeLoc, path, Module::AllVisible, isInclude)) {
+    if (interp.getCI()->loadModule(includeLoc, path, Module::AllVisible, isInclude)) {
       // After module load we need to "force" Sema to generate the code for
       // things like dynamic classes.
-      getSema().ActOnEndOfTranslationUnit();
+      interp.getSema().ActOnEndOfTranslationUnit();
       return Interpreter::kSuccess;
     }
 
@@ -1599,7 +1655,7 @@ namespace cling {
     if (!m_DynamicLookupDeclared && value) {
       // No dynlookup for the dynlookup header!
       m_DynamicLookupEnabled = false;
-      if (loadModuleForHeader("cling/Interpreter/DynamicLookupRuntimeUniverse.h")
+      if (loadModuleForHeader(*this, "cling/Interpreter/DynamicLookupRuntimeUniverse.h")
           != kSuccess)
       declare("#include \"cling/Interpreter/DynamicLookupRuntimeUniverse.h\"");
     }