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 NoHonorNaNs
= FiniteMathOnly
;
38 NoHonorInfs
= FiniteMathOnly
;
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
.equals(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
.C2x
= Std
.isC2x();
115 Opts
.CPlusPlus
= Std
.isCPlusPlus();
116 Opts
.CPlusPlus11
= Std
.isCPlusPlus11();
117 Opts
.CPlusPlus14
= Std
.isCPlusPlus14();
118 Opts
.CPlusPlus17
= Std
.isCPlusPlus17();
119 Opts
.CPlusPlus20
= Std
.isCPlusPlus20();
120 Opts
.CPlusPlus23
= Std
.isCPlusPlus23();
121 Opts
.CPlusPlus26
= Std
.isCPlusPlus26();
122 Opts
.GNUMode
= Std
.isGNUMode();
123 Opts
.GNUCVersion
= 0;
124 Opts
.HexFloats
= Std
.hasHexFloats();
125 Opts
.WChar
= Std
.isCPlusPlus();
126 Opts
.Digraphs
= Std
.hasDigraphs();
128 Opts
.HLSL
= Lang
== Language::HLSL
;
129 if (Opts
.HLSL
&& Opts
.IncludeDefaultHeader
)
130 Includes
.push_back("hlsl.h");
132 // Set OpenCL Version.
133 Opts
.OpenCL
= Std
.isOpenCL();
134 if (LangStd
== LangStandard::lang_opencl10
)
135 Opts
.OpenCLVersion
= 100;
136 else if (LangStd
== LangStandard::lang_opencl11
)
137 Opts
.OpenCLVersion
= 110;
138 else if (LangStd
== LangStandard::lang_opencl12
)
139 Opts
.OpenCLVersion
= 120;
140 else if (LangStd
== LangStandard::lang_opencl20
)
141 Opts
.OpenCLVersion
= 200;
142 else if (LangStd
== LangStandard::lang_opencl30
)
143 Opts
.OpenCLVersion
= 300;
144 else if (LangStd
== LangStandard::lang_openclcpp10
)
145 Opts
.OpenCLCPlusPlusVersion
= 100;
146 else if (LangStd
== LangStandard::lang_openclcpp2021
)
147 Opts
.OpenCLCPlusPlusVersion
= 202100;
148 else if (LangStd
== LangStandard::lang_hlsl2015
)
149 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2015
;
150 else if (LangStd
== LangStandard::lang_hlsl2016
)
151 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2016
;
152 else if (LangStd
== LangStandard::lang_hlsl2017
)
153 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2017
;
154 else if (LangStd
== LangStandard::lang_hlsl2018
)
155 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2018
;
156 else if (LangStd
== LangStandard::lang_hlsl2021
)
157 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2021
;
158 else if (LangStd
== LangStandard::lang_hlsl202x
)
159 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_202x
;
161 // OpenCL has some additional defaults.
165 Opts
.setDefaultFPContractMode(LangOptions::FPM_On
);
166 Opts
.OpenCLCPlusPlus
= Opts
.CPlusPlus
;
167 Opts
.OpenCLPipes
= Opts
.getOpenCLCompatibleVersion() == 200;
168 Opts
.OpenCLGenericAddressSpace
= Opts
.getOpenCLCompatibleVersion() == 200;
170 // Include default header file for OpenCL.
171 if (Opts
.IncludeDefaultHeader
) {
172 if (Opts
.DeclareOpenCLBuiltins
) {
173 // Only include base header file for builtin types and constants.
174 Includes
.push_back("opencl-c-base.h");
176 Includes
.push_back("opencl-c.h");
181 Opts
.HIP
= Lang
== Language::HIP
;
182 Opts
.CUDA
= Lang
== Language::CUDA
|| Opts
.HIP
;
184 // HIP toolchain does not support 'Fast' FPOpFusion in backends since it
185 // fuses multiplication/addition instructions without contract flag from
186 // device library functions in LLVM bitcode, which causes accuracy loss in
187 // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446.
188 // For device library functions in bitcode to work, 'Strict' or 'Standard'
189 // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas'
190 // FP contract option is used to allow fuse across statements in frontend
191 // whereas respecting contract flag in backend.
192 Opts
.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas
);
193 } else if (Opts
.CUDA
) {
195 // Emit OpenCL version metadata in LLVM IR when targeting SPIR-V.
196 Opts
.OpenCLVersion
= 200;
198 // Allow fuse across statements disregarding pragmas.
199 Opts
.setDefaultFPContractMode(LangOptions::FPM_Fast
);
202 Opts
.RenderScript
= Lang
== Language::RenderScript
;
204 // OpenCL, C++ and C2x have bool, true, false keywords.
205 Opts
.Bool
= Opts
.OpenCL
|| Opts
.CPlusPlus
|| Opts
.C2x
;
207 // OpenCL and HLSL have half keyword
208 Opts
.Half
= Opts
.OpenCL
|| Opts
.HLSL
;
211 FPOptions
FPOptions::defaultWithoutTrailingStorage(const LangOptions
&LO
) {
212 FPOptions
result(LO
);
216 FPOptionsOverride
FPOptions::getChangesSlow(const FPOptions
&Base
) const {
217 FPOptions::storage_type OverrideMask
= 0;
218 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
219 if (get##NAME() != Base.get##NAME()) \
220 OverrideMask |= NAME##Mask;
221 #include "clang/Basic/FPOptions.def"
222 return FPOptionsOverride(*this, OverrideMask
);
225 LLVM_DUMP_METHOD
void FPOptions::dump() {
226 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
227 llvm::errs() << "\n " #NAME " " << get##NAME();
228 #include "clang/Basic/FPOptions.def"
229 llvm::errs() << "\n";
232 LLVM_DUMP_METHOD
void FPOptionsOverride::dump() {
233 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
234 if (has##NAME##Override()) \
235 llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override();
236 #include "clang/Basic/FPOptions.def"
237 llvm::errs() << "\n";