bool ide::initInvocationByClangArguments(ArrayRef<const char *> ArgList, CompilerInvocation &Invok, std::string &Error) { llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts{ new clang::DiagnosticOptions() }; clang::TextDiagnosticBuffer DiagBuf; llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> ClangDiags = clang::CompilerInstance::createDiagnostics(DiagOpts.get(), &DiagBuf, /*ShouldOwnClient=*/false); // Clang expects this to be like an actual command line. So we need to pass in // "clang" for argv[0]. std::vector<const char *> ClangArgList; ClangArgList.push_back("clang"); ClangArgList.insert(ClangArgList.end(), ArgList.begin(), ArgList.end()); // Create a new Clang compiler invocation. std::unique_ptr<clang::CompilerInvocation> ClangInvok = clang::createInvocationFromCommandLine(ClangArgList, ClangDiags); if (!ClangInvok || ClangDiags->hasErrorOccurred()) { for (auto I = DiagBuf.err_begin(), E = DiagBuf.err_end(); I != E; ++I) { Error += I->second; Error += " "; } return true; } auto &PPOpts = ClangInvok->getPreprocessorOpts(); auto &HSOpts = ClangInvok->getHeaderSearchOpts(); Invok.setTargetTriple(adjustClangTriple(ClangInvok->getTargetOpts().Triple)); if (!HSOpts.Sysroot.empty()) Invok.setSDKPath(HSOpts.Sysroot); if (!HSOpts.ModuleCachePath.empty()) Invok.setClangModuleCachePath(HSOpts.ModuleCachePath); auto &CCArgs = Invok.getClangImporterOptions().ExtraArgs; for (auto MacroEntry : PPOpts.Macros) { std::string MacroFlag; if (MacroEntry.second) MacroFlag += "-U"; else MacroFlag += "-D"; MacroFlag += MacroEntry.first; CCArgs.push_back(MacroFlag); } for (auto &Entry : HSOpts.UserEntries) { switch (Entry.Group) { case clang::frontend::Quoted: CCArgs.push_back("-iquote"); CCArgs.push_back(Entry.Path); break; case clang::frontend::IndexHeaderMap: CCArgs.push_back("-index-header-map"); LLVM_FALLTHROUGH; case clang::frontend::Angled: { std::string Flag; if (Entry.IsFramework) Flag += "-F"; else Flag += "-I"; Flag += Entry.Path; CCArgs.push_back(Flag); break; } case clang::frontend::System: if (Entry.IsFramework) CCArgs.push_back("-iframework"); else CCArgs.push_back("-isystem"); CCArgs.push_back(Entry.Path); break; case clang::frontend::ExternCSystem: case clang::frontend::CSystem: case clang::frontend::CXXSystem: case clang::frontend::ObjCSystem: case clang::frontend::ObjCXXSystem: case clang::frontend::After: break; } } if (!PPOpts.ImplicitPCHInclude.empty()) { clang::FileSystemOptions FileSysOpts; clang::FileManager FileMgr(FileSysOpts); auto PCHContainerOperations = std::make_shared<clang::PCHContainerOperations>(); std::string HeaderFile = clang::ASTReader::getOriginalSourceFile( PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerOperations->getRawReader(), *ClangDiags); if (!HeaderFile.empty()) { CCArgs.push_back("-include"); CCArgs.push_back(std::move(HeaderFile)); } } for (auto &Header : PPOpts.Includes) { CCArgs.push_back("-include"); CCArgs.push_back(Header); } for (auto &Entry : HSOpts.ModulesIgnoreMacros) { std::string Flag = "-fmodules-ignore-macro="; Flag += Entry; CCArgs.push_back(Flag); } for (auto &Entry : HSOpts.VFSOverlayFiles) { CCArgs.push_back("-ivfsoverlay"); CCArgs.push_back(Entry); } if (!ClangInvok->getLangOpts()->isCompilingModule()) { CCArgs.push_back("-Xclang"); llvm::SmallString<64> Str; Str += "-fmodule-name="; Str += ClangInvok->getLangOpts()->CurrentModule; CCArgs.push_back(Str.str()); } if (PPOpts.DetailedRecord) { Invok.getClangImporterOptions().DetailedPreprocessingRecord = true; } if (!ClangInvok->getFrontendOpts().Inputs.empty()) { Invok.getFrontendOptions().ImplicitObjCHeaderPath = ClangInvok->getFrontendOpts().Inputs[0].getFile(); } return false; }