void c2ffi::init_ci(config &c, clang::CompilerInstance &ci) { using clang::DiagnosticOptions; using clang::TextDiagnosticPrinter; using clang::TargetOptions; using clang::TargetInfo; ci.getInvocation().setLangDefaults(ci.getLangOpts(), c.kind, clang::LangStandard::lang_unspecified); DiagnosticOptions *dopt = new DiagnosticOptions; TextDiagnosticPrinter *tpd = new TextDiagnosticPrinter(llvm::errs(), dopt, false); ci.createDiagnostics(tpd); llvm::IntrusiveRefCntPtr<TargetOptions> *pto = new llvm::IntrusiveRefCntPtr<TargetOptions>(new TargetOptions()); if(c.arch == "") (*pto)->Triple = llvm::sys::getDefaultTargetTriple(); else (*pto)->Triple = c.arch; TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto->getPtr()); ci.setTarget(pti); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(clang::TU_Complete); ci.getPreprocessorOpts().UsePredefines = false; }
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; }
void prepareCompilerforFile(const char* szSourceCodeFilePath) { // To reuse the source manager we have to create these tables. m_CompilerInstance.getSourceManager().clearIDTables(); //m_CompilerInstance.InitializeSourceManager(clang::FrontendInputFile(szSourceCodeFilePath, clang::InputKind::IK_C));// ger(m_CompilerInstance.getFileManager()); // supply the file to the source manager and set it as main-file const clang::FileEntry * file = m_CompilerInstance.getFileManager().getFile(szSourceCodeFilePath); clang::FileID fileID = m_CompilerInstance.getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::CharacteristicKind::C_User); m_CompilerInstance.getSourceManager().setMainFileID(fileID); // CodeGenAction needs this clang::FrontendOptions& feOptions = m_CompilerInstance.getFrontendOpts(); feOptions.Inputs.clear(); feOptions.Inputs.push_back(clang::FrontendInputFile(szSourceCodeFilePath, clang::FrontendOptions::getInputKindForExtension(clang::StringRef(szSourceCodeFilePath).rsplit('.').second), 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()); } }
void c2ffi::init_ci(config &c, clang::CompilerInstance &ci) { using clang::DiagnosticOptions; using clang::TextDiagnosticPrinter; using clang::TargetOptions; using clang::TargetInfo; DiagnosticOptions *dopt = new DiagnosticOptions; TextDiagnosticPrinter *tpd = new TextDiagnosticPrinter(llvm::errs(), dopt, false); ci.createDiagnostics(tpd); std::shared_ptr<TargetOptions> pto = std::shared_ptr<TargetOptions>(new TargetOptions()); if(c.arch == "") pto->Triple = llvm::sys::getDefaultTargetTriple(); else pto->Triple = c.arch; TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto); clang::LangOptions &lo = ci.getLangOpts(); switch(pti->getTriple().getEnvironment()) { case llvm::Triple::EnvironmentType::GNU: lo.GNUMode = 1; break; case llvm::Triple::EnvironmentType::MSVC: lo.MSVCCompat = 1; lo.MicrosoftExt = 1; break; default: std::cerr << "c2ffi warning: Unhandled environment: '" << pti->getTriple().getEnvironmentName().str() << "' for triple '" << c.arch << "'" << std::endl; } ci.getInvocation().setLangDefaults(lo, c.kind, c.std); ci.setTarget(pti); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(clang::TU_Complete); ci.getPreprocessorOpts().UsePredefines = false; ci.getPreprocessorOutputOpts().ShowCPP = c.preprocess_only; ci.getPreprocessor().setPreprocessedOutput(c.preprocess_only); }
void c2ffi::add_include(clang::CompilerInstance &ci, const char *path, bool is_angled, bool show_error) { struct stat buf; if(stat(path, &buf) < 0 || !S_ISDIR(buf.st_mode)) { if(show_error) { std::cerr << "Error: Not a directory: "; if(is_angled) std::cerr << "-i "; else std::cerr << "-I "; std::cerr << path << std::endl; exit(1); } return; } const clang::DirectoryEntry *dirent = ci.getFileManager().getDirectory(path); clang::DirectoryLookup lookup(dirent, clang::SrcMgr::C_System, false); ci.getPreprocessor().getHeaderSearchInfo() .AddSearchPath(lookup, is_angled); }
/// \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; }
static void addModuleDependencies(ArrayRef<ModuleDecl::ImportedModule> imports, StringRef indexStorePath, bool indexSystemModules, StringRef targetTriple, const clang::CompilerInstance &clangCI, DiagnosticEngine &diags, IndexUnitWriter &unitWriter, StringScratchSpace &moduleNameScratch) { auto &fileMgr = clangCI.getFileManager(); for (auto &import : imports) { ModuleDecl *mod = import.second; if (mod->isOnoneSupportModule()) continue; // ignore the Onone support library. if (mod->isSwiftShimsModule()) continue; for (auto *FU : mod->getFiles()) { switch (FU->getKind()) { case FileUnitKind::Source: case FileUnitKind::Builtin: break; case FileUnitKind::SerializedAST: case FileUnitKind::DWARFModule: case FileUnitKind::ClangModule: { auto *LFU = cast<LoadedFile>(FU); if (auto *F = fileMgr.getFile(LFU->getFilename())) { std::string moduleName = mod->getNameStr(); bool withoutUnitName = true; if (FU->getKind() == FileUnitKind::ClangModule) { withoutUnitName = false; auto clangModUnit = cast<ClangModuleUnit>(LFU); if (auto clangMod = clangModUnit->getUnderlyingClangModule()) { moduleName = clangMod->getTopLevelModuleName(); // FIXME: clang's -Rremarks do not seem to go through Swift's // diagnostic emitter. clang::index::emitIndexDataForModuleFile(clangMod, clangCI, unitWriter); } } else { // Serialized AST file. // Only index system modules (essentially stdlib and overlays). // We don't officially support binary swift modules, so normally // the index data for user modules would get generated while // building them. if (mod->isSystemModule() && indexSystemModules) { emitDataForSwiftSerializedModule(mod, indexStorePath, indexSystemModules, targetTriple, clangCI, diags, unitWriter); withoutUnitName = false; } } clang::index::writer::OpaqueModule opaqMod = moduleNameScratch.createString(moduleName); unitWriter.addASTFileDependency(F, mod->isSystemModule(), opaqMod, withoutUnitName); } break; } } } } }