diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 0edf376..4c8ad91 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -601,8 +601,7 @@ def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
   InGroup<IgnoredAttributes>;
 
 def warn_auto_module_import : Warning<
-  "treating #%select{include|import|include_next|__include_macros}0 as an "
-  "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
+  "treating #%0 as an import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
 def warn_uncovered_module_header : Warning<
   "umbrella header for module '%0' does not include header '%1'">, 
   InGroup<IncompleteUmbrella>, DefaultIgnore;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index ff76e95..dfea240 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -222,6 +222,9 @@ def err_expected_selector_for_method : Error<
 def err_expected_property_name : Error<"expected property name">;
 
 def err_unexpected_at : Error<"unexpected '@' in program">;
+def err_unexpected_import : Error<"module import must be at file scope">;
+def err_unexpected_implicit_import : Error<
+  "module import (due to #%0) must be at file scope">;
 
 def err_invalid_reference_qualifier_application : Error<
   "'%0' qualifier may not be applied to a reference">;
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index bca267f..2b21ca5 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/include/clang/Basic/TokenKinds.h
@@ -100,6 +100,17 @@ inline bool isAnnotation(TokenKind K) {
   return false;
 }
 
+/// \brief A kind of include directive.
+enum IncludeDirectiveKind {
+  IDK_include,
+  IDK_import,
+  IDK_include_next,
+  IDK___include_macros
+};
+
+IncludeDirectiveKind getIncludeDirectiveKind(PPKeywordKind Kind);
+const char *getIncludeDirectiveSpelling(IncludeDirectiveKind Kind);
+
 }  // end namespace tok
 }  // end namespace clang
 
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index baa890a..9e7955b 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -435,7 +435,7 @@ private:
   bool isEofOrEom() {
     tok::TokenKind Kind = Tok.getKind();
     return Kind == tok::eof || Kind == tok::annot_module_begin ||
-           Kind == tok::annot_module_end || Kind == tok::annot_module_include;
+           Kind == tok::annot_module_end;
   }
 
   /// \brief Handle the annotation token produced for #pragma unused(...)
@@ -1266,6 +1266,8 @@ private:
 
   Decl *ParseObjCMethodDefinition();
 
+  void DiagnoseAndSkipImplicitImportNotAtTopLevel();
+
 public:
   //===--------------------------------------------------------------------===//
   // C99 6.5: Expressions.
diff --git a/lib/Basic/TokenKinds.cpp b/lib/Basic/TokenKinds.cpp
index 92fc2a2..002ce86 100644
--- a/lib/Basic/TokenKinds.cpp
+++ b/lib/Basic/TokenKinds.cpp
@@ -46,3 +46,33 @@ const char *tok::getKeywordSpelling(TokenKind Kind) {
   }
   return 0;
 }
+
+tok::IncludeDirectiveKind tok::getIncludeDirectiveKind(tok::PPKeywordKind Kind){
+  switch (Kind) {
+    case tok::pp_include:
+      return tok::IDK_include;
+    case tok::pp_import:
+      return tok::IDK_import;
+    case tok::pp_include_next:
+      return tok::IDK_include_next;
+    case tok::pp___include_macros:
+      return tok::IDK___include_macros;
+    default:
+      break;
+  }
+  llvm_unreachable("unknown include directive kind");
+}
+
+const char *tok::getIncludeDirectiveSpelling(tok::IncludeDirectiveKind Kind) {
+  switch (Kind) {
+    case tok::IDK_include:
+      return "include";
+    case tok::IDK_import:
+      return "import";
+    case tok::IDK_include_next:
+      return "include_next";
+    case tok::IDK___include_macros:
+      return "__include_macros";
+  }
+  llvm_unreachable("unknown include directive kind");
+}
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 4a9e09f..f97af59 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -1527,28 +1527,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
         PathString += '.';
       PathString += Path[I].first->getName();
     }
-    int IncludeKind = 0;
-    
-    switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
-    case tok::pp_include:
-      IncludeKind = 0;
-      break;
-      
-    case tok::pp_import:
-      IncludeKind = 1;
-      break;        
-        
-    case tok::pp_include_next:
-      IncludeKind = 2;
-      break;
-        
-    case tok::pp___include_macros:
-      IncludeKind = 3;
-      break;
-        
-    default:
-      llvm_unreachable("unknown include directive kind");
-    }
+
+    tok::IncludeDirectiveKind IncludeKind = getIncludeDirectiveKind(
+      IncludeTok.getIdentifierInfo()->getPPKeywordID());
 
     // Determine whether we are actually building the module that this
     // include directive maps to.
@@ -1562,7 +1543,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
       CharSourceRange ReplaceRange(SourceRange(HashLoc, CharEnd), 
                                    /*IsTokenRange=*/false);
       Diag(HashLoc, diag::warn_auto_module_import)
-        << IncludeKind << PathString 
+        << getIncludeDirectiveSpelling(IncludeKind) << PathString
         << FixItHint::CreateReplacement(ReplaceRange,
              "@import " + PathString.str().str() + ";");
     }
@@ -1598,13 +1579,15 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
                                       SearchPath, RelativePath, Imported);
       }
 
