From 467dc88512b4ba4bb16e274ea3771dc1415d31da Mon Sep 17 00:00:00 2001
From: Douglas Gregor <dgregor@apple.com>
Date: Thu, 25 Aug 2011 22:30:56 +0000
Subject: [PATCH] Introduce a -cc1 option "-emit-module", that creates a binary
 module from the given source. -emit-module behaves similarly to -emit-pch,
 except that Sema is somewhat more strict about the contents of -emit-module.
 In the future, there are likely to be more interesting differences.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138595 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/LangOptions.h             | 12 ++++++++++++
 include/clang/Driver/CC1Options.td            |  2 ++
 include/clang/Frontend/ASTUnit.h              | 15 ++++++---------
 include/clang/Frontend/CompilerInstance.h     |  2 +-
 include/clang/Frontend/FrontendAction.h       |  8 ++++----
 include/clang/Frontend/FrontendActions.h      | 11 +++++++++--
 include/clang/Frontend/FrontendOptions.h      |  1 +
 include/clang/Parse/ParseAST.h                |  8 ++++----
 include/clang/Sema/Sema.h                     | 14 ++++++--------
 include/clang/Serialization/ASTWriter.h       |  2 +-
 lib/Frontend/ASTMerge.cpp                     |  4 ++--
 lib/Frontend/ASTUnit.cpp                      | 19 +++++++++----------
 lib/Frontend/CompilerInstance.cpp             |  4 ++--
 lib/Frontend/CompilerInvocation.cpp           |  3 +++
 lib/Frontend/FrontendAction.cpp               |  6 +++---
 lib/Frontend/FrontendActions.cpp              |  5 +++--
 .../ExecuteCompilerInvocation.cpp             |  3 ++-
 lib/Parse/ParseAST.cpp                        |  4 ++--
 lib/Sema/Sema.cpp                             | 19 +++++++++++++------
 lib/Serialization/ChainedIncludesSource.cpp   |  2 +-
 lib/Serialization/GeneratePCH.cpp             |  2 +-
 test/Modules/Inputs/lookup_left.hpp           |  4 ++++
 test/Modules/lookup.cpp                       |  5 ++---
 test/Modules/lookup.m                         |  4 ++--
 tools/libclang/CIndex.cpp                     |  7 ++++---
 25 files changed, 99 insertions(+), 67 deletions(-)

diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index dc77d4c1496..5cdeda3877d 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -296,6 +296,18 @@ public:
   }
 };
 
+/// \brief Describes the kind of translation unit being processed.
+enum TranslationUnitKind {
+  /// \brief The translation unit is a complete translation unit.
+  TU_Complete,
+  /// \brief The translation unit is a prefix to a translation unit, and is
+  /// not complete.
+  TU_Prefix,
+  /// \brief The translation unit is a module.
+  TU_Module
+};
+  
+  /// \brief 
 }  // end namespace clang
 
 #endif
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 3edd436b7ef..2c3bfc07a09 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -360,6 +360,8 @@ def ast_view : Flag<"-ast-view">,
   HelpText<"Build ASTs and view them with GraphViz">;
 def print_decl_contexts : Flag<"-print-decl-contexts">,
   HelpText<"Print DeclContexts and their Decls">;
+def emit_module : Flag<"-emit-module">,
+  HelpText<"Generate pre-compiled module file">;
 def emit_pth : Flag<"-emit-pth">,
   HelpText<"Generate pre-tokenized header file">;
 def emit_pch : Flag<"-emit-pch">,
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index db3f7ee01c1..08b626facc8 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -112,8 +112,8 @@ private:
   /// \brief Track whether the main file was loaded from an AST or not.
   bool MainFileIsAST;
 
-  /// \brief Whether this AST represents a complete translation unit.
-  bool CompleteTranslationUnit;
+  /// \brief What kind of translation unit this AST represents.
+  TranslationUnitKind TUKind;
 
   /// \brief Whether we should time each operation.
   bool WantTiming;
@@ -548,11 +548,8 @@ public:
   llvm::MemoryBuffer *getBufferForFile(StringRef Filename,
                                        std::string *ErrorStr = 0);
 
-  /// \brief Whether this AST represents a complete translation unit.
-  ///
-  /// If false, this AST is only a partial translation unit, e.g., one
-  /// that might still be used as a precompiled header or preamble.
-  bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
+  /// \brief Determine what kind of translation unit this AST represents.
+  TranslationUnitKind getTranslationUnitKind() const { return TUKind; }
 
   typedef llvm::PointerUnion<const char *, const llvm::MemoryBuffer *>
       FilenameOrMemBuf;
