1 //===- LangOptions.cpp - C Language Family Language Options ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the LangOptions class.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Basic/LangOptions.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/Support/Path.h"
17 using namespace clang
;
19 LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified
) {
20 #define LANGOPT(Name, Bits, Default, Description) Name = Default;
21 #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
22 #include "clang/Basic/LangOptions.def"
25 void LangOptions::resetNonModularOptions() {
26 #define LANGOPT(Name, Bits, Default, Description)
27 #define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default;
28 #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
29 Name = static_cast<unsigned>(Default);
30 #include "clang/Basic/LangOptions.def"
32 // Reset "benign" options with implied values (Options.td ImpliedBy relations)
33 // rather than their defaults. This avoids unexpected combinations and
34 // invocations that cannot be round-tripped to arguments.
35 // FIXME: we should derive this automatically from ImpliedBy in tablegen.
36 AllowFPReassoc
= UnsafeFPMath
;
37 NoHonorInfs
= FastMath
;
38 NoHonorNaNs
= FastMath
;
40 // These options do not affect AST generation.
41 NoSanitizeFiles
.clear();
42 XRayAlwaysInstrumentFiles
.clear();
43 XRayNeverInstrumentFiles
.clear();
45 CurrentModule
.clear();
49 bool LangOptions::isNoBuiltinFunc(StringRef FuncName
) const {
50 for (unsigned i
= 0, e
= NoBuiltinFuncs
.size(); i
!= e
; ++i
)
51 if (FuncName
== NoBuiltinFuncs
[i
])
56 VersionTuple
LangOptions::getOpenCLVersionTuple() const {
57 const int Ver
= OpenCLCPlusPlus
? OpenCLCPlusPlusVersion
: OpenCLVersion
;
58 if (OpenCLCPlusPlus
&& Ver
!= 100)
59 return VersionTuple(Ver
/ 100);
60 return VersionTuple(Ver
/ 100, (Ver
% 100) / 10);
63 unsigned LangOptions::getOpenCLCompatibleVersion() const {
66 if (OpenCLCPlusPlusVersion
== 100)
68 if (OpenCLCPlusPlusVersion
== 202100)
70 llvm_unreachable("Unknown OpenCL version");
73 void LangOptions::remapPathPrefix(SmallVectorImpl
<char> &Path
) const {
74 for (const auto &Entry
: MacroPrefixMap
)
75 if (llvm::sys::path::replace_path_prefix(Path
, Entry
.first
, Entry
.second
))
79 std::string
LangOptions::getOpenCLVersionString() const {
82 llvm::raw_string_ostream
Out(Result
);
83 Out
<< (OpenCLCPlusPlus
? "C++ for OpenCL" : "OpenCL C") << " version "
84 << getOpenCLVersionTuple().getAsString();
89 void LangOptions::setLangDefaults(LangOptions
&Opts
, Language Lang
,
90 const llvm::Triple
&T
,
91 std::vector
<std::string
> &Includes
,
92 LangStandard::Kind LangStd
) {
93 // Set some properties which depend solely on the input kind; it would be nice
94 // to move these to the language standard, and have the driver resolve the
95 // input kind + language standard.
97 // FIXME: Perhaps a better model would be for a single source file to have
98 // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std)
99 // simultaneously active?
100 if (Lang
== Language::Asm
) {
101 Opts
.AsmPreprocessor
= 1;
102 } else if (Lang
== Language::ObjC
|| Lang
== Language::ObjCXX
) {
106 if (LangStd
== LangStandard::lang_unspecified
)
107 LangStd
= getDefaultLanguageStandard(Lang
, T
);
108 const LangStandard
&Std
= LangStandard::getLangStandardForKind(LangStd
);
109 Opts
.LangStd
= LangStd
;
110 Opts
.LineComment
= Std
.hasLineComments();
111 Opts
.C99
= Std
.isC99();
112 Opts
.C11
= Std
.isC11();
113 Opts
.C17
= Std
.isC17();
114 Opts
.C23
= Std
.isC23();
115 Opts
.C2y
= Std
.isC2y();
116 Opts
.CPlusPlus
= Std
.isCPlusPlus();
117 Opts
.CPlusPlus11
= Std
.isCPlusPlus11();
118 Opts
.CPlusPlus14
= Std
.isCPlusPlus14();
119 Opts
.CPlusPlus17
= Std
.isCPlusPlus17();
120 Opts
.CPlusPlus20
= Std
.isCPlusPlus20();
121 Opts
.CPlusPlus23
= Std
.isCPlusPlus23();
122 Opts
.CPlusPlus26
= Std
.isCPlusPlus26();
123 Opts
.GNUMode
= Std
.isGNUMode();
124 Opts
.GNUCVersion
= 0;
125 Opts
.HexFloats
= Std
.hasHexFloats();
126 Opts
.WChar
= Std
.isCPlusPlus();
127 Opts
.Digraphs
= Std
.hasDigraphs();
128 Opts
.RawStringLiterals
= Std
.hasRawStringLiterals();
130 Opts
.HLSL
= Lang
== Language::HLSL
;
131 if (Opts
.HLSL
&& Opts
.IncludeDefaultHeader
)
132 Includes
.push_back("hlsl.h");
134 // Set OpenCL Version.
135 Opts
.OpenCL
= Std
.isOpenCL();
136 if (LangStd
== LangStandard::lang_opencl10
)
137 Opts
.OpenCLVersion
= 100;
138 else if (LangStd
== LangStandard::lang_opencl11
)
139 Opts
.OpenCLVersion
= 110;
140 else if (LangStd
== LangStandard::lang_opencl12
)
141 Opts
.OpenCLVersion
= 120;
142 else if (LangStd
== LangStandard::lang_opencl20
)
143 Opts
.OpenCLVersion
= 200;
144 else if (LangStd
== LangStandard::lang_opencl30
)
145 Opts
.OpenCLVersion
= 300;
146 else if (LangStd
== LangStandard::lang_openclcpp10
)
147 Opts
.OpenCLCPlusPlusVersion
= 100;
148 else if (LangStd
== LangStandard::lang_openclcpp2021
)
149 Opts
.OpenCLCPlusPlusVersion
= 202100;
150 else if (LangStd
== LangStandard::lang_hlsl2015
)
151 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2015
;
152 else if (LangStd
== LangStandard::lang_hlsl2016
)
153 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2016
;
154 else if (LangStd
== LangStandard::lang_hlsl2017
)
155 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2017
;
156 else if (LangStd
== LangStandard::lang_hlsl2018
)
157 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2018
;
158 else if (LangStd
== LangStandard::lang_hlsl2021
)
159 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2021
;
160 else if (LangStd
== LangStandard::lang_hlsl202x
)
161 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_202x
;
162 else if (LangStd
== LangStandard::lang_hlsl202y
)
163 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_202y
;
165 // OpenCL has some additional defaults.
169 Opts
.setDefaultFPContractMode(LangOptions::FPM_On
);
170 Opts
.OpenCLCPlusPlus
= Opts
.CPlusPlus
;
171 Opts
.OpenCLPipes
= Opts
.getOpenCLCompatibleVersion() == 200;
172 Opts
.OpenCLGenericAddressSpace
= Opts
.getOpenCLCompatibleVersion() == 200;
174 // Include default header file for OpenCL.
175 if (Opts
.IncludeDefaultHeader
) {
176 if (Opts
.DeclareOpenCLBuiltins
) {
177 // Only include base header file for builtin types and constants.
178 Includes
.push_back("opencl-c-base.h");
180 Includes
.push_back("opencl-c.h");
185 Opts
.HIP
= Lang
== Language::HIP
;
186 Opts
.CUDA
= Lang
== Language::CUDA
|| Opts
.HIP
;
188 // HIP toolchain does not support 'Fast' FPOpFusion in backends since it
189 // fuses multiplication/addition instructions without contract flag from
190 // device library functions in LLVM bitcode, which causes accuracy loss in
191 // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446.
192 // For device library functions in bitcode to work, 'Strict' or 'Standard'
193 // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas'
194 // FP contract option is used to allow fuse across statements in frontend
195 // whereas respecting contract flag in backend.
196 Opts
.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas
);
197 } else if (Opts
.CUDA
) {
199 // Emit OpenCL version metadata in LLVM IR when targeting SPIR-V.
200 Opts
.OpenCLVersion
= 200;
202 // Allow fuse across statements disregarding pragmas.
203 Opts
.setDefaultFPContractMode(LangOptions::FPM_Fast
);
206 // OpenCL, C++ and C23 have bool, true, false keywords.
207 Opts
.Bool
= Opts
.OpenCL
|| Opts
.CPlusPlus
|| Opts
.C23
;
209 // OpenCL and HLSL have half keyword
210 Opts
.Half
= Opts
.OpenCL
|| Opts
.HLSL
;
213 FPOptions
FPOptions::defaultWithoutTrailingStorage(const LangOptions
&LO
) {
214 FPOptions
result(LO
);
218 FPOptionsOverride
FPOptions::getChangesSlow(const FPOptions
&Base
) const {
219 FPOptions::storage_type OverrideMask
= 0;
220 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
221 if (get##NAME() != Base.get##NAME()) \
222 OverrideMask |= NAME##Mask;
223 #include "clang/Basic/FPOptions.def"
224 return FPOptionsOverride(*this, OverrideMask
);
227 LLVM_DUMP_METHOD
void FPOptions::dump() {
228 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
229 llvm::errs() << "\n " #NAME " " << get##NAME();
230 #include "clang/Basic/FPOptions.def"
231 llvm::errs() << "\n";
234 LLVM_DUMP_METHOD
void FPOptionsOverride::dump() {
235 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
236 if (has##NAME##Override()) \
237 llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override();
238 #include "clang/Basic/FPOptions.def"
239 llvm::errs() << "\n";