-      if (IncludeKind != 3) {
+      if (IncludeKind != tok::IDK___include_macros) {
         // Let the parser know that we hit a module import, and it should
         // make the module visible.
         // FIXME: Produce this as the current token directly, rather than
         // allocating a new token for it.
+        llvm::PointerIntPair<Module *, 2, tok::IncludeDirectiveKind>
+          AnnotValue(Imported, IncludeKind);
         EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include,
-                             Imported);
+                             AnnotValue.getOpaqueValue());
       }
       return;
     }
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 4cf87e5..bdabccc 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -571,7 +571,6 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
     case tok::eof:
     case tok::annot_module_begin:
     case tok::annot_module_end:
-    case tok::annot_module_include:
       // Ran out of tokens.
       return false;
 
@@ -961,7 +960,6 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
     case tok::eof:
     case tok::annot_module_begin:
     case tok::annot_module_end:
-    case tok::annot_module_include:
       // Ran out of tokens.
       return false;
 
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0950ab0..149c882 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1551,7 +1551,6 @@ void Parser::SkipMalformedDecl() {
     case tok::eof:
     case tok::annot_module_begin:
     case tok::annot_module_end:
-    case tok::annot_module_include:
       return;
 
     default:
@@ -3347,6 +3346,11 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
       continue;
     }
 
+    if (Tok.is(tok::annot_module_include)) {
+      DiagnoseAndSkipImplicitImportNotAtTopLevel();
+      continue;
+    }
+
     if (!Tok.is(tok::at)) {
       struct CFieldCallback : FieldCallback {
         Parser &P;
@@ -3371,9 +3375,12 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
       ParsingDeclSpec DS(*this);
       ParseStructDeclaration(DS, Callback);
     } else { // Handle @defs
-      ConsumeToken();
+      SourceLocation AtLoc = ConsumeToken();
       if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
-        Diag(Tok, diag::err_unexpected_at);
+        if (getLangOpts().Modules && Tok.isObjCAtKeyword(tok::objc_import))
+          Diag(AtLoc, diag::err_unexpected_import);
+        else
+          Diag(AtLoc, diag::err_unexpected_at);
         SkipUntil(tok::semi);
         continue;
       }
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index c8460c0..0b747c0 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -79,9 +79,11 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
     SingleDecl = ParseObjCPropertyDynamic(AtLoc);
     break;
   case tok::objc_import:
-    if (getLangOpts().Modules)
-      return ParseModuleImport(AtLoc);
-      
+    if (getLangOpts().Modules) {
+      Diag(AtLoc, diag::err_unexpected_import);
+      SkipUntil(tok::semi);
+      break;
+    }
     // Fall through
       
   default:
@@ -423,6 +425,12 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
       continue;
     }
 
+    if (Tok.is(tok::annot_module_include)) {
+      DiagnoseAndSkipImplicitImportNotAtTopLevel();
+      continue;
+    }
+
+
     // If we got to the end of the file, exit the loop.
     if (isEofOrEom())
       break;
@@ -470,6 +478,14 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
     ConsumeToken();
 
     switch (DirectiveKind) {
+    case tok::objc_import:
+      if (getLangOpts().Modules) {
+        Diag(AtLoc, diag::err_unexpected_import);
+        SkipUntil(tok::semi);
+        break;
+      }
+      // fallthrough
+
     default:
       // FIXME: If someone forgets an @end on a protocol, this loop will
       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
@@ -2069,7 +2085,12 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
 
   if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
     return ParseObjCAutoreleasePoolStmt(AtLoc);
-  
+
+  if (getLangOpts().Modules && Tok.isObjCAtKeyword(tok::objc_import)) {
+    SkipUntil(tok::semi);
+    return StmtError(Diag(AtLoc, diag::err_unexpected_import));
+  }
+
   ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
   if (Res.isInvalid()) {
     // If the expression is invalid, skip ahead to the next semicolon. Not
@@ -2162,23 +2183,24 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
     case tok::objc_selector:
       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
-      default: {
-        const char *str = 0;
-        if (GetLookAheadToken(1).is(tok::l_brace)) {
-          char ch = Tok.getIdentifierInfo()->getNameStart()[0];
-          str =  
-            ch == 't' ? "try" 
-                      : (ch == 'f' ? "finally" 
-                                   : (ch == 'a' ? "autoreleasepool" : 0));
-        }
-        if (str) {
-          SourceLocation kwLoc = Tok.getLocation();
-          return ExprError(Diag(AtLoc, diag::err_unexpected_at) << 
-                             FixItHint::CreateReplacement(kwLoc, str));
-        }
-        else
-          return ExprError(Diag(AtLoc, diag::err_unexpected_at));
+        // fallthrough
+    default: {
+      const char *str = 0;
+      if (GetLookAheadToken(1).is(tok::l_brace)) {
+        char ch = Tok.getIdentifierInfo()->getNameStart()[0];
+        str =
+          ch == 't' ? "try"
+                    : (ch == 'f' ? "finally"
+                                 : (ch == 'a' ? "autoreleasepool" : 0));
+      }
+      if (str) {
+        SourceLocation kwLoc = Tok.getLocation();
+        return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
+                           FixItHint::CreateReplacement(kwLoc, str));
       }
+      else
+        return ExprError(Diag(AtLoc, diag::err_unexpected_at));
+    }
     }
   }
 }
