diff --git a/Sources/SwiftDriver/Jobs/CommandLineArguments.swift b/Sources/SwiftDriver/Jobs/CommandLineArguments.swift index 73a457c2b..821191251 100644 --- a/Sources/SwiftDriver/Jobs/CommandLineArguments.swift +++ b/Sources/SwiftDriver/Jobs/CommandLineArguments.swift @@ -56,7 +56,7 @@ extension Array where Element == Job.ArgTemplate { /// Append an option's spelling to the command line arguments. mutating func appendFlag(_ option: Option) { switch option.kind { - case .flag, .joinedOrSeparate, .remaining, .separate: + case .flag, .joinedOrSeparate, .remaining, .separate, .multiArg: break case .commaJoined, .input, .joined: fatalError("Option cannot be appended as a flag: \(option)") @@ -95,7 +95,7 @@ extension Array where Element == Job.ArgTemplate { assert(!option.attributes.contains(.argumentIsPath)) appendFlag(option.spelling + argument.asMultiple.joined(separator: ",")) - case .remaining: + case .remaining, .multiArg: appendFlag(option.spelling) for arg in argument.asMultiple { try appendSingleArgument(option: option, argument: arg) diff --git a/Sources/SwiftOptions/Option.swift b/Sources/SwiftOptions/Option.swift index 3cb6598af..b7aeb9ec7 100644 --- a/Sources/SwiftOptions/Option.swift +++ b/Sources/SwiftOptions/Option.swift @@ -56,6 +56,9 @@ public struct Option { /// An option with multiple arguments, which are collected by splitting /// the text directly following the spelling at each comma. case commaJoined + /// An option with multiple arguments, which the number of arguments is + /// specified by numArgs. + case multiArg } /// The spelling of the option, including any leading dashes. @@ -81,11 +84,15 @@ public struct Option { /// The group in which this option occurs. public let group: Group? + /// The number of arguments for MultiArg options. + public let numArgs: UInt + public init(_ spelling: String, _ kind: Kind, alias: Option? = nil, attributes: OptionAttributes = [], metaVar: String? = nil, helpText: String? = nil, - group: Group? = nil) { + group: Group? = nil, + numArgs: UInt = 0) { self.spelling = spelling self.kind = kind self.aliasFunction = alias.map { aliasOption in { aliasOption }} @@ -93,6 +100,7 @@ public struct Option { self.metaVar = metaVar self.helpText = helpText self.group = group + self.numArgs = numArgs } } diff --git a/Sources/SwiftOptions/OptionParsing.swift b/Sources/SwiftOptions/OptionParsing.swift index e4d4892ba..bda78d5b9 100644 --- a/Sources/SwiftOptions/OptionParsing.swift +++ b/Sources/SwiftOptions/OptionParsing.swift @@ -171,6 +171,21 @@ extension OptionTable { parsedOptions.addOption(option, argument: .single(arguments[index])) index += 1 + + case .multiArg: + if argument != option.spelling { + throw OptionParseError.unknownOption( + index: index - 1, argument: argument) + } + let endIdx = index + Int(option.numArgs) + if endIdx > arguments.endIndex { + throw OptionParseError.missingArgument( + index: index - 1, argument: argument) + } + parsedOptions.addOption(option, argument: .multiple(Array())) + arguments[index.." - case .separate, .remaining, .joinedOrSeparate: + case .separate, .remaining, .joinedOrSeparate, .multiArg: displayName += " " + (option.metaVar ?? "") } diff --git a/Sources/SwiftOptions/Options.swift b/Sources/SwiftOptions/Options.swift index cd6e072f6..71ce912ff 100644 --- a/Sources/SwiftOptions/Options.swift +++ b/Sources/SwiftOptions/Options.swift @@ -169,6 +169,7 @@ extension Option { public static let disableDeserializationRecovery: Option = Option("-disable-deserialization-recovery", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't attempt to recover from missing xrefs (etc) in swiftmodules") public static let disableDeserializationSafety: Option = Option("-disable-deserialization-safety", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't avoid reading potentially unsafe decls in swiftmodules") public static let disableDiagnosticPasses: Option = Option("-disable-diagnostic-passes", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't run diagnostic passes") + public static let disableDynamicActorIsolation: Option = Option("-disable-dynamic-actor-isolation", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Disable dynamic actor isolation checks") public static let disableEmitGenericClassRoTList: Option = Option("-disable-emit-generic-class-ro_t-list", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of a section with references to class_ro_t of generic class patterns") public static let disableExperimentalClangImporterDiagnostics: Option = Option("-disable-experimental-clang-importer-diagnostics", .flag, attributes: [.helpHidden, .frontend, .noDriver, .moduleInterface], helpText: "Disable experimental diagnostics when importing C, C++, and Objective-C libraries") public static let disableExperimentalLifetimeDependenceInference: Option = Option("-disable-experimental-lifetime-dependence-inference", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable experimental lifetime dependence inference") @@ -211,7 +212,9 @@ extension Option { public static let disableOnlyOneDependencyFile: Option = Option("-disable-only-one-dependency-file", .flag, attributes: [.doesNotAffectIncrementalBuild], helpText: "Disables incremental build optimization that only produces one dependencies file") public static let disableOsChecks: Option = Option("-disable-os-checks", .flag, attributes: [.noDriver], helpText: "Skip OS related diagnostics") public static let disableOsChecks_: Option = Option("--disable-os-checks", .flag, alias: Option.disableOsChecks, attributes: [.noDriver], helpText: "Skip OS related diagnostics") + public static let disableOssaCompleteLifetimes: Option = Option("-disable-ossa-complete-lifetimes", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Do not require linear OSSA lifetimes after SILGen") public static let disableOssaOpts: Option = Option("-disable-ossa-opts", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't run SIL OSSA optimization passes.") + public static let disableOssaVerifyComplete: Option = Option("-disable-ossa-verify-complete", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Do not verify linear OSSA lifetimes after SILGen") public static let disablePlaygroundTransform: Option = Option("-disable-playground-transform", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable playground transformation") public static let disablePreallocatedInstantiationCaches: Option = Option("-disable-preallocated-instantiation-caches", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Avoid preallocating metadata instantiation caches in globals") public static let disablePreviousImplementationCallsInDynamicReplacements: Option = Option("-disable-previous-implementation-calls-in-dynamic-replacements", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable calling the previous implementation in dynamic replacements") @@ -219,6 +222,7 @@ extension Option { public static let disableReadonlyStaticObjects: Option = Option("-disable-readonly-static-objects", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Avoid allocating static objects in a read-only data section") public static let disableReflectionMetadata: Option = Option("-disable-reflection-metadata", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of reflection metadata for nominal types") public static let disableReflectionNames: Option = Option("-disable-reflection-names", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of names of stored properties and enum cases inreflection metadata") + public static let disableStrictConcurrencyRegionBasedIsolation: Option = Option("-disable-region-based-isolation-with-strict-concurrency", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable region based isolation when running with strict concurrency enabled. Only enabled with asserts") public static let disableRelativeProtocolWitnessTables: Option = Option("-disable-relative-protocol-witness-tables", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable relative protocol witness tables") public static let disableRemoveDeprecatedCheck: Option = Option("-disable-remove-deprecated-check", .flag, attributes: [.noDriver], helpText: "Skip diagnosing removal of deprecated symbols") public static let disableRemoveDeprecatedCheck_: Option = Option("--disable-remove-deprecated-check", .flag, alias: Option.disableRemoveDeprecatedCheck, attributes: [.noDriver], helpText: "Skip diagnosing removal of deprecated symbols") @@ -304,6 +308,7 @@ extension Option { public static let emitDependencies: Option = Option("-emit-dependencies", .flag, attributes: [.frontend, .noInteractive, .supplementaryOutput], helpText: "Emit basic Make-compatible dependencies files") public static let emitDigesterBaselinePath: Option = Option("-emit-digester-baseline-path", .separate, attributes: [.noInteractive, .argumentIsPath, .supplementaryOutput], metaVar: "", helpText: "Emit a baseline file for the module to using the API digester") public static let emitDigesterBaseline: Option = Option("-emit-digester-baseline", .flag, attributes: [.noInteractive, .supplementaryOutput], helpText: "Emit a baseline file for the module using the API digester") + public static let emitEmptyObjectFile: Option = Option("-emit-empty-object-file", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Produce a valid but dummy object file when building a library module") public static let emitExecutable: Option = Option("-emit-executable", .flag, attributes: [.noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit a linked executable", group: .modes) public static let emitExtensionBlockSymbols: Option = Option("-emit-extension-block-symbols", .flag, attributes: [.helpHidden, .frontend, .noInteractive, .supplementaryOutput], helpText: "Emit 'swift.extension' symbols for extensions to external types instead of directly associating members and conformances with the extended nominal when generating symbol graphs") public static let emitFineGrainedDependencySourcefileDotFiles: Option = Option("-emit-fine-grained-dependency-sourcefile-dot-files", .flag, attributes: [.helpHidden, .frontend], helpText: "Emit dot files for every source file.") @@ -380,7 +385,7 @@ extension Option { public static let enableDeserializationRecovery: Option = Option("-enable-deserialization-recovery", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Attempt to recover from missing xrefs (etc) in swiftmodules") public static let enableDeserializationSafety: Option = Option("-enable-deserialization-safety", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Avoid reading potentially unsafe decls in swiftmodules") public static let enableDestroyHoisting: Option = Option("-enable-destroy-hoisting=", .joined, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "true|false", helpText: "Whether to enable destroy hoisting") - public static let enableDeterministicCheck: Option = Option("-enable-deterministic-check", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Check compiler output determinisim by running it twice") + public static let enableDeterministicCheck: Option = Option("-enable-deterministic-check", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Check compiler output determinism by running it twice") public static let enableDynamicReplacementChaining: Option = Option("-enable-dynamic-replacement-chaining", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable chaining of dynamic replacements") public static let enableEmitGenericClassRoTList: Option = Option("-enable-emit-generic-class-ro_t-list", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable emission of a section with references to class_ro_t of generic class patterns") public static let enableExperimentalAdditiveArithmeticDerivation: Option = Option("-enable-experimental-additive-arithmetic-derivation", .flag, attributes: [.frontend], helpText: "Enable experimental 'AdditiveArithmetic' derived conformances") @@ -406,7 +411,6 @@ extension Option { public static let enableFragileResilientProtocolWitnesses: Option = Option("-enable-fragile-relative-protocol-tables", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable relative protocol witness tables") public static let enableImplicitBacktracingModuleImport: Option = Option("-enable-implicit-backtracing-module-import", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable the implicit import of the _Backtracing module.") public static let enableImplicitDynamic: Option = Option("-enable-implicit-dynamic", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Add 'dynamic' to all declarations") - public static let enableImportPtrauthFieldFunctionPointers: Option = Option("-enable-import-ptrauth-field-function-pointers", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable import of custom ptrauth qualified field function pointers") public static let enableIncrementalImports: Option = Option("-enable-incremental-imports", .flag, attributes: [.frontend], helpText: "Enable cross-module incremental build metadata and driver scheduling for Swift modules") public static let enableInferPublicConcurrentValue: Option = Option("-enable-infer-public-sendable", .flag, attributes: [.frontend, .noDriver], helpText: "Enable inference of Sendable conformances for public structs and enums") public static let enableInvalidEphemeralnessAsError: Option = Option("-enable-invalid-ephemeralness-as-error", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Diagnose invalid ephemeral to non-ephemeral conversions as errors") @@ -432,6 +436,7 @@ extension Option { public static let enableOperatorDesignatedTypes: Option = Option("-enable-operator-designated-types", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable operator designated types") public static let enableOssaCompleteLifetimes: Option = Option("-enable-ossa-complete-lifetimes", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Require linear OSSA lifetimes after SILGen") public static let enableOssaModules: Option = Option("-enable-ossa-modules", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Always serialize SIL in ossa form. If this flag is not passed in, when optimizing ownership will be lowered before serializing SIL") + public static let enableOssaVerifyComplete: Option = Option("-enable-ossa-verify-complete", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Verify linear OSSA lifetimes after SILGen") public static let enablePackMetadataStackPromotion: Option = Option("-enable-pack-metadata-stack-promotion=", .joined, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "true|false", helpText: "Whether to skip heapifying stack metadata packs when possible.") public static let enablePackMetadataStackPromotionNoArg: Option = Option("-enable-pack-metadata-stack-promotion", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Skip heapifying stack metadata packs when possible.") public static let enablePrivateImports: Option = Option("-enable-private-imports", .flag, attributes: [.helpHidden, .frontend, .noInteractive], helpText: "Allows this module's internal and private API to be accessed") @@ -459,7 +464,8 @@ extension Option { public static let entryPointFunctionName: Option = Option("-entry-point-function-name", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "", helpText: "Name of the entry point function") public static let experimentalAllowModuleWithCompilerErrors: Option = Option("-experimental-allow-module-with-compiler-errors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Attempt to output .swiftmodule, regardless of compilation errors") public static let experimentalAllowNonResilientAccess: Option = Option("-experimental-allow-non-resilient-access", .flag, attributes: [.frontend], helpText: "Allow non-resilient access by generating all contents besides exportable decls") - public static let experimentalCForeignReferenceTypes: Option = Option("-experimental-c-foreign-reference-types", .flag, attributes: [.helpHidden, .frontend, .moduleInterface], helpText: "Enable experimental C foreign references types (with reference coutning).") + public static let experimentalAllowedReexportedModules: Option = Option("-experimental-allowed-reexported-modules=", .commaJoined, attributes: [.noDriver], helpText: "Allow reexporting symbols from the provided modules if they are themselves exported from the main module. This is a comma separated list of module names.") + public static let experimentalCForeignReferenceTypes: Option = Option("-experimental-c-foreign-reference-types", .flag, attributes: [.helpHidden, .frontend, .moduleInterface], helpText: "Enable experimental C foreign references types (with reference counting).") public static let experimentalClangImporterDirectCc1Scan: Option = Option("-experimental-clang-importer-direct-cc1-scan", .flag, attributes: [.helpHidden, .frontend], helpText: "Enables swift driver to construct swift-frontend invocations using -direct-clang-cc1-module-build") public static let experimentalCxxStdlib: Option = Option("-experimental-cxx-stdlib", .separate, attributes: [.helpHidden], helpText: "C++ standard library to use; forwarded to Clang's -stdlib flag") public static let emitModuleSeparately: Option = Option("-experimental-emit-module-separately", .flag, attributes: [.helpHidden], helpText: "Emit module files as a distinct job") @@ -469,7 +475,7 @@ extension Option { public static let experimentalLazyTypecheck: Option = Option("-experimental-lazy-typecheck", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Type-check lazily as needed to produce requested outputs") public static let experimentalOneWayClosureParams: Option = Option("-experimental-one-way-closure-params", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable experimental support for one-way closure parameters") public static let experimentalPackageBypassResilience: Option = Option("-experimental-package-bypass-resilience", .flag, attributes: [.frontend], helpText: "Enable optimization to bypass resilience within a package") - public static let ExperimentalPackageCMO: Option = Option("-experimental-package-cmo", .flag, attributes: [.frontend], helpText: "Enable optimization to perform defalut CMO within a package boundary") + public static let ExperimentalPackageCMO: Option = Option("-experimental-package-cmo", .flag, attributes: [.frontend], helpText: "Enable optimization to perform default CMO within a package boundary") public static let experimentalPackageInterfaceLoad: Option = Option("-experimental-package-interface-load", .flag, attributes: [.helpHidden, .frontend], helpText: "Enables loading a package interface if in the same package specified with package-name") public static let ExperimentalPerformanceAnnotations: Option = Option("-experimental-performance-annotations", .flag, attributes: [.helpHidden, .frontend], helpText: "Deprecated, has no effect") public static let platformCCallingConventionEQ: Option = Option("-experimental-platform-c-calling-convention=", .joined, alias: Option.platformCCallingConvention, attributes: [.helpHidden, .frontend, .noDriver]) @@ -482,7 +488,8 @@ extension Option { public static let experimentalSkipNonInlinableFunctionBodies: Option = Option("-experimental-skip-non-inlinable-function-bodies", .flag, attributes: [.helpHidden, .frontend], helpText: "Skip type-checking and SIL generation for non-inlinable function bodies") public static let experimentalSpiImports: Option = Option("-experimental-spi-imports", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable experimental support for SPI imports") public static let experimentalSpiOnlyImports: Option = Option("-experimental-spi-only-imports", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable use of @_spiOnly imports") - public static let explainModuleDependency: Option = Option("-explain-module-dependency", .separate, attributes: [], helpText: "Emit remark/notes describing why compilaiton may depend on a module with a given name.") + public static let enableExperimentalSwiftBasedClosureSpecialization: Option = Option("-experimental-swift-based-closure-specialization", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use the experimental Swift based closure-specialization optimization pass instead of the existing C++ one") + public static let explainModuleDependency: Option = Option("-explain-module-dependency", .separate, attributes: [], helpText: "Emit remark/notes describing why compilation may depend on a module with a given name.") public static let explicitDependencyGraphFormat: Option = Option("-explicit-dependency-graph-format=", .joined, attributes: [.helpHidden, .doesNotAffectIncrementalBuild], helpText: "Specify the explicit dependency graph output format to either 'json' or 'dot'") public static let explicitInterfaceModuleBuild: Option = Option("-explicit-interface-module-build", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use the specified command-line to build the module from interface, instead of flags specified in the interface") public static let driverExplicitModuleBuild: Option = Option("-explicit-module-build", .flag, attributes: [.helpHidden], helpText: "Prebuild module dependencies to make them explicit") @@ -647,6 +654,7 @@ extension Option { public static let pchDisableValidation: Option = Option("-pch-disable-validation", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable validating the persistent PCH") public static let pchOutputDir: Option = Option("-pch-output-dir", .separate, attributes: [.helpHidden, .frontend, .argumentIsPath], helpText: "Directory to persist automatically created precompiled bridging headers") public static let placeholderDependencyModuleMap: Option = Option("-placeholder-dependency-module-map-file", .separate, attributes: [.frontend, .noDriver], metaVar: "", helpText: "Specify a JSON file containing information of external Swift module dependencies") + public static let platformAvailabilityInheritanceMapPath: Option = Option("-platform-availability-inheritance-map-path", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "", helpText: "Path of the platform inheritance platform map") public static let playgroundHighPerformance: Option = Option("-playground-high-performance", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Omit instrumentation that has a high runtime performance impact") public static let playgroundOption: Option = Option("-playground-option", .separate, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Provide an option to the playground transform (if enabled)") public static let playground: Option = Option("-playground", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Apply the playground semantics and transformation") @@ -701,7 +709,7 @@ extension Option { public static let resourceDir: Option = Option("-resource-dir", .separate, attributes: [.helpHidden, .frontend, .argumentIsPath], metaVar: "", helpText: "The directory that holds the compiler resource files") public static let remarkIndexingSystemModule: Option = Option("-Rindexing-system-module", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit a remark when indexing a system module") public static let remarkMacroLoading: Option = Option("-Rmacro-loading", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit remarks about loaded macro implementations") - public static let remarkModuleApiImport: Option = Option("-Rmodule-api-import", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit remarks about the import briging in each element composing the API") + public static let remarkModuleApiImport: Option = Option("-Rmodule-api-import", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit remarks about the import bridging in each element composing the API") public static let RmoduleInterfaceRebuild: Option = Option("-Rmodule-interface-rebuild", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Emits a remark if an imported module needs to be re-compiled from its module interface") public static let remarkLoadingModule: Option = Option("-Rmodule-loading", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit remarks about loaded module") public static let remarkModuleRecovery: Option = Option("-Rmodule-recovery", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit remarks about contextual inconsistencies in loaded modules") @@ -745,7 +753,7 @@ extension Option { public static let silVerifyNone: Option = Option("-sil-verify-none", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Completely disable SIL verification") public static let skipImportInPublicInterface: Option = Option("-skip-import-in-public-interface", .separate, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Skip the import statement corresponding to a module name when printing the public interface.") public static let skipInheritedDocs: Option = Option("-skip-inherited-docs", .flag, attributes: [.helpHidden, .frontend, .noInteractive, .supplementaryOutput], helpText: "Skip emitting doc comments for members inherited through classes or default implementations") - public static let skipProtocolImplementations: Option = Option("-skip-protocol-implementations", .flag, attributes: [.helpHidden, .frontend, .noInteractive, .supplementaryOutput], helpText: "Skip emitting symbols that are implementations of protocol requirements or inherited from protocl extensions") + public static let skipProtocolImplementations: Option = Option("-skip-protocol-implementations", .flag, attributes: [.helpHidden, .frontend, .noInteractive, .supplementaryOutput], helpText: "Skip emitting symbols that are implementations of protocol requirements or inherited from protocol extensions") public static let skipSynthesizedMembers: Option = Option("-skip-synthesized-members", .flag, attributes: [.noDriver], helpText: "Skip members inherited through classes or default implementations") public static let solverDisableShrink: Option = Option("-solver-disable-shrink", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable the shrink phase of expression type checking") public static let solverExpressionTimeThresholdEQ: Option = Option("-solver-expression-time-threshold=", .joined, attributes: [.helpHidden, .frontend, .noDriver]) @@ -763,6 +771,7 @@ extension Option { public static let suppressStaticExclusivitySwap: Option = Option("-suppress-static-exclusivity-swap", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Suppress static violations of exclusive access with swap()") public static let suppressWarnings: Option = Option("-suppress-warnings", .flag, attributes: [.frontend], helpText: "Suppress all warnings") public static let swiftAsyncFramePointerEQ: Option = Option("-swift-async-frame-pointer=", .joined, attributes: [.helpHidden, .frontend, .noDriver], helpText: "One of 'auto', 'always' or 'never'") + public static let swiftModuleCrossImport: Option = Option("-swift-module-cross-import", .multiArg, attributes: [.frontend, .noDriver], metaVar: " ", helpText: "Specify the cross import module", numArgs: 2) public static let swiftModuleFile: Option = Option("-swift-module-file=", .joined, attributes: [.frontend, .noDriver], metaVar: "=", helpText: "Specify Swift module input explicitly built from textual interface") public static let swiftOnly: Option = Option("-swift-only", .flag, attributes: [.noDriver], helpText: "Only include APIs defined from Swift source") public static let swiftOnly_: Option = Option("--swift-only", .flag, alias: Option.swiftOnly, attributes: [.noDriver], helpText: "Only include APIs defined from Swift source") @@ -830,7 +839,7 @@ extension Option { public static let vfsoverlayEQ: Option = Option("-vfsoverlay=", .joined, alias: Option.vfsoverlay) public static let vfsoverlay: Option = Option("-vfsoverlay", .joinedOrSeparate, attributes: [.frontend, .argumentIsPath], helpText: "Add directory to VFS overlay file") public static let visualcToolsRoot: Option = Option("-visualc-tools-root", .separate, attributes: [.frontend, .argumentIsPath], metaVar: "", helpText: "VisualC++ Tools Root") - public static let visualcToolsVersion: Option = Option("-visualc-tools-version", .separate, attributes: [.frontend,], metaVar: "", helpText: "VisualC++ ToolSet Version") + public static let visualcToolsVersion: Option = Option("-visualc-tools-version", .separate, attributes: [.frontend], metaVar: "", helpText: "VisualC++ ToolSet Version") public static let v: Option = Option("-v", .flag, attributes: [.doesNotAffectIncrementalBuild], helpText: "Show commands to run and use verbose output") public static let warnConcurrency: Option = Option("-warn-concurrency", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Warn about code that is unsafe according to the Swift Concurrency model and will become ill-formed in a future language version") public static let warnImplicitOverrides: Option = Option("-warn-implicit-overrides", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Warn about implicit overrides of protocol members") @@ -1013,6 +1022,7 @@ extension Option { Option.disableDeserializationRecovery, Option.disableDeserializationSafety, Option.disableDiagnosticPasses, + Option.disableDynamicActorIsolation, Option.disableEmitGenericClassRoTList, Option.disableExperimentalClangImporterDiagnostics, Option.disableExperimentalLifetimeDependenceInference, @@ -1055,7 +1065,9 @@ extension Option { Option.disableOnlyOneDependencyFile, Option.disableOsChecks, Option.disableOsChecks_, + Option.disableOssaCompleteLifetimes, Option.disableOssaOpts, + Option.disableOssaVerifyComplete, Option.disablePlaygroundTransform, Option.disablePreallocatedInstantiationCaches, Option.disablePreviousImplementationCallsInDynamicReplacements, @@ -1063,6 +1075,7 @@ extension Option { Option.disableReadonlyStaticObjects, Option.disableReflectionMetadata, Option.disableReflectionNames, + Option.disableStrictConcurrencyRegionBasedIsolation, Option.disableRelativeProtocolWitnessTables, Option.disableRemoveDeprecatedCheck, Option.disableRemoveDeprecatedCheck_, @@ -1148,6 +1161,7 @@ extension Option { Option.emitDependencies, Option.emitDigesterBaselinePath, Option.emitDigesterBaseline, + Option.emitEmptyObjectFile, Option.emitExecutable, Option.emitExtensionBlockSymbols, Option.emitFineGrainedDependencySourcefileDotFiles, @@ -1250,7 +1264,6 @@ extension Option { Option.enableFragileResilientProtocolWitnesses, Option.enableImplicitBacktracingModuleImport, Option.enableImplicitDynamic, - Option.enableImportPtrauthFieldFunctionPointers, Option.enableIncrementalImports, Option.enableInferPublicConcurrentValue, Option.enableInvalidEphemeralnessAsError, @@ -1276,6 +1289,7 @@ extension Option { Option.enableOperatorDesignatedTypes, Option.enableOssaCompleteLifetimes, Option.enableOssaModules, + Option.enableOssaVerifyComplete, Option.enablePackMetadataStackPromotion, Option.enablePackMetadataStackPromotionNoArg, Option.enablePrivateImports, @@ -1303,6 +1317,7 @@ extension Option { Option.entryPointFunctionName, Option.experimentalAllowModuleWithCompilerErrors, Option.experimentalAllowNonResilientAccess, + Option.experimentalAllowedReexportedModules, Option.experimentalCForeignReferenceTypes, Option.experimentalClangImporterDirectCc1Scan, Option.experimentalCxxStdlib, @@ -1326,6 +1341,7 @@ extension Option { Option.experimentalSkipNonInlinableFunctionBodies, Option.experimentalSpiImports, Option.experimentalSpiOnlyImports, + Option.enableExperimentalSwiftBasedClosureSpecialization, Option.explainModuleDependency, Option.explicitDependencyGraphFormat, Option.explicitInterfaceModuleBuild, @@ -1491,6 +1507,7 @@ extension Option { Option.pchDisableValidation, Option.pchOutputDir, Option.placeholderDependencyModuleMap, + Option.platformAvailabilityInheritanceMapPath, Option.playgroundHighPerformance, Option.playgroundOption, Option.playground, @@ -1607,6 +1624,7 @@ extension Option { Option.suppressStaticExclusivitySwap, Option.suppressWarnings, Option.swiftAsyncFramePointerEQ, + Option.swiftModuleCrossImport, Option.swiftModuleFile, Option.swiftOnly, Option.swiftOnly_, diff --git a/Sources/SwiftOptions/ParsedOptions.swift b/Sources/SwiftOptions/ParsedOptions.swift index 8b209b1fa..6cf27266b 100644 --- a/Sources/SwiftOptions/ParsedOptions.swift +++ b/Sources/SwiftOptions/ParsedOptions.swift @@ -74,7 +74,7 @@ extension ParsedOption: CustomStringConvertible { case .joinedOrSeparate, .separate: return option.spelling + " " + argument.asSingle.spm_shellEscaped() - case .remaining: + case .remaining, .multiArg: let args = argument.asMultiple if args.isEmpty { return option.spelling @@ -193,7 +193,7 @@ extension ParsedOptions { result.append(parsed.option.spelling) result.append(parsed.argument.asSingle) - case .remaining: + case .remaining, .multiArg: result.append(parsed.option.spelling) result.append(contentsOf: parsed.argument.asMultiple) } diff --git a/Sources/makeOptions/makeOptions.cpp b/Sources/makeOptions/makeOptions.cpp index 9926d7911..5ab8472d5 100644 --- a/Sources/makeOptions/makeOptions.cpp +++ b/Sources/makeOptions/makeOptions.cpp @@ -34,6 +34,7 @@ enum class OptionKind { RemainingArgs, CommaJoined, JoinedOrSeparate, + MultiArg, }; #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(ID_PREFIX, PREFIX, NAME, ID, KIND, \ @@ -113,6 +114,7 @@ struct RawOption { unsigned flags; const char *helpText; const char *metaVar; + unsigned numArgs; bool isGroup() const { return kind == OptionKind::Group; @@ -135,7 +137,7 @@ static const RawOption rawOptions[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ { OptionID::Opt_##ID, PREFIX, NAME, swiftify(#ID), OptionKind::KIND, \ - OptionID::Opt_##GROUP, OptionID::Opt_##ALIAS, FLAGS, HELPTEXT, METAVAR }, + OptionID::Opt_##GROUP, OptionID::Opt_##ALIAS, FLAGS, HELPTEXT, METAVAR, PARAM }, #include "swift/Option/Options.inc" #undef OPTION }; @@ -291,6 +293,10 @@ int makeOptions_main() { out << ".separate"; break; + case OptionKind::MultiArg: + out << ".multiArg"; + break; + case OptionKind::Group: case OptionKind::Unknown: assert(false && "Should have been filtered out"); @@ -350,6 +356,9 @@ int makeOptions_main() { if (option.group != OptionID::Opt_INVALID) { out << ", group: ." << groups[groupIndexByID[option.group]].id; } + if (option.kind == OptionKind::MultiArg) { + out << ", numArgs: " << option.numArgs; + } out << ")\n"; }); }); diff --git a/Tests/SwiftOptionsTests/OptionParsingTests.swift b/Tests/SwiftOptionsTests/OptionParsingTests.swift index 71346857a..b6ef6387b 100644 --- a/Tests/SwiftOptionsTests/OptionParsingTests.swift +++ b/Tests/SwiftOptionsTests/OptionParsingTests.swift @@ -36,6 +36,20 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(results.description, "-- input1 input2") } + func testParsingMultiArg() throws { + var options = OptionTable() + let two = Option("-two", .multiArg, attributes: [], numArgs: 2) + let three = Option("-three", .multiArg, attributes: [], numArgs: 3) + options.addNewOption(two) + options.addNewOption(three) + let results = try options.parse(["-two", "1", "2", "-three", "1", "2", "3", "-two", "2", "3"], for: .batch) + XCTAssertEqual(results.description, "-two 1 2 -three 1 2 3 -two 2 3") + // Check not enough arguments are passed. + XCTAssertThrowsError(try options.parse(["-two", "1"], for: .batch)) { error in + XCTAssertEqual(error as? OptionParseError, .missingArgument(index: 0, argument: "-two")) + } + } + func testParseErrors() { let options = OptionTable() @@ -85,3 +99,9 @@ final class SwiftDriverTests: XCTestCase { } } } + +extension OptionTable { + mutating func addNewOption(_ opt: Option) { + options.append(opt) + } +}