static bool recordSourceFileUnit(SourceFile *primarySourceFile, StringRef indexUnitToken, StringRef indexStorePath, bool indexSystemModules, bool isDebugCompilation, StringRef targetTriple, ArrayRef<const clang::FileEntry *> fileDependencies, const clang::CompilerInstance &clangCI, DiagnosticEngine &diags) { auto &fileMgr = clangCI.getFileManager(); auto *module = primarySourceFile->getParentModule(); bool isSystem = module->isSystemModule(); auto *mainFile = fileMgr.getFile(primarySourceFile->getFilename()); // FIXME: Get real values for the following. StringRef swiftVersion; StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot; IndexUnitWriter unitWriter(fileMgr, indexStorePath, "swift", swiftVersion, indexUnitToken, module->getNameStr(), mainFile, isSystem, /*isModuleUnit=*/false, isDebugCompilation, targetTriple, sysrootPath, getModuleInfoFromOpaqueModule); // Module dependencies. ModuleDecl::ImportFilter importFilter; importFilter |= ModuleDecl::ImportFilterKind::Public; importFilter |= ModuleDecl::ImportFilterKind::Private; importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly; SmallVector<ModuleDecl::ImportedModule, 8> imports; primarySourceFile->getImportedModules(imports, importFilter); StringScratchSpace moduleNameScratch; addModuleDependencies(imports, indexStorePath, indexSystemModules, targetTriple, clangCI, diags, unitWriter, moduleNameScratch); // File dependencies. for (auto *F : fileDependencies) unitWriter.addFileDependency(F, /*FIXME:isSystem=*/false, /*Module=*/nullptr); recordSourceFile(primarySourceFile, indexStorePath, diags, [&](StringRef recordFile, StringRef filename) { unitWriter.addRecordFile(recordFile, fileMgr.getFile(filename), module->isSystemModule(), /*Module=*/nullptr); }); std::string error; if (unitWriter.write(error)) { diags.diagnose(SourceLoc(), diag::error_write_index_unit, error); return true; } return false; }
ClangParser() { // Usually all examples try to build the CompilerInstance Object from CompilerInvocation object. // However, CompilterInstance already has an in-built CompilerInvocation object. So we use it. // Only problem is: target options are not set correctly for the in-built object. We do it manually. // This below line is just to assert that the object exist. clang::CompilerInvocation& invocation = m_CompilerInstance.getInvocation(); // Diagnostics is needed - set it up m_CompilerInstance.createDiagnostics(); // set the include directories path clang::HeaderSearchOptions & headerSearchOptions = m_CompilerInstance.getHeaderSearchOpts(); headerSearchOptions.AddPath("C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\include", clang::frontend::IncludeDirGroup::Angled, false, false); // headerSearchOptions.Verbose = true; // set few options clang::LangOptions& langOptions = m_CompilerInstance.getLangOpts(); langOptions.CPlusPlus = 1; langOptions.Bool = 1; langOptions.RTTI = 0; #if defined(_MSC_VER) langOptions.MicrosoftExt = 1; langOptions.MSVCCompat = 1; langOptions.MSBitfields = 1; langOptions.DelayedTemplateParsing = 1; // MSVC parses templates at the time of actual use m_CompilerInstance.getDiagnosticOpts().setFormat(clang::TextDiagnosticFormat::Msvc); //clInstance.getTargetOpts().ABI = "microsoft"; #endif // Need to set the source manager before AST m_CompilerInstance.createFileManager(); m_CompilerInstance.createSourceManager(m_CompilerInstance.getFileManager()); // Need to set the target before AST. Adjust the default target options and create a target m_CompilerInstance.getTargetOpts().Triple = llvm::sys::getProcessTriple(); m_CompilerInstance.setTarget(clang::TargetInfo::CreateTargetInfo(m_CompilerInstance.getDiagnostics(), &m_CompilerInstance.getTargetOpts())); // Create pre-processor and AST Context m_CompilerInstance.createPreprocessor(clang::TranslationUnitKind::TU_Module); m_CompilerInstance.createASTContext(); if (m_CompilerInstance.hasPreprocessor()) { clang::Preprocessor & preprocessor = m_CompilerInstance.getPreprocessor(); preprocessor.getBuiltinInfo().InitializeBuiltins(preprocessor.getIdentifierTable(), preprocessor.getLangOpts()); } }
/// \returns true if an error occurred. static bool emitDataForSwiftSerializedModule(ModuleDecl *module, StringRef indexStorePath, bool indexSystemModules, StringRef targetTriple, const clang::CompilerInstance &clangCI, DiagnosticEngine &diags, IndexUnitWriter &parentUnitWriter) { StringRef filename = module->getModuleFilename(); std::string moduleName = module->getNameStr(); std::string error; auto isUptodateOpt = parentUnitWriter.isUnitUpToDateForOutputFile(/*FilePath=*/filename, /*TimeCompareFilePath=*/filename, error); if (!isUptodateOpt.hasValue()) { diags.diagnose(SourceLoc(), diag::error_index_failed_status_check, error); return true; } if (*isUptodateOpt) return false; // FIXME: Would be useful for testing if swift had clang's -Rremark system so // we could output a remark here that we are going to create index data for // a module file. // Pairs of (recordFile, groupName). std::vector<std::pair<std::string, std::string>> records; if (!module->isStdlibModule()) { std::string recordFile; bool failed = false; auto consumer = makeRecordingConsumer(filename, indexStorePath, &diags, &recordFile, &failed); indexModule(module, /*Hash=*/"", *consumer); if (failed) return true; records.emplace_back(recordFile, moduleName); } else { // Record stdlib groups as if they were submodules. auto makeSubmoduleNameFromGroupName = [](StringRef groupName, SmallString<128> &buf) { buf += "Swift"; if (groupName.empty()) return; buf += '.'; for (char ch : groupName) { if (ch == '/') buf += '.'; else if (ch == ' ' || ch == '-') buf += '_'; else buf += ch; } }; auto appendGroupNameForFilename = [](StringRef groupName, SmallString<256> &buf) { if (groupName.empty()) return; buf += '_'; for (char ch : groupName) { if (ch == '/' || ch ==' ') buf += '_'; else buf += ch; } }; bool failed = false; StdlibGroupsIndexRecordingConsumer groupIndexConsumer([&](StringRef groupName, SymbolTracker &tracker) -> bool { SmallString<128> moduleName; makeSubmoduleNameFromGroupName(groupName, moduleName); SmallString<256> fileNameWithGroup = filename; appendGroupNameForFilename(groupName, fileNameWithGroup); std::string outRecordFile; failed = failed || writeRecord(tracker, fileNameWithGroup.str(), indexStorePath, &diags, outRecordFile); if (failed) return false; records.emplace_back(outRecordFile, moduleName.str()); return true; }); indexModule(module, /*Hash=*/"", groupIndexConsumer); if (failed) return true; } auto &fileMgr = clangCI.getFileManager(); bool isSystem = module->isSystemModule(); // FIXME: Get real values for the following. StringRef swiftVersion; StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot; std::string indexUnitToken = module->getModuleFilename(); // For indexing serialized modules 'debug compilation' is irrelevant, so // set it to true by default. bool isDebugCompilation = true; IndexUnitWriter unitWriter(fileMgr, indexStorePath, "swift", swiftVersion, indexUnitToken, moduleName, /*MainFile=*/nullptr, isSystem, /*IsModuleUnit=*/true, isDebugCompilation, targetTriple, sysrootPath, getModuleInfoFromOpaqueModule); const clang::FileEntry *FE = fileMgr.getFile(filename); bool isSystemModule = module->isSystemModule(); for (auto &pair : records) { std::string &recordFile = pair.first; std::string &groupName = pair.second; if (recordFile.empty()) continue; clang::index::writer::OpaqueModule mod = &groupName; unitWriter.addRecordFile(recordFile, FE, isSystemModule, mod); } ModuleDecl::ImportFilter importFilter; importFilter |= ModuleDecl::ImportFilterKind::Public; importFilter |= ModuleDecl::ImportFilterKind::Private; SmallVector<ModuleDecl::ImportedModule, 8> imports; module->getImportedModules(imports, importFilter); StringScratchSpace moduleNameScratch; addModuleDependencies(imports, indexStorePath, indexSystemModules, targetTriple, clangCI, diags, unitWriter, moduleNameScratch); if (unitWriter.write(error)) { diags.diagnose(SourceLoc(), diag::error_write_index_unit, error); return true; } return false; }