//===- 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/ADT/Triple.h" #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; 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 }; /// 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 from a list of header files. CMK_HeaderModule, /// Compiling a C++ modules TS module 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 }; 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, }; 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 }; /// 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, /// 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 }; /// Alias for RoundingMode::NearestTiesToEven. static constexpr unsigned FPR_ToNearest = static_cast(llvm::RoundingMode::NearestTiesToEven); /// 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 }; /// 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 }; 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. llvm::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; LangOptions(); // 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 interface (.cppm or module map)? bool isCompilingModule() const { return getCompilingModule() != CMK_None; } /// 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; /// 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; } /// Remap path prefix according to -fmacro-prefix-path option. void remapPathPrefix(SmallString<256> &Path) const; }; /// Floating point control options class FPOptionsOverride; class FPOptions { public: // We start by defining the layout. using storage_type = uint16_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; public: FPOptions() : Value(0) { setFPContractMode(LangOptions::FPM_Off); setRoundingMode(static_cast(LangOptions::FPR_ToNearest)); setFPExceptionMode(LangOptions::FPE_Ignore); } 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); setRoundingMode(LO.getFPRoundingMode()); setFPExceptionMode(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 && getFPExceptionMode() == 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); } 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 || getFPExceptionMode() != LangOptions::FPE_Ignore || getAllowFEnvAccess(); } 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; } // 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 = uint32_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) {} 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); 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(); }; /// 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