@@ -624,7 +621,7 @@ public:
                                              bool OnlyLocalDecls = false,
                                              bool CaptureDiagnostics = false,
                                              bool PrecompilePreamble = false,
-                                          bool CompleteTranslationUnit = true,
+                                      TranslationUnitKind TUKind = TU_Complete,
                                        bool CacheCodeCompletionResults = false,
                                        bool NestedMacroExpansions = true);
 
@@ -652,7 +649,7 @@ public:
                                       unsigned NumRemappedFiles = 0,
                                       bool RemappedFilesKeepOriginalName = true,
                                       bool PrecompilePreamble = false,
-                                      bool CompleteTranslationUnit = true,
+                                      TranslationUnitKind TUKind = TU_Complete,
                                       bool CacheCodeCompletionResults = false,
                                       bool CXXPrecompilePreamble = false,
                                       bool CXXChainedPCH = false,
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 425f2e7241d..3f97f1addbc 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -548,7 +548,7 @@ public:
                                raw_ostream &OS);
 
   /// \brief Create the Sema object to be used for parsing.
-  void createSema(bool CompleteTranslationUnit,
+  void createSema(TranslationUnitKind TUKind,
                   CodeCompleteConsumer *CompletionConsumer);
   
   /// Create the frontend timer and replace any existing one with it.
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index 4762e093cf4..f85cc7ec913 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -11,6 +11,7 @@
 #define LLVM_CLANG_FRONTEND_FRONTENDACTION_H
 
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/OwningPtr.h"
 #include <string>
@@ -160,9 +161,8 @@ public:
   /// file inputs.
   virtual bool usesPreprocessorOnly() const = 0;
 
-  /// usesCompleteTranslationUnit - For AST based actions, should the
-  /// translation unit be completed?
-  virtual bool usesCompleteTranslationUnit() { return true; }
+  /// \brief For AST-based actions, the kind of translation unit we're handling.
+  virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
 
   /// hasPCHSupport - Does this action support use with PCH?
   virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); }
@@ -282,7 +282,7 @@ public:
   WrapperFrontendAction(FrontendAction *WrappedAction);
 
   virtual bool usesPreprocessorOnly() const;
-  virtual bool usesCompleteTranslationUnit();
+  virtual TranslationUnitKind getTranslationUnitKind();
   virtual bool hasPCHSupport() const;
   virtual bool hasASTFileSupport() const;
   virtual bool hasIRSupport() const;
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 646ee2552a4..ef204312c44 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -67,15 +67,22 @@ protected:
 };
 
 class GeneratePCHAction : public ASTFrontendAction {
+  bool MakeModule;
+  
 protected:
   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
                                          StringRef InFile);
 
-  virtual bool usesCompleteTranslationUnit() { return false; }
+  virtual TranslationUnitKind getTranslationUnitKind() { 
+    return MakeModule? TU_Module : TU_Prefix;
+  }
 
   virtual bool hasASTFileSupport() const { return false; }
 
 public:
+  /// \brief Create a new action
+  explicit GeneratePCHAction(bool MakeModule) : MakeModule(MakeModule) { }
+  
   /// \brief Compute the AST consumer arguments that will be used to
   /// create the PCHGenerator instance returned by CreateASTConsumer.
   ///
@@ -128,7 +135,7 @@ public:
   virtual ~ASTMergeAction();
 
   virtual bool usesPreprocessorOnly() const;