@@ -2954,3 +2976,16 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
   
   return;
 }
+
+void Parser::DiagnoseAndSkipImplicitImportNotAtTopLevel() {
+  assert(Tok.is(tok::annot_module_include) && "expected implicit import");
+
+  typedef llvm::PointerIntPair<Module *, 2, tok::IncludeDirectiveKind> AnnotValTy;
+  tok::IncludeDirectiveKind IncludeKind =
+    AnnotValTy::getFromOpaqueValue(Tok.getAnnotationValue()).getInt();
+
+  Diag(Tok.getLocation(), diag::err_unexpected_implicit_import)
+    << getIncludeDirectiveSpelling(IncludeKind);
+
+  ConsumeToken();
+}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index f2e4ad9..66fef90 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -884,6 +884,11 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
   }
 
   while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+    if (Tok.is(tok::annot_module_include)) {
+      DiagnoseAndSkipImplicitImportNotAtTopLevel();
+      continue;
+    }
+
     if (Tok.is(tok::annot_pragma_unused)) {
       HandlePragmaUnused();
       continue;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index efa6a1b..1b44364 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -309,7 +309,6 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
       // Stop before an OpenMP pragma boundary.
     case tok::annot_module_begin:
     case tok::annot_module_end:
-    case tok::annot_module_include:
       // Stop before we change submodules. They generally indicate a "good"
       // place to pick up parsing again (except in the special case where
       // we're trying to skip to EOF).
@@ -602,10 +601,17 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
     HandlePragmaUnused();
     return false;
 
+  case tok::at:
+    if (getLangOpts().Modules &&
+        PP.LookAhead(0).isObjCAtKeyword(tok::objc_import)) {
+      Result = ParseModuleImport(ConsumeToken());
+      return false;
+    }
+    break;
+
   case tok::annot_module_include:
     Actions.ActOnModuleInclude(Tok.getLocation(),
-                               reinterpret_cast<Module *>(
-                                   Tok.getAnnotationValue()));
+                               llvm::PointerIntPair<Module *, 2, tok::IncludeDirectiveKind>::getFromOpaqueValue(Tok.getAnnotationValue()).getPointer());
     ConsumeToken();
     return false;
 
@@ -739,6 +745,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
   }
   case tok::at:
     return ParseObjCAtDirectives();
+  case tok::annot_module_include:
+    DiagnoseAndSkipImplicitImportNotAtTopLevel();
+    return DeclGroupPtrTy();
   case tok::minus:
   case tok::plus:
     if (!getLangOpts().ObjC1) {
diff --git a/test/Modules/auto-module-import.m b/test/Modules/auto-module-import.m
index bf99377..eaa67a1 100644
--- a/test/Modules/auto-module-import.m
+++ b/test/Modules/auto-module-import.m
@@ -83,6 +83,7 @@ int getNotInModule() {
   return not_in_module;
 }
 
-void includeNotAtTopLevel() { // expected-note {{to match this '{'}}
-  #include <NoUmbrella/A.h> // expected-warning {{treating #include as an import}} expected-error {{expected '}'}}
-} // expected-error {{extraneous closing brace}}
+void includeNotAtTopLevel() {
+  #include <NoUmbrella/A.h> // expected-warning {{treating #include as an import}} \
+                               expected-error {{module import (due to #include) must be at file scope}}
+}
diff --git a/test/Modules/import-not-at-top-level.m b/test/Modules/import-not-at-top-level.m
new file mode 100644
index 0000000..56cd243
--- /dev/null
+++ b/test/Modules/import-not-at-top-level.m
@@ -0,0 +1,29 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -Wno-objc-root-class -F %S/Inputs -fmodules-cache-path=%t %s -verify
+
+@interface I
+@import Module; // expected-error{{module import must be at file scope}}
+#import "Module/Module.h" // expected-error{{module import (due to #import) must be at file scope}}
+#include "Module/Module.h" // expected-error{{module import (due to #include) must be at file scope}}
+#include_next "Module/Module.h" // expected-error{{module import (due to #include_next) must be at file scope}} \
+                                   expected-warning{{#include_next in primary source file}}
+@end
+
+void foo() {
+@import Module; // expected-error{{module import must be at file scope}}
+#import "Module/Module.h" // expected-error{{module import (due to #import) must be at file scope}}
+}
+
+struct Bar {
+@import Module; // expected-error{{module import must be at file scope}}
+#import "Module/Module.h" // expected-error{{module import (due to #import) must be at file scope}}
+};
+
+@implementation I
+@import Module; // expected-error{{module import must be at file scope}}
+#import "Module/Module.h" // expected-error{{module import (due to #import) must be at file scope}}
+-Method {
+@import Module; // expected-error{{module import must be at file scope}}
+#import "Module/Module.h" // expected-error{{module import (due to #import) must be at file scope}}
+}
+@end
