Пример #1
0
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
  // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module
  // that it depends on.

  bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls();

  if (OnlyLocal) {
    for (ASTUnit::top_level_iterator TL = Unit.top_level_begin(),
                                  TLEnd = Unit.top_level_end();
           TL != TLEnd; ++TL) {
      IdxCtx.indexTopLevelDecl(*TL);
      if (IdxCtx.shouldAbort())
        return;
    }

  } else {
    TranslationUnitDecl *TUDecl = Unit.getASTContext().getTranslationUnitDecl();
    for (TranslationUnitDecl::decl_iterator
           I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; ++I) {
      IdxCtx.indexTopLevelDecl(*I);
      if (IdxCtx.shouldAbort())
        return;
    }
  }
}
Пример #2
0
bool SerializationTest::Serialize(llvm::sys::Path& Filename,
                                  llvm::sys::Path& FNameDeclPrint,
                                  ASTContext &Ctx) {
    {
        // Pretty-print the decls to a temp file.
        std::string Err;
        llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), true, Err);
        assert (Err.empty() && "Could not open file for printing out decls.");
        llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));

        TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl();
        for (DeclContext::decl_iterator I = TUD->decls_begin(Ctx),
                E = TUD->decls_end(Ctx);
                I != E; ++I)
            FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
    }

    // Serialize the translation unit.

    // Reserve 256K for bitstream buffer.
    std::vector<unsigned char> Buffer;
    Buffer.reserve(256*1024);

    Ctx.EmitASTBitcodeBuffer(Buffer);

    // Write the bits to disk.
    if (FILE* fp = fopen(Filename.c_str(),"wb")) {
        fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
        fclose(fp);
        return true;
    }

    return false;
}
bool FlattenCFGTransformer::execute() {
	this->renamer = new VarRenamer(this->resMgr);
	this->preTranser = new StmtPretransformer(this->resMgr);
	OwningPtr<RefVarToPtrMap> refMap(new RefVarToPtrMap(0));
	assert(refMap.get() && "reference variable map alloc failed");
	this->dclMover = new LocalDeclMover(this->resMgr, refMap.get());
	this->flat = new CFGFlattener(this->resMgr);

	TranslationUnitDecl *decls = this->resMgr.getCompilerInstance().getASTContext().getTranslationUnitDecl();
	for(TranslationUnitDecl::decl_iterator I = decls->decls_begin(), E = decls->decls_end();
			I != E; ++I) {
		Decl *D = *I;
		DPRINT("TUDecl %s %x | Ctx %x -> p %x", D->getDeclKindName(), (unsigned int)D, (unsigned int)D->getDeclContext(), (unsigned int)decls);
		SourceLocation Loc = D->getLocation();

		if(Loc.isInvalid() 
				|| this->compInst.getSourceManager().isInSystemHeader(Loc)){
			continue;
		}

		if(HandleAnyFunctionDecl(D)) {
			continue;
		} else if(HandleAnyClassDecl(D)) {
			continue;
		}
	}

	delete this->renamer;
	delete this->preTranser;
	delete this->dclMover;
	delete this->flat;
	refMap.reset();

	return true;
}
Пример #4
0
void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
  
  TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
  if (MigrateProperty)
    for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
         D != DEnd; ++D) {
      if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
        migrateObjCInterfaceDecl(Ctx, CDecl);
      else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
        ObjCProtocolDecls.insert(PDecl);
      else if (const ObjCImplementationDecl *ImpDecl =
               dyn_cast<ObjCImplementationDecl>(*D))
        migrateProtocolConformance(Ctx, ImpDecl);
      else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
        DeclContext::decl_iterator N = D;
        ++N;
        if (N != DEnd)
          if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N))
            migrateNSEnumDecl(Ctx, ED, TD);
      }
      // migrate methods which can have instancetype as their result type.
      if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D))
        migrateInstanceType(Ctx, CDecl);
    }
  
  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
  RewritesReceiver Rec(rewriter);
  Editor->applyRewrites(Rec);

  for (Rewriter::buffer_iterator
        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
    FileID FID = I->first;
    RewriteBuffer &buf = I->second;
    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
    assert(file);
    SmallString<512> newText;
    llvm::raw_svector_ostream vecOS(newText);
    buf.write(vecOS);
    vecOS.flush();
    llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
                   StringRef(newText.data(), newText.size()), file->getName());
    SmallString<64> filePath(file->getName());
    FileMgr.FixupRelativePath(filePath);
    Remapper.remap(filePath.str(), memBuf);
  }

  if (IsOutputFile) {
    Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
  } else {
    Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
  }
}
Пример #5
0
 void ClangInternalState::printAST(llvm::raw_ostream& Out, ASTContext& C) {
   TranslationUnitDecl* TU = C.getTranslationUnitDecl();
   unsigned Indentation = 0;
   bool PrintInstantiation = false;
   std::string ErrMsg;
   clang::PrintingPolicy policy = C.getPrintingPolicy();
   TU->print(Out, policy, Indentation, PrintInstantiation);
   // TODO: For future when we relpace the bump allocation with slab.
   //
   //Out << "Allocated memory: " << C.getAllocatedMemory();
   //Out << "Side table allocated memory: " << C.getSideTableAllocatedMemory();
   Out.flush();
 }