-  virtual bool usesCompleteTranslationUnit();
+  virtual TranslationUnitKind getTranslationUnitKind();
   virtual bool hasPCHSupport() const;
   virtual bool hasASTFileSupport() const;
   virtual bool hasCodeCompletionSupport() const;
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index e7c2ac4002a..75e3eba80cd 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -35,6 +35,7 @@ namespace frontend {
     EmitCodeGenOnly,        ///< Generate machine code, but don't emit anything.
     EmitObj,                ///< Emit a .o file.
     FixIt,                  ///< Parse and apply any fixits to the source.
+    GenerateModule,         ///< Generate pre-compiled module.
     GeneratePCH,            ///< Generate pre-compiled header.
     GeneratePTH,            ///< Generate pre-tokenized header.
     InitOnly,               ///< Only execute frontend initialization.
diff --git a/include/clang/Parse/ParseAST.h b/include/clang/Parse/ParseAST.h
index 0d37e21becd..725387024e1 100644
--- a/include/clang/Parse/ParseAST.h
+++ b/include/clang/Parse/ParseAST.h
@@ -14,6 +14,8 @@
 #ifndef LLVM_CLANG_PARSE_PARSEAST_H
 #define LLVM_CLANG_PARSE_PARSEAST_H
 
+#include "clang/Basic/LangOptions.h"
+
 namespace clang {
   class Preprocessor;
   class ASTConsumer;
@@ -27,15 +29,13 @@ namespace clang {
   /// This operation inserts the parsed decls into the translation
   /// unit held by Ctx.
   ///
-  /// \param CompleteTranslationUnit When true, the parsed file is
-  /// considered to be a complete translation unit, and any
-  /// end-of-translation-unit wrapup will be performed.
+  /// \param TUKind The kind of translation unit being parsed.
   ///
   /// \param CompletionConsumer If given, an object to consume code completion
   /// results.
   void ParseAST(Preprocessor &pp, ASTConsumer *C,
                 ASTContext &Ctx, bool PrintStats = false,
-                bool CompleteTranslationUnit = true,
+                TranslationUnitKind TUKind = TU_Complete,
                 CodeCompleteConsumer *CompletionConsumer = 0);
 
   /// \brief Parse the main file known to the preprocessor, producing an 
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 07bbd18bee8..adf2702cce8 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -630,16 +630,14 @@ public:
   /// for C++ records.
   llvm::FoldingSet<SpecialMemberOverloadResult> SpecialMemberCache;
 
-  /// \brief Whether the code handled by Sema should be considered a
-  /// complete translation unit or not.
+  /// \brief The kind of translation unit we are processing.
   ///
-  /// When true (which is generally the case), Sema will perform
+  /// When we're processing a complete translation unit, Sema will perform
   /// end-of-translation-unit semantic tasks (such as creating
   /// initializers for tentative definitions in C) once parsing has
-  /// completed. This flag will be false when building PCH files,
-  /// since a PCH file is by definition not a complete translation
-  /// unit.
-  bool CompleteTranslationUnit;
+  /// completed. Modules and precompiled headers perform different kinds of
+  /// checks.
+  TranslationUnitKind TUKind;
 
   llvm::BumpPtrAllocator BumpAlloc;
 
@@ -685,7 +683,7 @@ public:
   bool isSelfExpr(Expr *RExpr);
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
-       bool CompleteTranslationUnit = true,
+       TranslationUnitKind TUKind = TU_Complete,
        CodeCompleteConsumer *CompletionConsumer = 0);
   ~Sema();
   
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 0bc8e29f8ed..1bb8edb0735 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -641,7 +641,7 @@ protected:
   const ASTWriter &getWriter() const { return Writer; }
 
 public:
-  PCHGenerator(const Preprocessor &PP, const std::string &OutputFile, 
+  PCHGenerator(const Preprocessor &PP, StringRef OutputFile, 
                bool Chaining, StringRef isysroot, raw_ostream *Out);
   ~PCHGenerator();
   virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index df4650e68f6..74aa5a64a49 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -93,8 +93,8 @@ bool ASTMergeAction::usesPreprocessorOnly() const {
   return AdaptedAction->usesPreprocessorOnly();
 }
 
-bool ASTMergeAction::usesCompleteTranslationUnit() {
-  return AdaptedAction->usesCompleteTranslationUnit();
+TranslationUnitKind ASTMergeAction::getTranslationUnitKind() {
+  return AdaptedAction->getTranslationUnitKind();
 }
 
 bool ASTMergeAction::hasPCHSupport() const {
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 71f9c0dada8..b8d9f2f8c20 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -97,7 +97,7 @@ static llvm::sys::cas_flag ActiveASTUnitObjects;
 ASTUnit::ASTUnit(bool _MainFileIsAST)
   : OnlyLocalDecls(false), CaptureDiagnostics(false),
     MainFileIsAST(_MainFileIsAST), 
-    CompleteTranslationUnit(true), WantTiming(getenv("LIBCLANG_TIMING")),
+    TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
     OwnsRemappedFileBuffers(true),
     NumStoredDiagnosticsFromDriver(0),
     ConcurrencyCheckValue(CheckUnlocked), 
@@ -759,8 +759,8 @@ public:
   TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
 
   virtual bool hasCodeCompletionSupport() const { return false; }
-  virtual bool usesCompleteTranslationUnit()  { 
-    return Unit.isCompleteTranslationUnit(); 
+  virtual TranslationUnitKind getTranslationUnitKind()  { 
+    return Unit.getTranslationUnitKind(); 
   }
 };
 
@@ -844,7 +844,7 @@ public:
 
   virtual bool hasCodeCompletionSupport() const { return false; }
   virtual bool hasASTFileSupport() const { return false; }
-  virtual bool usesCompleteTranslationUnit() { return false; }
+  virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; }
 };
 
 }
@@ -1592,8 +1592,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
   AST->Diagnostics = Diags;
   AST->OnlyLocalDecls = false;
   AST->CaptureDiagnostics = false;
-  AST->CompleteTranslationUnit = Action ? Action->usesCompleteTranslationUnit()
-                                        : true;
+  AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
   AST->ShouldCacheCodeCompletionResults = false;
   AST->Invocation = CI;
 
@@ -1727,7 +1726,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
                                              bool OnlyLocalDecls,
                                              bool CaptureDiagnostics,
                                              bool PrecompilePreamble,
-                                             bool CompleteTranslationUnit,
+                                             TranslationUnitKind TUKind,
                                              bool CacheCodeCompletionResults,
                                              bool NestedMacroExpansions) {  
   // Create the AST unit.
@@ -1737,7 +1736,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
   AST->Diagnostics = Diags;
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->CaptureDiagnostics = CaptureDiagnostics;
-  AST->CompleteTranslationUnit = CompleteTranslationUnit;
+  AST->TUKind = TUKind;
   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
   AST->Invocation = CI;
   AST->NestedMacroExpansions = NestedMacroExpansions;
@@ -1762,7 +1761,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
                                       unsigned NumRemappedFiles,
                                       bool RemappedFilesKeepOriginalName,
                                       bool PrecompilePreamble,
-                                      bool CompleteTranslationUnit,
+                                      TranslationUnitKind TUKind,
                                       bool CacheCodeCompletionResults,
                                       bool CXXPrecompilePreamble,
                                       bool CXXChainedPCH,
@@ -1828,7 +1827,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
   AST->FileMgr = new FileManager(AST->FileSystemOpts);
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->CaptureDiagnostics = CaptureDiagnostics;
-  AST->CompleteTranslationUnit = CompleteTranslationUnit;
+  AST->TUKind = TUKind;
   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
   AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
   AST->StoredDiagnostics.swap(StoredDiagnostics);
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 026cb5a3d51..ec8b6dc9105 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -382,10 +382,10 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
                                           ShowGlobals, OS);
 }
 
