static CompilerInvocation * createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path, DiagnosticsEngine& Diags) { llvm::opt::ArgStringList CCArgs { "-cc1", "-triple", "bpf-pc-linux", "-fsyntax-only", "-ferror-limit", "19", "-fmessage-length", "127", "-O2", "-nostdsysteminc", "-nobuiltininc", "-vectorize-loops", "-vectorize-slp", "-Wno-unused-value", "-Wno-pointer-sign", "-x", "c"}; CCArgs.append(CFlags.begin(), CFlags.end()); CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs); FrontendOptions& Opts = CI->getFrontendOpts(); Opts.Inputs.clear(); Opts.Inputs.emplace_back(Path, FrontendOptions::getInputKindForExtension("c")); return CI; }
static bool checkForMigration(StringRef resourcesPath, ArrayRef<const char *> Args) { IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); DiagnosticConsumer *DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient)); // Chain in -verify checker, if requested. VerifyDiagnosticConsumer *verifyDiag = nullptr; if (VerifyDiags) { verifyDiag = new VerifyDiagnosticConsumer(*Diags); Diags->setClient(verifyDiag); } CompilerInvocation CI; if (!CompilerInvocation::CreateFromArgs(CI, Args.begin(), Args.end(), *Diags)) return true; if (CI.getFrontendOpts().Inputs.empty()) { llvm::errs() << "error: no input files\n"; return true; } if (!CI.getLangOpts()->ObjC1) return false; arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0], std::make_shared<PCHContainerOperations>(), Diags->getClient()); return Diags->getClient()->getNumErrors() > 0; }
static bool HasARCRuntime(CompilerInvocation &origCI) { // This duplicates some functionality from Darwin::AddDeploymentTarget // but this function is well defined, so keep it decoupled from the driver // and avoid unrelated complications. for (unsigned i = 0, e = origCI.getPreprocessorOpts().Macros.size(); i != e; ++i) { StringRef define = origCI.getPreprocessorOpts().Macros[i].first; bool isUndef = origCI.getPreprocessorOpts().Macros[i].second; if (isUndef) continue; if (!define.startswith(SimulatorVersionDefineName())) continue; unsigned Major = 0, Minor = 0, Micro = 0; if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) && Major < 10 && Minor < 100 && Micro < 100) return Major >= 5; } llvm::Triple triple(origCI.getTargetOpts().Triple); if (triple.getOS() == llvm::Triple::IOS) return triple.getOSMajorVersion() >= 5; if (triple.getOS() == llvm::Triple::Darwin) return triple.getOSMajorVersion() >= 11; if (triple.getOS() == llvm::Triple::MacOSX) { unsigned Major, Minor, Micro; triple.getOSVersion(Major, Minor, Micro); return Major > 10 || (Major == 10 && Minor >= 7); } return false; }
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, std::string &Error) { SmallVector<const char *, 16> Args; sanitizeCompilerArgs(OrigArgs, Args); Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath); bool Err = Invocation.parseArgs(Args, Diags); if (Err) { // FIXME: Get the actual diagnostic. Error = "error when parsing the compiler arguments"; return Err; } // FIXME: The frontend should be dealing with symlinks, maybe similar to // clang's FileManager ? std::string PrimaryFile = SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile); for (auto &InputFile : Invocation.getFrontendOptions().InputFilenames) { InputFile = SwiftLangSupport::resolvePathSymlinks(InputFile); } ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); ImporterOpts.DetailedPreprocessingRecord = true; setModuleName(Invocation); Invocation.setSerializedDiagnosticsPath(StringRef()); Invocation.getLangOptions().AttachCommentsToDecls = true; auto &FrontendOpts = Invocation.getFrontendOptions(); if (FrontendOpts.PlaygroundTransform) { // The playground instrumenter changes the AST in ways that disrupt the // SourceKit functionality. Since we don't need the instrumenter, and all we // actually need is the playground semantics visible to the user, like // silencing the "expression resolves to an unused l-value" error, disable it. FrontendOpts.PlaygroundTransform = false; } if (!PrimaryFile.empty()) { Optional<unsigned> PrimaryIndex; for (auto i : indices(Invocation.getFrontendOptions().InputFilenames)) { auto &CurFile = Invocation.getFrontendOptions().InputFilenames[i]; if (PrimaryFile == CurFile) { PrimaryIndex = i; break; } } if (!PrimaryIndex) { llvm::SmallString<64> Err; llvm::raw_svector_ostream OS(Err); OS << "'" << PrimaryFile << "' is not part of the input files"; Error = OS.str(); return true; } Invocation.getFrontendOptions().PrimaryInput = SelectedInput(*PrimaryIndex); } return Err; }
SwiftInterfaceGenContextRef SwiftInterfaceGenContext::create(StringRef DocumentName, bool IsModule, StringRef ModuleOrHeaderName, CompilerInvocation Invocation, std::string &ErrMsg) { SwiftInterfaceGenContextRef IFaceGenCtx{ new SwiftInterfaceGenContext() }; IFaceGenCtx->Impl.DocumentName = DocumentName; IFaceGenCtx->Impl.IsModule = IsModule; IFaceGenCtx->Impl.ModuleOrHeaderName = ModuleOrHeaderName; IFaceGenCtx->Impl.Invocation = Invocation; CompilerInstance &CI = IFaceGenCtx->Impl.Instance; // Display diagnostics to stderr. CI.addDiagnosticConsumer(&IFaceGenCtx->Impl.DiagConsumer); Invocation.clearInputs(); if (CI.setup(Invocation)) { ErrMsg = "Error during invocation setup"; return nullptr; } ASTContext &Ctx = CI.getASTContext(); CloseClangModuleFiles scopedCloseFiles(*Ctx.getClangModuleLoader()); // Load standard library so that Clang importer can use it. auto *Stdlib = getModuleByFullName(Ctx, Ctx.StdlibModuleName); if (!Stdlib) { ErrMsg = "Could not load the stdlib module"; return nullptr; } if (IsModule) { if (getModuleInterfaceInfo(Ctx, ModuleOrHeaderName, IFaceGenCtx->Impl, ErrMsg)) return nullptr; } else { auto &FEOpts = Invocation.getFrontendOptions(); if (FEOpts.ImplicitObjCHeaderPath.empty()) { ErrMsg = "Implicit ObjC header path is empty"; return nullptr; } auto &Importer = static_cast<ClangImporter &>(*Ctx.getClangModuleLoader()); Importer.importBridgingHeader(FEOpts.ImplicitObjCHeaderPath, CI.getMainModule(), /*diagLoc=*/{}, /*trackParsedSymbols=*/true); if (getHeaderInterfaceInfo(Ctx, ModuleOrHeaderName, IFaceGenCtx->Impl.Info, ErrMsg)) return nullptr; } if (makeParserAST(IFaceGenCtx->Impl.TextCI, IFaceGenCtx->Impl.Info.Text)) { ErrMsg = "Error during syntactic parsing"; return nullptr; } return IFaceGenCtx; }
void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin, const char **ArgEnd, Diagnostic &Diags) { // Parse the arguments. llvm::OwningPtr<OptTable> Opts(createCC1OptTable()); unsigned MissingArgIndex, MissingArgCount; llvm::OwningPtr<InputArgList> Args( Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount)); // Check for missing argument error. if (MissingArgCount) Diags.Report(diag::err_drv_missing_argument) << Args->getArgString(MissingArgIndex) << MissingArgCount; // Issue errors on unknown arguments. for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN), ie = Args->filtered_end(); it != ie; ++it) Diags.Report(diag::err_drv_unknown_argument) << it->getAsString(*Args); ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags); ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, Diags); ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args); ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags); FrontendOptions::InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args); if (DashX != FrontendOptions::IK_AST) ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags); ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, Diags); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args); ParseTargetArgs(Res.getTargetOpts(), *Args); }
//===----------------------------------------------------------------------===// // EditorOpenTypeInterface //===----------------------------------------------------------------------===// void SwiftLangSupport::editorOpenTypeInterface(EditorConsumer &Consumer, ArrayRef<const char *> Args, StringRef TypeUSR) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; if (getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(), StringRef(), Error)) { Consumer.handleRequestError(Error.c_str()); return; } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; std::string ErrMsg; auto IFaceGenRef = SwiftInterfaceGenContext::createForTypeInterface( Invocation, TypeUSR, ErrMsg); if (!IFaceGenRef) { Consumer.handleRequestError(ErrMsg.c_str()); return; } IFaceGenRef->reportEditorInfo(Consumer); // reportEditorInfo requires exclusive access to the AST, so don't add this // to the service cache until it has returned. IFaceGenContexts.set(TypeUSR, IFaceGenRef); }
void SwiftLangSupport::getDocInfo(llvm::MemoryBuffer *InputBuf, StringRef ModuleName, ArrayRef<const char *> Args, DocInfoConsumer &Consumer) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; bool Failed = getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(), StringRef(), Error); if (Failed) { Consumer.failed(Error); return; } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; if (!ModuleName.empty()) { bool Error = reportModuleDocInfo(Invocation, ModuleName, Consumer); if (Error) Consumer.failed("Error occurred"); return; } Failed = reportSourceDocInfo(Invocation, InputBuf, Consumer); if (Failed) Consumer.failed("Error occurred"); }
static bool performTransformations(StringRef resourcesPath, ArrayRef<const char *> Args) { // Check first. if (checkForMigration(resourcesPath, Args)) return true; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); DiagnosticConsumer *DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> TopDiags( new DiagnosticsEngine(DiagID, &*DiagOpts, &*DiagClient)); CompilerInvocation origCI; if (!CompilerInvocation::CreateFromArgs(origCI, Args.begin(), Args.end(), *TopDiags)) return true; if (origCI.getFrontendOpts().Inputs.empty()) { llvm::errs() << "error: no input files\n"; return true; } if (!origCI.getLangOpts()->ObjC1) return false; MigrationProcess migration(origCI, std::make_shared<PCHContainerOperations>(), DiagClient); std::vector<TransformFn> transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(), origCI.getMigratorOpts().NoFinalizeRemoval); assert(!transforms.empty()); std::unique_ptr<PrintTransforms> transformPrinter; if (OutputTransformations) transformPrinter.reset(new PrintTransforms(llvm::outs())); for (unsigned i=0, e = transforms.size(); i != e; ++i) { bool err = migration.applyTransform(transforms[i], transformPrinter.get()); if (err) return true; if (VerboseOpt) { if (i == e-1) llvm::errs() << "\n##### FINAL RESULT #####\n"; else llvm::errs() << "\n##### OUTPUT AFTER "<< i+1 <<". TRANSFORMATION #####\n"; printResult(migration.getRemapper(), llvm::errs()); llvm::errs() << "\n##########################\n\n"; } } if (!OutputTransformations) printResult(migration.getRemapper(), llvm::outs()); // FIXME: TestResultForARC return false; }
void updateCode(std::unique_ptr<llvm::MemoryBuffer> Buffer) { BufferID = SM.addNewSourceBuffer(std::move(Buffer)); Parser.reset(new ParserUnit(SM, BufferID, CompInv.getLangOptions(), CompInv.getModuleName())); Parser->getDiagnosticEngine().addConsumer(DiagConsumer); auto &P = Parser->getParser(); for (bool Done = false; !Done; Done = P.Tok.is(tok::eof)) { P.parseTopLevel(); } }
static void printResult(FileRemapper &remapper, raw_ostream &OS) { CompilerInvocation CI; remapper.applyMappings(CI); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); // The changed files will be in memory buffers, print them. for (unsigned i = 0, e = PPOpts.RemappedFileBuffers.size(); i != e; ++i) { const llvm::MemoryBuffer *mem = PPOpts.RemappedFileBuffers[i].second; OS << mem->getBuffer(); } }
bool migrator::updateCodeAndEmitRemap(CompilerInstance *Instance, const CompilerInvocation &Invocation) { // Delete the remap file, in case someone is re-running the Migrator. If the // file fails to compile and we don't get a chance to overwrite it, the old // changes may get picked up. llvm::sys::fs::remove(Invocation.getMigratorOptions().EmitRemapFilePath); Migrator M { Instance, Invocation }; // Provide inputs and configuration // Phase 1: Pre Fix-it passes // These uses the initial frontend invocation to apply any obvious fix-its // to see if we can get an error-free AST to get to Phase 2. std::unique_ptr<swift::CompilerInstance> PreFixItInstance; if (Instance->getASTContext().hadError()) { PreFixItInstance = M.repeatFixitMigrations(2, Invocation.getLangOptions().EffectiveLanguageVersion); // If we still couldn't fix all of the errors, give up. if (PreFixItInstance == nullptr || !PreFixItInstance->hasASTContext() || PreFixItInstance->getASTContext().hadError()) { return true; } M.StartInstance = PreFixItInstance.get(); } // Phase 2: Syntactic Transformations auto FailedSyntacticPasses = M.performSyntacticPasses(); if (FailedSyntacticPasses) { return true; } // Phase 3: Post Fix-it Passes // Perform fix-it based migrations on the compiler, some number of times in // order to give the compiler an opportunity to // take its time reaching a fixed point. // This is the end of the pipeline, so we throw away the compiler instance(s) // we used in these fix-it runs. if (M.getMigratorOptions().EnableMigratorFixits) { M.repeatFixitMigrations(Migrator::MaxCompilerFixitPassIterations, {4, 0, 0}); } // OK, we have a final resulting text. Now we compare against the input // to calculate a replacement map describing the changes to the input // necessary to get the output. // TODO: Document replacement map format. auto EmitRemapFailed = M.emitRemap(); auto EmitMigratedFailed = M.emitMigratedFile(); auto DumpMigrationStatesFailed = M.dumpStates(); return EmitRemapFailed || EmitMigratedFailed || DumpMigrationStatesFailed; }
void SwiftLangSupport::editorOpenHeaderInterface(EditorConsumer &Consumer, StringRef Name, StringRef HeaderName, ArrayRef<const char *> Args, bool UsingSwiftArgs, bool SynthesizedExtensions, StringRef swiftVersion) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; ArrayRef<const char *> SwiftArgs = UsingSwiftArgs ? Args : llvm::None; if (getASTManager().initCompilerInvocationNoInputs(Invocation, SwiftArgs, CI.getDiags(), Error)) { Consumer.handleRequestError(Error.c_str()); return; } if (!UsingSwiftArgs && initInvocationByClangArguments(Args, Invocation, Error)) { Consumer.handleRequestError(Error.c_str()); return; } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; if (!swiftVersion.empty()) { auto swiftVer = version::Version::parseVersionString(swiftVersion, SourceLoc(), nullptr); if (swiftVer.hasValue()) Invocation.getLangOptions().EffectiveLanguageVersion = swiftVer.getValue(); } auto IFaceGenRef = SwiftInterfaceGenContext::create(Name, /*IsModule=*/false, HeaderName, None, Invocation, Error, SynthesizedExtensions, None); if (!IFaceGenRef) { Consumer.handleRequestError(Error.c_str()); return; } IFaceGenRef->reportEditorInfo(Consumer); // reportEditorInfo requires exclusive access to the AST, so don't add this // to the service cache until it has returned. IFaceGenContexts.set(Name, IFaceGenRef); }
//===----------------------------------------------------------------------===// // EditorOpenInterface //===----------------------------------------------------------------------===// void SwiftLangSupport::editorOpenInterface(EditorConsumer &Consumer, StringRef Name, StringRef ModuleName, Optional<StringRef> Group, ArrayRef<const char *> Args, bool SynthesizedExtensions, Optional<StringRef> InterestedUSR) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; if (getASTManager().initCompilerInvocationNoInputs(Invocation, Args, CI.getDiags(), Error)) { Consumer.handleRequestError(Error.c_str()); return; } trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; SwiftArgs.Args.Args.assign(Args.begin(), Args.end()); // NOTE: do not use primary file // NOTE: do not use files TracedOp.start(trace::OperationKind::OpenInterface, SwiftArgs, {std::make_pair("Name", Name), std::make_pair("ModuleName", ModuleName)}); } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; std::string ErrMsg; auto IFaceGenRef = SwiftInterfaceGenContext::create(Name, /*IsModule=*/true, ModuleName, Group, Invocation, ErrMsg, SynthesizedExtensions, InterestedUSR); if (!IFaceGenRef) { Consumer.handleRequestError(ErrMsg.c_str()); return; } IFaceGenRef->reportEditorInfo(Consumer); // reportEditorInfo requires exclusive access to the AST, so don't add this // to the service cache until it has returned. IFaceGenContexts.set(Name, IFaceGenRef); }
static bool makeParserAST(CompilerInstance &CI, StringRef Text) { CompilerInvocation Invocation; Invocation.setModuleName("main"); Invocation.setInputKind(InputFileKind::IFK_Swift); std::unique_ptr<llvm::MemoryBuffer> Buf; Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>"); Invocation.addInputBuffer(Buf.get()); if (CI.setup(Invocation)) return true; CI.performParseOnly(); return false; }
int doFormat(ArrayRef<StringRef> InputFiles) { for (auto InputFilename : InputFiles) { CompilerInvocation Invocation; Invocation.addInputFilename(InputFilename); Invocation.setModuleName("Format"); CompilerInstance Instance; auto &SourceMgr = Instance.getSourceMgr(); auto &Diags = Instance.getDiags(); PrintingDiagnosticConsumer DiagPrinter; Instance.addDiagnosticConsumer(&DiagPrinter); if (Instance.setup(Invocation)) { return EXIT_FAILURE; } // First, parse the file normally and get the regular old AST. Instance.performParseOnly(); auto BufferID = Instance.getInputBufferIDs().back(); auto &SF = Instance.getMainModule() ->getMainSourceFile(SourceFileKind::Main); auto Buffer = llvm::MemoryBuffer::getFile(InputFilename); if (!Buffer) { Diags.diagnose(SourceLoc(), diag::cannot_open_file, InputFilename, Buffer.getError().message()); return EXIT_FAILURE; } auto Tokens = tokenizeWithTrivia(Invocation.getLangOptions(), SourceMgr, BufferID); SmallVector<Decl *, 256> FileDecls; SF.getTopLevelDecls(FileDecls); sema::Semantics Sema; for (auto *Decl : FileDecls) { if (Decl->escapedFromIfConfig()) { continue; } auto NewNode = transformAST(ASTNode(Decl), Sema, SourceMgr, BufferID, Tokens); if (NewNode.hasValue()) { auto Reformatted = format(NewNode.getValue()); Reformatted.print(llvm::outs()); } } } return EXIT_SUCCESS; }
/// Implicitly import the SwiftOnoneSupport module in non-optimized /// builds. This allows for use of popular specialized functions /// from the standard library, which makes the non-optimized builds /// execute much faster. static bool shouldImplicityImportSwiftOnoneSupportModule(CompilerInvocation &Invocation) { if (Invocation.getImplicitModuleImportKind() != SourceFile::ImplicitModuleImportKind::Stdlib) return false; SILOptions::SILOptMode optimization = Invocation.getSILOptions().Optimization; if (optimization <= SILOptions::SILOptMode::None && shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization( Invocation.getFrontendOptions().RequestedAction)) { return true; } return optimization == SILOptions::SILOptMode::None && Invocation.getFrontendOptions().isCreatingSIL(); }
static bool makeParserAST(CompilerInstance &CI, StringRef Text, CompilerInvocation Invocation) { Invocation.getFrontendOptions().InputsAndOutputs.clearInputs(); Invocation.setModuleName("main"); Invocation.setInputKind(InputFileKind::IFK_Swift); std::unique_ptr<llvm::MemoryBuffer> Buf; Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>"); Invocation.getFrontendOptions().InputsAndOutputs.addInput( InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get())); if (CI.setup(Invocation)) return true; CI.performParseOnly(); return false; }
void SwiftLangSupport::editorOpenHeaderInterface(EditorConsumer &Consumer, StringRef Name, StringRef HeaderName, ArrayRef<const char *> Args) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; if (getASTManager().initCompilerInvocation(Invocation, llvm::None, CI.getDiags(), StringRef(), Error)) { Consumer.handleRequestError(Error.c_str()); return; } if (initInvocationByClangArguments(Args, Invocation, Error)) { Consumer.handleRequestError(Error.c_str()); return; } trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; SwiftArgs.Args.Args.assign(Args.begin(), Args.end()); // NOTE: do not use primary file // NOTE: do not use files TracedOp.start(trace::OperationKind::OpenHeaderInterface, SwiftArgs, {std::make_pair("Name", Name), std::make_pair("HeaderName", HeaderName)}); } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; auto IFaceGenRef = SwiftInterfaceGenContext::create(Name, /*IsModule=*/false, HeaderName, None, Invocation, Error); if (!IFaceGenRef) { Consumer.handleRequestError(Error.c_str()); return; } IFaceGenContexts.set(Name, IFaceGenRef); IFaceGenRef->reportEditorInfo(Consumer); }
static bool ParseTBDGenArgs(TBDGenOptions &Opts, ArgList &Args, DiagnosticEngine &Diags, CompilerInvocation &Invocation) { using namespace options; Opts.HasMultipleIGMs = Invocation.getSILOptions().hasMultipleIGMs(); if (const Arg *A = Args.getLastArg(OPT_module_link_name)) { Opts.ModuleLinkName = A->getValue(); } if (const Arg *A = Args.getLastArg(OPT_tbd_install_name)) { Opts.InstallName = A->getValue(); } if (const Arg *A = Args.getLastArg(OPT_tbd_compatibility_version)) { if (auto vers = version::Version::parseVersionString( A->getValue(), SourceLoc(), &Diags)) { Opts.CompatibilityVersion = *vers; } } if (const Arg *A = Args.getLastArg(OPT_tbd_current_version)) { if (auto vers = version::Version::parseVersionString( A->getValue(), SourceLoc(), &Diags)) { Opts.CurrentVersion = *vers; } } return false; }
static bool applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut) { if (!origCI.getLangOpts()->ObjC1) return false; LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC(); // Make sure checking is successful first. CompilerInvocation CInvokForCheck(origCI); if (arcmt::checkForManualIssues(CInvokForCheck, Input, DiagClient, emitPremigrationARCErrors, plistOut)) return true; CompilerInvocation CInvok(origCI); CInvok.getFrontendOpts().Inputs.clear(); CInvok.getFrontendOpts().Inputs.push_back(Input); MigrationProcess migration(CInvok, DiagClient, outputDir); bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode, NoFinalizeRemoval); assert(!transforms.empty()); for (unsigned i=0, e = transforms.size(); i != e; ++i) { bool err = migration.applyTransform(transforms[i]); if (err) return true; } IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); if (outputDir.empty()) { origCI.getLangOpts()->ObjCAutoRefCount = true; return migration.getRemapper().overwriteOriginal(*Diags); } else { // If we are migrating code that gets the '-fobjc-arc' flag, make sure // to remove it so that we don't get errors from normal compilation. origCI.getLangOpts()->ObjCAutoRefCount = false; return migration.getRemapper().flushToDisk(outputDir, *Diags); } }
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, std::string &Error) { SmallVector<const char *, 16> Args(OrigArgs.begin(), OrigArgs.end()); Args.push_back("-resource-dir"); Args.push_back(Impl.RuntimeResourcePath.c_str()); if (auto driverInvocation = driver::createCompilerInvocation(Args, Diags)) { Invocation = *driverInvocation; } else { // FIXME: Get the actual diagnostic. Error = "error when parsing the compiler arguments"; return true; } Invocation.getFrontendOptions().InputsAndOutputs = resolveSymbolicLinksInInputs( Invocation.getFrontendOptions().InputsAndOutputs, UnresolvedPrimaryFile, Error); if (!Error.empty()) return true; ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); ImporterOpts.DetailedPreprocessingRecord = true; assert(!Invocation.getModuleName().empty()); Invocation.getLangOptions().AttachCommentsToDecls = true; Invocation.getLangOptions().DiagnosticsEditorMode = true; Invocation.getLangOptions().CollectParsedToken = true; auto &FrontendOpts = Invocation.getFrontendOptions(); if (FrontendOpts.PlaygroundTransform) { // The playground instrumenter changes the AST in ways that disrupt the // SourceKit functionality. Since we don't need the instrumenter, and all we // actually need is the playground semantics visible to the user, like // silencing the "expression resolves to an unused l-value" error, disable it. FrontendOpts.PlaygroundTransform = false; } // Disable the index-store functionality for the sourcekitd requests. FrontendOpts.IndexStorePath.clear(); ImporterOpts.IndexStorePath.clear(); // Force the action type to be -typecheck. This affects importing the // SwiftONoneSupport module. FrontendOpts.RequestedAction = FrontendOptions::ActionType::Typecheck; // We don't care about LLVMArgs FrontendOpts.LLVMArgs.clear(); // Disable expensive SIL options to reduce time spent in SILGen. disableExpensiveSILOptions(Invocation.getSILOptions()); return false; }
void SwiftLangSupport::findModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args, std::function<void(ArrayRef<StringRef>, StringRef Error)> Receiver) { CompilerInvocation Invocation; Invocation.getClangImporterOptions().ImportForwardDeclarations = true; Invocation.clearInputs(); CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); std::vector<StringRef> Groups; std::string Error; if (getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(), StringRef(), Error)) { Receiver(Groups, Error); return; } if (CI.setup(Invocation)) { Error = "Compiler invocation set up fails."; Receiver(Groups, Error); return; } ASTContext &Ctx = CI.getASTContext(); // Setup a typechecker for protocol conformance resolving. OwnedResolver TypeResolver = createLazyResolver(Ctx); // Load standard library so that Clang importer can use it. auto *Stdlib = getModuleByFullName(Ctx, Ctx.StdlibModuleName); if (!Stdlib) { Error = "Cannot load stdlib."; Receiver(Groups, Error); return; } auto *M = getModuleByFullName(Ctx, ModuleName); if (!M) { Error = "Cannot find the module."; Receiver(Groups, Error); return; } std::vector<StringRef> Scratch; Receiver(collectModuleGroups(M, Scratch), Error); }
MigrationProcess::MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient, StringRef outputDir) : OrigCI(CI), DiagClient(diagClient), HadARCErrors(false) { if (!outputDir.empty()) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient, /*ShouldOwnClient=*/false)); Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true); } }
static bool applyTransforms(CompilerInvocation &origCI, llvm::StringRef Filename, InputKind Kind, DiagnosticClient *DiagClient, llvm::StringRef outputDir) { if (!origCI.getLangOpts().ObjC1) return false; // Make sure checking is successful first. CompilerInvocation CInvokForCheck(origCI); if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient)) return true; CompilerInvocation CInvok(origCI); CInvok.getFrontendOpts().Inputs.clear(); CInvok.getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename)); MigrationProcess migration(CInvok, DiagClient, outputDir); std::vector<TransformFn> transforms = arcmt::getAllTransformations(); assert(!transforms.empty()); for (unsigned i=0, e = transforms.size(); i != e; ++i) { bool err = migration.applyTransform(transforms[i]); if (err) return true; } llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); llvm::IntrusiveRefCntPtr<Diagnostic> Diags( new Diagnostic(DiagID, DiagClient, /*ShouldOwnClient=*/false)); if (outputDir.empty()) { origCI.getLangOpts().ObjCAutoRefCount = true; return migration.getRemapper().overwriteOriginal(*Diags); } else { // If we are migrating code that gets the '-fobjc-arc' flag, make sure // to remove it so that we don't get errors from normal compilation. origCI.getLangOpts().ObjCAutoRefCount = false; return migration.getRemapper().flushToDisk(outputDir, *Diags); } }
bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > & remap, StringRef outputDir, DiagnosticConsumer *DiagClient) { assert(!outputDir.empty()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); FileRemapper remapper; bool err = remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanged=*/true); if (err) return true; CompilerInvocation CI; remapper.applyMappings(CI); remap = CI.getPreprocessorOpts().RemappedFiles; return false; }
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, std::string &Error) { SmallVector<const char *, 16> Args; sanitizeCompilerArgs(OrigArgs, Args); Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath); if (Invocation.parseArgs(Args, Diags)) { // FIXME: Get the actual diagnostic. Error = "error when parsing the compiler arguments"; return true; } Invocation.getFrontendOptions().Inputs = resolveSymbolicLinksInInputs( Invocation.getFrontendOptions().Inputs, UnresolvedPrimaryFile, Error); if (!Error.empty()) return true; ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); ImporterOpts.DetailedPreprocessingRecord = true; setModuleName(Invocation); Invocation.setSerializedDiagnosticsPath(StringRef()); Invocation.getLangOptions().AttachCommentsToDecls = true; Invocation.getLangOptions().DiagnosticsEditorMode = true; Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true; auto &FrontendOpts = Invocation.getFrontendOptions(); if (FrontendOpts.PlaygroundTransform) { // The playground instrumenter changes the AST in ways that disrupt the // SourceKit functionality. Since we don't need the instrumenter, and all we // actually need is the playground semantics visible to the user, like // silencing the "expression resolves to an unused l-value" error, disable it. FrontendOpts.PlaygroundTransform = false; } // Disable the index-store functionality for the sourcekitd requests. FrontendOpts.IndexStorePath.clear(); ImporterOpts.IndexStorePath.clear(); return false; }
static bool HasARCRuntime(CompilerInvocation &origCI) { // This duplicates some functionality from Darwin::AddDeploymentTarget // but this function is well defined, so keep it decoupled from the driver // and avoid unrelated complications. llvm::Triple triple(origCI.getTargetOpts().Triple); if (triple.isiOS()) return triple.getOSMajorVersion() >= 5; if (triple.getOS() == llvm::Triple::Darwin) return triple.getOSMajorVersion() >= 11; if (triple.getOS() == llvm::Triple::MacOSX) { unsigned Major, Minor, Micro; triple.getOSVersion(Major, Minor, Micro); return Major > 10 || (Major == 10 && Minor >= 7); } return false; }
static void setModuleName(CompilerInvocation &Invocation) { if (!Invocation.getModuleName().empty()) return; StringRef Filename = Invocation.getOutputFilename(); if (Filename.empty()) { if (Invocation.getInputFilenames().empty()) { Invocation.setModuleName("__main__"); return; } Filename = Invocation.getInputFilenames()[0]; } Filename = llvm::sys::path::filename(Filename); StringRef ModuleName = llvm::sys::path::stem(Filename); if (ModuleName.empty() || !Lexer::isIdentifier(ModuleName)) { Invocation.setModuleName("__main__"); return; } Invocation.setModuleName(ModuleName); }
static bool reportSourceDocInfo(CompilerInvocation Invocation, llvm::MemoryBuffer *InputBuf, DocInfoConsumer &Consumer) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); EditorDiagConsumer DiagConsumer; CI.addDiagnosticConsumer(&DiagConsumer); Invocation.addInputBuffer(InputBuf); if (CI.setup(Invocation)) return true; DiagConsumer.setInputBufferIDs(CI.getInputBufferIDs()); ASTContext &Ctx = CI.getASTContext(); CloseClangModuleFiles scopedCloseFiles(*Ctx.getClangModuleLoader()); CI.performSema(); // Setup a typechecker for protocol conformance resolving. OwnedResolver TypeResolver = createLazyResolver(Ctx); SourceTextInfo SourceInfo; if (getSourceTextInfo(CI, SourceInfo)) return true; addParameterEntities(CI, SourceInfo); reportDocEntities(Ctx, SourceInfo.TopEntities, Consumer); reportSourceAnnotations(SourceInfo, CI, Consumer); for (auto &Diag : DiagConsumer.getDiagnosticsForBuffer( CI.getInputBufferIDs().back())) Consumer.handleDiagnostic(Diag); return false; }