diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 8ea6697..4f76329 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -170,4 +170,7 @@ def err_analyzer_config_multiple_values : Error<
 def err_drv_modules_validate_once_requires_timestamp : Error<
   "option '-fmodules-validate-once-per-build-session' requires "
   "'-fbuild-session-timestamp=<seconds since Epoch>'">;
+def err_drv_conflicting_module_names : Error<
+  "conflicting module names specified: '-fmodule-name=%0' and "
+  "'-fmodule-implementation-of %1'">;
 }
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 2d0173c..cc4c5c3 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6860,6 +6860,8 @@ def err_module_private_definition : Error<
   "definition of %0 must be imported from module '%1' before it is required">;
 def err_module_self_import : Error<
   "import of module '%0' appears within same top-level module '%1'">;
+def err_module_import_in_implementation : Error<
+  "@import of module '%0' in implementation of '%1'; use #import">;
 }
 
 let CategoryName = "Documentation Issue" in {
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index d4e8b4e..facc1b2 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -82,6 +82,11 @@ public:
   /// \brief The name of the current module.
   std::string CurrentModule;
 
+  /// \brief The name of the module that the translation unit is an
+  /// implementation of. Prevents semantic imports, but does not otherwise
+  /// treat this as the CurrentModule.
+  std::string ImplementationOfModule;
+
   /// \brief Options for parsing comments.
   CommentOptions CommentOpts;
   
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index dfaf50c..e8aec09 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -603,6 +603,9 @@ def fmodule_maps : Flag <["-"], "fmodule-maps">, Group<f_Group>,
 def fmodule_name : JoinedOrSeparate<["-"], "fmodule-name=">, Group<f_Group>,
   Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">,
   HelpText<"Specify the name of the module to build">;
+def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">,
+  Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">,
+  HelpText<"Specify the name of the module whose implementation file this is">;
 def fmodule_map_file : JoinedOrSeparate<["-"], "fmodule-map-file=">,
   Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">,
   HelpText<"Load this module map file">;
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index f8714b2..ae1c799 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -36,5 +36,6 @@ void LangOptions::resetNonModularOptions() {
   Sanitize = SanitizerOptions::Disabled;
 
   CurrentModule.clear();
+  ImplementationOfModule.clear();
 }
 
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 5eac3dc..118e76a 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -3280,6 +3280,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     A->render(Args, CmdArgs);
   }
 
+  if (Arg *Impl = Args.getLastArg(options::OPT_fmodule_implementation_of)) {
+    if (Arg *Name = Args.getLastArg(options::OPT_fmodule_name)) {
+      if (Impl->getValue() != Name->getValue())
+        D.Diag(diag::err_drv_conflicting_module_names)
+            << Name->getValue() << Impl->getValue();
+    }
+    Impl->claim();
+    Impl->render(Args, CmdArgs);
+  }
+
   // -fmodule-map-file can be used to specify a file containing module
   // definitions.
   if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) {
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 960296f..9b79a87 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -1170,7 +1170,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
   // when both the preprocessor and parser see the same import declaration.
   if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) {
     // Make the named module visible.
-    if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule)
+    if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule &&
+        ModuleName != getLangOpts().ImplementationOfModule)
       ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,
                                        ImportLoc, /*Complain=*/false);
     return LastModuleImportResult;
@@ -1184,7 +1185,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
   if (Known != KnownModules.end()) {
     // Retrieve the cached top-level module.
     Module = Known->second;    
-  } else if (ModuleName == getLangOpts().CurrentModule) {
+  } else if (ModuleName == getLangOpts().CurrentModule ||
+             ModuleName == getLangOpts().ImplementationOfModule) {
     // This is the module we're building. 
     Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
     Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
@@ -1392,6 +1394,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
       Module = Sub;
     }
   }
+
+  // Don't make the module visible if we are in the implementation.
+  if (ModuleName == getLangOpts().ImplementationOfModule)
+    return ModuleLoadResult(Module, false);
   
   // Make the named module visible, if it's not already part of the module
   // we are parsing.
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 1087cdb..79b7085 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1395,6 +1395,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
   Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
   Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name);
+  Opts.ImplementationOfModule =
+      Args.getLastArgValue(OPT_fmodule_implementation_of);
+
   Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
 
   if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) {
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 4ae3869..c874bf2 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -1520,7 +1520,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
 
   // If we are supposed to import a module rather than including the header,
   // do so now.
-  if (SuggestedModule && getLangOpts().Modules) {
+  if (SuggestedModule && getLangOpts().Modules &&
+      SuggestedModule.getModule()->getTopLevelModuleName() !=
+      getLangOpts().ImplementationOfModule) {
     // Compute the module access path corresponding to this module.
     // FIXME: Should we have a second loadModule() overload to avoid this
     // extra lookup step?
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c56d883..85f786b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12999,6 +12999,9 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
   if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule)
     Diag(ImportLoc, diag::err_module_self_import)
         << Mod->getFullModuleName() << getLangOpts().CurrentModule;
+  else if (Mod->getTopLevelModuleName() == getLangOpts().ImplementationOfModule)
+    Diag(ImportLoc, diag::err_module_import_in_implementation)
+        << Mod->getFullModuleName() << getLangOpts().ImplementationOfModule;
 
   SmallVector<SourceLocation, 2> IdentifierLocs;
   Module *ModCheck = Mod;
diff --git a/test/Driver/modules.m b/test/Driver/modules.m
index d8e20e4..6b5b351 100644
--- a/test/Driver/modules.m
+++ b/test/Driver/modules.m
@@ -19,3 +19,11 @@
 
 // RUN: %clang -fmodules-validate-system-headers -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS %s
 // MODULES_VALIDATE_SYSTEM_HEADERS: -fmodules-validate-system-headers
+
+// RUN: %clang -fmodule-implementation-of Foo -### %s 2>&1 \
+// RUN:     | FileCheck -check-prefix=CHECK-IMPL-OF %s
+// CHECK-IMPL-OF: -fmodule-implementation-of
+
+// RUN: %clang -fmodule-implementation-of Foo -fmodule-name=Bar -### %s 2>&1 \
+// RUN:     | FileCheck -check-prefix=CHECK-IMPL-OF-ERR %s
+// CHECK-IMPL-OF-ERR: conflicting module names specified: '-fmodule-name=Bar' and '-fmodule-implementation-of Foo'
diff --git a/test/Modules/implementation-of-module.m b/test/Modules/implementation-of-module.m
new file mode 100644
index 0000000..0b5be5f
--- /dev/null
+++ b/test/Modules/implementation-of-module.m
@@ -0,0 +1,24 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
+// RUN:     -fmodule-implementation-of category_right -fsyntax-only
+
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
+// RUN:     -fmodule-implementation-of category_right -dM -E -o - 2>&1 | FileCheck %s
+// CHECK-NOT: __building_module
+
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
+// RUN:     -fmodule-implementation-of category_left -verify
+
+// RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
+// RUN:     -fmodule-implementation-of category_right -emit-pch -o %t.pch
+// RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
+// RUN:     -DWITH_PREFIX -include-pch %t.pch -fmodule-implementation-of category_right
+
+#ifndef WITH_PREFIX
+
+@import category_left; // expected-error{{@import of module 'category_left' in implementation of 'category_left'; use #import}}
+@import category_left.sub; // expected-error{{@import of module 'category_left.sub' in implementation of 'category_left'; use #import}}
+#import "category_right.h" // expected-error{{treating}}
+#import "category_right_sub.h" // expected-error{{treating}}
+
+#endif