-void CompilerInstance::createSema(bool CompleteTranslationUnit,
+void CompilerInstance::createSema(TranslationUnitKind TUKind,
                                   CodeCompleteConsumer *CompletionConsumer) {
   TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
-                         CompleteTranslationUnit, CompletionConsumer));
+                         TUKind, CompletionConsumer));
 }
 
 // Output Files
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index bc6b08d686a..763c8a1e8bd 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -372,6 +372,7 @@ static const char *getActionName(frontend::ActionKind Kind) {
   case frontend::EmitCodeGenOnly:        return "-emit-codegen-only";
   case frontend::EmitObj:                return "-emit-obj";
   case frontend::FixIt:                  return "-fixit";
+  case frontend::GenerateModule:         return "-emit-module";
   case frontend::GeneratePCH:            return "-emit-pch";
   case frontend::GeneratePTH:            return "-emit-pth";
   case frontend::InitOnly:               return "-init-only";
@@ -1205,6 +1206,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
       // fall-through!
     case OPT_fixit:
       Opts.ProgramAction = frontend::FixIt; break;
+    case OPT_emit_module:
+      Opts.ProgramAction = frontend::GenerateModule; break;
     case OPT_emit_pch:
       Opts.ProgramAction = frontend::GeneratePCH; break;
     case OPT_emit_pth:
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 0753686a347..b92f75ba43e 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -398,7 +398,7 @@ void ASTFrontendAction::ExecuteAction() {
     CompletionConsumer = &CI.getCodeCompletionConsumer();
 
   if (!CI.hasSema())
-    CI.createSema(usesCompleteTranslationUnit(), CompletionConsumer);
+    CI.createSema(getTranslationUnitKind(), CompletionConsumer);
 
   ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats);
 }