Пример #6
0
void ASTMergeAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  CI.getDiagnostics().getClient()->BeginSourceFile(
                                             CI.getASTContext().getLangOpts());
  CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
                                       &CI.getASTContext());
  IntrusiveRefCntPtr<DiagnosticIDs>
      DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
  for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
    IntrusiveRefCntPtr<DiagnosticsEngine>
        Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(),
                                    new ForwardingDiagnosticConsumer(
                                          *CI.getDiagnostics().getClient()),
                                    /*ShouldOwnClient=*/true));
    std::unique_ptr<ASTUnit> Unit =
        ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerOperations(),
                                 Diags, CI.getFileSystemOpts(), false);

    if (!Unit)
      continue;

    ASTImporter Importer(CI.getASTContext(), 
                         CI.getFileManager(),
                         Unit->getASTContext(), 
                         Unit->getFileManager(),
                         /*MinimalImport=*/false);

    TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
    CI.getASTConsumer().Initialize(CI.getASTContext());
    for (auto *D : TU->decls()) {
      // Don't re-import __va_list_tag, __builtin_va_list.
      if (const auto *ND = dyn_cast<NamedDecl>(D))
        if (IdentifierInfo *II = ND->getIdentifier())
          if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list"))
            continue;
      
      Decl *ToD = Importer.Import(D);
    
      if (ToD) {
        DeclGroupRef DGR(ToD);
        CI.getASTConsumer().HandleTopLevelDecl(DGR);
      }
    }
  }

  AdaptedAction->ExecuteAction();
  CI.getDiagnostics().getClient()->EndSourceFile();
}
Пример #7
0
void ASTMergeAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  CI.getDiagnostics().getClient()->BeginSourceFile(
                                             CI.getASTContext().getLangOpts());
  CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
                                       &CI.getASTContext());
  IntrusiveRefCntPtr<DiagnosticIDs>
      DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
  for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
    IntrusiveRefCntPtr<DiagnosticsEngine>
        Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(),
                                    new ForwardingDiagnosticConsumer(
                                          *CI.getDiagnostics().getClient()),
                                    /*ShouldOwnClient=*/true));
    ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
                                             CI.getFileSystemOpts(), false);
    if (!Unit)
      continue;

    ASTImporter Importer(CI.getASTContext(), 
                         CI.getFileManager(),
                         Unit->getASTContext(), 
                         Unit->getFileManager(),
                         /*MinimalImport=*/false);

    TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
    for (DeclContext::decl_iterator D = TU->decls_begin(), 
                                 DEnd = TU->decls_end();
         D != DEnd; ++D) {
      // Don't re-import __va_list_tag, __builtin_va_list.
      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
        if (IdentifierInfo *II = ND->getIdentifier())
          if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list"))
            continue;
      
      Importer.Import(*D);
    }

    delete Unit;
  }

  AdaptedAction->ExecuteAction();
  CI.getDiagnostics().getClient()->EndSourceFile();
}
Пример #8
0
bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
                                    llvm::sys::Path& FNameDeclPrint) {

    // Deserialize the translation unit.
    ASTContext *NewCtx;

    {
        // Create the memory buffer that contains the contents of the file.
        llvm::OwningPtr<llvm::MemoryBuffer>
        MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str()));

        if (!MBuffer)
            return false;

        NewCtx = ASTContext::ReadASTBitcodeBuffer(*MBuffer, FMgr);
    }

    if (!NewCtx)
        return false;

    {
        // Pretty-print the deserialized decls to a temp file.
        std::string Err;
        llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), true, Err);
        assert (Err.empty() && "Could not open file for printing out decls.");
        llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));

        TranslationUnitDecl *TUD = NewCtx->getTranslationUnitDecl();
        for (DeclContext::decl_iterator I = TUD->decls_begin(*NewCtx),
                E = TUD->decls_end(*NewCtx);
                I != E; ++I)
            FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
    }

    delete NewCtx;

    return true;
}
Пример #9
0
void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
  
  TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
  for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
       D != DEnd; ++D) {
    if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
      migrateObjCInterfaceDecl(Ctx, CDecl);
  }
  
  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
  RewritesReceiver Rec(rewriter);
  Editor->applyRewrites(Rec);

  for (Rewriter::buffer_iterator
        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
    FileID FID = I->first;
    RewriteBuffer &buf = I->second;
    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
    assert(file);
    SmallString<512> newText;
    llvm::raw_svector_ostream vecOS(newText);
    buf.write(vecOS);
    vecOS.flush();
    llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
                   StringRef(newText.data(), newText.size()), file->getName());
    SmallString<64> filePath(file->getName());
    FileMgr.FixupRelativePath(filePath);
    Remapper.remap(filePath.str(), memBuf);
  }

  if (IsOutputFile) {
    Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
  } else {
    Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
  }
}
ModuleLoadResult
CompilerInstance::loadModule(SourceLocation ImportLoc,
                             ModuleIdPath Path,
                             Module::NameVisibilityKind Visibility,
                             bool IsInclusionDirective) {
  // If we've already handled this import, just return the cached result.
  // This one-element cache is important to eliminate redundant diagnostics
  // when both the preprocessor and parser see the same import declaration.
  if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) {
    // Make the named module visible.
    if (LastModuleImportResult)
      ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility);
    return LastModuleImportResult;
  }
  
  // Determine what file we're searching from.
  StringRef ModuleName = Path[0].first->getName();
  SourceLocation ModuleNameLoc = Path[0].second;

  clang::Module *Module = 0;
  
  // If we don't already have information on this module, load the module now.
  llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known
    = KnownModules.find(Path[0].first);
  if (Known != KnownModules.end()) {
    // Retrieve the cached top-level module.
    Module = Known->second;    
  } else if (ModuleName == getLangOpts().CurrentModule) {
    // This is the module we're building. 
    Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName);
    Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
  } else {
    // Search for a module with the given name.
    Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
    std::string ModuleFileName;
    if (Module)
      ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
    else
      ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName);

    if (ModuleFileName.empty()) {
      getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
        << ModuleName
        << SourceRange(ImportLoc, ModuleNameLoc);
      LastModuleImportLoc = ImportLoc;
      LastModuleImportResult = ModuleLoadResult();
      return LastModuleImportResult;
    }
    
    const FileEntry *ModuleFile
      = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false,
                                 /*CacheFailure=*/false);
    bool BuildingModule = false;
    if (!ModuleFile && Module) {
      // The module is not cached, but we have a module map from which we can
      // build the module.

      // Check whether there is a cycle in the module graph.
      ModuleBuildStack Path = getSourceManager().getModuleBuildStack();
      ModuleBuildStack::iterator Pos = Path.begin(), PosEnd = Path.end();
      for (; Pos != PosEnd; ++Pos) {
        if (Pos->first == ModuleName)
          break;
      }

      if (Pos != PosEnd) {
        SmallString<256> CyclePath;
        for (; Pos != PosEnd; ++Pos) {
          CyclePath += Pos->first;
          CyclePath += " -> ";
        }
        CyclePath += ModuleName;

        getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
          << ModuleName << CyclePath;
        return ModuleLoadResult();
      }

      // Check whether we have already attempted to build this module (but
      // failed).
      if (getPreprocessorOpts().FailedModules &&
          getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
        getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
          << ModuleName
          << SourceRange(ImportLoc, ModuleNameLoc);

        return ModuleLoadResult();
      }

      BuildingModule = true;
      compileModule(*this, ModuleNameLoc, Module, ModuleFileName);
      ModuleFile = FileMgr->getFile(ModuleFileName);

      if (!ModuleFile && getPreprocessorOpts().FailedModules)
        getPreprocessorOpts().FailedModules->addFailed(ModuleName);
    }

    if (!ModuleFile) {
      getDiagnostics().Report(ModuleNameLoc,
                              BuildingModule? diag::err_module_not_built
                                            : diag::err_module_not_found)
        << ModuleName
        << SourceRange(ImportLoc, ModuleNameLoc);
      return ModuleLoadResult();
    }

    // If we don't already have an ASTReader, create one now.
    if (!ModuleManager) {
      if (!hasASTContext())
        createASTContext();

      std::string Sysroot = getHeaderSearchOpts().Sysroot;
      const PreprocessorOptions &PPOpts = getPreprocessorOpts();
      ModuleManager = new ASTReader(getPreprocessor(), *Context,
                                    Sysroot.empty() ? "" : Sysroot.c_str(),
                                    PPOpts.DisablePCHValidation);
      if (hasASTConsumer()) {
        ModuleManager->setDeserializationListener(
          getASTConsumer().GetASTDeserializationListener());
        getASTContext().setASTMutationListener(
          getASTConsumer().GetASTMutationListener());
        getPreprocessor().setPPMutationListener(
          getASTConsumer().GetPPMutationListener());
      }
      OwningPtr<ExternalASTSource> Source;
      Source.reset(ModuleManager);
      getASTContext().setExternalSource(Source);
      if (hasSema())
        ModuleManager->InitializeSema(getSema());
      if (hasASTConsumer())
        ModuleManager->StartTranslationUnit(&getASTConsumer());
    }

    // Try to load the module we found.
    unsigned ARRFlags = ASTReader::ARR_None;
    if (Module)
      ARRFlags |= ASTReader::ARR_OutOfDate;
    switch (ModuleManager->ReadAST(ModuleFile->getName(),
                                   serialization::MK_Module, ImportLoc,
                                   ARRFlags)) {
    case ASTReader::Success:
      break;

    case ASTReader::OutOfDate: {
      // The module file is out-of-date. Rebuild it.
      getFileManager().invalidateCache(ModuleFile);
      bool Existed;
      llvm::sys::fs::remove(ModuleFileName, Existed);

      // Check whether we have already attempted to build this module (but
      // failed).
      if (getPreprocessorOpts().FailedModules &&
          getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
        getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
          << ModuleName
          << SourceRange(ImportLoc, ModuleNameLoc);

        return ModuleLoadResult();
      }

      compileModule(*this, ModuleNameLoc, Module, ModuleFileName);

      // Try loading the module again.
      ModuleFile = FileMgr->getFile(ModuleFileName);
      if (!ModuleFile ||
          ModuleManager->ReadAST(ModuleFileName,
                                 serialization::MK_Module, ImportLoc,
                                 ASTReader::ARR_None) != ASTReader::Success) {
        if (getPreprocessorOpts().FailedModules)
          getPreprocessorOpts().FailedModules->addFailed(ModuleName);
        KnownModules[Path[0].first] = 0;
        return ModuleLoadResult();
      }

      // Okay, we've rebuilt and now loaded the module.
      break;
    }

    case ASTReader::VersionMismatch:
    case ASTReader::ConfigurationMismatch:
    case ASTReader::HadErrors:
      // FIXME: The ASTReader will already have complained, but can we showhorn
      // that diagnostic information into a more useful form?
      KnownModules[Path[0].first] = 0;
      return ModuleLoadResult();

    case ASTReader::Failure:
      // Already complained, but note now that we failed.
      KnownModules[Path[0].first] = 0;
      return ModuleLoadResult();
    }
    
    if (!Module) {
      // If we loaded the module directly, without finding a module map first,
      // we'll have loaded the module's information from the module itself.
      Module = PP->getHeaderSearchInfo().getModuleMap()
                 .findModule((Path[0].first->getName()));
    }

    if (Module)
      Module->setASTFile(ModuleFile);
    
    // Cache the result of this top-level module lookup for later.
    Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
  }
  
  // If we never found the module, fail.
  if (!Module)
    return ModuleLoadResult();
  
  // Verify that the rest of the module path actually corresponds to
  // a submodule.
  if (Path.size() > 1) {
    for (unsigned I = 1, N = Path.size(); I != N; ++I) {
      StringRef Name = Path[I].first->getName();
      clang::Module *Sub = Module->findSubmodule(Name);
      
      if (!Sub) {
        // Attempt to perform typo correction to find a module name that works.
        llvm::SmallVector<StringRef, 2> Best;
        unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
        
        for (clang::Module::submodule_iterator J = Module->submodule_begin(), 
                                            JEnd = Module->submodule_end();
             J != JEnd; ++J) {
          unsigned ED = Name.edit_distance((*J)->Name,
                                           /*AllowReplacements=*/true,
                                           BestEditDistance);
          if (ED <= BestEditDistance) {
            if (ED < BestEditDistance) {
              Best.clear();
              BestEditDistance = ED;
            }
            
            Best.push_back((*J)->Name);
          }
        }
        
        // If there was a clear winner, user it.
        if (Best.size() == 1) {
          getDiagnostics().Report(Path[I].second, 
                                  diag::err_no_submodule_suggest)
            << Path[I].first << Module->getFullModuleName() << Best[0]
            << SourceRange(Path[0].second, Path[I-1].second)
            << FixItHint::CreateReplacement(SourceRange(Path[I].second),
                                            Best[0]);
          
          Sub = Module->findSubmodule(Best[0]);
        }
      }
      
      if (!Sub) {
        // No submodule by this name. Complain, and don't look for further
        // submodules.
        getDiagnostics().Report(Path[I].second, diag::err_no_submodule)
          << Path[I].first << Module->getFullModuleName()
          << SourceRange(Path[0].second, Path[I-1].second);
        break;
      }
      
      Module = Sub;
    }
  }
  
  // Make the named module visible, if it's not already part of the module
  // we are parsing.
  if (ModuleName != getLangOpts().CurrentModule) {
    if (!Module->IsFromModuleFile) {
      // We have an umbrella header or directory that doesn't actually include
      // all of the headers within the directory it covers. Complain about
      // this missing submodule and recover by forgetting that we ever saw
      // this submodule.
      // FIXME: Should we detect this at module load time? It seems fairly
      // expensive (and rare).
      getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
        << Module->getFullModuleName()
        << SourceRange(Path.front().second, Path.back().second);
      
      return ModuleLoadResult(0, true);
    }

    // Check whether this module is available.
    StringRef Feature;
    if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) {
      getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
        << Module->getFullModuleName()
        << Feature
        << SourceRange(Path.front().second, Path.back().second);
      LastModuleImportLoc = ImportLoc;
      LastModuleImportResult = ModuleLoadResult();
      return ModuleLoadResult();
    }

    ModuleManager->makeModuleVisible(Module, Visibility);
  }
  
  // If this module import was due to an inclusion directive, create an 
  // implicit import declaration to capture it in the AST.
  if (IsInclusionDirective && hasASTContext()) {
    TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
    ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
                                                     ImportLoc, Module,
                                                     Path.back().second);
    TU->addDecl(ImportD);
    if (Consumer)
      Consumer->HandleImplicitImportDecl(ImportD);
  }
  
  LastModuleImportLoc = ImportLoc;
  LastModuleImportResult = ModuleLoadResult(Module, false);
  return LastModuleImportResult;
}