diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp | 306 | 
1 files changed, 205 insertions, 101 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp index 42a67720c353..5576854a7d8b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp @@ -27,6 +27,7 @@  #include "clang/Serialization/ASTWriter.h"  #include "clang/Lex/HeaderSearch.h"  #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h"  #include "clang/Basic/TargetOptions.h"  #include "clang/Basic/TargetInfo.h"  #include "clang/Basic/Diagnostic.h" @@ -180,6 +181,14 @@ void OnDiskData::Cleanup() {    CleanPreambleFile();  } +struct ASTUnit::ASTWriterData { +  SmallString<128> Buffer; +  llvm::BitstreamWriter Stream; +  ASTWriter Writer; + +  ASTWriterData() : Stream(Buffer), Writer(Stream) { } +}; +  void ASTUnit::clearFileLevelDecls() {    for (FileDeclsTy::iterator           I = FileDecls.begin(), E = FileDecls.end(); I != E; ++I) @@ -495,8 +504,8 @@ class ASTInfoCollector : public ASTReaderListener {    ASTContext &Context;    LangOptions &LangOpt;    HeaderSearch &HSI; +  IntrusiveRefCntPtr<TargetOptions> &TargetOpts;    IntrusiveRefCntPtr<TargetInfo> &Target; -  std::string &Predefines;    unsigned &Counter;    unsigned NumHeaderInfos; @@ -504,54 +513,38 @@ class ASTInfoCollector : public ASTReaderListener {    bool InitializedLanguage;  public:    ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,  -                   HeaderSearch &HSI, +                   HeaderSearch &HSI,  +                   IntrusiveRefCntPtr<TargetOptions> &TargetOpts,                     IntrusiveRefCntPtr<TargetInfo> &Target, -                   std::string &Predefines,                     unsigned &Counter) -    : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target), -      Predefines(Predefines), Counter(Counter), NumHeaderInfos(0), +    : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI),  +      TargetOpts(TargetOpts), Target(Target), +      Counter(Counter), NumHeaderInfos(0),        InitializedLanguage(false) {} -  virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { +  virtual bool ReadLanguageOptions(const LangOptions &LangOpts, +                                   bool Complain) {      if (InitializedLanguage)        return false;      LangOpt = LangOpts; -     -    // Initialize the preprocessor. -    PP.Initialize(*Target); -     -    // Initialize the ASTContext -    Context.InitBuiltinTypes(*Target); -          InitializedLanguage = true; +     +    updated();      return false;    } -  virtual bool ReadTargetTriple(StringRef Triple) { +  virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, +                                 bool Complain) {      // If we've already initialized the target, don't do it again.      if (Target)        return false; -    // FIXME: This is broken, we should store the TargetOptions in the AST file. -    TargetOptions TargetOpts; -    TargetOpts.ABI = ""; -    TargetOpts.CXXABI = ""; -    TargetOpts.CPU = ""; -    TargetOpts.Features.clear(); -    TargetOpts.Triple = Triple; -    Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts); -    return false; -  } +    this->TargetOpts = new TargetOptions(TargetOpts); +    Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(),  +                                          *this->TargetOpts); -  virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, -                                    StringRef OriginalFileName, -                                    std::string &SuggestedPredefines, -                                    FileManager &FileMgr) { -    Predefines = Buffers[0].Data; -    for (unsigned I = 1, N = Buffers.size(); I != N; ++I) { -      Predefines += Buffers[I].Data; -    } +    updated();      return false;    } @@ -559,9 +552,27 @@ public:      HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);    } -  virtual void ReadCounter(unsigned Value) { +  virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value) {      Counter = Value;    } + +private: +  void updated() { +    if (!Target || !InitializedLanguage) +      return; + +    // Inform the target of the language options. +    // +    // FIXME: We shouldn't need to do this, the target should be immutable once +    // created. This complexity should be lifted elsewhere. +    Target->setForcedLangOptions(LangOpt); + +    // Initialize the preprocessor. +    PP.Initialize(*Target); + +    // Initialize the ASTContext +    Context.InitBuiltinTypes(*Target); +  }  };  class StoredDiagnosticConsumer : public DiagnosticConsumer { @@ -621,8 +632,10 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,    StoredDiags.push_back(StoredDiagnostic(Level, Info));  } -const std::string &ASTUnit::getOriginalSourceFileName() { -  return OriginalSourceFile; +ASTDeserializationListener *ASTUnit::getDeserializationListener() { +  if (WriterData) +    return &WriterData->Writer; +  return 0;  }  llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename, @@ -638,11 +651,11 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,    if (!Diags.getPtr()) {      // No diagnostics engine was provided, so create our own diagnostics object      // with the default options. -    DiagnosticOptions DiagOpts;      DiagnosticConsumer *Client = 0;      if (CaptureDiagnostics)        Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics); -    Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd-ArgBegin, +    Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(), +                                                ArgEnd-ArgBegin,                                                  ArgBegin, Client,                                                  /*ShouldOwnClient=*/true,                                                  /*ShouldCloneClient=*/false); @@ -679,7 +692,10 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,    AST->SourceMgr = new SourceManager(AST->getDiagnostics(),                                       AST->getFileManager(),                                       UserFilesAreVolatile); -  AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(), +  AST->HSOpts = new HeaderSearchOptions(); +   +  AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, +                                         AST->getFileManager(),                                           AST->getDiagnostics(),                                           AST->ASTFileLangOpts,                                           /*Target=*/0)); @@ -734,12 +750,12 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,    // Gather Info for preprocessor construction later on.    HeaderSearch &HeaderInfo = *AST->HeaderInfo.get(); -  std::string Predefines;    unsigned Counter;    OwningPtr<ASTReader> Reader; -  AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts,  +  AST->PP = new Preprocessor(new PreprocessorOptions(), +                             AST->getDiagnostics(), AST->ASTFileLangOpts,                               /*Target=*/0, AST->getSourceManager(), HeaderInfo,                                *AST,                                /*IILookup=*/0, @@ -757,10 +773,12 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,                              /*DelayInitialization=*/true);    ASTContext &Context = *AST->Ctx; +  bool disableValid = false; +  if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) +    disableValid = true;    Reader.reset(new ASTReader(PP, Context,                               /*isysroot=*/"", -                             /*DisableValidation=*/false, -                             /*DisableStatCache=*/false, +                             /*DisableValidation=*/disableValid,                               AllowPCHWithCompilerErrors));    // Recover resources if we crash before exiting this method. @@ -769,21 +787,25 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,    Reader->setListener(new ASTInfoCollector(*AST->PP, Context,                                             AST->ASTFileLangOpts, HeaderInfo,  -                                           AST->Target, Predefines, Counter)); +                                           AST->TargetOpts, AST->Target,  +                                           Counter)); -  switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) { +  switch (Reader->ReadAST(Filename, serialization::MK_MainFile, +                          ASTReader::ARR_None)) {    case ASTReader::Success:      break;    case ASTReader::Failure: -  case ASTReader::IgnorePCH: +  case ASTReader::OutOfDate: +  case ASTReader::VersionMismatch: +  case ASTReader::ConfigurationMismatch: +  case ASTReader::HadErrors:      AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);      return NULL;    }    AST->OriginalSourceFile = Reader->getOriginalSourceFile(); -  PP.setPredefines(Reader->getSuggestedPredefines());    PP.setCounterValue(Counter);    // Attach the AST reader to the AST context as an external AST @@ -897,6 +919,10 @@ public:      for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)        handleTopLevelDecl(*it);    } + +  virtual ASTDeserializationListener *GetASTDeserializationListener() { +    return Unit.getDeserializationListener(); +  }  };  class TopLevelDeclTrackerAction : public ASTFrontendAction { @@ -1047,14 +1073,13 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {      CCInvocation(new CompilerInvocation(*Invocation));    Clang->setInvocation(CCInvocation.getPtr()); -  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File; +  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();    // Set up diagnostics, capturing any diagnostics that would    // otherwise be dropped.    Clang->setDiagnostics(&getDiagnostics());    // Create the target instance. -  Clang->getTargetOpts().Features = TargetFeatures;    Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),                     Clang->getTargetOpts()));    if (!Clang->hasTarget()) { @@ -1070,9 +1095,9 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {    assert(Clang->getFrontendOpts().Inputs.size() == 1 &&           "Invocation must have exactly one source file!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&           "FIXME: AST inputs not yet supported here!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&           "IR inputs not support here!");    // Configure the various subsystems. @@ -1217,7 +1242,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,    // command line (to another file) or directly through the compiler invocation    // (to a memory buffer).    llvm::MemoryBuffer *Buffer = 0; -  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File); +  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].getFile());    if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {      // Check whether there is a file-file remapping of the main file      for (PreprocessorOptions::remapped_file_iterator @@ -1267,7 +1292,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,    // If the main source file was not remapped, load it now.    if (!Buffer) { -    Buffer = getBufferForFile(FrontendOpts.Inputs[0].File); +    Buffer = getBufferForFile(FrontendOpts.Inputs[0].getFile());      if (!Buffer)        return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));     @@ -1429,7 +1454,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(          // buffer size we reserved when creating the preamble.          return CreatePaddedMainFileBuffer(NewPreamble.first,                                             PreambleReservedSize, -                                          FrontendOpts.Inputs[0].File); +                                          FrontendOpts.Inputs[0].getFile());        }      } @@ -1482,7 +1507,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(    // Save the preamble text for later; we'll need to compare against it for    // subsequent reparses. -  StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].File; +  StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].getFile();    Preamble.assign(FileMgr->getFile(MainFilename),                    NewPreamble.first->getBufferStart(),                     NewPreamble.first->getBufferStart()  @@ -1492,7 +1517,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(    delete PreambleBuffer;    PreambleBuffer      = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize, -                                                FrontendOpts.Inputs[0].File); +                                                FrontendOpts.Inputs[0].getFile());    memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),            NewPreamble.first->getBufferStart(), Preamble.size());    memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),  @@ -1500,7 +1525,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(    const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';      // Remap the main source file to the preamble buffer. -  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File); +  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].getFile());    PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);    // Tell the compiler invocation to generate a temporary precompiled header. @@ -1518,15 +1543,14 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(      CICleanup(Clang.get());    Clang->setInvocation(&*PreambleInvocation); -  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File; +  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();    // Set up diagnostics, capturing all of the diagnostics produced.    Clang->setDiagnostics(&getDiagnostics());    // Create the target instance. -  Clang->getTargetOpts().Features = TargetFeatures;    Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), -                                               Clang->getTargetOpts())); +                                                Clang->getTargetOpts()));    if (!Clang->hasTarget()) {      llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();      Preamble.clear(); @@ -1544,9 +1568,9 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(    assert(Clang->getFrontendOpts().Inputs.size() == 1 &&           "Invocation must have exactly one source file!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&           "FIXME: AST inputs not yet supported here!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&           "IR inputs not support here!");    // Clear out old caches and data. @@ -1633,7 +1657,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(    return CreatePaddedMainFileBuffer(NewPreamble.first,                                       PreambleReservedSize, -                                    FrontendOpts.Inputs[0].File); +                                    FrontendOpts.Inputs[0].getFile());  }  void ASTUnit::RealizeTopLevelDeclsFromPreamble() { @@ -1664,7 +1688,7 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {  }  StringRef ASTUnit::getMainFileName() const { -  return Invocation->getFrontendOpts().Inputs[0].File; +  return Invocation->getFrontendOpts().Inputs[0].getFile();  }  ASTUnit *ASTUnit::create(CompilerInvocation *CI, @@ -1733,9 +1757,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,    CI->getFrontendOpts().DisableFree = false;    ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); -  // Save the target features. -  AST->TargetFeatures = CI->getTargetOpts().Features; -    // Create the compiler instance to use for building the AST.    OwningPtr<CompilerInstance> Clang(new CompilerInstance()); @@ -1744,14 +1765,13 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,      CICleanup(Clang.get());    Clang->setInvocation(CI); -  AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File; +  AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();    // Set up diagnostics, capturing any diagnostics that would    // otherwise be dropped.    Clang->setDiagnostics(&AST->getDiagnostics());    // Create the target instance. -  Clang->getTargetOpts().Features = AST->TargetFeatures;    Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),                     Clang->getTargetOpts()));    if (!Clang->hasTarget()) @@ -1765,9 +1785,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,    assert(Clang->getFrontendOpts().Inputs.size() == 1 &&           "Invocation must have exactly one source file!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&           "FIXME: AST inputs not yet supported here!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&           "IR inputs not supported here!");    // Configure the various subsystems. @@ -1840,9 +1860,6 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {    Invocation->getFrontendOpts().DisableFree = false;    ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); -  // Save the target features. -  TargetFeatures = Invocation->getTargetOpts().Features; -      llvm::MemoryBuffer *OverrideMainBuffer = 0;    if (PrecompilePreamble) {      PreambleRebuildCounter = 2; @@ -1909,12 +1926,13 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,                                        bool AllowPCHWithCompilerErrors,                                        bool SkipFunctionBodies,                                        bool UserFilesAreVolatile, +                                      bool ForSerialization,                                        OwningPtr<ASTUnit> *ErrAST) {    if (!Diags.getPtr()) {      // No diagnostics engine was provided, so create our own diagnostics object      // with the default options. -    DiagnosticOptions DiagOpts; -    Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin,  +    Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(), +                                                ArgEnd - ArgBegin,                                                  ArgBegin);    } @@ -1972,6 +1990,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,    AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();    AST->StoredDiagnostics.swap(StoredDiagnostics);    AST->Invocation = CI; +  if (ForSerialization) +    AST->WriterData.reset(new ASTWriterData());    CI = 0; // Zero out now to ease cleanup during crash recovery.    // Recover resources if we crash before exiting this method. @@ -2002,7 +2022,6 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {    // Remap files.    PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); -  PPOpts.DisableStatCache = true;    for (PreprocessorOptions::remapped_file_buffer_iterator            R = PPOpts.remapped_file_buffer_begin(),           REnd = PPOpts.remapped_file_buffer_end(); @@ -2238,7 +2257,6 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,      // Adjust priority based on similar type classes.      unsigned Priority = C->Priority; -    CXCursorKind CursorKind = C->Kind;      CodeCompletionString *Completion = C->Completion;      if (!Context.getPreferredType().isNull()) {        if (C->Kind == CXCursor_MacroDefinition) { @@ -2272,12 +2290,11 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,        CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),                                      CCP_CodePattern, C->Availability);        Builder.AddTypedTextChunk(C->Completion->getTypedText()); -      CursorKind = CXCursor_NotImplemented;        Priority = CCP_CodePattern;        Completion = Builder.TakeString();      } -    AllResults.push_back(Result(Completion, Priority, CursorKind,  +    AllResults.push_back(Result(Completion, Priority, C->Kind,                                  C->Availability));    } @@ -2341,7 +2358,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,      CICleanup(Clang.get());    Clang->setInvocation(&*CCInvocation); -  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File; +  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();    // Set up diagnostics, capturing any diagnostics produced.    Clang->setDiagnostics(&Diag); @@ -2351,7 +2368,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,                                      StoredDiagnostics);    // Create the target instance. -  Clang->getTargetOpts().Features = TargetFeatures;    Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),                                                 Clang->getTargetOpts()));    if (!Clang->hasTarget()) { @@ -2367,9 +2383,9 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,    assert(Clang->getFrontendOpts().Inputs.size() == 1 &&           "Invocation must have exactly one source file!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&           "FIXME: AST inputs not yet supported here!"); -  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR && +  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&           "IR inputs not support here!"); @@ -2398,8 +2414,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,      = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);    Clang->setCodeCompletionConsumer(AugmentedConsumer); -  Clang->getFrontendOpts().SkipFunctionBodies = true; -    // If we have a precompiled preamble, try to use it. We only allow    // the use of the precompiled preamble if we're if the completion    // point is within the main file, after the end of the precompiled @@ -2420,7 +2434,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,    // If the main file has been overridden due to the use of a preamble,    // make that override happen and introduce the preamble. -  PreprocessorOpts.DisableStatCache = true;    StoredDiagnostics.insert(StoredDiagnostics.end(),                             stored_diag_begin(),                             stored_diag_afterDriver_begin()); @@ -2438,8 +2451,9 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,      PreprocessorOpts.PrecompiledPreambleBytes.second = false;    } -  // Disable the preprocessing record -  PreprocessorOpts.DetailedRecord = false; +  // Disable the preprocessing record if modules are not enabled. +  if (!Clang->getLangOpts().Modules) +    PreprocessorOpts.DetailedRecord = false;    OwningPtr<SyntaxOnlyAction> Act;    Act.reset(new SyntaxOnlyAction); @@ -2457,7 +2471,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,    checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());  } -CXSaveError ASTUnit::Save(StringRef File) { +bool ASTUnit::Save(StringRef File) {    // Write to a temporary file and later rename it to the actual file, to avoid    // possible race conditions.    SmallString<128> TempPath; @@ -2466,7 +2480,7 @@ CXSaveError ASTUnit::Save(StringRef File) {    int fd;    if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,                                   /*makeAbsolute=*/false)) -    return CXSaveError_Unknown; +    return true;    // FIXME: Can we somehow regenerate the stat cache here, or do we need to     // unconditionally create a stat cache when we parse the file? @@ -2476,32 +2490,43 @@ CXSaveError ASTUnit::Save(StringRef File) {    Out.close();    if (Out.has_error()) {      Out.clear_error(); -    return CXSaveError_Unknown; +    return true;    }    if (llvm::sys::fs::rename(TempPath.str(), File)) {      bool exists;      llvm::sys::fs::remove(TempPath.str(), exists); -    return CXSaveError_Unknown; +    return true;    } -  return CXSaveError_None; +  return false; +} + +static bool serializeUnit(ASTWriter &Writer, +                          SmallVectorImpl<char> &Buffer, +                          Sema &S, +                          bool hasErrors, +                          raw_ostream &OS) { +  Writer.WriteAST(S, std::string(), 0, "", hasErrors); + +  // Write the generated bitstream to "Out". +  if (!Buffer.empty()) +    OS.write(Buffer.data(), Buffer.size()); + +  return false;  }  bool ASTUnit::serialize(raw_ostream &OS) {    bool hasErrors = getDiagnostics().hasErrorOccurred(); +  if (WriterData) +    return serializeUnit(WriterData->Writer, WriterData->Buffer, +                         getSema(), hasErrors, OS); +    SmallString<128> Buffer;    llvm::BitstreamWriter Stream(Buffer);    ASTWriter Writer(Stream); -  // FIXME: Handle modules -  Writer.WriteAST(getSema(), 0, std::string(), 0, "", hasErrors); -   -  // Write the generated bitstream to "Out". -  if (!Buffer.empty()) -    OS.write((char *)&Buffer.front(), Buffer.size()); - -  return false; +  return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);  }  typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap; @@ -2761,6 +2786,85 @@ SourceLocation ASTUnit::getStartOfMainFileID() {    return SourceMgr->getLocForStartOfFile(FID);  } +std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> +ASTUnit::getLocalPreprocessingEntities() const { +  if (isMainFileAST()) { +    serialization::ModuleFile & +      Mod = Reader->getModuleManager().getPrimaryModule(); +    return Reader->getModulePreprocessedEntities(Mod); +  } + +  if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord()) +    return std::make_pair(PPRec->local_begin(), PPRec->local_end()); + +  return std::make_pair(PreprocessingRecord::iterator(), +                        PreprocessingRecord::iterator()); +} + +bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) { +  if (isMainFileAST()) { +    serialization::ModuleFile & +      Mod = Reader->getModuleManager().getPrimaryModule(); +    ASTReader::ModuleDeclIterator MDI, MDE; +    llvm::tie(MDI, MDE) = Reader->getModuleFileLevelDecls(Mod); +    for (; MDI != MDE; ++MDI) { +      if (!Fn(context, *MDI)) +        return false; +    } + +    return true; +  } + +  for (ASTUnit::top_level_iterator TL = top_level_begin(), +                                TLEnd = top_level_end(); +         TL != TLEnd; ++TL) { +    if (!Fn(context, *TL)) +      return false; +  } + +  return true; +} + +namespace { +struct PCHLocatorInfo { +  serialization::ModuleFile *Mod; +  PCHLocatorInfo() : Mod(0) {} +}; +} + +static bool PCHLocator(serialization::ModuleFile &M, void *UserData) { +  PCHLocatorInfo &Info = *static_cast<PCHLocatorInfo*>(UserData); +  switch (M.Kind) { +  case serialization::MK_Module: +    return true; // skip dependencies. +  case serialization::MK_PCH: +    Info.Mod = &M; +    return true; // found it. +  case serialization::MK_Preamble: +    return false; // look in dependencies. +  case serialization::MK_MainFile: +    return false; // look in dependencies. +  } + +  return true; +} + +const FileEntry *ASTUnit::getPCHFile() { +  if (!Reader) +    return 0; + +  PCHLocatorInfo Info; +  Reader->getModuleManager().visit(PCHLocator, &Info); +  if (Info.Mod) +    return Info.Mod->File; + +  return 0; +} + +bool ASTUnit::isModuleFile() { +  return isMainFileAST() && !ASTFileLangOpts.CurrentModule.empty(); +} +  void ASTUnit::PreambleData::countLines() const {    NumLines = 0;    if (empty())  | 