@@ -432,8 +432,8 @@ void WrapperFrontendAction::EndSourceFileAction() {
 bool WrapperFrontendAction::usesPreprocessorOnly() const {
   return WrappedAction->usesPreprocessorOnly();
 }
-bool WrapperFrontendAction::usesCompleteTranslationUnit() {
-  return WrappedAction->usesCompleteTranslationUnit();
+TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {
+  return WrappedAction->getTranslationUnitKind();
 }
 bool WrapperFrontendAction::hasPCHSupport() const {
   return WrappedAction->hasPCHSupport();
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index d6df141905a..5e2b9c473f0 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -79,12 +79,13 @@ ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
   std::string OutputFile;
   raw_ostream *OS = 0;
   bool Chaining;
-  if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining))
+  if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, 
+                                  Chaining))
     return 0;
 
   if (!CI.getFrontendOpts().RelocatablePCH)
     Sysroot.clear();
-  return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, Sysroot,
+  return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, Sysroot, 
                           OS);
 }
 
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index ed081923f36..a506b410c5c 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -50,7 +50,8 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
   case EmitCodeGenOnly:        return new EmitCodeGenOnlyAction();
   case EmitObj:                return new EmitObjAction();
   case FixIt:                  return new FixItAction();
-  case GeneratePCH:            return new GeneratePCHAction();
+  case GenerateModule:         return new GeneratePCHAction(true);
+  case GeneratePCH:            return new GeneratePCHAction(false);
   case GeneratePTH:            return new GeneratePTHAction();
   case InitOnly:               return new InitOnlyAction();
   case ParseSyntaxOnly:        return new SyntaxOnlyAction();
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index 5c2c2f785fe..fdd7d0f151a 100644
--- a/lib/Parse/ParseAST.cpp
+++ b/lib/Parse/ParseAST.cpp
@@ -37,11 +37,11 @@ using namespace clang;
 ///
 void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
                      ASTContext &Ctx, bool PrintStats,
-                     bool CompleteTranslationUnit,
+                     TranslationUnitKind TUKind,
                      CodeCompleteConsumer *CompletionConsumer) {
 
   llvm::OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer,
-                                   CompleteTranslationUnit,
+                                   TUKind,
                                    CompletionConsumer));
 
   // Recover resources if we crash before exiting this method.
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index f9da82dbb3b..d3ace9dc69e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -74,7 +74,7 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
 }
 
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
-           bool CompleteTranslationUnit,
+           TranslationUnitKind TUKind,
            CodeCompleteConsumer *CodeCompleter)
   : TheTargetAttributesSema(0), FPFeatures(pp.getLangOptions()),
     LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
@@ -85,7 +85,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
     ObjCShouldCallSuperDealloc(false),
-    CompleteTranslationUnit(CompleteTranslationUnit),
+    TUKind(TUKind),
     NumSFINAEErrors(0), SuppressAccessChecking(false), 
     AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
     NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
