//===--- LangOptions.h - Language & configuration options -------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the LangOptions class, which provides various // language and configuration flags. // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_LANGOPTIONS_H #define SWIFT_BASIC_LANGOPTIONS_H #include "swift/Basic/CXXStdlibKind.h" #include "swift/Basic/Feature.h" #include "swift/Basic/FunctionBodySkipping.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/PlaygroundOption.h" #include "swift/Basic/Version.h" #include "swift/Config.h" #include "clang/CAS/CASOptions.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/Regex.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include #include #include #include namespace swift { struct DiagnosticBehavior; class DiagnosticEngine; /// Kind of implicit platform conditions. enum class PlatformConditionKind { #define PLATFORM_CONDITION(LABEL, IDENTIFIER) LABEL, #include "swift/AST/PlatformConditionKinds.def" }; /// Describes how strict concurrency checking should be. enum class StrictConcurrency { /// Enforce Sendable constraints where it has been explicitly adopted and /// perform actor-isolation checking wherever code has adopted concurrency. Minimal, /// Enforce Sendable constraints and perform actor-isolation checking /// wherever code has adopted concurrency, including code that has /// explicitly adopted Sendable. Targeted, /// Enforce Sendable constraints and actor-isolation checking throughout /// the entire module. Complete, }; /// Access or distribution level of a library. enum class LibraryLevel : uint8_t { /// Application Programming Interface that is publicly distributed so /// public decls are really public and only @_spi decls are SPI. API, /// System Programming Interface that has restricted distribution /// all decls in the module are considered to be SPI including public ones. SPI, /// Internal Programming Interface that is not distributed and only usable /// from within a project. IPI, /// The library has some other undefined distribution. Other }; enum class AccessNoteDiagnosticBehavior : uint8_t { Ignore, RemarkOnFailure, RemarkOnFailureOrSuccess, ErrorOnFailureRemarkOnSuccess }; enum class ConcurrencyModel : uint8_t { Standard, TaskToThread, }; enum class DefaultIsolation : uint8_t { MainActor, Nonisolated }; /// Describes the code size optimization behavior for code associated with /// declarations that are marked unavailable. enum class UnavailableDeclOptimization : uint8_t { /// No optimization. Unavailable declarations will contribute to the /// resulting binary by default in this mode. None, /// Stub out code associated with unavailable declarations. /// /// For example, the bodies of unavailable functions should be compiled as /// if they just contained a call to fatalError(). Stub, /// Avoid generating any code for unavailable declarations. /// /// NOTE: This optimization can be ABI breaking for a library evolution /// enabled module because existing client binaries built with a /// pre-Swift 5.9 compiler may depend on linkable symbols associated with /// unavailable declarations. Complete, }; /// A collection of options that affect the language dialect and /// provide compiler debugging facilities. class LangOptions final { public: /// The target we are building for. /// /// This represents the minimum deployment target. llvm::Triple Target; /// \brief The second target for a zippered build /// /// This represents the target and minimum deployment version for the /// second ('variant') target when performing a zippered build. /// For example, if the target is x86_64-apple-macosx10.14 then /// a target-variant of x86_64-apple-ios12.0-macabi will produce /// a zippered binary that can be loaded into both macCatalyst and /// macOS processes. A value of 'None' means no zippering will be /// performed. std::optional TargetVariant; /// The target triple to instantiate the internal clang instance. /// When not specified, the compiler will use the value of -target to /// instantiate the clang instance. /// This is mainly used to avoid lowering the target triple to use for clang when /// importing a .swiftinterface whose -target value may be different from /// the loading module. /// The lowering triple may result in multiple versions of the same Clang /// modules being built. std::optional ClangTarget; std::optional ClangTargetVariant; /// The SDK version, if known. std::optional SDKVersion; /// The target variant SDK version, if known. std::optional VariantSDKVersion; /// The SDK canonical name, if known. std::string SDKName; /// The lowest target OS version that code in this module may be inlined /// into. In resilient modules, this should match the minimum /// deployment target of the *first* resilient version of the module, since /// clients may need to interoperate with versions as far back as that /// deployment target. llvm::VersionTuple MinimumInliningTargetVersion; /// The alternate name to use for the entry point instead of main. std::optional entryPointFunctionName; /// /// Language features /// /// User-overridable language version to compile for. version::Version EffectiveLanguageVersion = version::Version{5, 10}; /// Swift runtime version to compile for. version::Version RuntimeVersion = version::Version::getCurrentLanguageVersion(); /// PackageDescription version to compile for. version::Version PackageDescriptionVersion; /// Enable experimental string processing bool EnableExperimentalStringProcessing = true; /// Disable API availability checking. bool DisableAvailabilityChecking = false; /// Optimization mode for unavailable declarations. std::optional UnavailableDeclOptimizationMode; /// Causes the compiler to use weak linkage for symbols belonging to /// declarations introduced at the deployment target. bool WeakLinkAtTarget = false; /// Should the editor placeholder error be downgraded to a warning? bool WarnOnEditorPlaceholder = false; /// Maximum number of typo corrections we are allowed to perform. /// This is disabled by default until we can get typo-correction working within acceptable performance bounds. unsigned TypoCorrectionLimit = 0; /// Should access control be respected? bool EnableAccessControl = true; /// Enable loading a package interface if both client and depdency module are in the /// same package determined by `package-name` flag. bool EnablePackageInterfaceLoad = false; /// Enable 'availability' restrictions for App Extensions. bool EnableAppExtensionRestrictions = false; /// Enable 'availability' restrictions for App Extension Libraries. bool EnableAppExtensionLibraryRestrictions = false; /// Diagnostic level to report when a public declarations doesn't declare /// an introduction OS version. enum class RequireExplicitAvailabilityDiagnosticBehavior : uint8_t { Ignore, Warning, Error, }; RequireExplicitAvailabilityDiagnosticBehavior RequireExplicitAvailabilityBehavior = RequireExplicitAvailabilityDiagnosticBehavior::Ignore; /// Introduction platform and version to suggest as fix-it /// when using RequireExplicitAvailability. std::string RequireExplicitAvailabilityTarget; // Availability macros definitions to be expanded at parsing. SmallVector AvailabilityMacros; /// Require public declarations to declare that they are Sendable (or not). bool RequireExplicitSendable = false; /// Detect and automatically import modules' cross-import overlays. bool EnableCrossImportOverlays = false; /// Emit a remark when import resolution implicitly adds a cross-import /// overlay. bool EnableCrossImportRemarks = false; /// Emit a remark after loading a module. bool EnableModuleLoadingRemarks = false; /// Emit remarks about contextual inconsistencies in loaded modules. bool EnableModuleRecoveryRemarks = false; /// Emit remarks for unexpected conditions when serializing a module. bool EnableModuleSerializationRemarks = false; /// Emit remarks about the source of each element exposed by the module API. bool EnableModuleApiImportRemarks = false; /// Emit a remark after loading a macro implementation. bool EnableMacroLoadingRemarks = false; /// Emit a remark when indexing a system module. bool EnableIndexingSystemModuleRemarks = false; /// Emit a remark on early exit in explicit interface build bool EnableSkipExplicitInterfaceModuleBuildRemarks = false; /// Emit a remark when \c \@abi infers an attribute or modifier. bool EnableABIInferenceRemarks = false; /// /// Support for alternate usage modes /// /// Enable features useful for running in the debugger. bool DebuggerSupport = false; /// Used only by the debugger. When set, the module loader will try to /// import non-public transitive dependencies. bool ImportNonPublicDependencies = false; /// Enable the MemoryBufferSerializedModuleImporter. /// Only used by lldb-moduleimport-test. bool EnableMemoryBufferImporter = false; /// Allows using identifiers with a leading dollar. bool EnableDollarIdentifiers = false; /// Allow throwing call expressions without annotation with 'try'. bool EnableThrowWithoutTry = false; /// Turn all throw sites into immediate traps. bool ThrowsAsTraps = false; /// If set, inserts instrumentation useful for testing the debugger. bool DebuggerTestingTransform = false; /// Indicates whether the AST should be instrumented to simulate a /// debugger's program counter. Similar to the PlaygroundTransform, this /// will instrument the AST with function calls that get called when you /// would see a program counter move in a debugger. To adopt this implement /// the __builtin_pc_before and __builtin_pc_after functions. bool PCMacro = false; /// Enable features useful for running playgrounds. // FIXME: This should probably be limited to the particular SourceFile. bool Playground = false; /// Indicates whether the playground transformation should be applied. bool PlaygroundTransform = false; /// Indicates the specific playground transformations to apply. PlaygroundOptionSet PlaygroundOptions; /// Keep comments during lexing and attach them to declarations. bool AttachCommentsToDecls = false; /// /// Flags for use by tests /// /// Enable Objective-C Runtime interop code generation and build /// configuration options. bool EnableObjCInterop = true; /// Enable C++ interop code generation and build configuration /// options. Disabled by default because there is no way to control the /// language mode of clang on a per-header or even per-module basis. Also /// disabled because it is not complete. bool EnableCXXInterop = false; /// The C++ interoperability source compatibility version. Defaults /// to the Swift language version. version::Version cxxInteropCompatVersion; /// What version of C++ interoperability a textual interface was originally /// generated with (if at all). std::optional FormalCxxInteropMode; void setCxxInteropFromArgs(llvm::opt::ArgList &Args, swift::DiagnosticEngine &Diags); /// The C++ standard library used for the current build. This can differ /// from the default C++ stdlib on a particular platform when `-Xcc /// -stdlib=xyz` was passed to the compiler. CXXStdlibKind CXXStdlib = CXXStdlibKind::Unknown; CXXStdlibKind PlatformDefaultCXXStdlib = CXXStdlibKind::Unknown; bool isUsingPlatformDefaultCXXStdlib() const { return CXXStdlib == PlatformDefaultCXXStdlib; } bool CForeignReferenceTypes = false; /// Imports getters and setters as computed properties. bool CxxInteropGettersSettersAsProperties = false; /// Should the compiler require C++ interoperability to be enabled /// when importing Swift modules that enable C++ interoperability. bool RequireCxxInteropToImportCxxInteropModule = true; // Workaround for bug when building SwiftCompilerSources (rdar://128013193) bool CxxInteropUseOpaquePointerForMoveOnly = false; /// On Darwin platforms, use the pre-stable ABI's mark bit for Swift /// classes instead of the stable ABI's bit. This is needed when /// targeting OSes prior to macOS 10.14.4 and iOS 12.2, where /// libobjc does not support the stable ABI's marker bit. bool UseDarwinPreStableABIBit = false; /// Enables checking that uses of @objc require importing /// the Foundation module. /// This is enabled by default because SILGen can crash in such a case, but /// it gets disabled when compiling the Swift core stdlib. bool EnableObjCAttrRequiresFoundation = true; /// If true, @testable import Foo produces an error if \c Foo /// was not compiled with -enable-testing. bool EnableTestableAttrRequiresTestableModule = true; /// /// Flags for developers /// /// Whether to record request references for incremental builds. bool RecordRequestReferences = true; /// Whether to dump debug info for request evaluator cycles. bool DebugDumpCycles = false; /// Disable SIL substituted function types. bool DisableSubstSILFunctionTypes = false; /// Whether to diagnose an ephemeral to non-ephemeral conversion as an /// error. bool DiagnoseInvalidEphemeralnessAsError = false; /// The maximum depth to which to test decl circularity. unsigned MaxCircularityDepth = 500; /// Perform all dynamic allocations using malloc/free instead of /// optimized custom allocator, so that memory debugging tools can be used. bool UseMalloc = false; /// Specifies how strict concurrency checking will be. StrictConcurrency StrictConcurrencyLevel = StrictConcurrency::Minimal; /// Enable experimental concurrency model. bool EnableExperimentalConcurrency = false; /// Disable experimental ClangImporter diagnostics. bool DisableExperimentalClangImporterDiagnostics = false; /// Enable experimental eager Clang module diagnostics. bool EnableExperimentalEagerClangModuleDiagnostics = false; /// Force ClangImporter's import-as-member extensions to load thier members /// immediately, bypassing their SwiftLookupTables. This emulates an /// implementation quirk of previous compilers. bool DisableNamedLazyImportAsMemberLoading = false; /// Disable the implicit import of the _Concurrency module. bool DisableImplicitConcurrencyModuleImport = !SWIFT_IMPLICIT_CONCURRENCY_IMPORT; /// Disable the implicit import of the _StringProcessing module. bool DisableImplicitStringProcessingModuleImport = false; /// Disable the implicit import of the Cxx module. bool DisableImplicitCxxModuleImport = false; // Whether to use checked continuations when making an async call from // Swift into ObjC. If false, will use unchecked continuations instead. bool UseCheckedAsyncObjCBridging = false; /// Should we check the target OSs of serialized modules to see that they're /// new enough? bool EnableTargetOSChecking = true; /// Whether to attempt to recover from missing cross-references, /// differences in APIs between language versions, and other /// errors when deserializing from a binary swiftmodule file. /// /// This feature should only be disabled for testing as regular builds /// rely heavily on it. bool EnableDeserializationRecovery = true; /// Enable early skipping deserialization of decls that are marked as /// unsafe to read. bool EnableDeserializationSafety = ::getenv("SWIFT_ENABLE_DESERIALIZATION_SAFETY"); /// Attempt to recover for imported modules with broken modularization /// in an unsafe way. Currently applies only to xrefs where the target /// decl moved to a different module that is already loaded. bool ForceWorkaroundBrokenModules = false; /// Whether to enable the new operator decl and precedencegroup lookup /// behavior. This is a staging flag, and will be removed in the future. bool EnableNewOperatorLookup = false; /// Use Clang function types for computing canonical types. /// If this option is false, the clang function types will still be computed /// but will not be used for checking type equality. /// [TODO: Clang-type-plumbing] Turn on for feature rollout. bool UseClangFunctionTypes = false; /// Access or distribution level of the whole module being parsed. LibraryLevel LibraryLevel = LibraryLevel::Other; /// The name of the package this module belongs to. std::string PackageName; /// Allow importing a non-package interface from the same package. bool AllowNonPackageInterfaceImportFromSamePackage = false; /// Diagnose implicit 'override'. bool WarnImplicitOverrides = false; /// Diagnose use of declarations that are soft-deprecated. bool WarnSoftDeprecated = false; /// Diagnose uses of NSCoding with classes that have unstable mangled names. bool EnableNSKeyedArchiverDiagnostics = true; /// Regex for the passes that should report passed and missed optimizations. /// /// These are shared_ptrs so that this class remains copyable. std::shared_ptr OptimizationRemarkPassedPattern; std::shared_ptr OptimizationRemarkMissedPattern; /// How should we emit diagnostics about access notes? AccessNoteDiagnosticBehavior AccessNoteBehavior = AccessNoteDiagnosticBehavior::RemarkOnFailureOrSuccess; DiagnosticBehavior getAccessNoteFailureLimit() const; bool shouldRemarkOnAccessNoteSuccess() const { return AccessNoteBehavior >= AccessNoteDiagnosticBehavior::RemarkOnFailureOrSuccess; } /// Whether collect tokens during parsing for syntax coloring. bool CollectParsedToken = false; /// Whether to disable the evaluation of '#if' decls, such that the bodies /// of active clauses aren't hoisted into the enclosing scope. bool DisablePoundIfEvaluation = false; /// When using fine-grained dependencies, emit dot files for every swiftdeps /// file. bool EmitFineGrainedDependencySourcefileDotFiles = false; /// Enable verification when every SubstitutionMap is constructed. bool VerifyAllSubstitutionMaps = false; /// If set to true, the source manager will avoid memory mapping source files /// with the expectation they may change on disk. This is most useful when /// opening files under sourcekitd on Windows, as memory mapping on Windows /// prevents files from being written. bool OpenSourcesAsVolatile = false; /// Load swiftmodule files in memory as volatile and avoid mmap. bool EnableVolatileModules = false; /// Enable experimental 'hermetic seal at link' feature. Turns on /// dead-stripping optimizations assuming that all users of library code /// are present at LTO time. bool HermeticSealAtLink = false; /// Allow deserializing implementation only dependencies. This should only /// be set true by lldb and other tooling, so that deserialization /// recovery issues won't bring down the debugger. /// TODO: remove this when @_implementationOnly modules are robust enough. bool AllowDeserializingImplementationOnly = false; // Allow errors during module generation. See corresponding option in // FrontendOptions. bool AllowModuleWithCompilerErrors = false; /// Enable using @_spiOnly on import decls. bool EnableSPIOnlyImports = false; /// A helper enum to represent whether or not we customized the default /// ASTVerifier behavior via a frontend flag. By default, we do not /// customize. /// /// NOTE: The default behavior is to run the ASTVerifier only when asserts /// are enabled. This just allows for one to customize that behavior. enum class ASTVerifierOverrideKind { NoOverride = 0, EnableVerifier = 1, DisableVerifier = 2, }; ASTVerifierOverrideKind ASTVerifierOverride = ASTVerifierOverrideKind::NoOverride; /// Dumps request evaluator cache statistics at the end of compilation. bool AnalyzeRequestEvaluator = false; /// Enables dumping rewrite systems from the requirement machine. bool DumpRequirementMachine = false; /// Enables statistics output from the requirement machine. bool AnalyzeRequirementMachine = false; /// Enables fine-grained debug output from the requirement machine. std::string DebugRequirementMachine; /// Maximum rule count for requirement machine Knuth-Bendix completion /// algorithm. unsigned RequirementMachineMaxRuleCount = 4000; /// Maximum term length for requirement machine Knuth-Bendix completion /// algorithm. unsigned RequirementMachineMaxRuleLength = 12; /// Maximum concrete type nesting depth for requirement machine property map /// algorithm. unsigned RequirementMachineMaxConcreteNesting = 30; /// Maximum number of attempts to make when splitting concrete equivalence /// classes. unsigned RequirementMachineMaxSplitConcreteEquivClassAttempts = 2; /// Enable preprocessing pass to eliminate conformance requirements /// on generic parameters which are made concrete. Usually you want this /// enabled. It can be disabled for debugging and testing. bool EnableRequirementMachineConcreteContraction = true; /// Enable the stronger minimization algorithm. Usually you want this /// enabled. It can be disabled for debugging and testing. bool EnableRequirementMachineLoopNormalization = true; /// Enable reuse of requirement machines for minimization. Usually you want /// this enabled. It can be disabled for debugging and testing. bool EnableRequirementMachineReuse = true; /// Enable experimental, more correct support for opaque result types as /// concrete types. This will sometimes fail to produce a convergent /// rewrite system. bool EnableRequirementMachineOpaqueArchetypes = false; /// Enable implicit lifetime dependence for ~Escapable return types. bool EnableExperimentalLifetimeDependenceInference = false; /// Skips decls that cannot be referenced externally. bool SkipNonExportableDecls = false; /// True if -allow-non-resilient-access is passed and built /// from source. bool AllowNonResilientAccess = false; /// When Package CMO is enabled, deserialization checks ensure that a decl's /// members are correctly deserialized to maintain the proper layout—a prerequisite /// for bypassing resilience when accessing the decl. By default, a warning is issued /// if a deserialization failure is found; this flag causes the build to fail fast instead. bool AbortOnDeserializationFailForPackageCMO = false; /// Enables dumping type witness systems from associated type inference. bool DumpTypeWitnessSystems = false; /// Enables dumping macro expansions. bool DumpMacroExpansions = false; /// The model of concurrency to be used. ConcurrencyModel ActiveConcurrencyModel = ConcurrencyModel::Standard; /// All block list configuration files to be honored in this compilation. std::vector BlocklistConfigFilePaths; /// Whether to ignore checks that a module is resilient during /// type-checking, SIL verification, and IR emission, bool BypassResilienceChecks = false; /// Disables `DynamicActorIsolation` feature. bool DisableDynamicActorIsolation = false; /// Defines the default actor isolation. DefaultIsolation DefaultIsolationBehavior = DefaultIsolation::Nonisolated; /// Whether or not to allow experimental features that are only available /// in "production". #ifdef NDEBUG bool RestrictNonProductionExperimentalFeatures = true; #else bool RestrictNonProductionExperimentalFeatures = false; #endif bool isConcurrencyModelTaskToThread() const { return ActiveConcurrencyModel == ConcurrencyModel::TaskToThread; } bool isDynamicActorIsolationCheckingEnabled() const { return !DisableDynamicActorIsolation && hasFeature(Feature::DynamicActorIsolation); } LangOptions(); /// Sets the target we are building for and updates platform conditions /// to match. /// /// \returns A pair - the first element is true if the OS was invalid. /// The second element is true if the Arch was invalid. std::pair setTarget(llvm::Triple triple); /// Returns the minimum platform version to which code will be deployed. /// /// This is only implemented on certain OSs. If no target has been /// configured, returns v0.0.0. llvm::VersionTuple getMinPlatformVersion() const { if (Target.isMacOSX()) { llvm::VersionTuple OSVersion; Target.getMacOSXVersion(OSVersion); return OSVersion; } else if (Target.isiOS()) { return Target.getiOSVersion(); } else if (Target.isWatchOS()) { return Target.getOSVersion(); } else if (Target.isXROS()) { return Target.getOSVersion(); } return llvm::VersionTuple(/*Major=*/0, /*Minor=*/0, /*Subminor=*/0); } /// Sets an implicit platform condition. void addPlatformConditionValue(PlatformConditionKind Kind, StringRef Value) { assert(!Value.empty()); PlatformConditionValues.emplace_back(Kind, Value.str()); } /// Removes all values added with addPlatformConditionValue. void clearAllPlatformConditionValues() { PlatformConditionValues.clear(); } /// Returns the value for the given platform condition or an empty string. StringRef getPlatformConditionValue(PlatformConditionKind Kind) const; /// Check whether the given platform condition matches the given value. bool checkPlatformCondition(PlatformConditionKind Kind, StringRef Value) const; /// Explicit conditional compilation flags, initialized via the '-D' /// compiler flag. void addCustomConditionalCompilationFlag(StringRef Name) { assert(!Name.empty()); CustomConditionalCompilationFlags.push_back(Name.str()); } /// Determines if a given conditional compilation flag has been set. bool isCustomConditionalCompilationFlagSet(StringRef Name) const; ArrayRef> getPlatformConditionValues() const { return PlatformConditionValues; } ArrayRef getCustomConditionalCompilationFlags() const { return CustomConditionalCompilationFlags; } /// Whether our effective Swift version is at least 'major'. /// /// This is usually the check you want; for example, when introducing /// a new language feature which is only visible in Swift 5, you would /// check for isSwiftVersionAtLeast(5). bool isSwiftVersionAtLeast(unsigned major, unsigned minor = 0) const { return EffectiveLanguageVersion.isVersionAtLeast(major, minor); } /// Whether the C++ interoperability compatibility version is at least /// 'major'. bool isCxxInteropCompatVersionAtLeast(unsigned major, unsigned minor = 0) const { return cxxInteropCompatVersion.isVersionAtLeast(major, minor); } /// Sets the "_hasAtomicBitWidth" conditional. void setHasAtomicBitWidth(llvm::Triple triple); /// Set the max atomic bit widths with the given bit width. void setMaxAtomicBitWidth(unsigned maxWidth) { switch (maxWidth) { case 128: AtomicBitWidths.emplace_back("_128"); AtomicBitWidthValues.push_back(128); LLVM_FALLTHROUGH; case 64: AtomicBitWidths.emplace_back("_64"); AtomicBitWidthValues.push_back(64); LLVM_FALLTHROUGH; case 32: AtomicBitWidths.emplace_back("_32"); AtomicBitWidthValues.push_back(32); LLVM_FALLTHROUGH; case 16: AtomicBitWidths.emplace_back("_16"); AtomicBitWidthValues.push_back(16); LLVM_FALLTHROUGH; case 8: AtomicBitWidths.emplace_back("_8"); AtomicBitWidthValues.push_back(8); break; default: return; } } /// Removes all atomic bit widths. void clearAtomicBitWidths() { AtomicBitWidths.clear(); AtomicBitWidthValues.clear(); } llvm::ArrayRef getAtomicBitWidthValues() const { return AtomicBitWidthValues; } /// Returns true if the given platform condition argument represents /// a supported target operating system. /// /// \param suggestedKind Populated with suggested replacement platform condition /// \param suggestedValues Populated with suggested replacement values /// if a match is not found, or if the value has been deprecated /// in favor of a newer one. static bool checkPlatformConditionSupported( PlatformConditionKind Kind, StringRef Value, PlatformConditionKind &suggestedKind, std::vector &suggestedValues); /// Return a hash code of any components from these options that should /// contribute to a Swift Bridging PCH hash. llvm::hash_code getPCHHashComponents() const { SmallString<16> Scratch; llvm::raw_svector_ostream OS(Scratch); OS << EffectiveLanguageVersion; return llvm::hash_combine(Target.str(), OS.str()); } /// Return a hash code of any components from these options that should /// contribute to a Swift Dependency Scanning hash. llvm::hash_code getModuleScanningHashComponents() const { auto hashValue = getPCHHashComponents(); if (TargetVariant.has_value()) hashValue = llvm::hash_combine(hashValue, TargetVariant.value().str()); if (ClangTarget.has_value()) hashValue = llvm::hash_combine(hashValue, ClangTarget.value().str()); if (ClangTargetVariant.has_value()) hashValue = llvm::hash_combine(hashValue, ClangTargetVariant.value().str()); if (SDKVersion.has_value()) hashValue = llvm::hash_combine(hashValue, SDKVersion.value().getAsString()); if (VariantSDKVersion.has_value()) hashValue = llvm::hash_combine(hashValue, VariantSDKVersion.value().getAsString()); return hashValue; } private: llvm::SmallVector AtomicBitWidths; llvm::SmallVector AtomicBitWidthValues; llvm::SmallVector, 10> PlatformConditionValues; llvm::SmallVector CustomConditionalCompilationFlags; public: //========================================================================== // MARK: Features //========================================================================== /// A wrapper around the feature state enumeration. struct FeatureState { enum class Kind : uint8_t { Off, EnabledForAdoption, Enabled }; private: Feature feature; Kind state; public: FeatureState(Feature feature, Kind state) : feature(feature), state(state) {} /// Returns whether the feature is enabled. bool isEnabled() const; /// Returns whether the feature is enabled in adoption mode. Should only /// be called if the feature is known to support this mode. bool isEnabledForAdoption() const; operator Kind() const { return state; } }; private: class FeatureStateStorage { std::vector states; public: FeatureStateStorage(); /// Sets the given state for the given feature. void setState(Feature feature, FeatureState::Kind state); /// Retrieves the state of the given feature. FeatureState getState(Feature feature) const; }; /// The states of language features. FeatureStateStorage featureStates; public: /// Retrieve the state of the given feature. FeatureState getFeatureState(Feature feature) const; /// Returns whether the given feature is enabled. bool hasFeature(Feature feature) const; /// Returns whether a feature with the given name is enabled. Returns /// `false` if a feature by this name is not known. bool hasFeature(llvm::StringRef featureName) const; /// Enables the given feature (enables in adoption mode if `forAdoption` is /// `true`). void enableFeature(Feature feature, bool forAdoption = false); /// Disables the given feature. void disableFeature(Feature feature); // ========================================================================= }; class TypeCheckerOptions final { public: /// If non-zero, warn when a function body takes longer than this many /// milliseconds to type-check. /// /// Intended for debugging purposes only. unsigned WarnLongFunctionBodies = 0; /// If non-zero, warn when type-checking an expression takes longer /// than this many milliseconds. /// /// Intended for debugging purposes only. unsigned WarnLongExpressionTypeChecking = 0; /// If non-zero, abort the expression type checker if it takes more /// than this many seconds. unsigned ExpressionTimeoutThreshold = 0; /// The upper bound, in bytes, of temporary data that can be /// allocated by the constraint solver. unsigned SolverMemoryThreshold = 512 * 1024 * 1024; /// The maximum number of scopes we explore before giving up. unsigned SolverScopeThreshold = 1024 * 1024; /// The maximum number of trail steps we take before giving up. unsigned SolverTrailThreshold = 64 * 1024 * 1024; /// If non-zero, abort the switch statement exhaustiveness checker if /// the Space::minus function is called more than this many times. /// /// Why this number? Times out in about a second on a 2017 iMac, Retina 5K, /// 4.2 GHz Intel Core i7. /// (It's arbitrary, but will keep the compiler from taking too much time.) unsigned SwitchCheckingInvocationThreshold = 200000; /// If true, the time it takes to type-check each function will be dumped /// to llvm::errs(). bool DebugTimeFunctionBodies = false; /// If true, the time it takes to type-check each expression will be /// dumped to llvm::errs(). bool DebugTimeExpressions = false; /// Controls the function bodies to skip during type-checking. FunctionBodySkipping SkipFunctionBodies = FunctionBodySkipping::None; /// /// Flags for developers /// /// Debug the generic signatures computed by the generic signature builder. bool DebugGenericSignatures = false; /// If this is set, we skip the inverse transform and print explicit /// Copyable/Escapable requirements in the above. bool DebugInverseRequirements = false; /// Whether we are debugging the constraint solver. /// /// This option enables verbose debugging output from the constraint /// solver. bool DebugConstraintSolver = false; /// Specific solution attempt for which the constraint /// solver should be debugged. unsigned DebugConstraintSolverAttempt = 0; /// Line numbers to activate the constraint solver debugger. /// Should be stored sorted. llvm::SmallVector DebugConstraintSolverOnLines; /// Triggers llvm fatal error if the typechecker tries to typecheck a decl /// or an identifier reference with any of the provided prefix names. This /// is for testing purposes. std::vector DebugForbidTypecheckPrefixes; /// Disable the shrink phase of the expression type checker. bool SolverDisableShrink = false; /// Enable experimental operator designated types feature. bool EnableOperatorDesignatedTypes = false; /// Disable constraint system performance hacks. bool DisableConstraintSolverPerformanceHacks = false; /// See \ref FrontendOptions.PrintFullConvention bool PrintFullConvention = false; /// Defer typechecking of declarations to their use at runtime bool DeferToRuntime = false; /// Allow request evalutation to perform type checking lazily, instead of /// eagerly typechecking source files after parsing. bool EnableLazyTypecheck = false; /// Disable the component splitter phase of the expression type checker. bool SolverDisableSplitter = false; }; /// Options for controlling the behavior of the Clang importer. class ClangImporterOptions final { public: /// The path to the Clang compiler executable. /// Used to detect the default include paths. std::string clangPath = "clang"; /// The module cache path which the Clang importer should use. std::string ModuleCachePath; /// The Scanning module cache path which the Clang Dependency Scanner should use. std::string ClangScannerModuleCachePath; /// Extra arguments which should be passed to the Clang importer. std::vector ExtraArgs; /// A directory for overriding Clang's resource directory. std::string OverrideResourceDir; /// The target CPU to compile for. /// /// Equivalent to Clang's -mcpu=. std::string TargetCPU; /// The path to which we should store indexing data, if any. std::string IndexStorePath; /// The bridging header or PCH that will be imported. std::string BridgingHeader; /// The bridging header PCH file. std::string BridgingHeaderPCH; /// When automatically generating a precompiled header from the bridging /// header, place it in this directory. std::string PrecompiledHeaderOutputDir; /// The optimization setting. This doesn't typically matter for /// import, but it can affect Clang's IR generation of static functions. std::string Optimization; /// Disable validating the persistent PCH. bool PCHDisableValidation = false; /// Don't verify input files for Clang modules if the module has been /// successfully validated or loaded during this build session. bool ValidateModulesOnce = false; /// Use the last modification time of this file as the underlying Clang /// build session timestamp. std::string BuildSessionFilePath; /// \see Mode enum class Modes : uint8_t { /// Set up Clang for importing modules into Swift and generating IR from /// Swift code. Normal, /// Set up Clang for backend compilation only. EmbedBitcode, /// Set up Clang to emit a precompiled module from a C/Objective-C module /// map or dump debugging info about a precompiled module. PrecompiledModule }; /// Controls how Clang is initially set up. Modes Mode = Modes::Normal; /// When set, preserves more information during import. /// /// Also \em disables some information that is only needed for object file /// generation. bool DetailedPreprocessingRecord = false; /// If true, Clang diagnostics will be dumped to stderr using Clang's /// diagnostic printer as well as being passed to Swift's diagnostic engine. bool DumpClangDiagnostics = false; /// If true, forward declarations will be imported using unavailable types /// instead of dropped altogether when possible. bool ImportForwardDeclarations = false; /// If true ignore the swift bridged attribute. bool DisableSwiftBridgeAttr = false; /// When set, don't look for or load overlays. bool DisableOverlayModules = false; /// When set, import SPI_AVAILABLE symbols with Swift SPI attributes. bool EnableClangSPI = true; /// When set, don't enforce warnings with -Werror. bool DebuggerSupport = false; /// When set, ClangImporter is disabled, and all requests go to the /// DWARFImporter delegate. bool DisableSourceImport = false; /// When building a PCM, rely on the Swift frontend's command-line -Xcc flags /// to build the Clang module via Clang frontend directly, /// and completely bypass the Clang driver. bool DirectClangCC1ModuleBuild = false; /// Disable implicitly-built Clang modules because they are explicitly /// built and provided to the compiler invocation. bool DisableImplicitClangModules = false; /// Enable ClangIncludeTree for explicit module builds scanning. bool UseClangIncludeTree = false; /// Using ClangIncludeTreeRoot for compilation. bool HasClangIncludeTreeRoot = false; /// Whether the dependency scanner should construct all swift-frontend /// invocations directly from clang cc1 args. bool ClangImporterDirectCC1Scan = false; /// Return a hash code of any components from these options that should /// contribute to a Swift Bridging PCH hash. llvm::hash_code getPCHHashComponents() const { using llvm::hash_combine; using llvm::hash_combine_range; return hash_combine(ModuleCachePath, hash_combine_range(ExtraArgs.begin(), ExtraArgs.end()), OverrideResourceDir, TargetCPU, BridgingHeader, PrecompiledHeaderOutputDir, static_cast(Mode), DetailedPreprocessingRecord, ImportForwardDeclarations, DisableSwiftBridgeAttr, DisableOverlayModules, EnableClangSPI); } /// Return a hash code of any components from these options that should /// contribute to a Swift Dependency Scanning hash. llvm::hash_code getModuleScanningHashComponents() const { return getPCHHashComponents(); } std::vector getRemappedExtraArgs( std::function pathRemapCallback) const; /// For a swift module dependency, interface build command generation must /// inherit /// `-Xcc` flags used for configuration of the building instance's /// `ClangImporter`. However, we can ignore Clang search path flags because /// explicit Swift module build tasks will not rely on them and they may be /// source-target-context-specific and hinder module sharing across /// compilation source targets. std::vector getReducedExtraArgsForSwiftModuleDependency() const; /// Get PCH input path. Return empty string if there is no PCH input. std::string getPCHInputPath() const; }; } // end namespace swift #endif // SWIFT_BASIC_LANGOPTIONS_H