//===- LangOptions.h - C Language Family Language Options -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file /// Defines the clang::LangOptions interface. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H #define LLVM_CLANG_BASIC_LANGOPTIONS_H #include "clang/Basic/CommentOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangStandard.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/StringRef.h" #include "llvm/TargetParser/Triple.h" #include #include #include namespace clang { /// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// this large collection of bitfields is a trivial class type. class LangOptionsBase { friend class CompilerInvocation; friend class CompilerInvocationBase; public: // Define simple language options (with no accessors). #define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" protected: // Define language options of enumeration type. These are private, and will // have accessors (below). #define LANGOPT(Name, Bits, Default, Description) #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ unsigned Name : Bits; #include "clang/Basic/LangOptions.def" }; /// In the Microsoft ABI, this controls the placement of virtual displacement /// members used to implement virtual inheritance. enum class MSVtorDispMode { Never, ForVBaseOverride, ForVFTable }; /// Shader programs run in specific pipeline stages. /// The order of these values matters, and must be kept in sync with the /// Triple Environment enum in llvm::Triple. The ordering is enforced in /// static_asserts in Triple.cpp and in clang/Basic/HLSLRuntime.h. enum class ShaderStage { Pixel = 0, Vertex, Geometry, Hull, Domain, Compute, Library, RayGeneration, Intersection, AnyHit, ClosestHit, Miss, Callable, Mesh, Amplification, Invalid, }; /// Keeps track of the various options that can be /// enabled, which controls the dialect of C or C++ that is accepted. class LangOptions : public LangOptionsBase { public: using Visibility = clang::Visibility; using RoundingMode = llvm::RoundingMode; enum GCMode { NonGC, GCOnly, HybridGC }; enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq }; // Automatic variables live on the stack, and when trivial they're usually // uninitialized because it's undefined behavior to use them without // initializing them. enum class TrivialAutoVarInitKind { Uninitialized, Zero, Pattern }; enum SignedOverflowBehaviorTy { // Default C standard behavior. SOB_Undefined, // -fwrapv SOB_Defined, // -ftrapv SOB_Trapping }; // FIXME: Unify with TUKind. enum CompilingModuleKind { /// Not compiling a module interface at all. CMK_None, /// Compiling a module from a module map. CMK_ModuleMap, /// Compiling a module header unit. CMK_HeaderUnit, /// Compiling a C++ modules interface unit. CMK_ModuleInterface, }; enum PragmaMSPointersToMembersKind { PPTMK_BestCase, PPTMK_FullGeneralitySingleInheritance, PPTMK_FullGeneralityMultipleInheritance, PPTMK_FullGeneralityVirtualInheritance }; using MSVtorDispMode = clang::MSVtorDispMode; enum DefaultCallingConvention { DCC_None, DCC_CDecl, DCC_FastCall, DCC_StdCall, DCC_VectorCall, DCC_RegCall, DCC_RtdCall }; enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; // Corresponds to _MSC_VER enum MSVCMajorVersion { MSVC2010 = 1600, MSVC2012 = 1700, MSVC2013 = 1800, MSVC2015 = 1900, MSVC2017 = 1910, MSVC2017_5 = 1912, MSVC2017_7 = 1914, MSVC2019 = 1920, MSVC2019_5 = 1925, MSVC2019_8 = 1928, MSVC2022_3 = 1933, }; enum SYCLMajorVersion { SYCL_None, SYCL_2017, SYCL_2020, // The "default" SYCL version to be used when none is specified on the // frontend command line. SYCL_Default = SYCL_2020 }; enum HLSLLangStd { HLSL_Unset = 0, HLSL_2015 = 2015, HLSL_2016 = 2016, HLSL_2017 = 2017, HLSL_2018 = 2018, HLSL_2021 = 2021, HLSL_202x = 2029, }; /// Clang versions with different platform ABI conformance. enum class ClangABI { /// Attempt to be ABI-compatible with code generated by Clang 3.8.x /// (SVN r257626). This causes <1 x long long> to be passed in an /// integer register instead of an SSE register on x64_64. Ver3_8, /// Attempt to be ABI-compatible with code generated by Clang 4.0.x /// (SVN r291814). This causes move operations to be ignored when /// determining whether a class type can be passed or returned directly. Ver4, /// Attempt to be ABI-compatible with code generated by Clang 6.0.x /// (SVN r321711). This causes determination of whether a type is /// standard-layout to ignore collisions between empty base classes /// and between base classes and member subobjects, which affects /// whether we reuse base class tail padding in some ABIs. Ver6, /// Attempt to be ABI-compatible with code generated by Clang 7.0.x /// (SVN r338536). This causes alignof (C++) and _Alignof (C11) to be /// compatible with __alignof (i.e., return the preferred alignment) /// rather than returning the required alignment. Ver7, /// Attempt to be ABI-compatible with code generated by Clang 9.0.x /// (SVN r351319). This causes vectors of __int128 to be passed in memory /// instead of passing in multiple scalar registers on x86_64 on Linux and /// NetBSD. Ver9, /// Attempt to be ABI-compatible with code generated by Clang 11.0.x /// (git 2e10b7a39b93). This causes clang to pass unions with a 256-bit /// vector member on the stack instead of using registers, to not properly /// mangle substitutions for template names in some cases, and to mangle /// declaration template arguments without a cast to the parameter type /// even when that can lead to mangling collisions. Ver11, /// Attempt to be ABI-compatible with code generated by Clang 12.0.x /// (git 8e464dd76bef). This causes clang to mangle lambdas within /// global-scope inline variables incorrectly. Ver12, /// Attempt to be ABI-compatible with code generated by Clang 14.0.x. /// This causes clang to: /// - mangle dependent nested names incorrectly. /// - make trivial only those defaulted copy constructors with a /// parameter-type-list equivalent to the parameter-type-list of an /// implicit declaration. Ver14, /// Attempt to be ABI-compatible with code generated by Clang 15.0.x. /// This causes clang to: /// - Reverse the implementation for DR692, DR1395 and DR1432. /// - pack non-POD members of packed structs. /// - consider classes with defaulted special member functions non-pod. Ver15, /// Attempt to be ABI-compatible with code generated by Clang 17.0.x. /// This causes clang to revert some fixes to its implementation of the /// Itanium name mangling scheme, with the consequence that overloaded /// function templates are mangled the same if they differ only by: /// - constraints /// - whether a non-type template parameter has a deduced type /// - the parameter list of a template template parameter Ver17, /// Conform to the underlying platform's C and C++ ABIs as closely /// as we can. Latest }; enum class CoreFoundationABI { /// No interoperability ABI has been specified Unspecified, /// CoreFoundation does not have any language interoperability Standalone, /// Interoperability with the ObjectiveC runtime ObjectiveC, /// Interoperability with the latest known version of the Swift runtime Swift, /// Interoperability with the Swift 5.0 runtime Swift5_0, /// Interoperability with the Swift 4.2 runtime Swift4_2, /// Interoperability with the Swift 4.1 runtime Swift4_1, }; enum FPModeKind { // Disable the floating point pragma FPM_Off, // Enable the floating point pragma FPM_On, // Aggressively fuse FP ops (E.g. FMA) disregarding pragmas. FPM_Fast, // Aggressively fuse FP ops and honor pragmas. FPM_FastHonorPragmas }; /// Possible floating point exception behavior. enum FPExceptionModeKind { /// Assume that floating-point exceptions are masked. FPE_Ignore, /// Transformations do not cause new exceptions but may hide some. FPE_MayTrap, /// Strictly preserve the floating-point exception semantics. FPE_Strict, /// Used internally to represent initial unspecified value. FPE_Default }; /// Possible float expression evaluation method choices. enum FPEvalMethodKind { /// The evaluation method cannot be determined or is inconsistent for this /// target. FEM_Indeterminable = -1, /// Use the declared type for fp arithmetic. FEM_Source = 0, /// Use the type double for fp arithmetic. FEM_Double = 1, /// Use extended type for fp arithmetic. FEM_Extended = 2, /// Used only for FE option processing; this is only used to indicate that /// the user did not specify an explicit evaluation method on the command /// line and so the target should be queried for its default evaluation /// method instead. FEM_UnsetOnCommandLine = 3 }; enum ExcessPrecisionKind { FPP_Standard, FPP_Fast, FPP_None }; /// Possible exception handling behavior. enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; enum class LaxVectorConversionKind { /// Permit no implicit vector bitcasts. None, /// Permit vector bitcasts between integer vectors with different numbers /// of elements but the same total bit-width. Integer, /// Permit vector bitcasts between all vectors with the same total /// bit-width. All, }; enum class AltivecSrcCompatKind { // All vector compares produce scalars except vector pixel and vector bool. // The types vector pixel and vector bool return vector results. Mixed, // All vector compares produce vector results as in GCC. GCC, // All vector compares produce scalars as in XL. XL, // Default clang behaviour. Default = Mixed, }; enum class SignReturnAddressScopeKind { /// No signing for any function. None, /// Sign the return address of functions that spill LR. NonLeaf, /// Sign the return address of all functions, All }; enum class SignReturnAddressKeyKind { /// Return address signing uses APIA key. AKey, /// Return address signing uses APIB key. BKey }; enum class ThreadModelKind { /// POSIX Threads. POSIX, /// Single Threaded Environment. Single }; enum class ExtendArgsKind { /// Integer arguments are sign or zero extended to 32/64 bits /// during default argument promotions. ExtendTo32, ExtendTo64 }; enum class GPUDefaultStreamKind { /// Legacy default stream Legacy, /// Per-thread default stream PerThread, }; enum class DefaultVisiblityExportMapping { None, /// map only explicit default visibilities to exported Explicit, /// map all default visibilities to exported All, }; enum class VisibilityForcedKinds { /// Force hidden visibility ForceHidden, /// Force protected visibility ForceProtected, /// Force default visibility ForceDefault, /// Don't alter the visibility Source, }; enum class VisibilityFromDLLStorageClassKinds { /// Keep the IR-gen assigned visibility. Keep, /// Override the IR-gen assigned visibility with default visibility. Default, /// Override the IR-gen assigned visibility with hidden visibility. Hidden, /// Override the IR-gen assigned visibility with protected visibility. Protected, }; enum class StrictFlexArraysLevelKind { /// Any trailing array member is a FAM. Default = 0, /// Any trailing array member of undefined, 0, or 1 size is a FAM. OneZeroOrIncomplete = 1, /// Any trailing array member of undefined or 0 size is a FAM. ZeroOrIncomplete = 2, /// Any trailing array member of undefined size is a FAM. IncompleteOnly = 3, }; enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran, CX_None }; public: /// The used language standard. LangStandard::Kind LangStd; /// Set of enabled sanitizers. SanitizerSet Sanitize; /// Is at least one coverage instrumentation type enabled. bool SanitizeCoverage = false; /// Paths to files specifying which objects /// (files, functions, variables) should not be instrumented. std::vector NoSanitizeFiles; /// Paths to the XRay "always instrument" files specifying which /// objects (files, functions, variables) should be imbued with the XRay /// "always instrument" attribute. /// WARNING: This is a deprecated field and will go away in the future. std::vector XRayAlwaysInstrumentFiles; /// Paths to the XRay "never instrument" files specifying which /// objects (files, functions, variables) should be imbued with the XRay /// "never instrument" attribute. /// WARNING: This is a deprecated field and will go away in the future. std::vector XRayNeverInstrumentFiles; /// Paths to the XRay attribute list files, specifying which objects /// (files, functions, variables) should be imbued with the appropriate XRay /// attribute(s). std::vector XRayAttrListFiles; /// Paths to special case list files specifying which entities /// (files, functions) should or should not be instrumented. std::vector ProfileListFiles; clang::ObjCRuntime ObjCRuntime; CoreFoundationABI CFRuntime = CoreFoundationABI::Unspecified; std::string ObjCConstantStringClass; /// The name of the handler function to be called when -ftrapv is /// specified. /// /// If none is specified, abort (GCC-compatible behaviour). std::string OverflowHandler; /// The module currently being compiled as specified by -fmodule-name. std::string ModuleName; /// The name of the current module, of which the main source file /// is a part. If CompilingModule is set, we are compiling the interface /// of this module, otherwise we are compiling an implementation file of /// it. This starts as ModuleName in case -fmodule-name is provided and /// changes during compilation to reflect the current module. std::string CurrentModule; /// The names of any features to enable in module 'requires' decls /// in addition to the hard-coded list in Module.cpp and the target features. /// /// This list is sorted. std::vector ModuleFeatures; /// Options for parsing comments. CommentOptions CommentOpts; /// A list of all -fno-builtin-* function names (e.g., memset). std::vector NoBuiltinFuncs; /// A prefix map for __FILE__, __BASE_FILE__ and __builtin_FILE(). std::map> MacroPrefixMap; /// Triples of the OpenMP targets that the host code codegen should /// take into account in order to generate accurate offloading descriptors. std::vector OMPTargetTriples; /// Name of the IR file that contains the result of the OpenMP target /// host code generation. std::string OMPHostIRFile; /// The user provided compilation unit ID, if non-empty. This is used to /// externalize static variables which is needed to support accessing static /// device variables in host code for single source offloading languages /// like CUDA/HIP. std::string CUID; /// C++ ABI to compile with, if specified by the frontend through -fc++-abi=. /// This overrides the default ABI used by the target. std::optional CXXABI; /// Indicates whether the front-end is explicitly told that the /// input is a header file (i.e. -x c-header). bool IsHeaderFile = false; /// The default stream kind used for HIP kernel launching. GPUDefaultStreamKind GPUDefaultStream; /// The seed used by the randomize structure layout feature. std::string RandstructSeed; /// Indicates whether to use target's platform-specific file separator when /// __FILE__ macro is used and when concatenating filename with directory or /// to use build environment environment's platform-specific file separator. /// /// The plaform-specific path separator is the backslash(\) for Windows and /// forward slash (/) elsewhere. bool UseTargetPathSeparator = false; // Indicates whether we should keep all nullptr checks for pointers // received as a result of a standard operator new (-fcheck-new) bool CheckNew = false; // In OpenACC mode, contains a user provided override for the _OPENACC macro. // This exists so that we can override the macro value and test our incomplete // implementation on real-world examples. std::string OpenACCMacroOverride; LangOptions(); /// Set language defaults for the given input language and /// language standard in the given LangOptions object. /// /// \param Opts - The LangOptions object to set up. /// \param Lang - The input language. /// \param T - The target triple. /// \param Includes - If the language requires extra headers to be implicitly /// included, they will be appended to this list. /// \param LangStd - The input language standard. static void setLangDefaults(LangOptions &Opts, Language Lang, const llvm::Triple &T, std::vector &Includes, LangStandard::Kind LangStd = LangStandard::lang_unspecified); // Define accessors/mutators for language options of enumeration type. #define LANGOPT(Name, Bits, Default, Description) #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ Type get##Name() const { return static_cast(Name); } \ void set##Name(Type Value) { Name = static_cast(Value); } #include "clang/Basic/LangOptions.def" /// Are we compiling a module? bool isCompilingModule() const { return getCompilingModule() != CMK_None; } /// Are we compiling a standard c++ module interface? bool isCompilingModuleInterface() const { return getCompilingModule() == CMK_ModuleInterface; } /// Are we compiling a module implementation? bool isCompilingModuleImplementation() const { return !isCompilingModule() && !ModuleName.empty(); } /// Do we need to track the owning module for a local declaration? bool trackLocalOwningModule() const { return isCompilingModule() || ModulesLocalVisibility; } bool isSignedOverflowDefined() const { return getSignedOverflowBehavior() == SOB_Defined; } bool isSubscriptPointerArithmetic() const { return ObjCRuntime.isSubscriptPointerArithmetic() && !ObjCSubscriptingLegacyRuntime; } bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const { return MSCompatibilityVersion >= MajorVersion * 100000U; } /// Reset all of the options that are not considered when building a /// module. void resetNonModularOptions(); /// Is this a libc/libm function that is no longer recognized as a /// builtin because a -fno-builtin-* option has been specified? bool isNoBuiltinFunc(StringRef Name) const; /// True if any ObjC types may have non-trivial lifetime qualifiers. bool allowsNonTrivialObjCLifetimeQualifiers() const { return ObjCAutoRefCount || ObjCWeak; } bool assumeFunctionsAreConvergent() const { return ConvergentFunctions; } /// Return the OpenCL C or C++ version as a VersionTuple. VersionTuple getOpenCLVersionTuple() const; /// Return the OpenCL version that kernel language is compatible with unsigned getOpenCLCompatibleVersion() const; /// Return the OpenCL C or C++ for OpenCL language name and version /// as a string. std::string getOpenCLVersionString() const; /// Returns true if functions without prototypes or functions with an /// identifier list (aka K&R C functions) are not allowed. bool requiresStrictPrototypes() const { return CPlusPlus || C23 || DisableKNRFunctions; } /// Returns true if implicit function declarations are allowed in the current /// language mode. bool implicitFunctionsAllowed() const { return !requiresStrictPrototypes() && !OpenCL; } /// Returns true if the language supports calling the 'atexit' function. bool hasAtExit() const { return !(OpenMP && OpenMPIsTargetDevice); } /// Returns true if implicit int is part of the language requirements. bool isImplicitIntRequired() const { return !CPlusPlus && !C99; } /// Returns true if implicit int is supported at all. bool isImplicitIntAllowed() const { return !CPlusPlus && !C23; } /// Check if return address signing is enabled. bool hasSignReturnAddress() const { return getSignReturnAddressScope() != SignReturnAddressScopeKind::None; } /// Check if return address signing uses AKey. bool isSignReturnAddressWithAKey() const { return getSignReturnAddressKey() == SignReturnAddressKeyKind::AKey; } /// Check if leaf functions are also signed. bool isSignReturnAddressScopeAll() const { return getSignReturnAddressScope() == SignReturnAddressScopeKind::All; } bool hasSjLjExceptions() const { return getExceptionHandling() == ExceptionHandlingKind::SjLj; } bool hasSEHExceptions() const { return getExceptionHandling() == ExceptionHandlingKind::WinEH; } bool hasDWARFExceptions() const { return getExceptionHandling() == ExceptionHandlingKind::DwarfCFI; } bool hasWasmExceptions() const { return getExceptionHandling() == ExceptionHandlingKind::Wasm; } bool isSYCL() const { return SYCLIsDevice || SYCLIsHost; } bool hasDefaultVisibilityExportMapping() const { return getDefaultVisibilityExportMapping() != DefaultVisiblityExportMapping::None; } bool isExplicitDefaultVisibilityExportMapping() const { return getDefaultVisibilityExportMapping() == DefaultVisiblityExportMapping::Explicit; } bool isAllDefaultVisibilityExportMapping() const { return getDefaultVisibilityExportMapping() == DefaultVisiblityExportMapping::All; } bool hasGlobalAllocationFunctionVisibility() const { return getGlobalAllocationFunctionVisibility() != VisibilityForcedKinds::Source; } bool hasDefaultGlobalAllocationFunctionVisibility() const { return getGlobalAllocationFunctionVisibility() == VisibilityForcedKinds::ForceDefault; } bool hasProtectedGlobalAllocationFunctionVisibility() const { return getGlobalAllocationFunctionVisibility() == VisibilityForcedKinds::ForceProtected; } bool hasHiddenGlobalAllocationFunctionVisibility() const { return getGlobalAllocationFunctionVisibility() == VisibilityForcedKinds::ForceHidden; } /// Remap path prefix according to -fmacro-prefix-path option. void remapPathPrefix(SmallVectorImpl &Path) const; RoundingMode getDefaultRoundingMode() const { return RoundingMath ? RoundingMode::Dynamic : RoundingMode::NearestTiesToEven; } FPExceptionModeKind getDefaultExceptionMode() const { FPExceptionModeKind EM = getFPExceptionMode(); if (EM == FPExceptionModeKind::FPE_Default) return FPExceptionModeKind::FPE_Ignore; return EM; } }; /// Floating point control options class FPOptionsOverride; class FPOptions { public: // We start by defining the layout. using storage_type = uint32_t; using RoundingMode = llvm::RoundingMode; static constexpr unsigned StorageBitSize = 8 * sizeof(storage_type); // Define a fake option named "First" so that we have a PREVIOUS even for the // real first option. static constexpr storage_type FirstShift = 0, FirstWidth = 0; #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ static constexpr storage_type NAME##Shift = \ PREVIOUS##Shift + PREVIOUS##Width; \ static constexpr storage_type NAME##Width = WIDTH; \ static constexpr storage_type NAME##Mask = ((1 << NAME##Width) - 1) \ << NAME##Shift; #include "clang/Basic/FPOptions.def" static constexpr storage_type TotalWidth = 0 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) +WIDTH #include "clang/Basic/FPOptions.def" ; static_assert(TotalWidth <= StorageBitSize, "Too short type for FPOptions"); private: storage_type Value; FPOptionsOverride getChangesSlow(const FPOptions &Base) const; public: FPOptions() : Value(0) { setFPContractMode(LangOptions::FPM_Off); setConstRoundingMode(RoundingMode::Dynamic); setSpecifiedExceptionMode(LangOptions::FPE_Default); } explicit FPOptions(const LangOptions &LO) { Value = 0; // The language fp contract option FPM_FastHonorPragmas has the same effect // as FPM_Fast in frontend. For simplicity, use FPM_Fast uniformly in // frontend. auto LangOptContractMode = LO.getDefaultFPContractMode(); if (LangOptContractMode == LangOptions::FPM_FastHonorPragmas) LangOptContractMode = LangOptions::FPM_Fast; setFPContractMode(LangOptContractMode); setRoundingMath(LO.RoundingMath); setConstRoundingMode(LangOptions::RoundingMode::Dynamic); setSpecifiedExceptionMode(LO.getFPExceptionMode()); setAllowFPReassociate(LO.AllowFPReassoc); setNoHonorNaNs(LO.NoHonorNaNs); setNoHonorInfs(LO.NoHonorInfs); setNoSignedZero(LO.NoSignedZero); setAllowReciprocal(LO.AllowRecip); setAllowApproxFunc(LO.ApproxFunc); if (getFPContractMode() == LangOptions::FPM_On && getRoundingMode() == llvm::RoundingMode::Dynamic && getExceptionMode() == LangOptions::FPE_Strict) // If the FP settings are set to the "strict" model, then // FENV access is set to true. (ffp-model=strict) setAllowFEnvAccess(true); else setAllowFEnvAccess(LangOptions::FPM_Off); setComplexRange(LO.getComplexRange()); } bool allowFPContractWithinStatement() const { return getFPContractMode() == LangOptions::FPM_On; } void setAllowFPContractWithinStatement() { setFPContractMode(LangOptions::FPM_On); } bool allowFPContractAcrossStatement() const { return getFPContractMode() == LangOptions::FPM_Fast; } void setAllowFPContractAcrossStatement() { setFPContractMode(LangOptions::FPM_Fast); } bool isFPConstrained() const { return getRoundingMode() != llvm::RoundingMode::NearestTiesToEven || getExceptionMode() != LangOptions::FPE_Ignore || getAllowFEnvAccess(); } RoundingMode getRoundingMode() const { RoundingMode RM = getConstRoundingMode(); if (RM == RoundingMode::Dynamic) { // C23: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is // "off", the translator may assume that the default rounding mode is in // effect. if (!getAllowFEnvAccess() && !getRoundingMath()) RM = RoundingMode::NearestTiesToEven; } return RM; } LangOptions::FPExceptionModeKind getExceptionMode() const { LangOptions::FPExceptionModeKind EM = getSpecifiedExceptionMode(); if (EM == LangOptions::FPExceptionModeKind::FPE_Default) { if (getAllowFEnvAccess()) return LangOptions::FPExceptionModeKind::FPE_Strict; else return LangOptions::FPExceptionModeKind::FPE_Ignore; } return EM; } bool operator==(FPOptions other) const { return Value == other.Value; } /// Return the default value of FPOptions that's used when trailing /// storage isn't required. static FPOptions defaultWithoutTrailingStorage(const LangOptions &LO); storage_type getAsOpaqueInt() const { return Value; } static FPOptions getFromOpaqueInt(storage_type Value) { FPOptions Opts; Opts.Value = Value; return Opts; } /// Return difference with the given option set. FPOptionsOverride getChangesFrom(const FPOptions &Base) const; // We can define most of the accessors automatically: #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ TYPE get##NAME() const { \ return static_cast((Value & NAME##Mask) >> NAME##Shift); \ } \ void set##NAME(TYPE value) { \ Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \ } #include "clang/Basic/FPOptions.def" LLVM_DUMP_METHOD void dump(); }; /// Represents difference between two FPOptions values. /// /// The effect of language constructs changing the set of floating point options /// is usually a change of some FP properties while leaving others intact. This /// class describes such changes by keeping information about what FP options /// are overridden. /// /// The integral set of FP options, described by the class FPOptions, may be /// represented as a default FP option set, defined by language standard and /// command line options, with the overrides introduced by pragmas. /// /// The is implemented as a value of the new FPOptions plus a mask showing which /// fields are actually set in it. class FPOptionsOverride { FPOptions Options = FPOptions::getFromOpaqueInt(0); FPOptions::storage_type OverrideMask = 0; public: using RoundingMode = llvm::RoundingMode; /// The type suitable for storing values of FPOptionsOverride. Must be twice /// as wide as bit size of FPOption. using storage_type = uint64_t; static_assert(sizeof(storage_type) >= 2 * sizeof(FPOptions::storage_type), "Too short type for FPOptionsOverride"); /// Bit mask selecting bits of OverrideMask in serialized representation of /// FPOptionsOverride. static constexpr storage_type OverrideMaskBits = (static_cast(1) << FPOptions::StorageBitSize) - 1; FPOptionsOverride() {} FPOptionsOverride(const LangOptions &LO) : Options(LO), OverrideMask(OverrideMaskBits) {} FPOptionsOverride(FPOptions FPO) : Options(FPO), OverrideMask(OverrideMaskBits) {} FPOptionsOverride(FPOptions FPO, FPOptions::storage_type Mask) : Options(FPO), OverrideMask(Mask) {} bool requiresTrailingStorage() const { return OverrideMask != 0; } void setAllowFPContractWithinStatement() { setFPContractModeOverride(LangOptions::FPM_On); } void setAllowFPContractAcrossStatement() { setFPContractModeOverride(LangOptions::FPM_Fast); } void setDisallowFPContract() { setFPContractModeOverride(LangOptions::FPM_Off); } void setFPPreciseEnabled(bool Value) { setAllowFPReassociateOverride(!Value); setNoHonorNaNsOverride(!Value); setNoHonorInfsOverride(!Value); setNoSignedZeroOverride(!Value); setAllowReciprocalOverride(!Value); setAllowApproxFuncOverride(!Value); setMathErrnoOverride(Value); if (Value) /* Precise mode implies fp_contract=on and disables ffast-math */ setAllowFPContractWithinStatement(); else /* Precise mode disabled sets fp_contract=fast and enables ffast-math */ setAllowFPContractAcrossStatement(); } storage_type getAsOpaqueInt() const { return (static_cast(Options.getAsOpaqueInt()) << FPOptions::StorageBitSize) | OverrideMask; } static FPOptionsOverride getFromOpaqueInt(storage_type I) { FPOptionsOverride Opts; Opts.OverrideMask = I & OverrideMaskBits; Opts.Options = FPOptions::getFromOpaqueInt(I >> FPOptions::StorageBitSize); return Opts; } FPOptions applyOverrides(FPOptions Base) { FPOptions Result = FPOptions::getFromOpaqueInt((Base.getAsOpaqueInt() & ~OverrideMask) | (Options.getAsOpaqueInt() & OverrideMask)); return Result; } FPOptions applyOverrides(const LangOptions &LO) { return applyOverrides(FPOptions(LO)); } bool operator==(FPOptionsOverride other) const { return Options == other.Options && OverrideMask == other.OverrideMask; } bool operator!=(FPOptionsOverride other) const { return !(*this == other); } #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ bool has##NAME##Override() const { \ return OverrideMask & FPOptions::NAME##Mask; \ } \ TYPE get##NAME##Override() const { \ assert(has##NAME##Override()); \ return Options.get##NAME(); \ } \ void clear##NAME##Override() { \ /* Clear the actual value so that we don't have spurious differences when \ * testing equality. */ \ Options.set##NAME(TYPE(0)); \ OverrideMask &= ~FPOptions::NAME##Mask; \ } \ void set##NAME##Override(TYPE value) { \ Options.set##NAME(value); \ OverrideMask |= FPOptions::NAME##Mask; \ } #include "clang/Basic/FPOptions.def" LLVM_DUMP_METHOD void dump(); }; inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const { if (Value == Base.Value) return FPOptionsOverride(); return getChangesSlow(Base); } /// Describes the kind of translation unit being processed. enum TranslationUnitKind { /// The translation unit is a complete translation unit. TU_Complete, /// The translation unit is a prefix to a translation unit, and is /// not complete. TU_Prefix, /// The translation unit is a module. TU_Module, /// The translation unit is a is a complete translation unit that we might /// incrementally extend later. TU_Incremental }; } // namespace clang #endif // LLVM_CLANG_BASIC_LANGOPTIONS_H