@@ -391,9 +391,9 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
 /// translation unit when EOF is reached and all but the top-level scope is
 /// popped.
 void Sema::ActOnEndOfTranslationUnit() {
-  // At PCH writing, implicit instantiations and VTable handling info are
-  // stored and performed when the PCH is included.
-  if (CompleteTranslationUnit) {
+  // Only complete translation units define vtables and perform implicit
+  // instantiations.
+  if (TUKind == TU_Complete) {
     // If any dynamic classes have their key function defined within
     // this translation unit, then those vtables are considered "used" and must
     // be emitted.
@@ -435,7 +435,8 @@ void Sema::ActOnEndOfTranslationUnit() {
                                            this)),
                               UnusedFileScopedDecls.end());
 
-  if (!CompleteTranslationUnit) {
+  if (TUKind == TU_Prefix) {
+    // Translation unit prefixes don't need any of the checking below.
     TUScope = 0;
     return;
   }
@@ -453,6 +454,12 @@ void Sema::ActOnEndOfTranslationUnit() {
       << I->first;
   }
 
+  if (TUKind == TU_Module) {
+    // Modules don't need any of the checking below.
+    TUScope = 0;
+    return;
+  }
+  
   // C99 6.9.2p2:
   //   A declaration of an identifier for an object that has file
   //   scope without an initializer, and without a storage-class
diff --git a/lib/Serialization/ChainedIncludesSource.cpp b/lib/Serialization/ChainedIncludesSource.cpp
index 454e4194abd..4ee1c1667fd 100644
--- a/lib/Serialization/ChainedIncludesSource.cpp
+++ b/lib/Serialization/ChainedIncludesSource.cpp
@@ -111,7 +111,7 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
     Clang->getASTContext().setASTMutationListener(
                                             consumer->GetASTMutationListener());
     Clang->setASTConsumer(consumer.take());
-    Clang->createSema(/*CompleteTranslationUnit=*/false, 0);
+    Clang->createSema(TU_Prefix, 0);
 
     if (firstInclude) {
       Preprocessor &PP = Clang->getPreprocessor();
diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp
index 3f3674e6166..ac395bb2d6f 100644
--- a/lib/Serialization/GeneratePCH.cpp
+++ b/lib/Serialization/GeneratePCH.cpp
@@ -27,7 +27,7 @@
 using namespace clang;
 
 PCHGenerator::PCHGenerator(const Preprocessor &PP,
-                           const std::string &OutputFile,
+                           StringRef OutputFile,
                            bool Chaining,
                            StringRef isysroot,
                            raw_ostream *OS)
diff --git a/test/Modules/Inputs/lookup_left.hpp b/test/Modules/Inputs/lookup_left.hpp
index b5b1e729a9c..66d6206137b 100644
--- a/test/Modules/Inputs/lookup_left.hpp
+++ b/test/Modules/Inputs/lookup_left.hpp
@@ -1 +1,5 @@
 int *f0(int*);
+
+#pragma weak weak_identifier // expected-warning{{weak identifier 'weak_identifier' never declared}}
+
+
diff --git a/test/Modules/lookup.cpp b/test/Modules/lookup.cpp
index ca12a281af8..e9f52b7c669 100644
--- a/test/Modules/lookup.cpp
+++ b/test/Modules/lookup.cpp
@@ -1,4 +1,3 @@
-
 void test(int i, float f) {
   // unqualified lookup
   f0(&i);
@@ -9,8 +8,8 @@ void test(int i, float f) {
   ::f0(&f);
 }
 
-// RUN: %clang_cc1 -emit-pch -x c++ -o %t_lookup_left.h.pch %S/Inputs/lookup_left.hpp
-// RUN: %clang_cc1 -emit-pch -x c++ -o %t_lookup_right.h.pch %S/Inputs/lookup_right.hpp
+// RUN: %clang_cc1 -emit-module -x c++ -verify -o %t_lookup_left.h.pch %S/Inputs/lookup_left.hpp
+// RUN: %clang_cc1 -emit-module -x c++ -o %t_lookup_right.h.pch %S/Inputs/lookup_right.hpp
 // RUN: %clang_cc1 -x c++ -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch -verify %s
 // RUN: %clang_cc1 -ast-print -x c++ -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch %s | FileCheck -check-prefix=CHECK-PRINT %s
 
diff --git a/test/Modules/lookup.m b/test/Modules/lookup.m
index bdffd44b910..85f1dd95d75 100644
--- a/test/Modules/lookup.m
+++ b/test/Modules/lookup.m
@@ -6,8 +6,8 @@ void test(id x) {
   [x method]; // expected-warning{{multiple methods named 'method' found}}
 }
 
-// RUN: %clang_cc1 -emit-pch -x objective-c -o %t_lookup_left.h.pch %S/Inputs/lookup_left.h
-// RUN: %clang_cc1 -emit-pch -x objective-c -o %t_lookup_right.h.pch %S/Inputs/lookup_right.h
+// RUN: %clang_cc1 -emit-module -x objective-c -o %t_lookup_left.h.pch %S/Inputs/lookup_left.h
+// RUN: %clang_cc1 -emit-module -x objective-c -o %t_lookup_right.h.pch %S/Inputs/lookup_right.h
 // RUN: %clang_cc1 -x objective-c -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch -verify %s
 // RUN: %clang_cc1 -ast-print -x objective-c -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch %s | FileCheck -check-prefix=CHECK-PRINT %s
 
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index f1f2cb10adf..5837e0412d9 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -2462,8 +2462,9 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
 
   bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
-  bool CompleteTranslationUnit
-    = ((options & CXTranslationUnit_Incomplete) == 0);
+  // FIXME: Add a flag for modules.
+  TranslationUnitKind TUKind
+    = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete;
   bool CacheCodeCompetionResults
     = options & CXTranslationUnit_CacheCompletionResults;
   bool CXXPrecompilePreamble
@@ -2553,7 +2554,7 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
                                  RemappedFiles->size(),
                                  /*RemappedFilesKeepOriginalName=*/true,
                                  PrecompilePreamble,
-                                 CompleteTranslationUnit,
+                                 TUKind,
                                  CacheCodeCompetionResults,
                                  CXXPrecompilePreamble,
                                  CXXChainedPCH,
-- 
GitLab